-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathbettery.c
executable file
·130 lines (108 loc) · 4.49 KB
/
bettery.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "Debug.h"
#include "battery.h"
#include "hal_adc.h"
#include "utils.h"
#include "OSAL.h"
#include "zcl.h"
#include "zcl_general.h"
#include "bdb_interface.h"
// (( 3 * 1.15 ) / (( 2^14 / 2 ) - 1 )) * 1000 (not correct)
// #define MULTI (float) 0.4211939934
// this coefficient calculated using
// https://docs.google.com/spreadsheets/d/1qrFdMTo0ZrqtlGUoafeB3hplhU3GzDnVWuUK4M9OgNo/edit?usp=sharing
#define MULTI (float)0.443
#define VOLTAGE_MIN 2.0
#define VOLTAGE_MAX 3.3
#ifndef ZCL_BATTERY_REPORT_INTERVAL
#define ZCL_BATTERY_REPORT_INTERVAL ((uint32) 1800000) //30 minutes
#endif
#ifndef ZCL_BATTERY_REPORT_DELAY
#define ZCL_BATTERY_REPORT_DELAY 5 * 1000
#endif
#ifndef ZCL_BATTERY_REPORT_REPORT_CONVERTER
#define ZCL_BATTERY_REPORT_REPORT_CONVERTER(millivolts) getBatteryRemainingPercentageZCLCR2032(millivolts)
#endif
#define POWER_CFG ZCL_CLUSTER_ID_GEN_POWER_CFG
#define ZCL_BATTERY_REPORT_EVT 0x0001
uint8 zclBattery_Voltage = 0xff;
uint8 zclBattery_PercentageRemainig = 0xff;
uint16 zclBattery_RawAdc = 0xff;
uint8 getBatteryVoltageZCL(uint16 millivolts) {
uint8 volt8 = (uint8)(millivolts / 100);
if ((millivolts - (volt8 * 100)) > 50) {
return volt8 + 1;
} else {
return volt8;
}
}
// return millivolts
uint16 getBatteryVoltage(void) {
HalAdcSetReference(HAL_ADC_REF_125V);
zclBattery_RawAdc = adcReadSampled(HAL_ADC_CHANNEL_VDD, HAL_ADC_RESOLUTION_14, HAL_ADC_REF_125V, 10);
return (uint16)(zclBattery_RawAdc * MULTI);
}
uint8 getBatteryRemainingPercentageZCL(uint16 millivolts) { return (uint8)mapRange(VOLTAGE_MIN, VOLTAGE_MAX, 0.0, 200.0, millivolts); }
uint8 getBatteryRemainingPercentageZCLCR2032(uint16 volt16) {
float battery_level;
if (volt16 >= 3000) {
battery_level = 100;
} else if (volt16 > 2900) {
battery_level = 100 - ((3000 - volt16) * 58) / 100;
} else if (volt16 > 2740) {
battery_level = 42 - ((2900 - volt16) * 24) / 160;
} else if (volt16 > 2440) {
battery_level = 18 - ((2740 - volt16) * 12) / 300;
} else if (volt16 > 2100) {
battery_level = 6 - ((2440 - volt16) * 6) / 340;
} else {
battery_level = 0;
}
return (uint8)(battery_level * 2);
}
void zclBattery_Report(void) {
uint16 millivolts = getBatteryVoltage();
zclBattery_Voltage = getBatteryVoltageZCL(millivolts);
zclBattery_PercentageRemainig = ZCL_BATTERY_REPORT_REPORT_CONVERTER(millivolts);
LREP("Battery voltageZCL=%d prc=%d voltage=%d\r\n", zclBattery_Voltage, zclBattery_PercentageRemainig, millivolts);
#if BDB_REPORTING
bdb_RepChangedAttrValue(1, POWER_CFG, ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING);
#else
const uint8 NUM_ATTRIBUTES = 3;
zclReportCmd_t *pReportCmd;
pReportCmd = osal_mem_alloc(sizeof(zclReportCmd_t) + (NUM_ATTRIBUTES * sizeof(zclReport_t)));
if (pReportCmd != NULL) {
pReportCmd->numAttr = NUM_ATTRIBUTES;
pReportCmd->attrList[0].attrID = ATTRID_POWER_CFG_BATTERY_VOLTAGE;
pReportCmd->attrList[0].dataType = ZCL_DATATYPE_UINT8;
pReportCmd->attrList[0].attrData = (void *)(&zclBattery_Voltage);
pReportCmd->attrList[1].attrID = ATTRID_POWER_CFG_BATTERY_PERCENTAGE_REMAINING;
pReportCmd->attrList[1].dataType = ZCL_DATATYPE_UINT8;
pReportCmd->attrList[1].attrData = (void *)(&zclBattery_PercentageRemainig);
pReportCmd->attrList[2].attrID = ATTRID_POWER_CFG_BATTERY_VOLTAGE_RAW_ADC;
pReportCmd->attrList[2].dataType = ZCL_DATATYPE_UINT16;
pReportCmd->attrList[2].attrData = (void *)(&zclBattery_RawAdc);
afAddrType_t inderect_DstAddr = {.addrMode = (afAddrMode_t)AddrNotPresent, .endPoint = 0, .addr.shortAddr = 0};
zcl_SendReportCmd(1, &inderect_DstAddr, POWER_CFG, pReportCmd, ZCL_FRAME_CLIENT_SERVER_DIR, TRUE, bdb_getZCLFrameCounter());
}
osal_mem_free(pReportCmd);
#endif
}
uint8 zclBattery_TaskId = 0;
void zclBattery_Init(uint8 task_id) {
zclBattery_TaskId = task_id;
#if BDB_REPORTING
osal_start_reload_timer(zclBattery_TaskId, ZCL_BATTERY_REPORT_EVT, ZCL_BATTERY_REPORT_INTERVAL);
#endif
}
uint16 zclBattery_event_loop(uint8 task_id, uint16 events) {
LREP("zclBattery_event_loop 0x%X\r\n", events);
if (events & ZCL_BATTERY_REPORT_EVT) {
LREPMaster("ZCL_BATTERY_REPORT_EVT\r\n");
zclBattery_Report();
return (events ^ ZCL_BATTERY_REPORT_EVT);
}
return 0;
}
void zclBattery_HandleKeys(uint8 portAndAction, uint8 keyCode) {
osal_start_timerEx(zclBattery_TaskId, ZCL_BATTERY_REPORT_EVT, ZCL_BATTERY_REPORT_DELAY);
}