2017年2月1日 星期三

LinkIt 7688: 0 Day IoT Gateway DIY

在工業界,Modbus 可說是使用最廣泛的通訊協議,廣泛到即使上露天拍賣輸入 "modbus" 也可以找到一堆 Modbus RTU devices。這些 device 的用途有:

  • 可程式控制器(PLC)
  • 溫度控制
  • 遠端 IO(類比,數位)
  • 電壓電流量測
  • 溫濕度量測
  • 水質監測
  • 族繁不及備載

Modbus RTU device:台達溫度控制器

Modbus RTU device 大部分走串列通訊,也就是傳統的 RS232/422/485,如果要讓這些 devices 連上 Ethernet or Wi-Fi,就必須買台 Modbus Gateway,這可是一筆不小的開銷。如果你想買上述裝置的網路版(Modbus TCP device),價錢更是三級跳。

連線架構(點圖放大)

(下圖為台達溫控器側面,可以明顯看出支援 RS485)

現在我們有了神器 LinkIt Smart 7688,只需要幾個步驟,就可以改造成市面上要價不斐的 Wi-Fi/Ethernet Modbus Gateway!

抓穩了,我們要起飛了!

1. 編譯 mbusd

mbusd 全名為 Open-source Modbus TCP to Modbus RTU (RS-232/485) gateway。為何選擇它?原因很簡單,因為 Google 搜尋結果排名第一(我承認這理由有點爛),不過去年測試的結果相當穩定。另外有一個頗知名的相關專案 - libmodbus,在本 blog 也提過,不過 libmodbus 偏向用於開發 Modbus TCP/RTU device,他並沒有 Gateway 功能。

1.1 下載 mbusd

在 7688 SDK 目錄內的 package/ 建立目錄 mbusd,以筆者的環境為例:
/opt/mt7688sdk/package/mbusd
clone source code:
.../mbusd# git clone https://github.com/3cky/mbusd.git src 

1.2 產生 Makefile

請依據你的環境修改以下 script 內的 SDK 路徑,然後存檔為 mkenv.sh (別忘了 chmod +x mkenv.sh)
#!/bin/sh
export PATH=$PATH:/opt/mt7688sdk/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin
export CPPFLAGS=CPPFLAGS="-I/opt/mt7688sdk/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include -I/opt/mt7688sdk/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/include -I/opt/mt7688sdk/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include -I/opt/mt7688sdk/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/include "
export CFLAGS=CFLAGS="-Os -pipe -mno-branch-likely -mips32r2 -mtune=24kec -mdsp -fno-caller-saves -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float "
export CXX
export CC=mipsel-openwrt-linux-uclibc-gcc
export AR=mipsel-openwrt-linux-uclibc-gcc-ar
export AS=mipsel-openwrt-linux-as
export LD=mipsel-openwrt-linux-uclibc-ld
export LD=mipsel-openwrt-linux-uclibc-ld
export RANLIB="mipsel-openwrt-linux-uclibc-gcc-ranlib"
export LDFLAGS="-L/opt/mt7688sdk/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/lib -L/opt/mt7688sdk/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/lib -L/opt/mt7688sdk/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib -L/opt/mt7688sdk/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/lib "
export NM="mipsel-openwrt-linux-uclibc-gcc-nm"
接著輸入以下指令:
.../mbus/src# ./mkenv.sh
.../mbus/src# ./configure --target=mipsel-openwrt-linux --host=mipsel-openwrt-linux --build=x86_64-linux-gnu

1.3 編譯

在 package/mbusd/ 這一層還需要一個 Makefile(如果你試過 7688 SDK helloworld 範例相信對此不陌生),版號 0.2.3 是因為寫這篇文章的當下mbusd  正好是這個版本:
include $(TOPDIR)/rules.mk

PKG_NAME:=mbusd
PKG_VERSION:=0.2.3
PKG_RELEASE:=1

include $(INCLUDE_DIR)/package.mk

PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)

TARGET_LDFLAGS+= \
  -Wl,-rpath-link=$(STAGING_DIR)/usr/lib

define Package/mbusd
  SECTION:=utils
  CATEGORY:=Utilities
  TITLE:=mbusd modbus gateway
endef

define Package/mbusd/description
 mbusd modbus gateway
endef

define Build/Prepare
 mkdir -p $(PKG_BUILD_DIR)
 $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Configure
endef

define Build/Compile
 $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
endef

define Package/mbusd/install
 $(INSTALL_DIR) $(1)/bin
 $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/mbusd $(1)/bin/
