项目背景
很久以前博主参加了一个DIY小车实现抓取等功能的比赛,但是后来由于疫情等原因没赶上参赛时间,当时就留下了一些小零件。
博主自己的一个研究方向是与点云相关的,就想用手头的超声波传感器加上舵机做一个超声波雷达的小玩具。
某宝上有很多卖支架的,但是提供的代码比较乱,因此博主整理了代码,希望能帮到需要的人。
所用材料
arduino UNO
超声波传感器HC-SR04
舵机SG90
舵机支架
实现效果
舵机载着超声波模块转了180°,然后舵机复位,不断重复。串口以“距离,角度”的格式打印结果
初始化设置
//超声波模块,两个任意端口即可
#define Trig 2
#define Echo 4
#define servopin 7 //定义舵机信号引脚接数字7脚
float dist; //记录超声波得到的距离
float tmp; //记录超声波返回的原始数据
float delta = 0.0; //超声波结果可能需要微调
int delay_time = 20; //
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(Trig, OUTPUT);
pinMode(Echo, INPUT);
pinMode(servopin, OUTPUT);
}
超声波的控制
超声波模块的具体原理可参考1
这里直接上代码
//给Trig发送一个低高低的短时间脉冲,触发测距
digitalWrite(Trig, LOW); //给Trig发送一个低电平
delayMicroseconds(2); //等待 2微妙
digitalWrite(Trig,HIGH); //给Trig发送一个高电平
delayMicroseconds(10); //等待 10微妙
digitalWrite(Trig, LOW); //给Trig发送一个低电平
tmp = float(pulseIn(Echo, HIGH)); //存储回波等待时间,
//pulseIn函数会等待引脚变为HIGH,开始计算时间,再等待变为LOW并停止计时
//返回脉冲的长度
//声速是:340m/1s 换算成 34000cm / 1000000μs => 34 / 1000
//因为发送到接收,实际是相同距离走了2回,所以要除以2
//距离(厘米) = (回波时间 * (34 / 1000)) / 2
//简化后的计算公式为 (回波时间 * 17)/ 1000
//可能存在一定的误差,所以引入修正量delta
dist = (tmp * 17 )/1000 + delta; //把回波时间换算成cm
舵机的控制
要注意的是,这款舵机产生周期为20ms,宽度为1.5ms的基准信号,通过改变信号宽度,可以实现对角度的控制
void servopulse(int angle) //PWM型号产生函数
{
// Microseconds 为纳秒
// 该舵机产生周期为20ms,因此需要调整使一个周期为20000ns
// 调整使得高频信号为0.5ms-2.5ms 对应顺时针至逆时针
// 本函数的输入是0-180,对应顺时针-逆时针,输入值控制角度
int pulsewidth = (angle * 11) + 500; // 角度换算到脉冲宽度
digitalWrite(servopin, HIGH);
delayMicroseconds(pulsewidth);
digitalWrite(servopin, LOW);
delayMicroseconds(20000 - pulsewidth);
}
扫描与旋转的整体代码
把函数run()放进loop里就好啦
void run(){
// 先初始化角度
// 在我的使用过程中,直接让舵机转到0度时实际上好像并没有真正转到0度,所以我这里写了两个servopulse(0),确保他真的复位了。应该是舵机太廉价了偏差大,如果你的实践中一切正常那可以只保留一个。
servopulse(0);
delay(1000);
servopulse(0);
delay(1000);
for(int i = 0; i < 180; i=i+1){
//旋转到需要的角度
servopulse(i);
//给程序一点时间让舵机转到需要的角度。这个delay和这个for循环最后的那个delay设的小一点其实没关系,但在后续的处理中可能会出问题,下一篇blog可能就会涉及到这个问题。这个值不建议设的很小
delay(30);
//给Trig发送一个低高低的短时间脉冲,触发测距
digitalWrite(Trig, LOW); //给Trig发送一个低电平
delayMicroseconds(2); //等待 2微妙
digitalWrite(Trig,HIGH); //给Trig发送一个高电平
delayMicroseconds(10); //等待 10微妙
digitalWrite(Trig, LOW); //给Trig发送一个低电平
tmp = float(pulseIn(Echo, HIGH)); //存储回波等待时间,
//pulseIn函数会等待引脚变为HIGH,开始计算时间,再等待变为LOW并停止计时
//返回脉冲的长度
//声速是:340m/1s 换算成 34000cm / 1000000μs => 34 / 1000
//因为发送到接收,实际是相同距离走了2回,所以要除以2
//距离(厘米) = (回波时间 * (34 / 1000)) / 2
//简化后的计算公式为 (回波时间 * 17)/ 1000
//可能存在一定的误差,所以引入修正量delta
dist = (tmp * 17 )/1000 + delta; //把回波时间换算成cm
//打印结果
Serial.print(dist);//串口输出距离换算成cm的结果
Serial.print(",");
Serial.println(i);
//测距时间间隔,毫秒为单位
delay(delay_time);
}
}