Подключение датчика направления ветра CYC-FX1-KV-A1 Печать
Добавил(а) microsin   

Датчик направления ветра CYC-FX1-KV-A1 (производства китайской компании WUHAN CHENYUN Technology Co., Ltd) представляет собой свободно поворачивающийся флюгер с аналоговым токовым выходом.

CYC FX1 KV A1 common view

Питается датчик от постоянного напряжения DC 9V .. 30V, и подключается тремя проводами:

Красный DC 9V .. 30V
Желтый Выходной сигнал
Черный Общий провод, GND

Ток на выходе датчика пропорционален углу поворота флюгера: 4 .. 20 мА в зависимости от угла поворота 0 .. 359 градусов. От угла поворота также зависит потребляемый ток: например, при напряжении питания 12V максимальный потребляемый ток составит около 26 мА.

Чтобы подключить выход датчика к АЦП микроконтроллера, его выход нужно нагрузить на постоянный резистор. В случае АЦП микроконтроллера ESP32-C3 номинал этого резистора должен быть 120 Ом, тогда максимальное напряжение на входе АЦП получится 2.4V, что при ослаблении на входе 11 db как раз будет попадать в диапазон 0 .. 2.5V (см. [1]).

Схема подключения датчика к каналу A0 (GPIO0) микроконтроллера ESP32-C3:

CYC FX1 KV A1 connect ESP32 C3

Код опроса датчика CYC-FX1-KV-A1:

#include "esp_log.h"
#include "esp_err.h"
#include "esp_adc/adc_oneshot.h"
#include "adcapp.h"
#include "pins.h"
#include "task_priorities.h"
#include "nvsapp.h"

static const char *TAG = "adcapp";
static adc_oneshot_unit_handle_t adc1_handle; // Дескриптор АЦП
bool adc_test_enabled = false;

// Функция считывания сырого значения ADC из входа GPIO0 esp_err_t get_adc_gpio0_raw(int *raw) {
esp_err_t ret;
do
{
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1, // Используем модуль ADC1
.ulp_mode = ADC_ULP_MODE_DISABLE, // Отключаем режим ULP (для
// простых задач не нужен)
};
// Конфигурация канала АЦП
adc_oneshot_chan_cfg_t config = {
.atten = ADC_ATTEN_DB_12, // Ослабление 12 дБ (диапазон 0 мВ - 2500 мВ)
.bitwidth = ADC_BITWIDTH_DEFAULT, // Используем разрядность по умолчанию (12 бит)
}; // Инициализируем блок АЦП
ret = adc_oneshot_new_unit(&init_config1, &adc1_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Ошибка инициализации модуля АЦП: %s", esp_err_to_name(ret));
break;
}

// Настраиваем конкретный канал (ADC_CHANNEL_0 на ADC1)
ret = adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_0, &config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Ошибка настройки канала: %s", esp_err_to_name(ret));
break;
}

ESP_LOGI(TAG, "АЦП инициализирован. Начинаем чтение с ADC1_CHANNEL_0...");
// Производим одиночное измерение
ret = adc_oneshot_read(adc1_handle, ADC_CHANNEL_0, raw);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Ошибка чтения АЦП: %s", esp_err_to_name(ret));
}
adc_oneshot_del_unit(adc1_handle);
}while(false);

return ret; }

static void adcTask(void *pvParameters) {
int imin, imax;
imin = 65535;
imax = 0;
printf("ADC test started\n");
while(adc_test_enabled)
{
int raw;
esp_err_t ret = get_adc_gpio0_raw(&raw);
if (ret == ESP_OK) {
ESP_LOGI(TAG, "ADC1_CHANNEL_0: %d", raw);
if (raw < imin) imin = raw;
if (raw > imax) imax = raw;
uint16_t deg = map_to_degree_float(raw, a0min, a0max);
//uint16_t deg = map_to_degree_optimized(raw, a0min, a0max);
printf("\r%4d a0min=%4d a0max=%4d град=%3u", raw, imin, imax, deg);
}
vTaskDelay(pdMS_TO_TICKS(100));
}
vTaskDelete(NULL); }

void adc_test_start(void) {
adc_test_enabled = true;
esp_log_level_set("gpio", ESP_LOG_ERROR); // Только ошибки
esp_log_level_set("adcapp", ESP_LOG_ERROR); // Только ошибки
xTaskCreate(&adcTask, "adcTask", 4096, NULL, PRIORITY_ADC_TEST, NULL); }

void adc_test_stop(void) {
adc_test_enabled = false; }

В этом примере применен драйвер режима однократного чтения АЦП (one shot mode). Сырое значение, считываемое с АЦП, масштабируется в значения 0° .. 360° с помощью функции map_to_degree_float. Значения a0min и a0max соответствуют значениям, считанным с канала A0 АЦП при токе 4 мА и 20 мА соответственно.

uint16_t map_to_degree_float(uint16_t value, uint16_t a0min, uint16_t a0max) {
    if (value <= a0min) return 0;
    if (value >= a0max) return 359;
    
    float result = (float)(value - a0min) * 359.0f / (float)(a0max - a0min);
    return (uint16_t)(result + 0.5f); // Округление до ближайшего
}

[Ссылки]

1. ESP32-C3: работа со встроенным АЦП.