STM32F4: Configurar el PWM con Timers

Un timer no es más que un contador. Es como un reloj que se usa para medir eventos temporales. Se configura a través de unos registros especiales y se puede elegir, entre otras cosas, su modo de funcionamiento.

En el ejemplo de hoy vamos a trabajar con la placa de desarrollo 32F411-DISCOVERY y nuestro objetivo va a ser aprender a configurar el TIM4 en modo PWM para controlar la intensidad de luz del led Naranja que viene integrado en la placa.

Esta placa está basada en el microcontrolador STM32F411 el cual dispone de hasta 11 Timers, de los cuales 6 pueden ser de 16 bits, y 2 de 32 bits, cada uno con hasta 4 canales de IC/OC/PWM o contador de pulsos. Además de 2 timers watchdog y un Systick Timer.

A través del software CubeMX activaremos el PWM Generation CH2 del TIM4 en la pestaña Pinout. Además de que asociaremos el pin PD13 la función alternativa de TIM4_CH2 (Channe2 PWM Generation CH2).

timers1

Con esto habremos conseguido dos cosas: por un lado configurar el canal 2 del Timer4 en modo PWM, y por otro lado asociar la salida del PWM al pin PD13, que es donde se encuentra el led naranja.

Tras esto pasamos a la pestaña Configuration y ahí configuramos el control del TIM4. Dentro de la pestaña de Parameter Settings hay 3 parámetros numéricos que debemos entender para configurarlos correctamente.

Prescaler (PSC – 16 bits value).

Con este valor podemos fijar la frecuencia del reloj asociado al Timer dividiendo la frecuencia del reloj de sistema.

Counter Period (AutoReload Register – 16 bits value).

Será el valor en el cual nuestro Timer saltará y nos avisará de alguna forma, ya sea reiniciándose o lanzando una interrupcion, etc.

Pulse (16 bits value).

Con este valor podemos fijar el ciclo de trabajo de nuestro PWM.

  • FreqTimer = FreqClock / (Prescaler + 1)
  • Prescaler = (FreqClock / FreqTimer) – 1
  • FreqPWM = FreqTimer / (CounterPeriod + 1)
  • Period = (FreqTimer / FreqPWM) – 1
  • Pulse = ((Period + 1) * DutyCicle) / 100 – 1
Queremos llevar a cabo dos ejemplos, por un lado queremos ver parpadear el led a varios ciclos de trabajo diferentes, y por otro lado queremos configurar un dimmer del led.

A grandes rasgos, lo que hacemos con esta técnica es fijar el periodo de la señal utilizando la frecuencia del PWM, y utilizar la frecuencia del timer para poder modular el ancho del pulso. Siendo esta frecuencia del timer una división de la frecuencia de reloj de nuestro microcontrolador.

Ejemplo 1. Parpadeo del led.

Para el parpadeo del led queremos un periodo de trabajo lento para que nos de tiempo a ver esa conmutación entre encendido y apagado del led. Es por ello que hemos fijado la Frecuencia del PWM a 1Hz. Luego, para hacer el resto de operaciones más fáciles hemos fijado la FreqTimer a 10 Khz. Con estos datos y usando las ecuaciones anteriores obtenemos:

  • APB2 timer clocks = 96 Mhz
  • Objetivo de PWM Freq = 1 Hz
  • Prescaler = 9599
  • Period = 9999

Para poder ver el cambio de parpadeo del led usaremos estos tres valores de Pulse (% Duty cicle).

  • Pulse: 99 (1%), 4999 (50%), 9899 (99%)

Ejemplo 2. Dimmer del led.

En este caso queremos que el periodo de trabajo sera muy pequeño para que las transiciones sean fluidas para el ojo humano. Es por ello que en este ejemplo hemos fijado la Frecuencia del PWM a 10 Khz. Luego, para hacer el resto de operaciones más fáciles hemos fijado la FreqTimer a 2 Mhz. Con estos datos y usando las ecuaciones anteriores obtenemos:

timers2

  • APB2 timer clocks = 96 Mhz
  • Objetivo de PWM Freq = 10 Khz
  • Prescaler = 47
  • Period = 199

Para poder ver un dimmer en el led recorreremos todos los valores posibles de Pulse (% Duty cicle).

  • Pulse: 0 (0%)-199 (100%)

Ejecución de los ejemplos

Una vez hemos generado la plantilla de código con CubeMX es momento de continuar en Eclipse.

Ahora debemos tener en cuenta que para que el PWM se ponga en funcionamiento tenemos que llamar a la función

Y para poder hacer cambios en el valor de Pulse desde Eclipse debemos llamar a la macro

STM32F4: Interrupción externa

En el ejemplo de hoy veremos como asociar la generación de una interrupción externa al botón de usuario que hay en la placa de desarrollo 32F411-DISCOVERY. Después vincularemos a la atención de esa interrupción el toggle del led rojo.