endef

$(eval $(call BuildPackage,mbusd))
進入 SDK 根目錄,輸入以下指令編譯 mbusd:
/opt/mt7688sdk# make package/mbusd/compile -j1 V=s
您可能會看到以下錯誤訊息:
......
libtool: Version mismatch error.  This is libtool 2.4.2, but the
libtool: definition of this LT_INIT comes from libtool 2.4.
libtool: You should recreate aclocal.m4 with macros from libtool 2.4.2
libtool: and run autoconf again.
.....
回到 package/mbusd/src/,輸入以下指令
.../mbus/src# autoreconf -ivf
.../mbus/src# ./configure --target=mipsel-openwrt-linux --host=mipsel-openwrt-linux --build=x86_64-linux-gnu
再回到 SDK 根目錄,輸入以下指令重新編譯:
/opt/mt7688sdk# make package/mbusd/clean
/opt/mt7688sdk# make package/mbusd/compile -j1 V=s

2. 安裝測試

如果 1. 編譯 mbusd 順利完成,應該可以在 SDK 目錄下找到安裝包(*.ipk):


把 ipk 拷貝到 7688 /tmp 下(個人習慣),輸入以下指令安裝 ipk:


輸入以下指令執行 mbusd (預設 parity: none, data bits: 8, stop bit: 1)


測試線路如下。會需要 Null Modem 轉接頭的原因是因為市面上大部分買的 TTL 轉 RS232 Tx/Rx 都對調了,所以需要 Null Modem 幫我調回來。


Modbus Master 測試軟體(Modbus Poll)測試:



觀察溫控器錶面,數值一樣,成功了!

註:沒有 Modbus RTU device 的朋友可以改用 Modbus Slave, ModSim32 兩套模擬軟體進行測試。

3. 開機時執行 mbusd

到這裡還差最後一里路,就是我們希望 7688 開機時執行 mbusd,這樣就不用每次重開機還要手動輸入指令。

觀察 /etc/rc.d/


可以看到 init 系統(procd)執行的順序是從 S00-S98,放在 S99 肯定是安全的選擇。

建立 /etc/init.d/mbusdctl,內容如下:
#!/bin/sh /etc/rc.common
#/etc/init.d/mbusdctl
START=99
STOP=99

start() {
    mbusd -p ttyS1 -s 38400 -T 1000
}

stop() {
    kill $(ps | grep '\bmbusd\b' | awk '{print $1}')
}
enable mbusdctl:


重開機後檢查是否在運行中:


成功了!我好興奮啊~

4. 待改進之處

  • 從開機到執行 mbusd 的時間太長,將近 1 分鐘,筆者曾經把 mbusd 放到較前面執行(< S99)但失敗了,如果您實驗出來請留言,感激不盡!
  • mbusd 啟動參數寫死在 script 裡:不過 LinkIt 7688 Web CGI 入門(1)(2)LinkIt 7688 筆記: rpcd,這三篇文章可以幫你解決問題。

5. 檔案下載

10 則留言:

  1. 非常棒!这个软件包可以提交给OpenWRT了

    回覆刪除
  2. 請問
    mkenv.sh
    要放在哪個路徑下.
    Thank you!

    回覆刪除
    回覆
    1. 只要不logout,在哪個路徑執行都可以

      刪除
  3. Hi 你好!
    我在編譯時失敗
    root@ubuntu:/home/max/MT7688_SDK_OpenWRT/openwrt/modbus# make package/mbusd/compile -j1 V=s
    make: `package/mbusd/compile' is up to date.
    能否告知是哪裡有問題.

    Thank you!

    回覆刪除
    回覆
    1. 您的路徑怪怪的,在範例中我是先把 7688 SDK 複製到 /opt 然後解開,目錄被我重新命名為 mt7688sdk,所以範例中是 /opt/mt7688sdk,MTK 提供的 helloworld 您可以編譯成功嗎?如果是,那您就成功一半了

      刪除
  4. Hi 你好!
    重新 download MT7688 SDK
    https://downloads.openwrt.org/chaos_calmer/15.05.1/ramips/mt7688/
    再依照你方式及路徑
    編譯成功.
    感謝你的幫忙.

    Thank you!

    回覆刪除
  5. Can you share the file "mbusd_02.3-1_ramips_24kec.ipk" with me

    enkavak@hotmail.com

    回覆刪除
    回覆
    1. Can you share the file "mbusd_0.2.3-1_ramips_24kec.ipk" with me

      enkavak@hotmail.com

      刪除