2013年7月29日 星期一

[Arduino] 將溫度寫入 SD 卡並以 Http 送給 Linux Server 以 PHP 寫入 MySQL 資料庫

前陣子玩了一些水耕的設備, 因為要天天記錄溫度、EC(電導度)、PH(酸鹼度), 顯得有點麻煩,所以打算自己 DIY 一些設備來玩玩。 首先考慮到程式開發的速度,選擇使用 Arduino 的板子來 DIY 我所購買的板子是 Arduino Leonardo,

另外購買 Arduino Ethernet W5100 網路擴展板,含 miniSD 座 以及 DS18B20 溫度感測器 不鏽鋼封裝 防水型
電路接法請參考Arduino 溫度感應
首先下載 OneWire Library Dallas Temperature Control Library 將這兩個檔案解壓縮後放到 Sketchbook 的資料夾下 相關說明請參考 葉難(Arduino 教學部落格) 或是開啟 Arduino 的 IDE 主程式,點選 File → Preferences 找到 Sketchbook 的路徑,
前置作業完成後就可以開始複製貼上了 程式碼如下:
#include 
#include 
#include 
#include "floatToString.h"
#include 
#include 

byte mac[] = {  0x00, 0xAB, 0xCB, 0xCD, 0xDE, 0x02 };
IPAddress ip(192,168,1,38);
IPAddress server( 192, 168, 1, 37 );
String strGet="GET /~webuser/hydroponics/TempDeg2DB.php?degree=";
String strHttp=" HTTP/1.1";
String strHost="Host: 192.168.1.37";  //OK
int serverPort=80;
//IPAddress mydns(168,95,1,1);  //OK
EthernetClient client;
#define ONE_WIRE_BUS 2
File myFile;
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
// arrays to hold device address
DeviceAddress insideThermometer;


void connect(String tempdeg){
         if (client.connect(server, serverPort)) {
             Serial.print("Make a HTTP request ... ");
             myFile.print("Make a HTTP request ... ");
             //### Send to Server
             String strHttpGet = strGet + tempdeg + strHttp;

             client.println(strHttpGet);
             client.println(strHost);
             client.println();

             SD.println(strHttpGet);
             SD.println(strHost);
             SD.println();
           } 
           else {
         }
}

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.print("Initializing SD card...");
  pinMode(4, OUTPUT);
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  //Serial.println("initialization done.");
  myFile = SD.open("Temp.txt", FILE_WRITE);
  if (myFile) {
    sensors.begin();
    
  // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(insideThermometer, 9);
 
  //### Init Net
  //Ethernet.begin(mac, ip, mydns);
  Ethernet.begin(mac, ip);
  
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
  // method 2 - faster
  float tempC = sensors.getTempC(deviceAddress);

  char mybuffer[6];
  connect(floatToString(mybuffer, tempC, 2));
  
}

void loop(void)
{ 
  myFile = SD.open("Temp.txt", FILE_WRITE);
  if (myFile) {
    sensors.requestTemperatures(); // Send the command to get temperatures
    printTemperature(insideThermometer);
    delay(15000);
    myFile.close();
  }
}
//====== 下面的程式碼不屬於本程式,而是網站本身帶出的 =====

因為我的板子是 Arduino Leonardo 所以 Compile 時檔案會太大,
因此上網找了一些方式可以再縮小檔案,雖然減少的量不大(2K),但不無小補。
移除 DNS 以減少檔案大小 參考文章(Reducing code size on Arduino Ethernet boards)
為了進一步減小檔案,再將浮點數轉換方式換掉。 浮點數轉字串
以上步驟做完時,重新 Compile 就可以過了。

修改過的程式碼請自行下載
浮點數轉字串Source Code(Flot2String.7z)
移除 DNS 的 Net Library Source Code(Ethernet_NoDNS.7z)

這時只要寫個 PHP 網頁程式,把資料寫入資料庫就可以囉~
//取出網址列所帶入的參數
    $send_degree=$_GET[degree];
 // 設定地區時間
 date_default_timezone_set("Asia/Taipei");
    echo strftime("%Y-%m-%d %H:%M:%S");
 //取得主機日期和時間
    $Login_Date=date("Y-n-j");
    $Login_Time=date("H:i:s");
 //資料庫登入資料
 $dbhost = 'localhost';
    $dbuser = 'testuser';
    $dbpass = '12345';
 $dbname = 'hydroponics';
 //登入資料庫
    $conn = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error with MySQL connection');
    mysql_query("SET NAMES 'utf8'");
    mysql_select_db($dbname);
 $sql = "INSERT INTO `Hydroponics`.`Temperature` (`degree`, `ServerDate`, `ServerTime`) VALUES ('$send_degree', '$Login_Date', '$Login_Time');";
 $result = mysql_query($sql) or die('MySQL query error');

13 則留言:

  1. 不一定要 Linux Server ,Windows 的 IIS 或是 Apache 都可以,只要能跑 PHP 的網頁就行了。
    這裡會寫 Linux Server 是因為我的主機正好是 Linux ,
    如何建立或安裝請自行 Google 囉~
    這裡不再另外說明。

    回覆刪除
  2. 您好:
    請問Arduino如何連結localhost的呢?
    如果說 我只是把Arduino當作sensor資料的傳輸管道
    然後傳回host computer後在執行server更新資料庫有什麼差別嗎?
    謝謝

    回覆刪除
    回覆
    1. 因為 Arduino 的網路板子就有一組獨立 IP ,所以你要連線的電腦將會是不同 IP ,因此沒有 Localhost 這個東東,
      硬要用,建議直接寫入 SD 卡比較方便
      或是插著 USB 直接傳輸,由電腦做 update database 的工作更簡單

      刪除
  3. 請問你的EC值Sensor是Arduino相容的嗎?如果是的話,可否提供購買資訊給我,因為我最近也要用到,但是一直找不到合適的。
    謝謝~~

    回覆刪除
    回覆
    1. 我的 EC Sensor 是另外 DIY 的,
      請參考http://www.octiva.net/projects/ppm/
      有關 TDS / EC 的轉換,我是參考
      http://www.ecaa.ntu.edu.tw/weifang/YunLin/EC2CF2PPM.pdf

      另外我也有購買數位式的 TDS / EC 測試筆,
      以便做數值比較

      刪除
  4. 請問有你改好的libraries請問有擬改好的嗎
    謝謝

    回覆刪除
  5. 感謝大大賜教!!
    我想讓Arduino傳送讀取到的rfid資料,傳上Raspberry PI上的mysql,我需要另外購買Arduino Ethernet板嗎?還是可以透過其他方式傳送?比如說抓到Arduino讀取的資料,把它傳送到位於PI的另一個程式上?

    回覆刪除
  6. Raspberry Pi 我沒玩過,
    不過應該大同小異,
    透過 Ethernet 傳送就要加買Arduino Ethernet板,
    若要透過 USB 傳送,可以直接使用 USB Port
    另外,Arduino Ethernet板就有記憶卡插槽,
    也可以存到記憶卡再將卡片換到Raspberry Pi 上,但這麼做不太實際就是了。

    回覆刪除
  7. 請問一下大大:
    我可以直接用Arduino打開我寫好的PHP程式網頁,而不是把php寫在Arduino裏頭嗎??

    回覆刪除
    回覆
    1. 不清楚你說的 "打開寫好的PHP" ??
      另外,我也沒有將 PHP 寫在 Arduino 裡,
      我是以 Arduino 將要傳送的資料,
      透過
      "GET /server.address/TempDeg2DB.php?degree="
      方式,將數值送給遠端的 PHP Server,請 PHP 幫我寫資料庫

      刪除