Hat jemand von euch NRF24L01+ zum laufen gebracht?

Ich habe mir die Mirf Bibliothek heruntergeladen und und mal getestet. Aber es scheint nicht zu funktionieren.

EInmal Arduino UNO und einmal Sainssmart

angeschlossen mit 2 billigen NRF24L01+ Module

auf dem einen habe ich den Code ping_server sketch von mirf hochgeladen und auf dem anderen den ping_client Sketch. Doch es scheint nicht zu funktionieren. Serial output von client zeigt immer "Timeout on response from server!"

Der Server zeigt "listening..." ein paar mal "got packet, reply sent" dann nicht mehr.

In der Console erscheint niemals "Ping: X "

Hallo,

habe es recht gut hinbekommen mit

Gruss Kalli

forgoden:
Ich habe mir die Mirf Bibliothek heruntergeladen und und mal getestet. Aber es scheint nicht zu funktionieren.

Also bei mir funktionieren die Dinger mit der Mirf-Library ganz ausgezeichnet.

Man muß sich natürlich nicht nur die Library runterladen und installieren, sondern auch die Module korrekt anschließen, z.B. an 3.3V Betriebsspannung (und nicht an 5V). Die Datenleitungen vertragen allerdings 5V Pegel problemlos. Ich habe hier die Ping-Demoprogramme für Server und Client jedenfalls mit zwei Unos problemlos zum Laufen bekommen. Ping-Zeiten so ca. 11 bis 12 ms wenn ich mich richtig erinnere.

Wie hast Du sie denn an Deinem Uno angeschlossen?

Die Pinsbelegungen waren richtig. Ich habe inzwischen herausgefunden dass Sainsmart einen Kondensator 10uF zwischen 3.3. und GND benögtigt. Arduino UNO braucht das komischerweise nicht.

eine Frage noch: Es gibt diese NRF24L01+ mit Antenne: http://www.ebay.de/itm/170998228905?ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1438.l2649
wie groß wäre die Reichweite dann?
Hängt die Reichweite auch davon ab ob beide eine Antenne haben? Ist die Antenne Sender oder Empfänger?

Hallo,
dieses Modul ist ohne Empfangs - und Sendeverstärker. Die Reichweite ist größer als mit der kleinen
Antennenschleife. Antenne ist für Senden und Empfang. Über die Reichweite kann man meist nichts genaues sagen,
kommt immer auf die Bedingungen am Ort an. Ich habe Module mit Empfangs- und Sendeverstärker, da ist eine
Reichweite bis 1000m angegeben, aber nur im Freifeld, wenn sich beide Antennen sehen. Zuhause habe ich eine
Verbindung vom Keller in den zweiten Stock, musste für eine einigermaßen stabile Verbindung noch ein Modul als
Repeater dazwischenschalten.

Ausprobieren !!!

Gruss Kalli

forgoden:
Hängt die Reichweite auch davon ab ob beide eine Antenne haben? Ist die Antenne Sender oder Empfänger?

Antennen werden üblicherweise sowohl zum Senden als auch zum Empfangen verwendet.

Und die billigen NRF24L01+ sind auch nicht ohne Antenne, sondern sie haben eine Printantenne, das sind speziell geformte Leiterbahnen auf der Platine, die als Antenne dienen.

Da Printantennen eine Richtwirkung haben, wird die maximale Reichweite von Modulen mit Printantenne nur bei optimaler Ausrichtung erzielt. Bei Printantennen wäre die Ausrichtung und damit die Reichweite bei freier Sichtverbindung dann optimal, wenn sich die Platinen mit den Printantenne direkt gegenüberstehen (also so ausgerichtet sind, wie man die Platinen aufeinander legen würde). Falls keine direkte Sichtverbindung zwischen Sender und Empfänger besteht, kann die optimale Ausrichtung variieren (wegen Reflektionen an Wänden), bei so kurzwelligen Signalen kann es durchaus Unterschiede beim Empfang geben, wenn man die Empfangsposition mal um einige Zentimeter vor/zurück/seitlich verändert und die Platine zum Sender etwas anders dreht.

Mit der größeren Rundstabantenne wird der Empfang unabhängig von der Ausrichtung des Moduls (man sollte aber die Rundstäbe an Sender und Empfänger gleich ausrichten) und auch die Reichweite kann wegen des besseren Antennenwirkungsgrads etwas höher sein als mit Printantennen. Aber wie viel das unter bestimmten Gegebenheiten tatsächlich bringt, müßte wohl ausprobiert werden.

Hallo zusammen,
ich habe gerade diesen Thread gefunden. Ich benutze die NRF24 Bibiolithek. Die Beispielprogramme, besonders das mit IRQ, funktionieren einwandfrei. Mein Problem ist aber, dass der NRF24 bei Neustart eines Programms nicht mehr zu arbeiten scheint. Nach verschiedenen Aktionen wie Vcc(3.3V) aus und wieder an, oder COMport schließen und wieder starten, laufen sie aber wieder. Ist aber sehr mühsam und auch nicht wirklich reproduzierbar.
Vcc habe ich mit einem 100nF gegen GND versehen.

Frage 1: Kann mir jemand einen Code nennen, um die NRF24 zu resetten. Ich glaube man muss die Register zurücksetzen, aber wie? :drooling_face:
Frage 2. Ich habe den IQR mit einem 10k Pullup versehen. Ist das OK?

Gruß Kucky

Hallo Kucky,

kucky:
...
Mein Problem ist aber, dass der NRF24 bei Neustart eines Programms nicht mehr zu arbeiten scheint. Nach verschiedenen Aktionen wie Vcc(3.3V) aus und wieder an, oder COMport schließen und wieder starten, laufen sie aber wieder.
...

Ich verwende diese Librarie und habe bei der Intitialisierung des NRF24-Moduls ähnliche Effekte festgestellt. Manchmal sind die Register des NRF24-Moduls nach der Intitialisierung nicht richtig beschrieben.
Ich mache dann nochmal einen Reset am Arduino und dann läuft es zu 90%.
Es ist wohl ein Timingproblem mit der verwendeten NRF24-Librarie oder der SPI-Librarie.

Manchmal (alle paar Tage oder auch Wochen) hängt sich bei mir die Senderseite auf.
Wenn das der Fall ist macht der Mikrocontroller auf der Senderseite einen Software-Reset. Dann läuft es wieder.
Ich habe den Software-Reset seit etwa 14 Tagen in Betrieb, kann aber nicht sagen ob und wie oft der schon eingegriffen hat.

kucky:
...
Frage 2. Ich habe den IQR mit einem 10k Pullup versehen. Ist das OK?
...

Wenn der Pullup an 3,3V geschaltet ist kann er nicht schaden, es geht aber auch ohne diesen Widerstand.

Gruß Peter

Hallo Peter,
danke für die schnelle Antwort. Ich verwende die gleiche Lib. Ich habe mal so versucht....

			case 'r':
				printf("\n\rReset Interrupt \n\r");
				detachInterrupt(0);
				delay(1000);
				attachInterrupt(0, check_radio, FALLING);
				if ( role == role_receiver )
					radio.startListening();
				break;

... weil wohl hier die Register beschrieben werden. Leider ist der Erfolg eher mau. Bei mir ist das Problem eher auf der Empfangsseite. Wie genau machst Du den Software-Reset? Der Pullup liegt gegen 3.3V.

Gruß Willi

Hallo Willi,

ich verwende keinen Interrupt für die NRF24 Kommunikation in meiner Anwendung.
Ausgangspunkt für meine aktuell laufende Anwendung war das Beispiel "pingpair" und nicht "pingpair_irq".

Der von dir gepostete "Codefetzen" schaltet im Falle eines Interrupts den Receiver auf Empfang.
Der Code, macht so wie ich das sehe, keine Initialisierung der NRF24 Module.

Bei mir sieht der Setup-Teil auf der Empfängerseite derzeit so aus:

// Role
// Receiver - role = role_ping_out;
role = role_ping_out;

// Transmitter - role = role_pong_back;
//role = role_pong_back;
  
