DoitCar 产品说明书

基于DoitCar的STA案例

  案例详细讲解了基于DoitCar的STA模式操作过程。程序使NodeMCU的工作在STA模式,连接到无线路由器。通过建立TCP客户端,连接到远程服务器,实现微信、网页以及手机APK的远程控制。

  本案例程序源码见资料包,包括:init.lua、sta.lua和DoitCarControlSTA.lua三个文件。   

init.lua和sta.lua文件

  NodeMCU在启动时预留了init.lua作为应用程序入口,如果没有该文件则忽略,如果存在则开始执行该文件。利用这个特性可以在init.lua中写入需要执行的代码,以便上电自动运行。本案例使用的init文件如下所示。

  资料包中文件名为“init.lua”。   


23     print("\n")
24     print("ESP8266 Started")
25     
26     local exefile="sta"
27     local luaFile = {exefile..".lua","DoitCarControlSTA.lua"}
28     for i, f in ipairs(luaFile) do
29         if file.open(f) then
30           file.close()
31           print("Compile File:"..f)
32           node.compile(f)
33           print("Remove File:"..f)
34           file.remove(f)
35         end
36      end
37     
38     if file.open(exefile..".lc") then
39         dofile(exefile..".lc")
40     else
41         print(exefile..".lc not exist")
42     end
43     exefile=nil;luaFile = nil
44     collectgarbage()

  程序第1、2行打印字符信息。

  第3行定义编译后需要执行的lc文件名,注意不包含后缀“.lc”或者“.lua”。

  第5行定义需要编译的lua文件名。

  第6行是使用for循环完成多个文件的操作。

  第7行判断文件是否存在,如果存在则执行编译。如果不存在则忽略。

  第8行是关闭已经打开的文件。

  第9~12行完成编译,自动生成“DoitCarControl.lc”文件。

  第16~20行判断文件是否存在,如果存在则执行刚刚编译完成的lc文件。

  第21~22行是回收内存。

  sta.lua”文件源码如下:    


 
1     print("Ready to Set up wifi mode")
2     wifi.setmode(wifi.STATION)
3
4 wifi.sta.config("MERCURY_1013","123456789")--ssid and password 5 wifi.sta.connect() 6 local cnt = 0 7 tmr.alarm(3, 1000, 1, function() 8 if (wifi.sta.getip() == nil) and (cnt < 20) then 9 print("Trying Connect to Router, Waiting...") 10 cnt = cnt + 1 11 else 12 tmr.stop(3) 13 if (cnt < 20) then print("Config done, IP is "..wifi.sta.getip()) 14 else print("Wifi setup time more than 20s, Please verify wifi.sta.config() function. Then re-download the file.") 15 end 16 cnt = nil; 17 collectgarbage(); 18 dofile("DoitCarControlSTA.lc"); 19 end 20 end)

  其中第4行是需要设置自己的无线路由器的SSID及密码,以便NodeMCU连接到该路由器。

  第18行是在完成连接后执行DoitCarControlSTA.lc程序。   

DoitCarControlSTA.lua文件

  在DoitCarControlSTA.lua文件中完成GPIO端口初始化,TCP客户端的创建、周期性尝试连接,设置定时器对速度进行调节。在连接成功并收到数据后,对数据进行解析,实现DoitCar小车电机的控制。

  源码如下。   


  122     --GPIO Define
