本文章介紹nRF24L01(+)除了標準的Multiceiver的網路應用外,另外實作
- One PTX and multi PRX.
- One PTX broadcast to multi PRX
- PTX & PRX role exchange: packet transmission of ring or ping-pong type。
nRF24L01簡介與驅動程式,請參閱前篇文章說明。
- 成果影片:
一、Multiceiver:
multiceiver.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "nRF24L01.h"
#include "string.h"
//#define RECV_NODE // define for PRX
uint8_t transnode=1; //PTX node 0 ~ 5
uint8_t role;
uint8_t can_send=false;
uint8_t send_buffer[33];
uint8_t addr[6][5] = {"0node", "1node", "2node","3node","4node","5node"};
uint8_t send_buffer[33];
uint32_t cnt=0;
void irq_callback(uint8_t event_type, uint8_t datapipe, uint8_t* data, uint8_t width) {
static uint32_t ack_payload=0;
uint8_t ack_buff[15];
switch(event_type) {
case EVENT_RX_DR:
data[width]='\0';
printf("RECV== pipe:%d, width:%d, %s\n", datapipe, width, data);
gpio_put(datapipe*2, !gpio_get(datapipe*2));
break;
case EVENT_TX_DS:
can_send=true;
printf("event_data_sent:%d\n", datapipe);
break;
case EVENT_MAX_RT:
//nRF24_flush_tx();
//can_send=true;
busy_wait_ms(2);
printf("event_max_rt:%d, can_sent:%d\n", datapipe, can_send);
break;
}
}
void keydown() {
if (gpio_get_irq_event_mask(15) == GPIO_IRQ_EDGE_RISE) {
gpio_acknowledge_irq(15, GPIO_IRQ_EDGE_RISE);
gpio_set_irq_enabled(15, GPIO_IRQ_EDGE_RISE, false);
nRF24_write_payload(send_buffer,strlen(send_buffer));
sprintf(send_buffer, "keydown");
busy_wait_ms(100);
can_send=true;
//gpio_set_irq_enabled(gpio, event_mask, true);
printf("keydown:%s\n",send_buffer);
gpio_set_irq_enabled(15,GPIO_IRQ_EDGE_RISE, true);
}
//gpio_set_irq_enabled(gpio,GPIO_IRQ_EDGE_FALL, true);
}
int main()
{
stdio_init_all();
sleep_ms(2000);
gpio_init(2);
gpio_init(4);
gpio_init(6);
gpio_set_dir(2, true);
gpio_set_dir(4, true);
gpio_set_dir(6, true);
uint8_t status;
nRF24_spi_default_init(20, 21, irq_callback);
//nRF24_set_RF_channel(0x1F);
#ifdef RECV_NODE
role=RECEIVER;
#else
role = TRANSMITTER;
#endif
nRF24_config_mode(role);
nRF24_enable_feature(FEATURE_EN_DPL, true);
//nRF24_enable_feature(FEATURE_EN_ACK_PAY, true);
//nRF24_enable_feature(FEATURE_EN_DYN_ACK, true);
#ifdef RECV_NODE
nRF24_enable_RXADDR(0b00001111);
nRF24_set_RX_addr(0, addr[0], 5);
nRF24_set_RX_addr(1, addr[1], 5);
nRF24_set_RX_addr(2, addr[2], 5);
nRF24_set_RX_addr(3, addr[3], 5);
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
nRF24_enable_data_pipe_dynamic_payload_length(1, true);
nRF24_enable_data_pipe_dynamic_payload_length(2, true);
nRF24_enable_data_pipe_dynamic_payload_length(3, true);
#else
nRF24_set_TX_addr(addr[transnode], 5);
nRF24_set_RX_addr(0, addr[transnode], 5);
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
gpio_pull_down(15);
gpio_add_raw_irq_handler(15, keydown);
gpio_set_irq_enabled(15, GPIO_IRQ_EDGE_RISE, true);
#endif
can_send=false;
while(1) {
#ifndef RECV_NODE
if (can_send) {
can_send=false;
nRF24_write_payload(send_buffer, strlen(send_buffer));
}
#endif
tight_loop_contents();
}
return 0;
}CMakeLists.txt
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/duser/pico/pico-sdk")
set(PICO_BOARD pico CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
project(nRF24L01 C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(nRF24L01 multiceive.c )
pico_set_program_name(nRF24L01 "nRF24L01")
pico_set_program_version(nRF24L01 "0.1")
pico_enable_stdio_uart(nRF24L01 0)
pico_enable_stdio_usb(nRF24L01 1)
# Add the standard library to the build
target_link_libraries(nRF24L01
pico_stdlib)
# Add the standard include files to the build
target_include_directories(nRF24L01 PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)
# Add any user requested libraries
target_link_libraries(nRF24L01
hardware_spi
)
add_subdirectory(nRF24L01)
target_link_libraries(nRF24L01
nRF24L01_drv)
pico_add_extra_outputs(nRF24L01)二、One PTX and multi PRX
1_T_n_R.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "nRF24L01.h"
#include "string.h"
#define SENDER // define for one PTX
uint8_t node_id=2; // define for PRX node 0~5
uint8_t role;
uint8_t can_send=false;
uint8_t send_buffer[33];
uint8_t addr[5][5] = {"0node", "1node", "2node","3node","4node", "5node"};
void irq_callback(uint8_t event_type, uint8_t datapipe, uint8_t* data, uint8_t width) {
static uint32_t ack_payload=0;
uint8_t ack_buff[15];
switch(event_type) {
case EVENT_RX_DR:
data[width]='\0';
printf("RECV== pipe:%d, width:%d, %s\n", datapipe, width, data);
gpio_put(2, !gpio_get(2));
break;
case EVENT_TX_DS:
//can_send=true;
printf("event_data_sent:%d\n", datapipe);
break;
case EVENT_MAX_RT:
//nRF24_flush_tx();
//can_send=true;
printf("event_max_rt:%d, can_sent:%d\n", datapipe, can_send);
break;
}
}
void keydown() {
uint8_t irq_pin=0;
if (gpio_get_irq_event_mask(13) == GPIO_IRQ_EDGE_RISE) {
irq_pin=13;
nRF24_set_TX_addr(addr[0],5);
nRF24_set_RX_addr(0, addr[0],5);
}
if (gpio_get_irq_event_mask(14) == GPIO_IRQ_EDGE_RISE) {
irq_pin=14;
nRF24_set_TX_addr(addr[1],5);
nRF24_set_RX_addr(0, addr[1],5);
}
if (gpio_get_irq_event_mask(15) == GPIO_IRQ_EDGE_RISE) {
irq_pin=15;
nRF24_set_TX_addr(addr[2],5);
nRF24_set_RX_addr(0, addr[2],5);
}
if (irq_pin == 13 || irq_pin==14 || irq_pin==15) {
gpio_acknowledge_irq(irq_pin, GPIO_IRQ_EDGE_RISE);
gpio_set_irq_enabled(irq_pin,GPIO_IRQ_EDGE_RISE, false);
nRF24_write_payload(send_buffer,strlen(send_buffer));
sprintf(send_buffer, "keydown");
busy_wait_ms(100);
can_send=true;
printf("keydown:%s\n",send_buffer);
gpio_set_irq_enabled(irq_pin,GPIO_IRQ_EDGE_RISE, true);
}
}
int main()
{
stdio_init_all();
sleep_ms(2000);
gpio_init(2);
gpio_init(4);
gpio_init(6);
gpio_set_dir(2, true);
gpio_set_dir(4, true);
gpio_set_dir(6, true);
uint8_t status;
nRF24_spi_default_init(20, 21, irq_callback);
//nRF24_set_RF_channel(0x1F);
#ifdef SENDER
role = TRANSMITTER;
#else
role=RECEIVER;
#endif
nRF24_config_mode(role);
nRF24_enable_feature(FEATURE_EN_DPL, true);
//nRF24_enable_feature(FEATURE_EN_ACK_PAY, true);
//nRF24_enable_feature(FEATURE_EN_DYN_ACK, true);
#ifdef SENDER
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
gpio_pull_down(13);
gpio_add_raw_irq_handler(13, keydown);
gpio_set_irq_enabled(13, GPIO_IRQ_EDGE_RISE, true);
gpio_pull_down(14);
gpio_set_irq_enabled(14, GPIO_IRQ_EDGE_RISE, true);
gpio_pull_down(15);
gpio_set_irq_enabled(15, GPIO_IRQ_EDGE_RISE, true);
#else
nRF24_set_RX_addr(0, addr[node_id], 5);
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
#endif
can_send=true;
while(1) {
#ifndef RECV_NODE
//if (can_send) {
// can_send=false;
// printf("send\n");
// nRF24_write_payload("keydown",7);
//// sleep_ms(500);
//}
#endif
tight_loop_contents();
}
return 0;
}三、Broadcast:
broadcast.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "nRF24L01.h"
#include "string.h"
//#define BROADCASTER // define if BROADCASTER (PTX)
#define LED_PIN 2
uint8_t addr[5][5] = {"0ode1", "1node", "2node", "3node", "4node"};
uint8_t send_buffer[33];
void irq_callback(uint8_t event_type, uint8_t datapipe, uint8_t* data, uint8_t width)
switch(event_type) {
case EVENT_RX_DR:
gpio_put(LED_PIN, !gpio_get(LED_PIN));
data[width]='\0';
printf("RECV== pipe:%d, width:%d, %s\n", datapipe, width, data);
break;
case EVENT_TX_DS:
printf("event_data_sent:%d\n", datapipe);
break;
case EVENT_MAX_RT:
//nRF24_flush_tx();
//can_send=true;
printf("event_max_rt:%d\n", datapipe);
break;
}
}
void keydown() {
if (gpio_get_irq_event_mask(15) == GPIO_IRQ_EDGE_RISE) {
gpio_acknowledge_irq(15, GPIO_IRQ_EDGE_RISE);
gpio_set_irq_enabled(15, GPIO_IRQ_EDGE_RISE, false);
nRF24_write_payload(send_buffer,strlen(send_buffer));
sprintf(send_buffer, "keydown");
busy_wait_ms(100);
//can_send=true;
printf("keydown:%s\n",send_buffer);
gpio_set_irq_enabled(15,GPIO_IRQ_EDGE_RISE, true);
}
}
int main()
{
stdio_init_all();
sleep_ms(2000);
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, true);
nRF24_spi_default_init(20, 21, irq_callback);
nRF24_enable_feature(FEATURE_EN_DPL, true);
//nRF24_enable_feature(FEATURE_EN_ACK_PAY, true);
#ifdef BROADCASTER
nRF24_config_mode(TRANSMITTER);
nRF24_enable_feature(FEATURE_EN_DYN_ACK, true);
nRF24_set_TX_addr(addr[0], 5);
gpio_pull_down(15);
gpio_add_raw_irq_handler(15, keydown);
gpio_set_irq_enabled(15, GPIO_IRQ_EDGE_RISE, true);
#else
nRF24_config_mode(RECEIVER);
#endif
nRF24_set_RX_addr(0, addr[0], 5);
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
uint32_t dc=0;
uint8_t send_buffer[32];
uint32_t count=0;
while(1) {
#ifdef BROADCASTER
//sprintf(send_buffer, "broadcast:%d", count++);
//count %=10000;
//nRF24_write_payload_no_ack(send_buffer,strlen(send_buffer));
#endif
sleep_ms(500);
}
return 0;
}四、PTX & PRX role swap: ping-pong mode

