-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathmain.cpp
More file actions
294 lines (244 loc) · 10.9 KB
/
main.cpp
File metadata and controls
294 lines (244 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
#include <ESPmDNS.h>
#include <esp_sleep.h>
#ifdef ESP_IDF_VERSION_MAJOR
#include "esp_wifi.h"
#include "esp_err.h"
#endif
#include "WebServer.h"
#include "Scale.h"
#include "WiFiManager.h"
#include "FlowRate.h"
#include "Calibration.h"
#include "BluetoothScale.h"
#include "TouchSensor.h"
#include "Display.h"
#include "PowerManager.h"
#include "BatteryMonitor.h"
#include "BoardConfig.h"
#include "Version.h"
// Board-specific pin configuration
uint8_t dataPin = HX711_DATA_PIN; // HX711 Data pin
uint8_t clockPin = HX711_CLOCK_PIN; // HX711 Clock pin
uint8_t touchPin = TOUCH_TARE_PIN; // Touch sensor for tare
uint8_t sleepTouchPin = TOUCH_SLEEP_PIN; // Touch sensor for sleep functionality
uint8_t batteryPin = BATTERY_PIN; // Battery voltage monitoring
uint8_t sdaPin = I2C_SDA_PIN; // I2C Data pin for display
uint8_t sclPin = I2C_SCL_PIN; // I2C Clock pin for display
float calibrationFactor = 4195.712891;
Scale scale(dataPin, clockPin, calibrationFactor);
FlowRate flowRate;
BluetoothScale bluetoothScale;
TouchSensor touchSensor(touchPin, &scale);
Display oledDisplay(sdaPin, sclPin, &scale, &flowRate);
PowerManager powerManager(sleepTouchPin, &oledDisplay);
BatteryMonitor batteryMonitor(batteryPin);
void setup() {
Serial.begin(115200);
// Set CPU frequency explicitly for power optimization
setCpuFrequencyMhz(80);
Serial.printf("CPU frequency set to: %dMHz for power optimization\n", getCpuFrequencyMhz());
// Version and board identification
Serial.println("=================================");
Serial.printf("WeighMyBru² v%s\n", WEIGHMYBRU_VERSION_STRING);
Serial.printf("Board: %s\n", WEIGHMYBRU_BOARD_NAME);
Serial.printf("Build: %s %s\n", WEIGHMYBRU_BUILD_DATE, WEIGHMYBRU_BUILD_TIME);
Serial.printf("Full Version: %s\n", WEIGHMYBRU_FULL_VERSION);
Serial.printf("Flash Size: %dMB\n", FLASH_SIZE_MB);
Serial.printf("CPU Frequency: %dMHz (Power Optimized)\n", getCpuFrequencyMhz());
Serial.println("=================================");
// Link scale and flow rate for tare operation coordination
scale.setFlowRatePtr(&flowRate);
// Check for factory reset request (hold touch pin during boot)
pinMode(touchPin, INPUT_PULLDOWN);
if (digitalRead(touchPin) == HIGH) {
Serial.println("FACTORY RESET: Touch pin held during boot - clearing WiFi credentials");
clearWiFiCredentials();
delay(1000);
}
// CRITICAL: Initialize BLE FIRST before WiFi to prevent radio conflicts
Serial.println("Initializing BLE FIRST for GaggiMate compatibility...");
Serial.printf("Free heap before BLE init: %u bytes\n", ESP.getFreeHeap());
Serial.printf("Free PSRAM before BLE init: %u bytes\n", ESP.getFreePsram());
try {
bluetoothScale.begin(); // Initialize BLE without scale reference
Serial.println("BLE initialized successfully - GaggiMate should be able to connect");
Serial.printf("Free heap after BLE init: %u bytes\n", ESP.getFreeHeap());
Serial.printf("Free PSRAM after BLE init: %u bytes\n", ESP.getFreePsram());
} catch (...) {
Serial.println("BLE initialization failed - continuing without Bluetooth");
Serial.printf("Free heap after BLE fail: %u bytes\n", ESP.getFreeHeap());
}
// Initialize display with error handling - don't block if display fails
Serial.println("Initializing display...");
bool displayAvailable = oledDisplay.begin();
if (!displayAvailable) {
Serial.println("WARNING: Display initialization failed!");
Serial.println("System will continue in headless mode without display.");
Serial.println("All functionality remains available via web interface.");
} else {
Serial.println("Display initialized - ready for visual feedback");
// Set reduced brightness for power optimization
oledDisplay.setBrightness(128); // 50% brightness vs 255 max
Serial.println("Display brightness set to 50% for power optimization");
}
// Check wake-up reason and show appropriate message
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason) {
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("Wakeup caused by external signal (touch sensor)");
// Show the same starting message as normal boot for consistency
delay(1500);
break;
case ESP_SLEEP_WAKEUP_EXT1:
Serial.println("Wakeup caused by external signal using RTC_CNTL");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Wakeup caused by timer");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("Wakeup caused by touchpad");
break;
default:
Serial.println("Wakeup was not caused by deep sleep: " + String(wakeup_reason));
// For normal startup, the begin() method already shows a startup message
delay(1000);
break;
}
//Wait for BLE to finish intitalizing before starting WiFi
delay(1500);
// Initialize WiFi power management BEFORE any WiFi operations
Serial.println("Initializing WiFi power management...");
// CRITICAL: Force WiFi completely off first to ensure clean state
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
delay(1000); // Allow hardware to fully reset
// Debug: Uncomment the next line to force reset WiFi state for testing
// resetWiFiEnabledState(); // DISABLED - state has been cleared
// ALWAYS enable WiFi power management for optimal battery life
WiFi.setSleep(true);
Serial.println("WiFi power management enabled for battery optimization");
// CRITICAL: Always setup WiFi first (like tare button scenario)
// This ensures all WiFi subsystems are properly initialized
// Then disable it cleanly if needed (replicating tare button sequence)
Serial.println("FORCING WiFi initialization to replicate tare button scenario...");
setupWiFiForced(); // Use forced setup to bypass state checks
// Wait for WiFi to fully stabilize after BLE is already running
delay(1500);
Serial.printf("Version: %s\n", ESP.getSdkVersion());
// Initialize scale with error handling - don't block web server if HX711 fails
Serial.println("Initializing scale...");
if (!scale.begin()) {
Serial.println("WARNING: Scale (HX711) initialization failed!");
Serial.println("Web server will continue to run, but scale readings will not be available.");
Serial.println("Check HX711 wiring and connections.");
} else {
Serial.println("Scale initialized successfully");
// Now that scale is ready, set the reference in BluetoothScale
bluetoothScale.setScale(&scale);
}
// BLE was initialized earlier - no need to initialize again
// bluetoothScale.begin(&scale);
// Set bluetooth reference in display for status indicator (if display available)
if (oledDisplay.isConnected()) {
oledDisplay.setBluetoothScale(&bluetoothScale);
}
// Set display reference in bluetooth for timer control
bluetoothScale.setDisplay(&oledDisplay);
// Set power manager reference in display for timer state synchronization (if display available)
if (oledDisplay.isConnected()) {
oledDisplay.setPowerManager(&powerManager);
}
// Set battery monitor reference in display for battery status (if display available)
if (oledDisplay.isConnected()) {
oledDisplay.setBatteryMonitor(&batteryMonitor);
}
// Initialize touch sensor
touchSensor.begin();
// Initialize power manager
powerManager.begin();
// Initialize battery monitor
batteryMonitor.begin();
// Check for low battery - prevent boot if voltage too low
float batteryVoltage = batteryMonitor.getBatteryVoltage();
if (batteryVoltage < 3.2f && batteryVoltage > 0.1f) { // > 0.1f to avoid false readings
Serial.printf("CRITICAL: Battery voltage too low (%.2fV) - entering sleep\n", batteryVoltage);
// Show battery low message on display with large, centered formatting
if (oledDisplay.isConnected()) {
oledDisplay.showBatteryLowMessage(batteryVoltage, 3000);
}
delay(3000); // Show message for 3 seconds
// Force clear any display state and sleep immediately
if (oledDisplay.isConnected()) {
oledDisplay.clear();
}
Serial.println("Forcing deep sleep now...");
esp_deep_sleep_start();
}
Serial.printf("Battery voltage OK (%.2fV) - continuing boot\n", batteryVoltage);
// Show IP addresses and welcome message if display is available
delay(100); // Small delay to ensure WiFi is fully initialized
if (oledDisplay.isConnected()) {
oledDisplay.showIPAddresses();
}
// Link display to touch sensor for tare feedback (if display available)
if (oledDisplay.isConnected()) {
touchSensor.setDisplay(&oledDisplay);
}
// Link flow rate to touch sensor for averaging reset on tare
touchSensor.setFlowRate(&flowRate);
setupWebServer(scale, flowRate, bluetoothScale, oledDisplay, batteryMonitor);
// CRITICAL: After full initialization, check if WiFi should be disabled
// This exactly replicates the tare button scenario: WiFi started, then disabled
Serial.println("=== POST-INITIALIZATION WiFi STATE CHECK ===");
if (!loadWiFiEnabledState()) {
Serial.println("WiFi should be disabled - applying clean shutdown like tare button");
Serial.println("(WiFi was initialized first, now disabling cleanly)");
// Small delay to ensure all systems are stable (like tare button timing)
delay(100);
// Now call disableWiFi() exactly like tare button does
disableWiFi();
Serial.println("WiFi cleanly disabled - 0.05A power consumption expected");
} else {
Serial.println("WiFi should remain enabled - no action needed");
}
}
void loop() {
static unsigned long lastWeightUpdate = 0;
static unsigned long lastWiFiCheck = 0;
static unsigned long lastDisplayUpdate = 0;
// Update weight at reduced frequency for power optimization
if (millis() - lastWeightUpdate >= 50) { // Reduced from 20ms to 50ms (20Hz from 50Hz)
float weight = scale.getWeight();
flowRate.update(weight);
lastWeightUpdate = millis();
}
static unsigned long lastBLEUpdate = 0;
// Check WiFi status every 30 seconds for debugging
if (millis() - lastWiFiCheck >= 30000) {
printWiFiStatus();
lastWiFiCheck = millis();
}
// Maintain WiFi AP stability
maintainWiFi();
// Update Bluetooth less frequently to reduce BLE interference and power usage
if (millis() - lastBLEUpdate >= 100) { // Reduced from 50ms to 100ms (10Hz from 20Hz)
bluetoothScale.update();
lastBLEUpdate = millis();
}
// Update touch sensor
touchSensor.update();
// Update power manager
powerManager.update();
// Update battery monitor
batteryMonitor.update();
// Update display less frequently for power saving
if (millis() - lastDisplayUpdate >= 100) { // Reduced display refresh rate to 10Hz
oledDisplay.update();
lastDisplayUpdate = millis();
}
// Increased delay for better power efficiency while maintaining responsiveness
delay(10); // Optimized delay: 10ms for good responsiveness with power savings
}