使用 PYNQ 和 Zigbee 創(chuàng)建一個簡單且可擴展的家庭自動化系統(tǒng)。
介紹
我們經(jīng)常忘記 FPGA 可用于消費類應(yīng)用,而不僅僅是工業(yè)、汽車、國防/航空航天等。對于諸如 Artix、Spartan 和 Zynq 7000 系列設(shè)備等 cist 優(yōu)化范圍內(nèi)的設(shè)備尤其如此。
可編程邏輯和 SoC 提供了一系列起初可能并不明顯的優(yōu)勢,包括
系統(tǒng)集成——將幾個離散的處理元件組合成一個包。
上市時間 - 與 ASIC 解決方案相比縮短了時間
現(xiàn)場更新——隨著標(biāo)準(zhǔn)和產(chǎn)品路線圖的發(fā)展,不僅可以升級軟件,還可以升級“固定”邏輯設(shè)計
架構(gòu)靈活性——為可編程邏輯提供廣泛的接口和功能加速的能力。
De Risking - 盡早開始開發(fā)的能力。
FPGA 在消費市場中的一種常見應(yīng)用是家庭自動化。在家庭自動化系統(tǒng)中,通常有一個中央安全網(wǎng)關(guān)來管理設(shè)備和更廣泛系統(tǒng)的連接。
對于這個項目,我們將演示連接到 ZigBee 控制燈系列的中央網(wǎng)關(guān)。
該項目的路線圖是在稍后階段將其與基于智能人工智能的數(shù)字鎖連接,該數(shù)字鎖將與網(wǎng)關(guān)通信并為解鎖人員建立家庭設(shè)置。
家庭自動化、PYNQ 和 ZigBee
完全可以直接從 PYNQ 的 Juptyer 筆記本控制和自動化 ZigBee 設(shè)備。這有一些很大的好處,例如自定義用戶界面,與其他家庭助理和自動化軟件相比,這本身就非常獨特。不僅如此,我們甚至可以利用這是一個 PYNQ 板這一事實,我們可以利用 PL 來進(jìn)一步定制我們的應(yīng)用程序。它非常適合家庭助理社區(qū),令人驚訝的是它相對簡單。讓我們向您展示我們是如何做到的。
特色圖片
方法總結(jié)
本節(jié)是對本項目中使用的方法進(jìn)行總結(jié)。
PYNQ 框架運行和底層操作系統(tǒng)。PYNQ 框架的底層操作系統(tǒng)是 Ubuntu。稍后我們將利用它來安裝 docker,然后安裝 deCONZ 軟件。
什么是 docker ?
簡單地說,docker 是一種分發(fā)軟件的好方法,可以減少多個虛擬機的開銷。Docker 能夠在所謂的“容器”中運行軟件,容器是一個完全打包的軟件,其中包括鏡像、庫和配置文件。由于容器將運行軟件,因此我們不必?fù)?dān)心兼容性問題,并且可以直接按預(yù)期運行,只需最少的干預(yù)。
為什么使用
Conbee II 使用制造商 Dresden Elektronik 提供的 deCONZ 軟件來連接和控制設(shè)備。deCONZ 軟件允許我們通過 Web 應(yīng)用程序連接和控制設(shè)備。使這一切正常工作的原因是 deCONZ Web 應(yīng)用程序具有內(nèi)置的 REST API,我們可以從 Juypter Notebook 環(huán)境中進(jìn)行接口!
先決條件 - 硬件
對于此演示將用于硬件:
Arty Z7 賽靈思 ZYNQ 7000
Conbee II USB 網(wǎng)關(guān)
智能燈 - 飛利浦 Hue GO 便攜式燈
Arty Z7 能夠運行 PYNQ 框架并具有 USB 插槽。USB 插槽是必需的,因為我們將直接從 Arty Z7 本身使用 ConBee II USB 網(wǎng)關(guān)。
Conbee II 是一個很棒的小型 USB 記憶棒,可以連接智能設(shè)備,如燈、開關(guān)、插座和傳感器。這個小棒適用于從 Windows 到 Ubuntu 的所有平臺,我們將在 PYNQ 上安裝它。
這個項目中的智能燈,是一個通用的藍(lán)牙智能燈,您可以在線獲取。您不必購買相同的,但一定要檢查它是否與 Conbee II 兼容??稍诖颂幷业郊嫒菰O(shè)備的完整列表:https ://phoscon.de/en/conbee2/compatible
設(shè)置 PYNQ
開始之前,我們需要從http://www.pynq.io/board.html下載 PYNQ 映像,在撰寫本文時 2.7 版是最新版本。在這里,我們將下載 PYNQ-Z1 圖像,因為它與我們的 Arty Z7 板兼容。
下載后,我們需要將圖像閃存到 SD 卡上。我們將使用 WinDisk32 軟件來刷寫鏡像。注意 刷寫 SD 卡會擦除所有內(nèi)容。確保 SD 卡上沒有任何內(nèi)容。
刷機過程完成后。取出 SD 卡并將卡插入 Arty Z7,確保 Boot Jumper 設(shè)置為 SD。插入 Arty 并等待 Pynq 映像啟動。
一旦 PYNQ 完成加載,我們需要找到我們的 IP 地址,輸入以下命令。
ifconfig -a
找到我們的IP地址,應(yīng)該在eth0接口下。這里我們的 IP 地址是 192.168.0.38。記下這一點,我們稍后將需要它。
設(shè)置 Docker 和 Docker-Compose
如方法摘要部分所述,我們將安裝 Docker。首先,我們需要將當(dāng)前用戶添加到撥出組
sudo usermod -a G dialout $USER
接下來我們需要使用以下命令下載 docker 包:
sudo apt-get install docker.io
等待安裝完成。完成后,我們需要安裝 docker compose。Docker compose 是一個使用工具,它將幫助我們創(chuàng)建和修改我們的軟件。
sudo apt-get install docker-compose
使用 docker compose 設(shè)置 DeConz
安裝 docker-compose 后,我們接下來需要設(shè)置 deCONZ 容器/應(yīng)用程序,這是與我們的 zigbee 設(shè)備進(jìn)行交互和查找的軟件。
導(dǎo)航到 /opt 文件夾:
cd /opt
接下來我們將創(chuàng)建一個新的 docker-compose.yaml 文件。
這是我們添加和配置容器的文件。
所以,回到創(chuàng)建 yaml 文件。
sudo nano docker-compose.yaml
確保保持縮進(jìn)正確!
version: "3.2"
services:
? deconz:
? image: deconzcommunity/deconz:latest
? privileged: true
? container_name: deCONZ
? network_mode: host
? restart: always
? volumes:
? ?- type: bind
? ?source: /opt/deconz
? ?target: /opt/deCONZ
? devices:
? - /dev/ttyACM0
? environment:
? ?- TZ=Europe/London
? ?- DECONZ_WEB_PORT=8090
? ?- DECONZ_WS_PORT=443
? ?- DEBUG_INFO=1
? ?- DEBUG_APS=0
? ?- DEBUG_ZCL=0
? ?- DEBUG_ZDP=0
? ?- DEBUG_OTAU=0
這一步將配置容器,以便下載最新版本的 deCONZ 軟件并將我們的門戶網(wǎng)站設(shè)置為端口 8090。這是關(guān)鍵,因為 PYNQ 使用 Jupyter 筆記本的門戶網(wǎng)站,默認(rèn)情況下使用端口 80 來訪問網(wǎng)頁和已打開額外的 9090 端口。這就是我們將 deCONZ 應(yīng)用程序的端口設(shè)置為使用 8090 的原因。因為這不會干擾 Pynq Jupyter 的筆記本網(wǎng)絡(luò)套接字。
保存 (CTR-S) 并關(guān)閉 (CTR-X) 配置。
接下來我們可以使用 docker-compose 啟動 deCONZ 應(yīng)用程序。輸入以下命令:
sudo docker-compose up -d
這將下載 deCONZ 應(yīng)用程序并在完成后自動啟動容器。
當(dāng)我們得到“Done”響應(yīng)時,讓我們做一個健全性檢查,看看容器是否真的在運行。
sudo docker container ls
容器正在運行。
Conbee II 和 deCONZ 設(shè)置
現(xiàn)在在容器中運行 deCONZ 應(yīng)用程序。我們可以使用以下說明打開 deCONZ 網(wǎng)絡(luò)應(yīng)用程序。
打開 Web 瀏覽器并輸入 IP 和端口號 8090。在我們的實例中,我們的 IP 地址是 192.168.0.32,端口號是:192.168.0.32:8090。
這將打開 Phoscon 網(wǎng)絡(luò)應(yīng)用程序。從下圖中我們可以看到我們的網(wǎng)關(guān)點擊圖標(biāo)開始設(shè)置。
在下一頁上,我們需要創(chuàng)建我們的登錄憑據(jù)(見下圖)。完成后單擊下一步。
Phoscon 應(yīng)用程序現(xiàn)在將要求您連接任何燈。您可以現(xiàn)在或以后連接您的燈。我們將連接我們的飛利浦 Hue GO 便攜式燈。確保我們的燈已插入。單擊搜索按鈕。
從上圖中我們可以看到,我們可以看到我們的 Lamp。如果您單擊燈,您可以重命名它以便更容易識別燈。一旦檢測到所有燈。單擊無燈繼續(xù)。不用擔(dān)心已經(jīng)檢測到的燈會被記住。
在下一頁上,我們可以創(chuàng)建一個新組來添加燈。下面是一個例子。
創(chuàng)建一個新組,編輯,管理燈光。
將我們的燈添加到組中。我們只有 1 盞燈要添加。單擊綠色加號圖標(biāo)
單擊保存并按箭頭圖標(biāo)返回組頁面。
將燈光添加到我們的自定義組中,我們可以控制它。請注意,在 webapp 和燈光下可能會有一些延遲。要有耐心。如果仍然存在問題,請考慮刷新頁面、將設(shè)備移近或使用以下命令重新啟動容器:
sudo docker container restart deCONZ
快速測試
單擊燈光選項卡以調(diào)整亮度、顏色和飽和度。也可以使用下圖中的圖標(biāo)更改色溫。
設(shè)置 REST API
現(xiàn)在通過燈光設(shè)置,我們可以使用 Jupyter 的 Notebook 創(chuàng)建自己的界面。這相對容易。由于 deCONZ 應(yīng)用程序有一個內(nèi)置的 API,我們可以通過使用一些簡單的 python 腳本來利用它。
打開一個新的 Web 瀏覽器并導(dǎo)航到 Jupyter 的筆記本頁面。在我們的例子中是 192.168.0.32:80。這將打開熟悉的 jupyter 筆記本。
我們將創(chuàng)建一個新文件夾以保持一切整潔。我們將文件夾命名為 ConBee II,并在該文件夾中創(chuàng)建一個新的 python3 應(yīng)用程序
REST API 通過發(fā)出請求來工作。
我們需要導(dǎo)入一些庫來發(fā)出請求。
import requests
import json
接下來,我們需要創(chuàng)建一個請求以獲取 API 密鑰。在新單元格中輸入:
URL = “http://192.168.0.38:8090/api”
device = {‘devicetype’: ‘a(chǎn)pplication’}
p = requests.post(URL, json=device)
pretty_json = json.loads(p.text)
print (json.dumps(pretty_json, indent=2))
運行上面的代碼,我們會收到如下錯誤:
錯誤是未按下鏈接按鈕。這是指身份驗證檢查。我們需要授權(quán)第三方應(yīng)用程序。回到 Phoscon 應(yīng)用程序并單擊網(wǎng)關(guān)選項。
在高級設(shè)置下,單擊驗證應(yīng)用程序。您將有 60 秒的時間重新運行上一步中的代碼。如果在時間內(nèi)完成,則使用 API 密鑰成功。您現(xiàn)在已經(jīng)成功驗證了您的應(yīng)用程序,并且可以開始使用 Jupyter 配置和控制設(shè)備。
在 Juypter 中控制我們的設(shè)備
現(xiàn)在要發(fā)出請求,我們需要提供我們的 API 密鑰。例如,我們希望看到我們的燈光。
# 代表上一步的 API 密鑰
r = requests.get(URL+“/D########9/lights”)
pretty_json = json.loads(r.text)
print (json.dumps(pretty_json, indent=2))
上圖向我們展示了 Philip Hue Lamp 和 ConBee II 設(shè)備
請使用命令查看完整列表。使用提供的鏈接:
https://dresden-elektronik.github.io/deconz-rest-doc/
可以修改的參數(shù)是“狀態(tài)”類別下列出的參數(shù):
這些參數(shù)需要請求 PUT 命令。例如,我們可以關(guān)閉我們的設(shè)備。
使用 Jupyter Notebook 創(chuàng)建自定義界面
既然我們知道如何控制我們的設(shè)備,接下來就是將它們集成到 Jupyter 的內(nèi)置 GUI 創(chuàng)建工具中。我們將使用 ipywidgets 庫。
import ipywidgets
讓我們先來了解一下 Light 的一些基本控件。我們需要一個“開啟開關(guān)”和一個“關(guān)閉開關(guān)”。沒有任何開關(guān),但我們可以使用按鈕。下面的代碼創(chuàng)建了一個將“on”值更改為 True 的按鈕。
btn = widgets.Button(description=‘On’)
display(btn)
def btn_eventhandler(obj):
data = {“on”: True}
r = requests.put(URL+“/D78828C329/lights/1/state”, json = data)
print(“Lamp is On!”)
btn.on_click(btn_eventhandler)
接下來讓我們關(guān)掉燈泡。這次我們將“on”值設(shè)置為 False。
btn = widgets.Button(description=‘OFF’)
display(btn)
def btn_eventhandler(obj):
data = {“on”: False}
r = requests.put(URL+“/D78828C329/lights/1/state”, json = data)
print(“Lamp is OFF!”)
btn.on_click(btn_eventhandler)
我們甚至可以添加一個顏色選擇器小部件。顏色選擇器小部件返回所選顏色的 RGB 值。然而,這帶來了一個小問題。deCONZ rest api 需要 HSV 中的值。HSV 顏色模型中的色調(diào)參數(shù)在 0°–360° 之間,映射到 0–65535 以獲得 16 位分辨率。
首先讓我們添加顏色選擇器
colorpicker = widgets.ColorPicker(
concise=False,
description=‘Pick a color’,
value=“#121254”,
disabled=False )
colorpicker ## Click the little blue square
接下來是獲取顏色選擇器中的信息并將值轉(zhuǎn)換為 deCONZ 軟件可以理解的可用格式。經(jīng)過無數(shù)小時的調(diào)試和撓頭。復(fù)制以下代碼:
import math?
#print(colorpicker.value)
def RGBtoHSV(colorpicker):
? ? R = int(colorpicker.value[1:3],16)
? ? G = int(colorpicker.value[3:5],16)
? ? B = int(colorpicker.value[5:7],16)
? ? R1 = R/255
? ? G1 = G/255
? ? B1 = B/255
? ? #print(R1)
? ? #print(G1)
? ? #print(B1)
? ? #print("\n")
? ? Cmax = max(R1,G1,B1)
? ? #print(Cmax)
? ? Cmin = min(R1,G1,B1)
? ? #print(Cmin)
? ? delta = Cmax - Cmin
? ? if delta != 0:
? ? ? ? if Cmax == R1:
? ? ? ? ? ? Hue = round(60*(((G1-B1)/delta)%6))
? ? ? ? elif Cmax == G1:
? ? ? ? ? ? Hue = round(60*(((B1-R1)/delta)+2))
? ? ? ? else:
? ? ? ? ? ? Hue = round(60*(((R1-G1)/delta)+4))
? ? else:
? ? ? ? if Cmax == R1:
? ? ? ? ? ? Hue = R1
? ? ? ? if Cmax == G1:
? ? ? ? ? ? Hue = G1
? ? ? ? if Cmax == B1:
? ? ? ? ? ? Hue = B1
? ? if Cmax != 0:
? ? ? ? Sat = 255*(delta/Cmax)
? ? ? ? #print("\nSaturation: {0}% of 255 is {1}".format(round((delta/Cmax)*100), round(Sat)))
? ? else:
? ? ? ? Sat = 0
? ? ? ? #print("Saturation: 0%")
? ? Vis = 255 * Cmax
? ? Hue = round(Hue * ((2**16)/360)) ## Mapped to 360 degrees
? ? #print("Visablity: {0}% of 255 is {1}".format(round((Cmax*100)), Vis))
? ? #print("\nRed {0} Green {1} Blue {2}".format(R,G,B))
? ? #print("Hue {0} Sat {1} Vis {2}".format(Hue,round(Sat),round(Vis)))
? ? #print (json.dumps(pretty_json, indent=2))
? ? return Hue, Sat, Vis
這會正確地從顏色選擇器返回色相、飽和度和可見度。調(diào)用此函數(shù):
Hue,Sat,Vis = RGBtoHSV(colorpicker)
接下來是簡單地發(fā)送 PUT 請求,Lamp 將根據(jù)需要更改顏色。
data = {"on": True,?
? ? ? ? "bri" : Vis,
? ? ? ? "hue" : Hue,
? ? ? ? "sat" : Sat
? ? ? ?}
r = requests.put(URL+"/D78828C329/lights/1/state", json = data)
#print(r)
pretty_json = json.loads(r.text)
#print (json.dumps(pretty_json, indent=2))
對于我們的最后一個示例,我們將使用滑塊控制色相、飽和度和亮度!
有了這個,我們可以改變看到的光。
現(xiàn)在我們已經(jīng)擁有了我們想要的所有 GUI 元素。我們需要將它們添加在一起以創(chuàng)建一個 GUI。我們可以通過使用 Juypter/Labs 創(chuàng)建我們自己的自定義界面來做到這一點,無需額外修改!
保存并關(guān)閉 Python3 筆記本。我們要導(dǎo)航到 Jupyter Labs,在搜索欄中簡單輸入 《ip》:9090/lab。在我們的例子中是 192.168.0.38:9090/lab。這將打開實驗室環(huán)境。在這里,我們要導(dǎo)航并打開我們的 python3 文件。
從這里您可以單擊并拖動帶有 UI 的單元格并開始創(chuàng)建獨特的 UI
這是我們非常基本的用戶界面。這可以在新選項卡中打開,如下所示。
評論