用 Python 寫程式控制 WiFi 無線遙控車實作
根據前幾篇文章的內容,已經可以簡單而初步地實作一台 WiFi 無線遙控車。基本上所有的事情都是在 Raspberry Pi 的系統上實作出來的。
材料
- motoduino 車子套件(板子需已燒錄 motoduino 的 firmware)
- ESP8266 模組
- 9V 方塊電池 x 3
- Raspberry Pi
- 區域網路
設置 WiFi 模組
原本的連線方式是用USB線連接motoduino 和 Scratch,所以這邊要使用ESP8266模組把這個連線切換成WiFi連線。因為不想更動到motoduino 裡面的firmware 所以我們要把ESP8266模組變成可以把motoduino 透過UART 的 tx/rx (pin腳1,2)傳出來的封包用WiFi 無線傳輸的方式傳到指定的網站,也就是Raspberry Pi 所架的網站,這邊假設 Raspberry Pi 的 IP 為 192.168.0.1。
要達到這個需求的一個方法就是去把 ESP8266 的 firmware 刷成 nodeMCU 之後再寫入lua script ,使其在開機之後自動連線到指定的AP上,並將 motoduino 的 UART 和 Raspberry Pi 的 UDP socket 連線。簡易的架構圖如下:
------------------------- ------------ ---------------
Rapsberry Pi UDP Socket | <==>|ESP8266 tx | ----> | rx motoduino|
| | rx | <---- | tx |
------------------------- ------------- ---------------
ESP8266 刷成 nodeMCU 的方式可以參考之前的文章 :
ESP8266 wifi 通訊模組韌體燒錄簡介
ESP8266 NodeMCU 使用 ESPLorer 寫入 Lua Script
ESP8266 NodeMCU 使用 Lua 自動連網
而自動連線的 Lua Script 如下:
print("ESP8266 START")
ssid = "My_AP"
passwd = "12345678"
scratch_ip = "192.168.0.1"
scratch_port = 12345
wifi.setmode(wifi.STATION)
wifi.sta.config(ssid,passwd,1)
tmr.alarm(1,1000, 1, function()
if wifi.sta.getip()==nil then
print(" Wait to IP address! for " .. ssid)
else
print("New IP address is "..wifi.sta.getip())
tmr.stop(1)
sck = net.createConnection(net.UDP)
sck:on('receive', function(sck,pl) uart.write(0,pl) end)
uart.on('data',0, function(data) sck:send(data) end,0)
sck:connect(scratch_port,scratch_ip)
sck:send("START UART Tunnel\n")
uart.setup(0,38400,8,0,1,0)
end
end)
print(wifi.sta.getip())
其中的 ssid = "MyAP" 為要連線的 AP SSID, passwd = "12345678" 為AP密碼。
scratchip = "192.168.0.1" 為 Raspberry Pi 的 IP 位址。而 scratch_port 為 Raspberry Pi 的 UDP socket 的 port number 。
scratchip = "192.168.0.1" 為 Raspberry Pi 的 IP 位址。而 scratch_port 為 Raspberry Pi 的 UDP socket 的 port number 。
所以在 Raspberry Pi 上可以寫一個 Python script 來接收 motoduino 所傳送過來的封包。
#!/usr/bin/env python3
import socket
def s4aDecode(data):
dev_id = (data[0] & 0b01111000) >> 3
dev_val = ((data[0] & 0b00000111 ) << 7) | (data[1] & 0b01111111)
return (dev_id, dev_val)
def handle_data(data):
i= 0
length = len(data)
if(data[i] & 0b10000000):
pass
else:
i+=1
while(i<length):
try:
print(s4aDecode(data[i:i+2]))
i+=2
except:
break
address = ('',12345)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(address)
while(True):
print('--')
data, addr = s.recvfrom(1024)
handle_data(data)
詳細的s4a protocol 格式設定可以看之前寫的文章:
Python 操控 S4A 透過通訊協定來下手
沒有留言 :
張貼留言