battery properties (#903)

* Battery params

* move category

* cleanup

* use property

* fix level

* fix battery computation

* fix level comp

* docs
This commit is contained in:
Peli de Halleux 2019-09-04 12:56:45 -07:00 committed by GitHub
parent 1317da8904
commit 87a65aa38f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 214 additions and 17 deletions

View 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)
})
```

View File

@ -1,13 +1,40 @@
const enum BatteryProperty {
//% level (%)
Level,
//% block="current (I)"
Current,
//% block="voltage (V)"
Voltage
}
namespace brick {
/**
* Returns the current battery level
*/
//% blockId=brickBatteryLevel block="battery level"
//% group="More"
//% group="Battery"
//% help=brick/battery-level
//% deprecated blockHidden=1
export function batteryLevel(): number {
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;
}
}
}

View File

@ -36,8 +36,17 @@ namespace sensors.internal {
let analogMM: MMap
let uartMM: MMap
let IICMM: MMap
let powerMM: MMap
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 {
port: number
@ -71,10 +80,13 @@ namespace sensors.internal {
IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
if (!IICMM) control.fail("no iic sensor")
unsafePollForChanges(500,
() => { return hashDevices(); },
(prev, curr) => { detectDevices();
});
powerMM = control.mmap("/dev/lms_power", 2, 0)
unsafePollForChanges(500,
() => { return hashDevices(); },
(prev, curr) => {
detectDevices();
});
sensorInfos.forEach(info => {
unsafePollForChanges(50, () => {
if (info.sensor) return info.sensor._query()
@ -82,9 +94,8 @@ namespace sensors.internal {
}, (prev, curr) => {
if (info.sensor) info.sensor._update(prev, curr)
})
})
}
})
}
export function getActiveSensors(): Sensor[] {
init();
@ -110,18 +121,130 @@ namespace sensors.internal {
return manufacturer + sensorType;
}
export function getBatteryInfo(): { temp: number; current: number } {
init();
return {
temp: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryTemp),
current: Math.round(analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent) / 10)
const ADC_REF = 5000 //!< [mV] maximal value on ADC
const ADC_RES = 4095 //!< [CNT] maximal count on ADC
// see c_ui.c
const SHUNT_IN = 0.11 // [Ohm]
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 {
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let r = 0;
for(let i = 0; i < conns.length; ++i) {
for (let i = 0; i < conns.length; ++i) {
r = (r << 8 | conns[i]);
}
return r;

View File

@ -1,6 +1,6 @@
//% color="#68C3E2" weight=100 icon="\uf106"
//% groups='["Buttons", "Screen"]'
//% groups='["Buttons", "Screen", "Battery"]'
//% labelLineWidth=60
namespace brick {
}