Skip to content

Instantly share code, notes, and snippets.

@w0rm49
Last active August 19, 2019 09:34
Show Gist options
  • Select an option

  • Save w0rm49/fc15f6dc06c4f7265e82363ab8067152 to your computer and use it in GitHub Desktop.

Select an option

Save w0rm49/fc15f6dc06c4f7265e82363ab8067152 to your computer and use it in GitHub Desktop.
Working time counter
/**
* connect ssd1306 to i2c pins
* button (or jumper) between pin 2 and ground
*
* how to reset counter:
* 1. press and hold button
* 2. reset or enable arduino
* 3. hold button at least 2 seconds,
* 4. reboot again
*/
#include <Wire.h>
#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define RESET_PIN 2
#define SCREEN_ADDRESS 0x3C
#define SCROLLBAR_Y 55
#define HOURS_Y 8
Adafruit_SSD1306 display(128, 64, &Wire, -1);
uint16_t totalMinutes = 0;
uint16_t hours = 0;
uint8_t minutes = 0;
unsigned long mlsLast = 0;
unsigned long mls = 0;
uint16_t eepromAddr = 0;
union sector {
uint16_t data[sizeof(uint16_t) * 4];
uint8_t bytes[sizeof(uint32_t) * 2];
};
void setup() {
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
panic();
}
display.setTextColor(WHITE);
resetRoutine();
readSavedCounter();
display.setTextSize(5);
draw();
mlsLast = millis();
}
void loop() {
mls = millis();
if (mls - mlsLast < 60000) {
return;
}
mlsLast = mls;
totalMinutes++;
draw();
writeValueToSector(eepromAddr, 0, totalMinutes);
delay(3000);
writeValueToSector(eepromAddr, 1, totalMinutes);
delay(3000);
writeValueToSector(eepromAddr, 2, totalMinutes);
}
void draw() {
hours = totalMinutes / 60;
minutes = totalMinutes - (hours * 60);
display.clearDisplay();
display.setCursor(22, HOURS_Y);
if (hours < 10) {
display.print(F("0"));
}
if (hours < 100) {
display.print(F("0"));
}
if (hours > 999) {
display.print(F("999"));
} else {
display.println(hours);
}
//frame
display.drawLine(2, SCROLLBAR_Y, 125, SCROLLBAR_Y, WHITE);
display.drawLine(2, SCROLLBAR_Y + 6, 125, SCROLLBAR_Y + 6, WHITE);
display.drawLine(2, SCROLLBAR_Y, 2, SCROLLBAR_Y + 6, WHITE);
display.drawLine(125, SCROLLBAR_Y, 125, SCROLLBAR_Y + 6, WHITE);
//progress bar
uint8_t m2 = 4 + minutes * 2 + 1;
display.drawLine(4, SCROLLBAR_Y + 2, m2, SCROLLBAR_Y + 2, WHITE);
display.drawLine(4, SCROLLBAR_Y + 3, m2, SCROLLBAR_Y + 3, WHITE);
display.drawLine(4, SCROLLBAR_Y + 4, m2, SCROLLBAR_Y + 4, WHITE);
display.display();
}
void panic() {
pinMode(LED_BUILTIN, OUTPUT);
for(;;) {
digitalWrite(LED_BUILTIN, HIGH);
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(300);
}
}
void resetRoutine() {
pinMode(RESET_PIN, INPUT_PULLUP);
uint8_t val = digitalRead(RESET_PIN);
if (val == HIGH) {
return;
}
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, HOURS_Y);
display.print(F("hold to reset"));
display.display();
delay(2000);
display.clearDisplay();
display.setCursor(0, HOURS_Y);
if (digitalRead(RESET_PIN) == HIGH) {
display.println(F("reset failed"));
display.println(F("try again"));
} else {
uint16_t addr = pickValueFromSector(127);
addr++;
if (addr > 126) {
addr = 0;
}
writeValueToFullSector(127, addr);
writeValueToFullSector(addr, 0);
display.println(F("release button"));
display.println(F("and reboot"));
}
display.display();
//hang
for(;;);
}
void readSavedCounter() {
uint16_t addr = pickValueFromSector(127);
if (addr > 126) {
writeValueToFullSector(127, 0);
writeValueToFullSector(0, 0);
eepromAddr = 0;
totalMinutes = 0;
} else {
eepromAddr = addr;
totalMinutes = pickValueFromSector(addr);
}
}
uint16_t pickValueFromSector(uint8_t num) {
sector sect;
uint16_t realAddress = num * 8;
EEPROM.get(realAddress, sect);
if ((sect.data[0] == sect.data[1]) || (sect.data[0] == sect.data[2])) {
return sect.data[0];
}
if (sect.data[1] == sect.data[2]) {
return sect.data[1];
}
//we can only guess here
return sect.data[0];
}
void writeValueToSector(uint8_t num, uint8_t offset, uint16_t value) {
uint16_t realAddress = num * 8 + offset * sizeof(uint16_t);
EEPROM.put(realAddress, value);
}
void writeValueToFullSector(uint8_t num, uint16_t value) {
sector sect;
uint16_t realAddress = num * 8;
sect.data[0] = value;
sect.data[1] = value;
sect.data[3] = value;
sect.data[4] = 0;
EEPROM.put(realAddress, sect);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment