6 #ifndef __BATTERYSENSOR_H__
7 #define __BATTERYSENSOR_H__
10 #include <AlarmClock.h>
12 #ifdef ARDUINO_ARCH_AVR
14 #ifndef __AVR_ATmega128__
15 #include <avr/power.h>
18 #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
19 #define ADMUX_VCCWRT1V1 (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1))
20 #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
21 #define ADMUX_VCCWRT1V1 (_BV(MUX5) | _BV(MUX0))
22 #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
23 #define ADMUX_VCCWRT1V1 (_BV(MUX3) | _BV(MUX2))
25 #define ADMUX_VCCWRT1V1 (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1))
44 void critical (__attribute__((unused)) uint8_t value ) {}
46 bool low ()
const {
return false; }
48 void low (__attribute__((unused)) uint8_t value ) {}
57 #ifdef ARDUINO_ARCH_AVR
59 #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
60 #define ADMUX_ADCMASK ((1 << MUX4)|(1 << MUX3)|(1 << MUX2)|(1 << MUX1)|(1 << MUX0))
62 #define ADMUX_ADCMASK ((1 << MUX3)|(1 << MUX2)|(1 << MUX1)|(1 << MUX0))
64 #define ADMUX_REFMASK ((1 << REFS1)|(1 << REFS0))
66 #define ADMUX_REF_AREF ((0 << REFS1)|(0 << REFS0))
67 #define ADMUX_REF_AVCC ((0 << REFS1)|(1 << REFS0))
68 #define ADMUX_REF_RESV ((1 << REFS1)|(0 << REFS0))
69 #define ADMUX_REF_VBG ((1 << REFS1)|(1 << REFS0))
71 #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
72 #define ADMUX_ADC_VBG ((1 << MUX4)|(1 << MUX3)|(1 << MUX2)|(1 << MUX1)|(0 << MUX0))
74 #define ADMUX_ADC_VBG ((1 << MUX3)|(1 << MUX2)|(1 << MUX1)|(0 << MUX0))
82 typedef uint16_t ValueType;
83 static const int DefaultDelay = 0;
86 #ifdef ARDUINO_ARCH_STM32F1
87 adc_reg_map *regs = ADC1->regs;
88 regs->CR2 |= ADC_CR2_TSVREFE;
89 regs->SMPR1 = ADC_SMPR1_SMP17;
97 #ifdef ARDUINO_ARCH_AVR
100 ADMUX &= ~(ADMUX_REFMASK | ADMUX_ADCMASK);
101 ADMUX |= ADMUX_REF_AVCC;
102 ADMUX |= ADMUX_ADC_VBG;
104 ADCSRA |= (1 << ADSC);
105 while (ADCSRA & (1 << ADSC)) ;
106 vcc = 1100UL * 1024 / ADC;
107 #elif defined ARDUINO_ARCH_STM32F1
108 vcc = 1200 * 4096 / adc_read(ADC1, 17);
110 DPRINT(F(
"iVcc: ")); DDECLN(vcc);
115 template<u
int8_t SENSPIN, u
int8_t ACTIVATIONPIN, u
int8_t ACTIVATIONSTATE=LOW, u
int16_t VCC=3300, u
int8_t FACTOR=57>
118 static const int DefaultDelay = 250;
121 pinMode(SENSPIN, INPUT);
122 pinMode(ACTIVATIONPIN, INPUT);
126 pinMode(ACTIVATIONPIN, OUTPUT);
127 digitalWrite(ACTIVATIONPIN, ACTIVATIONSTATE==LOW ? LOW : HIGH);
128 digitalWrite(SENSPIN,LOW);
133 uint32_t value = analogRead(SENSPIN);
134 digitalWrite(SENSPIN,HIGH);
135 digitalWrite(ACTIVATIONPIN, ACTIVATIONSTATE==LOW ? HIGH : LOW);
136 pinMode(ACTIVATIONPIN,INPUT);
138 uint16_t refvcc = VCC;
140 InternalVCC::start();
141 refvcc = InternalVCC::finish();
143 uint16_t vin = (value * refvcc * FACTOR) / 1024 / 10;
145 DPRINT(F(
"eVcc: ")); DDECLN(vin);
151 template <
class SENSOR,
int DELAY=SENSOR::DefaultDelay>
154 volatile typename SENSOR::ValueType m_Value;
158 void resetCurrent() { m_Value = 0; }
165 typename SENSOR::ValueType tmp = sensor().finish();
166 if( m_Value == 0 || tmp < m_Value ) {
170 typename SENSOR::ValueType value ()
const {
return m_Value; }
171 SENSOR& sensor () {
return m_Sensor; }
172 typename SENSOR::ValueType measure () {
178 template <
class SENSOR,
int DELAY=SENSOR::DefaultDelay>
181 volatile typename SENSOR::ValueType m_Value;
185 virtual void trigger (__attribute__((unused))
AlarmClock& clock) {
186 typename SENSOR::ValueType tmp = sensor().finish();
187 if( m_Value == 0 || tmp < m_Value ) {
192 void resetCurrent() { m_Value = 0; }
196 set(millis2ticks(DELAY));
199 typename SENSOR::ValueType value ()
const {
return m_Value; }
200 SENSOR& sensor () {
return m_Sensor; }
201 typename SENSOR::ValueType measure () {
204 m_Value = sensor().finish();
209 template <
class METER>
212 uint8_t m_Low, m_Critical;
224 uint8_t current ()
const {
return (m_Meter.value() + 50) / 100; }
225 bool critical ()
const {
return current() < m_Critical; }
226 void critical (uint8_t value ) { m_Critical = value; }
227 bool low ()
const {
return current() < m_Low; }
228 void low (uint8_t value ) { m_Low = value; }
229 void resetCurrent() { m_Meter.resetCurrent(); }
231 void init(uint32_t period,
AlarmClock& clock) {
232 m_Meter.sensor().init();
239 uint16_t voltageHighRes() {
return m_Meter.value(); }
240 uint8_t voltage() {
return current(); }
242 METER& meter () {
return m_Meter; }
250 template <u
int8_t SENSPIN,u
int8_t ACTIVATIONPIN,u
int16_t VCC=3300>
262 template <u
int8_t SENSPIN,u
int8_t ACTIVATIONPIN,u
int16_t VCC=3300>
265 uint8_t m_ActivationPin;
266 uint8_t m_DividerRatio;
267 uint16_t m_RefVoltage;
271 m_SensePin(SENSPIN), m_ActivationPin(ACTIVATIONPIN), m_DividerRatio(2), m_RefVoltage(VCC) {}
274 void init(uint32_t period,
AlarmClock& clock,uint16_t refvolt=VCC,uint8_t divider=2) {
275 m_DividerRatio=divider;
276 m_RefVoltage = refvolt;
277 pinMode(m_SensePin, INPUT);
278 if (m_ActivationPin < 0xFF) {
279 pinMode(m_ActivationPin, OUTPUT);
281 BatterySensor::init(period,clock);
285 virtual uint8_t voltage () {
286 if (m_ActivationPin != 0xFF) {
287 digitalWrite(m_ActivationPin, HIGH);
290 analogRead(m_SensePin);
292 uint32_t value = analogRead(m_SensePin);
293 uint16_t vcc = (value * m_DividerRatio * m_RefVoltage) / 1024 / 100;
294 if (m_ActivationPin != 0xFF) {
295 digitalWrite(m_ActivationPin, LOW);
297 DPRINT(F(
"Bat: ")); DDECLN(vcc);
303 #ifdef ARDUINO_ARCH_AVR
312 static volatile uint16_t __gb_BatCurrent;
313 static volatile uint8_t __gb_BatCount;
314 static uint16_t (*__gb_BatIrq)();
324 uint8_t
current ()
const {
return (__gb_BatCurrent + 50) / 100; }
357 if( __gb_BatCount < 10 ) {
359 if( ++m_BatSkip > 10 ) {
361 while( __gb_BatCount++ < 10 ) {
362 while (ADCSRA & (1 << ADSC)) ;
363 ADCSRA |= (1 << ADSC);
368 ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
372 ADCSRA &= ~((1 << ADIE) | (1 << ADIF));
373 while (ADCSRA & (1 << ADSC)) ;
377 void unsetIdle (uint16_t (*irqfunc)()) {
379 ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
381 __gb_BatIrq = irqfunc;
383 ADMUX &= ~(ADMUX_REFMASK | ADMUX_ADCMASK);
384 ADMUX |= ADMUX_REF_AVCC;
385 ADMUX |= ADMUX_ADC_VBG;
386 ADCSRA |= (1 << ADIE) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
387 ADCSRA |= (1 << ADSC);
390 #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
391 static void __vectorfunc() __asm__("__vector_24") __attribute__((__signal__, __used__, __externally_visible__));
393 static void __vectorfunc() __asm__("__vector_21") __attribute__((__signal__, __used__, __externally_visible__));
415 void init(__attribute__((unused)) uint32_t period,__attribute__((unused))
AlarmClock& clock) {
433 IrqBaseBatt::unsetIdle(
irq);
448 return 1100UL * 1024 / ADC;
453 extern volatile uint16_t intVCC;
454 template <u
int8_t SENSPIN,u
int8_t ACTIVATIONPIN,u
int8_t FACTOR=57>
467 void init(__attribute__((unused)) uint32_t period,__attribute__((unused))
AlarmClock& clock) {
468 pinMode(SENSPIN, INPUT);
472 uint16_t getInternalVcc() {
474 ADMUX &= ~(ADMUX_REFMASK | ADMUX_ADCMASK);
475 ADMUX |= ADMUX_REF_AVCC;
476 ADMUX |= ADMUX_ADC_VBG;
478 ADCSRA |= (1 << ADSC);
479 while (ADCSRA & (1 << ADSC)) ;
480 return 1100UL * 1024 / ADC;
490 pinMode(ACTIVATIONPIN, INPUT);
498 #ifndef analogPinToChannel
499 #define analogPinToChannel(p) ((p)-14)
503 pinMode(ACTIVATIONPIN, OUTPUT);
504 digitalWrite(ACTIVATIONPIN, LOW);
506 ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
511 intVCC = getInternalVcc();
513 ADMUX &= ~(ADMUX_REFMASK | ADMUX_ADCMASK);
514 ADMUX |= ADMUX_REF_AVCC;
515 ADMUX |= analogPinToChannel(SENSPIN);
516 ADCSRA |= (1 << ADIE) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
517 ADCSRA |= (1 << ADSC);
522 return 1UL * intVCC * FACTOR * ADC / 1024 / 10;