When trying to sleep the Arduino and using interrupt to wake it up the Arduino is immediately woken up, even when the interrupt pin is unconnected. I believe it is related to the NB-IoT shield is connected. It only, happens if the shield is connected to network. Also tried to do MODEM_STREAM.end() with no success, in case it was related to shield using the UART to wake it up. Is this related to WDT used by the library?
Dear Sindre,
This should not be related to the wdt functions inside the nb-iot library.
These are implemented to make our library wdt friendly.
To use a wdt you need to enable it in the sketch. (.ino file)
Do you use the correct way to implement the interrupt?
See documentation: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
Best regards,
Jan
Hi Jan,
Thank you for your reply.
Yes, I have correctly implemented the interrupt.
It is only happening after communication with the shield before putting the Arduino to sleep, then the Arduino is immediately woken up not triggered by the interrupt.
I am doing DEBUG_STREAM.flush() and MODEM_STREAM.end() before going to sleep also with no success. If i power up the shield and keep it connected as long as I dont ask for any data from the shield then the Arduino is keeping sleeping waiting for interrupt to fire.
Any suggestions?
Hi Sindrevr,
It is quite possible that activity on the UART is generating an interrupt which is immediately waking the board (which board are you using?). You could try adding a small delay before entering sleep mode.
Hi Gabriel,
Thank you for your early reply.
I am using the Leonardo, i have tried both adding small & big delays.
Disabling DEBUG, ending serial comm prior going to sleep without any success.
Also switched to UNO and used jumper wires between the shield and UNO still without any success.
If i dont request any data from the SODAQ shield then the Arduino is going to sleep and stay in sleep mode until interrupt on the selected pin occurs. Could you confirm that Arduino sleep mode is tested with this shield / library? The reason i suspected the library is that it also happens when just asking for “nbiot.getDefaultBaudrate()”. And that information is just stored in the library is my understanding.
I am out of ideas.
BR,
Sindre
Can you show me what code you are using to place the board in power down or sleep mode?
Additionally, I believe the issue is that something is generating an interrupt which is immediately waking the board. Can you also provide the section of code which sets up any interrupts.
Hi Gabriel,
Attached is a snip from the code.
The shield is connected with jumper wires, so powering shield is done with pin 6.
#include <avr/sleep.h>
const byte interruptPin = 7;
volatile byte state = LOW;
void setup()
{
pinMode(interruptPin, INPUT_PULLUP);
nbiot.init(MODEM_STREAM, 6);
}
void loop()
{
if (nbiot.connect(apn, cdp, “”)) {
DEBUG_STREAM.println(“Connected succesfully!”);
MODEM_STREAM.println(“AT+NSOCR=DGRAM,17,1234,1”);
do_flash_led(13);
}
else {
DEBUG_STREAM.println(“Failed to connect!”);
delay(2000);
return;
}
nbiot.disconnect();
delay(3000);
sleepNow();
}
void sleepNow() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
DEBUG_STREAM.flush();
DEBUG_STREAM.end();
MODEM_STREAM.end();
sodaq_wdt_safe_delay(5000);
sleep_enable();
attachInterrupt(digitalPinToInterrupt(interruptPin), logData, LOW);
sleep_mode();
//CONTINUE HERE AFTER WAKING UP
sleep_disable();
DEBUG_STREAM.begin(9600);
MODEM_STREAM.begin(9600);
detachInterrupt(4); //avoid random interrupts*/
}
void logData() {
//do something quick, flip a flag, and handle in loop() - or do nothing at all, here
}
That doesen`t work.
I have tried entering “4” that should be the interrupt no for pin 7 on the Leonardo.
Using “7” or the variable for pin7 does not work…
Sorry, I got confused with which board you were using. I’m not entirely familiar with the Leonardo board and the specifics of the sleep functionality for that MCU.
There is something else going on with your interrupt pin which is causing the board to wake immediately (or effectively preventing it from entering sleep mode). I would recommend perhaps attaching a scope to see what is going on.
The library does not actually use the watch dog timer (neither does your sketch appear to be using it either). It just uses the safe delay method.
One other thing you could try is to switch off the NB-IoT after you are finished (after disconnect()). There is a method off(), you don’t need to switch it back on as the connect function will do that for you.
Also one other thing, could you list the pins that you have wired up.
The minimum required pins are (shield pins referenced):
- D0 / RX
- D1 / TX
- D7 / Enable
- 3.3V
- 5V (for 5V IO levels)
- GND
- IO_REF
http://support.sodaq.com/wp-content/uploads/2017/02/nb-iot_shield_rev3b_sch-1.pdf
I have tried both nbiot.disconnect() and nbiot.off() without any improvements.
The reason that I suspect the library to do something strange is because the Arduino “deny” to stay sleeping. If i don´t perform any “nbiot.***()” commands at all before going to sleep then the Arduino is sleeping until a interrupt occurs. Even when all the jumper cables between Leonardo and Sodaq shield is disconnected and i perform an “nbiot.” command the Arduino “reject” to stay sleeping…
Both tried on Arduino Uno and Leonardo.
Serial monitor when Sodaq shield is physically disconnected and one nbiot. command is performed:
SODAQ All Things Talk Arduino Example
[rdResp]: timed out
Going to sleep
AWAKE
[rdResp]: timed out
Going to sleep
AWAKE
[rdResp]: timed out
Going to sleep
AWAKE
As mentioned earlier in this post, the shield could be connected and the Arduino would stay sleeping as long as I don`t perform any nbiot. command. So i doubt any external interrupts is actually happening as this is happening also when shield is disconnected, but offcourse only if I perform a nbiot. command. A digital analyzer / oscilloscope is arriving tomorrow. But i doubt there is physical interrupts happening.
Do you have the ability to check it out yourself using Leonardo / Uno?
All the pins that you mentioned is connected.
Thank you for all the support.
I’m sorry but I don’t have the necessary hardware to test this.
All the library actually does is read and write to the stream object which is connected to the UART (additionally, you can specify a second debug stream).
The only watch dog timer calls are done to the reset function which simply clears any pending interrupt from that module (if enabled). The safe delay method also makes calls to that reset method (to prevent a delay from triggering a board reset).
I do not believe this will have any effect on your sleep cycle, however, if necessary, you can remove the lines from the library files. There are only three references, one to sodaq_wdt_reset() which can be removed and two which call the safe delay method which can be swapped for the standard delay().
Finally
Removing sodaq_wdt_reset(); and modifying the 3 sodaq_wdt_safe_delay(delay_count) to use standard delay() did the job. Now the Arduino stays sleeping. Tested on both Leonardo and Uno.
Thank you for all the support and tips Gabriel
So many hours troubleshooting, suspecting HW interrupt and this was doing it all
This is odd, the WDT interrupt wasn’t actually been configured or enabled in your sketch.
I suspect that it might be related to the operation on line 143 of Sodaq_wdt.cpp