¿Cómo usar los temporizadores en la placa STM32 y la biblioteca HAL para medir la velocidad del motor?

2

Necesito medir la velocidad de un motor giratorio instalado en un disco codificador con 20 ranuras. El sensor basado en LM393 se mantiene en el lugar correcto, de modo que el disco del codificador gira entre la parte de detección.

Creo que necesitaría tres temporizadores proporcionados por la placa STM32: uno para proporcionar PWM (TIM4), segundo (TIM1) para medir el tiempo de (1000 mseg ~ 1 seg) y tercer temporizador (TIM2) para medir el número de pulsos recibido del disco codificador en 1 seg.

El período de contador de TIM1 (registro de recarga automática) se fija a 1000 y la frecuencia a 1000Hz. La frecuencia de TIM2 es la misma que la frecuencia PWM-10kHz. La salida del sensor está conectada a PC15 y PWM a PD12.

El siguiente código utiliza la biblioteca HAL. Tengo dudas sobre cómo usar estos dos temporizadores / contadores dentro del bucle while, qué funciones de la biblioteca HAL usar aquí y cómo usar. Además, el código para el control de PWM y el cálculo de la velocidad se deben colocar en el mismo bucle.

int main(void)
{
        volatile GPIO_PinState level; // stores input state from PC15, sensor output is connected to PC15
        uint16_t dutycycle=70;
        int speed=0;                  //speed variable
        int constant=(2*3*1)/20;      //roughly circumference/20 slots

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();       //for measuring 1 second
  MX_TIM4_Init();       //for PWM
  MX_TIM2_Init();      //for counting output pulses from PC15 pin

  HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);    //Start PWM signal
  level=HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15); //HAL function is called to read pin status

  while (1)
  {
              counter1=__HAL_TIM_GetCounter(&tim2);
              speed=(counter1)*(constant);          //speed variable, counter 1 related to TIM2  

            htim4.Instance->CCR1=dutycycle;   //setting the duty cycle of PWM signal
            HAL_Delay(1000);dutycycle+=10;    //1 sec delay and then increases dutycyle by 10%
            if(dutycycle==90)dutycycle=50;    //resets to 50% duty cycle
  }

La placa de desarrollo es STM32F407 , CubeMX es el generador de código fuente e IDE es Eclipse . El sistema operativo es Linux (Ubuntu 15.04) . Por favor sugerir.

    
pregunta abinjacob

4 respuestas

3

La mejor manera es configurar un temporizador en el modo de codificador para contar los pulsos de su sensor. Si tiene pulsos A y B, elija el modo de codificador TIM_ENCODERMODE_TI12 si solo pulsa A y luego TIM_ENCODERMODE_TI1 . (Este código funciona bien en una placa de descubrimiento STM32F4).

