本文最后更新于:2021年12月14日 晚上
简单介绍如何利用Arduino单片和ESP8266开发板,结合物联网云平台,制作一款能远程遥控的小车。 KeyWords:单片机控制、WiFi、远程遥控、手机App
Arduino+ESP8266的远程控制小车 硬件选型 小车主控板:Arduino UNO Aruduino平台于2005年诞生,两位就职于米兰设计学院的教授,希望开发一款具有软件开发功能的开源的硬件实验平台,于是在他们的合作下,Arduino应运而生。Arduino的编程的语言脱胎于C,如果你有了C语言的学习经验的话,在了解了基本的语言特点和语法之后,便能够非常快速的在Arduino上进行独立的开发工作。关于Arduino的语言,主要有一下两部分,其一是setup()函数,该函数的作用只要在于对系统进行初始化,对相应的引脚进行定义,比如设置输入还是输出模式。第二部分是loop()函数,该函数是用来编写对应的功能的,同时loop()函数将启动硬件部分。不仅如此,Arduino拥有丰富的库文件,分为:官方提供和开发者自定义两种类型。
正如上文提到的,Arduino同时兼具软件开发的功能,拥有着自己的软件开发环境——Arduino IDE。它最为显著的特点就是可以跨多个平台运行,极大方便了使用。目前支持的平台包括:Linux、Windows和MacOS等。Arduino IDE是针对Arduino开发板的一个集成开源的编译软件,操作界面简单、语言风格与C语言相近、使用的库文件是开源的并且简单的代码可以直接通过串口进行下载。对于使用Arduino的开发者来说,这是一款首选的开发环境。
ArduinoIDE是基于processing IDE开发的,是初学者十分的友好,能够快速的掌握,并具有很高的灵活性。Arduino的语言对于avr-gcc库二次封装,因而不需要太多的单片机和编程基础,便可以进行快速的开发。它的工作流程为,在开发者编写好代码,编译后,将语言转换成C++,再用avr-gcc将编译语言转换成二进制,这样一来,开发者编写的内容才能够背Arduino的硬件识别,程序才能够运行。这串代码通过USB接口连接到电脑,再上传到Arduino的存储器进行存储。
在开发者使用Arduino IDE的时候,要做好以下的准备工作:在PC端下载对应硬件的驱动,选择合适的端口。这些步骤完成之后,便可开始程序的编写。Arduino还有第三方的图形化编程软件,极大地降低了对开发者的编程能力的要求,只要能够符合逻辑的设计出功能,按照规定的方式设置对应的参数,便可以下载程序到硬件开发板进行使用。
Arduino软件下载 Arduino中文社区
小车选用的是Arduino UNO的开发板,搭载芯片为ATmega328p。
同时为了方便对控制小车其他配件,选用了一块配套的功能转接板,如下所示:
远程连接模块:ESP8266开发板 小车采用ESP-12E开发板(NoteMCU)作为WIFI连接的模块,通过该块开发板连接物联网云平台,实现远程的控制实现。
其他配件 小车还需要的配件包括:四个直流电机,底盘,车轮,螺丝(若干),铜柱(若干),电池盒,可充电电池。
云平台选择——点灯科技(Blinker) 官网首页
开发文档
远程控制设计 小车控制 远程控制功能主要分为两个主要部分,分别是对小车的动作控制和云平台连接。
小车的行动通过控制电机的转速来实现,单片机的I/O口输出不同的信号,改变驱动电路中PWM的比例值,进而对电机的转速进行调控。将对应的电机状态用函数进行封装,配合不同指令调用对应的函数来实现对小车的控制。
小车基本动作的函数如下表所示:
小车基本动作函数
函数名
功能
备注
run()
小车向前进
左右电机前进
brake()
小车停止
左右电机停止
left()
小车左转
右电机前进左电机停止
right()
小车右转
右电机停止左电机前进
back()
小车后退
左右电机反转
云平台连接 云平台远程连接采用ESP-12E开发板实现,首先通过ESP-12E板和物联网云平台(采用的是Blinker平台)进行远程连接,首先给开发板刷入Blinker的固件,当设备连接启动后,Arduino板通过串口向ESP-12E开发板发送AT指令,进行WIFI连接。连接成功后,就可以通过手机端向云平台发送指令,再由云平台发送给ESP-12E,Arduino通过串口读取指令,调用相应的动作函数。
AT指令字段说明
AT指令
BLINKER_WIFI=0
3275431b24545
f55
bruce6545555
说明
模块工作于透传模式
绑定设备的密钥
WIFI名称
WIFI密码
Bilnker云平台远程连接,主要分为新建组件、设置回调函数、绑定组件与回调函数三个步骤,主要的函数说明如下。
远程连接主要函数说明
函数名
功能
备注
BlinkerButton ButtonRun(“btn-run”);
创建Button对象,键值为“btn-run”
对应Blinker app上的按键控件
void buttonRun_callback(const String & state)
获取按键的状态
根据按键的触发状态执行对应语句
ButtonRun.attach(buttonRun_callback)
绑定控件和对应的回调函数
源代码 小车控制部分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 int Left_motor=8 ; int Left_motor_pwm=9 ; int Right_motor=11 ; int Right_motor_pwm=10 ; char buffer[18 ]; void setup () { Serial.begin(9600 ); Serial.flush(); Serial.println("AT+BLINKER_WIFI=0,3275431b255e,f55,bruce6545555" ); pinMode(Left_motor,OUTPUT); pinMode(Left_motor_pwm,OUTPUT); pinMode(Right_motor_pwm,OUTPUT); pinMode(Right_motor,OUTPUT); }void run () { digitalWrite(Right_motor,LOW); digitalWrite(Right_motor_pwm,HIGH); analogWrite(Right_motor_pwm,90 ); digitalWrite(Left_motor,LOW); digitalWrite(Left_motor_pwm,HIGH); analogWrite(Left_motor_pwm,90 ); }void brake () { digitalWrite(Right_motor_pwm,LOW); analogWrite(Right_motor_pwm,0 ); digitalWrite(Left_motor_pwm,LOW); analogWrite(Left_motor_pwm,0 ); }void left () { digitalWrite(Right_motor,LOW); digitalWrite(Right_motor_pwm,HIGH); analogWrite(Right_motor_pwm,110 ); digitalWrite(Left_motor,LOW); digitalWrite(Left_motor_pwm,LOW); analogWrite(Left_motor_pwm,0 ); }void spin_left () { digitalWrite(Right_motor,LOW); digitalWrite(Right_motor_pwm,HIGH); analogWrite(Right_motor_pwm,90 ); digitalWrite(Left_motor,HIGH); digitalWrite(Left_motor_pwm,HIGH); analogWrite(Left_motor_pwm,90 ); }void right () { digitalWrite(Right_motor,LOW); digitalWrite(Right_motor_pwm,LOW); analogWrite(Right_motor_pwm,0 ); digitalWrite(Left_motor,LOW); digitalWrite(Left_motor_pwm,HIGH); analogWrite(Left_motor_pwm,110 ); }void spin_right () { digitalWrite(Right_motor,HIGH); digitalWrite(Right_motor_pwm,HIGH); analogWrite(Right_motor_pwm,50 ); digitalWrite(Left_motor,LOW); digitalWrite(Left_motor_pwm,HIGH); analogWrite(Left_motor_pwm,50 ); }void back () { digitalWrite(Right_motor,HIGH); digitalWrite(Right_motor_pwm,HIGH); analogWrite(Right_motor_pwm,90 ); digitalWrite(Left_motor,HIGH); digitalWrite(Left_motor_pwm,HIGH); analogWrite(Left_motor_pwm,90 ); }void loop () { if (Serial.available() > 0 ) { int index = 0 ; delay(100 ); int numChar = Serial.available(); if (numChar > 15 ) { numChar = 15 ; } while (numChar--) { buffer[index++] = Serial.read(); } Serial.println(buffer); splitString(buffer); } }void splitString (char *data) { Serial.print("Data entered:" ); Serial.println(data); char *parameter; parameter = strtok(data, " ," ); Serial.println(parameter); while (parameter != NULL ) { setMove(parameter); parameter = strtok(NULL , " ," ); Serial.println(parameter); } for (int x = 0 ; x < 16 ; x++) { buffer[x] = '\0' ; } Serial.flush(); }void setMove (char *data) { if ((data[0 ] == 'O' ) && (data[1 ] == 'N' )&& (data[2 ] == 'A' )) { Serial.println("go forward!" ); run(); } if ((data[0 ] == 'O' ) && (data[1 ] == 'N' )&& (data[2 ] == 'B' )) { Serial.println("go back!" ); back(); } if ((data[0 ] == 'O' ) && (data[1 ] == 'N' )&& (data[2 ] == 'C' )) { Serial.println("go left!" ); left(); } if ((data[0 ] == 'O' ) && (data[1 ] == 'N' )&& (data[2 ] == 'D' )) { Serial.println("go right!" ); right(); } if ((data[0 ] == 'O' ) && (data[1 ] == 'N' )&& (data[2 ] == 'E' )) { Serial.println("Stop!" ); brake(); } if ((data[0 ] == 'O' ) && (data[1 ] == 'N' )&& (data[2 ] == 'F' )) { Serial.println("Stop!" ); brake(); } }
远程连接部分(烧制在ESP-12E开发板) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 #define BLINKER_AT_MQTT #include <Blinker.h> BlinkerButton ButtonRun ("btn-run" ) ;BlinkerButton ButtonBack ("btn-back" ) ;BlinkerButton ButtonLeft ("btn-left" ) ;BlinkerButton ButtonRight ("btn-right" ) ;BlinkerButton ButtonStop ("btn-stop" ) ;BlinkerButton ButtonOn ("btn-on" ) ;BlinkerButton ButtonOff ("btn-off" ) ;int counter = 0 ;void buttonRun_callback (const String & state) { if (state == BLINKER_CMD_BUTTON_PRESSED){ Serial.write("ONA" ); } else if (state == BLINKER_CMD_BUTTON_RELEASED){ Serial.write("ONE" ); } else { Serial.write("ONA" ); delay(1000 ); Serial.write("ONE" ); } }void buttonBack_callback (const String & state) { if (state == BLINKER_CMD_BUTTON_PRESSED){ Serial.write("ONB" ); } else if (state == BLINKER_CMD_BUTTON_RELEASED){ Serial.write("ONE" ); } else { Serial.write("ONB" ); delay(1000 ); Serial.write("ONE" ); } }void buttonLeft_callback (const String & state) { if (state == BLINKER_CMD_BUTTON_PRESSED){ Serial.write("ONC" ); } else if (state == BLINKER_CMD_BUTTON_RELEASED){ Serial.write("ONE" ); } else { Serial.write("ONC" ); delay(1000 ); Serial.write("ONE" ); } }void buttonRight_callback (const String & state) { if (state == BLINKER_CMD_BUTTON_PRESSED){ Serial.write("OND" ); } else if (state == BLINKER_CMD_BUTTON_RELEASED){ Serial.write("ONE" ); } else { Serial.write("OND" ); delay(1000 ); Serial.write("ONE" ); } }void buttonStop_callback (const String & state) { Serial.write("ONE" ); }void buttonOn_callback (const String & state) { digitalWrite(2 ,LOW); Serial.write("ONF" ); }void buttonOff_callback (const String & state) { digitalWrite(2 ,HIGH); }void setup () { Blinker.begin(); pinMode(2 ,OUTPUT); ButtonRun.attach(buttonRun_callback); ButtonBack.attach(buttonBack_callback); ButtonLeft.attach(buttonLeft_callback); ButtonRight.attach(buttonRight_callback); ButtonStop.attach(buttonStop_callback); ButtonOn.attach(buttonOn_callback); ButtonOff.attach(buttonOff_callback); }void loop () { Blinker.run(); }