#include <stdio.h>
#include "pico/stdlib.h"
#include "nRF24L01.h"
#include "string.h"
#define LED_PIN 2
#define NODE_A
uint8_t addr_a[2][5] = {"1a---", "2a---"};
uint8_t addr_b[2][5] = {"1b---", "2b---"};
bool can_send=true;
uint8_t role, new_role;
void irq_callback(uint8_t event_type, uint8_t datapipe, uint8_t* data, uint8_t width) {
switch(event_type) {
case EVENT_RX_DR:
data[width]='\0';
printf("RECV== pipe:%d, width:%d, %s\n", datapipe, width, data);
gpio_put(LED_PIN, true);
can_send=true;
new_role = TRANSMITTER;
break;
case EVENT_TX_DS:
puts("TX_DS");
new_role=RECEIVER;
gpio_put(LED_PIN, false);
can_send=false;
break;
case EVENT_MAX_RT:
//nRF24_flush_tx();
//can_send=true;
//printf("event_max_rt:%d, can_sent:%d\n", datapipe, can_send);
break;
}
}
int main()
{
stdio_init_all();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, true);
uint8_t status;
nRF24_spi_default_init(20, 21, irq_callback);
#ifdef NODE_A
role=TRANSMITTER;
new_role=TRANSMITTER;
nRF24_config_mode(TRANSMITTER);
can_send=true;
nRF24_set_TX_addr(addr_b[0], 5);
nRF24_set_RX_addr(0, addr_b[0], 5);
nRF24_set_RX_addr(1, addr_a[0], 5);
#else
role = RECEIVER;
new_role = RECEIVER;
nRF24_config_mode(RECEIVER);
can_send=false;
nRF24_set_TX_addr(addr_a[0], 5);
nRF24_set_RX_addr(0, addr_a[0], 5);
nRF24_set_RX_addr(1, addr_b[0], 5);
#endif
nRF24_enable_feature(FEATURE_EN_DPL, true);
uint32_t count=0;
uint8_t send_buff[32];
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
nRF24_enable_data_pipe_dynamic_payload_length(1, true);
uint32_t dc=0;
while(1) {
if (role != new_role) {
role = new_role;
nRF24_config_mode(role);
}
if (can_send && role==TRANSMITTER) {
can_send=false;
sprintf(send_buff, "0:abcdefgh%d", count++);
count %=10000;
nRF24_write_payload(send_buff,strlen(send_buff));
}
sleep_ms(500);
}
return 0;
}五、PTX & PRX role swap: ring mode

