1
+ #include "common.h"
2
+
3
+ #ifdef USE_BATTERY_MOD
4
+
5
+ #include "battery.h"
6
+ #include "ha/esp_zigbee_ha_standard.h"
7
+ #include "tools.h"
8
+ #include "zcl/esp_zigbee_zcl_power_config.h"
9
+
10
+ static const char * TAG = "ESP_ZB_BATT" ;
11
+
12
+ #include "esp_adc/adc_cali.h"
13
+ #include "esp_adc/adc_cali_scheme.h"
14
+ #include "esp_adc/adc_oneshot.h"
15
+ #include "soc/soc_caps.h"
16
+
17
+ #define ADC_CHANNEL ADC_CHANNEL_0
18
+ #define ADC_ATTEN ADC_ATTEN_DB_12
19
+
20
+ static bool adc_calibration_init (adc_unit_t unit , adc_channel_t channel , adc_atten_t atten , adc_cali_handle_t * out_handle );
21
+ static void adc_calibration_deinit (adc_cali_handle_t handle );
22
+
23
+ adc_cali_handle_t adc1_cali_chan0_handle = NULL ;
24
+
25
+ adc_oneshot_unit_handle_t adc1_handle ;
26
+
27
+ int adc_raw ;
28
+ float battery_voltage ;
29
+ int battery_millivolts ;
30
+
31
+ int64_t last_battery_measurement_time = 0 ;
32
+
33
+ bool do_calibration1_chan0 ;
34
+
35
+ void batteryUpdate (void ) {
36
+ batterySetup ();
37
+ batteryReadVolts ();
38
+ batteryPercentage ();
39
+ }
40
+
41
+ void batterySetup (void ) {
42
+ ESP_LOGI (TAG , "Setup ADC" );
43
+
44
+ adc_oneshot_unit_init_cfg_t init_config1 = {
45
+ .unit_id = ADC_UNIT_1 ,
46
+ };
47
+ ESP_ERROR_CHECK (adc_oneshot_new_unit (& init_config1 , & adc1_handle ));
48
+
49
+ adc_oneshot_chan_cfg_t config = {
50
+ .atten = ADC_ATTEN ,
51
+ .bitwidth = ADC_BITWIDTH_DEFAULT ,
52
+ };
53
+ ESP_ERROR_CHECK (adc_oneshot_config_channel (adc1_handle , ADC_CHANNEL , & config ));
54
+
55
+ do_calibration1_chan0 = adc_calibration_init (ADC_UNIT_1 , ADC_CHANNEL , ADC_ATTEN , & adc1_cali_chan0_handle );
56
+ }
57
+
58
+ void batteryReadVolts () {
59
+ int adc = 0 , sample = 0 , count = 10 ;
60
+
61
+ ESP_ERROR_CHECK (adc_oneshot_read (adc1_handle , ADC_CHANNEL , & adc_raw )); //one blank measurement for stabilization
62
+
63
+ while (sample < count ) {
64
+ ESP_ERROR_CHECK (adc_oneshot_read (adc1_handle , ADC_CHANNEL , & adc_raw ));
65
+ // ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, ADC_CHANNEL, adc_raw);
66
+ adc += adc_raw ;
67
+ sample ++ ;
68
+ }
69
+
70
+ int adc_avg = adc / count ;
71
+
72
+ ESP_LOGI (TAG , "ADC%d Channel[%d] Raw Data: %d" , ADC_UNIT_1 + 1 , ADC_CHANNEL , adc_avg );
73
+
74
+ if (do_calibration1_chan0 ) {
75
+ ESP_ERROR_CHECK (adc_cali_raw_to_voltage (adc1_cali_chan0_handle , adc_avg , & battery_millivolts ));
76
+ // ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw, &battery_millivolts));
77
+ ESP_LOGI (TAG , "ADC%d Channel[%d] Cali Voltage: %d mV" , ADC_UNIT_1 + 1 , ADC_CHANNEL , battery_millivolts );
78
+ battery_millivolts = battery_millivolts * 2 ; // divider
79
+ battery_voltage = battery_millivolts / 1000.0 ;
80
+
81
+ last_battery_measurement_time = millis ();
82
+ ESP_LOGW (TAG , "LAST READ BATT %d millis" , (int )last_battery_measurement_time );
83
+ }
84
+
85
+ ESP_ERROR_CHECK (adc_oneshot_del_unit (adc1_handle ));
86
+ if (do_calibration1_chan0 ) {
87
+ adc_calibration_deinit (adc1_cali_chan0_handle );
88
+ }
89
+ }
90
+
91
+ void batteryPercentage (void ) {
92
+
93
+ // 0% 3.2v
94
+ // 100% 4.2v
95
+
96
+ uint8_t percentage = 0 ;
97
+ if (battery_voltage < 3.2 ) {
98
+ percentage = 0 ;
99
+ } else if (battery_voltage > 4.1 ) {
100
+ percentage = 100 ;
101
+ } else {
102
+ percentage = (uint8_t )(((battery_voltage - 3.2f ) / (4.2f - 3.2f )) * 100 );
103
+ // percentage = (uint8_t)((battery_voltage - 3.2) * 100 / 2.5);
104
+ }
105
+
106
+ ESP_LOGI (TAG , "vIN: %.3f, percentage: %d" , battery_voltage , percentage );
107
+ percentage = percentage * 2 ; // zigbee scale
108
+ uint8_t r_state = 0 ;
109
+ esp_zb_zcl_status_t status = esp_zb_zcl_set_attribute_val (HA_ENDPOINT , ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG , ESP_ZB_ZCL_CLUSTER_SERVER_ROLE , ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID , & percentage , false);
110
+ if (status != ESP_ZB_ZCL_STATUS_SUCCESS ) {
111
+ ESP_LOGE (TAG , "Setting ON_OFF for CH%d attribute failed!" , 0 );
112
+ }
113
+ }
114
+
115
+ static void adc_calibration_deinit (adc_cali_handle_t handle ) {
116
+ #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
117
+ ESP_LOGI (TAG , "deregister %s calibration scheme" , "Curve Fitting" );
118
+ ESP_ERROR_CHECK (adc_cali_delete_scheme_curve_fitting (handle ));
119
+
120
+ #elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
121
+ ESP_LOGI (TAG , "deregister %s calibration scheme" , "Line Fitting" );
122
+ ESP_ERROR_CHECK (adc_cali_delete_scheme_line_fitting (handle ));
123
+ #endif
124
+ }
125
+
126
+ static bool adc_calibration_init (adc_unit_t unit , adc_channel_t channel , adc_atten_t atten , adc_cali_handle_t * out_handle ) {
127
+
128
+ adc_cali_handle_t handle = NULL ;
129
+ esp_err_t ret = ESP_FAIL ;
130
+ bool calibrated = false;
131
+
132
+ #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
133
+ if (!calibrated ) {
134
+ ESP_LOGI (TAG , "calibration scheme version is %s" , "Curve Fitting" );
135
+ adc_cali_curve_fitting_config_t cali_config = {
136
+ .unit_id = unit ,
137
+ .chan = channel ,
138
+ .atten = atten ,
139
+ .bitwidth = ADC_BITWIDTH_DEFAULT ,
140
+ };
141
+ ret = adc_cali_create_scheme_curve_fitting (& cali_config , & handle );
142
+ if (ret == ESP_OK ) {
143
+ calibrated = true;
144
+ }
145
+ }
146
+ #endif
147
+
148
+ #if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
149
+ if (!calibrated ) {
150
+ ESP_LOGI (TAG , "calibration scheme version is %s" , "Line Fitting" );
151
+ adc_cali_line_fitting_config_t cali_config = {
152
+ .unit_id = unit ,
153
+ .atten = atten ,
154
+ .bitwidth = ADC_BITWIDTH_DEFAULT ,
155
+ };
156
+ ret = adc_cali_create_scheme_line_fitting (& cali_config , & handle );
157
+ if (ret == ESP_OK ) {
158
+ calibrated = true;
159
+ }
160
+ }
161
+ #endif
162
+
163
+ * out_handle = handle ;
164
+ if (ret == ESP_OK ) {
165
+ ESP_LOGI (TAG , "Calibration Success" );
166
+ } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated ) {
167
+ ESP_LOGW (TAG , "eFuse not burnt, skip software calibration" );
168
+ } else {
169
+ ESP_LOGE (TAG , "Invalid arg or no memory" );
170
+ }
171
+
172
+ return calibrated ;
173
+ }
174
+
175
+ #endif
0 commit comments