Running Arduino+NRF24l01 w/ interrupt consuming 1.5uA in sleep
I am using this Arduino Nano Pro 8mhz 3.3v :link text
I am using this NRF chip: link text
Here is my test environment:
- Arduino Nano with desoldered jumper for bypassing voltage regulation (If you dont have bypass jumper on the knock off Nano, look at this post: link text )
- NRF connected via pinout on MySensors guide
- 3V direct supply from 2 AA Batteries
- uCurrent Gold testing voltage current
- Fluke 179 reading in mV
- Using the BinarySwitchSensor sketch in the MySensors library
If I upload the sketch as is with the recommended setup guide, Pin 2 or 3 is an interrupt pin and that goes to GND and acts as a switch. Pin 2/3 is HIGH and uses the internal pull up resistor. We will refer to the 2 different states of the switch as follows:
"oState" (Open, when Pin 2/3 does NOT touch GND)
"cState" (Closed, when Pin 2/3 touches GND)
When running everything I get these sleep numbers:
oState: 23-24uA
cState: 117uA
I downgraded my Arduino IDE from 1.6.5 to 1.0.6 and here are my new numbers:
oState: 2.5-2.7uA
cState: 98-100uA
Everything is looking good but my cState is still too high for any battery applications that I am trying to get.
Removed digitalWrite on pin 2/3. Connected 10M resistor from pin 2 to VCC. GND is switch to pin 2.
oState: 2.5-2.7uA
cState: 3.1-3.2uA
Reference measurements:
At this point I ran the "DallasTemperatureSensor" to test current using the WDT, I did NOT connect Temp sensor
Sleep current with WDT enabled @ 30 seconds: 7.6-7.8uA
Using "BinarySwitchSensor", remove NRF completely and only have Arduino:
Sleep current: 110-120nA OR .4-.5uA (had issues reading this but I believe it is the nA)
Connecting VCC/GND only to NRF to read standalone current:
NRF only: 800-900nA Shutdown current
Useless numbers while running the BinarySwitchSleepSensor sketch:
Sleep current: 2.7-2.9uA with NRF/Arduino fully connected
Sleep current with nRF GND disconnected: 1.7uA
Sleep current with nRF VCC and GND disconnected: 294nA
Sleep current with nRF VCC/GND/Pin9 disconnected: 281nA
Sleep current with nRF VCC/GND/P9/P10 disconnected: 196nA
Sleep current with nRF VCC/GND/P9/P10/P11/P12/P13 disconnected: 110-112nA
Sleep mode with ONLY Arduino: 110-112nA
NRF plugged into VCC/GND only: 800-900nA
At this point we are getting 2.7-2.9uA with Arduino/NRF. Stock MySensors library and Arduino 1.0.6 IDE. ( I am using the BinarySwitchSleep Sketch from MySensors lib)
To get even lower power....
Open up mysensors.cpp with NotePad++ application
Look for this code:
bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
// Let serial prints finish (debug, log etc)
bool pinTriggeredWakeup = true;
Serial.flush();
RF24::powerDown();
attachInterrupt(interrupt, wakeUp, mode);
if (ms>0) {
pinIntTrigger = 0;
sleep(ms);
if (0 == pinIntTrigger) {
pinTriggeredWakeup = false;
}
} else {
Serial.flush();
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}
detachInterrupt(interrupt);
return pinTriggeredWakeup;
}
We are going to add this code:
SPI.end();
for (byte i = 9; i <= 13; i++)
{
pinMode (i, OUTPUT);
digitalWrite (i, LOW);
} // end of for loop
The final code should look like this:
bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
// Let serial prints finish (debug, log etc)
bool pinTriggeredWakeup = true;
Serial.flush();
RF24::powerDown();
attachInterrupt(interrupt, wakeUp, mode);
SPI.end();
for (byte i = 9; i <= 13; i++)
{
pinMode (i, OUTPUT);
digitalWrite (i, LOW);
} // end of for loop
if (ms>0) {
pinIntTrigger = 0;
sleep(ms);
if (0 == pinIntTrigger) {
pinTriggeredWakeup = false;
}
} else {
Serial.flush();
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}
detachInterrupt(interrupt);
return pinTriggeredWakeup;
}
IMPORTANT: Because you are ending SPI, you will need to call the sensor at the beginning of your loop to reinitialize the NRF
void loop()
{
sensor_node.begin();
Adding both SPI.end(); and for(); loop:
Sleep current: 1.5uA
If you add just the SPI.end();
Sleep current: 2uA
If you just add the for(); loop:
Sleep current: 1.9uA - 2.2uA
- If you are using ONLY the "for(); loop", you do NOT need to reinitialize the radio when you come out of sleep. I have noticed a much longer up time when having to reinitialize.
OTHER MEASUREMENTS using the DallasTemperatureSensor with WDT at 30 seconds, no sensor connected:
Edited Sleep with for(); loop:
Sleep current: 6.4-6.5uA
Edited Sleep with for(); loop AND SPI.end();:
Sleep current: (Could not get SPI.end(); to work on sleep(w/WDT))
Quick comment: There are a few sleep options in the MySensors.cpp Depending on which one you are calling will depend on which one you need to edit. Here are some examples of the sleep functions in the .cpp file:
void MySensor::sleep(unsigned long ms)
bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
int8_t MySensor::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms)