2011年10月17日星期一

Arduino 模擬 Modbus Slave

最近又有新的案子,是要在 Window 7 下來連 Modbus 設備,很久沒寫有關 Modbus 的連線軟體了,上網再查一下 Modbus 的相關資料,居然發現了好東西,有人用 Arduino 開發模擬 Modbus Slave 的軟件,趕快下載下來測一下。

原始網頁 - Arduino Modbus Slave,因為是別人寫的,就不方便把人家的程式展示在我這,有興趣的自己去看,我的測試環境如下:

  1. Arduin Uno 板。
  2. Dfrobot 出的 I/O expansion (5.0) Board(上有 RS 485 介面)。
  3. USB 轉 RS232。
  4. RS232 轉 RS 485m
  5. LCD 1602 (I2C 介面) 。 用來 Debug 用。
Lcd 1602 I2C介面

Arduino Uno 上載 I/O Expansion 板

Usb 轉 RS232 和 Rs232 轉 RS485

還要再下載一個很好用的 Simply Modus,這是一個把 Window 成 Modbus Master (Poll)的軟體,有了這個軟體,作 Modbus 測試很方便:

Simply Modbus 的執行畫面


先用 Arduino - 0022 把下載下來的 Pde 上傳到 Arduino Uno 板子上,我有迫不急待的在Simply Modbus 上按 Send, 好像沒有結果, 下定決心把 LCD 1602的程式碼加入 Modbus_rtu_slave.pde中,我只在程式的一開始加入:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

並在 Setup 程式碼中加上:

lcd.init();
lcd.backlight();
lcd.print("Start");

為了讓 LCD 上是顯示出 HEX 數字,我又找呵一段小程式,把收到的字元轉成16 進位的數字,便於跟 Simply Modbus 上的資料直接作比對,程式如下:

void lcdPrintHex (const unsigned char out) {
  unsigned char temp;
  temp = out >> 4;
  temp += (temp > 9) ? 'A' - 10 : '0';
  lcd.print (temp);
  temp = out & 0x0f;
  temp += (temp > 9) ? 'A' - 10 : '0';
  lcd.print (temp);
}

在 validate_request 中加上 lcdPrintHex 來顯示收到的資料,再重信上載到 Arduin Uno 板上,再度按下 Simply Modbus 上的 Send 鍵,結果 LCD 上還是 未顯示任何資料,心快涼了一半,哪出錯了。 首先最值得懷疑的就是 Dfrobot 出的這塊 expansion board 有問題,上原廠的 Wiki 版找答案,在 Wiki 上有2個非常簡單的小程式,在 Sample Rs485 Transmit Data 中有一行:

digitalWrite(EN, HIGH);//Enable data transmit

EN 在最前面是設定為 2,RS485 再作傳輸時,除本身的 0 and 1 pins 傳資料外,還要處理 Pin 2
,再次 Trace 下載下來的程式 ,發現我下載下來ˇ的程式,把 Pin 2 寫成 Pin 0 ,更正程式後,在次上傳,終於看到結果了。