零知IDE——基于零知ESP32与DRV8833的稳定电机测速系统实现教程

 ✔零知开源(零知IDE)是一个专为电子初学者/电子兴趣爱好者设计的开源软硬件平台,在硬件上提供超高性价比STM32系列开发板、物联网控制板。取消了Bootloader程序烧录,让开发重心从 “配置环境” 转移到 “创意实现”,极大降低了技术门槛。零知IDE编程软件,内置上千个覆盖多场景的示例代码,支持项目源码一键下载,项目文章在线浏览。零知开源(零知IDE)平台通过软硬件协同创新,让你的创意快速转化为实物,来动手试试吧!

✔访问零知实验室,获取更多实战项目和教程资源吧!

www.lingzhilab.com

目录

一、硬件操作部分

硬件清单

接线方案表

具体接线图

连接实物图

二、代码讲解部分

硬件定时器中断

硬件定时器配置

指数加权移动平均滤波

项目完整代码

三、项目结果演示

校准全过程

参数调节指南

稳定速度输出波形图

视频演示

四、DRV8833 与红外对射传感器技术讲解

DRV8833 电机驱动模块

红外对射计数传感器

五、常见问题解答(FAQ)

Q1:为什么我的脉冲计数仍然不稳定?

Q2:电机不转动


项目概述

        本项目基于零知 ESP32主控,搭配DRV8833 电机驱动模块红外对射计数传感器,实现了高精度、高稳定性的电机速度测量与控制。核心功能包括:通过串口接收 PWM 指令控制电机转速,利用红外对射传感器采集电机码盘脉冲,结合定时器中断精准采样、EMA 指数加权滤波和平滑阈值处理,最终在 OLED 屏实时显示稳定的速度值(cm/s)、当前 PWM 输出和原始脉冲数

项目难点及解决方案

        问题描述1:实时脉冲数据经常出现大幅跳动

解决方案:采用ESP32的硬件定时器提供精确的1秒采样周期,同时结合指数加权移动平均(EMA)滤波算法和变化阈值检测机制,实现了速度值的稳定输出

一、硬件操作部分

硬件清单

组件名称型号规格数量备注
主控板零知ESP32-WROOM-321核心控制器
电机驱动DRV8833双H桥驱动模块1电机速度控制
传感器红外对射计数传感器1脉冲检测
OLED显示屏0.96寸I2C SSD13061数据显示
直流电机微型直流电机1待测对象
码盘20格黑白码盘1安装于电机轴

接线方案表

        DRV8833采用5V供电确保电机驱动能力

零知 ESP32 引脚连接器件器件引脚功能说明
12(MOTOR_AIN1)DRV8833AIN1电机 PWM 控制引脚 1
13(MOTOR_AIN2)DRV8833AIN2电机方向 / 停止控制引脚 2
14(SENSOR_PIN)红外对射传感器信号脚(OUT)脉冲计数信号输入
21(SDA)OLED1306SDAI2C 数据总线
22(SCL)OLED1306SCLI2C 时钟总线
DRV8833 OUT1直流电机电机引脚 1电机动力输出
DRV8833 OUT2直流电机电机引脚 2电机动力输出

具体接线图

连接实物图

二、代码讲解部分

        代码核心在于实现了多层级的稳定性算法,下面详细解析关键部分:

硬件定时器中断

// ================= 硬件定时器配置 =================
hw_timer_t *speedSampleTimer = NULL;          // 速度采样定时器
volatile unsigned int timerInterruptCount = 0;// 定时器中断计数(10次=1秒)
portMUX_TYPE timerCriticalMux = portMUX_INITIALIZER_UNLOCKED; // 临界区保护锁

// ================= 中断服务函数 =================
/**
 * @brief 红外传感器中断服务函数(上升沿触发+1ms去抖)
 * 功能:过滤毛刺信号,统计有效脉冲数
 */
void IRAM_ATTR infraredSensorIsr() {
  unsigned long currentIsrTime = micros();
  // 1ms去抖:两次中断间隔>1000μs→视为有效脉冲
  if (currentIsrTime - lastSensorIsrTime > 1000) { 
    portENTER_CRITICAL_ISR(&timerCriticalMux); // 禁止其他中断,保护计数变量
    sensorPulseCount++;
    portEXIT_CRITICAL_ISR(&timerCriticalMux);
    lastSensorIsrTime = currentIsrTime;
  }
}

