Skip to content

Commit

Permalink
IRQ based battery measurement during active time
Browse files Browse the repository at this point in the history
  • Loading branch information
pa-pa committed Nov 23, 2019
1 parent c7544df commit 0277421
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 7 deletions.
10 changes: 6 additions & 4 deletions Activity.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ class Sleep : public Idle<ENABLETIMER2> {
uint32_t ticks = sysclock.next();
if( sysclock.isready() == false ) {
if( ticks == 0 || ticks > millis2ticks(15) ) {
hal.radio.setIdle();
hal.setIdle();
uint32_t offset = doSleep(ticks);
hal.unsetIdle();
sysclock.correct(offset);
sysclock.enable();
}
Expand Down Expand Up @@ -123,8 +124,9 @@ class SleepRTC : public Idle<true> {
uint32_t ticks = sysclock.next();
if( sysclock.isready() == false ) {
if( ticks == 0 || ticks > millis2ticks(15) ) {
hal.radio.setIdle();
hal.setIdle();
uint32_t offset = doSleep(ticks);
hal.unsetIdle();
sysclock.correct(offset);
sysclock.enable();
}
Expand Down Expand Up @@ -182,13 +184,13 @@ class Activity : public Alarm {
}
else {
// ensure radio is up and running
hal.radio.wakeup();
hal.wakeup();
}
}

template <class Hal>
void sleepForever (Hal& hal) {
hal.radio.setIdle();
hal.setIdle();
while( true ) {
#if defined(ARDUINO_ARCH_AVR) && ! (defined(ARDUINO_AVR_ATmega32) || defined(__AVR_ATmega644__))
LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF);
Expand Down
15 changes: 15 additions & 0 deletions AskSinPP.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,27 @@ class AskSin : public AskSinBase {
radio.waitTimeout(millis);
}

void setIdle () {
radio.setIdle();
battery.setIdle();
}

void unsetIdle () {
battery.unsetIdle();
}

void wakeup () {
radio.wakeup();
}

#ifdef ARDUINO_ARCH_AVR
template <bool ENABLETIMER2=false, bool ENABLEADC=false>
void idle () { activity.savePower< Idle<ENABLETIMER2,ENABLEADC> >(*this); }

template <bool ENABLETIMER2=false>
void sleep () { activity.savePower< Sleep<ENABLETIMER2> >(*this); }

void sleepForever () { activity.sleepForever(*this); }
#endif
};

Expand Down
61 changes: 61 additions & 0 deletions BatterySensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ class BattSensor : public Alarm {
uint8_t voltage() { return current(); }

METER& meter () { return m_Meter; }

void setIdle () {}
void unsetIdle () {}
};

typedef BattSensor<SyncMeter<InternalVCC> > BatterySensor;
Expand Down Expand Up @@ -267,6 +270,64 @@ class BatterySensorExt : public BatterySensor {

};

extern volatile uint16_t __gb_BatCurrent;
extern void (*__gb_BatIrq)();

class IrqInternalBatt {
uint8_t m_Low, m_Critical;
public:
IrqInternalBatt () : m_Low(0), m_Critical(0) {}
~IrqInternalBatt() {}

uint8_t current () const { return (__gb_BatCurrent + 50) / 100; }
bool critical () const { return current() < m_Critical; }
void critical (uint8_t value ) { m_Critical = value; }
bool low () const { return current() < m_Low; }
void low (uint8_t value ) { m_Low = value; }

void init(__attribute__((unused)) uint32_t period,__attribute__((unused)) AlarmClock& clock) {
unsetIdle();
}

// for backward compatibility
uint16_t voltageHighRes() { return __gb_BatCurrent; }
uint8_t voltage() { return current(); }

void setIdle () {
__gb_BatIrq = 0;
}

void unsetIdle () {
__gb_BatIrq = irq;
ADMUX &= ~(ADMUX_REFMASK | ADMUX_ADCMASK);
ADMUX |= ADMUX_REF_AVCC; // select AVCC as reference
ADMUX |= ADMUX_ADC_VBG; // measure bandgap reference voltage
ADCSRA |= (1 << ADIE); // enable interrupt
ADCSRA |= (1 << ADSC); // start conversion
}

static void irq () {
uint16_t v = 1100UL * 1024 / ADC;
if( __gb_BatCurrent == 0 ) {
__gb_BatCurrent = v;
}
else {
v = (__gb_BatCurrent + v) / 2;
if( v < __gb_BatCurrent ) {
__gb_BatCurrent = v;
}
}
ADCSRA |= (1 << ADSC); // start conversion
}
};


ISR(ADC_vect) {
if( __gb_BatIrq != 0 ) {
__gb_BatIrq();
}
}

}

#endif
4 changes: 4 additions & 0 deletions Globals.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

#include <Arduino.h>

namespace as {

Expand All @@ -7,4 +8,7 @@ void* __gb_radio;

const char* __gb_chartable = "0123456789ABCDEF";

uint16_t __gb_BatCurrent = 0;
void (*__gb_BatIrq)() = 0;

}
13 changes: 10 additions & 3 deletions examples/HM-SEC-RHS/HM-SEC-RHS.ino
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

// define this to read the device id, serial and device type from bootloader section
// #define USE_OTA_BOOTLOADER
// #define BATTERY_IRQ

#define CFG_STEPUP_BYTE 0x00
#define CFG_STEPUP_OFF 0x00
Expand Down Expand Up @@ -96,7 +97,11 @@ public:
}
};

typedef BattSensor<AsyncMeter<SwitchSensor> > BatSensor;
#ifdef BATTERY_IRQ
typedef IrqInternalBatt BatSensor;
#else
typedef BattSensor<AsyncMeter<SwitchSensor> > BatSensor;
#endif

/**
* Configure the used hardware
Expand Down Expand Up @@ -190,8 +195,10 @@ public:
// set battery low/critical values
battery().low(getConfigByte(CFG_BAT_LOW_BYTE));
battery().critical(getConfigByte(CFG_BAT_CRITICAL_BYTE));
#ifndef BATTERY_IRQ
// set the battery mode
battery().meter().sensor().mode(getConfigByte(CFG_STEPUP_BYTE));
#endif
}
};

Expand Down Expand Up @@ -219,10 +226,10 @@ void loop() {
// if we drop below critical battery level - switch off all and sleep forever
if( hal.battery.critical() ) {
// this call will never return
hal.activity.sleepForever(hal);
hal.sleepForever();
}
// if nothing to do - go sleep
hal.activity.savePower<Sleep<> >(hal);
hal.sleep<>();
}
}

0 comments on commit 0277421

Please sign in to comment.