Raspberry PIを買って以来、Linuxサーバとしてしか使用していないので、
電子工作っぽいことをしたくなり、I2Cの温度センサーで温度を記録するプログラムを作ることにしました。
とりあえず、安くて精度も高い(±0.25%,最大±0.5%)高精度I2C温度センサーMCP9808を
スイッチサイエンスで購入しました。
とりあえずMCP9808とピンをハンダ付けしておきます。

・VDDとRaspiの1番(3.3V)
・GNDとRaspiの6番(GND)
・SDAとRaspiの3番
・SCLとRaspiの5番
につなげます。

写真を見ると変な繋げ方になっていますが、単にメスメスのジャンパケーブルがなかっただけです。

ここからは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>
#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;
temp = t & 0x0FFF;
temp /= 16;
if(t & 0x1000){
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行き。
約一日間、記録を取った結果はこんな感じ。

急激に温度が下がってる部分は、エアコン付けたからです。
上がってる部分は、おそらく、TV録画のためPCが稼働しているからです。
参考:http://www.raspberrypi.org/forums/viewtopic.php?t=40831&p=540457
参考:http://openrtm.org/openrtm/ja/content/pirt-unit_with_i2cdevices