Robofun 機器人論壇

 找回密碼
 申請會員
搜索
熱搜: 活動 交友 discuz
查看: 700|回復: 2

nRF24L01 一傳多問題

[複製鏈接]
發表於 2019-11-8 03:20:42 | 顯示全部樓層 |閱讀模式
大家好
小弟用3個nRF24L01組成系統, 1個當master, 2個當slave
master定時輪流詢問slave(step 1,3), slave收到後回應master(step 2,4)
nrf24L01.png

但是slave總會規律低收不到來自master訊息
print.png

有人有成功經驗嗎
研究好久都沒結果
附上程式碼
謝謝

master 程式碼


  1. #include <SPI.h>
  2. #include "RF24.h"

  3. RF24 rf24(7, 8); // CE腳, CSN腳

  4. byte pipe = 1;  // 指定通道編號
  5. const byte addr[][6] = {"1Node","2Node"};
  6. const byte addr_m_tx[][6] = {"1MOSI", "2MOSI"};     
  7. const byte addr_s_tx[][6] = {"1MISO", "2MISO"};     
  8. const char msg1[] = "1 Happy Hacking!";
  9. const char msg2[] = "2 Happy Hacking!";
  10. unsigned long started_waiting_at;

  11. void setup() {
  12.   Serial.begin(9600);
  13.   rf24.begin();
  14.   rf24.setChannel(83);                      // 設定頻道編號
  15.   rf24.openWritingPipe(addr_m_tx[0]);       // 設定1Node通道位址   
  16.   rf24.openReadingPipe(pipe, addr_s_tx[0]); // 設定1Node通道位址   
  17.   rf24.setPALevel(RF24_PA_MIN);             // 設定廣播功率
  18.   rf24.setDataRate(RF24_2MBPS);             // 設定傳輸速率
  19.   rf24.stopListening();                     // 停止偵聽;設定成發射模式
  20.   Serial.println("nRF24L01 master ready!");
  21. }

  22. void loop() {

  23.   rf24.openWritingPipe(addr_m_tx[0]);       // 設定1Node通道位址
  24.   rf24.openReadingPipe(pipe, addr_s_tx[0]); // 設定1Node通道位址     
  25.   rf24.write(&msg1, sizeof(msg1));  // 傳送資料

  26. #if 1
  27.   rf24.startListening();
  28.   started_waiting_at = micros();
  29.   
  30.   while(1)
  31.   {
  32.     //if(rf24.available(&pipe))
  33.     if(rf24.available())
  34.     {
  35.        char msg[32] = "";
  36.        rf24.read(&msg, sizeof(msg));
  37.        Serial.println(msg); // 顯示訊息內容
  38.        break;  
  39.     }
  40.    
  41.     if(micros() - started_waiting_at > 100000)    //If waited longer than 100ms, indicate timeout and exit while loop
  42.     {
  43.       Serial.println("Timeout");
  44.       break;
  45.     }
  46.   }
  47.   
  48.   rf24.stopListening();
  49. #endif


  50.   delay(1000);
  51.   rf24.openWritingPipe(addr_m_tx[1]);       // 設定2Node通道位址
  52.   rf24.openReadingPipe(pipe, addr_s_tx[1]); // 設定2Node通道位址  
  53.   rf24.write(&msg2, sizeof(msg2));  // 傳送資料

  54. #if 1
  55.   rf24.startListening();
  56.   started_waiting_at = micros();

  57.   while(1)
  58.   {
  59.     //if(rf24.available(&pipe))
  60.     if(rf24.available())
  61.     {
  62.        char msg[32] = "";
  63.        rf24.read(&msg, sizeof(msg));               
  64.        Serial.println(msg); // 顯示訊息內容
  65.        break;  
  66.     }
  67.   
  68.     if(micros() - started_waiting_at > 100000)    //If waited longer than 100ms, indicate timeout and exit while loop
  69.     {
  70.       Serial.println("Timeout");
  71.       break;
  72.     }
  73.   }
  74.   
  75. #endif
  76.   rf24.stopListening();

  77.   delay(1000);
  78. }