Empezaremos configurando CubeMX, donde ya por defecto nos han puesto el GPIO PA0 configurado como GPIO_EXTI0 que indica que ese pin está configurado como interrupción externa. 

Para ello en la pestaña Configuration, dentro de la configuración de GPIO seleccionamos el pin PA0-WKUP y lo configuramos en modo External Interrupt Mode with Rising edge trigger detection, No pull-up and no pull-down.

Ahora debemos activar dicha interrupción bajo la pestaña Configuration, en la configuración de NVIC, debemos activar la línea EXTI line0 interrupt

Activando estas opciones en CubeMX nos generará el código correspondiente a la inicialización del sistema y activará la interrupción asociada a la linea 0, que en nuestra placa está vinculada al botón de usuario.

Si abrimos el fichero main.c y pinchamos sobre la definición de la función MX_GPIO_Init() podemos ver dos líneas al final del método que fijan la prioridad y activan la interrupción.

Si abrimos el fichero stm32f4xx_it.c podemos ver como ha aparecido una función para la gestión de la interrupción EXTI line0. Si pulsamos sobre la definición de HAL_GPIO_EXTI_IRQHandler(), nos lleva a otro método que limpia el flag de interrupción asociado al GPIO que ha generado la interrupción y llama a su callback asociado HAL_GPIO_EXTI_Callback(). Si vamos a la definición de esta última función vemos que está definida como tipo __weak y en un comentario nos dicen que debe ser implementada en espacio de usuario.

Como nosotros somos muy obedientes copiamos la definición de la función y nos lo llevamos al fichero gpio.c donde dentro del USER CODE 2 pegamos:

A este callback acudirá nuestro programa cuando se detecte una pulsación del botón. Ya que es recomendable hacer el mínimo de operaciones dentro del callback de una interrupción, en este callback sólo realizaremos la operación de toggle del led.

Para ello, dentro de este callback haremos la llamada a HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14). De esta forma cada vez que se pulse el botón de usuario el led rojo de la placa debe conmutar.

Se deja al lector la resolución de varios problemas tales como el sistema antirebotes software que habría que poner asociado a las interrupciones que se generan a través del botón, o el problema asociado a que dentro del callback habrá que distinguir entre los diferentes GPIOs que generen interrupción.

Solo nos falta compilar, y debuguear en Ac6 STM32 C/C++ Application. Y con eso podremos ver conmutar el led rojo de la placa cada vez que pulsamos el botón de usuario.

STM32F4: Primeros pasos con el entorno de desarrollo

En el tutorial que vamos a llevar a cabo hoy veremos como instalar todas las herramientas de desarrollo para poner en marcha la placa de desarrollo 32F411-DISCOVERY. Una vez tengamos todas las herramientas instaladas procederemos a compilar y ejecutar un programa que haga parpadear un led.

Unos de los entornos de desarrollo integrado (IDE) que nosotros usamos en el B105 es eclipse. Para trabajar y poder compilar de forma cruzada para los STM32 existe una versión de eclipse que contiene todos los plugins y librerias necesarias para trabajar con dispositivos de STM llamada System Workbench for STM32 (SW4STM32). Es una herramienta gratuita que debéis descargar e instalar en vuestro ordenador. Para poder descargarla tendréis que registraros en la web. Es posible, que si no lo tenéis instalado todavía, tengáis que instalar Java en vuestro ordenador.

eclpse

 

Ahora procedemos a descargar e instalar el software STM32CubeMX que no es más que un generador de código de inicialización para los microcontroladores y plataformas de desarrollo de ST. Con este software podremos crear el código inicial con las capas de abstracción hardware con las que queremos inicializar nuestra plataforma.

cubmxAl instalar SW4STM32 y CubeMX se nos deberían instalar los drivers correspondientes para poder usar el programador integrado en la placa Discovery para el STM-Link v2 o v2.1.

Proyecto Toggle Led

Abrimos CubeMX y creamos un nuevo proyecto. En la pestaña Board Selector elegimos nuestra placa STM32F411E-DISCO.

cubemx1

 

A través de este software se pueden activar y desactivar los periféricos y los middlewares disponibles en el microcontrolador STM32F411. Además se pueden asociar los periféricos y funciones a los pines, o asignar funciones alternativas a un pin tales como: GPIO de salida, entrada, de interrupción, analógico, de PWM, etc.

Antes de configurar nada del microcontrolador vamos a configurar el programa para que nos genere el código con la estructura correcta. Para ellos entraremos en Project Settings, pondremos un nombre a nuestro proyecto en Project Name, por ejemplo Toggle Led. En Toolchain/IDE seleccionaremos SW4STM32 y desactivamos el Generate Under Root.

Bajo la pestaña Code Generator seleccionamos Copy only the necessary library files, Generate peripheral initialization as a pair of ‘.c/.h’, Keep user code when re-generating y Delete previously generated files when not re-generated. Aceptamos la configuración.