/**
 * @brief 定时器中断服务函数(100ms触发一次)
 * 功能:累计中断次数,触发1秒一次的速度计算
 */
void IRAM_ATTR speedSampleTimerIsr() {
  portENTER_CRITICAL_ISR(&timerCriticalMux);
  timerInterruptCount++;
  portEXIT_CRITICAL_ISR(&timerCriticalMux);
}

        IRAM_ATTR确保中断函数存储在IRAM中,提高执行速度

硬件定时器配置

void setup() {
  // 串口初始化(115200波特率,用于控制和波形输出)
  Serial.begin(115200);
  while (!Serial); // 等待串口就绪(兼容部分开发板)
  
  // OLED初始化
  if (!oledDisplay.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR)) {
    Serial.println("OLED Init Failed!");
    while (1); // 初始化失败则卡死,提示错误
  }
  oledDisplay.setTextColor(SSD1306_WHITE); // 设置字体颜色为白色

  // PWM初始化(适配DRV8833)
  ledcSetup(PWM_CHANNEL_MOTOR, PWM_FREQUENCY, PWM_RESOLUTION);
  ledcSetup(PWM_CHANNEL_STANDBY, PWM_FREQUENCY, PWM_RESOLUTION);
  ledcAttachPin(MOTOR_DRV_AIN1, PWM_CHANNEL_MOTOR);
  ledcAttachPin(MOTOR_DRV_AIN2, PWM_CHANNEL_STANDBY);

  // 红外传感器初始化(下拉输入+上升沿中断)
  pinMode(INFRARED_SENSOR_PIN, INPUT_PULLDOWN);
  attachInterrupt(digitalPinToInterrupt(INFRARED_SENSOR_PIN), 
                  infraredSensorIsr, RISING);

  // 速度采样定时器初始化(100ms中断一次)
  speedSampleTimer = timerBegin(0, 80, true); // 定时器0,80分频(1MHz计数),向上计数
  timerAttachInterrupt(speedSampleTimer, &speedSampleTimerIsr, true); // 绑定中断函数
  timerAlarmWrite(speedSampleTimer, 100000ul, true); // 100000×1μs=100ms,自动重载
  timerAlarmEnable(speedSampleTimer); // 使能定时器中断
  
  // 系统就绪提示
  Serial.println("=== System Ready ===");
  Serial.println("Usage: Send PWM value (0~255) via Serial to control motor");
  Serial.println("Serial Output Format: RawPulse | FilteredPulse | Speed(cm/s)");
  Serial.println("====================");
}

        timerBegin 使用定时器0,预分频80(80MHz/80=1MHz),向上计数;timerAlarmWrite设置报警值为100,000微秒,自动重载;每10次中断构成1秒的完整采样周期

指数加权移动平均滤波

void loop() {
  // 1. 串口接收PWM指令,控制电机速度
  if (Serial.available() > 0) {
    int inputPwm = Serial.parseInt(); // 读取串口发送的PWM值
    // 验证输入有效性(仅接收0~255的数值)
    if ((Serial.read() == '\n' || Serial.read() == '\r') && inputPwm >= 0 && inputPwm <= 255) {
      setMotorPwmSpeed(inputPwm);
      Serial.printf("Motor PWM Set to: %d\n", currentMotorPwm);
    } else {
      Serial.println("Invalid Input! Please send number between 0~255");
    }
  }

  // 2. 每1秒采样一次,计算稳定速度(定时器中断累计10次=1秒)
  if (timerInterruptCount >= 10) {
    portENTER_CRITICAL(&timerCriticalMux); // 临界区保护,避免数据冲突
    unsigned long rawPulse = sensorPulseCount; // 读取原始脉冲数
    sensorPulseCount = 0;                      // 重置脉冲计数
    timerInterruptCount = 0;                   // 重置定时器计数
    portEXIT_CRITICAL(&timerCriticalMux);

    // --- 核心算法:数据平滑+稳定速度计算 ---
    // A. 静态噪声过滤:低速截止
    if (rawPulse < minValidPulse) {
      rawPulse = 0;
      filteredPulseCount = 0.0; // 强制归零,避免噪声导致的虚假速度
    }

    // B. EMA指数加权滤波:平滑原始脉冲数据
    // 公式:滤波后值 = α×当前测量值 + (1-α)×上一次滤波值
    filteredPulseCount = (emaFilterAlpha * rawPulse) + ((1.0 - emaFilterAlpha) * filteredPulseCount);

    // C. 阈值判断:仅当脉冲变化足够大时更新显示(抑制微小波动)
    if (abs(filteredPulseCount - lastDisplayedPulse) > speedUpdateThreshold || rawPulse == 0) {
      lastDisplayedPulse = filteredPulseCount; // 更新显示用脉冲数
    }

    // D. 计算最终稳定速度(cm/s)
    currentSpeedCmS = lastDisplayedPulse * cmPerPulse;

    // --- 串口输出(格式固定,适配波形工具) ---
    // 输出格式:Raw脉冲数 | 滤波后脉冲数 | 速度(cm/s),保留2位小数
    Serial.print(rawPulse);
    Serial.print(" | ");
    Serial.print(filteredPulseCount, 1); // 滤波后脉冲数保留1位小数
    Serial.print(" | ");
    Serial.println(currentSpeedCmS, 2); // 速度保留2位小数,波形更细腻

    // --- 更新OLED显示 ---
    updateOledDisplay(lastDisplayedPulse, currentSpeedCmS);
  }
}
环节输入输出核心作用
低速截止原始脉冲数0 或原始值过滤静态噪声(无电机转动时的误计数)
EMA 滤波原始脉冲数 / 上次平滑值平滑后脉冲数抑制大幅波动,保留趋势
变化阈值平滑后脉冲数 / 上次显示值稳定显示值过滤 ±1~2 的微小波动,保持显示稳定

项目完整代码

/**************************************************************************************
文件: /DRV8833_Motor_Stable_Speed/DRV8833_Motor_Stable_Speed.ino
作者:零知实验室(深圳市在芯间科技有限公司)
-^^- 零知开源,让电子制作变得更简单! -^^-
时间: 2025-12-2 16:36:27
说明: 基于ESP32的电机稳速测速系统。通过红外传感器检测脉冲,结合EMA滤波和阈值算法计算稳定速度,并在OLED上实时显示。可通过串口调节电机PWM速度。
***************************************************************************************/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// ================= 用户可调参数 (校准区) =================
// 1. 脉冲-距离转换系数 (cm/脉冲):根据实际硬件校准
// 理论计算: 轮径25.75mm × π ÷ 码盘20格 ≈ 0.4045 cm/脉冲
// 校准规则:测量距离偏短→增大;偏长→减小
float cmPerPulse = 0.4045; 

// 2. EMA滤波平滑系数 (0.01~1.0)
// 小值→更平滑但响应慢;大值→响应快但抖动大
const float emaFilterAlpha = 0.3; 

// 3. 速度更新阈值 (死区):抑制微小波动
// 仅当脉冲变化超过此值时更新显示,避免数值频繁跳动
const float speedUpdateThreshold = 2.0; 

// 4. 最小有效脉冲数:过滤静态噪声
// 1秒内脉冲数小于此值→视为电机停止
const int minValidPulse = 2;

// ================= 硬件引脚定义 =================
#define OLED_SCREEN_WIDTH 128    // OLED屏幕宽度
#define OLED_SCREEN_HEIGHT 64    // OLED屏幕高度
#define OLED_I2C_ADDR 0x3C       // OLED默认I2C地址
Adafruit_SSD1306 oledDisplay(OLED_SCREEN_WIDTH, OLED_SCREEN_HEIGHT, &Wire, -1);

// DRV8833电机驱动引脚
#define MOTOR_DRV_AIN1 12        // 电机PWM控制引脚1
#define MOTOR_DRV_AIN2 13        // 电机方向/停止控制引脚2
#define INFRARED_SENSOR_PIN 14   // 红外对射传感器信号引脚

// ESP32 PWM配置参数
#define PWM_CHANNEL_MOTOR 0      // 电机PWM通道1
#define PWM_CHANNEL_STANDBY 1    // 电机备用通道2
#define PWM_RESOLUTION 8         // PWM分辨率(8位→0~255)
#define PWM_FREQUENCY 1000       // PWM频率(1kHz,适配DRV8833)

// ================= 全局变量 =================
volatile unsigned long sensorPulseCount = 0;   // 传感器原始脉冲计数
volatile unsigned long lastSensorIsrTime = 0;  // 传感器中断上次触发时间(去抖用)

