Forum: Mikrocontroller und Digitale Elektronik nRF24L01 interrupt am Arduino


von Jonny H. (jonny123) Flattr this


Lesenswert?

Hallo,

ich möchte eine Smart-Home mit einem Arduino Mega als Master aufbauen, 
welches über CAN kommuniziert. Dies funktioniert bisher auch recht gut 
(im kleinen Aufbau).
Zusätzlich möchte ich auch andere Geräte über 2.4 Ghz ansprechen.
Hierzu habe ich mir ein paar nRF24L01 besorgt.


Allerdings ist das Programm so umfangreich, dass es immer um die 17 ms 
zum durchlaufen benötigt. Und es wird noch sehr viel umfangreicher.

Jetzt habe ich das Problem, dass das die am Master ankommenden Daten vom 
Slave nicht immer ausgewertet werden, weil das Programm gerade etwas 
anderes macht.

Also wollte ich den Interrupt Pin am nRF24L01 nutzen. Hierzu habe ich 
mir ein kleines Programm zum testen geschrieben.
1
/*
2
   2.4 GHz Master
3
4
  Pinbelegung:
5
    NRF24L01  | Arduino Uno/Nano/Mini  | Arduino Mega
6
    VCC                 3.3 V               3.3 V
7
    GND                 GND                 GND
8
    CSN                 8                   8
9
    CE                  7                   7
10
    SCK                 13                  52
11
    MOSI                11                  51
12
    MISO                12                  50
13
    IRQ                  3                   3
14
15
16
*/
17
#define SenderID 1 // Wie CAN-ID
18
19
20
#include <SPI.h>
21
#include <nRF24L01.h>
22
#include <RF24.h>
23
24
25
RF24 radio(7, 8); // CE, CSN
26
#define PinIRQ 3  // Arduino Uno, Mega und Nano: Pin 3
27
#define IRQ 1
28
const byte addresses[][6] = {"12345", "54321"}; // Kommunikationsrichtung: {"Slave -> Master", "Master -> Slave"};
29
30
unsigned long letzteUebermittelteNachricht = 0;
31
unsigned long SendeIntervall = 5000;
32
volatile unsigned char Empfangen[9];
33
volatile byte neueNachrichtEmpfangen = false;
34
35
void setup() {
36
  Serial.begin(115200);
37
  attachInterrupt(IRQ, AnkommendeNachricht, FALLING);
38
  radio.begin();
39
  radio.openWritingPipe(addresses[1]);      // Mater -> Slave
40
  radio.openReadingPipe(1, addresses[0]);   // Slave -> Master
41
  //radio.setPALevel(RF24_PA_MIN);
42
  radio.startListening();
43
}
44
void loop()
45
{
46
  unsigned long aktuelleMillis = millis();
47
  /*************************************************************
48
     Nachricht senden, falls das Sendeintervall abgelaufen ist
49
   *************************************************************/
50
  if (aktuelleMillis - letzteUebermittelteNachricht > SendeIntervall)
51
  {
52
    letzteUebermittelteNachricht = aktuelleMillis;
53
    int LaufzeitInSekunden = aktuelleMillis / 1000;
54
    unsigned char Sendung[9] = {SenderID, LaufzeitInSekunden, 1, 2, 3, 4, 5, 100, 255};
55
    radio.stopListening();
56
    radio.write(&Sendung, sizeof(Sendung));
57
    radio.startListening();
58
    Serial.print("2.4 Ghz-Nachricht gesendet: ");
59
    for (int i = 0; i < 9; i++)
60
    {
61
      Serial.print(Sendung[i]);
62
      Serial.print("\t");
63
    }
64
    Serial.println();
65
  }
66
  /*************************************************************
67
    Prüfen ob eine Nachricht vorliegt
68
  *************************************************************/
69
  if (neueNachrichtEmpfangen)
70
  {
71
    Serial.print("2.4 Ghz-Nachricht von ID ");
72
    Serial.print(Empfangen[0]);
73
    Serial.print(" empfangen: ");
74
    for (int i = 1; i < sizeof(Empfangen); i++)
75
    {
76
77
      Serial.print(Empfangen[i]);
78
      Serial.print("\t");
79
    }
80
    Serial.println();
81
    neueNachrichtEmpfangen = false;
82
  }
83
  if (aktuelleMillis % 1000 == 1)     // Zur Kontrolle, ob der Arduino noch läuft
84
  {
85
    Serial.println("Laeuft");
86
  }
87
  delay(1);
88
}
89
90
void AnkommendeNachricht()
91
{
92
  Serial.println("Interrupt");
93
  radio.read(Empfangen, sizeof(Empfangen));
94
  neueNachrichtEmpfangen = true;    // Variable setzen, dass eine neue Nachricht zur Auswertung bereit steht
95
}

Das Programm läuft ca 5 Sekunden einwandfrei und dann kommt permanent 
ein Interrupt, obwohl eigentlich nichts gesendet wird.
Sieht jemand den Fehler oder hat jemand etwas ähnliches schon gemacht?
Stört vielleicht mein 2.4 Ghz WLAN?

Meine 3.3V Spannungsquelle läuft recht stabil, soweit ich es ohne 
richtiges Oszi beurteilen kann.

Gruß
Jonny

: Bearbeitet durch User
von Anal Eiser (Gast)


Lesenswert?

Schwerster (und vielleicht einziger) Fehler den ich momentan
sehe ist dass du in deiner Funktion AnkommendeNachricht die ja
im Interrupt-Kontext aufgerufen wird, mit println arbeitest.

Das ist tötlich da du eine ganze Ewigkeit dort Zeit verbrauchst
Zeichen auszugeben und die Routine sich bemüssigt sieht dauernd
darauf zu warten dass dein serielles Terminal endlich alle
Zeichen empfangen hat.

Du musst ein Flag im Interrupt-Kontext setzen und in der Haupt-
schleife das "Signal" ausgeben. Aber auch da könnte es irgendwann
zeitlich eng werden wenn viele Interrupts und Daten vom NRF24
daherkommen.

von Anal Eiser (Gast)


Lesenswert?

Dein Buffer Empfangen[9] könnte auch überlaufen und deine RAM-
Inhalte zerschossen werden da eine Nachricht aus dem NRF24
32 Byte netto gross sein kann.

Auch das

radio.read(Empfangen, sizeof(Empfangen));

würde ich nicht im Interrupt-Kontext sondern Flag-gesteuert
in der Hautpschleife abarbeiten. Damit kann der Arduino
zeitlich relaxter reagieren. Ist allerdings nicht so dringend
da das Umkopieren der Daten nur ein paar Mikrosekunden dauert.

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.