Skip to content

Latest commit

 

History

History
103 lines (78 loc) · 2.83 KB

File metadata and controls

103 lines (78 loc) · 2.83 KB

Read Battery Voltage

This program lets you read the Battery voltage from the Glyph C3

To allow this first short the MSR pads at the bottom.

Circuit

ckt

Code

use esp_idf_svc::hal::prelude::*;
use esp_idf_svc::hal::adc::oneshot::{AdcDriver, AdcChannelDriver, config::AdcChannelConfig};
use esp_idf_svc::hal::adc::attenuation::DB_11;
use esp_idf_svc::hal::adc::ADC1;
use esp_idf_svc::hal::gpio::{Gpio0, PinDriver}; // Added PinDriver
use std::thread;
use std::time::Duration;

pub struct BatteryMonitor<'a> {
    adc: &'a AdcDriver<'a, ADC1>,
    pin: AdcChannelDriver<'a, Gpio0, &'a AdcDriver<'a, ADC1>>,
}

impl<'a> BatteryMonitor<'a> {
    pub fn new(
        adc: &'a AdcDriver<'a, ADC1>, 
        pin: AdcChannelDriver<'a, Gpio0, &'a AdcDriver<'a, ADC1>>
    ) -> Self {
        Self { adc, pin }
    }

    // Returns (Percentage, Voltage, Raw_ADC_Value)
    pub fn get_status(&mut self) -> (u8, f32, u16) {
        let raw_value = self.adc.read(&mut self.pin).unwrap_or(0);

        // 1. Convert Raw to Voltage at Pin (0-2.5V range)
        let voltage_pin = (raw_value as f32 / 4095.0) * 2.5; 
        
        // 2. Convert to Battery Voltage
        // HYPOTHESIS: The divider is 1/4 (e.g. 300k/100k)
        let voltage_bat = voltage_pin * 4.0;

        let percentage = if voltage_bat >= 4.2 {
            100
        } else if voltage_bat <= 3.0 {
            0
        } else {
            ((voltage_bat - 3.0) / (4.2 - 3.0) * 100.0) as u8
        };

        (percentage, voltage_bat, raw_value)
    }
}

fn main() -> anyhow::Result<()> {
    esp_idf_svc::sys::link_patches();
    esp_idf_svc::log::EspLogger::initialize_default();

    let peripherals = Peripherals::take()?;

    log::info!("Starting Battery Monitor with LED...");

    let adc = AdcDriver::new(peripherals.adc1)?;

    let config = AdcChannelConfig {
        attenuation: DB_11,
        ..Default::default()
    };

    let adc_pin = AdcChannelDriver::new(&adc, peripherals.pins.gpio0, &config)?;
    let mut monitor = BatteryMonitor::new(&adc, adc_pin);

    // --- LED SETUP ---
    // GPIO 8 is standard for Onboard LED on C3 SuperMini/Glyph
    let mut led = PinDriver::output(peripherals.pins.gpio1)?;

    loop {
        let (pct, volts, raw) = monitor.get_status();
        log::info!("Bat: {}% | Volts: {:.2}V | Raw: {}", pct, volts, raw);
        
        // --- LED LOGIC ---
        // Note: Onboard LEDs are usually "Active Low" (0 = ON, 1 = OFF)
        if pct > 70 {
            // High Battery -> Solid ON
            led.set_high()?; 
        } else if pct < 50 {
            // Low Battery -> Blink
            led.toggle()?;
        } else {
            // Medium Battery (50-70%) -> OFF
            led.set_low()?;
        }
        
        // Loop every 500ms for a nice blinking speed
        thread::sleep(Duration::from_millis(500));
    }
}