複製代碼


slave1 程式碼


  1. #include <SPI.h>
  2. #include "RF24.h"

  3. RF24 rf24(7, 8); // CE腳, CSN腳

  4. byte pipe = 1;  // 指定通道編號
  5. const byte addr_m_tx[6] = "1MOSI";     
  6. const byte addr_s_tx[6] = "1MISO";     
  7. const char ack_msg[] = "Slave1 ack";

  8. void setup() {
  9.   Serial.begin(9600);
  10.   rf24.begin();
  11.   rf24.setChannel(83);  // 設定頻道編號
  12.   rf24.setPALevel(RF24_PA_MIN);
  13.   rf24.setDataRate(RF24_2MBPS);
  14.   rf24.openWritingPipe(addr_s_tx);      // 設定1Node通道位址   
  15.   rf24.openReadingPipe(pipe,addr_m_tx); // 設定1Node通道位址
  16.   
  17.   rf24.startListening();  // 開始監聽無線廣播
  18.   Serial.println("nRF24L01 slave1 ready!");
  19. }

  20. void loop() {
  21.   if (rf24.available(&pipe)) {
  22.     char msg[32] = "";
  23.     rf24.read(&msg, sizeof(msg));
  24.     Serial.println(msg); // 顯示訊息內容
  25.     rf24.stopListening();
  26.     rf24.write( &ack_msg, sizeof(ack_msg) );
  27.     rf24.startListening();   
  28.   }
  29. }
複製代碼


slave2 程式碼


  1. #include <SPI.h>
  2. #include "RF24.h"

  3. RF24 rf24(7, 8); // CE腳, CSN腳

  4. byte pipe = 1;  // 指定通道編號
  5. const byte addr_m_tx[6] = "2MOSI";     
  6. const byte addr_s_tx[6] = "2MISO";     
  7. const char ack_msg[] = "Slave2 ack";

  8. void setup() {
  9.   Serial.begin(9600);
  10.   rf24.begin();
  11.   rf24.setChannel(83);  // 設定頻道編號
  12.   rf24.setPALevel(RF24_PA_MIN);
  13.   rf24.setDataRate(RF24_2MBPS);
  14.   rf24.openWritingPipe(addr_s_tx);      // 設定2Node通道位址   
  15.   rf24.openReadingPipe(pipe,addr_m_tx); // 設定2Node通道位址  
  16.   
  17.   rf24.startListening();  // 開始監聽無線廣播
  18.   Serial.println("nRF24L01 slave ready!");
  19. }

  20. void loop() {
  21.   if (rf24.available(&pipe)) {
  22.     char msg[32] = "";
  23.     rf24.read(&msg, sizeof(msg));
  24.     Serial.println(msg); // 顯示訊息內容
  25.     rf24.stopListening();
  26.     rf24.write( &ack_msg, sizeof(ack_msg) );
  27.     rf24.startListening();   
  28.   }
  29. }
複製代碼
發表於 2019-11-8 09:02:57 | 顯示全部樓層
把 程式 TIMEOUT 時間加長
或是
SLAVE 端 調過來看   
原來

  1.     Serial.println(msg); // 顯示訊息內容
  2.     rf24.stopListening();
  3.     rf24.write( &ack_msg, sizeof(ack_msg) );
  4.     rf24.startListening();
複製代碼

改成

  1.     rf24.stopListening();
  2.     rf24.write( &ack_msg, sizeof(ack_msg) );
  3.     rf24.startListening();
  4.     Serial.println(msg); // 顯示訊息內容
複製代碼
 樓主| 發表於 2019-11-10 17:01:58 | 顯示全部樓層
嗨,更新一下狀況
我後來排除timeout值太短或serial.println造成延遲的關係

後來方法是master在timeout的時候再重傳一次資料
這樣就能收到slave回應

