/* * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_timer.h" #include "soc/soc_caps.h" #include "esp_log.h" #include "esp_adc/adc_oneshot.h" #include "esp_adc/adc_cali.h" #include "esp_adc/adc_cali_scheme.h" #include "adc_measure.h" #include "modbus.h" const static char *TAG = "Adc measure"; #define ADC_V_UNIT ADC_UNIT_2 #define ADC_V_CHAN ADC_CHANNEL_0 #define ADC_IL_UNIT ADC_UNIT_1 #define ADC_IL_CHAN ADC_CHANNEL_4 #define ADC_IR_UNIT ADC_UNIT_1 #define ADC_IR_CHAN ADC_CHANNEL_5 #define ADC_ATTEN ADC_ATTEN_DB_11 /* 衰减决定了可测量电压的范围 */ #define ADC_MEASURE_LOOP_PERIOD_MS 100 /* ADC采样时间周期 */ static adc_oneshot_unit_handle_t adc1_handle; static adc_oneshot_unit_handle_t adc2_handle; static adc_cali_handle_t adc1_cali_handle; static adc_cali_handle_t adc2_cali_handle; typedef struct { uint16_t v_raw; uint16_t i_l_raw; uint16_t i_r_raw; uint16_t v; uint16_t i_l; uint16_t i_r; } adc_measure_data_t; /* gWordVar寄存器组对应到adc_measure_data_t的各个结构 */ adc_measure_data_t *adc_measure_data = (adc_measure_data_t *)&gWordVar[20]; static void adc_measure_loop_cb(void *args) { int v_raw, i_l_raw, i_r_raw; int v, i_l, i_r; adc_measure_one(0, &v_raw, &v); adc_measure_one(1, &i_l_raw, &i_l); adc_measure_one(2, &i_r_raw, &i_r); adc_measure_data->v_raw = (short)v_raw; adc_measure_data->i_l_raw = (short)i_l_raw; adc_measure_data->i_r_raw = (short)i_r_raw; adc_measure_data->v = (short)v; adc_measure_data->i_l = (short)i_l; adc_measure_data->i_r = (short)i_r; // ESP_LOGI(TAG, "v_raw = %d, i_l_raw = %d, i_r_raw = %d", v_raw, i_l_raw, i_r_raw); // ESP_LOGI(TAG, "v = %d, i_l = %d, i_r = %d", v, i_l , i_r); } void adc_measure_init(void) { ESP_LOGI(TAG, "adc_measure_init"); /* 创建ADC unit1的句柄 */ adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = ADC_UNIT_1, }; ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); /* 创建ADC unit2的句柄 */ adc_oneshot_unit_init_cfg_t init_config2 = { .unit_id = ADC_UNIT_2, .ulp_mode = ADC_ULP_MODE_DISABLE, }; ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config2, &adc2_handle)); /* 通道配置 */ adc_oneshot_chan_cfg_t config = { .bitwidth = ADC_BITWIDTH_DEFAULT, .atten = ADC_ATTEN, }; /* 修正:这里并没有用宏 */ ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, ADC_V_CHAN, &config)); ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_IL_CHAN, &config)); ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_IR_CHAN, &config)); /* 校正配置 */ esp_err_t ret = ESP_FAIL; adc_cali_curve_fitting_config_t cali_config = { .unit_id = ADC_UNIT_1, .atten = ADC_ATTEN, .bitwidth = ADC_BITWIDTH_DEFAULT, }; ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_handle); if (ret == ESP_OK) { ESP_LOGI(TAG, "ADC1 Calibration Success"); } else { ESP_LOGI(TAG, "ADC1 Calibration Fault"); adc1_cali_handle = NULL; } cali_config.unit_id = ADC_UNIT_2; ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc2_cali_handle); if (ret == ESP_OK) { ESP_LOGI(TAG, "ADC2 Calibration Success"); } else { ESP_LOGI(TAG, "ADC2 Calibration Fault"); adc2_cali_handle = NULL; } /* 定时测量 */ ESP_LOGI(TAG, "Create a timer to do ADC measure"); const esp_timer_create_args_t periodic_timer_args = { .callback = adc_measure_loop_cb, .arg = NULL, .name = "adc_measure_loop" }; esp_timer_handle_t adc_measure_loop_timer = NULL; ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &adc_measure_loop_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(adc_measure_loop_timer, ADC_MEASURE_LOOP_PERIOD_MS * 1000)); } /* id=0测量电压 id=1测量电流L id=2测量电流R */ int adc_measure_one(int id, int *raw, int *v) { int adc_raw; int voltage; /* mv */ int adc_unit = 0; int adc_channel = 0; adc_oneshot_unit_handle_t adc_unit_handle = NULL; adc_cali_handle_t adc_cali_handle = NULL; switch (id) { case 0: adc_unit = ADC_V_UNIT; adc_channel = ADC_V_CHAN; break; case 1: adc_unit = ADC_IL_UNIT; adc_channel = ADC_IL_CHAN; break; case 2: adc_unit = ADC_IR_UNIT; adc_channel = ADC_IR_CHAN; break; default: ESP_LOGE(TAG, "Invalid id: %d", id); return -1; } if (adc_unit == ADC_UNIT_1) { adc_unit_handle = adc1_handle; adc_cali_handle = adc1_cali_handle; } else if (adc_unit == ADC_UNIT_2) { adc_unit_handle = adc2_handle; adc_cali_handle = adc2_cali_handle; } /* 读原始数据 */ ESP_ERROR_CHECK(adc_oneshot_read(adc_unit_handle, adc_channel, &adc_raw)); // ESP_LOGI(TAG, "id: %d Raw Data: %d", id, adc_raw); /* 校正 */ if (adc_cali_handle){ ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc_cali_handle, adc_raw, &voltage)); // ESP_LOGI(TAG, "id: %d Cali Voltage: %d", id, voltage); } if (raw != NULL) *raw = adc_raw; if (v != NULL) *v = voltage; return voltage; } /* 修正:存在溢出风险 */ int adc_measure_avg(int id, int times) { long long avg = 0; int i = 0; for (i = 0; i < times; i++) avg += adc_measure_one(id, NULL, NULL); avg /= times; return avg; }