/*
* Arduino
* board: MicroCore/attiny13 (https://github.com/MCUdude/MicroCore) v2.2.0
* clock: 1.2MHz
* brown out: 1.8V
* eeprom: retained
* micros: disabled
*
* touchCount
* idle 870 + noise 3-4 -> threshold 5 ~= signal shift 0.6%
* lower noise with grounded case
* baseCount
* https://www.ti.com/lit/pdf/slaa521
*
* power consumption:
* 30uA Sleep
* 110uA Sample
* 70mA Led
*
* MCP1643
* Schottky diode at Vcc to have Vcc < Vled at full batteries
* both LEDs over shunt resistor, because at > 4.7 Ohm already at control limit
* designed for higher power -> efficiency here < 70%
*
* Icon
* https://www.flaticon.com/de/kostenloses-icon/die-gluhbirne_74072 512px copy into 600dpi picture and invert
*/
#include
#include "ADCTouch.h" // = https://github.com/MCUdude/MicroCore/pull/133
//#include
#include
#define DEBUG_PRINT 1
#define PIN_RXD PIN_PB0
#define PIN_TXD PIN_PB1
#define PIN_UNUSED PIN_PB2
#define PIN_TOUCH A3 // = PB3
#define PIN_LED PIN_PB4
const uint16_t ADCTouch::samples = 8;
const int16_t touchThreshold = 6;
int16_t touchBaseCount = 0;
const long sleepMillis = 250; // sample each 1/4 sec
const int8_t outOnSec = 15;
int8_t outOnTime = 0; // >0 time in 1/4sec unit, 0 calibrate, -1 sample
#if DEBUG_PRINT
int16_t outOnCount = 0;
int16_t maxDiff = 0;
#endif
void setup() {
#if DEBUG_PRINT
// c:\Users\kai\AppData\Local\Arduino15\packages\MicroCore\hardware\avr\2.2.0\libraries\Serial_examples\examples\OscillatorCalibration\OscillatorCalibration.ino
// 0x3B-D for 19200 baud @ 1.2MHz and 115000 baud @ 9.6MHz
// 0x31;0x41 for 38400 baud @ 4.8MHz; n/a for 600KHz
uint8_t cal = EEPROM.read(0);
if (cal < 0x80)
OSCCAL = cal;
#else
pinMode(PIN_RXD, INPUT_PULLUP);
pinMode(PIN_TXD, INPUT_PULLUP);
#endif
pinMode(PIN_UNUSED, INPUT_PULLUP);
pinMode(PIN_LED, OUTPUT);
for(int i=0; i<6; i++) {
ADCTouch::read(PIN_TOUCH); // fully discharge
delay(250);
PORTB = PORTB ^ _BV(PIN_LED);
}
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
// outOnTime == 0 -> calibrate at first loop()
}
void loop() {
digitalWrite(PIN_LED, outOnTime>0 ? HIGH : LOW);
uint32_t m = millis();
while (millis() - m < sleepMillis)
sleep_mode(); // wake up each 16ms by watchdog timer
//noInterrupts(); // no difference
int16_t touchCount = ADCTouch::read(PIN_TOUCH);
//interrupts();
int16_t diff = touchCount - touchBaseCount;
if(outOnTime == 0) { // voltage (and therefore ADC value) increases for older batteries after light off -> calibrate & skip 1 value
diff = 0;
touchBaseCount = touchCount;
outOnTime--;
}
if(diff > 0) {
touchBaseCount++;
} else {
touchBaseCount = (touchCount + touchBaseCount)/2;
}
if(diff >= touchThreshold) {
if(outOnTime < 0)
outOnCount++;
outOnTime = 4 * outOnSec;
}
if(outOnTime > 0) {
outOnTime--;
}
#if DEBUG_PRINT
if(diff > maxDiff)
maxDiff = diff;
Serial.print(outOnCount);
Serial.print(' ');
Serial.print(touchCount);
Serial.print(' ');
Serial.print(touchBaseCount);
Serial.print(' ');
Serial.print(diff);
Serial.print(' ');
Serial.print(maxDiff);
Serial.print('\n');
#endif
}