Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better use of wifi and time configuration #9

Closed
wants to merge 8 commits into from
Closed
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
src/os_config.h
9 changes: 6 additions & 3 deletions src/home.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const char *months[] = {"January", "February", "March", "April", "May", "June",

const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void drawHomeUI(GxEPD_Class *display, ESP32Time *rtc, int batteryStatus) {
void drawHomeUI(GxEPD_Class *display, ESP32Time *rtc, int batteryStatus, bool isCharging) {
display->fillScreen(GxEPD_WHITE);
display->setTextColor(GxEPD_BLACK);
display->setTextWrap(false);
Expand All @@ -14,7 +14,7 @@ void drawHomeUI(GxEPD_Class *display, ESP32Time *rtc, int batteryStatus) {
String hoursFiller = rtc->getHour(true) < 10 ? "0" : "";
String minutesFiller = rtc->getMinute() < 10 ? "0" : "";
String timeStr = hoursFiller + String(rtc->getHour(true)) + ":" + minutesFiller + String(rtc->getMinute());
printCenterString(display, timeStr.c_str(), 100, 125);
printCenterString(display, timeStr.c_str(), 98, 125);

// Date
display->setFont(&Outfit_60011pt7b);
Expand All @@ -27,7 +27,10 @@ void drawHomeUI(GxEPD_Class *display, ESP32Time *rtc, int batteryStatus) {
const unsigned char *icon_battery_small_array[6] = {epd_bitmap_icon_battery_0_small, epd_bitmap_icon_battery_20_small,
epd_bitmap_icon_battery_40_small, epd_bitmap_icon_battery_60_small,
epd_bitmap_icon_battery_80_small, epd_bitmap_icon_battery_100_small};
display->drawBitmap(170, 2, icon_battery_small_array[batteryStatus / 20], 28, 28, GxEPD_BLACK);
const unsigned char *icon_battery = epd_bitmap_icon_battery_charging_small;
if (!isCharging)
icon_battery = icon_battery_small_array[batteryStatus / 20];
display->drawBitmap(170, 2, icon_battery, 28, 28, GxEPD_BLACK);

// Status icons
display->drawBitmap(2, 2, icon_wifi_small, 28, 28, GxEPD_BLACK);
Expand Down
2 changes: 1 addition & 1 deletion src/home.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
#include "resources/fonts/Outfit_80036pt7b.h"
#include "resources/icons.h"

void drawHomeUI(GxEPD_Class *display, ESP32Time *rtc, int batteryStatus);
void drawHomeUI(GxEPD_Class *display, ESP32Time *rtc, int batteryStatus, bool isCharging);
88 changes: 82 additions & 6 deletions src/lib/battery.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,87 @@
#include "battery.h"

#define VOLTAGE_REFERENCE 3.3 // Voltage reference of the ADC
#define ADC_RESOLUTION 4096 // 12-bit ADC resolution
#define NUM_SAMPLES 25 // Number of samples to average
#define DELAY_BETWEEN_SAMPLES 5 // Delay between ADC samples in milliseconds
#define VOLTAGE_RISING_DIFF 0.046 // if the voltage diff is more than this it's probably fine to assume that it's growing
#define VOLTAGE_STABLE_DIFF 0.012 // if the voltage diff is less than this it's probably fine to assume that it's nearing at 100%
#define RESISTOR_MULTIPLIER 2
#define BATTERY_MIN_STATUS 0 // 0%
#define BATTERY_MAX_STATUS 100 // 100%

float readBatteryVoltage() {
int adcValueSum = 0;

// Take multiple ADC readings to average out noise
for (int i = 0; i < NUM_SAMPLES; i++) {
adcValueSum += analogRead(BAT_ADC);
delay(DELAY_BETWEEN_SAMPLES); // Wait between readings
}

// Calculate the average ADC value
int adcValueAvg = adcValueSum / NUM_SAMPLES;

// Convert the average ADC value to actual voltage
float batteryVoltage = (adcValueAvg * VOLTAGE_REFERENCE) / ADC_RESOLUTION;

// Return the value multiplied by the resistor effective multiplier
return batteryVoltage * RESISTOR_MULTIPLIER;
}

void setPreviousVoltage(Preferences *preferences) { preferences->putFloat("prev_volt", readBatteryVoltage()); }

int calculateBatteryStatus() {
int bat = 0;
for (uint8_t i = 0; i < 25; i++) {
bat += analogRead(BAT_ADC);
return constrain(map(readBatteryVoltage() * 1000, BATTERY_MIN_VOLTAGE, BATTERY_MAX_VOLTAGE, BATTERY_MIN_STATUS, BATTERY_MAX_STATUS),
BATTERY_MIN_STATUS, BATTERY_MAX_STATUS);
}

bool isBatteryCharging(GxEPD_Class *display, Preferences *preferences) {
float currentVoltage = readBatteryVoltage();
float previousVoltage = preferences->getFloat("prev_volt");
Serial.printf("The current voltage is: %f\n", currentVoltage);
Serial.printf("The previous voltage is: %f\n", previousVoltage);
preferences->putFloat("prev_volt", currentVoltage);

// code for debugging
// char cur[10];
// char pre[10];
// dtostrf(currentVoltage, 1, 6, cur);
// dtostrf(previousVoltage, 1, 6, pre);
// display->setTextColor(GxEPD_BLACK);
// display->setFont(&Outfit_60011pt7b);
// printLeftString(display, cur, 34, 154);
// printLeftString(display, pre, 34, 174);

float voltDiff = currentVoltage - previousVoltage;
bool isCharging = voltDiff > VOLTAGE_RISING_DIFF || voltDiff > 0;
bool isFalling = voltDiff < -VOLTAGE_RISING_DIFF;
bool wasCharging = preferences->getBool("charging");

if (wasCharging && isFalling) {
isCharging = false;
preferences->putBool("charging", isCharging);
return isCharging;
}

if (wasCharging && !isCharging && !isFalling) {
isCharging = true;
preferences->putBool("charging", isCharging);
return isCharging;
}
bat /= 25;
float volt = (bat * 3.3 / 4096);
return constrain(map(volt * 1000, 1630, 1850, 0, 100), 0, 100);

if (!wasCharging && isCharging) {
isCharging = voltDiff > VOLTAGE_STABLE_DIFF;
preferences->putBool("charging", isCharging);
return isCharging;
}

// if (!wasCharging && isCharging)
// isCharging = voltageDiff >= VOLTAGE_RISING_DIFF;
// if (wasCharging && !isCharging)
// isCharging = (-voltageDiff < VOLTAGE_STABLE_DIFF);
// wasCharging = isCharging;

preferences->putBool("charging", isCharging);
return isCharging;
}
14 changes: 13 additions & 1 deletion src/lib/battery.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#pragma once

#include "Arduino.h"
#include "GxDEPG0150BN/GxDEPG0150BN.h" // 1.54" b/w 200x200
#include "GxEPD.h"
#include "os_config.h"

int calculateBatteryStatus();
#include "lib/ui.h"

#include "Preferences.h"
#include "resources/fonts/Outfit_60011pt7b.h"
#include "resources/fonts/Outfit_80036pt7b.h"
#include "resources/icons.h"

int calculateBatteryStatus();
float readBatteryVoltage();
void setPreviousVoltage(Preferences *preferences);
bool isBatteryCharging(GxEPD_Class *display, Preferences *preferences);
24 changes: 9 additions & 15 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ volatile SemaphoreHandle_t timerSemaphore;

void ARDUINO_ISR_ATTR onTimer() { xSemaphoreGiveFromISR(timerSemaphore, NULL); }

void WiFiConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
log(LogLevel::INFO, "WiFi connected");
configTime(GMT_OFFSET_SEC, DAY_LIGHT_OFFSET_SEC, NTP_SERVER1);
log(LogLevel::INFO, "Time synchronized from WiFi");
}

void setup() {
Serial.begin(115200);
delay(10);
Expand All @@ -64,9 +58,9 @@ void setup() {
SPI.begin(SPI_SCK, -1, SPI_DIN, EPD_CS);

pinMode(PWR_EN, OUTPUT);
pinMode(PIN_MOTOR, OUTPUT);
// pinMode(PIN_MOTOR, OUTPUT);
digitalWrite(PWR_EN, HIGH);
digitalWrite(PIN_MOTOR, LOW);
// digitalWrite(PIN_MOTOR, LOW);
pinMode(PIN_KEY, INPUT_PULLUP);
ButtonConfig *buttonConfig = button.getButtonConfig();
buttonConfig->setEventHandler(handleButtonEvent);
Expand All @@ -80,11 +74,9 @@ void setup() {
pinMode(BAT_ADC, ANALOG);
adcAttachPin(BAT_ADC);
analogReadResolution(12);
analogSetWidth(50);
// analogSetWidth(50); what does this even do? Not really useful...
log(LogLevel::SUCCESS, "Hardware pins initiliazed");

WiFi.onEvent(WiFiConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED);

timerSemaphore = xSemaphoreCreateBinary();
uiTimer = timerBegin(0, 80, true);
timerAttachInterrupt(uiTimer, &onTimer, true);
Expand All @@ -95,15 +87,13 @@ void setup() {
preferences.begin(PREFS_KEY);
log(LogLevel::SUCCESS, "Preferences initiliazed");

configTime(GMT_OFFSET_SEC, DAY_LIGHT_OFFSET_SEC, nullptr);
log(LogLevel::SUCCESS, "Time configured");

display.init();
display.setRotation(1);
log(LogLevel::SUCCESS, "Display initiliazed");

if (digitalRead(PIN_KEY) == 0)
wakeup = WakeupFlag::WAKEUP_FULL;

log(LogLevel::INFO, "Starting wakeup process...");

switch (wakeup) {
Expand All @@ -119,6 +109,10 @@ void setup() {
xTaskCreate(buttonUpdateTask, "ButtonUpdateTask", 10000, NULL, 1, NULL);
wakeupFull(&wakeup, &wakeupCount, &display, &rtc, &preferences);
break;

case WakeupFlag::WAKEUP_CHARGING:
wakeupCharging(&wakeup, &wakeupCount, &display, &rtc, &preferences);
break;
}

log(LogLevel::SUCCESS, "Wakeup process completed");
Expand Down Expand Up @@ -146,7 +140,7 @@ void loop() {
void buttonUpdateTask(void *pvParameters) {
while (1) {
button.check();
// vTaskDelay(5);
vTaskDelay(5 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
Expand Down
18 changes: 14 additions & 4 deletions src/os_config.h
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

// OS Configuration
#define DEVICE_NAME "qewer33's Watch"
#define DEVICE_NAME "QPaper"
#define PREFS_KEY "qpaper-os"

// Hardware Configuration
Expand All @@ -23,11 +23,21 @@
#define EPD_RESET 17
#define EPD_BUSY 16

// Battery configuration
#define BATTERY_MIN_VOLTAGE 2800 // 2.8V but change this to whatever is the minimum value that works
#define BATTERY_MAX_VOLTAGE 3905 // 3.9V but change this to whatever is the maximum value that works

// Time Configuration
#define NTP_SERVER1 "pool.ntp.org"
#define NTP_SERVER1 "time.google.com"
#define NTP_SERVER2 "time.nist.gov"
#define GMT_OFFSET_SEC (3600 * 3)
#define DAY_LIGHT_OFFSET_SEC 0
#define NTP_SERVER3 "pool.ntp.org"
#define GMT_OFFSET_SEC 3600 // 3600 seconds = 1 hour of offset from GMT
#define DAY_LIGHT_OFFSET_SEC 3600 // 3600 seconds = 1 hour of offset during daylight savings

// WiFi Configuration
#define WIFI_SSID "wifissid"
#define WIFI_PASSWD "wifipassword"
#define WIFI_RETRIES 60

// Software Functions Configuration
#define UPDATE_WAKEUP_TIMER_US 60 * 1000000
10 changes: 9 additions & 1 deletion src/resources/icons.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Use https://javl.github.io/image2cpp/
// with inverted color and black background

// ----- qpaperOS LOGO -----
// ----- qpaperOS LOGO ----- 100x100

const unsigned char qpaperos_logo_100[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -151,3 +151,11 @@ const unsigned char epd_bitmap_icon_battery_100_small[] PROGMEM = {
0xdb, 0x40, 0x6f, 0x6e, 0xdb, 0x60, 0x6f, 0x6e, 0xdb, 0x60, 0x6f, 0x6e, 0xdb, 0x60, 0x6f, 0x6e, 0xdb, 0x60, 0x6f, 0x6e, 0xdb, 0x40, 0x67,
0x64, 0xdb, 0x00, 0x60, 0x00, 0x03, 0x00, 0x7f, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// 'charging', 32x28px
const unsigned char epd_bitmap_icon_battery_charging_small[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00,
0x00, 0x00, 0x38, 0x00, 0x00, 0x3f, 0xbb, 0xfe, 0x00, 0x3f, 0x7b, 0xff, 0x00, 0x60, 0x78, 0x03, 0x00, 0x60, 0x78, 0x03, 0x00, 0x60, 0xff,
0xc3, 0x40, 0x60, 0xff, 0xc3, 0x60, 0x61, 0xff, 0x83, 0x60, 0x61, 0xff, 0x83, 0x60, 0x63, 0xff, 0x03, 0x60, 0x63, 0xff, 0x03, 0x40, 0x60,
0x1f, 0x03, 0x00, 0x60, 0x1e, 0x03, 0x00, 0x7f, 0xde, 0xff, 0x00, 0x3f, 0xdd, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Loading