Attiny85, NRF24L01, and watchdog

I’m pretty stumped by this, hopefully someone can chime in. I have some code for a watchdog wake-up from sleep, and I have code for using an attiny85 with an NRF radio. Each works by itself, but not when I put it together.

What I’m after is to have the attiny wake up periodically, take a reading, transmit that reading, then go back to sleep.

My hunch is that the RF library is using interrupts or a timer which is conflicting with my sleep-code.

Here is my code for the sleep/wake:

#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>

#define LED 0

ISR(WDT_vect) 
  {
  wdt_disable();  
  }

void myWatchdogEnable(const byte interval) 
  {
  wdt_reset();
    
  MCUSR = 0;                          // reset various flags
  WDTCR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCR =  0b01000000 | interval;    // set WDIE, and appropriate delay
  
  ADCSRA &= ~_BV(ADEN);

  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_bod_disable();
  sei();
  sleep_mode();     
  
  
  ADCSRA |= _BV(ADEN);
  
  } 

void setup()
{
pinMode (LED, OUTPUT);
}  

void loop(){

  digitalWrite (LED, HIGH); 
  delay (2000);    
  digitalWrite (LED, LOW);  

  for (int i = 0; i < 8; i++){
  myWatchdogEnable (0b000110);  // 1 second
  }

}  

// sleep bit patterns:
//  1 second:  0b000110
//  2 seconds: 0b000111
//  4 seconds: 0b100000
//  8 seconds: 0b100001

Here is the attiny85 radio transmission code:

#include "RF24.h"

#define CE_PIN 6
#define CSN_PIN 6 //Since we are using 3 pin configuration we will use same pin for both CE and CSN

RF24 radio(CE_PIN, CSN_PIN);

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

void setup() {
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  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.openWritingPipe(address); // Write to device address 'SimpleNode'
}

void loop(void){
  payload++;
  radio.write( &payload, sizeof(unsigned long) ); //Send data to 'Receiver' ever second
  delay(1000);
  }

Each one of those works fine. But here is the combined code that does not work:

#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include "RF24.h"

#define CE_PIN 6
#define CSN_PIN 6

RF24 radio(CE_PIN, CSN_PIN);

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

void setup()
{
  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.openWritingPipe(address); // Write to device address 'SimpleNode'
  pinMode (4, OUTPUT);
}  

void loop(){

  digitalWrite (4, HIGH);

  delay(250);

  payload++;
  radio.write( &payload, sizeof(unsigned long) ); //Send data to 'Receiver' ever second

  delay(250);

  digitalWrite(4, LOW);

  for (int i = 0; i < 8; i++){
  myWatchdogEnable (0b000110);  // 1 second
  }
}  

ISR(WDT_vect) 
  {
  wdt_disable();  
  }

void myWatchdogEnable(const byte interval) 
  {
  noInterrupts();
  wdt_reset();
    
  MCUSR = 0;                          // reset various flags
  WDTCR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCR =  0b01000000 | interval;    // set WDIE, and appropriate delay
  
  //ADCSRA &= ~_BV(ADEN);

  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_bod_disable();
  interrupts();
  sleep_mode();     
  
  
  //ADCSRA |= _BV(ADEN);
  
  } 


// sleep bit patterns:
//  1 second:  0b000110
//  2 seconds: 0b000111
//  4 seconds: 0b100000
//  8 seconds: 0b100001

What RF24 library are you using?

What is the watchdog program supposed to do?

And what is supposed to happen in the combined program?

My wild guess is that something needs to be done to the nRF24 when the Arduino wakes up. For example it does not normally reset when you press the reset button on an Arduino. I have not used one of them with a sleeping Arduino.

...R
Simple nRF24L01+ Tutorial

I’m using the TMRH20 RF24 library, with the 3-wire connection from NerdRalph. It works well, just not with the sleep commands.

I gave a quick summary above of what I’d like to do, but I should add more details.

The watchdog circuit simply turns on an LED, turns it off, goes to sleep for 10 seconds, and repeats.

The final circuit (which runs the combined code) is a PCB with an attiny85 and integrated NRF24L01 radio and moisture sensor. The attiny sleeps and wakes up every 30 minutes, and then turns on a mosfet which powers up the NRF and moisture sensor. It takes an averaged reading from the moisture sensor, then transmits that back to the base node.

I’ve tested the circuit with the attiny powering up the mosfet, and it transmits just fine, but not when the sleep code is included (and nothing else has changed). I attached an image of the schematic for your reference.

silly_cone:
The final circuit (which runs the combined code) is a PCB with an attiny85 and integrated NRF24L01 radio and moisture sensor. The attiny sleeps and wakes up every 30 minutes, and then turns on a mosfet which powers up the NRF and moisture sensor. It takes an averaged reading from the moisture sensor, then transmits that back to the base node.

Powering down the nRF24 sounds like a good idea - so it should restart completely each time.

If this was my project I would write a simple Arduino program that turns the nRf24 off and on without any use of the WDT and get that working before doing anything more complex.

When your Arduino wakes up does it run the code in setup() ?

...R

I'll try switching it on and off without sleeping and make sure that works as expected.

And I'm obviously no expert on sleeping 'duinos, but I'm guessing that no, it does not re-run setup() upon waking.

silly_cone:
, but I'm guessing that no, it does not re-run setup() upon waking.

I don't know either.

But if you switch on your nRF24 you will need to go through the same function calls that you have in setup() to initialize it properly. Perhaps put those few lines of code into a function that you can call from setup() or from anywhere else.

...R

I only had a few minutes to test this, but yes, the radio needs re-initialized after each power cut. Without re-initializing the radio, its just dead-air. But if run the startup commands after switching on the MOSFET, it works just fine.

I'll attempt the sleep-code with this change tomorrow and report back.