Added battery module, cal factor refresh bug

This commit is contained in:
2026-03-27 17:14:16 +01:00
parent f000924c05
commit eab70f9bf9
12 changed files with 224 additions and 36 deletions

View File

@@ -6,6 +6,18 @@
namespace router { namespace router {
int send(const Task &task) { int send(const Task &task) {
if (task.target == MOD_ALL) {
for (size_t i = 0; i < MOD_COUNT; i++) {
module_base *mod = modules[i];
if (mod == nullptr) {
continue;
}
return mod->push(task);
}
}
if (task.target >= MOD_COUNT) { if (task.target >= MOD_COUNT) {
return 1; return 1;
} }
@@ -23,4 +35,4 @@ namespace router {
Task t{target, type, data}; Task t{target, type, data};
return send(t); return send(t);
} }
} } // namespace router

View File

@@ -10,8 +10,10 @@ enum module_id : uint8_t {
MOD_CFG, MOD_CFG,
MOD_GPS, MOD_GPS,
MOD_LCD, MOD_LCD,
MOD_BAT,
MOD_COUNT, MOD_COUNT,
MOD_NULL MOD_NULL,
MOD_ALL,
}; };
enum task_type : uint8_t { enum task_type : uint8_t {
@@ -25,6 +27,9 @@ enum task_type : uint8_t {
TASK_CONFIG_WRITE_TEMP_TRACK, TASK_CONFIG_WRITE_TEMP_TRACK,
TASK_CONFIG_TRACK_DELETE, TASK_CONFIG_TRACK_DELETE,
TASK_CONFIG_CFG_RESET, TASK_CONFIG_CFG_RESET,
TASK_CONFIG_VBAT_CAL_SET,
TASK_BATTERY_CAL,
TASK_ALL_CONFIG_UPDATED,
}; };
struct Task { struct Task {

View File

@@ -11,6 +11,7 @@ struct vehicle_config{
bool auto_detect_track = true; bool auto_detect_track = true;
uint8_t track_fallback = 0; uint8_t track_fallback = 0;
bool track_slot_occupied[8] = {false}; bool track_slot_occupied[8] = {false};
double vbat_calibration = 0;
}; };
struct lat_lng { struct lat_lng {

View File

@@ -0,0 +1,14 @@
// Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "general_store.h"
volatile double vbat_global = 0;
void vbat_global_read(double& out) {
out = vbat_global;
}
void vbat_global_write(const double& in) {
vbat_global = in;
}

9
src/data/general_store.h Normal file
View File

@@ -0,0 +1,9 @@
// Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
extern volatile double vbat_global;
void vbat_global_read(double& out);
void vbat_global_write(const double& in);

View File

@@ -13,6 +13,7 @@
#include "base/modules.h" #include "base/modules.h"
#include "base/module_base.h" #include "base/module_base.h"
#include "base/router.h" #include "base/router.h"
#include "modules/battery/battery.h"
@@ -22,6 +23,7 @@ lcd *driver_display = new lcd(logger_output);
gps *gps_module = new gps(&Serial2, logger_output); gps *gps_module = new gps(&Serial2, logger_output);
config *system_config = new config(logger_output); config *system_config = new config(logger_output);
cmd *command_handler = new cmd(&Serial, logger_output); cmd *command_handler = new cmd(&Serial, logger_output);
battery *battery_handler = new battery(logger_output);
void setup() { void setup() {
@@ -31,6 +33,7 @@ void setup() {
modules[MOD_GPS] = gps_module; modules[MOD_GPS] = gps_module;
modules[MOD_CFG] = system_config; modules[MOD_CFG] = system_config;
modules[MOD_CMD] = command_handler; modules[MOD_CMD] = command_handler;
modules[MOD_BAT] = battery_handler;
driver_display->init(); driver_display->init();
driver_display->print_message("Starting Initialization"); driver_display->print_message("Starting Initialization");
@@ -57,6 +60,12 @@ void setup() {
delay(1000); delay(1000);
driver_display->print_message("GPS Init Complete"); driver_display->print_message("GPS Init Complete");
delay(1000); delay(1000);
driver_display->print_message("Bat Init...");
battery_handler->init();
delay(1000);
driver_display->print_message("Bat Init Complete");
delay(1000);
router::send(MOD_LCD, TASK_DISPLAY_DRIVER_PRIMARY); router::send(MOD_LCD, TASK_DISPLAY_DRIVER_PRIMARY);
} }
@@ -65,4 +74,5 @@ void loop() {
driver_display->loop(); driver_display->loop();
command_handler->parse_task(); command_handler->parse_task();
system_config->loop(); system_config->loop();
battery_handler->loop();
} }

View File

@@ -3,12 +3,70 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#include "battery.h" #include "battery.h"
#include "base/router.h"
#include "data/config_store.h"
#include "data/general_store.h"
int battery::calibrate(const Task &task) {
double actual_voltage;
memcpy(&actual_voltage, &task.data, sizeof(double));
int adc_read = analogRead(VBAT_PIN);
double cal_factor = actual_voltage / adc_read;
uint32_t output_val;
memcpy(&output_val, &cal_factor, sizeof(uint32_t));
router::send(MOD_CFG, TASK_CONFIG_VBAT_CAL_SET, output_val);
return 0;
}
int battery::push(const Task &task) { return _queue.push(task); } int battery::push(const Task &task) { return _queue.push(task); }
battery::battery() : _logger(nullptr) {} battery::battery() : _logger(nullptr) {}
battery::battery(system_logger *logger) battery::battery(system_logger *logger) : _logger(logger) {}
: _logger(logger) {}
battery::~battery() {} battery::~battery() {}
int battery::init() {
pinMode(VBAT_PIN, INPUT);
vehicle_config config;
config_global_read(config);
_cal = config.vbat_calibration;
}
int battery::loop(unsigned long timeout_ms) {
if (millis() > _last_read + _update_interval) {
int adc_read = analogRead(VBAT_PIN);
_vbat = _cal * adc_read;
vbat_global_write(_vbat);
}
Task active_task;
int res = _queue.pop(active_task);
if (res == 0) {
if (active_task.target == MOD_BAT) {
switch (active_task.type) {
case TASK_BATTERY_CAL:
this->calibrate(active_task);
break;
default:
break;
}
} else if (active_task.target == MOD_ALL) {
switch (active_task.type)
{
case TASK_ALL_CONFIG_UPDATED: {
vehicle_config config;
config_global_read(config);
_cal = config.vbat_calibration;
break;
}
default:
break;
}
}
}
return 0;
}

View File

@@ -2,8 +2,10 @@
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com> // Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#pragma once #pragma once
#define VBAT_PIN A3
#include "base/module_base.h" #include "base/module_base.h"
#include "base/ring_buffer.h"
#include "custom_types.h"
#include "modules/logger/system_logger.h" #include "modules/logger/system_logger.h"
#include <Arduino.h> #include <Arduino.h>
@@ -12,10 +14,17 @@ class battery : public module_base {
private: private:
system_logger *_logger; system_logger *_logger;
ring_buffer<Task, 16> _queue; ring_buffer<Task, 16> _queue;
double _vbat = 0;
double _cal = 0;
unsigned long _update_interval = 1000;
unsigned long _last_read = 0;
int calibrate(const Task& task);
public: public:
int push(const Task &task) override; int push(const Task &task) override;
battery(); battery();
battery(system_logger *logger); battery(system_logger *logger);
~battery(); ~battery();
int init();
int loop(unsigned long timeout_ms = 500);
}; };

View File

@@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#include "data/track_store.h" #include "data/track_store.h"
#include "data/config_store.h" #include "data/config_store.h"
#include "data/general_store.h"
#include "base/router.h" #include "base/router.h"
char *cmd::trim_arg(char *input) { char *cmd::trim_arg(char *input) {
@@ -107,6 +108,14 @@ cmd::command_id cmd::parse_command_name(const char *input) {
return CMD_DISPLAY_DRIVER_PRIMARY; return CMD_DISPLAY_DRIVER_PRIMARY;
} }
if (strcmp(input, "BATTERY_CAL") == 0) {
return CMD_BATTERY_CAL;
}
if (strcmp(input, "BATTERY_PRINT_VBAT") == 0) {
return CMD_BATTERY_PRINT_VBAT;
}
return CMD_UNKNOWN; return CMD_UNKNOWN;
} }
@@ -362,6 +371,46 @@ int cmd::handle_display_driver_primary(unsigned short argc) {
return router::send(MOD_LCD, TASK_DISPLAY_DRIVER_PRIMARY); return router::send(MOD_LCD, TASK_DISPLAY_DRIVER_PRIMARY);
} }
int cmd::handle_battery_cal(unsigned short argc, char *argv[]) {
if (argc != 2) {
#ifdef ERROR
if (_logger != nullptr) {
_logger->error("BATTERY_CAL expects 1 argument");
}
#endif
return 1;
}
double vbat = strtod(argv[1], nullptr);
uint32_t task_data;
memcpy(&task_data, &vbat, sizeof(uint32_t));
#ifdef INFO
if (_logger != nullptr) {
_logger->info("Calibrating VBAT");
}
#endif
router::send(MOD_BAT, TASK_BATTERY_CAL, task_data);
return 0;
}
int cmd::handle_battery_print_vbat(unsigned short argc) {
if (argc != 1) {
#ifdef ERROR
if (_logger != nullptr) {
_logger->error("BATTERY_PRINT_VBAT expects no arguments");
}
#endif
return 1;
}
#ifdef INFO
double vbat;
vbat_global_read(vbat);
if (_logger != nullptr) {
_logger->info("VBAT: " + String(vbat));
}
#endif
}
int cmd::handle_unknown_command(unsigned short argc, char *argv[]) { int cmd::handle_unknown_command(unsigned short argc, char *argv[]) {
#ifdef ERROR #ifdef ERROR
if (_logger != nullptr) { if (_logger != nullptr) {
@@ -404,6 +453,12 @@ int cmd::dispatch_command(command_id command, unsigned short argc, char *argv[])
case CMD_DISPLAY_DRIVER_PRIMARY: case CMD_DISPLAY_DRIVER_PRIMARY:
return this->handle_display_driver_primary(argc); return this->handle_display_driver_primary(argc);
case CMD_BATTERY_CAL:
return this->handle_battery_cal(argc, argv);
case CMD_BATTERY_PRINT_VBAT:
return this->handle_battery_print_vbat(argc);
case CMD_UNKNOWN: case CMD_UNKNOWN:
default: default:
return this->handle_unknown_command(argc, argv); return this->handle_unknown_command(argc, argv);

View File

@@ -25,6 +25,8 @@ private:
CMD_TRACK_AUTODETECT, CMD_TRACK_AUTODETECT,
CMD_DISPLAY_GPS_DEBUG, CMD_DISPLAY_GPS_DEBUG,
CMD_DISPLAY_DRIVER_PRIMARY, CMD_DISPLAY_DRIVER_PRIMARY,
CMD_BATTERY_CAL,
CMD_BATTERY_PRINT_VBAT,
}; };
HardwareSerial *_data_stream; HardwareSerial *_data_stream;
@@ -53,6 +55,8 @@ private:
int handle_track_autodetect_command(unsigned short argc); int handle_track_autodetect_command(unsigned short argc);
int handle_display_gps_debug(unsigned short argc); int handle_display_gps_debug(unsigned short argc);
int handle_display_driver_primary(unsigned short argc); int handle_display_driver_primary(unsigned short argc);
int handle_battery_cal(unsigned short argc, char *argv[]);
int handle_battery_print_vbat(unsigned short argc);
int handle_unknown_command(unsigned short argc, char *argv[]); int handle_unknown_command(unsigned short argc, char *argv[]);
public: public:

View File

@@ -8,9 +8,7 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
int config::push(const Task &task) { int config::push(const Task &task) { return _queue.push(task); }
return _queue.push(task);
}
int config::task_complete() { int config::task_complete() {
_task_memory_stale = true; _task_memory_stale = true;
@@ -101,6 +99,11 @@ int config::reset_cfg() {
return this->write_cfg(); return this->write_cfg();
} }
int config::write_vbat_cal(double val) {
_config.vbat_calibration = val;
return this->write_cfg();
}
config::config() : _logger(nullptr), _valid_config(true) {} config::config() : _logger(nullptr), _valid_config(true) {}
config::config(system_logger *logger) : _logger(logger), _valid_config(true) {} config::config(system_logger *logger) : _logger(logger), _valid_config(true) {}
@@ -121,6 +124,7 @@ int config::write_cfg() {
_logger->info("Config updated and saved to EEPROM"); _logger->info("Config updated and saved to EEPROM");
} }
#endif #endif
router::send(MOD_ALL, TASK_ALL_CONFIG_UPDATED);
return 0; return 0;
} }
@@ -215,7 +219,6 @@ int config::handle_active_task(unsigned long timeout_ms) {
} }
this->task_complete(); this->task_complete();
return 0; return 0;
} }
case TASK_CONFIG_WRITE_TEMP_TRACK: { case TASK_CONFIG_WRITE_TEMP_TRACK: {
@@ -236,6 +239,13 @@ int config::handle_active_task(unsigned long timeout_ms) {
return res; return res;
} }
case TASK_CONFIG_VBAT_CAL_SET: {
double cal_value;
memcpy(&cal_value, &_active_task.data, sizeof(double));
int res = this->write_vbat_cal(cal_value);
this->task_complete();
}
default: default:
break; break;
} }

View File

@@ -47,6 +47,7 @@ private:
int write_track_from_temp(); int write_track_from_temp();
int delete_track(unsigned short idx); int delete_track(unsigned short idx);
int reset_cfg(); int reset_cfg();
int write_vbat_cal(double val);
public: public:
int push(const Task &task) override; int push(const Task &task) override;