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


von Thomas Z. (tom_tom)


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
1
#include <SPI.h>
2
#include "nRF24L01.h"
3
#include "RF24.h"
4
#include "printf.h"
5
6
#include "LowPower.h"
7
8
//Status LED
9
#define STATUS_LED_RED 2
10
#define STATUS_LED_BLUE 3
11
12
//Soil Moisture Sensor
13
#define  SOIL_MOISTURE_VCC 10
14
#define  SOIL_MOISTURE_DATA 1
15
16
//NRF24L01
17
#define  NRF24L01_VCC 5
18
19
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9, 13 */ 
20
RF24 radio(8,7);
21
uint64_t pipeAddressSenderLivingroom = 0xf0f0f0f0e1;
22
uint64_t pipeAddressSenderKitchen = 0xf0f0f0f0e2;
23
uint64_t pipeAddressReceiver = 0xf0f0f0f0d2;
24
25
struct dataStruct{
26
  char room[4] = "KU";
27
  float temperature = 0.0; //Temperatur
28
  float humidity = 0.0; //Luftfeuchtigkeit
29
  float heatIndex = 0.0; //gefühlte Luftfeuchtigkeit
30
  uint16_t  soilMoisture = 0; //Bodenfeuchtigkeit
31
} data;
32
33
void initRadio() {
34
  Serial.println("INIT RADIO");
35
36
  pinMode(NRF24L01_VCC, OUTPUT);
37
  digitalWrite(NRF24L01_VCC,HIGH);
38
  delay(3000);
39
  //radio.failureDetected = 0;
40
  
41
  Serial.println("RADIO BEGIN");
42
  radio.begin();
43
  Serial.println("RADIO POWER UP");
44
  radio.powerUp();
45
  
46
  radio.setPALevel(RF24_PA_MAX); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
47
  radio.setDataRate(RF24_1MBPS); //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
48
  radio.setChannel(118); //87
49
  
50
  //radio.setAutoAck(1);                    // Ensure autoACK is enabled
51
  //radio.enableAckPayload();               // Allow optional ack payloads
52
  radio.setRetries(15,15);                 // Smallest time between retries, max no. of retries
53
  //radio.setPayloadSize(sizeof(bool));                // Here we are sending 1-byte payloads to test the call-response speed
54
  radio.openWritingPipe(pipeAddressSenderLivingroom);
55
  radio.openReadingPipe(1,pipeAddressReceiver);
56
  //radio.startListening();                 // Start listening
57
58
59
  //radio.enableDynamicAck();
60
  //radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
61
  Serial.println("RADIO STOP LISTENING");
62
  radio.stopListening();
63
  radio.flush_tx();
64
//  printf_begin();
65
  radio.printDetails();
66
67
68
}
69
70
void setup()
71
{
72
  //NRF24L01
73
  Serial.begin(9600);
74
  printf_begin();
75
  Serial.println("START");
76
  pinMode(STATUS_LED_RED, OUTPUT);
77
  pinMode(STATUS_LED_BLUE, OUTPUT);
78
79
  
80
}
81
82
83
void loop()
84
{
85
  digitalWrite(STATUS_LED_BLUE,HIGH);
86
  delay(300);
87
  digitalWrite(STATUS_LED_BLUE,LOW);
88
  //Sensoren mit Strom versorgen
89
  //Bodenfeuchtesensor anschalten
90
  pinMode(SOIL_MOISTURE_VCC, OUTPUT);
91
  digitalWrite(SOIL_MOISTURE_VCC,HIGH);
92
  
93
  initRadio();
94
  
95
  digitalWrite(STATUS_LED_RED,HIGH);
96
  delay(100);
97
  digitalWrite(STATUS_LED_RED,LOW);
98
99
  //Bodenfeuchtesensor auslesen
100
  //data.soilMoisture = analogRead(SOIL_MOISTURE_DATA);
101
102
    //bool ok = radio.write(&data,sizeof(dataStruct), 0);
103
    //bool ok = radio.write(&data,sizeof(dataStruct), 1);
104
    bool ok = radio.writeBlocking(&data,sizeof(dataStruct), 1000);
105
    radio.txStandBy(1000);
106
   
107
    if (ok)
108
    {
109
//      radio.startListening();
110
//      if (radio.available()) {
111
//        bool acknowledgement;
112
//        while(radio.available() ){                    // If an ack with payload was received
113
//          digitalWrite(STATUS_LED_BLUE,HIGH);
114
//          radio.read( &acknowledgement, sizeof(bool) ); 
115
//        }
116
//        digitalWrite(STATUS_LED_BLUE,LOW);
117
//        radio.stopListening();
118
//      }
119
      digitalWrite(STATUS_LED_BLUE,HIGH);
120
      delay(150);
121
      digitalWrite(STATUS_LED_BLUE,LOW);
122
      delay(150);
123
      digitalWrite(STATUS_LED_BLUE,HIGH);
124
      delay(150);
125
      digitalWrite(STATUS_LED_BLUE,LOW);
126
      delay(150);
127
      digitalWrite(STATUS_LED_BLUE,HIGH);
128
      delay(150);
129
      digitalWrite(STATUS_LED_BLUE,LOW);
130
      //radio.closeReadingPipe(1);
131
    }
132
    else {
133
      digitalWrite(STATUS_LED_RED,HIGH);
134
      delay(150);
135
      digitalWrite(STATUS_LED_RED,LOW);
136
      delay(150);
137
      digitalWrite(STATUS_LED_RED,HIGH);
138
      delay(150);
139
      digitalWrite(STATUS_LED_RED,LOW);
140
      delay(150);
141
      digitalWrite(STATUS_LED_RED,HIGH);
142
      delay(150);
143
      digitalWrite(STATUS_LED_RED,LOW);
144
      //radio.closeReadingPipe(1);
145
      delay(3000);
146
    }
147
    
148
149
//    radio.closeReadingPipe(1);
150
151
//    if (ok)
152
//      printf("ok.\n\r");
153
//    else
154
//      printf("failed.\n\r");
155
156
//  delay(dht.getMinimumSamplingPeriod());
157
158
  //Bodenfeuchtesensor abschalten
159
  pinMode(SOIL_MOISTURE_VCC, INPUT);
160
  digitalWrite(SOIL_MOISTURE_VCC,LOW);
161
  //radio.powerDown();
162
  delay(100);
163
  pinMode(NRF24L01_VCC, INPUT);
164
  digitalWrite(NRF24L01_VCC,LOW);
165
166
  int pinMode7 = getPinMode(7);
167
  int pinMode8 = getPinMode(8);
168
  int pinMode11 = getPinMode(11);
169
  int pinMode12 = getPinMode(12);
170
  int pinMode13 = getPinMode(13);
171
172
  int pinVal7 = digitalRead(7);
173
  int pinVal8 = digitalRead(8);
174
  int pinVal11 = digitalRead(11);
175
  int pinVal12 = digitalRead(12);
176
  int pinVal13 = digitalRead(13);
177
178
  pinMode(7, INPUT);
179
  pinMode(8, INPUT);
180
  pinMode(11, INPUT);
181
  pinMode(12, INPUT);
182
  pinMode(13, INPUT);
183
  digitalWrite(7,LOW);
184
  digitalWrite(8,LOW);
185
  digitalWrite(11,LOW);
186
  digitalWrite(12,LOW);
187
  digitalWrite(13,LOW);
188
  
189
  for (int i=0;i<1;i++) { //37 ca. 5 Minuten
190
    //LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
191
  }
192
  delay(5000);
193
194
//  leaveSleep();
195
196
//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
197
198
  pinMode(7, pinMode7);
199
  pinMode(8, pinMode8);
200
  pinMode(11, pinMode11);
201
  pinMode(12, pinMode12);
202
  pinMode(13, pinMode13);
203
204
  digitalWrite(7,pinVal7);
205
  digitalWrite(8,pinVal8);
206
  digitalWrite(11,pinVal11);
207
  digitalWrite(12,pinVal12);
208
  digitalWrite(13,pinVal13);
209
210
}
211
212
int getPinMode(uint8_t pin)
213
{
214
  if (pin >= NUM_DIGITAL_PINS) return (-1);
215
216
  uint8_t bit = digitalPinToBitMask(pin);
217
  uint8_t port = digitalPinToPort(pin);
218
  volatile uint8_t *reg = portModeRegister(port);
219
  if (*reg & bit) return (OUTPUT);
220
221
  volatile uint8_t *out = portOutputRegister(port);
222
  return ((*out & bit) ? INPUT_PULLUP : INPUT);
223
}



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

