Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8041

General • ADC + DMA + FreeRTOS does not work.

$
0
0
I have the following code, which represents a task, it works perfectly if used outside of freeRTOS, but in RTOS it does not obtain any value from the ADC, I have tried several alternatives, and I no longer know if the code is wrong to activate the ADC with DMA or if it is a failure related to the presence of freeRTOS.

Code:

#include "FreeRTOS.h"#include "task.h"#include "semphr.h"#include "queue.h"#include "hardware/vreg.h"#include "hardware/adc.h"#include "hardware/dma.h"#include "inc/neopixel.h"#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include "inc/magnectostriccao.h"#include "tasks_paramiters.h"#include "task_adc_with_dma.h"// buffer de texto para o display oledextern char text_line_oled[max_text_lines][max_text_columns];// buffer de amostragem do ADC, microfone que coleta o audio// os samples devem ser no comprimento equivalente aos segundos// necessários para uma amostragem adequadauint16_t adc_buffer[SAMPLES];QueueHandle_t adc_Buffer_Semaphore;static uint dma_channel;static dma_channel_config dma_cfg;void task_adc_with_dma(void *pvParameters){  (void)pvParameters;  printf("Task ADC DMA\n");  // O código abaixo deve ser transportado para a TASK (FreeRTOS) que  // faz o processamento da amostragem via DMA  adc_gpio_init(MIC_PIN);  adc_init();  adc_select_input(MIC_CHANNEL);  adc_fifo_setup(      true,  // Habilitar FIFO      true,  // Habilitar request de dados do DMA      1,     // Threshold para ativar request DMA é 1 leitura do ADC      false, // Não usar bit de erro      false  // Não fazer downscale das amostras para 8-bits, manter 12-bits.  );  adc_set_clkdiv(ADC_CLOCK_DIV);  // Tomando posse de canal do DMA.  dma_channel = dma_claim_unused_channel(true);  // Configurações do DMA.  dma_cfg = dma_channel_get_default_config(dma_channel);  channel_config_set_transfer_data_size(&dma_cfg, DMA_SIZE_16); // Tamanho da transferência é 16-bits (usamos uint16_t para armazenar valores do ADC)  channel_config_set_read_increment(&dma_cfg, false);           // Desabilita incremento do ponteiro de leitura (lemos de um único registrador)  channel_config_set_write_increment(&dma_cfg, true);           // Habilita incremento do ponteiro de escrita (escrevemos em um array/buffer)  channel_config_set_dreq(&dma_cfg, DREQ_ADC); // Usamos a requisição de dados do ADC  adc_Buffer_Semaphore = xSemaphoreCreateBinary();  TickType_t xLastWakeTime = xTaskGetTickCount();  while (1)  {     // Realiza uma amostragem do microfone. deve ser transportado para a TASK de amostragem ADC     sample_mic();       // realiza a exibição do status da coleta de ruidos    // Pega a potência média da amostragem do microfone.    float avg = mic_power();    avg = 2.f * abs(ADC_ADJUST(avg)); // Ajusta para intervalo de 0 a 3.3V. (apenas magnitude, sem sinal)    float db = 20.f * log(ADC_MAX/(avg+0.00001)); // Calcula o volume em decibels.    uint intensity = get_intensity(avg); // Calcula intensidade a ser mostrada na matriz de LEDs.    // Limpa a matriz de LEDs.    npClear();    // A depender da intensidade do som, acende LEDs específicos.    switch (intensity)    {    case 0:      memcpy(text_line_oled[3], "   Sem Som    ", max_text_columns);      break; // Se o som for muito baixo, não acende nada.    case 1:      memcpy(text_line_oled[3], "   Pouco Som  ", max_text_columns);      npSetLED(12, 0, 0, 80); // Acende apenas o centro.      break;    case 2:      memcpy(text_line_oled[3], "  Nivel ideal ", max_text_columns);      npSetLED(12, 0, 0, 120); // Acente o centro.      // Primeiro anel.      npSetLED(7, 0, 0, 80);      npSetLED(11, 0, 0, 80);      npSetLED(13, 0, 0, 80);      npSetLED(17, 0, 0, 80);      break;    case 3:      memcpy(text_line_oled[3], "   Alto Som   ", max_text_columns);      // Centro.      npSetLED(12, 60, 60, 0);      // Primeiro anel.      npSetLED(7, 0, 0, 120);      npSetLED(11, 0, 0, 120);      npSetLED(13, 0, 0, 120);      npSetLED(17, 0, 0, 120);      // Segundo anel.      npSetLED(2, 0, 0, 80);      npSetLED(6, 0, 0, 80);      npSetLED(8, 0, 0, 80);      npSetLED(10, 0, 0, 80);      npSetLED(14, 0, 0, 80);      npSetLED(16, 0, 0, 80);      npSetLED(18, 0, 0, 80);      npSetLED(22, 0, 0, 80);      break;    case 4:      memcpy(text_line_oled[3], "Muito Alto Som", max_text_columns);      // Centro.      npSetLED(12, 80, 0, 0);      // Primeiro anel.      npSetLED(7, 60, 60, 0);      npSetLED(11, 60, 60, 0);      npSetLED(13, 60, 60, 0);      npSetLED(17, 60, 60, 0);      // Segundo anel.      npSetLED(2, 0, 0, 120);      npSetLED(6, 0, 0, 120);      npSetLED(8, 0, 0, 120);      npSetLED(10, 0, 0, 120);      npSetLED(14, 0, 0, 120);      npSetLED(16, 0, 0, 120);      npSetLED(18, 0, 0, 120);      npSetLED(22, 0, 0, 120);      // Terceiro anel.      npSetLED(1, 0, 0, 80);      npSetLED(3, 0, 0, 80);      npSetLED(5, 0, 0, 80);      npSetLED(9, 0, 0, 80);      npSetLED(15, 0, 0, 80);      npSetLED(19, 0, 0, 80);      npSetLED(21, 0, 0, 80);      npSetLED(23, 0, 0, 80);      break;    }    // Atualiza a matriz.    npWrite();    sprintf(text_line_oled[5], "  %02.2f dB    ", db);        xTaskDelayUntil(&xLastWakeTime, TASK_ADC_DMA_DELAY );    //printf("FIM LOOP Task ADC DMA %d\n", xLastWakeTime);  }}/** * Realiza as leituras do ADC e armazena os valores no buffer. */void sample_mic(){  adc_fifo_drain(); // Limpa o FIFO do ADC.  adc_run(false);   // Desliga o ADC (se estiver ligado) para configurar o DMA.  dma_channel_configure(dma_channel, &dma_cfg,                        adc_buffer,      // Escreve no buffer.                        &(adc_hw->fifo), // Lê do ADC.                        SAMPLES,         // Faz SAMPLES amostras.                        true             // Liga o DMA.  );  // Liga o ADC e espera acabar a leitura.  adc_run(true);  dma_channel_wait_for_finish_blocking(dma_channel);  // Acabou a leitura, desliga o ADC de novo.  adc_run(false);}/** * Calcula a potência média das leituras do ADC. (Valor RMS) */float mic_power(){  float avg = 0.f;  for (uint i = 0; i < SAMPLES; ++i)    avg += adc_buffer[i] * adc_buffer[i];  avg /= SAMPLES;  return sqrt(avg);}/** * Calcula a intensidade do volume registrado no microfone, de 0 a 4, usando a tensão. */uint8_t get_intensity(float v){  uint count = 0;  while ((v -= ADC_STEP / 20) > 0.f)    ++count;  return count;}

Statistics: Posted by carlosdelfino — Tue Feb 18, 2025 4:29 am



Viewing all articles
Browse latest Browse all 8041

Trending Articles