From f2a1730a8df693350aef14aa6df6f563ffe6f786 Mon Sep 17 00:00:00 2001 From: Timm Date: Sat, 8 Jun 2024 09:50:05 +0200 Subject: [PATCH] feat: Add INA219 battery sensor (#2380) * specify specific pip version wich works with zmq install * add INA219 sensor * average measurement for more accurate results. Use supply voltage for measurement. * Revert "specify specific pip version wich works with zmq install" This reverts commit 48dd1bfc6c73f9a6fb1329ae6528e495b07b36e5. * correct format * Update src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/__init__.py Co-authored-by: s-martin * Update copyright notice * Update license * Update license * Document the INA219 * add error handling and type safety * Update batterymonitor.md * Update __init__.py * fix markdown lint for batterymonitor.md * fix markdown lint batterymonitor.md * Update documentation/builders/components/power/batterymonitor.md Co-authored-by: s-martin * Update documentation/builders/components/power/batterymonitor.md Co-authored-by: s-martin --------- Co-authored-by: Timm Co-authored-by: s-martin --- .../components/power/batterymonitor.md | 59 +++++++++++++++++-- .../batt_mon_i2c_ina219/__init__.py | 56 ++++++++++++++++++ 2 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/__init__.py diff --git a/documentation/builders/components/power/batterymonitor.md b/documentation/builders/components/power/batterymonitor.md index d57e14acb..151010caa 100644 --- a/documentation/builders/components/power/batterymonitor.md +++ b/documentation/builders/components/power/batterymonitor.md @@ -1,13 +1,15 @@ -# Battery Monitor based on a ADS1015 +# Battery Monitor > [!CAUTION] > Lithium and other batteries are dangerous and must be treated with care. > Rechargeable Lithium Ion batteries are potentially hazardous and can -> present a serious **FIRE HAZARD** if damaged, defective or improperly used. -> Do not use this circuit to a lithium ion battery without expertise and -> training in handling and use of batteries of this type. +> present a serious **FIRE HAZARD** if damaged, defective, or improperly used. +> Do not use this circuit for a lithium-ion battery without the expertise and +> training in handling and using batteries of this type. > Use appropriate test equipment and safety protocols during development. -> There is no warranty, this may not work as expected or at all! +> There is no warranty, this may not work as expected! + +## Battery Monitor based on a ADS1015 The script in [src/jukebox/components/battery_monitor/batt_mon_i2c_ads1015/\_\_init\_\_.py](../../../../src/jukebox/components/battery_monitor/batt_mon_i2c_ads1015/__init__.py) is intended to read out the voltage of a single Cell LiIon Battery using a [CY-ADS1015 Board](https://www.adafruit.com/product/1083): @@ -31,3 +33,50 @@ The script in [src/jukebox/components/battery_monitor/batt_mon_i2c_ads1015/\_\_i > > * the circuit is constantly draining the battery! (leak current up to: 2.1µA) > * the time between sample needs to be a minimum 1sec with this high impedance voltage divider don't use the continuous conversion method! + +## Battery Monitor based on an INA219 + +The script in [src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/\_\_init\_\_.py](../../../../src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/__init__.py) is intended to read out the voltage of a single cell or multiple LiIon Battery using a [INA219 Board](https://www.adafruit.com/product/904): + +```text + 3.3V + + + | + .----o----. + | | SDA + .-------------------------------o AIN o------ + | | INA219 | SCL + | .----------o AOUT o------ + --- | | | + Battery - Regulator + Raspi '----o----' + 2.9V-4.2V| | | + | | | + === === === +``` + +## Configuration example + +The battery monitoring is configured in the jukebox.yml file. + +The "battmon" module has to be added to the modules setting. + +```yaml +modules: + named: + # Do not change the order! + publishing: publishing + ... + battmon: battery_monitor.batt_mon_i2c_ina219 +``` + +The battmon module needs further configuration: + +```yaml +battmon: + scale_to_phy_num: 1 + scale_to_phy_denom: 0 + warning_action: + all_clear_action: +``` + +The setting "scale_to_phy_denom" does not influence the INA219. However, the scale can be adjusted to fit multiple LiIon cells. diff --git a/src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/__init__.py b/src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/__init__.py new file mode 100644 index 000000000..c9b51eece --- /dev/null +++ b/src/jukebox/components/battery_monitor/batt_mon_i2c_ina219/__init__.py @@ -0,0 +1,56 @@ +# RPi-Jukebox-RFID Version 3 +# Copyright (c) See file LICENSE in project root folder + +import logging +import jukebox.plugs as plugs +import jukebox.cfghandler +from ina219 import INA219 +from ina219 import DeviceRangeError +from components.battery_monitor import BatteryMonitorBase + +logger = logging.getLogger('jb.battmon.ina219') + +batt_mon = None + + +class battmon_ina219(BatteryMonitorBase.BattmonBase): + '''Battery Monitor based on a INA219 + + See [Battery Monitor documentation](../../builders/components/power/batterymonitor.md) + ''' + + def __init__(self, cfg): + super().__init__(cfg, logger) + + def init_batt_mon_hw(self, num: float, denom: float) -> None: + try: + self.adc = INA219(float(num) / 1000, busnum=1) + self.adc.configure(self.adc.RANGE_16V, self.adc.GAIN_AUTO, self.adc.ADC_32SAMP, self.adc.ADC_32SAMP) + except DeviceRangeError as e: + logger.error(f"Device range error: {e}") + raise + except Exception as e: + logger.error(f"Failed to initialize INA219: {e}") + raise + + def get_batt_voltage(self) -> int: + try: + batt_voltage_mV = self.adc.supply_voltage() * 1000.0 + return int(batt_voltage_mV) + except Exception as e: + logger.error(f"Failed to get supply voltage from INA219: {e}") + raise + + +@plugs.finalize +def finalize(): + global batt_mon + cfg = jukebox.cfghandler.get_handler('jukebox') + batt_mon = battmon_ina219(cfg) + plugs.register(batt_mon, name='batt_mon') + + +@plugs.atexit +def atexit(**ignored_kwargs): + global batt_mon + batt_mon.status_thread.cancel()