xyzll3 發表於 2019-11-8 03:20:42

nRF24L01 一傳多問題

大家好
小弟用3個nRF24L01組成系統, 1個當master, 2個當slave
master定時輪流詢問slave(step 1,3), slave收到後回應master(step 2,4)


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


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

master 程式碼


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

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

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

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

void loop() {

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

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

while(1)
{
    //if(rf24.available(&pipe))
    if(rf24.available())
    {
       char msg = "";
       rf24.read(&msg, sizeof(msg));
       Serial.println(msg); // 顯示訊息內容
       break;
    }
   
    if(micros() - started_waiting_at > 100000)    //If waited longer than 100ms, indicate timeout and exit while loop
    {
      Serial.println("Timeout");
      break;
    }
}

rf24.stopListening();
#endif


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

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

while(1)
{
    //if(rf24.available(&pipe))
    if(rf24.available())
    {
       char msg = "";
       rf24.read(&msg, sizeof(msg));               
       Serial.println(msg); // 顯示訊息內容
       break;
    }

    if(micros() - started_waiting_at > 100000)    //If waited longer than 100ms, indicate timeout and exit while loop
    {
      Serial.println("Timeout");
      break;
    }
}

#endif
rf24.stopListening();

delay(1000);
}

slave1 程式碼


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

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

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

void setup() {
Serial.begin(9600);
rf24.begin();
rf24.setChannel(83);// 設定頻道編號
rf24.setPALevel(RF24_PA_MIN);
rf24.setDataRate(RF24_2MBPS);
rf24.openWritingPipe(addr_s_tx);      // 設定1Node通道位址   
rf24.openReadingPipe(pipe,addr_m_tx); // 設定1Node通道位址

rf24.startListening();// 開始監聽無線廣播
Serial.println("nRF24L01 slave1 ready!");
}

void loop() {
if (rf24.available(&pipe)) {
    char msg = "";
    rf24.read(&msg, sizeof(msg));
    Serial.println(msg); // 顯示訊息內容
    rf24.stopListening();
    rf24.write( &ack_msg, sizeof(ack_msg) );
    rf24.startListening();   
}
}

slave2 程式碼


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

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

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

void setup() {
Serial.begin(9600);
rf24.begin();
rf24.setChannel(83);// 設定頻道編號
rf24.setPALevel(RF24_PA_MIN);
rf24.setDataRate(RF24_2MBPS);
rf24.openWritingPipe(addr_s_tx);      // 設定2Node通道位址   
rf24.openReadingPipe(pipe,addr_m_tx); // 設定2Node通道位址

rf24.startListening();// 開始監聽無線廣播
Serial.println("nRF24L01 slave ready!");
}

void loop() {
if (rf24.available(&pipe)) {
    char msg = "";
    rf24.read(&msg, sizeof(msg));
    Serial.println(msg); // 顯示訊息內容
    rf24.stopListening();
    rf24.write( &ack_msg, sizeof(ack_msg) );
    rf24.startListening();   
}
}

超新手 發表於 2019-11-8 09:02:57

把 程式 TIMEOUT 時間加長
或是
SLAVE 端 調過來看   
原來

    Serial.println(msg); // 顯示訊息內容
    rf24.stopListening();
    rf24.write( &ack_msg, sizeof(ack_msg) );
    rf24.startListening();

改成

    rf24.stopListening();
    rf24.write( &ack_msg, sizeof(ack_msg) );
    rf24.startListening();
    Serial.println(msg); // 顯示訊息內容

xyzll3 發表於 2019-11-10 17:01:58

嗨,更新一下狀況
我後來排除timeout值太短或serial.println造成延遲的關係

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

master 程式碼


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

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

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

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

void loop() {

delay(1000);


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

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

while(1)
{
    //if(rf24.available(&pipe))
    if(rf24.available())
    {
       char msg = "";
       rf24.read(&msg, sizeof(msg));
       Serial.println(msg); // 顯示訊息內容
       break;
    }
   
    if(micros() - started_waiting_at > 300000)    //If waited longer than 100ms, indicate timeout and exit while loop
    {
      rf24.stopListening();
      rf24.write(&msg1, sizeof(msg1));// 重傳資料
      rf24.startListening();
      started_waiting_at = micros();
      Serial.println("Resend 1");
    }
}

rf24.stopListening();
#endif

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

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

while(1)
{
    //if(rf24.available(&pipe))
    if(rf24.available())
    {
       char msg = "";
       rf24.read(&msg, sizeof(msg));               
       Serial.println(msg); // 顯示訊息內容
       break;
    }

    if(micros() - started_waiting_at > 300000)    //If waited longer than 100ms, indicate timeout and exit while loop
    {
      rf24.stopListening();
      rf24.write(&msg2, sizeof(msg2));// 重傳資料
      rf24.startListening();
      started_waiting_at = micros();
      Serial.println("Resend 2");
    }
}

#endif
rf24.stopListening();

}



不過不清楚為什麼一定要重傳一次
印像中SPI需要dummy data,會不會有關呢
還請熟悉SPI高手解惑
頁: [1]
查看完整版本: nRF24L01 一傳多問題