Files
WII5Firmware/WII5Battery.cpp
T
scottp 295abb37ee Initial public release of WII5 Buoy firmware
Firmware for an autonomous wave-measurement buoy (ATmega2560-based
WII5 v2 board). Reads wave motion from a Sparton AHRS-M1/M2 IMU,
samples GPS and battery state, and reports back over Iridium SBD
satellite telemetry. Originally developed 2012-2024.

This is the first public release. Code, documentation, and field-tested
operating modes (Capture, Sleep, Position, ManualTest, SelfTest,
LowBattery) are licensed under Apache 2.0 — see LICENSE and NOTICE.

See README.md for an overview and build instructions, CONTRIBUTING.md
for how to contribute, and DEPLOYMENTS.md for the field-deployment log.
2026-05-07 16:27:18 +10:00

200 lines
5.6 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2012-2024 Scott Penrose <scottp@dd.com.au> and WII5 Buoy contributors
//
// This file is part of WII5 Buoy firmware.
// See LICENSE for full terms.
/**
* @file WII5Battery.cpp
* @brief Battery monitor: voltage sampling, running average, and threshold logic.
*/
/*
WII5Battery
*/
#include <Arduino.h>
#include <WII5Battery.h>
#include <WII5Sh3dConsole.h>
#include <TimeLib.h>
void WII5Battery::begin() {
// ??? powerSetPin(POWER_BATTERY_PIN, POWER_IMU_SERIAL_ON, POWER_BATTERY_PIN_OFF);
#ifdef BATTERY_1_VOLTS_PIN
pinMode(BATTERY_1_VOLTS_PIN, OUTPUT);
digitalWrite(BATTERY_1_VOLTS_PIN, LOW);
#endif
#ifdef BATTERY_1_VOLTS_ANALOG
pinMode(BATTERY_1_VOLTS_ANALOG, INPUT);
#endif
#ifdef BATTERY_2_VOLTS_ANALOG
pinMode(BATTERY_2_VOLTS_ANALOG, INPUT);
#endif
// Set the age high... never got it.
age = WII5TIME_1WEEK * 1000;
// Start by getting the voltage as early as possible
step = WII5BATTERY_ON; stepWait = 0; stepCount = 0;
};
bool WII5Battery::isRunning() {
return (step != WII5BATTERY_OFF);
}
void WII5Battery::start(bool force) {
step = WII5BATTERY_ON; stepWait = 300000; stepCount = 0;
}
void WII5Battery::stop(bool force) {
step = WII5BATTERY_OFF; stepWait = 0; stepCount = 0;
}
uint16_t WII5Battery::scale(uint16_t data, uint16_t d) {
return int(0 + (float)data * (float)((float)d / 1000));
}
uint32_t WII5Battery::scale(uint32_t data, uint32_t d) {
return (uint32_t)(0 + (float)data * (float)((float)d / 1000));
}
void WII5Battery::loop() {
// Check timeouts (e.g. how long blocked low voltage?)
// Testing Voltage Mode
switch (step) {
case WII5BATTERY_OFF:
// TODO step counter
// TIMEOUT - Not applicable
// off();
// Hard coded every 5 minutes for now
if (stepWait > 300000) {
step = WII5BATTERY_ON; stepWait = 0; stepCount = 0;
}
break;
case WII5BATTERY_ON:
digitalWrite(BATTERY_1_VOLTS_PIN, HIGH);
// on();
avgBattery1.reset();
avgBattery2.reset();
step = WII5BATTERY_MEASURE; stepWait = 0; stepCount = 0;
break;
case WII5BATTERY_MEASURE:
// How many should we measure?
if (stepCount > 100) { // TODO Hard coded?
step = WII5BATTERY_STORE; stepWait = 0; stepCount = 0;
}
else {
#ifdef BATTERY_1_VOLTS_ANALOG
// Should we scale n ow or later?
uint16_t in = analogRead(BATTERY_1_VOLTS_ANALOG);
avgBattery1.checkAndAddReading(scale((uint16_t) in, (uint16_t)BATTERY_1_VOLTS_MULT));
#endif
#ifdef BATTERY_2_VOLTS_ANALOG
// avgBattery2.checkAndAddReading(scale((uint16_t) analogRead(BATTERY_2_VOLTS_ANALOG), (uint16_t)BATTERY_2_VOLTS_MULT);
#endif
}
break;
case WII5BATTERY_STORE:
// TODO Where do we store this?
// - Current Metadata - sure - useful
// - SD card or SPIMemory - be nice?
// console.log(LOG_DEBUG, F("BATTERY: Storage not yet implemented"));
// TODO Check this is decivolts !
// TODO can we use openLogs etc to write log to disk
// #ifdef BATTERY_2_VOLTS_ANALOG
//int(avgBattery2.getMean() * 100);
// #endif
value = int(avgBattery1.getMean());
age = 0;
step = WII5BATTERY_ANALYSE; stepWait = 0; stepCount = 0;
break;
case WII5BATTERY_ANALYSE:
if (
(value < wii5Config.getBatteryLow())
&& (wii5Controller.getMode() != WII5MODE_LOWBATTERY)
) {
console.log(LOG_INFO, F("Low Battery detected V=%d, Low=%d, Mid=%d"),
value, wii5Config.getBatteryLow(), wii5Config.getBatteryMid()
);
wii5Controller.setMode(WII5MODE_LOWBATTERY);
}
else if (
(value > wii5Config.getBatteryMid())
&& (wii5Controller.getMode() == WII5MODE_LOWBATTERY)
) {
console.log(LOG_INFO, F("Mid Battery detected V=%d, Low=%d, Mid=%d"),
value, wii5Config.getBatteryLow(), wii5Config.getBatteryMid()
);
wii5Controller.setDefaultMode();
}
#ifdef BATTERY_1_VOLTS_ANALOG
wii5Display.atDataSend(
F("battery1"),
F("volts=%d,swing=%d,min=%d,max=%d"),
int(avgBattery1.getMean()),
int(avgBattery1.getStd()),
int(avgBattery1.getMin()),
int(avgBattery1.getMax())
);
#endif
#ifdef BATTERY_2_VOLTS_ANALOG
// TODO
console.printf(F("# battery: #=2 mean=%d +-%d min=%d max=%d\r\n"),
// avgAccelZ.getN(),
int(avgBattery2.getMean()),
int(avgBattery2.getStd()),
int(avgBattery2.getMin()),
int(avgBattery2.getMax())
);
#endif
wii5Display.atCommandSend(F("status"), F("voltage=%ld"),
wii5Battery.value
);
wii5Display.atCommandSend(F("status"), F("update"));
/*
RULES:
* Valid date tinme ?
* Check date time not too far future, and not in past
* Batter 2 - work out which to use (not this release)
* Confidition of battery - how long it has been on this average etc
if (
// Low Battery
(TOO LOW)
// Disabled still
&& (wii5Config.getDisableLowBattery() > now()
) {
}
*/
step = WII5BATTERY_FINISH; stepWait = 0; stepCount = 0;
break;
case WII5BATTERY_FINISH:
digitalWrite(BATTERY_1_VOLTS_PIN, LOW);
step = WII5BATTERY_OFF; stepWait = 0; stepCount = 0;
break;
default:
console.log(LOG_FATAL, F("BATTERY: Default step... step=%d"), step);
step = WII5BATTERY_OFF; stepWait = 0; stepCount = 0;
break;
}
stepCount++;
return;
}
WII5Battery wii5Battery;