本文章介紹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; }
沒有留言:
張貼留言