servo-pwm.c
El temporizador configurado para contar microsegundos genera el impulso de control del servo (0,5 a 2,5 ms sobre periodo de 20 ms). La función servo_angle convierte cualquier ángulo en un valor de comparación: la base de todo brazo robótico en C.
Hardware
Una STM32F407G-DISC1 (Discovery F4, Cortex-M4 @ 168 MHz) con ST-LINK integrado, pines de 3,3 V. 1 servo de ángulo (SG90/MG90S) + alimentación externa de 5 V aconsejada.
Cableado
Señal del servo en el pin del canal (p. ej. PA6 para TIM3_CH1, configurado en el .ioc), + a 5 V externo, masas unidas.
Funcionamiento
El temporizador cuenta a 1 MHz (PSC elegido en CubeMX) con ARR=19999, es decir 20 ms; la comparación fija el ancho del impulso. El bucle barre 0-180° en pasos de 5°.
Ejecución
Proyecto STM32CubeIDE « STM32F407G-DISC1 »: pega el codigo en main.c, configura el .ioc, Run. La placa tiene 4 LED (PD12-PD15) y el boton USER en PA0.
Variantes
Añade suavizado (interpolación de posición), o controla 4 servos en 4 canales de un mismo temporizador para un mini brazo.
servo-pwm.c
// Servo 50 Hz : periode 20 ms, impulsion 0,5..2,5 ms.
// Timer configure dans CubeMX : PSC et ARR pour compter en us.
#include "main.h"
extern TIM_HandleTypeDef htim3; // ex. 1 MHz de comptage, ARR=19999
#define SERVO_CANAL TIM_CHANNEL_1
static void servo_angle(int angle) { // 0..180
uint32_t us = 500 + (uint32_t)angle * 2000 / 180; // 500..2500 us
__HAL_TIM_SET_COMPARE(&htim3, SERVO_CANAL, us);
}
uint32_t t0 = 0;
int angle = 0, sens = 1;
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
HAL_TIM_PWM_Start(&htim3, SERVO_CANAL);
for (;;) {
if (HAL_GetTick() - t0 >= 20) { // pas de 20 ms
t0 = HAL_GetTick();
servo_angle(angle);
angle += sens * 5; // 5 degres par pas
if (angle >= 180) sens = -1;
if (angle <= 0) sens = 1;
}
}
}