🛠 Piloter un micro-servo avec le PWM
Objetivos
Generar una señal PWM de servo con el RP2040: el chip dispone de 16 canales PWM (8 slices × 2 canales). Un micro-servo estándar (SG90, MG90S…) espera una frecuencia de 50 Hz y un pulso de 1 ms para el centro (0,5 ms ≈ -90°, 2,5 ms ≈ +90°). Configurarás una slice PWM en modo «phase correct» con el Pico SDK y barrerás el ángulo suavemente.
Material
- 1 × Raspberry Pi Pico
- 1 × micro-servo (SG90 o MG90S)
- Alimentación externa de 4,8-6 V para el servo (no lo alimentes desde el 3V3 de la Pico: la corriente de arranque supera lo que la placa puede suministrar con holgura)
- Cables: señal (naranja/amarillo) en GP1, negativo del servo en GND de la Pico Y en el negativo de la alimentación (¡masa común obligatoria!)
Código completo
// servo.c — GP1, 50 Hz, pulse 0,5..2,5 ms (mode phase-correct)
#include "pico/stdlib.h"
#include "hardware/pwm.h"
#define SERVO_PIN 1
#define PERIOD_US 20000u // 50 Hz
static uint16_t angle_to_pulse_us(int angle) { // 0..180 -> 500..2500 us
return 500 + (uint16_t)(angle * 2000 / 180);
}
int main(void) {
gpio_set_function(SERVO_PIN, GPIO_FUNC_PWM);
uint slice = pwm_gpio_to_slice_num(SERVO_PIN);
pwm_set_clkdiv_mode(slice, PWM_DIV_FREE_RUNNING);
pwm_set_clkdiv(slice, 125.0f); // 125 MHz / 125 = 1 MHz (1 us/tick)
pwm_set_wrap(slice, PERIOD_US - 1);
pwm_set_enabled(slice, true);
while (true) {
for (int a = 0; a <= 180; a += 5) {
pwm_set_gpio_level(SERVO_PIN, angle_to_pulse_us(a));
sleep_ms(20);
}
for (int a = 180; a >= 0; a -= 5) {
pwm_set_gpio_level(SERVO_PIN, angle_to_pulse_us(a));
sleep_ms(20);
}
}
}
Verificación esperada
El servo barre lentamente de 0° a 180° y luego vuelve, sin tirones. Al desconectar la señal, el servo debe permanecer inmóvil (sin impulso = sin par). Verifica también que los 3,3 V de la placa no «caigan» cuando el servo hace fuerza: síntoma = la Pico se reinicia, por lo que debes revisar la masa/alimentación del servo.
Errores frecuentes
- Olvidar la masa común entre la Pico y la alimentación del servo: el servo tiembla frenéticamente.
- Alimentar el servo desde el 3V3 de la Pico: caída de tensión (brown-out) y reinicios.
- Reloj de slice incorrecto: sin el
clkdivadecuado, el periodo es erróneo y el servo no responde — recuerda que el PWM proviene del reloj de 125 MHz. - Confundir nivel (
level) y periodo: el nivel debe permanecer inferior al wrap, de lo contrario la salida queda bloqueada en 1. - Alimentar el servo a 5 V en el pin de señal: la señal de control PWM debe permanecer en 3,3 V, la Pico no es tolerante a 5 V.
Otros tutoriales para esta placa
Ejemplos de código para esta placa
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython