ModbusRTU讀取溫濕度
# PinToo之ModbusRTU讀取溫濕度
# 1. 說明
範例採用ModbusRTU通訊協議,讀取駁接在Arduino上的DHT22溫濕度感測器數據。ModbusRTU傳輸方式為1個主機對應多個從機,此時使用從機的從機號來做識別,如果主機傳輸的從機號對應到該從機的號碼,如果格式正確該從機會作迴應。因此在Modbus傳輸中,每個從機都是被動的,在運行過程中會不斷監聽是否有收到請求。範例中的Arduino ModbusRTU設定為從機,等待主機發出指令進行各種控制活動。每個從機都有固定的保持暫存器的地址,需參照規範來進行存取。範例中也設定從機號與控制參數的地址。
範例中使用TTL轉RS-485模組(簡稱為TTL485)作為數據傳輸轉換的裝置,用於PC設備與Modbus RTU設備間的數據傳輸,單條485匯流排可以支援32個ModbusRTU設備。範例中採用TTL485擴充套件Arduino開發板在ModbusRTU的功能。TTL485與Arduino開發板的連線方式如下:
TTL485針腳 | Arduino針腳 | 功能 |
---|---|---|
RO | RX | 接受資訊 |
RE | D2 | 收發控制 |
DE | D2 | 收發控制 |
DI | TX | 發送資訊 |
VCC | 5V | 供電 |
GND | GND | 接地線 |
通過範例學習,可以掌握fxUsbSerial控制元件的屬性設定和方法的使用,並結合arduino開發板進行DHT22溫濕度感測器的數據採集。
# 2. 零件連線圖
# 3. 使用零件
序 | 零件名稱 | 數量 |
---|---|---|
1 | Arduino UNO R3 開發板 | 1 |
2 | ProtoShield 原型擴充套件板 含mini麵包板 | 1 |
3 | TTL轉RS-485模組 | 1 |
4 | DHT22溫濕度模組 | 1 |
5 | USB轉485模組 | 1 |
6 | USB數據線 | 1 |
7 | 麵包線 | 若干 |
# 4. Arduino流程圖
# 5. Arduino程式
使用Arduino IDE 編譯並上傳以下Arduino程式。
// 使用溫濕度感測器之鏈接庫 https://github.com/adafruit/DHT-sensor-library
// 使用鏈接庫 https://drive.google.com/file/d/0Bx5wWRfN_z7oMDlZMDhWbXM2VFU/view
// 使用擴充模組 Arduino Sensor Shield 感測器擴充套件板 V5 XBee RS485
// 讀取溫濕度 因為modbus 無法傳遞小數字 所以先乘100 到客戶端取用時要除 100
#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>
#include <DHT.h>
#define dhtPin 8 //讀取DHT22 Data
#define dhtType DHT22 //選用DHT22
DHT dht(dhtPin, dhtType); // Initialize DHT sensor
modbusDevice regBank; // 宣告 Modbus
modbusSlave slave;
#define RS485TxEnablePin 2
#define RS485Baud 9600
#define RS485Format SERIAL_8N1
void setup() {
dht.begin();//啟動DHT
regBank.setId(2); // 設定 Modus 從機號=2
regBank.add(40001); // 設定會使用到之 Holding Register 之地址
regBank.add(40002);
slave._device = ®Bank; // 啟動 modbus RTU
slave.setBaud(&Serial,RS485Baud,RS485Format,RS485TxEnablePin);
}
void loop() {
float h = dht.readHumidity()*100; //讀取濕度 因為modbus 無法傳遞小數字 所以先乘100 到客戶端取用時要除 100
float t = dht.readTemperature()*100; //讀取攝氏溫度
if (isnan(h) || isnan(t)) {
Serial.println("無法從DHT感測器讀取!");
return;
}
regBank.set(40001,t); // 地址 1 存放所測得之溫度
regBank.set(40002,h); // 地址 2 放所測得之濕度
slave.run();
delay(500);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 6. 設計明細
開啟PinToo設計器,分別加入下插圖之控制元件。或者點選左上角的[打開模板Lib檔案]
選擇模板檔案來打開對應模板。
①:TfxSuperButton元件,控制元件名稱為fxSuperButtonSearch
。
②:TfxWidgetLCDLabel元件,控制元件名稱為fxWidgetLCDLabel1
。
③:TfxWidgetLCDLabel元件,控制元件名稱為fxWidgetLCDLabel2
。
④:TfxLabel元件,控制元件名稱為fxLabelMsg
。
⑤:TfxSuperButton元件,控制元件名稱為fxSuperButtonConnect
。
⑥:TfxUsbSerial元件,控制元件名稱為fxUsbSerial1
。
fxRunFrame屬性設定
Height
:設定頁面高度=800
。Width
:設定頁面寬度=400
。
fxTimer1屬性設定
Interval
:設定計時器觸發的時間間隔,單位為ms,設定為5000
。Enabled
:設定是否啟用,設定為False
。
fxComboBox1屬性設定
Visible
:設定控制元件是否可見,設定為False
。
①fxSuperButtonSearch屬性設定
Height
:設定控制元件高度=40
。Width
:設定控制元件寬度=40
。ButtonType
:設定按鈕型別,設定為TfxSvgButton
。Name
:設定控制元件名稱=fxSuperButtonSearch
。ButtonType.SvgData
:設定SVG數據,其數據內容如下。
<path d="M27.3009262084961,24.3846530914307 L25.7649688720703,24.3846530914307 L25.2202167510986,23.8603782653809 C27.1248054504395,21.6445026397705 28.2716579437256,18.7691841125488 28.2716579437256,15.6358289718628 C28.2716579437256,8.65642738342285 22.6152267456055,3 15.6358289718628,3 C8.65642929077148,3 3,8.65642642974854 3,15.6358289718628 C3,22.6152286529541 8.65642738342285,28.2716579437256 15.6358289718628,28.2716579437256 C18.7650909423828,28.2716579437256 21.6404075622559,27.1248054504395 23.8603782653809,25.2202167510986 L24.3846530914307,25.7649688720703 L24.3846530914307,27.3009262084961 L34.1042022705078,37 L37,34.1042022705078 L27.3009262084961,24.3846530914307 Z M15.6358289718628,24.3846530914307 C10.7944831848145,24.3846530914307 6.88700199127197,20.4771690368652 6.88700199127197,15.6358270645142 C6.88700199127197,10.7944822311401 10.7944831848145,6.88700103759766 15.6358289718628,6.88700103759766 C20.4771728515625,6.88700103759766 24.3846549987793,10.7944822311401 24.3846549987793,15.6358289718628 C24.3846549987793,20.4771728515625 20.4771728515625,24.3846549987793 15.6358299255371,24.3846549987793 Z" p-id="2128" fill="Black" stroke="Null"></path>
1②fxWidgetLCDLabel1屬性設定
Height
:設定控制元件高度=95
。Width
:設定控制元件寬度=285
。Color
:設定背景顏色=Black
。
③fxWidgetLCDLabel2屬性設定
Height
:設定控制元件高度=95
。Width
:設定控制元件寬度=285
。Color
:設定背景顏色=Black
。
④fxLabelMsg屬性設定
Height
:設定控制元件高度=40
。Width
:設定控制元件寬度=280
。Text
:設定標籤文字=點選左側按鈕選擇連線埠
。Name
:設定控制元件名稱=fxLabelMsg
。TextSettings.Font
:設定字型大小及顏色。Size
=18,Style
中將fsBold
勾選。使用該屬性需將StyledSettings
中的所有設定為True
的選項的勾去除。
⑤fxSuperButtonConnect屬性設定
Height
:設定控制元件高度=40
。Width
:設定控制元件寬度=40
。ButtonType
:設定按鈕型別,設定為TfxSvgButton
。Name
:設定控制元件名稱=fxSuperButtonSearch
。ButtonType.SvgData
:設定SVG數據,其數據內容如下。
<path d="M13.2001752853394,21.7010040283203 L26.7997760772705,21.7010040283203 L26.7997760772705,18.301628112793 L13.2001752853394,18.301628112793 L13.2001752853394,21.7010040283203 Z M6.22977828979492,20 C6.22977828979492,16.0902290344238 9.28790664672852,13.0296897888184 13.2001752853394,13.0296897888184 L18.3003368377686,13.0296897888184 L18.3003368377686,9.79977798461914 L13.2001752853394,9.79977798461914 C7.58953714370728,9.79977798461914 3,14.3893594741821 3,20 C3,25.6105518341064 7.58953714370728,30.2002239227295 13.2001752853394,30.2002239227295 L18.3003368377686,30.2002239227295 L18.3003368377686,26.9703559875488 L13.2001752853394,26.9703559875488 C9.28790664672852,26.9703998565674 6.22977828979492,23.9074516296387 6.22977828979492,20 M26.7997760772705,9.79977607727051 L21.6996212005615,9.79977607727051 L21.6996212005615,13.0296878814697 L26.7997760772705,13.0296878814697 C30.7093658447266,13.0296878814697 33.7676315307617,16.0902290344238 33.7676315307617,19.9999980926514 C33.7676315307617,23.9074077606201 30.7094097137451,26.9703521728516 26.7997760772705,26.9703521728516 L21.6996212005615,26.9703521728516 L21.6996212005615,30.2002182006836 L26.7997760772705,30.2002182006836 C32.4103698730469,30.2002182006836 37,25.6105480194092 37,19.9999980926514 C36.9999504089355,14.3893585205078 32.4103698730469,9.79977607727051 26.7997760772705,9.79977607727051 Z" p-id="3256" fill="Black" stroke="Null"></path>
1⑥fxUsbSerial1屬性設定
UsbSerialType
:通訊埠通訊協議型別,設定為RS485
。
# 7. 程式設計
點選設計界面右下角的按鈕,切換至單元選擇界面,勾選需要使用的單元。該程式需要引用uUsbSerial
單元。
# 7.1. 程式初始設定
在程式啟動時,修改數值顯示區的外觀。
Begin
fxWidgetLCDLabel1.Caption.FillOff.Color := NULL;
fxWidgetLCDLabel2.Caption.FillOff.Color := NULL;
fxWidgetLCDLabel1.Caption.Format := '000.00';
fxWidgetLCDLabel2.Caption.Format := '000.00';
End.
2
3
4
5
6
# 7.2. 事件設定
- ①fxSuperButtonSearch-OnClick事件
點選按鈕載入通訊埠設備列表。
Procedure fxSuperButtonSearchOnClick(Sender: TObject);
//選擇連線設備
Begin
fxComboBox1.Items := fxUsbSerial1.Devices;
fxComboBox1.DropDown;
End;
2
3
4
5
6
- fxComboBox1-OnChange事件
點選切換設備時顯示目前選擇的設備資訊。
Procedure fxComboBox1OnChange(Sender: TObject);
//顯示連線
Begin
fxUsbSerial1.UsbDevice := fxComboBox1.Items[fxComboBox1.ItemIndex];
fxLabelMsg.Text := '已連線設備 ' + fxComboBox1.Items[fxComboBox1.ItemIndex];
End;
2
3
4
5
6
- ⑤fxSuperButtonConnect-OnClick事件
點選以開啟通訊埠進行通訊連線,啟用計時器。
Procedure fxSuperButtonConnectOnClick(Sender: TObject);
//連線埠
Begin
fxUsbSerial1.Open(True);
fxTimer1.Enabled := True;
fxLabelMsg.Text := '已開啟讀取'
End;
2
3
4
5
6
7
- fxTimer1-OnTimer事件
程式每隔五秒鐘進行一次讀取操作。
Procedure fxTimer1OnTimer(Sender: TObject);
//開啟計數
Begin
fxUsbSerial1.ReadHoldingRegisters(2,0,2);
End;
2
3
4
5
- ⑥fxUsbSerial1-OnReadHoldingRegisters事件
當Usb通訊埠控制元件讀取Modbus設備的保持暫存器時觸發事件,用於接收返回的數據結果。
Procedure fxUsbSerial1OnReadHoldingRegisters(Sender: TObject; ReceiveData: string; UserData: string);
//讀取並轉換計數
var
s: TStrings;
Begin
s := TStringlist.Create;
s.CommaText := UserData;
if s.Count = 2 Then
begin
fxWidgetLCDLabel1.Caption.Value := StrToInt(s[0]) * 0.01;
fxWidgetLCDLabel2.Caption.Value := StrToInt(s[1]) * 0.01;
End;
s.Free;
End;
2
3
4
5
6
7
8
9
10
11
12
13
14
# 8. 運行結果
使用滑鼠在 PinToo 功能表,點選[儲存至資料庫]
按鈕,將其儲存至資料庫,點選[除錯運行]
確認能夠正常打開。
通過同步中心,將程式上傳至手機PinToo運行;同步時,請確保手機已經運行PinToo,並且已經登陸。
將手機與RS485轉USB的埠相連線,為Arduino通電,在手機端點選搜索按鈕,在彈出的列表中選擇通訊埠埠,點選右側的連線按鈕開啟通訊埠,每隔5秒鐘更新溫度及濕度資訊。