// 滤波后数据存储
float filteredPulseCount = 0.0;    // EMA滤波后的脉冲数
float currentSpeedCmS = 0.0;       // 当前稳定速度(cm/s)
float lastDisplayedPulse = 0.0;    // 上一次显示的脉冲数

int currentMotorPwm = 0;           // 当前电机PWM输出值

// ================= 硬件定时器配置 =================
hw_timer_t *speedSampleTimer = NULL;          // 速度采样定时器
volatile unsigned int timerInterruptCount = 0;// 定时器中断计数(10次=1秒)
portMUX_TYPE timerCriticalMux = portMUX_INITIALIZER_UNLOCKED; // 临界区保护锁

// ================= 中断服务函数 =================
/**
 * @brief 红外传感器中断服务函数(上升沿触发+1ms去抖)
 * 功能:过滤毛刺信号,统计有效脉冲数
 */
void IRAM_ATTR infraredSensorIsr() {
  unsigned long currentIsrTime = micros();
  // 1ms去抖:两次中断间隔>1000μs→视为有效脉冲
  if (currentIsrTime - lastSensorIsrTime > 1000) { 
    portENTER_CRITICAL_ISR(&timerCriticalMux); // 禁止其他中断,保护计数变量
    sensorPulseCount++;
    portEXIT_CRITICAL_ISR(&timerCriticalMux);
    lastSensorIsrTime = currentIsrTime;
  }
}

/**
 * @brief 定时器中断服务函数(100ms触发一次)
 * 功能:累计中断次数,触发1秒一次的速度计算
 */
void IRAM_ATTR speedSampleTimerIsr() {
  portENTER_CRITICAL_ISR(&timerCriticalMux);
  timerInterruptCount++;
  portEXIT_CRITICAL_ISR(&timerCriticalMux);
}

// ================= 辅助函数 =================
/**
 * @brief 设置电机PWM速度
 * @param pwmVal: PWM值(0~255),0→停止,越大转速越快
 */
void setMotorPwmSpeed(int pwmVal) {
  currentMotorPwm = constrain(pwmVal, 0, 255); // 限制PWM范围(0~255)
  if (currentMotorPwm == 0) {
    ledcWrite(PWM_CHANNEL_MOTOR, 0);
    ledcWrite(PWM_CHANNEL_STANDBY, 0); // 两通道均为0→电机停止
  } else {
    ledcWrite(PWM_CHANNEL_MOTOR, currentMotorPwm);
    ledcWrite(PWM_CHANNEL_STANDBY, 0); // DRV8833正转模式
  }
}

/**
 * @brief 更新OLED显示内容
 * @param dispPulse: 显示用脉冲数(滤波后)
 * @param dispSpeed: 显示用速度(cm/s)
 */
void updateOledDisplay(float dispPulse, float dispSpeed) {
  oledDisplay.clearDisplay();
  
  // 标题栏
  oledDisplay.setTextSize(1);
  oledDisplay.setCursor(0, 0);
  oledDisplay.println("STABLE SPEED METER");
  oledDisplay.drawLine(0, 10, OLED_SCREEN_WIDTH, 10, SSD1306_WHITE);

  // 速度显示(大号字体)
  oledDisplay.setCursor(0, 20);
  oledDisplay.setTextSize(2);
  oledDisplay.print(dispSpeed, 2); // 保留2位小数,提高精度
  oledDisplay.setTextSize(1);
  oledDisplay.println(" cm/s");

  // 辅助信息(PWM+脉冲数)
  oledDisplay.setCursor(0, 45);
  oledDisplay.print("PWM: "); oledDisplay.print(currentMotorPwm);
  
  oledDisplay.setCursor(64, 45);
  oledDisplay.print("Pulse: "); oledDisplay.print((int)dispPulse);

  oledDisplay.display();
}

