battery properties (#903)
* Battery params * move category * cleanup * use property * fix level * fix battery computation * fix level comp * docs
This commit is contained in:
		
							
								
								
									
										47
									
								
								docs/reference/brick/battery-property.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								docs/reference/brick/battery-property.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					# battery Property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Return the information about the battery
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sig
 | 
				
			||||||
 | 
					brick.batteryInfo(BatteryProperty.Level)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* property: the kind of information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Returns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* a [number](/types/number) which represents the value of the property requested.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Show the battery level percentage on the screen. Also, show a green light if the battery level is above 15%. If the battery level is below 15% but above 5%, show a orange light. But, if the battery level is below 5%, show a pulsing red light.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```blocks
 | 
				
			||||||
 | 
					let battery = 0;
 | 
				
			||||||
 | 
					forever(function() {
 | 
				
			||||||
 | 
					    brick.showString("Battery level:", 1)
 | 
				
			||||||
 | 
					    brick.showNumber(battery, 2)
 | 
				
			||||||
 | 
					    battery = brick.batteryInfo(BatteryProperty.Level);
 | 
				
			||||||
 | 
					    if (battery > 15)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        brick.setStatusLight(StatusLight.Green);
 | 
				
			||||||
 | 
					    } else if (battery > 5) {
 | 
				
			||||||
 | 
					        brick.setStatusLight(StatusLight.Orange);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        brick.setStatusLight(StatusLight.RedPulse)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pause(30000)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Or see all the values
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```blocks
 | 
				
			||||||
 | 
					forever(function () {
 | 
				
			||||||
 | 
					    brick.showValue("bat V", brick.batteryInfo(BatteryProperty.Voltage), 1)
 | 
				
			||||||
 | 
					    brick.showValue("bat %", brick.batteryInfo(BatteryProperty.Level), 2)
 | 
				
			||||||
 | 
					    brick.showValue("bat I", brick.batteryInfo(BatteryProperty.Current), 3)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
@@ -1,13 +1,40 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					const enum BatteryProperty {
 | 
				
			||||||
 | 
					    //% level (%)
 | 
				
			||||||
 | 
					    Level,
 | 
				
			||||||
 | 
					    //% block="current (I)"
 | 
				
			||||||
 | 
					    Current,
 | 
				
			||||||
 | 
					    //% block="voltage (V)"
 | 
				
			||||||
 | 
					    Voltage
 | 
				
			||||||
 | 
					} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace brick {
 | 
					namespace brick {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns the current battery level
 | 
					     * Returns the current battery level
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    //% blockId=brickBatteryLevel block="battery level"
 | 
					    //% blockId=brickBatteryLevel block="battery level"
 | 
				
			||||||
    //% group="More"
 | 
					    //% group="Battery"
 | 
				
			||||||
    //% help=brick/battery-level
 | 
					    //% help=brick/battery-level
 | 
				
			||||||
 | 
					    //% deprecated blockHidden=1
 | 
				
			||||||
    export function batteryLevel(): number {
 | 
					    export function batteryLevel(): number {
 | 
				
			||||||
        const info = sensors.internal.getBatteryInfo();
 | 
					        const info = sensors.internal.getBatteryInfo();
 | 
				
			||||||
        return info.current;
 | 
					        return info.level;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns information about the battery
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    //% blockId=brickBatteryProperty block="battery %property"
 | 
				
			||||||
 | 
					    //% group="Battery"
 | 
				
			||||||
 | 
					    //% help=brick/battery-property
 | 
				
			||||||
 | 
					    export function batteryInfo(property: BatteryProperty): number {
 | 
				
			||||||
 | 
					        const info = sensors.internal.getBatteryInfo();
 | 
				
			||||||
 | 
					        switch(property) {
 | 
				
			||||||
 | 
					            case BatteryProperty.Level: return info.level;
 | 
				
			||||||
 | 
					            case BatteryProperty.Current: return info.Ibatt;
 | 
				
			||||||
 | 
					            case BatteryProperty.Voltage: return info.Vbatt;
 | 
				
			||||||
 | 
					            default: return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -36,8 +36,17 @@ namespace sensors.internal {
 | 
				
			|||||||
    let analogMM: MMap
 | 
					    let analogMM: MMap
 | 
				
			||||||
    let uartMM: MMap
 | 
					    let uartMM: MMap
 | 
				
			||||||
    let IICMM: MMap
 | 
					    let IICMM: MMap
 | 
				
			||||||
 | 
					    let powerMM: MMap
 | 
				
			||||||
    let devcon: Buffer
 | 
					    let devcon: Buffer
 | 
				
			||||||
    let sensorInfos: SensorInfo[]
 | 
					    let sensorInfos: SensorInfo[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let batteryInfo: {
 | 
				
			||||||
 | 
					        CinCnt: number;
 | 
				
			||||||
 | 
					        CoutCnt: number;
 | 
				
			||||||
 | 
					        VinCnt: number;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let batteryVMin: number;
 | 
				
			||||||
 | 
					    let batteryVMax: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class SensorInfo {
 | 
					    class SensorInfo {
 | 
				
			||||||
        port: number
 | 
					        port: number
 | 
				
			||||||
@@ -71,10 +80,13 @@ namespace sensors.internal {
 | 
				
			|||||||
        IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
 | 
					        IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
 | 
				
			||||||
        if (!IICMM) control.fail("no iic sensor")
 | 
					        if (!IICMM) control.fail("no iic sensor")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsafePollForChanges(500, 
 | 
					        powerMM = control.mmap("/dev/lms_power", 2, 0)
 | 
				
			||||||
            () => { return hashDevices(); }, 
 | 
					
 | 
				
			||||||
            (prev, curr) => { detectDevices(); 
 | 
					        unsafePollForChanges(500,
 | 
				
			||||||
        });
 | 
					            () => { return hashDevices(); },
 | 
				
			||||||
 | 
					            (prev, curr) => {
 | 
				
			||||||
 | 
					                detectDevices();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        sensorInfos.forEach(info => {
 | 
					        sensorInfos.forEach(info => {
 | 
				
			||||||
            unsafePollForChanges(50, () => {
 | 
					            unsafePollForChanges(50, () => {
 | 
				
			||||||
                if (info.sensor) return info.sensor._query()
 | 
					                if (info.sensor) return info.sensor._query()
 | 
				
			||||||
@@ -82,9 +94,8 @@ namespace sensors.internal {
 | 
				
			|||||||
            }, (prev, curr) => {
 | 
					            }, (prev, curr) => {
 | 
				
			||||||
                if (info.sensor) info.sensor._update(prev, curr)
 | 
					                if (info.sensor) info.sensor._update(prev, curr)
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })        
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    export function getActiveSensors(): Sensor[] {
 | 
					    export function getActiveSensors(): Sensor[] {
 | 
				
			||||||
        init();
 | 
					        init();
 | 
				
			||||||
@@ -110,18 +121,130 @@ namespace sensors.internal {
 | 
				
			|||||||
        return manufacturer + sensorType;
 | 
					        return manufacturer + sensorType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    export function getBatteryInfo(): { temp: number; current: number } {
 | 
					    const ADC_REF = 5000                  //!< [mV]  maximal value on ADC
 | 
				
			||||||
        init();
 | 
					    const ADC_RES = 4095                  //!< [CNT] maximal count on ADC
 | 
				
			||||||
        return {
 | 
					    // see c_ui.c
 | 
				
			||||||
            temp: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryTemp),
 | 
					    const SHUNT_IN = 0.11              //  [Ohm]
 | 
				
			||||||
            current: Math.round(analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent) / 10)
 | 
					    const AMP_CIN = 22.0              //  [Times]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const EP2_SHUNT_IN = 0.05              //  [Ohm]
 | 
				
			||||||
 | 
					    const EP2_AMP_CIN = 15.0              //  [Times]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const SHUNT_OUT = 0.055             //  [Ohm]
 | 
				
			||||||
 | 
					    const AMP_COUT = 19.0              //  [Times]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const VCE = 0.05              //  [V]
 | 
				
			||||||
 | 
					    const AMP_VIN = 0.5               //  [Times]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const AVR_CIN = 300
 | 
				
			||||||
 | 
					    const AVR_COUT = 30
 | 
				
			||||||
 | 
					    const AVR_VIN = 30
 | 
				
			||||||
 | 
					    // lms2012
 | 
				
			||||||
 | 
					    const BATT_INDICATOR_HIGH = 7500          //!< Battery indicator high [mV]
 | 
				
			||||||
 | 
					    const BATT_INDICATOR_LOW = 6200          //!< Battery indicator low [mV]
 | 
				
			||||||
 | 
					    const ACCU_INDICATOR_HIGH = 7500          //!< Rechargeable battery indicator high [mV]
 | 
				
			||||||
 | 
					    const ACCU_INDICATOR_LOW = 7100          //!< Rechargeable battery indicator low [mV]    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function CNT_V(C: number) {
 | 
				
			||||||
 | 
					        return ((C * ADC_REF) / (ADC_RES * 1000.0))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function updateBatteryInfo() {
 | 
				
			||||||
 | 
					        let CinCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent);
 | 
				
			||||||
 | 
					        let CoutCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.MotorCurrent);
 | 
				
			||||||
 | 
					        let VinCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.Cell123456);
 | 
				
			||||||
 | 
					        if (!batteryInfo) {
 | 
				
			||||||
 | 
					            batteryVMin = BATT_INDICATOR_LOW;
 | 
				
			||||||
 | 
					            batteryVMax = BATT_INDICATOR_HIGH;
 | 
				
			||||||
 | 
					            if (powerMM) {
 | 
				
			||||||
 | 
					                const accu = powerMM.getNumber(NumberFormat.UInt8LE, 0);
 | 
				
			||||||
 | 
					                if (accu > 0) {
 | 
				
			||||||
 | 
					                    control.dmesg("rechargeable battery")
 | 
				
			||||||
 | 
					                    batteryVMin = ACCU_INDICATOR_LOW;
 | 
				
			||||||
 | 
					                    batteryVMax = ACCU_INDICATOR_HIGH;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            batteryInfo = { 
 | 
				
			||||||
 | 
					                CinCnt: CinCnt, 
 | 
				
			||||||
 | 
					                CoutCnt: CoutCnt,
 | 
				
			||||||
 | 
					                VinCnt: VinCnt
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            // update in background
 | 
				
			||||||
 | 
					            control.runInParallel(() => forever(updateBatteryInfo)); 
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            CinCnt = batteryInfo.CinCnt = ((batteryInfo.CinCnt * (AVR_CIN - 1)) + CinCnt) / AVR_CIN;
 | 
				
			||||||
 | 
					            CoutCnt = batteryInfo.CoutCnt = ((batteryInfo.CoutCnt * (AVR_COUT - 1)) + CoutCnt) / AVR_COUT;
 | 
				
			||||||
 | 
					            VinCnt = batteryInfo.VinCnt = ((batteryInfo.VinCnt * (AVR_VIN - 1)) + VinCnt) / AVR_VIN;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export function getBatteryInfo(): { 
 | 
				
			||||||
 | 
					        level: number; 
 | 
				
			||||||
 | 
					        Ibatt: number, 
 | 
				
			||||||
 | 
					        Vbatt: number, 
 | 
				
			||||||
 | 
					        Imotor: number 
 | 
				
			||||||
 | 
					    } {
 | 
				
			||||||
 | 
					        init();
 | 
				
			||||||
 | 
					        if (!batteryInfo) updateBatteryInfo();
 | 
				
			||||||
 | 
					        const CinCnt = batteryInfo.CinCnt;
 | 
				
			||||||
 | 
					        const CoutCnt = batteryInfo.CoutCnt;
 | 
				
			||||||
 | 
					        const VinCnt = batteryInfo.VinCnt;
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					void      cUiUpdatePower(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef Linux_X86
 | 
				
			||||||
 | 
					  DATAF   CinV;
 | 
				
			||||||
 | 
					  DATAF   CoutV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((UiInstance.Hw == FINAL) || (UiInstance.Hw == FINALB))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    CinV                =  CNT_V(UiInstance.CinCnt) / AMP_CIN;
 | 
				
			||||||
 | 
					    UiInstance.Vbatt    =  (CNT_V(UiInstance.VinCnt) / AMP_VIN) + CinV + VCE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UiInstance.Ibatt    =  CinV / SHUNT_IN;
 | 
				
			||||||
 | 
					    CoutV               =  CNT_V(UiInstance.CoutCnt) / AMP_COUT;
 | 
				
			||||||
 | 
					    UiInstance.Imotor   =  CoutV / SHUNT_OUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    CinV                =  CNT_V(UiInstance.CinCnt) / EP2_AMP_CIN;
 | 
				
			||||||
 | 
					    UiInstance.Vbatt    =  (CNT_V(UiInstance.VinCnt) / AMP_VIN) + CinV + VCE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UiInstance.Ibatt    =  CinV / EP2_SHUNT_IN;
 | 
				
			||||||
 | 
					    UiInstance.Imotor   =  0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef DEBUG_TEMP_SHUTDOWN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  UiInstance.Vbatt  =  7.0;
 | 
				
			||||||
 | 
					  UiInstance.Ibatt  =  5.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}        
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					       const CinV = CNT_V(CinCnt) / AMP_CIN;
 | 
				
			||||||
 | 
					       const Vbatt = CNT_V(VinCnt) / AMP_VIN + CinV + VCE;
 | 
				
			||||||
 | 
					       const Ibatt = CinV / SHUNT_IN;
 | 
				
			||||||
 | 
					       const CoutV = CNT_V(CoutCnt) / AMP_COUT;
 | 
				
			||||||
 | 
					       const Imotor = CoutV / SHUNT_OUT;
 | 
				
			||||||
 | 
					       const level   = Math.max(0, Math.min(100, Math.floor((Vbatt * 1000.0 - batteryVMin)
 | 
				
			||||||
 | 
					        / (batteryVMax - batteryVMin) * 100)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            level: level,
 | 
				
			||||||
 | 
					            Vbatt: Vbatt,
 | 
				
			||||||
 | 
					            Ibatt: Ibatt,
 | 
				
			||||||
 | 
					            Imotor: Imotor
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function hashDevices(): number {
 | 
					    function hashDevices(): number {
 | 
				
			||||||
        const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
 | 
					        const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
 | 
				
			||||||
        let r = 0;
 | 
					        let r = 0;
 | 
				
			||||||
        for(let i = 0; i < conns.length; ++i) {
 | 
					        for (let i = 0; i < conns.length; ++i) {
 | 
				
			||||||
            r = (r << 8 | conns[i]);
 | 
					            r = (r << 8 | conns[i]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return r;
 | 
					        return r;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
//% color="#68C3E2" weight=100 icon="\uf106"
 | 
					//% color="#68C3E2" weight=100 icon="\uf106"
 | 
				
			||||||
//% groups='["Buttons", "Screen"]'
 | 
					//% groups='["Buttons", "Screen", "Battery"]'
 | 
				
			||||||
//% labelLineWidth=60
 | 
					//% labelLineWidth=60
 | 
				
			||||||
namespace brick {
 | 
					namespace brick {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user