From a595cb59fec86d403991ef7f2ff745fad80e01ee Mon Sep 17 00:00:00 2001 From: Carlos Pereira Atencio Date: Fri, 15 Nov 2024 16:09:12 +0000 Subject: [PATCH] Add feature to log voltage into the datalog. --- README.md | 28 +++++++++++++++++--- source/main.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 33a34a6..c76c80c 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,37 @@ # BBC micro:bit V2 Battery Voltage Measurement -A C++ example project showing how to measure the BBC micro:bit V2 battery +A micro:bit C++ project showing how to measure the BBC micro:bit V2 battery voltage. -This project measures the input voltage, in millivolts, from the nRF52833 -microcontroller and prints it on the display and serial. +This project measures the input voltage, in millivolts, of the nRF52833 +microcontroller. It shows the value on the micro:bit display and also sends +it via serial. -A prebuilt hex file can be download from the +It's important to note that the battery voltage is not exactly the same +as the microcontroller input voltage, as there is some +[safety circuitry](https://github.com/microbit-foundation/microbit-v2-hardware) +between the battery and the microcontroller that will produce a small voltage +drop. + +A prebuilt hex file can be downloaded from the [GitHub Releases page](https://github.com/microbit-foundation/microbit-v2-battery-voltage/releases). A similar example for micro:bit V1 can be found in: https://os.mbed.com/teams/microbit/code/microbit-battery-test/ +## Logging the voltage + +If the button A is pressed (keep it pressed until the text stops scrolling and +all display LEDs are on), the battery voltage will be logged into the +[data log](https://microbit.org/get-started/user-guide/data-logging/). + +The voltage is logged once per minute, and when the log is full +(it should take over 5 days) a cross will be displayed and the programme will +stop running. + +The data-log can then be accessed by connecting the micro:bit to a computer +and opening the `MY_DATA.HTM` file inside the `MICROBIT` USB drive. + ## How is the battery voltage measured To measure the micro:bit battery voltage, the nRF52833 (the target MCU) diff --git a/source/main.cpp b/source/main.cpp index 6040402..5077caf 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,6 +2,8 @@ MicroBit uBit; +// Configures the interval (in seconds) between battery voltage logs +static size_t LOGGING_INTERVAL_SECS = 60; // The ADC channel to be used for the battery voltage measurement static int BATTERY_ADC_CHANNEL = -1; @@ -70,6 +72,69 @@ static void vdd_adc_init() { (void)get_vdd_millivolts(); } +/** + * Log the battery voltage every minute. + * + * The logging interval is set by the LOGGING_INTERVAL_SECS global variable. + * Once the log is full, a cross is displayed on the LED matrix and the program + * stops running. + */ +static void log_battery_voltage() { + // First turn on all display LEDS on + for (int row = 0; row < 5; row++) { + for (int col = 0; col < 5; col++) { + uBit.display.image.setPixelValue(row, col, 255); + } + } + + // Configure data logging and clear any previous data + uBit.log.setSerialMirroring(false); + uBit.log.setTimeStamp(TimeStampFormat::Seconds); + uBit.log.clear(false); + uBit.log.setVisibility(true); + + // Read the battery voltage every second, average it over 60 seconds and log it + const size_t BUFFER_SIZE = LOGGING_INTERVAL_SECS; + int voltages[BUFFER_SIZE] = {0}; + size_t voltages_index = 0; + + uint32_t next_log_time = uBit.systemTime(); + while (!uBit.log.isFull()) { + while (uBit.systemTime() < next_log_time); + next_log_time += LOGGING_INTERVAL_SECS * 1000; + + voltages[voltages_index] = get_vdd_millivolts(); + voltages_index++; + + if (voltages_index >= BUFFER_SIZE) { + voltages_index = 0; + int voltage_sum = 0; + for (size_t i = 0; i < BUFFER_SIZE; i++) { + voltage_sum += voltages[i]; + } + int voltage_average = voltage_sum / BUFFER_SIZE; + + uBit.log.beginRow(); + uBit.log.logData("mV", ManagedString(voltage_average)); + uBit.log.endRow(); + } + } + + // Log storage is full, show a cross on the display + const MicroBitImage IMG_CROSS( + "255,000,000,000,255\n" + "000,255,000,255,000\n" + "000,000,255,000,000\n" + "000,255,000,255,000\n" + "255,000,000,000,255\n" + ); + uBit.display.print(IMG_CROSS); + while (true) { + uBit.sleep(1000); + } +} + + int main() { uBit.init(); @@ -81,6 +146,11 @@ int main() { uBit.serial.send(battery_mv + "\r\n"); uBit.display.scroll(battery_mv); + // On button A enter into a mode where the battery voltage into logged once per minute + if (uBit.buttonA.isPressed()) { + log_battery_voltage(); + } + uBit.sleep(1000); } }