今回は、前回の熱電センサ2接続にさらにマイクロSDカードI/Fを並列接続する例を紹介します。
●SDカード併用制御の概要
先の2個並列制御の回路にSDカードI/Fを追加して同時に使用します。回路は図3のようにしています。#290 microSDカードボードは筆者が製作したマイクロSDカードのI/Fボードです。一般的なSDカードI/Fが付いたシールドも使用できます。
SDカードはリード/ライトを確認するために、10件記録したら記録した内容を一括で読み出し、シリアルで出力します。結果はArduino-IDEのシリアル・モニタで確認できます(CTRL+SHIFT+Mで起動)。
SDカードI/Fは前回述べたようにSPIのデータ・モードが「モード0」で、温度モジュールの「モード1」と異なります。そのため、SDカードのアクセス直前にモード0に切り替える処理、温度モジュールをアクセスする直前にモード1に切り替える処理が追加されています。
<サンプルスケッチ ReadTempW_SD.zip>
/* 熱電対コンバータ 温度読み出しサンプル copyright (c) 2013 T.N www.wsnak.com 13/01/14 新規 13/01/15 Wバージョン 13/01/16 SDカード併用テスト 13/01/16 SDカード併用テスト(トランジスタ オープンコレクタ接続対応) 熱電対センサモジュールSPI#1 MISO (D12) CLK (D13) CS (D8) 熱電対センサモジュールSPI#2 MISO (D12) CLK (D13) CS (D9) 注意 MISOは3ステート、オープンコレクタ出力にはなっていないので、 並列接続時はトランジスタのオープン・コレクタ回路などのバッファ を入れる必要あり(その場合はビット反転の必要あり) */ #define OPEN_COLLECTOR // センサモジュールのMISO出力(ビット反転) #include <SD.h> // SDライブラリ #include <SPI.h> #define SPI_CS_ON digitalWrite(SPI_cs, LOW) // /cs = L #define SPI_CS_OFF digitalWrite(SPI_cs, HIGH) // /cs = H #define SPI_CS2_ON digitalWrite(SPI_cs2, LOW) // /cs = L #define SPI_CS2_OFF digitalWrite(SPI_cs2, HIGH) // /cs = H #define SPI_SD_ON digitalWrite(SPI_SD, LOW) // /cs = L #define SPI_SD_OFF digitalWrite(SPI_SD, HIGH) // /cs = H const int SPI_cs = 8; // 熱電対センサモジュール CSポート番号 const int SPI_cs2 = 9; // 熱電対センサモジュール CSポート番号 const int SPI_SD = 10; // SDカード CSポート番号 byte spiDat[4]; char strBuf[16]; File myFile; // ファイルハンドル const char *fName = "test0002.txt"; // SDカード保存ファイル名 byte Count; // ------------------------- // 初期化 // ------------------------- void setup() { Serial.begin(19200); // シリアルポート初期化 pinMode(SPI_cs, OUTPUT); // センサモジュール#1 cs pinMode(SPI_cs2, OUTPUT); // センサモジュール#2 cs pinMode(SPI_SD, OUTPUT); // SDカード cs SPI_CS_OFF; SPI_CS2_OFF; SPI_SD_OFF; if (!SD.begin(SPI_SD)) { // SDオブジェクト初期化 Serial.println("initialization failed!"); // 初期化失敗 } else { Serial.println("initialization done."); // 初期化成功 Serial.println(fName); } SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV4); // SPIクロック分周比 SPI.setBitOrder(MSBFIRST); // 送信ビット順番 writeSd("test SD & TC"); Count = 0; // レコード書き込み回数 } // ------------------------- // メインループ // ------------------------- void loop() { word val1, val2; // 温度センサ1 val1 = getSpiData(0); getTemp(val1, strBuf); Serial.print(strBuf); delay(1); writeSd(strBuf); // SDカードへ文字列書き込み Serial.print(" "); // 温度センサ2 val2 = getSpiData(1); getTemp(val2, strBuf); Serial.println(strBuf); delay(1); writeSd(strBuf); // SDカードへ文字列書き込み Count++; if(Count == 10) { Serial.println("**** read SD 10 ****"); // 10回目の書き込みのときまとめて読み出す SPI.setDataMode(SPI_MODE0); // SPIデータモード切替 myFile = SD.open(fName); if (myFile) { Serial.println("---- read SD ----"); // 無くなるまで読み出しを繰り返す while (myFile.available()) { // 1行読み出してシリアル送信 Serial.write(myFile.read()); } // ファイルをクローズ myFile.close(); Serial.println("---- end ----"); } else { Serial.println("read failed"); } // while(1); // halt } delay(1000); // 1秒 } // // SDカードへ文字列書き込み // byte writeSd(char *str) { SPI.setDataMode(SPI_MODE0); // SPIデータモード切替 myFile = SD.open(fName, FILE_WRITE); if(myFile) { myFile.println(str); // 1行書き込み myFile.close(); } else { return false; } return true; } // // 温度モジュールからSPIでデータを読み出す // word getSpiData(byte num) { byte i; SPI.setDataMode(SPI_MODE1); // SPIデータモード切替 if(num == 0) { SPI_CS_ON; } else { SPI_CS2_ON; } for(i = 0; i < 2; i++) { // 2バイトだけ受信 #ifdef OPEN_COLLECTOR spiDat[i] = ~SPI.transfer(0); // ダミーデータ送信(1バイト受信)(ビット反転) #else spiDat[i] = SPI.transfer(0); // ダミーデータ送信(1バイト受信) #endif } SPI_CS_OFF; SPI_CS2_OFF; return ((word)spiDat[0] << 8) | (word)spiDat[1]; } // // SPIで読み出したデータを温度値の文字列に変換する // void getTemp(word spival16, char *str) { word val, vali; byte sign, vals; val = spival16 >> 2; if(val & 0x2000) { // 符号ビットをチェック // 負数(2の補数) val = ~val + 1; // 正数に戻す val &= 0x3FFF; // 数値抽出 sign = true; // 負数マーク } else { // 正数 sign = false; } // 整数部分と小数部分に分ける vali = val >> 2; // 整数部(上位11ビット) vals = (byte)val & 0x03; // 小数部(下位2ビット) vals = vals * 25; // 25=0.25*100 小数部を整数化 // 表示用文字列作成 if(sign) { // 負数 sprintf(str, "-%d.%-2d", vali, vals); } else { // 整数 sprintf(str, "+%d.%-2d", vali, vals); } }
この記事は2013年1~2月頃にCQ出版のブログへ掲載したものを少し修正したものです。
参考文献