SPI温度センサADT7310を使う(6) SDカード併用 (9/30更新)

今回は16ビット ワンショット・モードによる温度測定に加えて、測定温度をSDカードへ記録する例を説明します。

pic130927-002

●SDカードI/FのSPIデータモード

ArduinoでSDカードI/FをSDライブラリで利用する際は、AVR内蔵のSPIハードウェアモジュールを利用します。

SDライブラリだけを使う場合はSPIはとくに意識する必要はありませんが、今回、ADT7310をSPIバスに並列に接続して、バスを共用するため、SPIとして少し意識する必要があります。

前述のように、SPIのデータモードには4種類ありますが、ADT7310とSDカードではデータモードが異なるため、アクセスの度にソフトウェアで切り替える必要があります。

ADT7310のデータモードは3、SDカードのデータモードは0です。すでに前回のプログラムでは、データモードを3に設定する処理が入っていますが、今回はSDカードにアクセスする際はデータモードを0に再設定するようにします。

●SDカードI/F WSN290

今回は、I/Fボードに筆者製作のWSN290ボードを使用しています。Arduinoのシールドとして販売されているSDカードI/FとカードI/F部分は互換性があります。

このボードは3.3Vのレギュレータとレベルコンバータを実装できるため、電源電圧は5V、信号も5V系のものを直結できます。

pic130927-004

WSN290 μSDカードボードの詳細はこちら→http://www.wsnak.com/kit/bbadp/index.htm

●SPI CS信号

SPIのCS信号はADT7310、SDカードでそれぞれ個別に必要です。それ以外の信号(MISO、MOSI、SCK)は両デバイスで共用(並列接続)します。

●接続図(9/30追加)

次に接続図を示します。

c7310sd

●サンプルスケッチ

今回は1秒毎にADT7310から温度値を読み出し、それをSDカードへ記録するという単純な処理プログラムを作成しました。

前回の16ビット、ワンショットモードの読み出し処理に手を加えて、SDカードへ書き込む処理を追加します。

処理を単純にしたため、記録停止、終了の操作ができませんので、起動後に測定、記録を開始し、規定回数に達したら測定、記録を停止するようにしました。記録が終わったSDカードはPCのカードリーダを使ってPCで読み込めます。SDカードのフォーマットはFAT16ですので、Windows PCで読めます。

スケッチを次に示します。


#include <SPI.h>
#include <SD.h>       // SDライブラリ

const int pinCS = 9;     // 温度センサCS D9
const int SD_cs = 10;    // SDカード CSポート番号

#define SPI_CS_ON   digitalWrite(pinCS, LOW)      // /cs = L
#define SPI_CS_OFF  digitalWrite(pinCS, HIGH)     // /cs = H

File myFile;        // ファイルハンドル
byte count = 0;

// 初期化
void setup(void) {
  byte reg;

  Serial.begin(19200);

  pinMode(pinCS, OUTPUT);   // spi cs
  pinMode(SD_cs, OUTPUT);    // SPI CS 出力設定
  SPI_CS_OFF;

  SPI.begin();
  SPI.setBitOrder(MSBFIRST);

  if (!SD.begin(SD_cs)) {    // SDオブジェクト初期化
    Serial.println("initialization failed!"); // 初期化失敗
  } else {
    Serial.println("initialization done.");   // 初期化成功
  }

  SPI.setDataMode(SPI_MODE3); // 負論理クロック 立ち上がりエッジサンプリング

  // ADT7310 ソフトウェアリセット 32bit
  SPI_CS_ON;
  SPI.transfer(0xFF);
  SPI.transfer(0xFF);
  SPI.transfer(0xFF);
  SPI.transfer(0xFF);
  SPI_CS_OFF;
  delay(100);
}

// メインループ
void loop(void) {
  uint16_t val;
  float tmp;
  int ival;

  SPI.setDataMode(SPI_MODE3);   // for ADT7310

  // モード設定 (スタートトリガ)
  SPI_CS_ON;
  SPI.transfer(0x08);       // コマンドバイト 0 0 001 000
  SPI.transfer(0xA0);       // コンフィギュレーションレジスタ 1 01 00000 16bit 1-shot
  SPI_CS_OFF;

  delay(240);               // 変換待ち

  // 温度読み出し
  SPI_CS_ON;
  SPI.transfer(0x50);       // コマンドバイト 0 1 010 000 (read tmp value)
  val = (uint16_t)SPI.transfer(0) << 8;   // AD変換値 上位
  val |= SPI.transfer(0);                 // AD変換値 下位
  SPI_CS_OFF;   // 摂氏温度換算
  ival = (long int)val;
  if(val & 0x8000) {         // 符号判定
    // 負数
    ival = ival - 65536;
  }
  tmp = (float)ival / 128.0;
  Serial.print(count);
  Serial.print(": ");
  Serial.println(tmp, 2);      // xx.xx

  SPI.setDataMode(SPI_MODE0);  // for SD card

  // ファイルを書き込みでオープン
  myFile = SD.open("temp.txt", FILE_WRITE);
  if (myFile) {
    myFile.print(count);
    myFile.print(": ");
    myFile.println(tmp, 2);   // xx.xx
    myFile.close();           // ファイルクローズ
    Serial.println("write done.");
  } else {     // ファイルオープンエラー
    Serial.println("error opening temp.txt");
  }
  count++;
  if(count > 10) {
    Serial.println("HALT");
    while(1) {};      // halt
  }
  delay(760);
}

26行目でSDカードオブジェクトを初期化してファイルをオープンしています。確認のため、オープンの可否をシリアルで送信しています。

32行目でSPIデータモードを切り替えて、35行目でADT7310をリセットしています。

50行目でSPIデータモードを3に再設定して、53行目でADT7310のワンショット測定のトリガをかけます。

58行目で240ms経過後、温度値を読出して、摂氏温度に換算しています。この部分は前回までの16ビット測定のプログラムと同じです。

71行目でカウンタ値と温度値をシリアルで送信しています。

76行目でデータモードを0に再設定して、80行目でSDカードへカウンタ値と温度値を書き込みます。

90行目でカウント値を調べて、一定値以上に達したらメッセージをシリアルで送信して処理を停止しさせます。

実行結果は次のようになります。(マイクロSDカードに記録されたテキストファイルをPCで読み込んだもの)

0: 0.00
1: 30.69
2: 30.67
3: 30.67
4: 30.62
5: 30.63
6: 30.62
7: 30.66
8: 30.66
9: 30.67
10: 30.67
HALT

冒頭に0.00とありますが、未変換の時に読み出しているようです。とりあえず、今回は無視してください。

コメントは受け付けていません。