2014年4月18日金曜日

arduinoをwebサーバーにしてブラウザから温度、照度を見てみる


イーサネットシールドとライブラリを使い、webサーバーを立ち上げ、測定した温度、照度をブラウザから確認できるようにします。




サンプルスケッチ「WebServer」とこの記事のスケッチを合わせただけ。
http://cranberrytree.blogspot.jp/2014/04/lcd.html



#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };    //シールドに貼られているシールのmacアドレスに変更
IPAddress ip(192,168,11,177);              //環境に合わせて変更
EthernetServer server(80);

const int pin_temp = A0;    //Analog input LM60
const int pin_lux = A5;     //Analog input NJL7502L

int sensorValue_temp = 0;   //value read from pin_temp
float offset = 0.424;       //offset 424mv
float vc = 0.00625;         //+6.25mv/1℃
float temp = 0.0;
float vref = 5.00;          //デフォルト参照電圧5V=電源電圧
                            //実際の電圧に合わせる
                            //USBの電圧はいいかげん 

int sensorValue_lux = 0;    //value read from pin_lux
float lux = 0.0;
long r_lux = 10000;         //NJL7502Lに接続している抵抗値
                            //10KΩ ~1,000lux
                            // 1KΩ ~10,000lux

void setup() {
//  analogReference(INTERNAL);  //参照電圧1.1Vにする時
  Serial.begin(9600);
    while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");

          get_temp();                //温度取得
          get_lux();                 //照度取得
          client.print("temperature = ");
          client.print(temp);
          client.print("<br />");       
          client.print("lux = ");
          client.print(lux);
          client.print("<br />");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

void get_temp(){
  sensorValue_temp = analogRead(pin_temp);
  float v_temp = sensorValue_temp * vref / 1024;
  temp = (v_temp - offset) / vc;           //電圧から温度に変換
  Serial.print("LM60 = " );
  Serial.print(sensorValue_temp);
  Serial.print("\t Volt = " );
  Serial.print(v_temp,4);
  Serial.print("\t TEMP = ");
  Serial.println(temp);
}

void get_lux(){
  sensorValue_lux = analogRead(pin_lux);
  float v_lux = sensorValue_lux * vref / 1024;
  lux = 2 * ( v_lux / r_lux ) * 1000000;        //データシートより lx = 2 x 光電流[μA]
  Serial.print("7502L = " );
  Serial.print(sensorValue_lux);
  Serial.print("\t Volt = " );
  Serial.print(v_lux,4);
  Serial.print("\t lux = ");
  Serial.println(lux);
}





イーサネットシールドを使わなかった時は、計測結果が置き時計時計の温度計やアナログ温度計とほぼ同じ(24℃)で精度に満足していたのですが、イーサネットシールドを乗せて温度を測定すると、温度が約6℃高く(30℃)なるというおかしなことになってしまいました。

色々悩みましたが、供給電圧が低いのが原因だったようです。
USBから給電している時の5Vピンは4.55V。
外部電源から供給した時は4.96Vでした。

外部電源使用時、置き時計の温度計、アナログ温度計(24℃)より2~3℃ほど低くなってしまいました。
個体差かも知れません。


追記:参照電圧と電源電圧について

アナログ入力時、ADCの基準となるのは参照電圧でデフォルトは電源電圧となっています。(内部1.1V、外部0V~5Vに変更可能)
デフォルトで測定する場合、電源電圧と変換式に注意しないといけません。
analogRead(pin) *vref/1024

実際に再計測しました。
USB電源使用時
4.55V
vref=5.0で計算 vref=4.55で計算

約30℃ 約21℃
外部電源使用時
4.96V
vref=5.0で計算 vref=4.96で計算

約21℃ 約21℃
USB電源使用時
4.55V
内部参照電圧1.1V
vref=1.1で計算

約23℃
アナログ温度計、置き時計のデジタル温度計は24℃
外部電源はDCジャックに9Vを入力
各電源電圧は5Vピンで測定
センサーには5Vピンから電源供給
イーサネットシールドを乗せて動作中

結論:特にアナログセンサーを使うときは、実際の電源電圧と計算式に注意

USB電源を使うときには電圧とvref(変数)の値に注意。測定結果が大きく変わる。
・外部電源をDCジャックにつなぐとarduinoボード上のレギュレーターの精度に依存する。
実際に出力電圧を測りvrefを定義するのがよりいい。
・アナログセンサーの出力電圧が1.1Vに収まるなら内部参照で測定してもいい。
・さらに精度が必要なら、外部参照するためにシャントレギュレーターが必要になる。

・・・と思う。



環境:arduinoUNO、arduinoIDE1.0.5、イーサネットシールドR3、win7(64bit)

0 件のコメント:

コメントを投稿