>应用案例>
/N32G031_SERVO_SMOOTH

让舵机平滑扫描

N32G031_SERVO_SMOOTH

简介

这是一个面向初学者的项目,通过 N32G031 微控制器讲解舵机控制,重点实现连贯、无顿挫的平滑扫描(Smooth Sweep)。它非常适合作为机器人技术和 for 循环应用的基础学习项目,并已针对 UnityMbed 跨平台工作流完成优化。

目标 MCUNations N32G031 (Cortex-M0)
有效信号引脚PA1 (软件模拟 PWM)
运动模式平滑扫描 (0°–90°)

演示视频

接线与硬件连接

设备线材/器件引脚N32G031 开发板引脚备注与安全提示
舵机(例如 SG90)棕色/黑色GND系统共地
舵机(例如 SG90)红色(VCC)5V电机主电源
舵机(例如 SG90)橙色/黄色PA1控制信号引脚(软件模拟 PWM)

运行方式与执行逻辑

接通电源后,舵机臂将持续按照以下四个阶段平滑扫描:

阶段 1:0° ➔ 45°

从 0° 平滑扫描至 45°

从 0° 平滑扫描至 45°(PULSE_0_DEG ➔ PULSE_45_DEG),然后保持位置。

阶段 2:45° ➔ 90°

从 45° 平滑扫描至 90°

从 45° 平滑扫描至 90°(PULSE_45_DEG ➔ PULSE_90_DEG),然后保持位置。

阶段 3:90° ➔ 45°

从 90° 平滑返回至 45°

从 90° 平滑返回至 45°(PULSE_90_DEG ➔ PULSE_45_DEG),然后保持位置。

阶段 4:45° ➔ 0°

从 45° 平滑返回至 0°

从 45° 平滑返回至 0°(PULSE_45_DEG ➔ PULSE_0_DEG),保持位置后重新开始循环。

main.c
// UnityMbed — 舵机平滑扫描控制 @ N32G031
#include "n32g031.h"
#include "n32g031_gpio.h"
#include "n32g031_rcc.h"

/* ====================================================================
 * [硬件校准区]
 * 各校准角度位置对应的脉宽参数
 * ==================================================================== */
#define PULSE_0_DEG     2250   // 0 度(最左侧)
#define PULSE_45_DEG    3325   // 45 度(左侧中间位置)
#define PULSE_90_DEG    4400   // 90 度(垂直/中心位置)

/* 简单的软件延时循环 */
void Delay_Loop(volatile uint32_t count) {
  while(count--) { __NOP(); }
}

/* ====================================================================
 * 子程序:发送单步脉冲(软件模拟 PWM)
 * ==================================================================== */
void Servo_Step(uint32_t pulse_width) {
  GPIO_SetBits(GPIOA, GPIO_PIN_1);
  Delay_Loop(pulse_width);
  GPIO_ResetBits(GPIOA, GPIO_PIN_1);
  Delay_Loop(100000);
}

/* ====================================================================
 * 核心运动程序:在脉冲角度之间平滑过渡
 * ==================================================================== */
void Smooth_Move(uint32_t start_pulse, uint32_t end_pulse) {
  // 如果目标角度更大,则平滑增加脉宽
  if (start_pulse < end_pulse) {
      for (uint32_t p = start_pulse; p <= end_pulse; p += 20) {
          Servo_Step(p);
      }
  }
  // 如果目标角度更小,则平滑减小脉宽
  else {
      for (uint32_t p = start_pulse; p >= end_pulse; p -= 20) {
          Servo_Step(p);
      }
  }
}

/* ====================================================================
 * 主程序入口:周期性平滑扫描循环
 * ==================================================================== */
int main(void) {
  /* 初始化 GPIOA 外设时钟,并将引脚 1 配置为推挽输出 */
  RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
  GPIO_InitType GPIO_InitStructure;
  GPIO_InitStruct(&GPIO_InitStructure);
  GPIO_InitStructure.Pin = GPIO_PIN_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

  while(1) {
      /* 1. 将舵机臂从 0 度平滑扫描至 45 度 */
      Smooth_Move(PULSE_0_DEG, PULSE_45_DEG);
      Delay_Loop(5000000); // 保持位置

      /* 2. 将舵机臂从 45 度平滑扫描至 90 度 */
      Smooth_Move(PULSE_45_DEG, PULSE_90_DEG);
      Delay_Loop(5000000);

      /* 3. 将舵机臂从 90 度平滑返回至 45 度 */
      Smooth_Move(PULSE_90_DEG, PULSE_45_DEG);
      Delay_Loop(5000000);

      /* 4. 将舵机臂从 45 度平滑返回至 0 度并重新开始循环 */
      Smooth_Move(PULSE_45_DEG, PULSE_0_DEG);
      Delay_Loop(5000000);
  }
}

学习与 AI 扩展思路

学习者可以使用 UnityMbed IDE 内置的 AI Assistant 探索、调试和修改本项目:

1

平滑运动

理解让机器人瞬间“跳转”到目标位置与使用 Smooth_Move 函数逐步移动之间的差异,从而创建自然、流畅的动画。

2

硬件校准

通过调整真实硬件参数(脉宽),亲手完成 0°、90° 和 180° 角度的精确校准。

3

for 循环应用

观察数值递增或递减时机械臂如何逐步移动,直观理解 for 循环的运行方式。

4

调整扫描步长

尝试修改 Smooth_Move 函数中的步进增量(p += 20、p += 50 或 p += 5),观察速度变化和慢动作效果。

构建与烧录指南

1

打开项目: 直接在 IDE 中打开此项目文件夹。

2

Build & Flash: 只需点击界面工具栏上的 Build 和 Flash 按钮。