Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
#include <Wire.h>
#include <Adafruit_AHTX0.h>
#include <Adafruit_BMP280.h>
#include <Preferences.h>
#include <Arduino.h>

#define SD_LOG_INTERVAL_MIN 10

// --- Hardware Instances ---
extern Adafruit_AHTX0 aht;
extern Adafruit_BMP280 bmp;
extern Preferences prefs;
extern M5Canvas canvas;

// --- Sensor Status ---
Expand All @@ -39,6 +37,17 @@ struct DeviceConfig
unsigned long last_sd_log = 0;
// CPU frequency: 0 = Auto (240 awake / 80 dimmed), else fixed 240/160/80.
int cpu_freq = 0;

// --- Advanced Settings ---
int volume = 128;
float temp_offset = 0.0f;
float hum_offset = 0.0f;
float press_offset = 0.0f;
bool alerts_enabled = false;
float temp_high_thresh = 35.0f;
float temp_low_thresh = 0.0f;
float hum_high_thresh = 80.0f;
float hum_low_thresh = 20.0f;
};
extern DeviceConfig config;

Expand All @@ -50,8 +59,13 @@ struct DisplayState
bool is_dimmed = false;
int current_theme = 0;
int settings_cursor = 0;
int adv_settings_cursor = 0;
bool wasPressed = false;
bool settings_dirty = false;

// Alert state tracking (prevents beeping every loop)
bool prev_t_alert = false;
bool prev_h_alert = false;
};
extern DisplayState state;

Expand Down Expand Up @@ -110,8 +124,10 @@ void drawDashboard();
void drawForecast();
void drawStats();
void drawSettings();
void drawAdvancedSettings();

void readSensors();
void checkAlerts();
void updateTrend(float current_slp);
void updateHistory(float current_slp);
void logToSD();
Expand Down
31 changes: 0 additions & 31 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// --- Sensor Instances ---
Adafruit_AHTX0 aht;
Adafruit_BMP280 bmp;
Preferences prefs;
M5Canvas canvas(&M5Cardputer.Display);

// --- Sensor Status ---
Expand Down Expand Up @@ -47,36 +46,6 @@ void playTone(int type)
}
}

void saveSettings()
{
prefs.begin("weather_app", false);
prefs.putFloat("alt", config.altitude);
prefs.putInt("intvl", config.update_interval);
prefs.putBool("snd", config.sound_enabled);
prefs.putBool("prs", config.show_pressure);
prefs.putInt("brt", config.screen_brightness);
prefs.putInt("dimto", config.auto_dim_timeout);
prefs.putBool("sdlog", config.sd_logging);
prefs.putInt("cpu", config.cpu_freq);
prefs.end();
state.settings_dirty = false;
}

void loadSettings()
{
prefs.begin("weather_app", true);
config.altitude = prefs.getFloat("alt", 100.0f);
config.update_interval = prefs.getInt("intvl", 1);
config.sound_enabled = prefs.getBool("snd", false);
config.show_pressure = prefs.getBool("prs", true);
state.current_theme = prefs.getInt("thm", 0);
config.screen_brightness = prefs.getInt("brt", 255);
config.auto_dim_timeout = prefs.getInt("dimto", 30);
config.sd_logging = prefs.getBool("sdlog", false);
config.cpu_freq = prefs.getInt("cpu", 0);
prefs.end();
}

// Apply the configured CPU frequency. Auto mode underclocks to 80 MHz while
// dimmed (battery) and returns to 240 MHz when awake
void applyCpuFrequency(bool dimmed)
Expand Down
56 changes: 0 additions & 56 deletions src/sensor.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,4 @@
#include "common.h"
#include <SPI.h>
#include <SD.h>

static SPIClass sdSPI(HSPI);
static bool sd_inited = false;
static bool sd_available = false;

void toggleSDLogging()
{
config.sd_logging = !config.sd_logging;
prefs.begin("weather_app", false);
prefs.putBool("sdlog", config.sd_logging);
prefs.end();
if (!config.sd_logging)
{
sd_inited = false;
sd_available = false;
}
playTone(config.sd_logging ? 1 : -1);
state.redraw = true;
}

// --- Zambretti-style forecaster (pressure + 3h tendency only) ---
// Returns a code 0..26 where higher values mean worse weather.
Expand Down Expand Up @@ -227,39 +206,4 @@ void updateTrend(float current_slp)
telemetry.slp_rate * 3.0f);
}

void logToSD()
{
if (!config.sd_logging)
return;

unsigned long interval = (unsigned long)SD_LOG_INTERVAL_MIN * 60UL * 1000UL;
if (config.last_sd_log != 0 && (millis() - config.last_sd_log) < interval)
return;
config.last_sd_log = millis();

if (!sd_inited)
{
sdSPI.begin(40, 39, 14, 12); // SCK, MISO, MOSI, CS (Cardputer SD slot)
sd_available = SD.begin(12, sdSPI, 25000000);
sd_inited = true;
}
if (!sd_available)
return;

File f = SD.open("/meteo.csv", FILE_APPEND);
if (!f)
return;

if (f.size() == 0)
f.println("uptime_ms,temp_c,humidity,pressure_hpa,slp_hpa,trend,rate_hpa_h,bat_pct");

int mv = M5Cardputer.Power.getBatteryVoltage();
int bat = map(constrain(mv, 3300, 4200), 3300, 4200, 0, 100);
char row[112];
snprintf(row, sizeof(row), "%lu,%.2f,%.2f,%.2f,%.2f,%d,%.3f,%d",
millis(), telemetry.temperature, telemetry.humidity,
telemetry.pressure, telemetry.slp, telemetry.pressure_trend,
telemetry.slp_rate, bat);
f.println(row);
f.close();
}
125 changes: 125 additions & 0 deletions src/storage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include "common.h"
#include <SPI.h>
#include <SD.h>