*C++ Programm auf dem BananaPi*
1
#include <stdio.h>
2
#include <cstdlib>
3
#include <iostream>
4
#include "/root/rf24pi/RF24.h"
5
#include <time.h> 
6
#include <fstream>
7
#include <string>
8
#include <sstream>
9
#include <curl/curl.h>
10
11
using namespace std;
12
13
bool writeValuesToFile = false;
14
bool writeValuesToFHEM = false;
15
16
//For Curl
17
string curlData; //will hold the url's contents
18
CURL* curl; //our curl object
19
  
20
  
21
uint8_t pipeNumerSenderLivingroom = 1;
22
uint64_t pipeAddressSenderLivingroom = 0xf0f0f0f0e1;
23
24
uint8_t pipeNumerSenderKitchen = 2;
25
uint64_t pipeAddressSenderKitchen = 0xf0f0f0f0e2;
26
27
uint64_t pipeAddressReceiver = 0xf0f0f0f0d2;
28
29
string _spidevice = "/dev/spidev0.0";
30
//uint32_t _spispeed = 8000000;
31
uint32_t _spispeed = 57600;
32
uint8_t _cepin = 25;
33
34
RF24 radio(_spidevice, _spispeed, _cepin);  //spi device, speed and CE,only CE is NEEDED in RPI
35
36
struct dataStruct{
37
  char room[4] = "WZ";
38
  float temperature = 0.0; //Temperatur
39
  float humidity = 0.0; //Luftfeuchtigkeit
40
  float heatIndex = 0.0; //gefühlte Luftfeuchtigkeit
41
  uint16_t  soilMoisture = 0; //Bodenfeuchtigkeit
42
};
43
  
