1 votos

STM32 Problema de medición de frecuencia PWM de captura de entrada usando HAL

Estoy tratando de medir el tiempo transcurrido entre dos interrupciones externas generadas por los flancos ascendentes de una señal PWM (generada utilizando un temporizador IC 555). El objetivo es determinar la frecuencia de la señal. Estoy utilizando el GPT (temporizador de propósito general) en modo de captura de entrada. La rutina de devolución de llamada se menciona en el código a continuación.

void HAL_TIM_IC_CaptureCallback (TIM_HandleTypeDef * htim)
{
if (htim->Instance == TIM2)
{
input_capture = __HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1); // leer el valor de captura del canal 1 de TIM2
frecuencia = input_capture - input_capture_prev;
input_capture_prev = input_capture;
FLAG ++;
}
}

Cada vez que sucede una interrupción externa, tomo el tiempo del temporizador y lo resto con el tiempo en que sucedió una interrupción anterior. Ahora quiero hacer un búfer y tomar 20 muestras que dividiré por la longitud de un búfer para obtener una lectura precisa. Básicamente quiero hacer una función que inicie el temporizador en modo de interrupción, tome 20 muestras, las divida por 20 y devuelva el valor preciso y después de eso desactive el temporizador. Aquí está el código de la función.

uint32_t sampleCapacitance(void)
{
uint32_t sum = 0;
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
FLAG = 0;
while (FLAG <20)
{
buffer[FLAG] = frecuencia;
sum + = buffer[FLAG];
}
HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_1);
regrésar suma/20;
}

Todas las variables utilizadas que no están definidas localmente son variables volátiles globales. Estoy llamando a esta función cada 1000 ms, el período de la señal PWM tiene una longitud variable (algunos ms a aprox. 100 ms). La frecuencia del reloj del sistema es de 48 MHz, y el valor del preescalador del temporizador es de 47999+1 que da una base de tiempo de 1000 Hz. Por alguna razón, esto no funciona correctamente (los valores del búfer son principalmente 0, excepto en el índice 20 y 0). Me gustaría saber si hay una manera más inteligente de hacer esto y hacer que funcione. Realmente soy nuevo en la programación de MCU, especialmente con la arquitectura ARM Cortex, así que cualquier ayuda sería apreciada. Gracias de antemano.

0voto

Damen Puntos 96

Lo que puedes hacer es crear una cola en la interrupción para almacenar el período. Debido a que la frecuencia de muestreo debe ser al menos el doble de la frecuencia del PWM, debes manejar el período de forma asincrónica (porque el bucle principal puede ser lento para manejar estas frecuencias). Tuve el mismo problema hace algún tiempo, pero en lugar de un PWM tenía una sierra con frecuencia variable, así que solo estaba contando los bordes de la sierra. Aquí tienes el código de referencia:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef * htim)
{
    static uint32_t prev1 = 0;

    if (htim->Instance == TIM1 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4 )
    {
        auto now = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_4);
        auto diff =( 65536 + now - prev1)%65536;  
        prev1 = now;
        single_producer_single_consumer_queue.push(diff);
    }
}

Observa que debido a que mi reloj no era lo suficientemente rápido para contar algunos períodos, tengo este normalizador para los desbordamientos que debo manejar de alguna manera (por ejemplo, comparar los valores de la cola para cambios enormes inmediatos de 65000 períodos de reloj a 1 período de reloj)

( 65536 + now - prev1)%65536

También ten en cuenta que en el modo de captura, HAL_TIM_ReadCapturedValue parece más razonable y más "alto nivel" que __HAL_TIM_GET_COMPARE

-1voto

Snicki Puntos 11

El sentido de la señal PWM es control de voltaje.

RC_and_ADC

Puedes usar un filtro RC y un ADC para medir la señal. V = (Duty/100)* Vmax (donde Duty = 0..100)

R1min = Vmax / Imax donde Imax es la corriente máxima permitida para la fuente PWM.

Vmax debe ser menor que Vcc de MC.

El capacitor debe ser alrededor de 30nf (1nf ... 1uf). Se recomienda un resistor de 4,7k.

C1 convierte PWM a DC. Cuando el ADC mide valores aleatorios - aumenta c1. Cuando el ADC está "atrasado" - disminuye c1.

Medí la señal con un voltímetro sin R1 y C1.

Además ver https://www.edn.com/a-faster-pwm-based-dac/ y Añadir dos entradas PWM a DC

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X