SmartCar蓝牙控制

小车搭建的这个项目,取名为【SmartCar】,这次更新的主版本为V2,小版本为V2.0.1.20170929,算是在原来的基础上有了较大的提升了。

SmartCar V2.0.1.20170929全部功能:

  1. 前进方向自动避障

  2. 前下方自动避障。可以在桌子上跑,不至于会掉下桌子

  3. 小车加入蓝牙模块,蓝牙模块与最小系统使用串口通信

  4. 手机app控制手机蓝牙与小车蓝牙通信,能做到启、停、左、右

接下来,会对这个版本进行优化,使App能更方便的控制小车    

记录下这个项目中经过的坑:

Android端

对于 Android 开发,话的时间比较长的是 Android 蓝牙开发,整个过程耗费了大概4天的业余时间,具体详情可以参考 Android 蓝牙开发
 Android App 界面截图:
微信图片_20170929110634.png

界面只是做了基本的控制和状态显示,项目见 github:https://github.com/xiongxianhe/SmartCar

小车端

小车端的坑主要是蓝牙模块的连接以及调试

蓝牙完全测试
在拿到蓝牙模块时,首先是确定它能不能正常的工作,所以先来简单测试,测试流程:

  1. 将蓝牙线接好

  2. 小车上电

  3. 打开 pc 端串口工具

  4. 在 pc 端串口工具里发送 AT 相关指令,看是否有结果返回

蓝牙接线

整个测试流程中,蓝牙接线是第一步,也是比较麻烦的一步,线没接好,那整个流程就走不下去了,来张我用的这款蓝牙图片:
微信图片_20170929113929.jpg
 共有6个引脚:

  • STATE:在命令模式下(串口 AT 指令模式)接 gnd,正常工作下可悬空

  • RX:串口读引脚,注意它的与单片机的接发,一旦接错,收发数据就异常了。我在这里被坑了好久,我的是接板子的 TX 引脚 P31

  • TX:串口发送数据引脚

  • GND:接地

  • +5V:接 VCC

  • EN:在命令模式下接高电平(VCC),正常工作下可悬空

当时在测试的时候,就是这几根线没接好,反反复复测试了好久,才测试好。

小车控制代码:

#include "STC12C5A60S2.h"

include <intrins.h>

/** L293D 电机驱动 真值表

控制MOTO1
EN1&nbsp;&nbsp;IN1&nbsp;&nbsp;--&gt;&nbsp;OUT1&nbsp;
EN1&nbsp;&nbsp;IN2&nbsp;&nbsp;--&gt;&nbsp;OUT2

控制MOTO2
EN2&nbsp;&nbsp;IN3&nbsp;&nbsp;--&gt;&nbsp;OUT3&nbsp;
EN2&nbsp;&nbsp;IN4&nbsp;&nbsp;--&gt;&nbsp;OUT4

一个电机有两个接线端&nbsp;&nbsp;一根正电源线&nbsp;&nbsp;一根负电源线
    控制这两根线的高低电平,使电平高低反转,使电机旋转

**/

/****/
/ 电机1  右电机 /
sbit en1 = P1 ^ 3;
sbit in1 = P1 ^ 5;
sbit in2 = P1 ^ 6;
/ 电机2  左电机 /
sbit en2 = P1 ^ 4;
sbit in3 = P1 ^ 1;
sbit in4 = P1 ^ 0;

/ 红外传感器 /
sbit rp1 = P2 ^ 3;  // 右前
sbit rp2 = P2 ^ 4;  // 左前
sbit rp3 = P2 ^ 0;  // 右下
sbit rp4 = P2 ^ 1;   // 左下

sbit k1 = P3 ^ 0;
sbit k2 = P3 ^ 1;
sbit k3 = P3 ^ 2;

sbit led1 = P0 ^ 0;
sbit led2 = P0 ^ 1;
sbit led3 = P0 ^ 2;
sbit led7 = P0 ^ 6;
sbit led8 = P0 ^ 7;

unsigned char TEST = 0;
unsigned char start = 0;

unsigned char isInter = 0;
unsigned char recvData = 0;
unsigned char CAR_START     = 0x01;
unsigned char CAR_STOP      = 0x02;
unsigned char CAR_RIGHT     = 0x03;
unsigned char CAR_LEFT      = 0x04;
unsigned char CAR_FORWARD   = 0x05;
unsigned char CAR_BACK      = 0x06;

void delay500ms(void)   //误差 -0.000000000028us
{
    unsigned char a,b,c;
    for(c=189;c>0;c--)
        for(b=230;b>0;b--)
            for(a=33;a>0;a--);
}
void delay100ms(void)   //误差 -0.000000000006us
{
    unsigned char a,b,c;
    for(c=244;c>0;c--)
        for(b=8;b>0;b--)
            for(a=152;a>0;a--);
    nop();  //if Keil,require use intrins.h
    nop();  //if Keil,require use intrins.h
}

