我們重視您的隱私
通過點擊「允許所有 Cookie」,代表您同意在您的設備上存儲 Cookie 以增強網站瀏覽體驗、分析網站使用情況並協助我們的行銷和網站效能優化工作。您可以在我們的隱私權政策中找到有關於此的更多資訊。
SmartDisplay 近年來已經被廣泛地應用在醫療、工控、車用等各種領域。簡單地說,它是結合微控制器的顯示器,能夠處理複雜的圖資載入、設定、顯示、甚至是輸入等工作,而外界只要利用簡單的指令就可以進行互動操作,因此非常適合各種需要顯示或控制的各類型應用。
SmartDisplay支援多種通訊介面。目前最常用的是CANbus/CANopen,RS485/Modbus,未來也將提供更多元的選擇。其中RS485/Modbus是工業界常用的通訊介面,市面上很容易取得各種價格合理的RS485裝置。線路架構單純,只要兩條線(RS485_A/RS485_B)就可以進行通訊,而且RS485通訊介面在作業系統上通常是以『序列埠』(Serial Port)的方式呈現,在每種平台都有對應的發展函式庫。再加上Modbus協定相當容易了解,因此我們選擇它來進行實驗與講解。
本文將由淺入深介紹如何控制SmartDisplay,了解其控制原理,最後再介紹如何製作跨平台的應用程式。無論您是工業界設備專家,或是熱衷動手做的Maker自造者,都歡迎和我們一起進入SmartDisplay的世界!
需要支援RS485介面的SmartDisplay進行連線測試。
由於個人電腦/樹莓派通常沒有RS485,我們可以選購各種USB to RS485的轉接線。有些單板電腦內建RS485,則可以直接使用。
符合前面兩個條件後,就可以選擇適合的執行環境。唯一的條件就是能夠讀寫序列埠,因此包括Windows、MacOS、各種Linux(包括樹莓派的Raspbian)、Arduino、單板電腦(SBC)等等都可以勝任,華凌型號:WUACLB120V0000N0NX01即是非常好的單板電腦(SBC)選擇。
首先我們要取得控制碼。最簡單的方式是從SmartDisplay GUI Builder取得。GUI Builder是SmartDisplay的絕佳輔助軟體。它可以幫助我們在沒有實體裝置的情況下學習、操作、設計、顯示使用者介面,完全不需要寫任何程式。具備所見即所得的特性,只要拖曳或點選按鈕或元件就可以進行使用者介面設計。除此之外,內建與SmartDisplay共用程式原始碼的模擬器,因此可以確保與實體裝置一致的外觀與行為。更棒的是,它還是免費的!
► 聯繫我們取得SmartDisplay GUI Builder
執行GUI Builder後,開啟一個專案。在此我們選擇 5”機種,下方的預設情境則選擇車用(Vehicle)。設好專案名稱後,按Create創建。如果先前已經產生過,也可以直按右側的選單直接選取。
專案打開後,先選取介面
Interface選擇RS485,RS485 Port則要設為RS485轉接線實際的連接埠,若是不清楚則可以在裝置管理員中查詢(重覆拔插看消失或顯示的是那一個)。Baudrate採用預設值115200即可。
不過如果現在還沒有RS485裝置也沒關係,只要Interface選擇RS485即可,RS485 Port可以先不用管,因為現在我們只使用模擬器,並不會真的連線到裝置。
按Simulator/Simulator with GUI 開啟模擬器:
執行後可以看到模擬畫面,各元件的控制項,以及右側的控制指令記錄。改變任何一個元件的值就會看到送出的指令內容:
每一個動作都會看到TX/RX兩個指令,這是因為裝置(即使現在其實是模擬器)在收到指令後,會送回相同指令表示已經收到。
我們將不同元件的幾個不同數值記錄下來,下一個步驟可以用來控制實體裝置。
RS485是利用兩條訊號線的電位差來傳送訊號,所以只要這兩條電線就可以連線,連地線都不用接。RS485的訊號線名稱為A+/B-,照著接即可。
主機如何傳送控制碼呢?只要作業系統的程式能寫資料到序列埠即可。不過在進行測試之前,有兩點得先注意一下。
1. 由於在不同作業系統上的Com Port名稱不一樣,因此在測試時請先查詢確定。例如下表:
2. 有些作業系統Com Port的權限預設為不開放,使用前必須先設定一下,以Linux/Ubuntu為例,如果Com Port名稱為 ttyUSB0,則只要在終端機下執行:
sudo chmod 666 /dev/ttyUSB0
下面提供兩種測試方法。
使用支援16進位輸入的序列埠終端機軟體,連線後直接輸入16進位控制碼:
正常的話,應該就可以看到裝置上的元件根據不同控制碼產生動作。
但這種方式只是用來測試是否連線成功,在應用上其實不太方便。要達到最佳效果,還是得藉由程式來完成。至於用那一種語言?其實都可以,我們先用當紅的跨平台程式語言python來試試。
下列程式使用python3執行。程式結構相當簡單,只是直接把三組控制碼每隔一秒寫入序列埠,讓裝置上的儀表持續轉動。
import serial v000 = bytes.fromhex('7B06000600006251') ser = serial.Serial(COM_PORT, 115200) |
python原始碼可以在各種平台上執行,因此只要序列埠的名稱正確,接上適當的轉接線後即可正常運作。
不過這示範程式內幾個固定的控制碼一定不符合實際應用,所以我們接下來要來了解這些指令的內容,才能充份發揮通訊界面的控制功能。
比對同一個元件,不同值的指令:
不難發現,藍色部分就是我們設定元件的值。
比對不同元件,同一個值的指令:
藍色部份顯然是指對元件的某種指標或位址。
至於後方兩個bytes的資料看起來沒有規則,請見以下的控制碼解密。
其實這8個bytes的內容就是所謂的Modbus訊息。簡單地用一張圖來說明各欄位的意義:
ID
每個Modbus裝置都要有一個識別碼。SmartDisplay的識別碼就是0x7B = 123
Fun(Function Code)
功能碼,說明這個訊息的目的,例如這裡的06就是 Write Single Register,也就寫入一個值到指定的地方。
Register Address
暫存器位址,也就是要寫入的目的地(也就是元件的地址)。
Data
要寫入的內容(也就是元件的值)
CRC
對前6個bytes進行CRC(Cyclic Redundancy Check)的結果,用來檢查傳輸過程資料是否發生錯誤。
有些概念了嗎?若要深入了解,還是得先看一下什麼是Modbus。
Modbus協定其實是一種資料格式。它基本上定義了一個主從架構的通訊內容。由於只是資料結構的定義,因此可以透過各種設備進行通訊,例如RS232, RS422, RS485, 甚至是網路。
由於網路上已經有非常多的教學與說明文件,所以這裡並不對Modbus進行詳細說明。其實只要知道一些概念,就可以對Modbus運用自如了。
Modbus將資料傳輸當成是『暫存器』(Register)存取。每個裝置都要定義自己的暫存器種類與位址供外界參考。所謂傳送資料給裝置就是寫入指定暫存器,讀取資料就是讀取指定暫存器,簡單明暸。另外,每個位址暫存器儲存的值都是16-bits。
根據資料的特性,Modbus定義了幾種讀寫的方法,以訊息中的功能碼指定。
以SmartDisplay的控制程式來說,最常用的就是06:Write single register(寫入一個16-bits的值)以及Read holding registers(讀取多個暫存器的值)。
這個看起來最神秘的部分其實不難,這只是一個通訊的檢查碼,用以確保通訊資料的正確性。我們不一定要深入研究其原理(但實際上也只是查表以及位元運算,最後得到16-bit檢查碼),只要了解如何使用即可。
前面提到每個Modbus都要定義暫存器種類與位址,現在就來討論這個主題。
SmartDisplay暫存器大致可分成三類:
1.)裝置資訊(例如版本、裝置名稱等)
使用04:Read Input Registers讀取。這些資料只有在更新韌體時才會改變,通常是剛連線時讀取,用來取得裝置特性參數。
2.)元件特性(例如種類、位置等等)
使用03:ReadHoldingRegisters/16: Write Multiple Register 讀寫。這些資料影響到元件的外觀顯示,在非設計階段時通常不會改變。若要改變內容,必須先將SmartDisplay顯示暫時關閉才能更新。
3.)元件數值(元件表現的值,例如轉速、開或關,百分比等等,因元件而異)
這是運作中主要改變的項目。每個元件都使用一個16-bits數值,因此用06:Write Single Register設定。
下面列出這些暫存器的整理清單:
早期的SmartDisplay只支援10個元件,因此widgetID的範圍介於0 ~ 9(含)。新版的韌體已經擴展到64個,不過定址方式有些改變,這裡暫不討論。
有了這些資料後(雖然還不完整,但是目前夠用了),我們就可以將控制指令進行包裝,傳送給SmartDisplay進行控制。至於如何包裝,以及如何加入CRC碼,將在後面的章節說明。
要讓SmartDisplay進入實際應用,還是需要有一個適合的人機介面(尤其是圖形人機介面,Graphics User Interface, GUI),才能發揮最大效用。目前跨平台的GUI發展平台有經有很多選擇,我們這裡使用Qt來實現。
許多人以為Qt僅僅是GUI函式庫,但其實它是相當完整的發展框架(Framework)。如果應用程式完全透過它的類別庫來實現,就可以很容易地將專案移植到其他平台(PC/Windows、Mac/MacOS、 Raspberry Pi/Raspbian、Android、iOS、Embedded等等),幾乎不用修改程式,是相當值得投資學習的發展工具軟體。
比較新版的Qt其實也已經支援Modbus類別庫了。但這裡為了說明,以及方便大家改寫成其他語言,我們還是從最基本的序列埠讀寫來實現這個測試程式。
這個程式除了提供選擇序列埠的功能以及傳送上個例子使用的控制碼以外,在使用者介面還進一步提供一個水平拉桿,能夠設定指定元件的數值。序列埠如果選擇COM的話,要記得再填上實際的編號。
下圖這個程式在樹莓派以及Ubuntu上的執行畫面,程式完全不用修改。
CRC運算其實不複雜,以Qt來實現大概就像以下的程式碼:
QByteArray SetWidgetValue::calculateCRC(QByteArray data) |
其中的 crcTable[] 的內容為:
const uint16_t crcTable[] = |
這裡沒有列出全部內容。github中有完整資料,有興趣可以自行搜尋下載,在這邊技術文章中只需要知道如何運用就好。
下面就是根據UI計算控制碼,然後送到SmartDisplay的關鍵函式:
void SetWidgetValue::on_sbValue_valueChanged(int value) |
如果您已熟悉Qt,則上述程式碼應該不難理解。若不熟悉的話,花一點時間研究一下,它有些觀念其實還相當不錯,值得深入學習。熟悉之後,對發展跨平台應用程式,或是快速製作系統雛型來說,都是不錯的選擇。
前面的例子只是針對一個元件值的設定。另外有更完整的範例SmartDisplayConsole供有興趣的讀者進一步了解。下圖是在樹莓派上的執行畫面:
文章最後有github網址,觀迎大家一起參考研究。
我們已經說明了控制SmartDisplay的每一個步驟,也提供了多種的控制方式。運用這些知識以及豐富的想像力,相信一定可以激盪出各種不一樣的火花,製作出更多樣性的產品。就讓我們一起用SmartDisplay創造更美好的未來吧!
Serial Terminal Basics
https://learn.sparkfun.com/tutorials/terminal-basics/command-line-windows-mac-linux
Modbus
https://www.modbustools.com/modbus.html
https://www.modbusdriver.com/doc/mbusmaster.net/modbus.htm
GettingStartedWithSmartDisplay
https://github.com/Smart-Display-Series/GettingStartedWithSmartDisplay.git
SmartDisplayConsole
https://github.com/Smart-Display-Series/SmartDisplayConsole.git
通過點擊「允許所有 Cookie」,代表您同意在您的設備上存儲 Cookie 以增強網站瀏覽體驗、分析網站使用情況並協助我們的行銷和網站效能優化工作。您可以在我們的隱私權政策中找到有關於此的更多資訊。