Ahora nos fijaremos en el pin PD12, que está asociado al led verde. Comprobamos que está en modo GPIO_Output. Y ahora simplemente confiamos que el resto de configuraciones por defecto son correctas.

Generamos el código pulsando sobre Project -> Generate Code. El programa comenzará a generar todo el código y al finalizar, en el cuadro emergente pulsaremos sobre abrir proyecto. Esto nos debe abrir e incluir el proyecto en SW4STM32 (Eclipse).

Podemos ver como tenemos una estructura de directorios y ficheros que nos ha generado CubeMX con todos los drivers y librerias necesarias para nuestro sencillo proyecto. Si abrimos el main.c podemos ver que hay muchas líneas que dicen USER CODE BEGIN/END.

eclipse2

 

Es muy importante que todo el código que escribamos lo hagamos dentro del bloque BEGIN/END. De lo contrario, cuando volvamos a generar código CubeMX lo sobreescribirá y no lo conservará.

En la inicialización vemos que se hace la llamada a MX_GPIO_Init(), con eclipse si mantenemos pulsado la tecla Ctrl mientras hacemos click sobre las función, nos abrirá su definición. Si la leemos un poco podemos ver una sección donde se define la funcionalidad del LD4_Pin asociado al puerto GPIOD y pin GPIO_PIN_12 que en nuestro caso es el GPIO asociado al Led Verde.

Si ahora accedemos a la definición de HAL_GPIO_Init() nos abrirá el fichero stm32f4xx_hal_gpio.c donde podemos ver todas las funciones de la HAL que nos ha generado CubeMX, entre ellas las de Read, Write y Toggle de un GPIO.

En nuestro caso, dentro del while(1) del main() haremos uso de HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12) para hacer parpadear el led. Para que podamos visualizarlo tendremos que poner un HAL_Delay(500).

Solo nos falta compilar, y debuguear en Ac6 STM32 C/C++ Application. Si dado el caso os preguntan que interfaz deseas utilizar (JTAG o SWD), debéis seleccionar SWD para la correcta comunicación con la placa de desarrollo. Y con eso podremos ver parpadear nuestro led verde cada 0.5 segundos en nuestra plataforma de desarrollo.

Demotherm. Pruebas del robot en entorno real de trabajo

Finalizados los desarrollos software en el laboratorio B105, era momento de volver a la universidad de Oviedo para realizar pequeñas reparaciones en la parte mecánica del robot.

Estas modificaciones mecánicas fueron rápidas ya que básicamente consistieron en cambiar piezas ya desarrolladas por otras modificadas que cumplían mejor con su misión.

Cuando el robot estuvo a punto tanto en la parte mecánica como electrónica, era momento de visitar las instalaciones de Therman, la empresa responsable del proyecto Demotherm. El objetivo de esta visita era el enfrentar el robot a un escenario real de trabajo y comprobar si la parte mecánica y electrónica cumplían con las especificaciones con las que se definió el proyecto.

El robot de demolición de refractario para ciclones cumplió holgadamente sus expectativas y fue capaz de agarrarse a las paredes del ciclón con sus orugas y realizar desplazamientos verticales. Una vez realizadas estas pruebas de comunicación, control, fuerza y movimientos en un ciclón de ensayo sólo nos queda probar la bomba de agua. 

Demotherm. Desarrollo software del robot

Una vez concluyeron las primeras pruebas de integración de la parte electrónica-mecánica el robot viajó al B105 en su sede de Teleco-Madrid para continuar con los desarrollos del proyecto Demotherm.

Antes de este momento ya se había avanzado bastante en diferentes módulos tanto de software como de hardware electrónico. Por un lado se habían diseñado, fabricado y soldado varias placas de circuito impreso para probar las comunicaciones CAN entre la unidad central de proceso del robot y los motores y sensores del mismo. Por otro lado estaban ya bastante avanzados los desarrollos de drivers para los motores y sensores y la arquitectura software que iba a seguir el proyecto.

Una vez el robot estuvo con nosotros se pudieron probar estos desarrollos software y hardware con un interacción directa sobre la mecánica del robot. Los desarrollos dieron sus frutos y todo funcionaba como se esperaba. Mientras el robot estuvo en el B105 se realizaron numerosos avances en el software de control. Desde las diferentes capas de control de los motores, potenciómetros, acelerómetros, etc. hasta la parte de comunicaciones remotas.

El robot está basado en un ARM® 32-bit Cortex®-M7 CPU con FPU, y todo su software ha sido desarrollado en lenguaje C, basando su arquitectura en el sistema operativo FreeRTOS.

No hay que perder de vista que este robot se debe controlar de forma remota por un operario, por lo que debemos tener una interfaz de usuario a partir de la cual el operario tenga control total del robot, y además pueda obtener la información que considere necesaria para operar.

Cuando todos estos desarrollos fueron testeados y se llegó a un estado estable de funcionamiento, era momento de volver a Gijón para probar el robot en un entorno real de trabajo, y ver si tanto mecánica como electrónica cumplen con sus especificaciones.