diff --git a/include/ADCconf.h b/include/ADCconf.h new file mode 100644 index 0000000..4e3c576 --- /dev/null +++ b/include/ADCconf.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Arduino.h" +#include "esp_adc/adc_continuous.h" + +class ADC_BME { + private: + uint32_t _FRAME_SIZE; + uint32_t _POOL_SIZE; + uint32_t _HZ_ADC; + adc_channel_t _channel; + uint8_t* _dma_buffer; + volatile bool dma_data_ready = false; + adc_continuous_handle_t handle_ADC = NULL; + static bool IRAM_ATTR adc_dma_callback(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data); + public: + void config(const uint32_t muestras_bloque, adc_channel_t channel, const uint32_t hz_adc, uint8_t* dma_buffer); + void setup(); + uint32_t read(uint16_t* samples_buffer); +}; diff --git a/src/ADCconf.cpp b/src/ADCconf.cpp new file mode 100644 index 0000000..9c5def0 --- /dev/null +++ b/src/ADCconf.cpp @@ -0,0 +1,94 @@ +#include "ADCconf.h" + +bool IRAM_ATTR ADC_BME::adc_dma_callback(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data){ + ADC_BME* adc =static_cast(user_data); + adc->dma_data_ready = true; + return false; +} + +void ADC_BME::config(const uint32_t muestras_bloque, adc_channel_t channel, const uint32_t hz_adc, uint8_t* dma_buffer){ + _FRAME_SIZE=muestras_bloque*4; + _POOL_SIZE=_FRAME_SIZE*4; + _channel=channel; + _HZ_ADC=hz_adc; + _dma_buffer=dma_buffer; +} + +void ADC_BME::setup(){ + adc_continuous_handle_cfg_t ADC_config = { + .max_store_buf_size = _POOL_SIZE, + .conv_frame_size = _FRAME_SIZE, + }; + ESP_ERROR_CHECK(adc_continuous_new_handle(&ADC_config, &handle_ADC)); + + adc_digi_pattern_config_t channel_config = {0}; + channel_config.channel = _channel; + channel_config.atten = ADC_ATTEN_DB_12; + channel_config.bit_width = ADC_BITWIDTH_12; + channel_config.unit = ADC_UNIT_1; + + adc_continuous_config_t adc_config = { + .pattern_num = 1, + .adc_pattern = &channel_config, + .sample_freq_hz = _HZ_ADC, + .conv_mode = ADC_CONV_SINGLE_UNIT_1, + }; + + ESP_ERROR_CHECK(adc_continuous_config(handle_ADC, &adc_config)); + + adc_continuous_evt_cbs_t cb_config = { + .on_conv_done = adc_dma_callback, + .on_pool_ovf = NULL + }; + + ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(handle_ADC, &cb_config, this)); + ESP_ERROR_CHECK(adc_continuous_start(handle_ADC)); + Serial.println("DMA Iniciado con sistema de bandera."); +} + +uint32_t ADC_BME::read(uint16_t* samples_buffer) { + + if (!dma_data_ready) { + return 0; + } + + dma_data_ready = false; + uint32_t ret_num = 0; + + // Leer datos DMA + esp_err_t ret = adc_continuous_read(handle_ADC,_dma_buffer,_FRAME_SIZE,&ret_num,0); + + if (ret != ESP_OK) + return 0; + + // Buffer temporal parseado + adc_continuous_data_t parsed_data[_FRAME_SIZE/4]; + + uint32_t parsed_count = 0; + + // Parsear datos + esp_err_t parse_ret = + adc_continuous_parse_data( + handle_ADC, + _dma_buffer, + ret_num, + parsed_data, + &parsed_count + ); + + if (parse_ret != ESP_OK) { + return 0; + } + + uint32_t valid_samples = 0; + // Copiar muestras limpias + for (uint32_t i = 0; i < parsed_count; i++) { + if (!parsed_data[i].valid) + continue; + + samples_buffer[valid_samples] = parsed_data[i].raw_data; + valid_samples++; + } + + return valid_samples; +} diff --git a/src/main.cpp b/src/main.cpp index 0155449..00f1798 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,19 @@ #include "Arduino.h" #include "freertos/ringbuf.h" -//DEBUG -uint8_t i_debug[10] = {0,1,2,3,4,5,6,7,8,9}; -const uint16_t SIZE_BUFFER = 1024; +#include "ADCconf.h" + +// API ESP-IDF para ADC modo continuo (uso de DMA) +#define MS_BLOQUE 10 +adc_channel_t CHANNEL = ADC_CHANNEL_3; +const uint32_t HZ_ADC = 1000; // Limitado a 611 - 83333 para el ESP32-S3 +const uint32_t MUESTRAS_BLOQUE = (HZ_ADC * MS_BLOQUE) / 1000; +uint8_t dma_buffer[MUESTRAS_BLOQUE * SOC_ADC_DIGI_RESULT_BYTES] = {0}; +uint16_t samples_buffer[MUESTRAS_BLOQUE] = {0}; +const uint32_t SIZE_BUFFER = MUESTRAS_BLOQUE*10; + +ADC_BME adc1_3; + // FreeRTOS TaskHandle_t ADCTaskHandle = NULL; TaskHandle_t WebSocketTaskHandle = NULL; @@ -15,6 +25,9 @@ void WebSocketTask(void *parameter); void setup(){ Serial.begin(230400); + adc1_3.config(MUESTRAS_BLOQUE, CHANNEL, HZ_ADC, dma_buffer); + adc1_3.setup(); + //Iniciar el buffer circular if (bufferHandle == NULL) { Serial.printf("Failed to create ring buffer!"); @@ -22,7 +35,7 @@ void setup(){ } xTaskCreatePinnedToCore( ADCTask, "ADCTask", 10000, NULL, 1, &ADCTaskHandle, 0); - xTaskCreatePinnedToCore( WebSocketTask, "WebSocketTask", 10000, NULL, 1, &WebSocketTaskHandle, 0); + xTaskCreatePinnedToCore( WebSocketTask, "WebSocketTask", 10000, NULL, 1, &WebSocketTaskHandle, 1); } void loop(){ @@ -30,8 +43,11 @@ void loop(){ void ADCTask(void *parameter){ for(;;) { - if (xRingbufferSend(bufferHandle, i_debug, sizeof(i_debug), pdMS_TO_TICKS(1000)) != pdTRUE) { - Serial.println("Failed to send message to ring buffer!"); + uint32_t count = adc1_3.read(samples_buffer); + if (count > 0) { + if (xRingbufferSend(bufferHandle, samples_buffer, count * sizeof(uint16_t), pdMS_TO_TICKS(1000)) != pdTRUE) { + Serial.println("Failed to send message to ring buffer!"); + } } vTaskDelay(pdMS_TO_TICKS(10)); } @@ -40,12 +56,13 @@ void ADCTask(void *parameter){ void WebSocketTask(void *parameter){ for(;;) { size_t receivedMessageSize; - uint8_t* receivedMessage = (uint8_t*)xRingbufferReceive(bufferHandle, &receivedMessageSize, pdMS_TO_TICKS(1000)); + uint16_t* receivedMessage = (uint16_t*)xRingbufferReceive(bufferHandle, &receivedMessageSize, pdMS_TO_TICKS(1000)); // 6. Check if the receive operation was successful if (receivedMessage != NULL) { - for(size_t i = 0; i < receivedMessageSize; i++) { - Serial.printf("%d ", receivedMessage[i]);} + size_t samples = receivedMessageSize / sizeof(uint16_t); + for(size_t i = 0; i < samples; i++) { + Serial.printf("%u ", receivedMessage[i]);} Serial.println(); vRingbufferReturnItem(bufferHandle, (void*)receivedMessage); } else {