大一下学期接触了ARDUINO 这个开源的嵌入式开发,利用一学期的时间只学了些基本的东西,再加上专业课程在学C语言,所以学起来相对比较轻松,但是大多都是理论上的东西还是觉得没有什么成就感,在网上看到大佬自己做的项目很羡慕,看到很多讲做智能小车的刚好这些知识我基本都具备而且又比较感兴趣所以打算将这个小项目作为我的学习的验证。(由于有很多大佬写的都很好,本文章只是自己做小车的一些体会经验,若存在不足,望海涵)
我所用的材料全都是在某宝上买的,智能车套件很多,价格也相差很大。
小车套件,我用的是某宝上购得的4WD底板
驱动模块:L298N电机驱动模块,这个模块比较经典而且我从网上查看的来看他的驱动能力强,关于这个模块的介绍也有很多,由于我水平低这里也就不介绍。
电池我选用的是18650电池,因为想要带动电机,L298N需要独立电源供电,且需要的功率很大,我最开始的想法是用arduino的DC线给arduino供电,显然这是一个愚蠢的想法。arduino的输出电压是5V,而L298N的输入电压一般是在5~12v,并且arduino的输出太小了,一定要给L298N独立电源,至于arduino的供电则可以由L298N的5V输出端提供。
HC-06无线蓝牙透传模块这是比较经典的蓝牙模块,在这里同样不对他做详细的介绍,网上有很多大佬的文章可以参考
迷你面包板一个由于接线很复杂看起来很乱,可以选择一个面包板方便接线,当然也可以选择不要
SG90舵机+云台+HC-SR04超声波模块,这一套就是拿来让小车测障碍物距离避障用的
主板,这是小车的控制核心,因为是新手,所以我用的是arduino uno开发板
底盘的拼装卖家会给教程,我讲的是我在各个模块拼装时遇到的问题以及经验
首先,在搭建模块时候建议将UNO板的TX,RX引脚留下给蓝牙模块,当然你也可以选择其它引脚搭建软件串口,但是将蓝牙连接在UNO板的TX,RX上有个弊端,每次你上传程序时或者用计算机的串口监视器都要将蓝牙模块的连接移除。除此之外还要预先留几个PWM引脚出来用于给电机调速,我一开始忘了这一细节,用到PWM的时候又折腾了一会儿。有个非常重要的地方就是所有模块都要共地也就是GND引脚全部都要接到一起。
由于出了点小差错(其实是我脑子犯浑,刚好在网上看到有人用充电宝做电源驱动小车,我也萌生了这个想法,当我实践才发现充电宝的功率根本带不动四驱车,等新买的电源又要一段时间,在这期间我阴差阳错发现两个轮子也能跑,只不过看起来有点奇怪,我想着反正电源到了也是一步一步升级小车的,不可能一步到位,在这之前我就简单的做了个只有两个轮子的(另外两个轮子被我拆下来了)的遥控车),其实2WD和4WD的区别就在于少了两个电机,程序和结构主体还是没变的
这个我只是使用了L298N和HC-06就可以实现了,而且代码也比较简单`
//初始化设置----------------------------------------------
const char Forward = 'f';
const char Backward = 'b';
const char Turn_left = 'l' ;
const char Turn_right = 'r' ;
const char Stop = 's';
const char Start = 'k';
#define right_backwardmotor1 2
#define right_backwardmotor2 4
#define left_backwardmotor1 7
#define left_backwardmotor2 8
#define left_pwm 9
#define right_pwm 10
uint8_t SPEED_LEVEL =100; //电机运行速度
#define SPEED_LEVEL_MAX 200 //手柄模式下电机最大速度
#define SPEED_LEVEL_MIN 100 //手柄模式下电机最小速度
//接受的指令
bool mode=1;//模式选择 'm=1',手柄模式 'm=0',自动模式
//---------------------------------------------------------
void setup() {
// put your setup code here, to run once:
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
Serial.begin(9600);
Serial.println("Arduino allready");
Serial.println("Please chose mode.");
Serial.println("The default mode is Joymode.");
}
void loop() {
while(Serial.available()>0){
char Cmd = Serial.read();
delay(1);
if(mode==1){
Serial.print("The Joy mode: ");
Serial.println(Cmd);
JoyMode(Cmd);//手柄模式
}
else{
Serial.print("The Auto mode: ");
Serial.println(Cmd);
AutoMode(Cmd);//自动模式
}
}
}
void JoyMode(char Cmd){//手柄模式函数
if(Cmd =='f' || Cmd == 'b' || Cmd == 'l' || Cmd == 'r'){
motorRun(Cmd,SPEED_LEVEL);
}
else{
switch(Cmd){
case 'm': //输入'm'切换模式
Serial.println("NOW, change to the Autonomic mode. LOADING...");
Serial.println("Welcome! Autonomic mode.");
mode=0;
break;
case 'c': //输入‘c’切换速度
if(SPEED_LEVEL < SPEED_LEVEL_MAX){
SPEED_LEVEL+=50;
Serial.print("The current speed: ");
Serial.println(SPEED_LEVEL);}
else if(SPEED_LEVEL == SPEED_LEVEL_MAX){
SPEED_LEVEL = SPEED_LEVEL_MIN;
Serial.print("The current speed: ");
Serial.println(SPEED_LEVEL);}
else{
Serial.println("Something wrong(From the speed.)");}
break;
}
}
}
void AutoMode(char Cmd){
SPEED_LEVEL = 100;
switch(Cmd){
case 'm':
mode = 1;
Serial.println("Now, change to the Joy mode. LOADING...");
Serial.println("Welcome! Joymode.");
break;
case 's':
motorRun(Cmd,SPEED_LEVEL);
Serial.println("Stop run.");
break;
case 'k':
Serial.println("Start run.");
break;
default:
Serial.println("In the autonomic mode, wrong command, please input command again!");
}
}
void motorRun(char Cmd, uint8_t SPEED_LEVEL){
switch(Cmd){
case Forward:
analogWrite(left_pwm,SPEED_LEVEL);
digitalWrite(left_backwardmotor1,HIGH);
digitalWrite(left_backwardmotor2,LOW);
analogWrite(right_pwm,SPEED_LEVEL);
digitalWrite(right_backwardmotor1,HIGH);
digitalWrite(right_backwardmotor2,LOW);
delay(200);
motorStop();
break;
case Backward:
analogWrite(left_pwm,SPEED_LEVEL);
digitalWrite(left_backwardmotor2,HIGH);
digitalWrite(left_backwardmotor1,LOW);
analogWrite(right_pwm,SPEED_LEVEL);
digitalWrite(right_backwardmotor1,LOW);
digitalWrite(right_backwardmotor2,HIGH);
delay(200);
motorStop();
break;
case Turn_left:
analogWrite(left_pwm,SPEED_LEVEL);
digitalWrite(left_backwardmotor2,HIGH);
digitalWrite(left_backwardmotor1,LOW);
analogWrite(right_pwm,SPEED_LEVEL);
digitalWrite(right_backwardmotor1,HIGH);
digitalWrite(right_backwardmotor2,LOW);
delay(100);
motorStop();
break;
case Turn_right:
analogWrite(left_pwm,SPEED_LEVEL);
digitalWrite(left_backwardmotor1,HIGH);
digitalWrite(left_backwardmotor2,LOW);
analogWrite(right_pwm,SPEED_LEVEL);
digitalWrite(right_backwardmotor2,HIGH);
digitalWrite(right_backwardmotor1,LOW);
delay(100);
motorStop();
break;
case Stop:
analogWrite(left_pwm,0);
analogWrite(right_pwm,0);
break;
default:
Serial.print("Wrong command!");
Serial.println("Please input true command again.");
}
}
void motorStop(){
analogWrite(left_pwm,0);
analogWrite(right_pwm,0);
}
下面解释一下代码以及贴上我遇到的问题
我记得最清楚的是当我在没用PWM调速之前一切测试基本顺利,第二天早上当我用上PWM后怎么也不能让轮子转起来,这可是折腾了我大半天,最后终于搞明白,L298N模块的ENA 和ENB 上的跳线帽是让它的引脚短路的,你把它拔了就一定要使用PWM波输出,哪怕是你要输出满电流或者零电流都必须用到PWM波输出,这样才能让正常L298N正常工作。程序的大概结构就是,小车默认为手柄模式也就是遥控模式,可以切换两个模式:自动模式和手柄模式,(自动模式里面没有代码,这只是我的一个基本框架后面可以慢慢加上模块后写代码),手柄模式就比较简单,接受串口发出的指令然后执行指令,可以在一个模式当中切换到另一个模式,然后将参数传到电机运行函数里面,值得注意的是每次电机转动后记得让它停下来,否则它一直处于通电的状态是不会停的,然后转向我不用说大家应该也能知道用差速转向就可以了,至于手机端的蓝牙控制我用的是Arduino Bluetooth.可以自定义按键可以选择手动发送数据。
(未完待续)