servo-pwm.c

STM32F103 "Blue Pill" (STM32F103C8T6) · Fichier : servo-pwm.c · Langage : C · Usage : Piloter un servo d'angle avec un timer PWM 50 Hz

Le timer configuré pour compter en microsecondes génère l'impulsion de commande du servo (0,5 à 2,5 ms sur période de 20 ms). La fonction servo_angle convertit n'importe quel angle en valeur de comparaison : la base de tout bras robotique en C.

Matériel requis

Une Blue Pill STM32F103C8T6 (Cortex-M3 @ 72 MHz, 64 Ko flash) alimentee par micro-USB ou 3,3 V externe ; programmation SWD ou bootloader serie. 1 servo d'angle (SG90/MG90S) + alimentation externe 5 V conseillée.

Câblage

Signal du servo sur la broche du canal (ex. PA6 pour TIM3_CH1, à configurer dans le .ioc), + sur 5 V externe, masses reliées.

Fonctionnement

Le timer compte à 1 MHz (PSC choisi dans CubeMX) avec ARR=19999 soit 20 ms ; la comparaison fixe la largeur d'impulsion. La boucle fait balayer 0-180° par pas de 5°.

Exécution

Projet STM32CubeIDE (STM32F103C8) ou Arduino (core STM32) : programmer par SWD (ST-LINK, adaptateur DAPLink) ou par le bootloader serie (BOOT0 a 1). Attention : LED PC13 active LOW.

Variantes

Ajouter un lissage (interpolation de position), ou piloter 4 servos sur 4 canaux d'un même timer pour un mini-goupinière.

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;
    }
  }
}

← Retour à la fiche