1

The core I use is this one
The chip I use is an ATtiny85
I run this using the Arduino IDE 1.8.2
RadioHead ASK library (slimmed down)

What I want to do is:

  • deep sleep
  • wake up every minute
  • turn on sensor
  • take measurement
  • transmit data
  • back to sleep

This works when I test it seperatly, where it goes awry is when I combine RadioHead with WDT and then try to use a delay. This always hangs.

Probably a timer issue, I am looking for a work around. I need the delay because I need to start the sensor, wait .5 sec and then take a measurement. Maybe I should give the ATtiny85 just some job to keep it busy for 0.5 sec?

This is working code, when I uncomment // driver.init(); it will fail.

// RadioHead ASK
#include <RH_ASK.h>

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

#ifndef cbi
  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Absolute reference PB to overcome inter-IDE issues
#define T_PIN 1 // transmission
#define L_PIN 3 // optional LED pin
#define S1 A2
#define S2 A1
#define BAUD 2000

// Baud rate, receiver, transmitter
RH_ASK driver(BAUD, 9, T_PIN); // pin 9 is non existent

// Watchdog
volatile boolean f_wdt = 1;

ISR(WDT_vect) {
  f_wdt=1;
}

// Sleep
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// Setup for Watchdog
void setup_watchdog(int ii) {
  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}

void setup() {
//  driver.init();
  setup_watchdog(8);
}

void loop()
{
  if (f_wdt==1) { 
    pinMode(0, OUTPUT);
    digitalWrite(0, HIGH);
    delay(500);
    digitalWrite(0, LOW);
    delay(500);
    system_sleep();
  }
}
  • 1
    The instruction bb|= (1<<WDCE) looks wrong: in the timed sequence, you are always writing this bit to one. The datasheet says (emphasis mine): “2. Within the next four clock cycles, in the same operation, write the WDE and WDP bits as desired, but with the WDCE bit cleared”. I would do something like cli(); WDTCR = _BV(WDCE) | _BV(WDE); WDTCR = _BV(WDIE) | _BV(WDP3); sei();. – Edgar Bonet Apr 27 '17 at 10:08
  • I do not understand this part of the code well enough to understand your suggestion. I need to read up on it. – Thijs Apr 27 '17 at 11:04
2

The RH_ASK library uses timer0, which is also used for millis and delay.

Quick workaround is to use the standard AVR delay instead.

#include <util/delay.h>

...

_delay_ms(500)
  • This point needs to be made in big bold red letters in the RadioHead documentation. Many hours were spent {wasted?} trying to debug the issue. +1 – bobthechemist Oct 9 '18 at 12:15

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.