2015年11月10日 星期二

用 Python 寫程式控制 WiFi 無線遙控車實作


用 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密碼。
scratch
ip = "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 透過通訊協定來下手
這樣就可以大概了解如何去用Python 來操控 motoduino 的車子了。我們寫了一些簡單的範例碼放在github之上。


沒有留言 :

張貼留言