master 程式碼


  1. #include <SPI.h>
  2. #include "RF24.h"

  3. RF24 rf24(7, 8); // CE腳, CSN腳

  4. byte pipe = 1;  // 指定通道編號
  5. const byte addr[][6] = {"1Node","2Node"};
  6. const byte addr_m_tx[][6] = {"1MOSI", "2MOSI"};     
  7. const byte addr_s_tx[][6] = {"1MISO", "2MISO"};     
  8. const char msg1[] = "1 Happy Hacking!";
  9. const char msg2[] = "2 Happy Hacking!";
  10. unsigned long started_waiting_at;

  11. void setup() {
  12.   Serial.begin(115200);
  13.   rf24.begin();
  14.   rf24.setChannel(83);                      // 設定頻道編號
  15.   //rf24.openWritingPipe(addr_m_tx[0]);       // 設定1Node通道位址   
  16.   //rf24.openReadingPipe(pipe, addr_s_tx[0]); // 設定1Node通道位址   
  17.   rf24.setPALevel(RF24_PA_MIN);             // 設定廣播功率
  18.   rf24.setDataRate(RF24_2MBPS);             // 設定傳輸速率
  19.   rf24.stopListening();                     // 停止偵聽;設定成發射模式
  20.   Serial.println("nRF24L01 master ready!");
  21. }

  22. void loop() {

  23.   delay(1000);

  24.   
  25.   rf24.openWritingPipe(addr_m_tx[0]);       // 設定1Node通道位址
  26.   rf24.openReadingPipe(pipe, addr_s_tx[0]); // 設定1Node通道位址     
  27.   rf24.write(&msg1, sizeof(msg1));  // 傳送資料

  28. #if 1
  29.   rf24.startListening();
  30.   started_waiting_at = micros();
  31.   
  32.   while(1)
  33.   {
  34.     //if(rf24.available(&pipe))
  35.     if(rf24.available())
  36.     {
  37.        char msg[32] = "";
  38.        rf24.read(&msg, sizeof(msg));
  39.        Serial.println(msg); // 顯示訊息內容
  40.        break;  
  41.     }
  42.    
  43.     if(micros() - started_waiting_at > 300000)    //If waited longer than 100ms, indicate timeout and exit while loop
  44.     {
  45.       rf24.stopListening();
  46.       rf24.write(&msg1, sizeof(msg1));  // 重傳資料
  47.       rf24.startListening();
  48.       started_waiting_at = micros();
  49.       Serial.println("Resend 1");
  50.     }
  51.   }
  52.   
  53.   rf24.stopListening();
  54. #endif

  55.   delay(1000);
  56.   rf24.openWritingPipe(addr_m_tx[1]);       // 設定2Node通道位址
  57.   rf24.openReadingPipe(pipe, addr_s_tx[1]); // 設定2Node通道位址  
  58.   rf24.write(&msg2, sizeof(msg2));  // 傳送資料

  59. #if 1
  60.   rf24.startListening();
  61.   started_waiting_at = micros();

  62.   while(1)
  63.   {
  64.     //if(rf24.available(&pipe))
  65.     if(rf24.available())
  66.     {
  67.        char msg[32] = "";
  68.        rf24.read(&msg, sizeof(msg));               
  69.        Serial.println(msg); // 顯示訊息內容
  70.        break;  
  71.     }
  72.   
  73.     if(micros() - started_waiting_at > 300000)    //If waited longer than 100ms, indicate timeout and exit while loop
  74.     {
  75.       rf24.stopListening();
  76.       rf24.write(&msg2, sizeof(msg2));  // 重傳資料
  77.       rf24.startListening();
  78.       started_waiting_at = micros();
  79.       Serial.println("Resend 2");
  80.     }
  81.   }
  82.   
  83. #endif
  84.   rf24.stopListening();

  85. }
複製代碼


master resend.png

不過不清楚為什麼一定要重傳一次
印像中SPI需要dummy data,會不會有關呢
還請熟悉SPI高手解惑
您需要登錄後才可以回帖 登錄 | 申請會員

本版積分規則

小黑屋|手機版|Archiver|機器人論壇 from 2005.07

GMT+8, 2020-7-6 01:50 , Processed in 0.069753 second(s), 8 queries , Apc On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表