はかますたいる!きょろの技的雑記

井上恭輔(@kyoro353)の私的かつ技的な日記です。米国サンフランシスコで暮らすエンジニアです。

ネットワーク温度計

実は先週、H8マイコンを使ってネットワーク温度計を作りました。


f:id:kyoro353:20080804002753j:image


やっつけ実装ですが、一応、マイコンボード単体で動作します。
PC不要でスタンドアロンで動作するところがマイコンの素敵なところです。


3秒おきの室温を測定して、サーバにUDPでデータを送信します。
サーバでは受信プログラムが走っており、受け取ったデータをロギング、
現在の室温は無意味にケータイやPCのブラウザから確認できたりします。


で、1週間の間、データを測定していたりしました。
日中は32度くらいまで上がるんですね


f:id:kyoro353:20080804010512p:image

上の図は帰宅してからの平均的な室温変化をグラフにまとめたものです。
自分の行動(主にエアコン操作(笑))と不快指数の推移が手に取るようにわかりますね。


個人的には温度変化が見事に対数関数になっているのに感心しました。
自然法則ってちゃんと働いてるんだなぁと再認識。


最後に、H8とロギング用サーバのプログラムコードを晒しておきます。
H8はMES2用のC言語、サーバはC#で書いてFreeBSD7.0のmono上で動かしています。
内容はほぼ参考サイトのサンプルプログラムで、「やまねこのマイコン実験室」さんと「DOBON.NET」さんを参考にさせて頂きました。
どうもありがとうございました。


【やまねこのマイコン実験室】
http://wiki.livedoor.jp/yamamaya_com/d/A/D%a5%b3%a5%f3%a5%d0%a1%bc%a5%bf%a4%f2%bb%c8%a4%c3%a4%c6%a4%df%a4%eb

【DOBON.NET】
http://dobon.net/vb/dotnet/file/writefile.html


MES2用温度測定&UDP送信プログラム

#include <h8/reg3067.h>
#include <mes2.h>
#include <string.h>

#define VREF          5.0
#define NUM_SAMPLING  100

int main(int argc, char **argv) {
	volatile int w ;
    int a, b, i ;
    float v, t ;
   	int log_fd ; 
	int sock; //ソケット
	int lcd;//LCD
	int tr,ts;
	char str[128];
	struct sockaddr addr ;	
	
	///LCDの初期化
    lcd = open("lcd0", 0);
    if(lcd == -1){
    	printf("LCD Initialize error...\r");
    	exit(0);
    }
	
	//ソケット作成
	sock = udp_socket() ;
	if(lcd == -1){
		printf("Socket create error\r");
    	exit(0);
    }
	//サーバアドレス設定(適当に書き換えてね)
	addr.sin_addr = IPADDR( 192,168, * , *** );
	addr.sin_port = 2002 ;
	
	while(1){
		fprintf(lcd, "wati...") ;
	    printf("wait...^") ;
	    
	    /* サンプリング&平均化 */
	    b = 0 ;
	    for ( i = 0 ; i < NUM_SAMPLING ; i ++ ) {
	        w = ADCSR ;
	        ADCSR = 0x20 ;
	        while ( ! ( ADCSR & 0x80 ) ) {
	        }
	        a = ADDRAH << 2 ;
	        a |= ADDRAL >> 6 ;
	        b += a ;
	        sleep( 10 ) ;
	    }
	    /* 読み取り値 → 電圧 */
	    v = VREF / 1024 * ( (float)b / NUM_SAMPLING ) ;
	    /* 電圧 → 温度 */
	    t = 218.5 - v / 0.008 ;

		tr = (int)t;
		ts = (int)( t * 10 ) % 10 ;
	    fprintf(lcd, "%d.%01d゚C\r", tr , ts ) ;
	    printf("%d.%01d゚C\r",tr,ts) ;
	    
	    sprintf(str,"%d.%01d", tr , ts) ;
	    
	    sendto( sock, str, strlen(str) , &addr ) ;
	    
	}
	
	udp_free(sock);
	return 0;
}

ロギング用サーバプログラム

using System;
using System.Collections.Generic;
using System.Text;

namespace UDP_get
{
	class Program
	{
		static void Main(string[] args)
		{
			//文字コードを指定する
			System.Text.Encoding enc = System.Text.Encoding.ASCII;


			//バインドするローカルポート番号
			int localPort = 2002;

			//ローカルポート番号localPortにバインドする
			System.Net.Sockets.UdpClient udp;
			udp = new System.Net.Sockets.UdpClient(localPort);

			//データを受信する
			System.Net.IPEndPoint remoteEP = null;

			while (true)
			{
				byte[] rcvBytes = udp.Receive(ref remoteEP);
				string rcvMsg = enc.GetString(rcvBytes);
				Console.WriteLine("Recv:{0}", rcvMsg);
				Console.WriteLine("From:{0}/Port:{1}",remoteEP.Address, remoteEP.Port);
				//ログを書き出す
				string textFile = "log.txt";
				//書き込む文字列
				string str = rcvMsg + "\n";
				//textFileの末尾にstrを書き加える
				System.IO.File.AppendAllText(textFile, str, enc);
				System.IO.File.WriteAllText("--path-to-logfile--", str, enc);

			}

			//UDP接続を終了
			udp.Close();

			Console.ReadLine();
		}
	}
}

はらへった。寝よう。