Category Archives: Arduino

ATTINY85 – INTERRUPTS AND WDT CODE

I use that code as a basis for all my sensor sketch developments with a Attiny85 chip.
It might be useful for some geeks out there.

Attiny85

Attiny85

Actually, this page is a kind of reminder and a startup for all my new projects.
It’s based on the use of watch dog timers and interrupts which is a very easy way to code sensors (temperature, humidity, shock, etc) and very efficient for not wasting to much power for the circuit. A Attiny85 should draw only a few micro amps(µA) while sleeping.

//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+

#include 
#include 
#include  


#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// https://www.arduino.cc/en/Reference/Volatile
// volatile keyword:
// Specifically, it directs the compiler to load the variable from RAM and not from a storage register,
// which is a temporary memory location where program variables are stored and manipulated. 
// Under certain conditions, the value for a variable stored in registers can be inaccurate.

volatile boolean f_wdt = 1;

// Use pin PB0 as wake up pin
const int wakeUpPin = 0;

const byte pinLed = 4;
const byte pinLedRed = 3;
  
void blink(int ii) {
  pinMode(pinLed, OUTPUT);
  for (byte i = ii ;  i > 0 ; i--){
     digitalWrite(pinLed, HIGH);
     delay(50);
     digitalWrite(pinLed, LOW); 
     delay(50);
  }
  
  pinMode(pinLed, INPUT); // reduce power
}

void blinkRed(int ii) {
  pinMode(pinLedRed, OUTPUT);
  for (byte i = ii ;  i > 0 ; i--){
     digitalWrite(pinLedRed, HIGH);
     delay(50);
     digitalWrite(pinLedRed, LOW); 
     delay(50);
  }
  pinMode(pinLedRed, INPUT); // reduce power
}

/******************************************************************/
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
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="" }="" void="" system_sleep()="" {="" cbi(adcsra,aden);="" switch="" analog="" to="" digitalconverter="" off="" set_sleep_mode(sleep_mode_pwr_down);="" sleep="" mode="" is="" here="" sleep_enable();="" sleep_mode();="" system="" sleeps="" here,="" waiting="" for="" interrupt="" sleep_disable();="" continues="" execution="" when="" out="" sbi(adcsra,aden);="" on="" service="" executed="" isr(wdt_vect)="" f_wdt="1;" global="" flag="" setup()="" setup_watchdog(9);="" pinmode(wakeuppin,="" input);="" the="" pin="" input="" digitalwrite(wakeuppin,="" high);="" activate="" internal="" pullup="" resistor="" pcmsk="" (pcint0);="" change="" mask="" register="" gifr="" (pcif);="" clear="" any="" outstanding="" interrupts="" general="" gimsk="" (pcie);="" enable="" sei();="" isr="" (pcint0_vect){}="" loop()="" system_sleep();="" if="" (=""> 0) {  // watchdog signal
    blink(5);
    f_wdt=0;         //reset flag
  } else {
    blinkRed(5);     // PCINT0 occured
  }
    
}
</wdce);>

Low battery detection code

Nick Gammon http://www.gammon.com.au/power

uint16_t readVcc(void) {
  uint16_t result;
  // Read 1.1V reference against Vcc
  ADMUX = (0<<REFS0) | (12<<MUX0);
  delay(2); // Wait for Vref to settle
  ADCSRA |= (1<<ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCW;
  return 1018500L / result; // Back-calculate AVcc in mV
}