Forum: Mikrocontroller und Digitale Elektronik Arduino + RF24 (nRF24L01+) sendet/empfängt immer nur 3 Mal Daten


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Thomas Z. (tom_tom)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen, ich stehe vor dem Problem dass mein Pi nur exakt 3 Mal 
Daten empfangen kann und vermute dass ich irgendwo einen Fehler habe. 
Erst dachte ich, es wäre ein Problem auf Sender-Seite, aber nun konnte 
ich eingrenzen dass es auf Empfängerseite sein muss.

Ich starte das Emfpangs-Programm, gebe dann dem Sender Strom und er 
übermittelt die Daten korrekt. Allerdings nur 3 Mal. Danach ist Schluss.
Wenn ich nun das Empfänger-Programm auf dem Pi beende und wieder starte, 
erhalte ich wieder Daten. Allerdings wieder nur genau 3 Mal.


*Sender: Arduino Nano (atmega238P) mit NRF24L01+ Modul (inkl. 
Stützkondensator 100nF)*

Arduino Sketch
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

#include "LowPower.h"

//Status LED
#define STATUS_LED_RED 2
#define STATUS_LED_BLUE 3

//Soil Moisture Sensor
#define  SOIL_MOISTURE_VCC 10
#define  SOIL_MOISTURE_DATA 1

//NRF24L01
#define  NRF24L01_VCC 5

/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9, 13 */ 
RF24 radio(8,7);
uint64_t pipeAddressSenderLivingroom = 0xf0f0f0f0e1;
uint64_t pipeAddressSenderKitchen = 0xf0f0f0f0e2;
uint64_t pipeAddressReceiver = 0xf0f0f0f0d2;

struct dataStruct{
  char room[4] = "KU";
  float temperature = 0.0; //Temperatur
  float humidity = 0.0; //Luftfeuchtigkeit
  float heatIndex = 0.0; //gefühlte Luftfeuchtigkeit
  uint16_t  soilMoisture = 0; //Bodenfeuchtigkeit
} data;

void initRadio() {
  Serial.println("INIT RADIO");

  pinMode(NRF24L01_VCC, OUTPUT);
  digitalWrite(NRF24L01_VCC,HIGH);
  delay(3000);
  //radio.failureDetected = 0;
  
  Serial.println("RADIO BEGIN");
  radio.begin();
  Serial.println("RADIO POWER UP");
  radio.powerUp();
  
  radio.setPALevel(RF24_PA_MAX); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
  radio.setDataRate(RF24_1MBPS); //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
  radio.setChannel(118); //87
  
  //radio.setAutoAck(1);                    // Ensure autoACK is enabled
  //radio.enableAckPayload();               // Allow optional ack payloads
  radio.setRetries(15,15);                 // Smallest time between retries, max no. of retries
  //radio.setPayloadSize(sizeof(bool));                // Here we are sending 1-byte payloads to test the call-response speed
  radio.openWritingPipe(pipeAddressSenderLivingroom);
  radio.openReadingPipe(1,pipeAddressReceiver);
  //radio.startListening();                 // Start listening


  //radio.enableDynamicAck();
  //radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
  Serial.println("RADIO STOP LISTENING");
  radio.stopListening();
  radio.flush_tx();
//  printf_begin();
  radio.printDetails();


}

void setup()
{
  //NRF24L01
  Serial.begin(9600);
  printf_begin();
  Serial.println("START");
  pinMode(STATUS_LED_RED, OUTPUT);
  pinMode(STATUS_LED_BLUE, OUTPUT);

  
}


