Arduino YUN Mini でIoT その2 温度測定

Arduino YUN Miniで温度を測る

 一番配線が少なくて済む1-wireのセンサDS18B20(現マキシム、旧ダラス)を使って温度を測ります。

 下記のWebサイトから、ライブラリをダウンロードします。

   Download Teensyduino, Version 1.31

 ダウンロードしたTeensyduinoInstall.exeをダブルクリックして、インストールを始めます。

 デスクトップに置いた最新バージョン1.7.11にインストールしようとしたら、Nextボタンが有効になりません。新しいバージョンにはインストールできないようです。

 C:\Program Files(x86)\Arduinoに入っていた古いバージョンに対してインストールしました。どのライブラリをインストールするかという選択画面では、全部にチェックが入っているので一度Noneをチェックして、OneWireだけにチェックをしました。インストール作業は数分かかります。

 インストールされたC:\Program Files(x86)\Arduino\hardware\teensy\avr\librariesを見ると、OneWireフォルダがあるので、1.7.11フォルダのlibrariesの中にコピーします。ライブラリの追加方法がわからなかったので、無理やり作業しています。

 1.7.11フォルダにあるarduino.exeをダブルクリックしてIDEをスタートします。

 ファイル・メニューから開くで、 デスクトップ-Arduino-1.71.11\hardware\libraries\OneWire\examples\DS18x20_Temperature¥DS18x20_Temperature.pdeを開きます。pdeはArduinoの古いプログラムの拡張子です。

#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
    Serial.begin(9600);
}

void loop(void) {
    byte i;
    byte present = 0;
    byte type_s;
    byte data[12];
    byte addr[8];
    float celsius, fahrenheit;

    if ( !ds.search(addr)) {
        Serial.println("No more addresses.");
        Serial.println();
        ds.reset_search();
        delay(250);
        return;
    }
    
    Serial.print("ROM =");
    for( i = 0; i < 8; i++) {
        Serial.write(' ');
        Serial.print(addr[i], HEX);
    }

    if (OneWire::crc8(addr, 7) != addr[7]) {
        Serial.println("CRC is not valid!");
    return;
    }
    Serial.println();

    // the first ROM byte indicates which chip
    switch (addr[0]) {
        case 0x10:
            Serial.println(" Chip = DS18S20"); // or old DS1820
            type_s = 1;
            break;
        case 0x28:
            Serial.println(" Chip = DS18B20");
            type_s = 0;
            break;
        case 0x22:
            Serial.println(" Chip = DS1822");
            type_s = 0;
            break;
        default:
            Serial.println("Device is not a DS18x20 family device.");
            return;
        }

ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end

delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();

// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
       // "count remain" gives full 12 bit resolution
       raw = (raw & 0xFFF0) + 12 - data[6];
    }
} else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print(" Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
}

 一度保存します。デスクトップ\ドキュメント\Aruduinoフォルダに保存されます。

 このプログラムをベースに、Arduino YUN Miniに対応した修正をします。

 ネットワークに対応するために、次のヘッダを追加します。

#include <Console.h>

 情報を保持する文字列を作成します。

String name;

 setup()の中に初期化と初期化メッセージを出力します。

Bridge.begin();
Console.begin();
while (!Console);
Console.println("! Start !");

 loop()の最初に、リターンを入れます。

  Console.println("");

 一番最後に、温度を表示します。

  Console.print(celsius);

 変更したプログラムです。

#include <OneWire.h>
#include <Console.h>
String name;
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary)

void setup() {
  Serial.begin(9600);
  Bridge.begin();
  Console.begin();
  while (!Console);
     Console.println("! Start !");
}

void loop() {
  Console.println("");
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
 float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    Serial.println(" No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  Serial.print("ROM =");
    for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return;
  }
// Serial.println();

// the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
        Serial.print(" Chip = DS18S20"); // or old DS1820
        type_s = 1;
        break;
    case 0x28:
        Serial.print(" / Chip = DS18B20");
        type_s = 0;
        break;
    case 0x22:
        Serial.print("  Chip = DS1822");
        type_s = 0;
        break;
    default:
        Serial.println("Device is not a DS18x20 family device.");
        return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1); // start conversion, with parasite power on at the end

  delay(1000); // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE); // Read Scratchpad

  Serial.print(" Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
  } else {
      byte cfg = (data[4] & 0x60);
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print(" Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
  Console.print(celsius);
}

温度センサの接続と実行

 プログラムには10番ピンを見ている記述が出てくるので、下のように接続しました。DS18B20はステンレスの筒に入っていて、3本のリード線が出ています。リード線の色はロットによって異なるようです。黒はGND、赤は電源へ、残った黄色は信号線と判断しました。信号線は、4.7kΩの抵抗で3.3Vへプルアップします。DS18B20の利用できる電源電圧は3~5.5Vです。

 Arduino IDEのツールから、ポート「linino at 192.168.111.100(Arduino Yun)」を選び、マイコンに書き込みます。書き込みが終了したら、IDE右上のシリアルモニタを開きます。温度が表示されています。

コラム 二つのArduino

 Arduino IDE1.7.11はArduino.orgの開発ツールです。Arduino.ccのバージョンは1.6.18です。1.6.18ではボードはArduino YUNだけしかサポートされていません。二つのツールではライブラリの管理が異なります。

 Arduino YUN Miniは1.7.11で開発しますが、Arduino.orgにはほとんど情報がありません。

 Arduino YUN Miniは、本文でも登場するlininoというキーワードで検索すると、linino.oneマイコン・ボードと同じようです。サポートはlinino.orgで行われています。

 Arduino YUN とArduino YUN Miniは、Wi-FiモジュールにLinux OSが入っています。OpenWRTというWi-Fiルータに搭載されているコンパクトなLinuxです。最新のArduino YUN Miniに対応した lininoIO-generic-linino-yun-mini-squashfs-sysupgrade.binをインストールすると、次の画面が出ます。