电机控制系统选用常用的L298N,其有四路PWM电机控制信号输出,是做小车的上佳之选。
红外对管
L298N电机驱动块
继电器
自锁开关
AMS1117线性稳压模块
电机马达
代码
int mode = 1; //模式 模式=1时,为自动控制模式 模式=0是为蓝牙控制模式
String data = ""; //定义一个字符串类型data 用来储存接收到的数据
bool flag = false; // 接收完成标志位
#define IN1 3 //定义引脚4是IN1
#define IN2 5 //定义引脚4是IN1
#define IN3 6 //定义引脚4是IN1
#define IN4 11 //定义引脚4是IN1
#define hwdg1 10 //第一个红外对管是10号引脚,名字为hwdg1
#define hwdg2 7 //第二个红外对管是7号引脚,名字为hwdg1
#define hwdg3 9 //第四个红外对管是9号引脚,名字为hwdg1
#define hwdg4 8 //第五个红外对管是8号引脚,名字为hwdg1
#define hwdg5 2 //第三个红外对管是2号引脚,名字为hwdg1
#define zskg 4 //自锁开关 定义引脚为4号引脚
int zskg_flag=0; //自锁开关的模式标志位 模式=0,停止扫地 模式=1开始扫地
#define jdq 12 //定义继电器为12号引脚
void setup() {
Serial.begin(9600);//串口开始 波特率是9600 是的是1s或者1ns传输一个周期的数据
pinMode(IN1, OUTPUT); //引脚输出1
pinMode(IN2, OUTPUT); //引脚输出2
pinMode(IN3, OUTPUT); //引脚输出3
pinMode(IN4, OUTPUT); //引脚输出4
pinMode(jdq, OUTPUT); //继电器引脚输出
pinMode(hwdg1, INPUT);//红外对管1模式为输入
pinMode(hwdg2, INPUT);//红外对管2模式为输入
pinMode(hwdg3, INPUT);//红外对管3模式为输入
pinMode(hwdg4, INPUT);//红外对管4模式为输入
pinMode(hwdg5, INPUT);//红外对管5模式为输入
pinMode(zskg, INPUT_PULLUP);//自锁开关模式为上拉输入,不按下时为1,按下时接地为0 为0开启扫地
}
void loop()
{
data_chuli(); //接收串口的数据
if (mode == 1)
{
zidong_mode(); //自动模式
}
saodi(); //扫地开关
}
/*
* 串口中断接收和串口处理函数
*/
void data_chuli()
{
if (flag) //如果串口中断接收完成
{
Serial.println(data);
if (data == '0') //如果data为0,全停 刹车
{
stod(1);
}
if (data == '1') //IN1 IN2 高低 IN3 IN4 高低 前进
{
qj();
}
if (data == '2') //IN1 IN2 低高 IN3 IN4 低高 后退
{
ht(1);
}
if (data == '3') //IN1 IN2 高低 IN3 IN4 低高 左转,靠反向力去转
{
zz();
}
if (data == '4') //IN1 IN2 低高 IN3 IN4 高低 右转,靠反向力去转
{
yz();
}
if (data == '5') //模式1
{
mode = 1;
}
if (data == '6') //模式0
{
mode = 0;
}
if (data == '7') //扫地模式1 打开扫地
{
zskg_flag = 1;
}
if (data == '8') //扫地模式0 关闭扫地
{
zskg_flag = 0;
}
flag=false; //还原串口标志位
data = ""; //清空串口数据等待下一次数据
}
}
void serialEvent() //串口中断函数
{
while (Serial.available()) {
char inChar = (char)Serial.read();
data += inChar;
delay(1);
flag = true;
}
}
/*
* 小车前进后退右转左转代码
*/
void disu_qj()
{
analogWrite(IN1, 110); //速度100
digitalWrite(IN2, LOW);
analogWrite(IN3, 120);
digitalWrite(IN4, LOW);
}
void disu_ht()
{
digitalWrite(IN1, LOW);
analogWrite(IN2, 150); //速度100
digitalWrite(IN3, LOW);
analogWrite(IN4, 150);
}
void disu_yz()
{
analogWrite(IN1, 0); //速度100
analogWrite(IN2, 150); //速度100
analogWrite(IN3, 150); //速度100
analogWrite(IN4, 0);
}
void disu_zz()
{
analogWrite(IN1, 150); //速度100
analogWrite(IN2, 0); //速度100
analogWrite(IN3, 0); //速度100
analogWrite(IN4, 150);
}
void qj()
{
digitalWrite(IN1, 1);
digitalWrite(IN2, 0);
digitalWrite(IN3, 1);
digitalWrite(IN4, 0);
}
void ht(int time)
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, 1);
digitalWrite(IN3, LOW);
digitalWrite(IN4, 1);
delay(time);
}
void zz()
{
digitalWrite(IN1, 1);
digitalWrite(IN2, 0);
digitalWrite(IN3, 0);
digitalWrite(IN4, 1);
}
void yz()
{
digitalWrite(IN1, 0);
digitalWrite(IN2, 1);
digitalWrite(IN3, 1);
digitalWrite(IN4, 0);
}
void stod(int time)
{
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
delay(time);
}
void err() //防止卡死或者有可能出现的错误情况
{
if (digitalRead(hwdg2) == 0 && digitalRead(hwdg3) == 0)
{
ht(500);
}
}
/**自动扫地函数**/
void zidong_mode() //自动模式
{
// Serial.println(String("z:") + digitalRead(hwdg2)); //打印调试
// Serial.println(String("r:") + digitalRead(hwdg3));
// Serial.println(String("l:") + digitalRead(hwdg1));
if (digitalRead(hwdg5) == 0) //如果中间红外对管检测到障碍物
{
delay(5);
err();
if (digitalRead(hwdg5) == 0)
{
ht(500);
delay(500);
stod(300);
}
}
else if (digitalRead(hwdg2) == 0) //如果第二个红外对管检测到障碍物
{
delay(5);
err();
if (digitalRead(hwdg2) == 0)
{
ht(500);
disu_yz();
delay(500);
}
}
else if (digitalRead(hwdg3) == 0)//如果第三个红外对管检测到障碍物
{
delay(5);
err();
if (digitalRead(hwdg3) == 0)
{
ht(500);
disu_zz();
delay(500);
}
}
else if (digitalRead(hwdg1) == 0) //如果第一个红外对管检测到障碍物
{ delay(5);
if (digitalRead(hwdg1) == 0)
{
ht(300);
disu_yz();
delay(200);
}
}
else if (digitalRead(hwdg4) == 0)//如果第四个红外对管检测到障碍物
{ delay(5);
if (digitalRead(hwdg4) == 0)
{
ht(300);
disu_zz();
delay(200);
}
}
else {
disu_qj(); //否则都没有障碍物 那就前进
}
}
void saodi()
{
// Serial.println(String("4:") + digitalRead(zskg));
if (digitalRead(zskg) == 0 || zskg_flag==1) //如果按钮按下接地 或者 自锁开关标志位==1(这是串口控制的)
{ delay(20);
if (digitalRead(zskg) == 0 || zskg_flag==1)
{
digitalWrite(jdq, 1); //继电器闭合
}
} else {
digitalWrite(jdq, 0); //继电器断开
}
}