之前偶然间了解到Arduino,脑子一热果断入手一套简单的小车开发套件,后来由于忙些其他的东西,就把它丢在角落里吃灰了……上个月正好表妹过生日,决定弄一弄也算准备一个诚意满满的小礼物了;这也是第一次接触硬件编程,也算是个小挑战。
由于只是入门级别的套件,像超声波,舵机,直流电机等配件的代码都是现成的,只需要配置开发环境,写自己的小车运行逻辑就行了,忍不住吐槽一下黑心商家的配件,各种问题搞得开发过程中莫名其妙的被坑……
安装好开发软件,把开发板接入电脑就可以写代码了,开发板接入电脑后先看看端口号:
然后开发软件中记得选择对应的端口,不然无法烧录程序。
新建一个项目,发现自动生成2个函数:
void setup()函数是初始化函数,里面的语句只会执行一次,一般用来设置硬件的引脚;void loop()函数是程序运行函数,里面的语句会重复执行(有点类似createjs的Ticker类),下面贴一个简单LED灯闪烁代码。
void setup(){
pinMode(11, OUTPUT); //将11号引脚上拉输出
}
void loop(){
digitalWrite(11,HIGH); //设置11号引脚位高电平
delay(1000);
digitalWrite(11,LOW); //设置11号引脚为低电平
delay(1000); // 闪烁时间间隔为1S
}
写完代码需要先编译再烧录到开发板里才能看到效果,有些复杂的配件需要监控返回值,比如超声波要看返回检测到障碍物的距离,红外遥控要看返回按键的键值,这就要用到串口监视器了;写好代码,每次按下红外遥控器,串口监视器会返回键值:
Serial.print(results.value);//返回当前按键值
注意串口监视器下面的波特率要和我们设置的一致。
Serial.begin(9600);
使用自带的开发界面写代码很不习惯,可以在首选项里设置使用外部编辑器,这样软件会把开发页面锁死,只能通过其他编辑器写代码了,这里我用sublime text(语言选择C++代码才会高亮显示)。
下面贴个全部源码,留个备份:
#include
#include
long control;
boolean car_automatic_move = false;
boolean car_trajectory = false;
//红外避障模块
// long SL;
//红外接收模块
int RECV_PIN = 11;//管脚
//舵机
int servopin = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;
long unsigned int return_decode() {
if (irrecv.decode(&results)) {
irrecv.resume();
Serial.print(results.value);//返回当前按键值
return results.value;
}
else
{
return 0;
irrecv.resume();
}
}
void setup() {
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(4, INPUT);
pinMode(7, INPUT);
pinMode(8, INPUT);
pinMode(A0, INPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
irrecv.enableIRIn();//初始化红外遥控
}
void loop() {
// SL = digitalRead(A0);//左避障管脚
// if (car_automatic_move && SL == 0) {//左避障触发
// car_forward();
// }
control = return_decode();
if (control == 16712445) {//前进
car_forward();
delay(500);
car_stop();
} else if (control == 16720605) {//后退
car_back();
delay(500);
car_stop();
} else if (control == 16769055) {// -
car_left();
delay(150);
car_stop();
} else if (control == 16754775) {// +
car_right();
delay(150);
car_stop();
} else if (control == 16761405) {//暂停
car_stop();
car_automatic_move = false;
} else if (control == 16748655) {//EQ
car_automatic_move = true;
} else if (control == 16750695) {//100+
} else if (control == 16756815) {//200+
} else if (control == 16738455) {//0 原地打转
car_left();
} else if (control == 16753245) {//CH-
servopulse(servopin, 180);
} else if (control == 16769565) {//CH+
servopulse(servopin, 0);
} else if (control == 16736925) {//CH
servopulse(servopin, 65);
}
// car_line();
car_automatic();
}
void car_forward() {//前进
analogWrite(3, 0);
analogWrite(5, 255);
analogWrite(6, 255);
analogWrite(9, 0);
}
void car_back() {//后退
analogWrite(3, 255);
analogWrite(5, 0);
analogWrite(6, 0);
analogWrite(9, 255);
}
void car_stop() {//停车
analogWrite(3, 0);
analogWrite(5, 0);
analogWrite(6, 0);
analogWrite(9, 0);
}
void car_left() {//左转
analogWrite(3, 255);
analogWrite(5, 0);
analogWrite(6, 255);
analogWrite(9, 0);
}
void car_right() {//右转
analogWrite(3, 0);
analogWrite(5, 255);
analogWrite(6, 0);
analogWrite(9, 255);
}
void car_line() {//红外循迹
if (car_trajectory) {
if (digitalRead(4)) {//左探头
Serial.print("left");
}
if (digitalRead(2)) {//右探头
Serial.print("right");
}
}
}
long speedF;
long speedL;
long speedR;
// 超声波检测距离
int ardublockUltrasonicSensorCodeAutoGeneratedReturnCM(int trigPin, int echoPin) {
long duration;
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(20);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
duration = duration / 59;
return duration;
}
//定义一个脉冲函数
void servopulse(int servopin, int myangle) {
int pulsewidth, count;
for (count = 0; count < 25; count++)
{
pulsewidth = (myangle * 11) + 500; //将角度转化为500-2480的脉宽值
digitalWrite(servopin, HIGH); //将舵机接口电平至高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin, LOW); //将舵机接口电平至低
delay(20 - pulsewidth / 1000);
}
}
// 测量前方距离
int range_F() {
speedF = ardublockUltrasonicSensorCodeAutoGeneratedReturnCM(7, 8) ;
Serial.print("speedF:");
Serial.println(speedF);
return speedF;
}
// 自动行驶
void car_automatic() {
if (car_automatic_move) {
car_forward();
if (range_F() <= 18) {
car_stop();
car_automatic_move = false;
delay(300);
servopulse(servopin, 20);
if (range_F() > 18) { //检测右方距离
servopulse(servopin, 65);
car_right();
delay(120);
car_automatic_move = true;
} else if (range_F() <= 18) { //检测右方距离
delay(300);
servopulse(servopin, 110);
if (range_F() > 18) { //检测左方距离
servopulse(servopin, 65);
car_left();
delay(120);
car_automatic_move = true;
} else if (range_F() <= 18) { //检测左方距离
car_back();
servopulse(servopin, 65);
delay(120);
car_right();
delay(120);
car_automatic_move = true;
}
}
}
}
}
本来要写红外避障模块的,可惜有一个红外避障配件是坏的,而且红外感应器“怕太阳光”,即使没有直接被阳光直射到,白天在室内也可能被太阳热辐射影响到红外信号,避障变成“智障”……一个直流电机也有问题,只有设置电流参数255才会工作,所以无法调整小车的行驶速度,再次吐槽一下黑心商家……