44
  
45
void setup() {
46
  printf("RF24 SensorReceiver\n");
47
  // Setup and configure rf radio
48
  radio.begin();
49
50
  radio.setPALevel(RF24_PA_HIGH); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
51
  radio.setDataRate(RF24_1MBPS); //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
52
  radio.setChannel(118);
53
  radio.setRetries(15,15);                 // Smallest time between retries, max no. of retries
54
  //radio.setAutoAck(1);                    // Ensure autoACK is enabled
55
  //radio.enableDynamicAck();
56
  //radio.enableAckPayload();                     // Allow optional ack payloads
57
  //radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
58
  //radio.setPayloadSize(sizeof(bool));                // Here we are sending 1-byte payloads to test the call-response speed
59
  
60
  //Receiver
61
  radio.openReadingPipe(pipeNumerSenderLivingroom, pipeAddressSenderLivingroom);
62
  //radio.openReadingPipe(pipeNumerSenderKitchen, pipeAddressSenderKitchen);
63
64
  // Start the radio listening for data
65
  radio.startListening();
66
  radio.printDetails();
67
68
}
69
70
size_t writeCallback(char* buf, size_t size, size_t nmemb, void* up)
71
{ //callback must have this declaration
72
    //buf is a pointer to the data that curl has for us
73
    //size*nmemb is the size of the buffer
74
75
    for (int c = 0; c<size*nmemb; c++)
76
    {
77
        curlData.push_back(buf[c]);
78
    }
79
    return size*nmemb; //tell curl how many bytes we handled
80
}
81
82
//Convert numbers to string value
83
template <typename T> std::string toString(const T& value){
84
  std::stringstream ss;
85
  ss << value;
86
  return ss.str();
87
} 
88
89
90
void call_CurlURL(const char* url) {
91
    curl_global_init(CURL_GLOBAL_ALL); //pretty obvious
92
    curl = curl_easy_init();
93
94
    curl_easy_setopt(curl, CURLOPT_URL, url);
95
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
96
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //tell curl to output its progress
97
98
    curl_easy_perform(curl);
99
100
    cout << endl << curlData << endl;
101
102
103
    curl_easy_cleanup(curl);
104
    curl_global_cleanup();
105
  
106
}
107
108
  
