arduinoで気温をツイート
arduinoにイーサネットシールドと温度センサLM35を接続してみました。
こんな感じで室温をツイートします。
https://twitter.com/#!/keigox68000/status/166234898166849537
スケッチ(プログラム)はいろんなところから借りてきたコードを切り貼りしてます。(この記事の最後に掲載)
Twitter関連は、NeoCatさんのArduinoからTwitterにPOSTするライブラリ OAuth版を参考にしてます。
温度センサ関連は、書籍を参考にしてます。
- 作者: 高橋隆雄
- 出版社/メーカー: 秀和システム
- 発売日: 2011/12/01
- メディア: 単行本
- 購入: 2人 クリック: 10回
- この商品を含むブログ (5件) を見る
arduinoのsprintfは固定小数点が「?」に化けるバグ(?)があるらしく、いろいろ検索してそれに気づくまでに何時間もかかってしまいました。くっそー
http://dereenigne.org/electronics/arduino/arduino-float-to-string
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1164927646
国内で同じような情報が見つけられませんでした……やっぱり海外のサイトも積極的に見ないとダメだなぁ。
結局、LM35から取得した数値を温度に変換したものを10倍してから整数部分だけを文字列に格納(小数点第一位まで求めて)、その文字列に小数点を挿入するという回りくどい方法で小数点第一までの温度を表示することにしました。
そんなわけでarduinoと便利なライブラリのおかげで定期的に室温をツイートするところまでは行けたのですが、室温が変わらない場合はTwitterの制限で連続ポストできないため、温度に時刻を付加してポストするようにしてみました。
ntpサーバから時刻を取得するのですが、こちらはarduino IDEのサンプルと、なんでも作っちゃう、かも。さんの「Arduinoで遊ぼう - NTPを使ってインターネット経由で時刻をあわせる」の記事がとても参考になりました。
とりあえず、arduinoを使ってデータを取得してツイートするところまではできたので、これから本番に移ります。室温なんかポストしてもTL汚すだけなのでもっと別なことで遊んでみます(笑)
気温を計測してポストする(必要ないコードなど残っていますが参考まで)
#include <SPI.h> // needed in Arduino 0019 or later #include <Ethernet.h> #include <Twitter.h> #include <EthernetUdp.h> #include <Time.h> // The includion of EthernetDNS is not needed in Arduino IDE 1.0 or later. // Please uncomment below in Arduino IDE 0022 or earlier. //#include <EthernetDNS.h> // Ethernet Shield Settings byte mac[] = { 0x**, 0x**, 0x**, 0x**, 0x**, 0x** }; // UDPローカルポート番号 unsigned int localPort = 8888; // NTPタイムサーバIPアドレス(ntp.nict.jp NTP server) IPAddress timeServer(133, 243, 238, 164); // NTPパケットバッファサイズ const int NTP_PACKET_SIZE= 48; // NTP送受信用パケットバッファ byte packetBuffer[NTP_PACKET_SIZE]; // Udpクラス EthernetUDP Udp; // 最後にパケットを送信した時間(ミリ秒) unsigned long lastSendPacketTime = 0; // If you don't specify the IP address, DHCP is used(only in Arduino 1.0 or later). byte ip[] = { イーサネットシールドのIPアドレスをカンマ区切りで }; // Your Token to Tweet (get it from http://arduino-tweet.appspot.com/) Twitter twitter("〜あなたの取得したトークン〜"); // Message to post char msg[256]; #define LM35_IN 0 void setup() { delay(1000); Ethernet.begin(mac, ip); Serial.begin(9600); Udp.begin(localPort); // 最初の時刻リクエストを送信 sendNTPpacket(timeServer); lastSendPacketTime = millis(); } void loop() { if ( millis() - lastSendPacketTime > 13000 ){ // NTPサーバへ時刻リクエストを送信 sendNTPpacket(timeServer); // 時間を更新 lastSendPacketTime = millis(); } // NTPサーバからのパケット受信 if ( Udp.parsePacket() ) { // バッファに受信データを読み込む Udp.read(packetBuffer, NTP_PACKET_SIZE); // 時刻情報はパケットの40バイト目からはじまる4バイトのデータ unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); // NTPタイムスタンプは64ビットの符号無し固定小数点数(整数部32ビット、小数部32ビット) // 1900年1月1日0時との相対的な差を秒単位で表している // 小数部は切り捨てて、秒を求めている unsigned long secsSince1900 = highWord << 16 | lowWord; // Serial.print("Seconds since Jan 1 1900 = " ); // Serial.println(secsSince1900); // NTPタイムスタンプをUNIXタイムに変換する // UNITタイムは1970年1月1日0時からはじまる // 1900年から1970年の70年を秒で表すと2208988800秒になる const unsigned long seventyYears = 2208988800UL; // NTPタイムスタンプから70年分の秒を引くとUNIXタイムが得られる unsigned long epoch = secsSince1900 - seventyYears; Serial.print("Unix time = "); Serial.println(epoch); // Timeライブラリに時間を設定(UNIXタイム) // 日本標準時にあわせるために+9時間しておく setTime(epoch + (9 * 60 * 60)); int temp_in,ht,mt,st,i; float temp; char disp[20]=""; char disp1[20]=""; char h[20],m[20],s[20]; ht = ((epoch + 32400) % 86400L) / 3600; mt = ((epoch + 32400) % 3600) / 60; st = (epoch + 32400) % 60; sprintf(h,"%02d:",ht); sprintf(m,"%02d:",mt); sprintf(s,"%02d",st); temp_in = analogRead(LM35_IN); temp = (float)(temp_in) * (float)(0.0048) * (float)1000; itoa(temp,disp,10); strncpy(disp1,disp,strlen(disp)-1); strcat(disp1,".\0"); strcat(disp1,&disp[strlen(disp)-1]); strcpy(msg,"現在の室温 "); strcat(msg,disp1); strcat(msg," ℃ ("); strcat(msg,h); strcat(msg,m); strcat(msg,s); strcat(msg,") #Arduino"); Serial.println(msg); Serial.println("connecting ..."); if (twitter.post(msg)) { int status = twitter.wait(&Serial); if (status == 200) { Serial.println("OK."); } else { Serial.print("failed :code "); Serial.println(status); } } else { Serial.println("connection failed."); } Serial.print(temp, 1); Serial.print("\n"); } Serial.print("wait..."); Serial.print("\n"); // wait unsigned long waitTime = 60000UL*58UL; delay(waitTime); } // send an NTP request to the time server at the given address unsigned long sendNTPpacket(IPAddress & address) { // set all bytes in the buffer to 0 memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: // NTP requests are to port 123 Udp.beginPacket(address, 123); Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); }