void loop()
{
  digitalWrite(STATUS_LED_BLUE,HIGH);
  delay(300);
  digitalWrite(STATUS_LED_BLUE,LOW);
  //Sensoren mit Strom versorgen
  //Bodenfeuchtesensor anschalten
  pinMode(SOIL_MOISTURE_VCC, OUTPUT);
  digitalWrite(SOIL_MOISTURE_VCC,HIGH);
  
  initRadio();
  
  digitalWrite(STATUS_LED_RED,HIGH);
  delay(100);
  digitalWrite(STATUS_LED_RED,LOW);

  //Bodenfeuchtesensor auslesen
  //data.soilMoisture = analogRead(SOIL_MOISTURE_DATA);

    //bool ok = radio.write(&data,sizeof(dataStruct), 0);
    //bool ok = radio.write(&data,sizeof(dataStruct), 1);
    bool ok = radio.writeBlocking(&data,sizeof(dataStruct), 1000);
    radio.txStandBy(1000);
   
    if (ok)
    {
//      radio.startListening();
//      if (radio.available()) {
//        bool acknowledgement;
//        while(radio.available() ){                    // If an ack with payload was received
//          digitalWrite(STATUS_LED_BLUE,HIGH);
//          radio.read( &acknowledgement, sizeof(bool) ); 
//        }
//        digitalWrite(STATUS_LED_BLUE,LOW);
//        radio.stopListening();
//      }
      digitalWrite(STATUS_LED_BLUE,HIGH);
      delay(150);
      digitalWrite(STATUS_LED_BLUE,LOW);
      delay(150);
      digitalWrite(STATUS_LED_BLUE,HIGH);
      delay(150);
      digitalWrite(STATUS_LED_BLUE,LOW);
      delay(150);
      digitalWrite(STATUS_LED_BLUE,HIGH);
      delay(150);
      digitalWrite(STATUS_LED_BLUE,LOW);
      //radio.closeReadingPipe(1);
    }
    else {
      digitalWrite(STATUS_LED_RED,HIGH);
      delay(150);
      digitalWrite(STATUS_LED_RED,LOW);
      delay(150);
      digitalWrite(STATUS_LED_RED,HIGH);
      delay(150);
      digitalWrite(STATUS_LED_RED,LOW);
      delay(150);
      digitalWrite(STATUS_LED_RED,HIGH);
      delay(150);
      digitalWrite(STATUS_LED_RED,LOW);
      //radio.closeReadingPipe(1);
      delay(3000);
    }
    

//    radio.closeReadingPipe(1);

//    if (ok)
//      printf("ok.\n\r");
//    else
//      printf("failed.\n\r");

//  delay(dht.getMinimumSamplingPeriod());

  //Bodenfeuchtesensor abschalten
  pinMode(SOIL_MOISTURE_VCC, INPUT);
  digitalWrite(SOIL_MOISTURE_VCC,LOW);
  //radio.powerDown();
  delay(100);
  pinMode(NRF24L01_VCC, INPUT);
  digitalWrite(NRF24L01_VCC,LOW);

  int pinMode7 = getPinMode(7);
  int pinMode8 = getPinMode(8);
  int pinMode11 = getPinMode(11);
  int pinMode12 = getPinMode(12);
  int pinMode13 = getPinMode(13);

  int pinVal7 = digitalRead(7);
  int pinVal8 = digitalRead(8);
  int pinVal11 = digitalRead(11);
  int pinVal12 = digitalRead(12);
  int pinVal13 = digitalRead(13);

  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  digitalWrite(7,LOW);
  digitalWrite(8,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  
  for (int i=0;i<1;i++) { //37 ca. 5 Minuten
    //LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
  delay(5000);

//  leaveSleep();

//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);

  pinMode(7, pinMode7);
  pinMode(8, pinMode8);
  pinMode(11, pinMode11);
  pinMode(12, pinMode12);
  pinMode(13, pinMode13);

  digitalWrite(7,pinVal7);
  digitalWrite(8,pinVal8);
  digitalWrite(11,pinVal11);
  digitalWrite(12,pinVal12);
  digitalWrite(13,pinVal13);

}

int getPinMode(uint8_t pin)
{
  if (pin >= NUM_DIGITAL_PINS) return (-1);

  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *reg = portModeRegister(port);
  if (*reg & bit) return (OUTPUT);

  volatile uint8_t *out = portOutputRegister(port);
  return ((*out & bit) ? INPUT_PULLUP : INPUT);
}



*Empfänger: BananaPi  mit NRF24L01+ Modul (inkl. Stützkondensator 
100nF)*

*C++ Programm auf dem BananaPi*
#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include "/root/rf24pi/RF24.h"
#include <time.h> 
#include <fstream>
#include <string>
#include <sstream>
#include <curl/curl.h>

using namespace std;

bool writeValuesToFile = false;
bool writeValuesToFHEM = false;

//For Curl
string curlData; //will hold the url's contents
CURL* curl; //our curl object
  
  
uint8_t pipeNumerSenderLivingroom = 1;
uint64_t pipeAddressSenderLivingroom = 0xf0f0f0f0e1;

uint8_t pipeNumerSenderKitchen = 2;
uint64_t pipeAddressSenderKitchen = 0xf0f0f0f0e2;

uint64_t pipeAddressReceiver = 0xf0f0f0f0d2;

string _spidevice = "/dev/spidev0.0";
//uint32_t _spispeed = 8000000;
uint32_t _spispeed = 57600;
uint8_t _cepin = 25;

RF24 radio(_spidevice, _spispeed, _cepin);  //spi device, speed and CE,only CE is NEEDED in RPI

struct dataStruct{
  char room[4] = "WZ";
  float temperature = 0.0; //Temperatur
  float humidity = 0.0; //Luftfeuchtigkeit
  float heatIndex = 0.0; //gefühlte Luftfeuchtigkeit
  uint16_t  soilMoisture = 0; //Bodenfeuchtigkeit
};
  
  
void setup() {
  printf("RF24 SensorReceiver\n");
  // Setup and configure rf radio
  radio.begin();

  radio.setPALevel(RF24_PA_HIGH); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
  radio.setDataRate(RF24_1MBPS); //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
  radio.setChannel(118);
  radio.setRetries(15,15);                 // Smallest time between retries, max no. of retries
  //radio.setAutoAck(1);                    // Ensure autoACK is enabled
  //radio.enableDynamicAck();
  //radio.enableAckPayload();                     // Allow optional ack payloads
  //radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
  //radio.setPayloadSize(sizeof(bool));                // Here we are sending 1-byte payloads to test the call-response speed
  
  //Receiver
  radio.openReadingPipe(pipeNumerSenderLivingroom, pipeAddressSenderLivingroom);
  //radio.openReadingPipe(pipeNumerSenderKitchen, pipeAddressSenderKitchen);

  // Start the radio listening for data
  radio.startListening();
  radio.printDetails();

}

size_t writeCallback(char* buf, size_t size, size_t nmemb, void* up)
{ //callback must have this declaration
    //buf is a pointer to the data that curl has for us
    //size*nmemb is the size of the buffer

    for (int c = 0; c<size*nmemb; c++)
    {
        curlData.push_back(buf[c]);
    }
    return size*nmemb; //tell curl how many bytes we handled
}

//Convert numbers to string value
template <typename T> std::string toString(const T& value){
  std::stringstream ss;
  ss << value;
  return ss.str();
} 


void call_CurlURL(const char* url) {
    curl_global_init(CURL_GLOBAL_ALL); //pretty obvious
    curl = curl_easy_init();

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //tell curl to output its progress

    curl_easy_perform(curl);

    cout << endl << curlData << endl;


    curl_easy_cleanup(curl);
    curl_global_cleanup();
  
}

  
int main(void)
{
  setup();
  
  time_t startTime;
  time_t currentTime;

  time(&startTime);
    
  double seconds;
  //while (seconds < 60)
  

  while (true)
  {
    time(&currentTime);
    seconds = difftime(currentTime, startTime);
    
    
    //check if new data available from pipeAddressSenderLivingroom
    if (radio.available(&pipeNumerSenderLivingroom)) {
      printf("Data available ");
      printf("%s \r\n", ctime (&currentTime) );

      //Data Array
      dataStruct data;
      
      while(radio.available(&pipeNumerSenderLivingroom)) {
        radio.read(&data, sizeof(dataStruct));
        //radio.stopListening();
        //bool acknowledgement;
        //radio.writeAckPayload(pipeNumerSenderKitchen, &acknowledgement, sizeof(bool) );
      }
          
      
      
      //radio.startListening();
            
      printf("Raum: \t\t\t %s \r\n", data.room);
      printf("Temperatur: \t\t %4.2f \r\n", data.temperature);
      printf("Luftfeuchtigkeit: \t %4.2f \r\n", data.humidity);
      printf("gefühlte Temp.: \t %4.2f \r\n", data.heatIndex);
      printf("Bodenfeuchtigkeit: \t %d \r\n", data.soilMoisture);

      printf("\r\n------------------------------------------\r\n","");
      
      if (writeValuesToFile) {
        //write data to file
         fstream file;
         file.open("SensorLivingroom.txt", ios::app);
         file << ctime (&currentTime) << "\r\n" << data.room << "\t" << data.temperature << "\t" << data.humidity << "\t" << data.heatIndex << "\t" << data.soilMoisture << endl;
         file << endl;
         file.close();
        delay(100);
      }
      
      if (writeValuesToFHEM) {
        //write data to FHEM
        //Temperatur
        string url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Temperatur%20";
        url.append(toString(data.temperature));
        url.append("&XHR=1");
        
        call_CurlURL(url.c_str());
        delay(100);

        //Luftfeuchtigkeit
        url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Luftfeuchtigkeit%20";
        url.append(toString(data.humidity));
        url.append("&XHR=1");
        
        call_CurlURL(url.c_str());
        delay(100);
        
        //Hitzeindex
        url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Hitzeindex%20";
        url.append(toString(data.heatIndex));
        url.append("&XHR=1");
        
        call_CurlURL(url.c_str());
        delay(100);
        
        //Bodenfeuchtigkeit
        url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Bodenfeuchtigkeit%20";
        url.append(toString(data.soilMoisture));
        url.append("&XHR=1");
        
        call_CurlURL(url.c_str());
        delay(100);
      }
    }
    delay(10);
    
    
  } 
 
  return 0;
}



Vielleicht hatte schon jemand das gleiche Problem...?

Viele Grüße, Thomas

: Bearbeitet durch User
von Arduinoquäler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Thomas Z. schrieb:
> Vielleicht hatte schon jemand das gleiche Problem...?

Wenn es genau dreimal funktioniert liegt es nahe dass die
RX- oder TX-Pipeline voll ist und nicht geleert wird (der
NRF24 hat eben einen 3-stufigen Buffer), aus welchen Gründen
auch immer .....

von Thomas Z. (tom_tom)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Arduinoquäler (geiler Name),

diese Vermutung habe ich auch. Allerdings weiß ich nicht wie ich diesen 
leeren kann. In der Doku habe ich dazu nicht wirklich was finden können.

Kann es evtl. auch damit zusammenhängen dass die Bibliotheken 
unterschiedlich sind? Die auf dem Pi ist 3 Jahre alt (keine neuere 
gefunden) und die vom Arduino hatte ich erst vor ein paar Wochen 
aktualisiert.

VG, Thomas

von Arduinoquäler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Thomas Z. schrieb:
> Kann es evtl. auch damit zusammenhängen dass die Bibliotheken
> unterschiedlich sind?

Weiss ich nicht, ich werde sie nicht vergleichen.

Aber eines fällt mir dazu noch ein: eine Pipe ist erst dann
geleert wenn alle Bytes geholt worden sind. Wenn du eine
Struktur zum Übertragen vereinbart hast und diese auf beiden
Systemen definiert hast können diese auf unterschiedlichen
Architekturen unterschiedlich gross sein (Fill Bytes wegen
Alignment). Das könnte also zu einem fehlerhafte Leeren
eines Buffers führen.

Ansonsten führt ein Flush eines Buffers indirekt zu dem
Ziel einen Buffer wieder frei zu machen. Ob die Lib dafür
ein API hat musst du selbst herausfinden.

von Nordischer Halbleiter (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Thomas Z. schrieb:
> Die auf dem Pi ist 3 Jahre alt (keine neuere gefunden)

Ich nutze auf dem RPi den RF24-Fork von TMRh20. Da diese Version 
regelmäßig aktualisiert wird ist höchstwahrscheinlich der ein oder 
andere Bug, der in deiner älteren Bibliothek noch schlummert, 
mittlerweile gefixt worden.

Code: https://github.com/TMRh20/RF24
Doku: http://tmrh20.github.io/RF24/

von Thomas Z. (tom_tom)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Nordischer Halbleiter,

danke für die Bibliothek. Jetzt funktioniert es alles so, wie es soll. 
:)

VG, Thomas

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.