void MX_TIM3_Init(void)
{
    TIM_Encoder_InitTypeDef encoderConfig;

    __TIM3_CLK_ENABLE();

    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 0;
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 0xFFFF;
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

    encoderConfig.EncoderMode = TIM_ENCODERMODE_TI12;

    encoderConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
    encoderConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
    encoderConfig.IC1Prescaler = TIM_ICPSC_DIV1;
    encoderConfig.IC1Filter = 0x00;

    encoderConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
    encoderConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
    encoderConfig.IC2Prescaler = TIM_ICPSC_DIV1;
    encoderConfig.IC2Filter = 0x00;

    if(HAL_TIM_Encoder_Init(&htim3, &encoderConfig) != HAL_OK)
    {

    }
}
/**TIM3 GPIO Configuration - Encoder
PB4     ------> TIM3_CH1
PB5     ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

En realidad, no nos dijo el tipo exacto de su STM32, por lo que debe verificar el temporizador, el pin y los valores de función alternativos para los suyos. Después de configurar el temporizador, se pueden usar las siguientes funciones simples.

Luego configure otro temporizador con interrupción periódica y llame a la función Encoder_Read en el ISR para consultar el valor de incremento actual.

uint32_t Encoder_Read(void)
{
    return TIM3->CNT;
}

void Encoder_Start(void)
{
    HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
}

void Encoder_Stop(void)
{
    HAL_TIM_Encoder_Stop(&htim3, TIM_CHANNEL_ALL);
}

En cada ISR puede calcular la diferencia entre el estado del contador anterior y el real. Ese será el número de pulsos durante el período a partir del cual puede calcular la velocidad (dado que sabe cuánto significa el incremento de la distancia 1). Tenga en cuenta los posibles desbordamientos de contadores.

actualización:
Ajuste de canal combinado: Modo de codificador. Aquí hay una foto.

    
respondido por el Bence Kaulics
1

Puede usar un solo temporizador en el modo de captura de entrada para medir la velocidad de un motor a partir de los impulsos de tacómetro generados por el sensor. La señal del sensor debe ingresar a uno de los canales de captura de entrada del temporizador (es decir, un pin con una función alternativa para la captura de entrada del temporizador).

Configure el contador para que cuente a una velocidad constante que sea apropiada para el rango de velocidades que necesita medir. La velocidad del contador debe ser lo suficientemente lenta como para no darse vuelta en el período entre los pulsos del tacómetro para la velocidad más lenta que pretende medir. Y la tasa de contador debe ser lo suficientemente rápida para proporcionar una resolución de tiempo suficiente entre los pulsos del tacómetro para la velocidad más rápida que pretende medir.

En el modo de captura de entrada, el temporizador contará todo el rango del valor del contador. Y el temporizador capturará el valor del contador y proporcionará una interrupción cada vez que se reciba un impulso de tacómetro. En el controlador de interrupción, debe comparar el valor del temporizador recién capturado con el valor capturado anteriormente para determinar el número de tics que se han producido entre los pulsos del tacómetro. Luego, con el número de tics conocidos entre los impulsos del tacómetro, puede calcular la velocidad de rotación del motor.

Aquí hay un código de ejemplo. Deberá elegir el TACH_TMR_INSTANCE, TACH_TMR_TICK_RATE, TACH_TMR_IC_CHANNEL y la polaridad que sean apropiados para usted. Este ejemplo es para un contador de 16 bits, por lo tanto, si está usando un contador de 32 bits, deberá ajustar el valor Period y el tipo de tach_timer_values , this_tach_timer_value y prev_tach_timer_value . Tenga en cuenta que este ejemplo no muestra la función HAL_TIM_IC_MspInit() , que es donde el reloj del temporizador y los relojes GPIO se habilitan y el pin GPIO está configurado para la función alternativa apropiada.

TIM_HandleTypeDef tach_timer_handle;
TIM_IC_InitTypeDef tach_timer_config;

HAL_StatusTypeDef TachInit()
{
    HAL_StatusTypeDef hal_status;

    tach_timer_handle.Instance = TACH_TMR_INSTANCE;

    tach_timer_handle.Init.Prescaler = (SystemCoreClock / TACH_TMR_TICK_RATE) - 1;
    tach_timer_handle.Init.Period = 0xFFFF;
    tach_timer_handle.Init.ClockDivision = 0;
    tach_timer_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    tach_timer_handle.Init.RepetitionCounter = 0;

    hal_status = HAL_TIM_IC_Init(&tach_timer_handle);
    if (hal_status != HAL_OK)
    {
        return hal_status;
    }

    tach_timer_config.ICPolarity = TIM_ICPOLARITY_RISING;
    tach_timer_config.ICSelection = TIM_ICSELECTION_DIRECTTI;
    tach_timer_config.ICPrescaler = TIM_ICPSC_DIV1;
    tach_timer_config.ICFilter = 0;

    hal_status = HAL_TIM_IC_ConfigChannel(&tach_timer_handle, &tach_timer_config, TACH_TMR_IC_CHANNEL);
    if (hal_status != HAL_OK)
    {
        return hal_status;
    }

    HAL_TIM_IC_Start_IT(&tach_timer_handle, TACH_TMR_IC_CHANNEL);
    if (hal_status != HAL_OK)
    {
        return hal_status;
    }

    return HAL_OK;
}


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *tim_handle)
{
    // An array for storing the two most recent captured counter values.
    static uint16_t tach_timer_values[2] = {0, 0};
    // An array index to identify the most recently captured counter value.
    static int tach_timer_index = 0;

    if (tim_handle == &tach_timer_handle)
    {
        uint16_t this_tach_timer_value = HAL_TIM_ReadCapturedValue(tim_handle, TACH_TMR_IC_CHANNEL);
        tach_timer_values[tach_timer_index++] = this_tach_timer_value;
        tach_timer_index &= 0x01;
        uint16_t prev_tach_timer_value = tach_timer_values[tach_timer_index];

        unsigned int tach_period_ticks = this_tach_timer_value - prev_tach_timer_value;
    }
}

No tiene que preocuparse por el traspaso del valor del contador cuando se calcula tach_period_ticks de esta manera, ya que se trata de un cálculo matemático sin firmar y el rollo sobre se elimina.

La velocidad del motor se puede calcular a partir de tach_period_ticks como este.

speed_rpm = (60 * TACH_TMR_TICK_RATE) / (tach_period_ticks * PULSES_PER_REVOLUTION);
    
respondido por el kkrambo
0

TIM1 no parece estar haciendo nada. Su bucle while se ejecuta a una velocidad determinada por HAL_Delay, que (¿creo?) Está utilizando algún otro temporizador que no haya definido explícitamente (o eso o espera ocupado).

Si su intención es ejecutar a una velocidad determinada por TIM1, debe configurar una interrupción en función de la condición de coincidencia de este temporizador (o desbordamiento, o como lo llame ST).

En general, puedo creer que la idea de contar pulsos dado un período de tiempo fijo sería un indicador de la velocidad del motor, pero no sé lo suficiente sobre su hardware en particular para decir más.

    
respondido por el Mitchell Kline
0
  

¿Cómo usar los temporizadores en la placa STM32 y la biblioteca HAL para medir la velocidad del motor?

para ese tipo de cosas, primero piense cómo lo mediría y luego cómo lo mediría con un enfoque / biblioteca en particular.

En términos generales, necesitará un contador y una base de tiempo: para que tenga la cantidad de pulsos en un período de tiempo conocido.

dependiendo de la velocidad del motor, puede usar la base de tiempo para controlar el contador, o viceversa. por ejemplo, puede precargar el contador con un desplazamiento, iniciar la base de tiempo y luego interrumpir el desbordamiento del contador. o al revés.

Así que en max, se necesitan dos temporizadores. en algunos casos, un temporizador es suficiente.

Una vez que descubras el concepto, la forma de implementarlo en tu entorno de software es simple.

    
respondido por el dannyf

Lea otras preguntas en las etiquetas