概述

装上了电机驱动,小车就可以跑起来了,但是如果希望能够精确的控制小车移动的距离就需要加上测速模块,下图是我使用的测速模块:

测速模块实物图

测速模块四个引脚定义为 +5VGNDOUT1OUT2,其中 OUT1 和 OUT2 为电平输出,直接接入单片机 IO 口,每一路带一个 LED 指示其输出状态,模块的工作电压为 3.3V—5V。然后在小车轮子的轴上固定上码盘,当轮子转动时,码盘会随轮子一起转动。

码盘实物图

测速原理

通过对射式计数传感器模块可以检测出和轮子同轴固定的码盘转过的栅格数 n,由于我使用的是 6 栅格的码盘,就可以算出轮子转动的圈数为 N=n/6,然后根据轮子的直径 R可以算出轮子的周长 L,用圈数 N 乘以周长 L 就是小车前进的距离 S=N*L,然后通过 Arduino 板的时钟计算出小车运动时间 T,则小车的平均速度 V=S/T

精度计算

由于我使用的是 6 栅格的码盘,小车车轮直径为 6.5cm,我们就可以计算该码盘能检测到的最小精度为:

3.14 * 6.5cm / 6 = 3.4 cm

这个精度可以满足小车运动的普通精度控制。如果需要提高小车运动最小精度的控制,可以使用更多栅格的码盘。

Arduino 编程实现

将测速模块的 OUT1 连接到 Arduino 板 IO 口的 13,下面用编程来测量速度。

/*
 * 智能小车测速程序
 * 通过测量码盘状态变化来计算小车运动距离和速度
 */

int pin = 13;      // 测速模块的 OUT1 连接到 pin 13
int i;             // 当前码盘状态
int j;             // 初始码盘状态
int n = 0;         // 码盘读数(即状态跳变次数),初始化为 0
int flag = 0;      // 因为初始读数可能为 0 或 1,该标志是用来读取初始状态的
int s;             // 小车运动的距离 (cm)
int t;             // 小车运动的时间 (s)
int v;             // 小车的速度 (cm/s)

void setup() {
  Serial.begin(9600);   // 初始化串口,波特率 9600
  pinMode(pin, INPUT);  // 设置 pin 口为输入模式
}

void loop() {
  i = digitalRead(pin);  // 读取码盘状态(0 或 1)
  
  if(!flag) {            // 获取初始状态读数存储在变量 j 中
      j = i;
      flag = 1;
  }

  if(i != j) {           // 每次状态发生跳变的时候,即和初始状态 j 不同时,码盘读数增加 1
    n += 1;
    j = i;
  }
  
  s = 3.4 * n;           // 小车运动的距离 (cm)=码盘的最小精度 3.4cm*码盘读数 n
  t = millis() / 1000;   // 小车运动的时间 (s)
  v = s / t;             // 小车的速度 (cm/s)
  
  Serial.println(v);     // 通过串口输出速度值
}

总结

这样就可以得到小车实时的平均速度了,但是这只是一个轮子的平均速度,如果得到两个轮子的速度,可以通过调节两个轮子的速度来达到改变行驶方向的目的。

扩展应用

通过速度反馈,我们可以实现更多高级功能:

  1. 速度闭环控制:通过测速模块反馈的速度值,调整 PWM 输出,实现精确的速度控制
  2. 直线行驶校正:比较两轮速度差异,自动调整两轮 PWM 输出,保证小车直线行驶
  3. 距离精确控制:根据码盘计数,可以让小车准确行驶指定距离