109
int main(void)
110
{
111
  setup();
112
  
113
  time_t startTime;
114
  time_t currentTime;
115
116
  time(&startTime);
117
    
118
  double seconds;
119
  //while (seconds < 60)
120
  
121
122
  while (true)
123
  {
124
    time(&currentTime);
125
    seconds = difftime(currentTime, startTime);
126
    
127
    
128
    //check if new data available from pipeAddressSenderLivingroom
129
    if (radio.available(&pipeNumerSenderLivingroom)) {
130
      printf("Data available ");
131
      printf("%s \r\n", ctime (&currentTime) );
132
133
      //Data Array
134
      dataStruct data;
135
      
136
      while(radio.available(&pipeNumerSenderLivingroom)) {
137
        radio.read(&data, sizeof(dataStruct));
138
        //radio.stopListening();
139
        //bool acknowledgement;
140
        //radio.writeAckPayload(pipeNumerSenderKitchen, &acknowledgement, sizeof(bool) );
141
      }
142
          
143
      
144
      
145
      //radio.startListening();
146
            
147
      printf("Raum: \t\t\t %s \r\n", data.room);
148
      printf("Temperatur: \t\t %4.2f \r\n", data.temperature);
149
      printf("Luftfeuchtigkeit: \t %4.2f \r\n", data.humidity);
150
      printf("gefühlte Temp.: \t %4.2f \r\n", data.heatIndex);
151
      printf("Bodenfeuchtigkeit: \t %d \r\n", data.soilMoisture);
152
153
      printf("\r\n------------------------------------------\r\n","");
154
      
155
      if (writeValuesToFile) {
156
        //write data to file
157
         fstream file;
158
         file.open("SensorLivingroom.txt", ios::app);
159
         file << ctime (&currentTime) << "\r\n" << data.room << "\t" << data.temperature << "\t" << data.humidity << "\t" << data.heatIndex << "\t" << data.soilMoisture << endl;
160
         file << endl;
161
         file.close();
162
        delay(100);
163
      }
164
      
165
      if (writeValuesToFHEM) {
166
        //write data to FHEM
167
        //Temperatur
168
        string url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Temperatur%20";
169
        url.append(toString(data.temperature));
170
        url.append("&XHR=1");
171
        
172
        call_CurlURL(url.c_str());
173
        delay(100);
174
175
        //Luftfeuchtigkeit
176
        url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Luftfeuchtigkeit%20";
177
        url.append(toString(data.humidity));
178
        url.append("&XHR=1");
179
        
180
        call_CurlURL(url.c_str());
181
        delay(100);
182
        
183
        //Hitzeindex
184
        url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Hitzeindex%20";
185
        url.append(toString(data.heatIndex));
186
        url.append("&XHR=1");
187
        
188
        call_CurlURL(url.c_str());
189
        delay(100);
190
        
191
        //Bodenfeuchtigkeit
192
        url = "http://192.168.178.26:8085/fhem?cmd=setreading%20WZ_Sensor%20Bodenfeuchtigkeit%20";
193
        url.append(toString(data.soilMoisture));
194
        url.append("&XHR=1");
195
        
196
        call_CurlURL(url.c_str());
197
        delay(100);
198
      }
199
    }
200
    delay(10);
201
    
202
    
203
  } 
204
 
205
  return 0;
206
}

Vielleicht hatte schon jemand das gleiche Problem...?

Viele Grüße, Thomas

: Bearbeitet durch User
von Arduinoquäler (Gast)


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)


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)


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)


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)


Lesenswert?

Hallo Nordischer Halbleiter,

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

VG, Thomas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.