LattePanda 項目之 P2.2 起飛條件檢測系統(CLI & GUI)


前言

原創文章,轉載引用務必注明鏈接,水平有限,如有疏漏,歡迎指正。

本文使用Markdown寫成,為獲得更好的閱讀體驗和正常的鏈接、圖片顯示,請訪問我的博客原文:

http://www.cnblogs.com/sjqlwy/p/lattepanda_pyui.html

本文測試環境:LattePanda:Windows 10 x64;Arduino 1.8.2;Python 3.6 + pyFirmata;TeamViewer 12|TightVNC C&S;host:Windows 7 x64

影響飛機飛行的六大氣象因素

來自中國天氣網:http://www.weather.com.cn/science/qxbk/jt/09/392758.shtml

氣壓
能見度
顛簸 結冰

目前,我們可以獲取氣壓、風力、雲層、能見度等方面的數據,而四軸飛行器屬於低空飛行,並不會受顛簸、結冰影響。為此,我們設計如下:

  1. 通過在線天氣預報API獲取當前天氣、風力、氣壓、能見度等信息;以及次日天氣狀況並進行判斷
  2. 獲取傳感器數據顯示當前環境狀況(由於缺少專業傳感器,未來會連接氣象站套件、購置新傳感器、連接其他MCU獲取氣壓等數據)
  3. 顯示結果:
  • 終端程序(CLI):Python Shell|Windows Command Prompt
  • 圖形界面(GUI):圖形程序或網頁界面(Web Interface)
  • 物理面板:使用LCD液晶屏、物理按鈕、LED燈等指示起飛條件狀態

獲取天氣條件(輸入)

天氣預報API

最簡便且准確的途徑就是獲取天氣預報啦,這里我們可以使用國內外諸多網站提供的服務API,可以在百度API Store查找使用各種免費收費服務。之前用過Yahoo、Weather等的API,這次無意中發現github上網友TonnyL整理的Awesome_APIs 列表,非常棒,感謝TonnyL,有可能的話大家可以去star或者捐贈。

我們選擇中央天氣預報(非官方) 這個API,首先數據准確,其次使用異常簡單。

使用方法講得很清楚,數據格式為json,如果不進行格式化,輸出結果如下:

其中\uXXXX為JS string,雖然有很多小工具如curl、httpie配合json格式化工具可以完成解碼,但是為了后續拓展方便,我們使用Python + requests庫來實現數據獲取與處理。

獲取天氣狀況

測試環境:Python 3.6.1 for Windows;pyFirmata 1.0.3 (pyserial needed);requests 2.14.2

代碼如下:

#!/usr/bin/env python3
#-*utf-8*-

import requests

def get_weather():
    # use api from https://github.com/jokermonn/-Api/blob/master/CenterWeather.md
    weather = requests.get('http://tj.nineton.cn/Heart/index/all',params = 'city=CHJS070000')
    return weather.json()

status = get_weather()['status']
cond = get_weather()['weather'][0]['now']
tomorrow = get_weather()['weather'][0]['future'][1]

if status == 'OK':
	print("********當前天氣********")
	print("當前城市:{0}\n當前天氣狀況: {1}\n溫度: {2} ℃\n風向: {3}\n風速: {4} m/s\n風力大小: {5}\n空氣濕度: {6}\n能見度: {7} km\n氣壓: {8} hPa".format(get_weather()['weather'][0]['city_name'], cond['text'], cond['temperature'], cond['wind_direction'], cond['wind_speed'], cond['wind_scale'], cond['humidity'], cond['visibility'], cond['pressure']))
	print("********明日天氣********")
	print("明日天氣情況:{0}\n風力大小:{1}".format(tomorrow["text"], tomorrow['wind']))
	if '雨' not in tomorrow['text']:
		affordable_wind = ('風力0級', '風力1級', '風力2級', '風力3級', '風力4級')
		if tomorrow['wind'] in affordable_wind:
			# 后續加入字體顏色
			print("明日適宜飛行!")
			# 綠燈亮
	else:
		# 后續加入字體顏色
		print('明日不宜飛行!')
		# 紅燈亮
else:
	print('failed to fetch weather condition of XuZhou!')

執行效果如下:

注意:

  1. 注意Python2和Python3的語法上稍有區別,建議閱讀廖雪峰的Python教程和免費的《A Byte of Python3(中文版)》這本書。
  2. requests庫簡單易用,內置json格式化功能。雖然還有許多其他更輕巧的庫或者工具可以使用,但是使用優美的requests庫可以降低學習成本,並為后續網絡爬蟲等的學習打下基礎。
  3. 請參考該api的json返回示例,注意字典{}和序列[],《A Byte of Python3(中文版)》有專門的講解。
  4. 這里推薦使用字符串的format()方法進行格式化輸出。
  5. params = 'city=CHJS070000'以我家徐州為例,具體城市代碼參考作者提供的數據庫文件
  6. 因為計算機都是業余愛好,所以代碼質量相當低,歡迎指正提建議。
  7. 當服務端 (Server)和客戶端 (Viewer)都使用TightVNC時,可以直接進行文字復制黏貼,但是我這里中文會出現亂碼,可能是兩個文件編碼不同也可能是TightVNC內置編碼問題,不過使用文件傳輸功能沒亂碼。
  8. 后續准備增加適宜和不適宜起飛的字體顏色,由於Windows和Linux的實現有所不同,考慮可移植性,暫時不進行功能整合。可以參考Python實現Windows CMD命令行彩色輸出Python 命令行輸出的顏色設置

