#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include <Bounce.h>
#include <Snooze.h>
SnoozeTimer timer;
SnoozeBlock config_teensy32(timer);
SnoozeBlock dummyConfig;
#define OLED_RESET 9
Adafruit_SSD1306 display(OLED_RESET);
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
struct mVdata { // data in mv format
uint16_t Vcc_mv;
uint16_t Bat_mv;
uint16_t Led_mv;
};
struct ADCdata { // as read Data
uint16_t VccADC;
uint16_t BatADC;
uint16_t LedADC;
};
struct EEPROMdata { //main set of data makes eeprom read write easy
uint32_t Compact3ADC;
uint32_t ElaspedT;
};
const int milisPerDay = 86400000;
const int milisPerHour = 3600000;
const int milisPerMin = 60000;
struct ADCdata RawADC;
struct mVdata dispData;
struct EEPROMdata StoreSet;
int eepromAdr = 0;
#define BUTTON_C 8
elapsedMillis OnTime;
int saves = 0;
Bounce bouncer_C = Bounce( BUTTON_C, 5 );
void saveXmV( uint16_t Delta_mV = 10);
boolean checkWipe(void);
boolean checkDump(void);
void wipeeEEPROM(void);
void dumpall(void);
boolean serialCheckYnWtimeout(uint32_t timeout = 30000);
void setup() {
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Serial?");
display.display();
while (!Serial && (OnTime < 15000));
if (OnTime < 15000) {
display.print(" Y"); display.display();
if (checkDump()) {
dumpall();
for (int cd = 60 ; cd > 0; cd = cd - 1) {
delay (1000);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(cd);
display.display();
}
}
if (checkWipe()) {
wipeeEEPROM();
}
}
else {
display.print(" N"); display.display();
delay(5000);
}
pinMode(BUTTON_C, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
analogReadResolution(10); // 10-bit resolution 0 to 1023
analogReadAveraging(32); // 4,8,16, or 32 samples.
}
void loop() {
REDUCED_CPU_BLOCK(dummyConfig) {
int value = 0; int digit = 0;
RawADC.VccADC = analogRead(A9);
RawADC.BatADC = analogRead(A7);
dispData.Vcc_mv = ((RawADC.VccADC * 6600) / 1023);
dispData.Bat_mv = ((RawADC.BatADC * 6600) / 1023);
digitalWrite (LED_BUILTIN, HIGH);
timer.setTimer(20); //led on
Snooze.deepSleep( config_teensy32 );
RawADC.LedADC = analogRead(A0);
dispData.Led_mv = ((RawADC.LedADC * 3300) / 1023);
digitalWrite (LED_BUILTIN, LOW);
bouncer_C .update ( );
value = bouncer_C.read();
if ( value == LOW) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print( dispData.Vcc_mv);
display.print( " ");
display.println( dispData.Bat_mv);
display.println( dispData.Led_mv);
digit = OnTime / milisPerDay;
display.print(digit);
display.print("D ");
digit = (OnTime % milisPerDay) / milisPerHour;
if (digit < 10)display.print("0");
display.print(digit);
display.print(":");
digit = (OnTime % milisPerHour) / milisPerMin;
if (digit < 10)display.print("0");
display.print(digit);
display.print(":");
digit = (OnTime % milisPerMin) / 1000;
if (digit < 10)display.print("0");
display.print(digit);
display.print(" EE=");
display.println(saves);
display.display();
}
else {
display.clearDisplay();
display.display();
timer.setTimer(1980); // display off
Snooze.deepSleep( config_teensy32 );
}
saveXmV(25);
}
}
uint32_t packData(struct ADCdata chunk) { // checked ok
return ((((chunk.VccADC * 1024) + chunk.BatADC) * 1024) + chunk.LedADC);
}
struct ADCdata unpackData(EEPROMdata EEpackeddata) { // checked ok
struct ADCdata tempDataChunk; uint32_t packeddata;
packeddata = EEpackeddata.Compact3ADC;
tempDataChunk.LedADC = (packeddata % 1024);
tempDataChunk.BatADC = ((packeddata / 1024) % 1024);
tempDataChunk.VccADC = ((packeddata / 1024) / 1024);
return tempDataChunk;
}
struct ADCdata unpackData(uint32_t packeddata) { // checked ok
struct ADCdata tempDataChunk;
tempDataChunk.LedADC = (packeddata % 1024);
tempDataChunk.BatADC = ((packeddata / 1024) % 1024);
tempDataChunk.VccADC = ((packeddata / 1024) / 1024);
return tempDataChunk;
}
void saveXmV( uint16_t Delta_mV ) {
static uint32_t eepromAdr = 0; static uint16_t lastSavemV = 6000;
if ((dispData.Bat_mv >= (lastSavemV + Delta_mV)) or (dispData.Bat_mv <= (lastSavemV - Delta_mV))) {
lastSavemV = dispData.Bat_mv;
lastSavemV = lastSavemV / Delta_mV;
lastSavemV = lastSavemV * Delta_mV;
StoreSet.ElaspedT = OnTime;
StoreSet.Compact3ADC = packData(RawADC);
if (eepromAdr < (E2END - sizeof(StoreSet))) {
EEPROM.put( eepromAdr, StoreSet );
eepromAdr = eepromAdr + sizeof(StoreSet);
saves = saves + 1;
}
}
}
void dumpall(void) {// check
struct mVdata tempDataChunk; struct ADCdata temmpEEChunk;
eepromAdr = 0;
while (eepromAdr < E2END) {
EEPROM.get( eepromAdr, StoreSet );
temmpEEChunk = unpackData(StoreSet);
tempDataChunk.Vcc_mv = ((temmpEEChunk.VccADC * 6600) / 1023);
tempDataChunk.Bat_mv = ((temmpEEChunk.BatADC * 6600) / 1023);
tempDataChunk.Led_mv = ((temmpEEChunk.LedADC * 3300) / 1023);
if (StoreSet.ElaspedT >= 1000) {
Serial.print(tempDataChunk.Vcc_mv);
Serial.print(",");
Serial.print(tempDataChunk.Bat_mv);
Serial.print(",");
Serial.print(tempDataChunk.Led_mv);
Serial.print(",");
Serial.println(StoreSet.ElaspedT);
}
else {
eepromAdr = E2END;
}
eepromAdr = eepromAdr + sizeof(StoreSet);
}
}
boolean serialCheckYnWtimeout(uint32_t timeout) {// checked ok
// returns true only if y or Y entered within timeout
elapsedMillis waiting = 0; char c = ' ';
while (waiting < timeout) {
if (Serial.available()) {
waiting = timeout + 1; // got one no more wait needed-
c = Serial.read();
if ((c == 'y') or (c == 'Y') )
{
return true;
}
return false;
}
}
return false;
}
void wipeeEEPROM(void) { // checked ok
for (int adr = 0; adr < E2END; adr = adr + 1) { //<=E2END *********************
EEPROM.put( adr, 0);
}
}
boolean checkWipe(void) { // checked ok
// double check wipe returns true to wipe
Serial.println("Wipe EEPROM y or n ? ");
if (serialCheckYnWtimeout() == true) {
Serial.println("Are you sure ? Wipe EEPROM y or n ? ");
if (serialCheckYnWtimeout() == true) {
return true;
}
return false;
}
return false;
}
boolean checkDump(void) { // checked ok
// double check wipe returns true to wipe
Serial.println("Dump EEPROM y or n ? ");
if (serialCheckYnWtimeout() == true) {
return true;
}
else {
return false;
}
}