This program lets you read the Battery voltage from the Glyph C3
To allow this first short the MSR pads at the bottom.
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));
}
}