static SPIClass sdSPI(HSPI);
static bool sd_inited = false;
static bool sd_available = false;

bool ensureSDReady() {
if (!sd_inited) {
sdSPI.begin(40, 39, 14, 12);
sd_available = SD.begin(12, sdSPI, 25000000);
sd_inited = true;
}
if (sd_available && !SD.exists("/cardmeteo")) {
SD.mkdir("/cardmeteo");
}
return sd_available;
}

void deinitSD() {
sd_inited = false;
sd_available = false;
}

void toggleSDLogging() {
config.sd_logging = !config.sd_logging;
saveSettings(); // Persist immediately to SD
if (!config.sd_logging) deinitSD();
playTone(config.sd_logging ? 1 : -1);
state.redraw = true;
}

void loadSettings() {
if (!ensureSDReady()) return; // Fallback to defaults if no SD

File f = SD.open("/cardmeteo/settings.cfg", FILE_READ);
if (!f) return;

while (f.available()) {
String line = f.readStringUntil('\n');
line.trim();
int eq = line.indexOf('=');
if (eq < 0) continue;

String key = line.substring(0, eq);
String val = line.substring(eq + 1);

if (key == "alt") config.altitude = val.toFloat();
else if (key == "intvl") config.update_interval = val.toInt();
else if (key == "snd") config.sound_enabled = (val == "1");
else if (key == "prs") config.show_pressure = (val == "1");
else if (key == "thm") state.current_theme = val.toInt();
else if (key == "brt") config.screen_brightness = val.toInt();
else if (key == "dimto") config.auto_dim_timeout = val.toInt();
else if (key == "sdlog") config.sd_logging = (val == "1");
else if (key == "cpu") config.cpu_freq = val.toInt();
else if (key == "vol") config.volume = val.toInt();
else if (key == "toffset") config.temp_offset = val.toFloat();
else if (key == "hoffset") config.hum_offset = val.toFloat();
else if (key == "poffset") config.press_offset = val.toFloat();
else if (key == "alert") config.alerts_enabled = (val == "1");
else if (key == "thi") config.temp_high_thresh = val.toFloat();
else if (key == "tlo") config.temp_low_thresh = val.toFloat();
else if (key == "hhi") config.hum_high_thresh = val.toFloat();
else if (key == "hlo") config.hum_low_thresh = val.toFloat();
}
f.close();

// If alerts are enabled, force sound on
if (config.alerts_enabled) config.sound_enabled = true;
}

void saveSettings() {
if (!ensureSDReady()) return;

File f = SD.open("/cardmeteo/settings.cfg", FILE_WRITE);
if (!f) return;

f.printf("alt=%.1f\n", config.altitude);
f.printf("intvl=%d\n", config.update_interval);
f.printf("snd=%d\n", config.sound_enabled ? 1 : 0);
f.printf("prs=%d\n", config.show_pressure ? 1 : 0);
f.printf("thm=%d\n", state.current_theme);
f.printf("brt=%d\n", config.screen_brightness);
f.printf("dimto=%d\n", config.auto_dim_timeout);
f.printf("sdlog=%d\n", config.sd_logging ? 1 : 0);
f.printf("cpu=%d\n", config.cpu_freq);
f.printf("vol=%d\n", config.volume);
f.printf("toffset=%.2f\n", config.temp_offset);
f.printf("hoffset=%.2f\n", config.hum_offset);
f.printf("poffset=%.2f\n", config.press_offset);
f.printf("alert=%d\n", config.alerts_enabled ? 1 : 0);
f.printf("thi=%.1f\n", config.temp_high_thresh);
f.printf("tlo=%.1f\n", config.temp_low_thresh);
f.printf("hhi=%.1f\n", config.hum_high_thresh);
f.printf("hlo=%.1f\n", config.hum_low_thresh);
f.close();
}

void logToSD() {
if (!config.sd_logging) return;

unsigned long interval = (unsigned long)SD_LOG_INTERVAL_MIN * 60UL * 1000UL;
if (config.last_sd_log != 0 && (millis() - config.last_sd_log) < interval) return;
config.last_sd_log = millis();

if (!ensureSDReady()) return;

File f = SD.open("/cardmeteo/meteo.csv", FILE_APPEND);
if (!f) return;

if (f.size() == 0)
f.println("uptime_ms,temp_c,humidity,pressure_hpa,slp_hpa,trend,rate_hpa_h,bat_pct");

int mv = M5Cardputer.Power.getBatteryVoltage();
int bat = map(constrain(mv, 3300, 4200), 3300, 4200, 0, 100);
char row[112];
snprintf(row, sizeof(row), "%lu,%.2f,%.2f,%.2f,%.2f,%d,%.3f,%d",
millis(), telemetry.temperature, telemetry.humidity,
telemetry.pressure, telemetry.slp, telemetry.pressure_trend,
telemetry.slp_rate, bat);
f.println(row);
f.close();
}