赞
踩
代码分享给同学们啦,在同学们运行小车的过程中,总会遇见各种奇怪的情况,比如小车不动啦,硬件烧掉啦,正负极接反啦,这都是初学者的必经之路,你们可以独立思考解决问题,也可以百度或者询问他人,只要思想不滑坡,办法总比困难多!( ͡• ͜ʖ ͡• )
小车演示视频:https://www.bilibili.com/video/BV1ur4y1n7RP
提示:完整的代码可以直接烧录Arduino运行,不过地图不同,执行效果也不同,完全copy就能用,就不要想了
// 左边电机引脚5-6,右边电机引脚9-10,必须是有PWM功能的端口 // 循迹引脚 11-12-13-14,从车头方向的最左边开始排序 #define LeftMotor1 3 //Arduino的3号引脚连接在D0端口,利用宏定义可以方便后期改端口 #define LeftMotor2 5 //Arduino的5号引脚连接在D1端口 #define RightMotor1 6 //Arduino的6号引脚连接在接D2端口 #define RightMotor2 9 //Arduino的9号引脚连接在接D3端口 #define track1 10 //Arduino的10号引脚连接在最左边的循迹模块的D0口,以下同理 #define track2 11 #define track3 12 #define track4 13 int Sensor[4] = {0, 0, 0, 0}; //初始化循迹的值 int i = 0;//计数或计时 void setup() { // put your setup code here, to run once: Serial.begin(9600); //串口初始化 Track_Init(); //循迹模块初始化 Motor_Init(); //电机引脚初始化 } void loop() { // put your main code here, to run repeatedly: Sensor_Read(); //不断地读取循迹模块的高低电平 xun_ji(); //循迹函数 count(); //计数函数 Print(); //打印循迹的高低电平 } void Track_Init() { //循迹模块D0引脚初始化,设置为输入模式 pinMode(track1, INPUT); pinMode(track2, INPUT); pinMode(track3, INPUT); pinMode(track4, INPUT); } void Motor_Init() { //电机引脚初始化,设置为输出模式 pinMode(LeftMotor1, OUTPUT); pinMode(LeftMotor2, OUTPUT); pinMode(RightMotor1, OUTPUT); pinMode(RightMotor2, OUTPUT); } void Sensor_Read() { Sensor [0] = digitalRead(track1); //检测到黑线为高电平(1),白线为低电平(0) Sensor [1] = digitalRead(track2); Sensor [2] = digitalRead(track3); Sensor [3] = digitalRead(track4); } void Motor_Speed(int Left1_Speed, int Left2_Speed, int Right1_Speed, int Right2_Speed) { analogWrite(LeftMotor1, Left1_Speed); //控制电机的速度,不同的车模,代码执行效果不同! analogWrite(LeftMotor2, Left2_Speed); analogWrite(RightMotor1, Right1_Speed); analogWrite(RightMotor2, Right2_Speed); } void xun_ji() //小车的速度可根据实际地图进行调节 { if (Sensor [0] == 0 && Sensor [1] == 1 && Sensor [2] == 0 && Sensor [3] == 0) //0-1-0-0 小左转 Motor_Speed(50, 0, 150, 0); //左轮速度 50 右轮直走 150 else if (Sensor [0] == 0 && Sensor [1] == 0 && Sensor [2] == 1 && Sensor [3] == 0) //0-0-1-0 小右转 Motor_Speed(150, 0, 50, 0); //左轮速度 150 右轮速度 50 else if (Sensor [0] == 1 && Sensor [1] == 0 && Sensor [2] == 0 && Sensor [3] == 0) //1-0-0-0 大左转 Motor_Speed(0, 180, 180, 0); //左轮速度 -180 右轮直走 180 else if (Sensor [0] == 0 && Sensor [1] == 0 && Sensor [2] == 0 && Sensor [3] == 1) //0-0-0-1 大右转 Motor_Speed(180, 0, 0, 180); //左轮直走 180 右轮速度 -180 else if (Sensor [0] == 1 && Sensor [1] == 1 && Sensor [2] == 0 && Sensor [3] == 0) //1-1-0-0 左急转弯 Motor_Speed(0, 200, 200, 0); //左轮反转 -200 右轮直走 200 else if (Sensor [0] == 0 && Sensor [1] == 0 && Sensor [2] == 1 && Sensor [3] == 1) //0-0-1-1 右急转弯 Motor_Speed(200, 0, 0, 200); //左轮直走 200 右轮反转 -200 else //除了左右转,就只剩下直走 Motor_Speed(100, 0, 100, 0); } void count() //计黑十字的函数封装 { if (i > 2) //i的具体范围要根据地图的黑十字路口而定! { Motor_Speed(0, 0, 0, 0); //如果到达终点,就停车 } else if (Sensor [0] == 1 && Sensor [1] == 1 && Sensor [2] == 1 && Sensor [3] == 1) { //1-1-1-1 计数 i++; delay(100); //延时可以防止i加的过快 } else if (Sensor [0] == 0 && Sensor [1] == 1 && Sensor [2] == 1 && Sensor [3] == 0) { //0-1-1-0 计数 i++; delay(100); } else if (Sensor [0] == 1 && Sensor [1] == 1 && Sensor [2] == 1 && Sensor [3] == 0) { //1-1-1-0 计数 i++; delay(100); } else if (Sensor [0] == 0 && Sensor [1] == 1 && Sensor [2] == 1 && Sensor [3] == 1) { //0-1-1-1 计数 i++; delay(100); } } void Print() //在串口打印循迹的高低电平 { Serial.print(Sensor [0]); Serial.print("---"); Serial.print(Sensor [1]); Serial.print("---"); Serial.print(Sensor [2]); Serial.print("---"); Serial.println(Sensor [3]); }
我们做的四驱小车前轮是不能转向的,那么怎么样才可以左右转呢?
其实就是通过左右轮的差速就可以转弯,想要小车左转的话,那么 右轮的速度就要大于左轮的速度,想要小车向左转90°的话,差速就行不通了,这时候怎么办呢?当然也是有解决办法的啦!可以让左轮反转,右轮正转,小车就可以原地大幅度转弯了,反转和正转的数值越大,小车转弯的幅度也就越大,具体的数值,就要看你们的地图的情况了。
循迹模块的主要情况,其中0表示检测到白线,1表示检测到黑线
| Sensor [0] | Sensor [1] | Sensor [2] | Sensor [3] | 运动状态 |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 直走 |
| 0 | 1 | 0 | 0 | 小左转 |
| 0 | 0 | 1 | 0 | 小右转 |
| 0 | 0 | 0 | 1 | 大左转 |
| 1 | 0 | 0 | 0 | 大右转 |
| 1 | 1 | 0 | 0 | 左急转弯 |
| 0 | 0 | 1 | 1 | 右急转弯 |
| 1 | 1 | 1 | 1 | 直走 |
Left1_Speed、Left2_Speed控制左轮的速度,Right1_Speed、Right2_Speed控制右轮的速度,相信大家在网上看到过很多把转弯和直走单独封装起来的代码,那样子也可以,不过我个人觉得,传四个参数进去,更加直观、简洁,同学们也可以根据自己的看法来对代码进行取舍
void Motor_Speed(int Left1_Speed, int Left2_Speed, int Right1_Speed, int Right2_Speed)
{
analogWrite(LeftMotor1, Left1_Speed); //控制电机的速度,不同的车模,代码执行效果不同!
analogWrite(LeftMotor2, Left2_Speed);
analogWrite(RightMotor1, Right1_Speed);
analogWrite(RightMotor2, Right2_Speed);
}
当里面的两个循迹模块,有一个检测到黑线(0-1-0-0或0-0-1-0),说明小车轻微偏离轨道,这时候我们可以用差速,让小车小转弯,这样小车就摆正回来了
if (Sensor [0] == 0 && Sensor [1] == 1 && Sensor [2] == 0 && Sensor [3] == 0) //0-1-0-0 小左转
Motor_Speed(50, 0, 250, 0); //左轮速度 50 右轮直走 250
else if (Sensor [0] == 0 && Sensor [1] == 0 && Sensor [2] == 1 && Sensor [3] == 0) //0-0-1-0 小右转
Motor_Speed(250, 0, 50, 0); //左轮速度 250 右轮速度 50
当外面的两个循迹模块,其中一个检测到黑线时(1-0-0-0或0-0-0-1),说明小车严重偏离轨道,这时差速就没什么用了,为了让小车回正,可以用反转,让小车以大幅度转弯
else if (Sensor [0] == 1 && Sensor [1] == 0 && Sensor [2] == 0 && Sensor [3] == 0) //1-0-0-0 大左转
Motor_Speed(0, 230, 255, 0); //左轮速度 -230 右轮直走 255
else if (Sensor [0] == 0 && Sensor [1] == 0 && Sensor [2] == 0 && Sensor [3] == 1) //0-0-0-1 大右转
Motor_Speed(255, 0, 0, 230); //左轮直走 255 右轮速度 -230
当小车遇到直角时,会出现左边两个或者右边两个循迹模块同时检测到黑线(1-1-0-0或0-0-1-1),这时小车就需要更大的转弯幅度了,也就是更大的反转
else if (Sensor [0] == 1 && Sensor [1] == 1 && Sensor [2] == 0 && Sensor [3] == 0) //1-1-0-0 左急转弯
Motor_Speed(0, 250, 250, 0); //左轮反转 -250 右轮直走 250
else if (Sensor [0] == 0 && Sensor [1] == 0 && Sensor [2] == 1 && Sensor [3] == 1) //0-0-1-1 右急转弯
Motor_Speed(250, 0, 0, 250); //左轮直走 250 右轮反转 -250
学会了用 if语句判断循迹的情况后,你们也可以学着用switch语句来判断,这样代码运行得会更快,也可以学PID算法,这样小车转弯会变得十分丝滑。
我相信你们通过自己的努力后,小车能过运行起来了!那么你可以理解代码,试着改一下速度或者是引脚,多去体会其中的道理,也自己去摸索一下怎样的速度是最合适的,要是感觉循迹小车太简单,没意思了,你也可以尝试着做蓝牙遥控小车、超声波避障小车、红外跟随小车呀,总之,多动手,勤思考,办法总比困难多。加油吧!同学们!(0^ ◇ ^0)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。