1

I have an ATtiny85 and an Arduino Uno both using NRF24L01 chips to communicate with one another. The ATtiny85 is powered by a CR2032 coin cell. I am using tmrh20's fork of the RF24 library which can be found here. Here's the problem I'm encountering:

Under the current code posted, the Uno will receive about 80 packets of data (80 packets times 2 seconds per packet is about 160 seconds of time) before the ATtiny will simply stop sending, and the Uno receives no more data. I can tell that it's the ATtiny, because I've got a DMM hooked up to it. Normally, my DMM tells me that the ATtiny is drawing less than 0.005mA of current, but at the instance of the stall the DMM reads approximately 1.4 mA of current draw, which makes sense because under normal conditions with no sleep the ATtiny draws about 1mA, and the radio not in power down mode and not transmitting draws 0.4mA.

I've spent quite some time trying everything from setting the clock speed to a different value (it's at 1MHz) to changing the power amplifier value. The only thing I've tried that makes an impact is getting rid of the powerUp and powerDown function calls. Once these are removed everything works perfectly transmission-wise, except the only issue is that the whole system is drawing 0.4mA constantly, which is too much.

I don't think the coin cell is a problem considering the system works when the powerUp and powerDown calls are removed. Here's my code:

Reciever:

#define CE_PIN 7
#define CSN_PIN 8

#include <SPI.h>
#include "RF24.h"

RF24 radio(CE_PIN, CSN_PIN);

byte address[11] = "SimpleNode";
unsigned long payload = 0;

void setup() {
  while (!Serial);
  Serial.begin(115200);
  radio.begin(); // Start up the radio
  radio.setAutoAck(1); // Ensure autoACK is enabled
  radio.setRetries(15,15); // Max delay between retries & number of retries
  radio.openReadingPipe(1, address); // Write to device address 'SimpleNode'
  radio.startListening();
  Serial.println("Did Setup");

}

long counter = 0;

void loop(void){
  if (radio.available()) {

    radio.read( &payload, sizeof(unsigned long) );
    if(payload != 0){
        Serial.print("Got Payload ");
        Serial.print(payload);
        Serial.print(" - ");
        Serial.println(counter);
        counter++;
    }
  }

}

Transmitter:

//Sleep
#include <avr/sleep.h>

const int sleepSecs = 2;

//Radio
#define CE_PIN 3
#define CSN_PIN 3 //Since we are using 3 pin configuration we will use same pin for both CE and CSN
#include "RF24.h"
RF24 radio(CE_PIN, CSN_PIN);
byte address[11] = "SimpleNode";
unsigned long payload = 0;

void setup() {
  //Setup radio
  radio.begin(); // Start up the radio
  radio.setAutoAck(1); // Ensure autoACK is enabled
  radio.setRetries(15,15); // Max delay between retries & number of retries
  //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
  radio.setPALevel(RF24_PA_HIGH);
  radio.openWritingPipe(address); // Write to device address 'SimpleNode'

  //Setup sleep
  setup_watchdog(6);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT
  sleep_enable();
}

volatile int watchdog_counter = 0;

ISR(WDT_vect) {
  watchdog_counter++;
}

void loop() {
  sleep_mode(); //Go to sleep!

  if(watchdog_counter >= sleepSecs)
  {
    ADCSRA |= (1<<ADEN);
    radio.powerUp();
    watchdog_counter = 0;

    payload = 123456;
    radio.write(&payload, sizeof(unsigned long) ); //Send data to 'Receiver' every second  

    radio.powerDown();
    ADCSRA &= ~(1<<ADEN); //Disable ADC, saves ~230uA
  }
}

//Sets the watchdog timer to wake us up, but not reset
//0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
//6=1sec, 7=2sec, 8=4sec, 9=8sec
//From: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void setup_watchdog(int timerPrescaler) {

  if (timerPrescaler > 9 ) timerPrescaler = 9; //Limit incoming amount to legal settings

  byte bb = timerPrescaler & 7; 
  if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary

  //This order of commands is important and cannot be combined
  MCUSR &= ~(1<<WDRF); //Clear the watch dog reset
  WDTCR |= (1<<WDCE) | (1<<WDE); //Set WD_change enable, set WD enable
  WDTCR = bb; //Set new watchdog timeout value
  WDTCR |= _BV(WDIE); //Set the interrupt enable, this will keep unit from resetting after each int
}
1

After looking at the RF24 header file, I suggest you call radio.stopListening() right before you call write(). Also add a delay of 5 ms after write(). It would be nice to know the exact point at which the program got stuck; add digitalWrite(13, HIGH) inside the IF block, after powerDown() and again outside the block, immediately after sleep_mode(), but with a LOW argument instead, so you can know if the problem is that the AVR stops waking up at some point or if its the radio methods that is blocking, for some reason.

  • 1
    an additional 5 ms after powerup? – Gerben Jan 16 '16 at 13:23
  • Yeah...the header file says it should be included for maximum compatibility. – TisteAndii Jan 16 '16 at 13:30
  • Oops...just checked your link...i didnt look at the source before...i guess i should change that – TisteAndii Jan 16 '16 at 13:32
  • One more thing: do I need to call startListening again after writing and delaying? – Alex Wulff Jan 16 '16 at 13:33
  • No...theres no need to listen at all since you are only transmitting... – TisteAndii Jan 16 '16 at 13:35
0

A delay after the powerUp() made the program work for longer, but it still stalled. More delays after write() only exacerbated the issue. The only thing that I've done to get this to work is to put the sending code in the watchdog ISR itself. However, this is limited to only around 4 seconds max per sent packet because this is the watchdog's max value, but that's OK for my application.

This leads me to believe that somehow the watchdog is interfering with sending, so possibly disabling it and reenabling after sending could have some effect if anyone else is having this problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.