獲取傳感器數據與物理按鈕控制

前文LattePanda 之深入學習 Firmata通訊有所介紹,我們這里先用簡單的pyFirmata庫進行演示模擬、數字傳感器讀寫。最終效果為:讀取光敏傳感器、溫濕度傳感器數據進行顯示(模擬、數字傳感器讀取),並且根據天氣預報情況判斷明日天氣條件是否可以起飛,如果可以,則綠色led亮5s,否則紅色led亮5s(數字寫入)。未來加入物理大黃按鈕進行控制(數字讀取)。代碼如下:

from pyfirmata import Arduino, util
from time import sleep

# 初始化串口
board = Arduino('COM5')

print("********傳感器數據********")
it = util.Iterator(board)
it.start()
board.analog[0].enable_reporting()
sleep(1) # 緩沖時間
# 待補充DHT11以及校准光敏傳感器
print("環境亮度:{0}\n環境溫度:{1}\n環境濕度:{2}\n".format(board.analog[0].read(), "N/A", "N/A"))	
board.analog[0].disable_reporting()

# 綠燈亮
board.digital[9].write(1)
sleep(5)
board.digital[9].write(0)

# 紅燈亮
board.digital[10].write(1)
sleep(5)
board.digital[10].write(0)

注意:

  1. 請填寫正確的串口編號
  2. 使用第三方StandardFirmataPlus固件是出現問題,led點亮后無法熄滅,重新燒錄官方StandardFirmata固件后回復正常,等待重新驗證問題。
  3. 操作模擬端口時,建議啟動一個迭代器線程進行處理,否則開發板會持續向串口發送數據,直到串口溢出。更多例子及使用方法請參考官方tests.py
  4. 開啟reporting后請延時后讀取模擬量,否則可能獲取不到傳感器數值;另外單次讀取完畢請disable,不然也會一直發送數據(Tx白色指示燈常亮)
  5. 后續使用pyMata-aio取代pyFirmata庫,它支持最新的firmata協議,使用異步,並且可以自動檢測Arduino串口。
  6. A9、A10分別接綠色、紅色LED。

【APRS氣象站套件(帶風速計、風向儀、雨量器)】

整合兩個功能,即可以得到命令行界面版控制界面完整源碼:

Graphics User Interface

前面搞定了CLI界面,基本功能實現了,但是此時的我想起來v2ex上一個段子:

原先 PM 將一個用的人少的運維管理頁面( web application ) JAVA web 給我用 Python 做,期待做成小工具。后來我想給客戶的東西總不能沒有界面吧,就用 bat 擼了一個。

客戶:握草,這界面?!還墨綠色?

:恩,目前是這樣

客戶:這滾動的怎么像黑客一樣?!!

:。。。

所以我們准備為地面站系統做一個圖形界面。用慣了CLI界面,對圖形界面設計編程這個新領域學習了一番,收獲頗豐,記錄如下。

計划中的地面控制站包括網頁版用戶交互界面(屏幕軟件交互)+物理控制面板(按鈕LED交互)。

Windows下的桌面軟件開發

  • 快手 aardio| 國人出品,專注於桌面軟件快速開發,功能強大,永久免費,不過存在一些爭議,名詞也從AAuto改成了aardio。相關文章:快手軟件存在哪些優點和不足?桌面程序開發語言選擇易語言還是快手aautoAAuto為何更名為aardio? 。后續有時間准備學學看。
  • C#|Windows桌面程序開發非常給力,然而我沒學
  • electron | Build cross platform desktop apps with JavaScript, HTML, and CSS。我不會網頁那些東西
  • Qt | 跨平台,文檔眾多。Linux下的KDE桌面環境就是基於Qt做出來的,還針對嵌入式系統推出了一個Qt Lite。即使有Qt Design,然而學習成本依然高,需要花時間去學習。
  • Visual Basic | 也支持Firmata協議。

因為比較熟悉Python,所以后續以它為例。在v2ex.com上搜索了一下:如果 Python 硬要寫桌面應用,該如何是好?

