小车搭建的这个项目,取名为【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  IN1  --> OUT1 
	EN1  IN2  --> OUT2

	控制MOTO2
	EN2  IN3  --> OUT3 
	EN2  IN4  --> OUT4

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

/********************************/
/* 电机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) {
		delay10ms();
		if(k2 == 0) {
			led2 = ~led2;
			TEST = 2;
			start = 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 == CAR_LEFT) {
				led7 = ~led7;
				TurnLeft();
				Forward();
				start = 1;	
				SBUF = CAR_LEFT;
				while(!TI);
				TI = 0;
			} else if(recvData == CAR_RIGHT) {
				led8 = ~led8;
				TurnRight();
				Forward();
				start = 1;
				SBUF = CAR_RIGHT;
				while(!TI);
				TI = 0;
			}
			SBUF = 0x88;
			while(!TI);
			TI = 0;
			ES = 1;
			isInter = 0;
			
			if(recvData == CAR_STOP) {
				Stop();
				start = 0;
			}
		}

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

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

分类: C51单片机

发表评论

电子邮件地址不会被公开。 必填项已用*标注