braintag

公開してしまう備忘録

Raspberry PI 高精度I2C温度センサーMCP9808で温度を記録

Raspberry PIを買って以来、Linuxサーバとしてしか使用していないので、
電子工作っぽいことをしたくなり、I2Cの温度センサーで温度を記録するプログラムを作ることにしました。

Raspberry Pi Model B+ (Plus)

Raspberry Pi Model B+ (Plus)


とりあえず、安くて精度も高い(±0.25%,最大±0.5%)高精度I2C温度センサーMCP9808を
スイッチサイエンスで購入しました。

とりあえずMCP9808とピンをハンダ付けしておきます。
f:id:kiwamaru:20140813103859j:plain

・VDDとRaspiの1番(3.3V)
GNDとRaspiの6番(GND)
・SDAとRaspiの3番
・SCLとRaspiの5番
につなげます。
f:id:kiwamaru:20140813103750j:plain
写真を見ると変な繋げ方になっていますが、単にメスメスのジャンパケーブルがなかっただけです。

ここからはRaspberry PIのコンソール上での作業

/etc/modulesを編集し、以下を追加

i2c-bcm2708
i2c-dev

/etc/modprobe.d/raspi-blacklist.confを編集し、i2c-bcm2708をコメントアウト

# blacklist spi and i2c by default (many users don't need them)

blacklist spi-bcm2708
#blacklist i2c-bcm2708

ここで一旦再起動。

sudo shutdown -r now


i2c-toolsと開発用のライブラリのインストール

#sudo apt-get install i2c-tools libi2c-dev

MCP9808のアドレスの確認

sudo i2cdetect -y 1
pi@raspberrypi ‾ $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

MCP9808のデータシートを見る
http://www.farnell.com/datasheets/1522173.pdf

5.1 Registersを見ると、温度を取得するには、

0101 = Temperature register (TA)

と書いてあるので、0x05(0b0101)を書き込めばいいことがわかります。

i2cgetを使用した簡単な温度の取得

pi@raspberrypi ‾ $ sudo /usr/sbin/i2cget -y 1 0x18 0x05 w
0xe4c1 <---結果

この結果をバイトスワップして、0x0FFFでマスクして、16で割ると、温度(摂氏)が出ます。(マイナスの場合はMSBの4bit目が符号)

上の結果、0xe4c1の場合、
1.バイトスワップ 0xc1e4
2.0x0FFFでマスク 0x01e4
3.16で割る 0x01e4 / 16 = 30℃

C言語で書くとこうです。ちなみに、sudoで実行しないと読めません。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include <linux/i2c-dev.h> // I2C用インクルード
#include <fcntl.h>
#include <sys/ioctl.h>

int main(int argc, char **argv)
{
    char *i2cFileName = "/dev/i2c-1";
    const unsigned char i2cAddress = 0x18;
    const __u8 t_reg = 0x05;
    int i2c_fd;

    if((i2c_fd = open(i2cFileName,O_RDWR)) < 0){
        fprintf(stderr,"Faild to open i2c port¥n");
        return 1;
    }
    if (ioctl(i2c_fd, I2C_SLAVE,i2cAddress) < 0) {
        fprintf(stderr,"Unable to get bus access to talk to slave¥n");
        return 1;
    }
    __s32 res = i2c_smbus_read_word_data(i2c_fd,t_reg);
    if(res < 0){
        fprintf(stderr,"Error i2c_smbus_read_word_data()¥n");
        return 1;
    }
    float temp;
    {
        __u16 t = res << 8 | res >> 8;//byte swap
        temp = t & 0x0FFF;      //mask
        temp /= 16;
        if(t & 0x1000){                 //sign or unsigned
            temp -= 256;
    	}
	}

    time_t t;
    time(&t);
    struct tm *m;
    m = localtime(&t);

    printf("%d/%d/%d-%d:%d:%d,%.2f¥n",m->tm_year+1900,m->tm_mon+1,m->tm_mday,m->tm_hour,m->tm_min,m->tm_sec,temp);

    return 0;
}

cronで10分毎に記録する

*/10 * * * * cd /home/pi/templogger;sudo ./templogger 2>&1 1>>temp.csv | logger -t templogger

※ログのローテーションとか考えてないです。エラーはsyslog行き。

約一日間、記録を取った結果はこんな感じ。
f:id:kiwamaru:20140819135452p:plain
急激に温度が下がってる部分は、エアコン付けたからです。
上がってる部分は、おそらく、TV録画のためPCが稼働しているからです。

参考:http://www.raspberrypi.org/forums/viewtopic.php?t=40831&p=540457
参考:http://openrtm.org/openrtm/ja/content/pirt-unit_with_i2cdevices