小车效果
APP效果
设计材料
- ESP8266-01s模块。
- 51单片机最小系统板。
- L293D芯片一个。
- Android系统手机。
- 面包板一块。
- 充电宝一个,当做电源。
- 杜邦线若干。
设计思路
说明:这是一个可远程遥控的小车,只要小车连接上WIFI,理论上无论你在多远的地方都能遥控小车,因为使用了onenet云平台;当然如果小车使用GSM模组就更好了,小车在哪都能受控。
- ESP8266通过MQTT协议连接onenet云服务器。
- ESP8266与51单片机之间使用串口通信。
- 51单片机通过L293D芯片驱动两个电机,一个负责方向,另一个负责前进和后退。
- ESP8266订阅手机端发布的主题,从而实现手机控制小车。
- 工作过程。
ESP8266端开发
说明:这是基于ESP8266-SDK进行二次开发的,怎么通过MQTT协议连接onenet不在多说,详情请查看我的另一篇博客看ESP8266端开发部分,提供了源代码,当然你也可以去安信可官方平台下载sdk包;在这里主要完成将相应的消息通过串口发送出去。
- 首先,订阅手机发布的
CAR
主题。
void mqttConnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
INFO("MQTT: Connected\r\n");
MQTT_Subscribe(client, "CAR", 0);//完成订阅
}
- 先判断是不是
CAR
主题,然后将该主题下的消息通过串口发送出去,比如说收到1
,那么就在新的一行打印1
即可。
void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
{
char *topicBuf = (char*)os_zalloc(topic_len+1),
*dataBuf = (char*)os_zalloc(data_len+1);
MQTT_Client* client = (MQTT_Client*)args;
os_memcpy(topicBuf, topic, topic_len);
topicBuf[topic_len] = 0;
os_memcpy(dataBuf, data, data_len);
dataBuf[data_len] = 0;
// INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf);
// INFO("Topic_len = %d, Data_len = %d\r\n", topic_len, data_len);//串口打印主题长度、有效载荷长度
if( os_strcmp(topicBuf,"CAR") == 0 )//判断是哪一个主题
{
if( os_strcmp(dataBuf,"0") == 0 ) //如果收到的是0就打印0
{
os_printf("0\n");
}
else if( os_strcmp(dataBuf,"1") == 0 )
{
os_printf("1\n");
}
//此处省略了2,3,4,5的打印代码,可以自行补充。
}
os_free(topicBuf);
os_free(dataBuf);
}
- 串口调试助手,调试实例。
51单片机端开发
- 说明:51单片机只需要读取到上述串口打印的消息,然后合理的解读到消息内容,同时做出相应的动作就可以了。 比如说,串口收到0,表示让小车左转;收到1让小车右转,收到2停止转向。手机按键是按下左键发送0,抬起左键发送2。这样马达就不会一直处于带电的状态。
- 晶振为11.0592M的, 初始化串口,波特率为9600,与ESP8266波特率保持一致即可。
- 源程序如下,可直接编译使用:
#include "reg52.h"
#include "intrins.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit Led=P3^7;
sbit JDQ_S=P0^0;
sbit JDQ_C=P0^1;
sbit turn_left=P1^1;
sbit turn_right=P1^2;
sbit qianjin=P1^3;
sbit houtui=P1^4;
u8 receivearray[100];
//串口初始化函数,波特率设置为9600
void UsartInit()
{
SCON=0x50;
PCON=0x80;
TMOD=0x21;
TH1=0xFA;
TL1=TH1;
EA=1;
ES=1;
TR1=1;
}
//串口发送函数,发送函数第一位为2,esp8266端才会发布消息
void Sent2Esp8266(u8 *p)
{
while(*p)
{
SBUF=*p;
while(!TI);
TI=0;
p++;
}
}
//主函数
void main()
{
UsartInit();
while(1)
{
}
}
//串口中断函数,用来读取串口读取到的数据
u8 i=0;
void Usart() interrupt 4
{
u8 receiveData;
receiveData=SBUF;
receivearray[i]=receiveData;
i++;
if(receivearray[i-1]=='\n')i=0;
switch(receivearray[0])
{
case '0':
turn_left=1;
turn_right=0;
Led=1;
//Sent2Esp8266("turn_left");
break;
case '1':
turn_left=0;
turn_right=1;
Led=0;
//Sent2Esp8266("turn_right");
break;
case '2':
turn_left=0;
turn_right=0;
//Sent2Esp8266("stop_turn");
break;
case '3':
qianjin=1;
houtui=0;
//Sent2Esp8266("qianjin");
break;
case '4':
qianjin=0;
houtui=1;
//Sent2Esp8266("houtui");
break;
case '5':
qianjin=0;
houtui=0;
//Sent2Esp8266("stop");
break;
}
RI = 0;
SBUF=receiveData;
while(!TI);
TI=0;
}
- L293D的使用,只需要使用单片机的6个管脚就够了,两个控制前进后退,两个控制方向,两个使EN能端。比如说
P1.0,P1.1来控制方方向,当高低电平不同时,电机旋转方向不同,将P1.0接1A,P1.1接2A;1Y、2Y接在电机上
。另一个电机也是一样,4、5、12、13管脚是联通的,将其中的一个接地即可,EN使能端高电平有效,可以给两个使能高电平,VCC1、2接电源正极
。
5、ESP8266与单片机连接
APP端开发
- 开发环境AndroidStudio3.6。
- 这里只说明一些代码的作用,详情请查看我的另一篇博客看APP开发部分。
- 手机端是不需要订阅消息的,只需要按键触发发布消息就可以了,下面是相关代码。
- 你可以下载最下面的源码填写你的OneNet相关ID直接使用。
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()){
case R.id.left:
if(event.getAction()==MotionEvent.ACTION_DOWN){//如果按键是按下的状态
btn_left.setTextColor(Color.parseColor("#6200EE"));//更改按键颜色
byte[] left={'0'};//左转所要发布的消息
MqttPublish mqttPublish_left=new MqttPublish("CAR",left,QoS.AT_LEAST_ONCE);//这里一CAR主题名发布
MqttClient.getInstance().sendMsg(mqttPublish_left);//发布消息
}else if(event.getAction()==MotionEvent.ACTION_UP){
btn_left.setTextColor(Color.parseColor("#c0c0c0"));
byte[] left={'2'};
MqttPublish mqttPublish_zt=new MqttPublish("CAR",left,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_zt);
}
break;
case R.id.right:
if(event.getAction()==MotionEvent.ACTION_DOWN){
btn_right.setTextColor(Color.parseColor("#6200EE"));
byte[] right={'1'};
MqttPublish mqttPublish_left=new MqttPublish("CAR",right,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_left);
}else if(event.getAction()==MotionEvent.ACTION_UP){
btn_right.setTextColor(Color.parseColor("#c0c0c0"));
byte[] left={'2'};
MqttPublish mqttPublish_zt=new MqttPublish("CAR",left,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_zt);
}
break;
case R.id.qj:
if(event.getAction()==MotionEvent.ACTION_DOWN){
btn_qj.setTextColor(Color.parseColor("#6200EE"));
byte[] right={'4'};
MqttPublish mqttPublish_left=new MqttPublish("CAR",right,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_left);
}else if(event.getAction()==MotionEvent.ACTION_UP){
btn_qj.setTextColor(Color.parseColor("#c0c0c0"));
byte[] left={'5'};
MqttPublish mqttPublish_zt=new MqttPublish("CAR",left,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_zt);
}
break;
case R.id.ht:
if(event.getAction()==MotionEvent.ACTION_DOWN){
btn_ht.setTextColor(Color.parseColor("#6200EE"));
byte[] right={'3'};
MqttPublish mqttPublish_left=new MqttPublish("CAR",right,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_left);
}else if(event.getAction()==MotionEvent.ACTION_UP){
btn_ht.setTextColor(Color.parseColor("#c0c0c0"));
byte[] left={'5'};
MqttPublish mqttPublish_zt=new MqttPublish("CAR",left,QoS.AT_LEAST_ONCE);
MqttClient.getInstance().sendMsg(mqttPublish_zt);
}
break;
}
return true;
}
- 点击下载源码
到此就结束喽,有什么问题的话,还请大家指出。