// ================= 初始化函数 =================
void setup() {
  // 串口初始化(115200波特率,用于控制和波形输出)
  Serial.begin(115200);
  while (!Serial); // 等待串口就绪(兼容部分开发板)
  
  // OLED初始化
  if (!oledDisplay.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR)) {
    Serial.println("OLED Init Failed!");
    while (1); // 初始化失败则卡死,提示错误
  }
  oledDisplay.setTextColor(SSD1306_WHITE); // 设置字体颜色为白色

  // PWM初始化(适配DRV8833)
  ledcSetup(PWM_CHANNEL_MOTOR, PWM_FREQUENCY, PWM_RESOLUTION);
  ledcSetup(PWM_CHANNEL_STANDBY, PWM_FREQUENCY, PWM_RESOLUTION);
  ledcAttachPin(MOTOR_DRV_AIN1, PWM_CHANNEL_MOTOR);
  ledcAttachPin(MOTOR_DRV_AIN2, PWM_CHANNEL_STANDBY);

  // 红外传感器初始化(下拉输入+上升沿中断)
  pinMode(INFRARED_SENSOR_PIN, INPUT_PULLDOWN);
  attachInterrupt(digitalPinToInterrupt(INFRARED_SENSOR_PIN), 
                  infraredSensorIsr, RISING);

  // 速度采样定时器初始化(100ms中断一次)
  speedSampleTimer = timerBegin(0, 80, true); // 定时器0,80分频(1MHz计数),向上计数
  timerAttachInterrupt(speedSampleTimer, &speedSampleTimerIsr, true); // 绑定中断函数
  timerAlarmWrite(speedSampleTimer, 100000ul, true); // 100000×1μs=100ms,自动重载
  timerAlarmEnable(speedSampleTimer); // 使能定时器中断
  
  // 系统就绪提示
  Serial.println("=== System Ready ===");
  Serial.println("Usage: Send PWM value (0~255) via Serial to control motor");
  Serial.println("Serial Output Format: RawPulse | FilteredPulse | Speed(cm/s)");
  Serial.println("====================");
}

// ================= 主循环 =================
void loop() {
  // 1. 串口接收PWM指令,控制电机速度
  if (Serial.available() > 0) {
    int inputPwm = Serial.parseInt(); // 读取串口发送的PWM值
    // 验证输入有效性(仅接收0~255的数值)
    if ((Serial.read() == '\n' || Serial.read() == '\r') && inputPwm >= 0 && inputPwm <= 255) {
      setMotorPwmSpeed(inputPwm);
      Serial.printf("Motor PWM Set to: %d\n", currentMotorPwm);
    } else {
      Serial.println("Invalid Input! Please send number between 0~255");
    }
  }

  // 2. 每1秒采样一次,计算稳定速度(定时器中断累计10次=1秒)
  if (timerInterruptCount >= 10) {
    portENTER_CRITICAL(&timerCriticalMux); // 临界区保护,避免数据冲突
    unsigned long rawPulse = sensorPulseCount; // 读取原始脉冲数
    sensorPulseCount = 0;                      // 重置脉冲计数
    timerInterruptCount = 0;                   // 重置定时器计数
    portEXIT_CRITICAL(&timerCriticalMux);

    // --- 核心算法:数据平滑+稳定速度计算 ---
    // A. 静态噪声过滤:低速截止
    if (rawPulse < minValidPulse) {
      rawPulse = 0;
      filteredPulseCount = 0.0; // 强制归零,避免噪声导致的虚假速度
    }

    // B. EMA指数加权滤波:平滑原始脉冲数据
    // 公式:滤波后值 = α×当前测量值 + (1-α)×上一次滤波值
    filteredPulseCount = (emaFilterAlpha * rawPulse) + ((1.0 - emaFilterAlpha) * filteredPulseCount);

    // C. 阈值判断:仅当脉冲变化足够大时更新显示(抑制微小波动)
    if (abs(filteredPulseCount - lastDisplayedPulse) > speedUpdateThreshold || rawPulse == 0) {
      lastDisplayedPulse = filteredPulseCount; // 更新显示用脉冲数
    }

    // D. 计算最终稳定速度(cm/s)
    currentSpeedCmS = lastDisplayedPulse * cmPerPulse;

    // --- 串口输出(格式固定,适配波形工具) ---
    // 输出格式:Raw脉冲数 | 滤波后脉冲数 | 速度(cm/s),保留2位小数
    Serial.print(rawPulse);
    Serial.print(" | ");
    Serial.print(filteredPulseCount, 1); // 滤波后脉冲数保留1位小数
    Serial.print(" | ");
    Serial.println(currentSpeedCmS, 2); // 速度保留2位小数,波形更细腻

    // --- 更新OLED显示 ---
    updateOledDisplay(lastDisplayedPulse, currentSpeedCmS);
  }
}

系统流程图

三、项目结果演示

校准全过程

1)硬件安装与接线

        按接线表连接所有器件,确保:

红外对射传感器与码盘间距 5~10mm,对齐齿隙;DRV8833 供电电压匹配电机;OLED I2C 地址为 0x3C

2)传统 PID 方案测试

        烧录原始 PID 代码,打开OLED 显示屏上的局域网地址,观察脉冲波形变化

原始脉冲数波动 52~71,抖动严重,无法稳定显示

3)改进方案校准

        烧录改进后代码,进行以下校准:

距离校准(CM_PER_PULSE):

        ①用尺子量取 1 米(100cm)距离,在串口发送 PWM=150,让电机带动轮子沿直线走 1 米;

        ②记录串口打印的Raw值(假设为 247),则CM_PER_PULSE=100/247≈0.405,修改代码后重新上传

滤波系数调节(FILTER_ALPHA):

        若速度仍抖,减小 α(如 0.2);若响应过慢,增大 α(如 0.4)

阈值调节(CHANGE_THRESHOLD):

        微小波动多则增大至 2.5~3.0;响应迟缓则减小至 1.5~2.0

4)稳定测试

        发送不同 PWM 值(50~255),观察串口和 OLED:

串口打印:Raw 值波动 ±3~5,但 Filtered 值波动≤±1,DispSpeed 波动≤±0.3 cm/s;
OLED 显示:速度值稳定,无频繁跳变

参数调节指南

参数默认值调节范围作用调节建议
CM_PER_PULSE0.40450.1-1.0每个脉冲对应的距离根据实际测量校准
FILTER_ALPHA0.30.01-1.0滤波平滑系数值越小越平滑但响应慢
CHANGE_THRESHOLD2.00.5-10.0变化检测阈值值越大显示越稳定
MIN_PULSE_CUTOFF21-10最小有效脉冲过滤静止噪声

稳定速度输出波形图

打开调试功能/串口绘图仪→设置波特率→观察波形脉冲和速度变化:

速度波形基本呈水平线,波动幅度≤±0.3 cm/s,无大幅跳变

视频演示

DRV8833的稳定电机测速系统

串口发送 PWM 指令(255→127→90→0)、实时展示 OLED 屏,速度值稳定更新,PWM 与原始脉冲数同步显示、串口波形区速度波形平稳,无剧烈波动

四、DRV8833 与红外对射传感器技术讲解

DRV8833 电机驱动模块

工作原理

        DRV8833 内部集成双 H 桥驱动电路,H 桥由 4 个 MOS 管组成,通过控制 MOS 管的导通 / 截止实现电机正转、反转、停止和调速

正转:AIN1=PWM,AIN2=LOW;
反转:AIN1=LOW,AIN2=PWM;
停止:AIN1=LOW,AIN2=LOW;
调速:改变 PWM 占空比(0~255),占空比越大,电机转速越高

红外对射计数传感器

工作原理

        传感器由红外发射管和接收管组成,呈对射式安装:

        无遮挡时:发射管发出的红外光被接收管接收,接收管导通,输出低电平;有遮挡时(码盘齿经过):红外光被阻断,接收管截止,输出高电平;电机转动时,码盘的齿和间隙交替遮挡红外光,传感器输出连续脉冲,脉冲数 = 码盘齿数 × 转动圈数。

计数逻辑

        本项目电机码盘为 20 格(20 齿 + 20 间隙),电机转 1 圈,传感器输出 20 个脉冲;结合轮径计算每脉冲对应的距离:

   每脉冲距离(cm)= 轮子周长(cm)/ 码盘齿数 =(π×轮径cm)/20

五、常见问题解答(FAQ)

Q1:为什么我的脉冲计数仍然不稳定?

        A:请按以下步骤排查:检查传感器安装是否牢固,码盘是否偏心;测量传感器输出信号,增大 FILTER_ALPHA 至 0.4~0.5,或增大 CHANGE_THRESHOLD 至 2.5~3.0,尝试更小的值(如0.2);检查电源稳定性

Q2:电机不转动

        A:请检查: DRV8833 供电,确保供电电大于等于电机工作电压; PWM 值大于等于70,电机启动需要最小电压驱动;DRV8833 模块引脚的 OUT1/OUT2 正确连接到电机,,AIN1=12,AIN2=13

项目资源整合

        DRV8833数据手册:       DRV8833 Dual H-Bridge Motor Driver datasheet (Rev. E)

        OLED SSD1306库文件:        Adafruit_SSD1306

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值