205 lines
5.8 KiB
C
205 lines
5.8 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#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;
|
|
}
|
|
|