已有的Python GUI庫方案

  • tkinter|難看,接口也難用。適合小玩意
  • wxPython | 還闊以
  • PyQt | 資料多,依賴復雜
  • REMI | Python REMote Interface library. Platform independent. In about 100 Kbytes, perfect for your diet.
  • Kivy | Open source Python library for rapid development of applicationsthat make use of innovative user interfaces, such as multi-touch apps.
  • Ironpython | IronPython is an open-source implementation of the Python programming language which is tightly integrated with the .NET Framework.
  • Gooey | Turn (almost) any Python command line program into a full GUI application with one line

最終我們選擇REMI庫來開發圖形界面版程序。主要看中依賴少、身材小巧、上手容易、跨平台能力強等。

Python2 與 Python3 :

因為Python2即將結束支持。使用Python的原因是因為簡單方便,庫多不用重復造輪子,跨平台,功能強大。運行效率其實已經不是最優先的考慮要求啦,畢竟不是嵌入式設備。之前也學過Visual Basic、C、Linux Shell,但是用上Python之后立即愛上了,此外也有現成優秀的庫支持Firmata協議。

REMI

既然有了那么多優秀的GUI庫,為什么還要創建一個呢,作者是這樣回答的:

  • Why another GUI lib?
    Kivy, PyQT and PyGObject all require native code for the host operating system, which means installing or compiling large dependencies. Remi needs only a web browser to show your GUI.

    Kivy,PyQT,PyGobject都需要安裝編譯大量依賴才能在宿主機上原生運行,而Remi僅需要網頁瀏覽器就可以顯示GUI界面了。

  • Do I need to know HTML?
    NO, It is not required, you have to code only in Python.

    僅需要會使用Python編程,而不用學習了解HTML(超文本標記語言,網頁開發語言)就可以進行開發。

私以為其他優點包括擴拓展性強,方便外網訪問等。我們可以看到REMI目前可實現的控件演示

包括按鈕、文本框、標簽、輸入對話框、列表、圖片、表格、滑動條、顏色選擇器、日期、文件選擇對話框、菜單欄、菜單選項、視頻播放等控件。具體用法可以參考docexamples文件夾里的內容。

最后推薦一個好用的Python IDE——PyCharm:

安裝與hello_DFROBOT!

REMI項目主頁:https://github.com/dddomodossola/remi

安裝方法很簡單,如上文所述:Win+R——cmd——python -m pip install remi,也可以pip install remi,注意需要管理員身份運行。另外新建的文件名不要和待加載的模塊名相同(比如remi.py),否則會提示ModuleNotFoundError: No module named remi之類的錯誤(別問我怎么知道的。。。)。我們新建一個文件如remi_demo.py,代碼如下:

import remi.gui as gui
from remi import start, App

class Hello_DFRobot(App):
    def __init__(self, *args):
        super(Hello_DFRobot, self).__init__(*args)

    def main(self):
        container = gui.VBox(width = 120, height = 100)
        self.lbl = gui.Label('DFROBOT')
        self.bt = gui.Button('Press me!')

        # setting the listener for the onclick event of the button
        self.bt.set_on_click_listener(self.on_button_pressed)

        # appending a widget to another, the first argument is a string key
        container.append(self.lbl)
        container.append(self.bt)

        # returning the root widget
        return container

    # listener function
    def on_button_pressed(self, widget):
        self.lbl.set_text('Drive the Future!')
        self.bt.set_text('Button pressed!')

# starts the webserver
start(Hello_DFRobot)

效果如圖所示:

運行后會自動打開一個網頁,點擊按鈕,按鈕和標簽文字都會改變。這里簡單講解一下,詳細的可以看官方doc文檔和examples示例。

我們下面將會結合

  • requests庫獲取天氣

  • pyFirmata庫與Arduino交互

  • remi庫作為圖形顯示

REMI editor

相信很多人都用過Visual Basic、Qt Designer這種可視化的用戶界面設計工具,而REMI也有類似的,而且是使用remi本身實現的,就在editor文件夾里,具體使用說明參考其下的README.md文件,說明比較簡略,這里詳述如下:

安裝好相關依賴庫之后,運行editor.py (我這里是用的PyCharm IDE打開運行的)。

注意:

  • 某個控件的響應可以在左下角signal connections里面設置。
  • 雖然Web界面具有極大的跨平台優勢,但是由於存在諸多瀏覽器、平台、屏幕大小分辨率,仍有可能設計出的界面在其他上面顯示不全,所以仍要了解一些基本HTML常識
  • ☆網頁制作的層絕對定位和相對定位:一般選中主widget,右下角最后設置positionabsolute絕對定位(相對於瀏覽器左上角),其他widget中的控件設置為relative相對定位,然后在Geometry里設置坐標。
  • 菜單欄Project Config可以設置項目的一些基本屬性(支持中文項目名稱),設計完畢后,點擊File->Save YourApp->Save As即可保存界面代碼,並在隨后的程序中使用。

GUI 來了!

然后GUI又走了!表示這太丑了,自己也看不下去。。。遂棄用。決定回頭仔細看看文檔再重新來過。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM