Go Down

Topic: ATTINY85 Watchdog INT is not working with INT/PCINT (Read 32 times) previous topic - next topic

lekarsenten

Hello community,

I've spent ~10 hrs and still unable to get my code to workable state and need some help.

Short: I have deep sleep (PWR_DOWN) in my Attiny85 code. The wake trigger is external interrupt or pin change interrupt. When I'm trying to use watchdog for power-efficient time counting, it's not working.
However, it's working when I add delays in function which enables watchdog.

Setup:
  • ATTINY85 at Digispark dev board;
  • running at 1 MHz;
  • pin 3 is connected to shake sensor;
  • pin 2 is connected to button;
  • 2 and 3 is in INPUT_PULLUP, other sides are connected to GND.


Workflow:
  • ShakeSensor producing PC interrupt, setting the flag. If this flag is set, payload inside loop is executed and loop counter will be reset.
  • If flag is not set, watchdog timer is being started for 120 ms. After that loop counter will be incremented.
  • If loop counter exceeds constant, MCU will fall into deep sleep.
  • Button will generate external interrupt which will reset duty cycle.

  • If I'll have delay(60) in WDT setup, it's working.
  • If I'll replace WDT sleep by delay(120), it's working.
  • I left some commented lines with alternatives which I've checked and they didn't work too.

What's wrong with my code?(below)

Code:
Code: [Select]
#include <Arduino.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>

#define led1 0 //1
#define led2 1 //2
#define led3 4 //4
#define shakeSensor 3
#define buttonPin 2

const int brightness = 64;
int count = 50;
int time = 500;
volatile int idlecycles = 0;
volatile bool blockInterrupted = false;
volatile bool interrupted = false;
const int cyclesCuttOff = 50;
int target;

//workers
void roll();
void showSequence(int, int, int);
void blinkNumber(int, int);
void showNumber(int, int);
void fadeNumber(int);

//sleep, wdt, interrupts
void fallasleep();
void letTheDogOut();

void setup()
{
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(shakeSensor, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(5, INPUT);
  cli();
  GIMSK = _BV(INT0) | _BV(PCIE); //INT0, PCINT0
  PCMSK = _BV(PCINT3);
  sei(); 
  ADCSRA &= ~(1 << ADEN);
  power_adc_disable();
  blinkNumber(5, 250);//ready
}

bool getInterrupted()
{
  return interrupted && !blockInterrupted;
}

void fallasleep()
{
 
  blinkNumber(6, 250); //show that we're going to sleep
  cli();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Turn off ADC
  ADCSRA = 0;

  // diable all modules availables
  power_all_disable(); // power off ADC, Timer 0 and 1, serial interface

  //configure interrupts

  GIMSK = _BV(INT0); //external only
  sleep_enable();
  sei();
  sleep_cpu();

  sleep_disable();

  power_all_enable(); // power everything back on
  cli();
  GIMSK |= _BV(PCIE); //both
  sei();
  blinkNumber(1, 250); //exiting sleep
}

void letTheDogOut()
{
  //delay(60); //Suddenly working OK with delays
  //blinkNumber(3, 50);
  /*cli();
  MCUSR = 0;
  WDTCR = _BV(WDCE) | _BV(WDE) | bit(WDIF); //enable editing, disable reset, clean old int flag (?!)
  WDTCR = _BV(WDIE) | _BV(WDP1) | (WDP0); //run dog for ~125ms*/
 
  wdt_reset();
  wdt_enable(WDTO_120MS);
  WDTCR |= _BV(WDIE);
 

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sei();
  sleep_cpu();

  sleep_disable();
  //delay(60);  //Suddenly working OK with delays
  //blinkNumber(4, 50);
}

//interrupt handlers

ISR(PCINT0_vect)
{
  interrupted = true;
}

ISR(INT0_vect)
{
}

ISR(WDT_vect)
{
  wdt_disable();
  idlecycles++;
}

//main loop
void loop()
{
  if (interrupted || digitalRead(shakeSensor) == 0) //pulled down by shaking
  {
    interrupted = false;//clear flag
    idlecycles = 0;//reset idle counter
    roll();
    fadeNumber(target);
  }
  //delay(120);idlecycles++ //working with delay instead of watchdog
  letTheDogOut();//handler will increment cycles count
  if (idlecycles >= cyclesCuttOff)//going into deep sleep
  {
    blockInterrupted = true;
    fallasleep();
    interrupted = false;
    //delay(500);
    fadeNumber(target); //showing last number after pressing the button
    idlecycles = 0;
    blockInterrupted = false;
  }
}

//LED routines below
....

Go Up