#include <stdio.h>
#include "pico/stdlib.h"
#include "nRF24L01.h"
#include "string.h"
#define LED_PIN 2
uint8_t node_id=3; // node id: 0~5 for each node
uint8_t total_nodes=4; // total nodes in the ring
uint8_t addr[6][5] = {"0node","1node", "2node", "3node", "4node", "5node"};
bool can_send=false;
uint8_t role, new_role;
void irq_callback(uint8_t event_type, uint8_t datapipe, uint8_t* data, uint8_t width) {
static uint32_t ack_payload=0;
uint8_t ack_buff[15];
switch(event_type) {
case EVENT_RX_DR:
gpio_put(LED_PIN, true);
data[width]='\0';
printf("RECV== pipe:%d, width:%d, %s\n", datapipe, width, data);
can_send=true;
new_role = TRANSMITTER;
break;
case EVENT_TX_DS:
puts("TX_DS");
new_role=RECEIVER;
gpio_put(LED_PIN, false);
can_send=false;
break;
case EVENT_MAX_RT:
//nRF24_flush_tx();
//can_send=true;
//printf("event_max_rt:%d, can_sent:%d\n", datapipe, can_send);
break;
}
}
int main()
{
stdio_init_all();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, true);
uint8_t status;
nRF24_spi_default_init(20, 21, irq_callback);
if (node_id==0) {
role=TRANSMITTER;
new_role=TRANSMITTER;
nRF24_config_mode(TRANSMITTER);
can_send=true;
nRF24_set_TX_addr(addr[1], 5);
nRF24_set_RX_addr(0, addr[1], 5);
nRF24_set_RX_addr(1, addr[0], 5);
} else {
role = RECEIVER;
new_role = RECEIVER;
nRF24_config_mode(RECEIVER);
can_send=false;
nRF24_set_TX_addr(addr[(node_id+1)%total_nodes], 5);
nRF24_set_RX_addr(0, addr[(node_id+1)%total_nodes], 5);
nRF24_set_RX_addr(1, addr[node_id], 5);
}
nRF24_enable_feature(FEATURE_EN_DPL, true);
uint32_t count=0;
uint8_t send_buff[32];
nRF24_enable_data_pipe_dynamic_payload_length(0, true);
nRF24_enable_data_pipe_dynamic_payload_length(1, true);
uint32_t dc=0;
while(1) {
if (role != new_role) {
role = new_role;
nRF24_config_mode(role);
}
if (can_send && role==TRANSMITTER) {
can_send=false;
sprintf(send_buff, "0:abcdefgh%d", count++);
count %=10000;
nRF24_write_payload(send_buff,strlen(send_buff));
}
sleep_ms(500);
}
return 0;
}



沒有留言:
張貼留言