目錄表

AT2051(數位溫度計) & UR485(RS-485 to USB) @ FreeBSD with PHP

今天下午拿到的新玩具~

前言

希望可以拿來偵測機房的溫度, 進而做些告警之類的事情,雖然有 VB 的程式, 但是 VB 不利於後續的使用, 因為需要能夠把記錄到的溫度丟到資料庫存起來 或是用 mrtg 進行長期之溫度監控, 所以就開始研究怎麼用 PHP 去取得 Serial port 的資料.

重點還要能好好利用 RS-485 的特性, RS-485 其實很常用於監控或是控制, 在大型的監控裡, 經常可以見到 RS-485 的蹤跡, 因為它可以遠距離的傳輸及控制. 且又可以多個偵測器使用同一條線路, 類似電話線這樣, 搭上線即可.

但是每個偵測器或是控制器又可以設定 ID 來區隔, 一路 RS-485 上可以擁有多個 ID 每個偵測器不可以重複 ID, 不然會出錯.

詳細資料可翻一下 Wikipedia 有關 RS-485 的資料

第一次接觸到 RS-485 是在某大型展覽館, 其空調及風扇等開關幾乎都用 RS-485 來控制, 且於每層樓使用 RS-485 轉 Ethernet 來減少所有樓層到中控室的線路數量.又兼具遠距監控控制的需求, 很佩服一開始想出來的人啊~.

實作

實作的部份可分三個部份:

  1. AT2051 及 UR485 的接線
  2. UR485 on FreeBSD
  3. PHP get UR485 data

實作開始

  1. AT2051 及 UR485 的接線
    • 這部份我不想著墨太多, 因為網路上有很多說明跟你說怎麼做, 且原廠網站上的說明更是詳細又清楚, 所以我直接略過這部份. 而我在這部份僅用了該公司的 VB on Windows XP 來檢查我線有沒有接錯而已.
  2. UR485 on FreeBSD
    • 我使用的 FreeBSD 是 7.2 Stable 版, UR485 一接上去之後就會偵測到 ucom0 (kernel 裡頭的 ucom 等 USB 的 device 要留著)網路上一些比較舊的文章都會寫它的 device 路徑為 /dev/ucom0, but 我在 7.2 一直都失敗, 最後用土法煉鋼的方式, 直接 ls /dev/ 看拔掉跟接上去的差別, 進而找到該裝置的位置是 /dev/cuaU0 一個很怪的名稱, 我也不知道為什麼~
  3. PHP get AT2051 data over UR485
    • 接下來就是最重點的部份了, 這部份我研究了大約一個多鐘頭, 從PHP Manual 去翻有關 RS-232 的資訊, 結果我找到了 DIO(Direct I/O) 這個函式, 在 FreeBSD 的 ports 位置為 /usr/ports/devel/php4-dio/ 安裝它之後才可以使用 dio 的相關函式. 下面為 UR485 使用 dio 取得資料的一個簡單程式內容PHP程式碼
AT2051.php
<?
  // 要顯示 debug 就改 1;
  $debug=1;
 
  // /dev/cuaU0
  $fd = dio_open('/dev/cuaU0',O_RDWR | O_NOCTTY | O_NDELAY);
  dio_fcntl($fd,F_SETFL,0);
 
  // 設定傳輸速率, 也就是 RS-232 常聽到的 9600 N 8 1
  dio_tcsetattr(
    $fd, array(
      'baud' => 9600,
      'bits' => 8,
      'stop' => 1,
      'parity' => 0)
  );
 
  // 按照 AT2051 說明書所說的, 要抓 ID 1 的偵測器
  // 就輸入給 01H, ID 2 給 02H 以此類推
  dio_write($fd,"\x01H",1);  // write 0x01H to /dev/cuaU0
 
  for($i=1 ; $i<=7 ; $i++) {
  // AT2051 最多只會輸出 7 個字
    $data = dio_read($fd, 2);
    // 從 AT2051 取得資料, 由於它最多一次
    // 只會有 2 個字元, 所有只需要 2 即可
    if($data == "T" || $go){
    // 一開始的字元偶爾會出現多餘的換行字元,
    // 所以從抓到 T 才開始
      $go=1;
      // 給個抓到 T 之後都要跑的 tag
      $temp .= $data;
      // 把抓到的字通通串起來
 
      // for debug 用, 顯示每次的回傳值
      if ($debug) echo "$i => $data\n";
 
    }
  }
 
  if ($debug) echo "ALL => $temp\n";
  // 把我不要的字通通取代掉
  $temp = str_replace("T1=+", "", $temp);
  if ($debug) echo "$temp\n";
  $temp = str_replace("C", "", $temp);
  if ($debug) echo "$temp\n";
 
  $up = "不知道";
 
  // 以下這邊是給 mrtg 畫圖輸出用的, 共輸出四行
  echo "0" . "\n";        // 綠色線
  echo $temp . "\n";      // 藍色線
  echo $up . "\n";        // 運作時間
  echo "AT2051 溫度\n";   // 註解
 
  // 養成關閉連線的好習慣
  dio_close($fd);
?>


<fbl>