123     function initGPIO()
124     --1,2EN     D1 GPIO5
125     --3,4EN     D2 GPIO4
126     --1A  ~2A   D3 GPIO0
127     --3A  ~4A   D4 GPIO2
128
129 gpio.mode(0,gpio.OUTPUT);--LED Light on 130 gpio.write(0,gpio.LOW); 131
132 gpio.mode(1,gpio.OUTPUT);gpio.write(1,gpio.LOW); 133 gpio.mode(2,gpio.OUTPUT);gpio.write(2,gpio.LOW); 134
135 gpio.mode(3,gpio.OUTPUT);gpio.write(3,gpio.HIGH); 136 gpio.mode(4,gpio.OUTPUT);gpio.write(4,gpio.HIGH); 137
138 pwm.setup(1,1000,1023);--PWM 1KHz, Duty 1023 139 pwm.start(1);pwm.setduty(1,0); 140 pwm.setup(2,1000,1023); 141 pwm.start(2);pwm.setduty(2,0); 142 end 143
144 --Control Program 145 print("Start DoitRobo Control"); 146 initGPIO(); 147
148 spdTargetA=1023;--target Speed 149 spdCurrentA=0;--current speed 150 spdTargetB=1023;--target Speed 151 spdCurrentB=0;--current speed 152 stopFlag=true; 153
154 tmr.alarm(1, 200, 1, function() 155 if stopFlag==false then 156 spdCurrentA=spdTargetA; 157 spdCurrentB=spdTargetB; 158 pwm.setduty(1,spdCurrentA); 159 pwm.setduty(2,spdCurrentB); 160 else 161 pwm.setduty(1,0); 162 pwm.setduty(2,0); 163 end 164 end) 165
166 local flagClientTcpConnected=false; 167 print("Start TCP Client"); 168 tmr.alarm(3, 5000, 1, function() 169 if flagClientTcpConnected==false then 170 print("Try connect Server"); 171 local conn=net.createConnection(net.TCP, false) 172 conn:connect(6005,"182.92.178.210"); 173 conn:on("connection",function(c) 174 print("TCPClient:conneted to server"); 175 flagClientTcpConnected = true; 176 end) 177 conn:on("disconnection",function(c) 178 flagClientTcpConnected = false; 179 conn=nil; 180 collectgarbage(); 181 end) 182 conn:on("receive", function(conn, m) 183 print("TCPClient:"..m); 184 if string.sub(m,1,1)=="b" then 185 conn:send("cmd=subscribe&topic=".."car".."\r\n"); 186 elseif string.sub(m,1,1)=="0" then --stop 187 pwm.setduty(1,0) 188 pwm.setduty(2,0) 189 stopFlag = true; 190 conn:send("ok\r\n"); 191 elseif string.sub(m,1,1)=="1" then --forward 192 gpio.write(3,gpio.HIGH) 193 gpio.write(4,gpio.HIGH) 194 stopFlag = false; 195 conn:send("ok\r\n"); 196 elseif string.sub(m,1,1)=="2" then --backward 197 gpio.write(3,gpio.LOW) 198 gpio.write(4,gpio.LOW) 199 stopFlag = false; 200 conn:send("ok\r\n"); 201 elseif string.sub(m,1,1)=="3" then --left 202 gpio.write(3,gpio.LOW) 203 gpio.write(4,gpio.HIGH) 204 stopFlag = false; 205 conn:send("ok\r\n"); 206 elseif string.sub(m,1,1)=="4" then --right 207 gpio.write(3,gpio.HIGH); 208 gpio.write(4,gpio.LOW); 209 stopFlag = false; 210 conn:send("ok\r\n"); 211 elseif string.sub(m,1,1)=="6" then --A spdUp 212 spdTargetA = spdTargetA+50;if(spdTargetA>1023) then spdTargetA=1023;end 213 conn:send("ok\r\n"); 214 elseif string.sub(m,1,1)=="7" then --A spdDown 215 spdTargetA = spdTargetA-50;if(spdTargetA《0) then spdTargetA=0;end 216 conn:send("ok\r\n");
217 elseif string.sub(m,1,1)=="8" then --B spdUp 218 spdTargetB = spdTargetB+50;if(spdTargetB>1023) then spdTargetB=1023;end 219 conn:send(spdTargetA.." "..spdTargetB.."\r\n"); 220 elseif string.sub(m,1,1)=="9" then --B spdDown 221 spdTargetB = spdTargetB-50;if(spdTargetB<0) then spdTargetB=0;end 222 conn:send(spdTargetA.." "..spdTargetB.."\r\n"); 223 else print("Invalid Command:"..m);end; 224 collectgarbage(); 225 end) 226 end 227 end)

  程序第1~21行定义initGPIO()函数,初始化GPIO口。

  第25行执行initGPIO()函数。

  第27~30行定义了四个变量,用于记录左轮、右轮的当前速度和目标设置速度。

  第31行定义一个标志,用于记录停止状态。

  第33~43行启动了周期性定时器1,每隔200毫秒对当前速度和目标速度进行计算,实现速度控制。其基本思路是:apk设置目标速度,程序在定时器中,将当前速度直接作为PWM占空比设置值进行输出。

  第45行启用flagClientTcpConnected变量,记录TCP客户端的连接状态。

  第47行启动周期性定时器3,每隔5秒钟检查一次TCP连接情况,并进行相应的处理。通过flagClientTcpConnected判断是否需要向服务器发起连接请求。本案例的服务器地址为:“182.92.178.210”,端口为“6005”。

  第52~60行是分别注册了TCP客户端的“connection”和“disconnection”事件。

  第61~104行是数据接收函数的实现代码。在这里面判断接收数据,并根据不同数据执行响应的动作。

  其中,第64行是向服务器发送设备名称。当NodeMCU连接到远程服务器时,服务器会返回字符“b”,此时需要向服务器报告设备名称。该设备名称用于手机apk、网页或者微信控制。本教程设置名称为“tank”。

  第103行,使用了collectgarbage()函数显示的回收内存。   

程序Log

  程序运行Log如下。   


30     NodeMCU 0.9.6 build 20150406  powered by Lua 5.1.4
31
32
33 ESP8266 Started 34 Compile File:sta.lua 35 Remove File:sta.lua 36 Compile File:DoitCarControlSTA.lua 37 Remove File:DoitCarControlSTA.lua 38 Ready to Set up wifi mode 39 > Trying Connect to Router, Waiting... 40 Trying Connect to Router, Waiting... 41 Config done, IP is 192.168.1.111 42 Start DoitRobo Control 43 Start TCP Client 44 Try connect Server 45 TCPClient:conneted to server 46 TCPClient:b 47
48 TCPClient:cmd=subscribe&res=1 49
50 Invalid Command:cmd=subscribe&res=1 51
52 TCPClient:1 53
54 TCPClient:2 55
56 TCPClient:3 57
58 TCPClient:4