void delay10ms(void)   //误差 -0.000000000001us
{
    unsigned char a,b,c;
    for(c=199;c>0;c--)
        for(b=120;b>0;b--)
            for(a=1;a>0;a--);
}

// 停止
void Stop()
{
en1 = 0;
en2 = 0;
}

// 向前
void Forward()
{
en1 = 1;
en2 = 1;
in1 = 1;
in2 = 0;
in3 = 1;
in4 = 0;
}
// 向后
void Back()
{
en1 = 1;
en2 = 1;
in1 = 0;
in2 = 1;
in3 = 0;
in4 = 1;
}
// 向左
void Left()
{
en1 = 1;
en2 = 1;
in1 = 1;
in2 = 0;
in3 = 0;
in4 = 1;
}
// 向右
void Right()
{
en1 = 1;
en2 = 1;
in1 = 0;
in2 = 1;
in3 = 1;
in4 = 0;
}

void keyPros()
{
if(k1==0) {
delay10ms();
if(k1 == 0) {
led1 = ~led1;
TEST = 1;
//test1();
start = 1;
Forward();

    }   
    while(!k1);
}
if(k2==0)&nbsp;{
    delay10ms();
    if(k2&nbsp;==&nbsp;0)&nbsp;{
        led2&nbsp;=&nbsp;~led2;
        TEST&nbsp;=&nbsp;2;
        start&nbsp;=&nbsp;0;
        Stop();
    }   
    while(!k2);
}   

}

unsigned char monitor = 0;
void Scan()
{
if((rp1 == 1 && rp2 == 1) || (rp3 == 0 && rp4 == 0)) { // 前方有障碍物  或者  底部有坑
Back();
delay100ms();
delay100ms();
monitor = 1;
return;
}
if(rp1 == 1) { // 前右边有障碍物
Left();
delay100ms();
delay100ms();
delay100ms();
monitor = 1;
return;
}
if(rp2 == 1) { // 前左边有障碍物
Right();
delay100ms();
delay100ms();
delay100ms();
monitor = 1;
return;
}
if(rp3 == 0) { // 低右边有坑
Back();
delay100ms();
Left();
delay100ms();
delay100ms();
delay100ms();
monitor = 1;
return;
}
if(rp4 == 0) { // 低左边有坑
Back();
delay100ms();
Right();
delay100ms();
delay100ms();
delay100ms();
monitor = 1;
return;
}
monitor = 0;
}

void TurnLeft()
{
Left();
delay100ms();
delay100ms();
}

void TurnRight()
{
Right();
delay100ms();
delay100ms();
}

void init()
{
TMOD = 0x20; // 定时器1 工作方式2  8位自动重装
TH1 = 0xf3;
TL1 = 0xf3;
PCON = 0x80; // 波特率加倍 f3 4800
TR1 = 1; // 定时器1启动 开始工作
REN = 1; // 允许串口接受数据  读数据
SM0 = 0; // 串口工作方式 10位数据异步  1位起始位 8位数据位 1位停止位
SM1 = 1; 
EA = 1; // 开启总中断
ES = 1; // 串口中断允许  打开串口中断
}

void main()
{
init();
isInter = 0;
while(1) {
if(isInter==1) {
ES = 0;
if(recvData == CAR_START) {

        }
        if(recvData&nbsp;==&nbsp;CAR_LEFT)&nbsp;{
            led7&nbsp;=&nbsp;~led7;
            TurnLeft();
            Forward();
            start&nbsp;=&nbsp;1;    
            SBUF&nbsp;=&nbsp;CAR_LEFT;
            while(!TI);
            TI&nbsp;=&nbsp;0;
        }&nbsp;else&nbsp;if(recvData&nbsp;==&nbsp;CAR_RIGHT)&nbsp;{
            led8&nbsp;=&nbsp;~led8;
            TurnRight();
            Forward();
            start&nbsp;=&nbsp;1;
            SBUF&nbsp;=&nbsp;CAR_RIGHT;
            while(!TI);
            TI&nbsp;=&nbsp;0;
        }
        SBUF&nbsp;=&nbsp;0x88;
        while(!TI);
        TI&nbsp;=&nbsp;0;
        ES&nbsp;=&nbsp;1;
        isInter&nbsp;=&nbsp;0;

        if(recvData&nbsp;==&nbsp;CAR_STOP)&nbsp;{
            Stop();
            start&nbsp;=&nbsp;0;
        }
    }

    keyPros();
    if(start&nbsp;==&nbsp;0)
        continue;
    Scan();
    if(monitor&nbsp;==&nbsp;0)&nbsp;{
        Forward();
    }
}

}

void ser() interrupt 4
{
RI = 0;
isInter = 1;
recvData = SBUF;
}

发表评论