Saturday, September 12, 2020

0000 0000 0100 0000

ATTiny13 looks after big brother ATTiny85

For a couple of years now I've been thinking about watchdogs - circuits or microcontrollers that watch/report on the circuit itself. For instance, some time ago I had an ESP8266 in my hothouse reporting temperature, humidity and atmospheric pressure every few minutes.

When the battery ran low, I lost data. So I have been looking at the possibility of enlisting an ATTiny13 (of course) to monitor the voltage in a circuit and then act at some minimum voltage threshold to, for instance, preserve data.

Coupled with that, I have been looking into EEProm storage on the ATTinys - so it seems that there may be an opportunity to combine the two as a "proof of concept". An ATTiny13 monitoring the overall voltage of the circuit, and an ATTiny85 storing data and perhaps shutting down when signalled by the "watchdog".


The code for the ATTiny85 is below. It just counts, and then when interrupted by the ATTiny13 it will display a "low battery" message, write the data to the EEProm and then shut down until the voltage/microcontroller is reset.

// ATTiny85 counts and if interrupted saves the count and then sleeps
// OneCircuit Thursday 10 September  19:18:08 AEST 2020

#include <EEPROM.h>
#include <avr/sleep.h>
#include <TM1637Display.h>

// pins to talk to the TM1637 display
#define CLK 2
#define DIO 1

int thisnumber = 0;             // counter
int address = 0;                // eeprom address
volatile bool LValarm = false;  // has the voltage dropped? Set "no"

// to make the word Low Battery in TM1637 speak
const uint8_t Lo_b[] = {
  SEG_F | SEG_E | SEG_D,                     // L
  SEG_G | SEG_E | SEG_D | SEG_C,             // o
  SEG_D,                                     // _
  SEG_F | SEG_G | SEG_E | SEG_C | SEG_D      // b
};


TM1637Display display(CLK, DIO);

void writetheeeprom() {
  EEPROM.put(address, thisnumber);
}

// Interrupt arrived from the ATTiny13!
ISR(PCINT0_vect) {
  LValarm = true;
}

void setup() {
  display.setBrightness(0x02);
  EEPROM.get(address, thisnumber);
  pinMode(PB3, INPUT);
  ADCSRA &= ~(1 << ADEN); // disable ADC (before power-off)
  GIMSK = 0b00100000;     // turns on pin change interrupts
  PCMSK = 0b00001000;     // turn on interrupts on pins PB3
  sei();                  // enables interrupts
}

void loop() {

  // routine while voltage is OK
  while (!LValarm) {
    thisnumber++;
    if (thisnumber > 9999) {
      thisnumber = 0;
    }
    display.showNumberDec(thisnumber, false);
    delay(75);
  }

  // shutdown routine
  writetheeeprom();
  display.setSegments(Lo_b);
  delay(10000);
  display.clear();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_cpu(); // wake upon reset
}


The code for the ATTiny13 is below. It monitors the voltage, giving a visual clue (Green LED) if the voltage is above the threshold, and another (Red LED) if the voltage falls below.

// ATTiny13 monitors PB3 and sends a pulse out if voltage drops
// OneCircuit Thursday 10 September  19:18:08 AEST 2020

int vcc = 0;
bool trigger85 = false;
int volt_threshold = 850;
bool debug = false;

void setup() {

  pinMode(PB1, OUTPUT);
  pinMode(PB2, OUTPUT);
  pinMode(PB4, INPUT_PULLUP);
  pinMode(PB3, INPUT_PULLUP);
  analogReference(INTERNAL);   // use internal 1.1V as reference
  delay(1000);   // settle time
}

void loop() {

  vcc = analogRead(PB3);

  // if voltage is OK and we haven't triggered, display green
  while (vcc > volt_threshold && !trigger85) {
    vcc = analogRead(PB3);
    digitalWrite(PB2, HIGH);
    delay(50);
    digitalWrite(PB2, LOW);
    delay(2000);
  }

  // send the pulse
  if (!trigger85) {
    pinMode(PB4, OUTPUT);
    digitalWrite(PB4, HIGH);
    delay(100);
    digitalWrite(PB4, LOW);
    delay(10);
    trigger85 = true;
  }
  // red lights
  digitalWrite(PB1, HIGH);
  delay(50);
  digitalWrite(PB1, LOW);
  delay(2000);
  
}

It works great and you can see the result in the video below.






No comments:

Post a Comment