I am working on a ultra-low power project using an ATMEGA328P, a nRF24L01 and a 0.47F super-capacitor to measure various sensors akin to Gammon's solar power project. I have been having problems with keeping the current consumption of the nRF24L01 low which appears to be a common problem as noted here. I only have been able to get the current down during sleep to 950uA as opposed to 7uA. Power for the nRF24L01 comes from an AMS1117 that is switched on and off from a digital pin. Thus, during sleep the nRF24L01 isn't drawing power directly so the current must be coming from the SPI. According to Gammon's code, after the radio message is sent he sets the SPI pins as OUTPUT and LOW following SPI.end(), like so:
bool ok = radio.write (&reading, sizeof reading);
radio.startListening ();
radio.powerDown ();
SPI.end ();
// set pins to OUTPUT and LOW
for (byte i = 9; i <= 13; i++)
{
pinMode (i, OUTPUT);
digitalWrite (i, LOW);
} // end of for loop
Since the current consumption is coming from the SPI, I decided to reverse this by setting the SPI pins to INPUT assuming that SPI.begin() would automatically set them back appropriately. At this point current during sleep was the expected 7uA but no messages were being sent. I checked around and found that there was a problem where SPI.end() causes SPI.transfer() to hang even after a new SPI.begin(). Unfortunately the solution there didn't work in my case.
I tried to change the pins to OUTPUT when coming out of sleep but that obviously didn't work. One of the posts pointed out that the pins shouldn't be configured as output before calling SPI.begin() because SPIClass::begin() does not have code in it to do so, and that this is probably done so for a reason. Indeed, in Gammon's code, where he sets all pins to OUTPUT and LOW during setup in order to minimize current consumption, he skips the SPI pins:
// set pins to OUTPUT and LOW
for (byte i = 0; i <= A5; i++)
{
// skip radio pins
if (i >= 9 && i <= 13)
continue;
pinMode (i, OUTPUT);
digitalWrite (i, LOW);
} // end of for loop
What I don't understand is why is it possible to set the SPI pins as OUTPUT after SPI.end() and not do the same after coming out of sleep and just before SPI.begin()? Also, why is it that if I tristate the pins after SPI.end() the SPI bus doesn't appear to work, that is, SPI.begin() appears to hang?