printf_begin();
printf("\n\rRF24/examples/pingpair/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);  

// Setup and configure rf radio
radio_1.begin();
radio_1.enableAckPayload();
radio_1.setAutoAck(true);
radio_1.setCRCLength(RF24_CRC_16);   // RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16
radio_1.setPALevel(RF24_PA_MAX);     // RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR    
radio_1.setDataRate(RF24_250KBPS);   // RF24_250KBPS , RF24_1MBPS , RF24_2MBPS
radio_1.setRetries(15,0);            // optionally, increase the delay between retries & # of retries
radio_1.setChannel(96);              // 0...127
radio_1.setPayloadSize(32);          // 1...32

// Open pipes to other nodes for communication
// This simple sketch opens two pipes for these two nodes to communicate
// back and forth.
// Open 'our' pipe for writing
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

// Master ATmega 2560
radio_1.openWritingPipe  (pipes[0]); // Receiver MEGA 2560
radio_1.openReadingPipe(1,pipes[1]); // Transmitter Garten
radio_1.openReadingPipe(2,pipes[2]); // Transmitter Reserve
radio_1.openReadingPipe(3,pipes[3]); // Transmitter Reserve
radio_1.openReadingPipe(4,pipes[4]); // Transmitter Reserve
radio_1.openReadingPipe(5,pipes[5]); // Transmitter Teststation

// Slave Garten
//radio.openWritingPipe(pipes[1]);
//radio.openReadingPipe(1,pipes[0]);

// Dump the configuration of the rf unit for debugging
radio_1.printDetails();

// Start listening
radio_1.startListening();

Wenn die Initialisierung erfolgreich war erhalte ich aus "radio_1.printDetails();" u.A. eine Ausgabe der Empfangsadressen:

RX_ADDR_P0-1	 = 0xf0f0f0f0e1 0xf0f0f0f0d2

Wenn die Initialisierung nicht funktioniert hat sieht die Ausgabe so, oder so ähnlich aus:

RX_ADDR_P0-1	 = 0x0000000000 0x0000000000

Derzeit Frage ich im Loop über "if (radio_1.available()) "ständig ab ob Daten empfangen wurden.
Wenn Daten vorhanden sind werden diese dann verarbeitet.

Um diese ständige Abfrage ob Daten vorhanden sind zu umgehen hatte ich auch mal versucht auf die Interrupt-Variante zu wechseln.
Das scheiterte aber an meiner Unfähigkeit den Code dazu zu schreiben.
Mein Problem war, dass das NRF24 Modul wohl zu drei verschiedenen Situationen einen Interrupt auslöst.
Ich habe in der NRF24-Librarie, oder bei der Initialisierung der Module, keine Möglichkeit gefunden das so umzustellen, das das Modul nur dann einen Interrupt auslöst wenn Daten empfangen wurden.

Weil ich aber deshalb bei jedem Interrupt erst nachschauen was der Auslöser war, habe ich die Interruptgeschichte wieder verworfen.

Der Software-Reset sieht so aus:

void softReset (void)
{
asm volatile ("jmp 0");
}

Wird aufgerufen wenn nach einer einstellbaren Überwachungszeit die Funkkommunikation nicht antwortet.
Der Software-Reset ist aber mit Vorsicht zu verwenden weil der Hardware Reset Pin hierauf nicht reagiert.
Angeschlossene Geräte mit Hardware Reset Pin bekommen das also nicht mit.

Gruß Peter

Einfach in den Reset Vektor zu springen hat auch den Nachteil dass damit die Register nicht auf 0 zurückgesetzt werden. Das kann negative Konsequenzen haben. Code kann sich z.B. darauf verlassen, dass diese auf 0 stehen. I/Os behalten ihren Zustand bei. Timer (die auch PWM machen) laufen weiter. Diverse Interruptquellen können aktiviert sein.

Das kann man aber beheben wenn man einen Reset über den Watchdog Timer auslöst:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_softreset
Erst das ist ein richtiger Reset in den Ausgangszustand

Serenifly:
...
Das kann man aber beheben wenn man einen Reset über den Watchdog Timer auslöst:
Frequently Asked Questions
Erst das ist ein richtiger Reset in den Ausgangszustand

Danke für die Erklärungen und den Link.
Mein englisch ist leider nicht so toll und ich kann deshalb mit den Erklärungen unter dem angegebenen Link wenig anfangen.
Wie müsste den der Code an Stelle von "asm volatile ("jmp 0");" aussehen um den Reset richtig zu machen?

Es bringt mir nichts im Loop ständig den Watchdog-Timer anzusprechen weil im Fehlerfall die Hauptroutine immer noch abgearbeitet wird. Es werden auch noch Daten empfangen und wohl auch aus softwaresicht noch Daten an das NRF24 Modul zum senden geschrieben. Aber das NRF24 Modul sendet diese aus irgend einem Grund nicht mehr.

In der Software habe ich einen millis() Zähler laufen der beim ordnungsgemäßem senden immer rückgesetzt wird.
Normalerweise wird alle 15 Sekunden gesendet und der Zähler somit alle 15s auf 0 gesetzt.
Wenn der über 125 Sekunden kommt rufe ich derzeit "softReset" auf.

Gruß Peter

Man aktiviert den WTD und startet eine Endlosschleife. 15ms später wird ein Reset ausgelöst, weil er nicht zurückgesetzt wird :slight_smile:

#include <avr/wdt.h>

#define soft_reset()        \
do                          \
{                           \
    wdt_enable(WDTO_15MS);  \
    for(;;)                 \
    {                       \
    }                       \
} while(0)

Zu dem Teil hier:

For newer AVRs (such as the ATmega1281) also add this function to your code to then disable the watchdog after a reset (e.g., after a soft reset):

Das bedeutet, dass auf neueren AVRs der WTD nach dem Reset noch aktiv ist. Darunter steht eine Funktion, die durch das section init3 im Startup Code ausgeführt wird (noch vor dem Programm) und den WTD abschaltet.

Code:

void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
void wdt_init(void)
{
    MCUSR = 0;
    wdt_disable();

    return;
}

Auf dem Arduino Mega sollte man damit aber sehr vorsichtig sein. Der hatte lange Zeit einen Bug im Bootloader wodurch der WTD nach einem Reset aktiviert blieb (und obiger Code ist da wohl keine Lösung, sonst gäbe ich nicht so viele Beschwerden). Da bin ich mir nicht sicher ob das inzwischen in der IDE gepatcht ist, da es vor relativ kurzer Zeit noch ein Problem war:
http://forum.arduino.cc/index.php?topic=204174.msg1507303#msg1507303
Selbst wenn der Fix inzwischen Teil der IDE ist müsste man den Bootload updaten.

Das gilt wie gesagt nur für den Mega! Auf dem UNO tritt das Problem nicht auf.

Danke für die schnelle Antwort!!

Ich glaube jetzt habe ich es verstanden.
Der WDT ist ständig inaktiv, erst wenn ich die "softReset" Funktion aufrufe wird der WDT aktiviert und dann durch eine Endlosschleife ausgelöst.
Ich werde das beim nächsten Softwareupdate entsprechend einbauen.

Was genau ist mit "neueren AVRs" gemeint?
Ich brauche den "softReset" auf einer Eigenbauplatine mit einem ATmega328P-PU.
Es ist kein Bootloader installiert. Funktioniert das damit?

Gruß Peter

peter_de:
Was genau ist mit "neueren AVRs" gemeint?

Steht nicht genau da. Es wird aber der Atmega1281 genannt. Der ist ein Zwischenstück zwischen Atmea328 und Atmega2560.

Ich würde das also immer Einbauen. Es schadet auch nichts, selbst wenn man es nicht bräuchte. Das deaktiviert einfach den WTD sehr früh während der Prozessor anläuft.

Die Bootloader Geschichte gilt wie gesagt nur für den Mega. Für dich dann nicht relevant.

Hallo zusammen,
vielen Dank, auch von mir. Ich glaube, dies auch im Großen und Ganzen verstanden zu haben. Ich werde meinen MEGAs einen aktuellen Bootloader verpassen. Aber wie genau rufe ich die "Reset-Funktion" auf. Ist vielleicht ´ne blöde Frage, stehe aber auf momentan dem Schlauch.

Gruß Willi

Wie gesagt, ich bin mir nicht sicher, dass der Bootloader der bei 1.0.5 dabei ist den Bug wirklich behoben hat. Es gibt aber auch .hex Files die wirklich gepatcht sind. Da kenne ich mich nicht so aus.

Aber wie genau rufe ich die "Reset-Funktion" auf

Das ist ein Makro, aber es wird genau wie eine Funktion aufgerufen:

soft_reset();

Könnte man wohl auch als echte Funktion schreiben

Aha, wieder was gelernt. Danke.

Ich hatte eben das hier gefunden:

#include <avr/wdt.h>

void reboot() {
  wdt_disable();  
  wdt_enable(WDTO_15MS);
  while (1) {}
}

Meinst Du die ..hex Files von Nickgammon?

Gruß Willi

kucky:
Ich hatte eben das hier gefunden:

Ja, das geht natürlich genauso.

Und dann eben der Teil:

void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
void wdt_init(void)
{
    MCUSR = 0;
    wdt_disable();

    return;
}

Das ist keine echte Funktion, sondern sieht nur so aus. Das wird automatisch in den Anfang des Speichers geschrieben und ausgeführt ohne das man es explizit aufruft

Meinst Du die ..hex Files von Nickgammon?

Ja, wobei das wahrscheinlich nicht der einzige Patch ist.