Comments (22)
I have taken the configure IRQ example and modified it for use in relay project. Even now I still have Core Panic after seeing "IRQ pin is actively LOW".
`nRF24L01+ IRQ_Receiver
Receving...
Boot number: 1
IRQ pin is actively LOW
data_sent: 1, data_fail: 0, data_ready: 0
'Data Ready' eveGuru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
Core 1 register dump:
PC : 0x4008ddac PS : 0x00060935 A0 : 0x8008cd1e A1 : 0x3ffbf13c
A2 : 0x3ffb897c A3 : 0x3ffb81a4 A4 : 0x00000004 A5 : 0x00060923
A6 : 0x00060923 A7 : 0x00000001 A8 : 0x3ffb81a4 A9 : 0x00000018
A10 : 0x3ffb81a4 A11 : 0x00000018 A12 : 0x3ffc265c A13 : 0x00060923
A14 : 0x007bf398 A15 : 0x003fffff SAR : 0x0000001b EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x40088ea9 LEND : 0x40088eb9 LCOUNT : 0xfffffff9
Core 1 was running in ISR context:
EPC1 : 0x400dc63b EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x00000000
Backtrace: 0x4008dda9:0x3ffbf13c |<-CORRUPTED
Core 0 register dump:
PC : 0x4008df3b PS : 0x00060035 A0 : 0x8008c947 A1 : 0x3ffbeabc
A2 : 0x3ffbf398 A3 ���I� 0x00000000 LBEG : 0x40088ea9 LEND : 0x40088eb9 LCOUNT : 0xfffffff9
Core 1 was running in ISR context:
EPC1 : 0x400dc657 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x00000000
Backtrace: 0x4008dda7:0x3ffbf13c |<-CORRUPTED
`
Have no idea of what to do with the Core register dumps. Closer to goal than previously...
from rf24.
This would be a workaround until we can figure out what is going on here:
Just need to configure the CE,CS and IRQ pins.
/*
* See documentation at https://nRF24.github.io/RF24
* See License information at root directory of this library
* Author: Brendan Doherty (2bndy5)
*/
/**
* This example uses Acknowledgement (ACK) payloads attached to ACK packets to
* demonstrate how the nRF24L01's IRQ (Interrupt Request) pin can be
* configured to detect when data is received, or when data has transmitted
* successfully, or when data has failed to transmit.
*
* This example was written to be used on 2 devices acting as "nodes".
* Use the Serial Monitor to change each node's behavior.
*/
#include <SPI.h>
#include "printf.h"
#include "RF24.h"
// We will be using the nRF24L01's IRQ pin for this example
#define IRQ_PIN 27 // this needs to be a digital input capable pin
volatile bool wait_for_event = false; // used to wait for an IRQ event to trigger
volatile bool gotInterrupt = false;
#define CE_PIN 12
#define CSN_PIN 14
// instantiate an object for the nRF24L01 transceiver
RF24 radio(CE_PIN, CSN_PIN);
// Let these addresses be used for the pair
uint8_t address[][6] = { "1Node", "2Node" };
// It is very helpful to think of an address as a path instead of as
// an identifying device destination
// to use different addresses on a pair of radios, we need a variable to
// uniquely identify which address this radio will use to transmit
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
// Used to control whether this node is sending or receiving
bool role = false; // true = TX node, false = RX node
// For this example, we'll be using a payload containing
// a string that changes on every transmission. (successful or not)
// Make a couple arrays of payloads & an iterator to traverse them
const uint8_t tx_pl_size = 5;
const uint8_t ack_pl_size = 4;
uint8_t pl_iterator = 0;
// The " + 1" compensates for the c-string's NULL terminating 0
char tx_payloads[][tx_pl_size + 1] = { "Ping ", "Pong ", "Radio", "1FAIL" };
char ack_payloads[][ack_pl_size + 1] = { "Yak ", "Back", " ACK" };
void interruptHandler(); // prototype to handle IRQ events
void printRxFifo(); // prototype to print RX FIFO with 1 buffer
void setup() {
Serial.begin(115200);
while (!Serial) {
// some boards need to wait to ensure access to serial over USB
}
// initialize the transceiver on the SPI bus
if (!radio.begin()) {
Serial.println(F("radio hardware is not responding!!"));
while (1) {} // hold in infinite loop
}
// print example's introductory prompt
Serial.println(F("RF24/examples/InterruptConfigure"));
// To set the radioNumber via the Serial monitor on startup
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
while (!Serial.available()) {
// wait for user input
}
char input = Serial.parseInt();
radioNumber = input == 1;
Serial.print(F("radioNumber = "));
Serial.println((int)radioNumber);
// role variable is hardcoded to RX behavior, inform the user of this
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
// setup the IRQ_PIN
pinMode(IRQ_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(IRQ_PIN), interruptHandler, FALLING);
// IMPORTANT: do not call radio.available() before calling
// radio.whatHappened() when the interruptHandler() is triggered by the
// IRQ pin FALLING event. According to the datasheet, the pipe information
// is unreliable during the IRQ pin FALLING transition.
// Set the PA Level low to try preventing power supply related problems
// because these examples are likely run with nodes in close proximity to
// each other.
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
// For this example we use acknowledgment (ACK) payloads to trigger the
// IRQ pin when data is received on the TX node.
// to use ACK payloads, we need to enable dynamic payload lengths
radio.enableDynamicPayloads(); // ACK payloads are dynamically sized
// Acknowledgement packets have no payloads by default. We need to enable
// this feature for all nodes (TX & RX) to use ACK payloads.
radio.enableAckPayload();
// Fot this example, we use the same address to send data back and forth
// set the TX address of the RX node into the TX pipe
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
// set the RX address of the TX node into a RX pipe
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
// additional setup specific to the node's role
if (role) {
// setup for TX mode
radio.stopListening(); // put radio in TX mode
} else {
// setup for RX mode
// let IRQ pin only trigger on "data ready" event in RX mode
radio.maskIRQ(1, 1, 0); // args = "data_sent", "data_fail", "data_ready"
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
radio.startListening(); // put radio in RX mode
}
// For debugging info
// printf_begin(); // needed only once for printing details
// radio.printDetails(); // (smaller) function that prints raw register values
// radio.printPrettyDetails(); // (larger) function that prints human readable data
}
void loop() {
if (gotInterrupt) {
gotInterrupt = false;
Serial.println(F("\tIRQ pin is actively LOW")); // show that this function was called
delayMicroseconds(250);
bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
radio.whatHappened(tx_ds, tx_df, rx_dr); // get values for IRQ masks
// whatHappened() clears the IRQ masks also. This is required for
// continued TX operations when a transmission fails.
// clearing the IRQ masks resets the IRQ pin to its inactive state (HIGH)
Serial.print(F("\tdata_sent: "));
Serial.print(tx_ds); // print "data sent" mask state
Serial.print(F(", data_fail: "));
Serial.print(tx_df); // print "data fail" mask state
Serial.print(F(", data_ready: "));
Serial.println(rx_dr); // print "data ready" mask state
if (tx_df) // if TX payload failed
radio.flush_tx(); // clear all payloads from the TX FIFO
// print if test passed or failed. Unintentional fails mean the RX node was not listening.
// pl_iterator has already been incremented by now
if (pl_iterator <= 1) {
Serial.print(F(" 'Data Ready' event test "));
Serial.println(rx_dr ? F("passed") : F("failed"));
} else if (pl_iterator == 2) {
Serial.print(F(" 'Data Sent' event test "));
Serial.println(tx_ds ? F("passed") : F("failed"));
} else if (pl_iterator == 4) {
Serial.print(F(" 'Data Fail' event test "));
Serial.println(tx_df ? F("passed") : F("failed"));
}
wait_for_event = false; // ready to continue with loop() operations
}
if (role && !wait_for_event) {
// delay(1); // wait for IRQ pin to fully RISE
// This device is a TX node. This if block is only triggered when
// NOT waiting for an IRQ event to happen
if (pl_iterator == 0) {
// Test the "data ready" event with the IRQ pin
Serial.println(F("\nConfiguring IRQ pin to ignore the 'data sent' event"));
radio.maskIRQ(true, false, false); // args = "data_sent", "data_fail", "data_ready"
Serial.println(F(" Pinging RX node for 'data ready' event..."));
} else if (pl_iterator == 1) {
// Test the "data sent" event with the IRQ pin
Serial.println(F("\nConfiguring IRQ pin to ignore the 'data ready' event"));
radio.maskIRQ(false, false, true); // args = "data_sent", "data_fail", "data_ready"
Serial.println(F(" Pinging RX node for 'data sent' event..."));
} else if (pl_iterator == 2) {
// Use this iteration to fill the RX node's FIFO which sets us up for the next test.
// write() uses virtual interrupt flags that work despite the masking of the IRQ pin
radio.maskIRQ(1, 1, 1); // disable IRQ masking for this step
Serial.println(F("\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected."));
// write() will call flush_tx() on 'data fail' events
if (radio.write(&tx_payloads[pl_iterator], tx_pl_size)) {
if (radio.rxFifoFull()) {
Serial.println(F("RX node's FIFO is full; it is not listening any more"));
} else {
Serial.println("Transmission successful, but the RX node might still be listening.");
}
} else {
Serial.println(F("Transmission failed or timed out. Continuing anyway."));
radio.flush_tx(); // discard payload(s) that failed to transmit
}
} else if (pl_iterator == 3) {
// test the "data fail" event with the IRQ pin
Serial.println(F("\nConfiguring IRQ pin to reflect all events"));
radio.maskIRQ(0, 0, 0); // args = "data_sent", "data_fail", "data_ready"
Serial.println(F(" Pinging inactive RX node for 'data fail' event..."));
}
if (pl_iterator < 4 && pl_iterator != 2) {
// IRQ pin is LOW when activated. Otherwise it is always HIGH
// Wait until IRQ pin is activated.
wait_for_event = true;
// use the non-blocking call to write a payload and begin transmission
// the "false" argument means we are expecting an ACK packet response
radio.startFastWrite(tx_payloads[pl_iterator++], tx_pl_size, false);
// In this example, the "data fail" event is always configured to
// trigger the IRQ pin active. Because the auto-ACK feature is on by
// default, we don't need a timeout check to prevent an infinite loop.
} else if (pl_iterator == 4) {
// all IRQ tests are done; flush_tx() and print the ACK payloads for fun
// CE pin is still HIGH which consumes more power. Example is now idling so...
radio.stopListening(); // ensure CE pin is LOW
// stopListening() also calls flush_tx() when ACK payloads are enabled
printRxFifo();
pl_iterator++;
// inform user what to do next
Serial.println(F("\n*** PRESS 'T' to restart the transmissions"));
Serial.println(F("*** PRESS 'R' to change to Receive role\n"));
} else if (pl_iterator == 2) {
pl_iterator++; // proceed from step 3 to last step (stop at step 4 for readability)
}
} else if (!role) {
// This device is a RX node
if (radio.rxFifoFull()) {
// wait until RX FIFO is full then stop listening
delay(100); // let ACK payload finish transmitting
radio.stopListening(); // also discards unused ACK payloads
printRxFifo(); // flush the RX FIFO
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1.
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
delay(100); // let TX node finish its role
radio.startListening(); // We're ready to start over. Begin listening.
}
} // role
if (Serial.available()) {
// change the role via the serial monitor
char c = toupper(Serial.read());
if (c == 'T') {
// Become the TX node
if (!role)
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
else
Serial.println(F("*** RESTARTING IRQ PIN TEST ***"));
role = true;
wait_for_event = false;
pl_iterator = 0; // reset the iterator
radio.flush_tx(); // discard any payloads in the TX FIFO
// startListening() clears the IRQ masks also. This is required for
// continued TX operations when a transmission fails.
radio.stopListening(); // this also discards any unused ACK payloads
} else if (c == 'R' && role) {
// Become the RX node
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
role = false;
radio.maskIRQ(0, 0, 0); // the IRQ pin should only trigger on "data ready" event
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
radio.flush_tx(); // make sure there is room for 3 new ACK payloads
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
radio.startListening();
}
} // Serial.available()
} // loop
/**
* when the IRQ pin goes active LOW, call this fuction print out why
*/
void interruptHandler() {
gotInterrupt = true;
} // interruptHandler
/**
* Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
* Remember that the payload sizes are declared as tx_pl_size and ack_pl_size.
*/
void printRxFifo() {
if (radio.available()) { // if there is data in the RX FIFO
// to flush the data from the RX FIFO, we'll fetch it all using 1 buffer
uint8_t pl_size = !role ? tx_pl_size : ack_pl_size;
char rx_fifo[pl_size * 3 + 1]; // RX FIFO is full & we know ACK payloads' size
if (radio.rxFifoFull()) {
rx_fifo[pl_size * 3] = 0; // add a NULL terminating char to use as a c-string
radio.read(&rx_fifo, pl_size * 3); // this clears the RX FIFO (for this example)
} else {
uint8_t i = 0;
while (radio.available()) {
radio.read(&rx_fifo + (i * pl_size), pl_size);
i++;
}
rx_fifo[i * pl_size] = 0; // add a NULL terminating char to use as a c-string
}
Serial.print(F("Complete RX FIFO: "));
Serial.println(rx_fifo); // print the entire RX FIFO with 1 buffer
}
}
from rf24.
Created a branch named update-irq-example with the changes proposed to both Linux and Arduino examples (not py example)
from rf24.
Have "Switch Project" turning switch on and off using RF24 IRQ interrupt:
22:16:27.790 -> Boot number: 2
22:16:27.822 ->
22:16:27.822 -> IRQ pin is actively LOW
22:16:27.822 -> data_sent: 1, data_fail: 0, data_ready: 0
22:16:27.887 -> 'Data Ready' event test failed
22:16:27.918 -> switchState: 1
22:16:27.950 ->
22:16:27.950 -> Battery power switched ON
22:16:27.950 -> ESP32 wake from Deep Sleep
22:16:27.993 ->
22:16:47.670 ->
22:16:47.670 -> IRQ pin is actively LOW
22:16:47.702 -> data_sent: 1, data_fail: 0, data_ready: 0
22:16:47.735 -> 'Data Ready' event test failed
22:16:47.767 -> switchState: 2
22:16:47.799 ->
22:16:47.799 -> Battery power switched OFF
22:16:47.831 -> ESP32 going to Deep Sleep
22:17:00.243 -> ��&zy��V���$g���
22:17:00.307 ->
22:17:00.307 ->
22:17:00.307 -> nRF24L01+ IRQ_Receiver
22:17:00.338 -> Receving...
22:17:00.371 ->
22:17:00.371 -> Boot number: 3
22:17:00.371 ->
22:17:00.371 -> IRQ pin is actively LOW
22:17:00.402 -> data_sent: 1, data_fail: 0, data_ready: 0
22:17:00.435 -> 'Data Ready' event test failed
22:17:00.499 -> switchState: 1
22:17:00.499 ->
22:17:00.499 -> Battery power switched ON
22:17:00.531 -> ESP32 wake from Deep Sleep
Is it possiable to send just an IRQ signal; when nRF24L01 is powerDown. Think I read the IRQ is available in powerdown mode.
Maybe have two instances of RF24; one for switchState and one for IRQ signal, or just add another member to structure for switchState.
Would like to use powerDown() and powerUP() in project; investigating more. Appreciate how responsive you have been with the library.
from rf24.
Swapped radio; issue is resolved.
Should there be an immediate response from the Transmit ping test?
from rf24.
Should there be an immediate response from the Transmit ping test?
Yes. In testing the configure IRQ example, I always enabled the RX side before engaging the TX side.
But I'm not sure why it is panicking. There must be a buffer operation missing if response is not received.
from rf24.
bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
radio.whatHappened(tx_ds, tx_df, rx_dr);
wait_for_event = false;
I seem to be getting a similar reaction from my ESP32 using the interrupt example. I modified the interrupt to contain just the above, and it still does it on reception of data. If I remove everything except for the wait_for_event=false
then it doesn't hang anymore. I suspect there is something going on with SPI and/or SPI transactions as they are supposed to be interrupt safe.
This will take some time to debug, so I would suggest not using interrupts with ESP32 for the time being, unless you can move all the functions that call SPI commands to outside of the interrupt.
from rf24.
We should also flush the RX FIFO when switching back to RX role. That example has been in need of some attention.
from rf24.
Would it be possiable to have a basic IRQ config for using interrupts; for example just minimum needed to implement in a project?
I did my best to sort out what I believed is needed for both transmitter and receiver. Could have missed something...
from rf24.
Would it be possiable to have a basic IRQ config for using interrupts
I would refer to the docs for finer detail:
from rf24.
Interrupt wdt timeout on CPU1
I believe this error is trying to say something. Probably all the stuff that was going on in that ISR was taking too long for a typical ISR. There may also be some kind of mutex lock on the Serial bus.
from rf24.
Should there be Serial Prints in an isr; think I read they should not be used in isr and the time spent in isr short.
from rf24.
If I remove everything except for the wait_for_event=false then it doesn't hang anymore.
Reminds me of rust programming language's closures. Any members of an ISR may have to be limited to volatile memory on the ESP32. Its easier to just separate everything out.
from rf24.
Will make changes to project code; thank you appreciate the help!
from rf24.
from rf24.
Getting ready to test; have moved everything below whatHappen to a conditional flag in loop.
from rf24.
This is how I setup the isr; moving the function to loop with a conditional statement of interruptResults:
`portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
volatile int interruptResults;
void isr() {
portENTER_CRITICAL_ISR(&mux);
interruptResults = 1;
portEXIT_CRITICAL_ISR(&mux);
}
`
Void loop(){ if(interruptResults){ .....your interruptHandler here no more core panic... received a couple of messages with SwitchState value of 1 more responses all following were switchState = 0 and not a value of expected 2. }
SwitchState comes on, in my code; switchState off does not change to off.
Something I missed. Do I need to clear anything before next radio,write()?
from rf24.
Is it possible to send just an IRQ signal; when nRF24L01 is powerDown.
Nope, the Microcontroller can be powered down, but not the radio if you want to receive data/trigger IRQ.
from rf24.
Any way to lower current comsumption? Standby I or II?.
Measured 25.5 mA with RF24_PA_LOW. Will be running from battery...
from rf24.
For hardware reasons, listening has to be done in Standby-II. The only configuration that might affect power consumption is the PA level (lower is better for consumption but worse for distance).
Remember, the PA level might be hardwired for some modules, namely ebyte modules.
from rf24.
@Tech500 Thinking we can close this issue now? Hoping you've had success with your project(s)!
from rf24.
I should PR my changes to the IRQ examples to help satisfy the panic problem
I just haven't got around to do much testing
from rf24.
Related Issues (20)
- nRF24L01+ gets recognized as nRF24L01 after software reboot HOT 7
- STM32F411 doesn't receive data HOT 4
- [feature request] support ESP-IDF platform HOT 19
- namespace for utility drivers HOT 3
- Multiple I2C buses In ESP 32 with multiple ports
- ESP32 and two Infrared Temperature Sensors (MLX90614) HOT 1
- Calling radio.available() after failed transmission when using writeFast or startWrite causes interrupt loop HOT 10
- 'make' errors, and RF24 on RPi, aarch64-linux-gnu HOT 18
- [Question] NRF24 Transmitter get "stuck" when powered from wall power outlet HOT 2
- RPi5 uses different gpio pin numbers (per Linux kernel update) HOT 48
- Radio.printDetails(); does nothing for MKR1010 but Radio.sprintfPrettyDetails(buffer); works fine???? HOT 4
- Pipe is sometimes returned at "255". HOT 15
- Is there a known ESP32 Deep Sleep issue with radio.powerDown()? [Question] HOT 19
- Can RF24 library be used with WiFi? HOT 2
- Can RF24 library be used with WiFi? HOT 4
- [Question] setChannel & setDataRate not read correctly by printPrettyDetails ? HOT 4
- Use Linux kernel's character device API to implement IRQ capability HOT 113
- [Question] R24.h, testRPD(void) "Strong signal > 64dBm" : "Weak signal < 64dBm" HOT 5
- [Question] Issue using the ManualAcknowledgements.ino HOT 11
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rf24.