目录
Arduino初识
来自官方:
Arduino程序main函数结构解析
#include <Arduino.h> // Declared weak in Arduino.h to allow user redefinitions. int atexit(void (* /*func*/ )()) { return 0; } // Weak empty variant initialization function. // May be redefined by variant files. void initVariant() __attribute__((weak)); void initVariant() { } void setupUSB() __attribute__((weak)); void setupUSB() { } int main(void) { init(); initVariant(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }
从官方的开发文档中,我看到了我们写在Arduion的代码是如何被实现的。
setup函数中的语句只会执行一次,因为loop函数被放进了for循环里面(且没有终止条件),由此loop函数一直循环。
电路的基本知识
在高中物理中学过,电路从正极出发回到负极。其实当我们输入了解之后我们知道,要让一个 灯💡亮起来的条件是有电压差。比如说,我们给灯泡💡左端4V电压,右端给2V电压,这时候由于两端的电压差为2V,由此灯泡💡会亮。但是当灯泡💡两端的电压都为4V时,由于没有电压差,灯泡💡就不会亮。
因此就很容易理解Arduino中
int ledpin=13; digitalWrite(ledpin,HIGH); digitalWrite(ledpin-1,LOW);
这段代码就将13号引脚变成了高电位,12号引脚是低电位,这时候接上灯泡💡就会亮起来。(为保护电路,不要直接接💡,要接一个电阻,Arduino的HIGH是5V)。
基于此就可以做一些有趣的小玩意:
1⃣️使用analogWrite函数和支持PWM的引脚,实现灯的亮度渐变。
/* Fading 通过analogWrite() 函数实现呼吸灯效果 */ int ledPin = 9; // LED连接在9号引脚上 void setup() { // Setup部分不进行任何处理 } void loop() { // 从暗到亮,以每次加5的形式逐渐亮起来 for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { // 输出PWM analogWrite(ledPin, fadeValue); // 等待30ms,以便观察到渐变效果 delay(30); } // 从亮到暗,以每次减5的形式逐渐暗下来 for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { // 输出PWM analogWrite(ledPin, fadeValue); // 等待30ms,以便观察到渐变效果 delay(30); } }
2⃣️使用analogRead函数和开关,通过读取引脚的输入,进而控制灯灯亮灭。
3⃣️使用光敏电阻感受光的亮度,实现灯的控制。
4⃣️使用RGB灯通过控制不同引脚的输出,实现不同颜色灯灯切换。
第一个大坑——串口通信:
为实现两块Arduino板之间的信息发送我们需要去了解串口通信的知识。
首先我们接触串口通信的时候,使用的是1,2引脚(既TX,RX)
因此我们遇到了第一个问题:无法上传程序。在TX,RX被占用时是无法上传程序的,必须拔掉再上传。
第二个问题:无法通信。因为电脑和Arduino板的通信 和 Arduino之间的通信相占,因此导致无法通信。
由此我们找到了使用软件串口的方式,使用方法也算比较简单,引用库函数include<SoftwareSerial.h>后基本问题就不大了。
我们初学Arduino的时候就遇到这个就确实卡住了很久很久很久!!!
/* * arduino uno端程序 * 串口使用情况 serial -----computer serial1----- nano softwearserial */ #include<SoftwareSerial.h> SoftwareSerial softSerial(6,5); void setup() { //初始化serial,该串口用于与计算机连接通信: Serial.begin(9600); //初始化serial1,该串口用于与设备B连接通信; softSerial.begin(9600); softSerial.listen(); } //两个字符串分别用于存储A,B两端传来的数据 String device_A_String=""; String device_B_String=""; void loop() { // 读取从计算机传入的数据,并通过softSerial发送个设备B: if(Serial.available()>0) { if(Serial.peek()!='\n') { device_A_String+=(char)Serial.read(); } else { Serial.read(); Serial.print("you said:"); Serial.println(device_A_String); softSerial.println(device_A_String); device_A_String=""; } } //读取从设备B传入的数据,并在串口监视器中显示 if(softSerial.available()>0) { if(softSerial.peek()!='\n') { device_B_String+=(char)softSerial.read(); } else { softSerial.read(); Serial.print("device B said:"); Serial.println(device_B_String); device_B_String=""; } } } /* * arduino uno端程序 * 串口使用情况 serial -----computer serial1----- nano softwearserial */ #include<SoftwareSerial.h> SoftwareSerial softSerial(3,2); void setup() { //初始化serial,该串口用于与计算机连接通信: Serial.begin(9600); //初始化serial1,该串口用于与设备B连接通信; softSerial.begin(9600); softSerial.listen(); } //两个字符串分别用于存储A,B两端传来的数据 String device_A_String=""; String device_B_String=""; void loop() { // 读取从计算机传入的数据,并通过softSerial发送个设备B: if(Serial.available()>0) { if(Serial.peek()!='\n') { device_A_String+=(char)Serial.read(); } else { Serial.read(); Serial.print("you said:"); Serial.println(device_A_String); softSerial.println(device_A_String); device_A_String=""; } } //读取从设备B传入的数据,并在串口监视器中显示 if(softSerial.available()>0) { if(softSerial.peek()!='\n') { device_B_String+=(char)softSerial.read(); } else { softSerial.read(); Serial.print("device B said:"); Serial.println(device_B_String); device_B_String=""; } } }
项目:基于Arduino板控制小车
几大问题:
1⃣️控制电机转动:
我们使用了L298N接入了Arduino板上的信号,再将L298N连接上了电机,一块L298N连接了两个电机,再通过电池给L298N供电,实现电机的基本转动。
2⃣️麦轮的安装:
麦轮——麦克纳姆轮,这是一种特殊的轮子。
比如说向前走的时候,普通的轮子会得到地面向前的摩擦力,从而向前。可是麦轮受到的摩擦力方向是斜向上。这样子的话,一对麦轮要想走直线,那么左右两个轮子就必须是左右方向(定为X方向)上的合力为零。这样子的话我们就会有两种麦轮(称为A,B),它们往前走的时候,受到的摩擦力方向分别是“东北”“西北”。这样子就能走直线了。
可为什么不直接用传统的轮子呢?
图源:https://blog.csdn.net/weixin_36815313/article/details/108836458utm_source=app&app_version=4.20.0
由图可知,经过对四个轮子的方向进行控制,我们可以实现平移,原地旋转等传统轮子不能实现的功能,极大丰富了小车的灵活度。
3⃣️电路连接:
这是我们第二次加入了PID算法后的接线,由于Arduino UNO R3的接口不够,我们已经换成了Arduino mage2560.
其实这么复杂的接线我们也很头疼,板子和电池的固定也是一大问题,我们目前尝试通过面包板,简化我们的接线。同时由于电机的本身的线材不能直接的用在Arduino板上,我们自制了一种接线(忘记拍了,下次更新补)。也存在缺点,连接电机的时候稳定性不好,当然也还算不错,就是不能有100%的稳定性,我们目前计划通过改造原本线材达到目的。
4⃣️使用PWM调速:
PWM的使用需要支持PWM的引脚。
PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压
占空比:
是一个脉冲周期内,高电平的时间与整个周期时间的比例周期: 一个脉冲信号的时间
1s内测周期次数等于频率
脉宽时间: 高电平时间
上图中 脉宽时间占总周期时间的比例,就是占空比
使用上还是比较简单的,通过digitalWrite函数,使用PWM对引脚输出0~255的PWM波(255时速度最大),进而实现速度对控制
5⃣️优化小车行驶的平稳性(PID):
这个就是我们遇到的最大的挑战了,由于平常四个电机的转动不能保证速度的一致,因此会导致走直线时就容易变成曲线。因此我们需要一种方式使得四个轮子的速度一致。
PID算法就提供了很好的途径,PID算法有增量式和位置式,我们这次选择的是增量式,位置式我们还没有了解。
//后左电机端口定义 #define MotorLpin1 35 //控制位3 #define MotorLpin2 37 //控制位4 #define MotorLpwm 3 //使能调速 ENB #define MotorLcountA 18 //编码器A //后右电机端口定义 #define MotorRpin1 31 //控制位1 #define MotorRpin2 33 //控制位2 #define MotorRpwm 2 //使能调速 ENA #define MotorRcountA 19 //编码器A //前左电机端口定义 #define MotorfLpin1 41 //控制位3 #define MotorfLpin2 43 //控制位4 #define MotorfLpwm 5 //使能调速 ENB #define MotorfLcountA 20 //编码器Af //前右电机端口定义 #define MotorfRpin1 45 //控制位3 #define MotorfRpin2 47 //控制位4 #define MotorfRpwm 6 //使能调速 ENB #define MotorfRcountA 21 //编码器Af volatile float motorL=0;//中断变量,左轮子脉冲计数 volatile float motorfL=0;//中断变量,前左轮子脉冲计数 volatile float motorR=0;//中断变量,右轮子脉冲计数 volatile float motorfR=0;//中断变量,前右轮子脉冲计数 float V_L=0; //左轮速度 单位cm/s float V_fL=0; float V_R=0; //右边轮速 单位cm/s float V_fR=0; int v1=0; //单位cm/s int v2=0; //单位cm/s int vf1=0; int vf2=0; float Target_V_L=50,Target_V_R=50;//单位cm/s float Target_V_fL=50,Target_V_fR=50; int Pwm_L=0,Pwm_R=0; //左右轮PWM int Pwm_fL=0,Pwm_fR=0; //PID变量 float kp=10,ki=0,kd=4; //PID参数 /************************************** * Arduino初始化函数 * *************************************/ void setup() { Motor_Init();//电机端口初始化 Serial.begin(9600);//开启串口 } /********************************************************* * 函数功能:增量式PI控制器(左轮) * 入口参数:当前速度(编码器测量值),目标速度 * 返回 值:电机PWM * 参考资料: * 增量式离散PID公式: * Pwm-=Kp*[e(k)-e(k-1)]+Ki*e(k)+Kd*[e(k)-2e(k-1)+e(k-2)] * e(k):本次偏差 * e(k-1):上一次偏差 * e(k-2):上上次偏差 * Pwm:代表增量输出 * 在速度闭环控制系统里面我们只使用PI控制,因此对PID公式可简化为: * Pwm-=Kp*[e(k)-e(k-1)]+Ki*e(k) * e(k):本次偏差 * e(k-1):上一次偏差 * Pwm:代表增量输出 * * 注意增量式PID先调I,再调P,最后再调D *********************************************************/ int Incremental_Pi_L(int current_speed,int target_speed){ static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差 bias=current_speed-target_speed; //计算本次偏差e(k) pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器 prev_bias=last_bias; //保存上上次偏差 last_bias=bias; //保存上一次偏差 //PWM 限幅度 Arduino的PWM 最高为255 限制在250 if(pwm<-250){ pwm=250; } if(pwm>250){ pwm=250; } //Serial.println(pwm); return pwm; //增量输出 } //右轮速度增量式PID控制器 int Incremental_Pi_R(float current_speed,float target_speed){ static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差 bias=current_speed-target_speed; //计算本次偏差e(k) pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器 prev_bias=last_bias; //保存上上次偏差 last_bias=bias; //保存上一次偏差 //PWM 限幅度 Arduino的PWM 最高为255限制在250 if(pwm<-250){ pwm=250; } if(pwm>250){ pwm=250; } //Serial.println(pwm); return pwm; //增量输出 } int Incremental_Pi_fL(int current_speed,int target_speed){ static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差 bias=current_speed-target_speed; //计算本次偏差e(k) pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器 prev_bias=last_bias; //保存上上次偏差 last_bias=bias; //保存上一次偏差 //PWM 限幅度 Arduino的PWM 最高为255 限制在250 if(pwm<-250){ pwm=250; } if(pwm>250){ pwm=250; } //Serial.println(pwm); return pwm; //增量输出 } int Incremental_Pi_fR(int current_speed,int target_speed){ static float pwm,bias,last_bias,prev_bias; //静态变量存在程序全周期:pwm:增量输出,bias:本次偏差,last_bias:上次偏差,prev_bais_:上上次偏差 bias=current_speed-target_speed; //计算本次偏差e(k) pwm-=(kp*(bias-last_bias)+ki*bias+kd*(bias-2*last_bias+prev_bias)); //增量式PID控制器 prev_bias=last_bias; //保存上上次偏差 last_bias=bias; //保存上一次偏差 //PWM 限幅度 Arduino的PWM 最高为255 限制在250 if(pwm<-250){ pwm=250; } if(pwm>250){ pwm=250; } //Serial.println(pwm); return pwm; //增量输出 } /**************************************************************************(测试完成) 函数功能:设置双轮工作模式和运动速度 入口参数:工作模式,左右轮pwm 返回 值:无 **************************************************************************/ void Set_Pwm(int mode,int speed_L,int speed_R){ if(mode==1){ //前进模式 //左电机 digitalWrite(MotorLpin1,LOW); digitalWrite(MotorLpin2,HIGH); analogWrite(MotorLpwm,speed_L); //右电机 digitalWrite(MotorRpin1,HIGH); digitalWrite(MotorRpin2,LOW); analogWrite(MotorRpwm,speed_R); }else if(mode==2){ //后退模式 //左电机 digitalWrite(MotorLpin1,HIGH); digitalWrite(MotorLpin2,LOW); analogWrite(MotorLpwm,speed_L); //右电机 digitalWrite(MotorRpin1,LOW); digitalWrite(MotorRpin2,HIGH); analogWrite(MotorRpwm,speed_R); }else if(mode==3){ //左转模式 //左电机 digitalWrite(MotorLpin1,HIGH); digitalWrite(MotorLpin2,LOW); analogWrite(MotorLpwm,speed_L); //右电机 digitalWrite(MotorRpin1,HIGH); digitalWrite(MotorRpin2,LOW); analogWrite(MotorRpwm,speed_R); }else if(mode==4){ //右转模式 //左电机 digitalWrite(MotorLpin1,LOW); digitalWrite(MotorLpin2,HIGH); analogWrite(MotorLpwm,speed_L); //右电机 digitalWrite(MotorRpin1,LOW); digitalWrite(MotorRpin2,HIGH); analogWrite(MotorRpwm,speed_R); } } void Setf_Pwm(int mode,int speed_fL,int speed_fR){ if(mode==1){ //前进模式 //左电机 digitalWrite(MotorfLpin1,LOW); digitalWrite(MotorfLpin2,HIGH); analogWrite(MotorfLpwm,speed_fL); //右电机 digitalWrite(MotorfRpin1,HIGH); digitalWrite(MotorfRpin2,LOW); analogWrite(MotorfRpwm,speed_fR); }else if(mode==2){ //后退模式 //左电机 digitalWrite(MotorfLpin1,HIGH); digitalWrite(MotorfLpin2,LOW); analogWrite(MotorfLpwm,speed_fL); //右电机 digitalWrite(MotorfRpin1,LOW); digitalWrite(MotorfRpin2,HIGH); analogWrite(MotorfRpwm,speed_fR); }else if(mode==3){ //左转模式 //左电机 digitalWrite(MotorfLpin1,HIGH); digitalWrite(MotorfLpin2,LOW); analogWrite(MotorfLpwm,speed_fL); //右电机 digitalWrite(MotorfRpin1,HIGH); digitalWrite(MotorfRpin2,LOW); analogWrite(MotorfRpwm,speed_fR); }else if(mode==4){ //右转模式 //左电机 digitalWrite(MotorfLpin1,LOW); digitalWrite(MotorfLpin2,HIGH); analogWrite(MotorfLpwm,speed_fL); //右电机 digitalWrite(MotorfRpin1,LOW); digitalWrite(MotorfRpin2,HIGH); analogWrite(MotorfRpwm,speed_fR); } } /**************************************************************************(测试完成) 函数功能:电机端口初始化,控制芯片引脚拉低 入口参数:无 返回 值:无 **************************************************************************/ void Motor_Init(){ //左电机 pinMode(MotorLpin1,OUTPUT); //驱动芯片控制引脚 pinMode(MotorLpin2,OUTPUT); //驱动芯片控制引脚 pinMode(MotorLpwm,OUTPUT); //驱动芯片控制引脚,PWM调速 pinMode(MotorLcountA,INPUT); //左轮编码器A引脚 //右电机 pinMode(MotorRpin1,OUTPUT); //驱动芯片控制引脚 pinMode(MotorRpin2,OUTPUT); //驱动芯片控制引脚 pinMode(MotorRpwm,OUTPUT); //驱动芯片控制引脚,PWM调速 pinMode(MotorRcountA,INPUT); //右轮编码器A引脚 //驱动芯片控制引脚全部拉低 digitalWrite(MotorLpin1,LOW); //左电机 digitalWrite(MotorLpin2,LOW); digitalWrite(MotorLpwm,LOW); digitalWrite(MotorRpin1,LOW); //右电机 digitalWrite(MotorRpin2,LOW); digitalWrite(MotorRpwm,LOW); //左电机 pinMode(MotorfLpin1,OUTPUT); //驱动芯片控制引脚 pinMode(MotorfLpin2,OUTPUT); //驱动芯片控制引脚 pinMode(MotorfLpwm,OUTPUT); //驱动芯片控制引脚,PWM调速 pinMode(MotorfLcountA,INPUT); //左轮编码器A引脚 //右电机 pinMode(MotorfRpin1,OUTPUT); //驱动芯片控制引脚 pinMode(MotorfRpin2,OUTPUT); //驱动芯片控制引脚 pinMode(MotorfRpwm,OUTPUT); //驱动芯片控制引脚,PWM调速 pinMode(MotorfRcountA,INPUT); //右轮编码器A引脚 //驱动芯片控制引脚全部拉低 digitalWrite(MotorfLpin1,LOW); //左电机 digitalWrite(MotorfLpin2,LOW); digitalWrite(MotorfLpwm,LOW); digitalWrite(MotorfRpin1,LOW); //右电机 digitalWrite(MotorfRpin2,LOW); digitalWrite(MotorfRpwm,LOW); } /*********************************** * 电机实际速度计算: * 公式: * 已知参数: * 车轮直径65mm, * 左边轮子一圈:390脉冲(RISING), * 右边轮子一圈:390脉冲(RISING), * 单位时间读两个轮子脉冲读取两个轮子脉冲 ***********************************/ void Read_Moto_V(){ unsigned long nowtime=0; motorL=0; motorR=0; nowtime=millis()+50;//读50毫秒 attachInterrupt(digitalPinToInterrupt(MotorLcountA),Read_Moto_L,RISING);//左轮脉冲开中断计数 attachInterrupt(digitalPinToInterrupt(MotorfLcountA),Read_Moto_fL,RISING);//左轮脉冲开中断计数 attachInterrupt(digitalPinToInterrupt(MotorRcountA),Read_Moto_R,RISING);//右轮脉冲开中断计数 attachInterrupt(digitalPinToInterrupt(MotorfRcountA),Read_Moto_fR,RISING);//前右轮脉冲开中断计数 while(millis()<nowtime); //达到50毫秒关闭中断 detachInterrupt(digitalPinToInterrupt(MotorLcountA));//左轮脉冲关中断计数 detachInterrupt(digitalPinToInterrupt(MotorfLcountA));//左轮脉冲关中断计数 detachInterrupt(digitalPinToInterrupt(MotorRcountA));//右轮脉冲关中断计数 detachInterrupt(digitalPinToInterrupt(MotorfRcountA));//右轮脉冲关中断计数 V_L=((motorL/390)*6.5*PI)/0.05; //单位cm/s V_fL=((motorfL/390)*6.5*PI)/0.05; //单位cm/s V_R=((motorR/390)*6.5*PI)/0.05; //单位cm/s V_fR=((motorfR/390)*6.5*PI)/0.05; //单位cm/s v1=V_L; vf1=V_fL; v2=V_R; vf2=V_fR; } /*************************** * 中断函数:读左轮脉冲 * **************************/ void Read_Moto_L(){ motorL++; } void Read_Moto_fL(){ motorfL++; } /************************** * 中断函数:读右轮脉冲 * *************************/ void Read_Moto_R(){ motorR++; } void Read_Moto_fR(){ motorfR++; } /*************************************** * Arduino主循环 * ***************************************/ void loop() { Read_Moto_V();//读取脉冲计算速度 Pwm_L=Incremental_Pi_L(V_L,Target_V_L);//左轮PI运算 Pwm_fL=Incremental_Pi_fL(V_fL,Target_V_fL);//前左轮PI运算 Pwm_R=Incremental_Pi_R(V_R,Target_V_R);//右轮PI运算 Pwm_fR=Incremental_Pi_fR(V_fR,Target_V_fR);//右轮PI运算 Serial.print(V_L);//直接用串口绘图画出速度曲线 Serial.print(","); Serial.print(V_R);//直接用串口绘图画出速度曲线 Serial.print(","); Serial.print(V_fR); Serial.print(","); Serial.println(V_fL); Set_Pwm(1,Pwm_L,Pwm_R); //设置左右轮速度 Setf_Pwm(1,Pwm_fL,Pwm_fR); //设置左右轮速度 }
由于我们对参数的调节还不是很熟练,以及一个编码器出现了问题,我们并没有完全实现利用PID算法控制小车的运动。而且可能因为机械误差的问题,我们的还不能实现轮子的速度都保持一致。我们预计这两天内会解决问题。
6⃣️为小车增加无线模块进行控制:
我们之前想实现对小车的无线控制,我们了解了几种方案:
1⃣️基于红外的遥控。
2⃣️:基于2.4G的JDY-40和蓝牙以及利用S-BUS传输的航模遥控器的控制。优点:控制距离长,受干扰小。缺点:配置时间长,难以驾驭!!!
基于此我们使用了红外的控制,其它的实现方式会在我们完成PID算法后再进行研究。
#include <IRremote.h> // 使用IRRemote函数库 ///选择/// #define choose 2 //1为通过串口打印码值模式 //2为主函数运行模式 //-------------------------------------------------------------------// //*******************************************************************// /// //电机设置/ /// #define leftA_PIN 5 #define leftB_PIN 6 #define righA_PIN 9 #define righB_PIN 10 void motor_pinint( ); //引脚初始化 void forward( ); //前进 void back( ); //后退 void turnLeftOrigin( ); //原地左 void turnRightOrigin( ); //原地右 void turnRightforword( ); //右前 void turnLeftforword( ); //左前 void turnLeftback( ); //左后 void turnRightback( ); //右后 void _stop(); //停车 //-------------------------------------------------------------------// //*******************************************************************// /// //红外遥控/ /// const int irReceiverPin = 2; // 红外接收器的 OUTPUT 引脚接在 PIN2 接口 定义irReceiverPin变量为PIN2接口 IRrecv irrecv(irReceiverPin); // 设置irReceiverPin定义的端口为红外信号接收端口 decode_results results; // 定义results变量为红外结果存放位置 void rev(void); void scan(void); //-------------------------------------------------------------------------// void setup() { Serial.begin(9600); //9600(PC端使用) motor_pinint(); //电机引脚初始化 irrecv.enableIRIn(); // 启动红外解码 } void loop() { if(choose==1) scan(); else if(choose==2) rev(); } /*电机引脚初始化*/ void motor_pinint( ) { pinMode (leftA_PIN, OUTPUT); //设置引脚为输出引脚 pinMode (leftB_PIN, OUTPUT); //设置引脚为输出引脚 pinMode (righA_PIN, OUTPUT); //设置引脚为输出引脚 pinMode (righB_PIN, OUTPUT); //设置引脚为输出引脚 } /************************************************** forward子函数——前进子函数 函数功能:控制车前进 **************************************************/ void forward( ) { analogWrite(leftA_PIN,180); analogWrite(leftB_PIN,0); //左轮前进 analogWrite(righA_PIN,180); analogWrite(righB_PIN,0); //右轮前进 } /************************************************** back子函数——后退子函数 函数功能:控制车后退 **************************************************/ void back( ) { analogWrite(leftA_PIN,0); analogWrite(leftB_PIN,180); //左轮后退 analogWrite(righA_PIN,0); analogWrite(righB_PIN,180); //右轮后退 } /************************************************** turnLeftOrigin子函数——原地左转子函数 函数功能:控制车原地左转 **************************************************/ void turnLeftOrigin( ) { analogWrite(leftA_PIN,0); analogWrite(leftB_PIN,120); //左轮后退 analogWrite(righA_PIN,120); analogWrite(righB_PIN,0); //右轮前进 } /************************************************** turnRightOrigin子函数——原地右转子函数 函数功能:控制车原地右转 **************************************************/ void turnRightOrigin( ) { analogWrite(leftA_PIN,120); analogWrite(leftB_PIN,0); //左轮前进 analogWrite(righA_PIN,0); analogWrite(righB_PIN,120); //右轮后退 } /************************************************** turnRightforword子函数——右前运动子函数 函数功能:控制车右前 **************************************************/ void turnRightforword( ) { analogWrite(leftA_PIN,200); analogWrite(leftB_PIN,0); //左轮快前进 analogWrite(righA_PIN,120); analogWrite(righB_PIN,0); //右轮慢前进 } /************************************************** turnLeftforword子函数——左前运动子函数 函数功能:控制车左前 **************************************************/ void turnLeftforword( ) { analogWrite(leftA_PIN,120); analogWrite(leftB_PIN,0); //左轮慢前进 analogWrite(righA_PIN,200); analogWrite(righB_PIN,0); //右轮快前进 } /************************************************** turnRightforword子函数——右后运动子函数 函数功能:控制车右后 **************************************************/ void turnRightback( ) { analogWrite(leftA_PIN,0); analogWrite(leftB_PIN,200); //左轮快后退 analogWrite(righA_PIN,0); analogWrite(righB_PIN,120); //右轮慢后退 } /************************************************** turnLeftforword子函数——左后运动子函数 函数功能:控制车左后 **************************************************/ void turnLeftback( ) { analogWrite(leftA_PIN,0); analogWrite(leftB_PIN,120); //左轮慢后退 analogWrite(righA_PIN,0); analogWrite(righB_PIN,200); //右轮快后退 } /************************************************** stop子函数—停止子函数 函数功能:控制车停止 **************************************************/ void _stop() { analogWrite(leftA_PIN,0); analogWrite(leftB_PIN,0); //左轮静止不动 analogWrite(righA_PIN,0); analogWrite(righB_PIN,0); //右轮静止不动 } void rev(void) { if (irrecv.decode(&results)) { // 解码成功,把数据放入results.value变量中 if ((results.value==16718055)||(results.value==1033561079)) {forward( ) ;delay(500);_stop();}//2前进 else if((results.value==465573243)||(results.value==16730805)||(results.value==304335233)||(results.value==891929274)||(results.value==93040025)) {back( ) ;delay(500);_stop();}//8后退 else if((results.value==16724175)||(results.value==814588342)||(results.value==2534850111)||(results.value==16724175)) {turnLeftforword( ) ;delay(500);_stop();}//1左前 else if((results.value==16743045)||(results.value==1635910171)||(results.value==16743045)) {turnRightforword( );delay(500);_stop();}//3右前 else if((results.value==1209942246)||(results.value==851901943)||(results.value==16728765)) {turnLeftback( ) ;delay(500);_stop();}//7左后 else if((results.value==16732845)||(results.value==1623741183)) {turnRightback( ) ;delay(500);_stop();}//9右后 else if((results.value==2351064443)||(results.value==16716015)||(results.value==3640844469)||(results.value==3606423579)) {turnLeftOrigin( ) ;delay(250);_stop();}//4原地左转 else if((results.value==16734885)||(results.value==71952287)) {turnRightOrigin( ) ;delay(250);_stop();}//6原地右转 irrecv.resume(); // 继续等待接收下一组信号 }if(results.value==0x16) delay(600); //延时600毫秒,做一个简单的消抖 } void scan(void) { if (irrecv.decode(&results)) { // 解码成功,把数据放入results变量中 // 把数据输入到串口 Serial.print("irCode: "); Serial.print(results.value, DEC); // 显示红外编码 Serial.print(", bits: "); Serial.println(results.bits); // 显示红外编码位数 irrecv.resume(); // 继续等待接收下一组信号 }if(results.value==0x16) digitalWrite(9, HIGH); delay(600); //延时600毫秒,做一个简单的消抖 }