OneWire interfaceの温度センサ DS18B20+ をArduinoで使ってみる
Arduino IDEには標準でOneWireのlibraryがないので、以下からDownloadした。
PJRC OneWire Library
偶然ここで紹介されているサンプルコードで、DS18S20という温度センサを使ってるので、
サンプルコードをそのまま流用しても問題なく動くのだけど、それでは面白くないので
コードを理解しつつ使いやすいものを作ってみる。
ちなみにDS18B20+のスペックはこちらにあった。
温度センサのdataピンを4.7kOhmでプルアップして、Arduinoのデジタルピンにつなぐ。
getTemperture(byte pin) という関数をつくり、温度センサが接続されているピンから温度を読み取れるようにしてみる。
関数は以下。
やることは、まずOneWireオブジェクトの定義、search()でOneWire deviceのアドレスの取得、そのDeviceに対して温度の変換コマンドをwrite(0x44)を使って投げる、温度の取得コマンドをwrite(0xBE)で投げる、最後にbufferにある温度をread()で読み取る。
サンプルコードでは温度をbyteの配列に格納して、bit shiftを使って温度を出しているけど、今回は共用体を使って、byteの配列にDS18B20のScratchpadのメモリマップと同じ構造体を使ってアクセスできるようにしてみた。 (crcとかも一応作ったけど、今回のコードでは使っていない)
ちなみに温度は2byteあるんだけど、8で割って0.5倍するとfloatの温度が得られるので(スペックより)、returnするところで計算している。
float getTemperature(byte pin) {
OneWire device(pin);
byte deviceAddr[12];
byte result;
union temperature{ -> 共用体を使って、byteの配列に構造体scratchPadからアクセスできるようにする
byte dataByte[8];
struct scratchPad { // Memory map of scratchpad. -> DS18B20+のScratchpadのメモリマップと同じ構造体
int tempRaw;
byte userByteH;
byte userByteL;
byte config;
byte reserved[3];
byte crc;
} scratchPad;
} temp_u;
device.search(deviceAddr); // Get one wire device address
device.reset();
device.select(deviceAddr);
device.write(0x44); // Issue convert temperature command
do {
result = device.read();
} while(!result); -> Convert Tコマンドが終わると1が返されるので、それまでwhileで待つ
device.reset();
device.select(deviceAddr);
device.write(0xBE); // Issue read scratchpad command
for(int i = 0; i < 8; i++) {
temp_u.dataByte[i] = device.read(); -> read()で1byteずつ読み取った温度はbyteの配列に入れられる
}
device.reset();
return (float)temp_u.scratchPad.tempRaw / 8.0 * 0.5; -> 共用体内の構造体のtempRawから温度を取得できる。
}
Arduino IDEには標準でOneWireのlibraryがないので、以下からDownloadした。
PJRC OneWire Library
偶然ここで紹介されているサンプルコードで、DS18S20という温度センサを使ってるので、
サンプルコードをそのまま流用しても問題なく動くのだけど、それでは面白くないので
コードを理解しつつ使いやすいものを作ってみる。
ちなみにDS18B20+のスペックはこちらにあった。
温度センサのdataピンを4.7kOhmでプルアップして、Arduinoのデジタルピンにつなぐ。
getTemperture(byte pin) という関数をつくり、温度センサが接続されているピンから温度を読み取れるようにしてみる。
関数は以下。
やることは、まずOneWireオブジェクトの定義、search()でOneWire deviceのアドレスの取得、そのDeviceに対して温度の変換コマンドをwrite(0x44)を使って投げる、温度の取得コマンドをwrite(0xBE)で投げる、最後にbufferにある温度をread()で読み取る。
サンプルコードでは温度をbyteの配列に格納して、bit shiftを使って温度を出しているけど、今回は共用体を使って、byteの配列にDS18B20のScratchpadのメモリマップと同じ構造体を使ってアクセスできるようにしてみた。 (crcとかも一応作ったけど、今回のコードでは使っていない)
ちなみに温度は2byteあるんだけど、8で割って0.5倍するとfloatの温度が得られるので(スペックより)、returnするところで計算している。
float getTemperature(byte pin) {
OneWire device(pin);
byte deviceAddr[12];
byte result;
union temperature{ -> 共用体を使って、byteの配列に構造体scratchPadからアクセスできるようにする
byte dataByte[8];
struct scratchPad { // Memory map of scratchpad. -> DS18B20+のScratchpadのメモリマップと同じ構造体
int tempRaw;
byte userByteH;
byte userByteL;
byte config;
byte reserved[3];
byte crc;
} scratchPad;
} temp_u;
device.search(deviceAddr); // Get one wire device address
device.reset();
device.select(deviceAddr);
device.write(0x44); // Issue convert temperature command
do {
result = device.read();
} while(!result); -> Convert Tコマンドが終わると1が返されるので、それまでwhileで待つ
device.reset();
device.select(deviceAddr);
device.write(0xBE); // Issue read scratchpad command
for(int i = 0; i < 8; i++) {
temp_u.dataByte[i] = device.read(); -> read()で1byteずつ読み取った温度はbyteの配列に入れられる
}
device.reset();
return (float)temp_u.scratchPad.tempRaw / 8.0 * 0.5; -> 共用体内の構造体のtempRawから温度を取得できる。
}