前回、micro SDカードスロットDIP化キットを利用してmicro SDカードを使う準備を行いました。今回は、micro SDカードに値を書き込み、温度センサ、光センサと組み合わせて利用する方法、さらに発展として土壌センサを利用して、デスクの上の観葉植物の状態を監視して水をあげる、ちょっと役に立つ?!デバイスを作ってみます。
今回の電子工作レシピ
完成までの時間目安:120分
必要なパーツ
- Arduino本体(Arduino Mini Pro)http://www.switch-science.com/catalog/946/
- イーサネットシールド(Ethernet Shield R3) https://strawberry-linux.com/catalog/items?code=35009
- ブレッドボード http://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=3DBC-TCK4
- CDSセンサ(光センサ) http://akizukidenshi.com/catalog/g/gI-00110/
- 温度センサ(LM61) http://akizukidenshi.com/catalog/g/gI-02753/
- サーボモータ
- 抵抗器(220Ω)
- くぎ 2本
- プッシュ型ノズル
イーサネットシールドでmicro SDカードと通信を同時に
micro SDカードを利用する方法はいくつかあります。電子工作の手間を省きたい方は、SDカードシールドやイーサネットシールド、ArduinoワイヤレスSDシールドなどにもSDカードソケットが搭載されているので、手軽にSDカードを利用することができます。
今回は、第6回記事でも登場したイーサネットシールドのmicro SDカードアダプタを使います。micro SDカードとLANケーブルによる通信の2つの機能を1つのシールドで実現できるので便利ですね。

写真1 イーサネットシールド
イーサネットシールドの準備は、第6回の記事を参考にセットアップしてください。イーサネットシールドでは、下記図1のpinがSDカードおよびLAN利用のため利用することができません。それ以外のpinで電子回路を作成する必要があります。

図1 イーサネットシールドの利用可能pin
イーサネットシールドでmicro SDカードを利用してみる
さっそくmicro SDカードを使ってみます。

写真2 イーサネットシールドにmicro SDカードを装着
プログラムを見ていきましょう。イーサネットシールドでmicro SDカードを利用する場合、前回と少し違う点があります。micro SDデータ入力に利用する2番端子が、Arduino側の10番pinに接続されていましたが、イーサネットシールドでは4番pinになります。
表1 micro SDカードの端子仕様
micro SD 端子番号 |
機能 |
説明 |
---|---|---|
1 |
DAT2 |
使いません |
2 |
DAT3/CS |
チップセレクト |
3 |
CMD/DI |
データ入力 |
4 |
VDD |
電源 |
5 |
CLK |
シリアルクロック |
6 |
VSS |
グランド |
7 |
DAT0/D0 |
データ出力 |
8 |
DAT1 |
使いません |
プログラムは下記となります。
プログラム1 SDカードを読み込むプログラム
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include <SPI.h> #include <SD.h> Sd2Card card; SdVolume volume; SdFile root; const int chipSelect = 4; // イーサネットの場合は4pinになります void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print( "\nInitializing SD card..." ); pinMode(4, OUTPUT); // イーサネットの場合は4pinになります if (!card.init(SPI_HALF_SPEED, chipSelect)) { Serial.println( "initialization failed. Things to check:" ); Serial.println( "* is a card is inserted?" ); Serial.println( "* Is your wiring correct?" ); Serial.println( "* did you change the chipSelect pin to match your shield or module?" ); return ; } else { Serial.println( "Wiring is correct and a card is present." ); } Serial.print( "\nCard type: " ); switch (card.type()) { case SD_CARD_TYPE_SD1: Serial.println( "SD1" ); break ; case SD_CARD_TYPE_SD2: Serial.println( "SD2" ); break ; case SD_CARD_TYPE_SDHC: Serial.println( "SDHC" ); break ; default : Serial.println( "Unknown" ); } if (!volume.init(card)) { Serial.println( "Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card" ); return ; } uint32_t volumesize; Serial.print( "\nVolume type is FAT" ); Serial.println(volume.fatType(), DEC); Serial.println(); volumesize = volume.blocksPerCluster(); // clusters are collections of blocks volumesize *= volume.clusterCount(); // we'll have a lot of clusters volumesize *= 512; // SD card blocks are always 512 bytes Serial.print( "Volume size (bytes): " ); Serial.println(volumesize); Serial.print( "Volume size (Kbytes): " ); volumesize /= 1024; Serial.println(volumesize); Serial.print( "Volume size (Mbytes): " ); volumesize /= 1024; Serial.println(volumesize); Serial.println( "\nFiles found on the card (name, date and size in bytes): " ); root.openRoot(volume); root.ls(LS_R | LS_DATE | LS_SIZE); } void loop( void ) {} |

図2 シリアルモニターで確認
イーサネットシールドでもmicro SDカードの内容を読み込むことができました。
温度センサ、光センサと組み合わせて記録してみる
micro SDカードの準備ができたので、温度センサ、光センサの取得をした値を記録します。温度センサ、光センサの使い方を忘れてしまった方は第7回の記事をおさらいしてみてください。
回路は下記の通りです。

図3 温度センサと光センサの回路

写真3 温度センサと光センサの回路
プログラムは、温度センサと光センサの数値をAnalogInputで入力し、その値をmicro SDカードに書き込みます。プログラム上の赤文字の部分が、実際にmicro SDカードに値を書き込む処理になります。ArduinoのSDカードライブラリでは、SD.open(“ファイル名”,”書き込みモード”)でSDカードの準備を行い、ファイルが開いた場合は、その内容をFile型の変数に渡してその後の書き込みや読み込みなどの処理を行います。ひととおり処理を行った後は、.close()でファイルを閉じるのを忘れないようにしましょう。
プログラム2:温度センサ、光センサの値をmicro SDカードに書き込むプログラム
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include <SPI.h> #include <SD.h> const int chipSelect = 4; void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print( "Initializing SD card..." ); pinMode(4, OUTPUT); if (!SD.begin(chipSelect)) { Serial.println( "Card failed, or not present" ); return ; } Serial.println( "card initialized." ); } void loop() { String dataString = "" ; for ( int analogPin = 0; analogPin < 2; analogPin++) { int sensor = analogRead(analogPin); if (analogPin == 0) { dataString += String(sensor); dataString += "," ; } else if (analogPin == 1){ dataString += String(modTemp(sensor)); } } File dataFile = SD.open( "DATALOG.TXT" , FILE_WRITE); //ファイル名 if (dataFile) { //SDカードのファイルが無事開けたら(ない場合は新規作成) dataFile.println(dataString); //dataStringに入っている内容を書き込み dataFile.close(); //書き込み後ファイルを閉じる Serial.println(dataString); } else { Serial.println( "error opening datalog.txt" ); } } //温度センサーの値を摂氏度℃に変換 float modTemp( int analog_val){ float tv = map(analog_val,0,1023,0,5000); // センサー値を電圧に変換する float temp = map(tv,300,1600,-30,100) ; return temp; } |

図4 温度センサと光センサの値をSDカードに書き込み
無事に書き込みできましたね。
観葉植物監視デバイスを作ってみる!
micro SDカードの読み込み、書き込みもできたので、いよいよ使えるデバイスを作って行きたいと思います。
観葉植物、部屋においてあると癒やされるのですが、毎日水をやるのはなかなか手間ですよね。筆者は、旅行や出張などで家をあけて、帰ってきたら枯れてしまっていたことが数知れず。そんな悩みを今回解決しちゃいましょう。

写真4 デスクの観葉植物
観葉植物監視デバイスの仕様を決める!
まずデバイスの仕様を決めましょう。水やりの負担を減らしたいので、土が乾いたことを土壌センサで検出して自動的に水をあげる仕様が良いですね。また、温度センサと光センサの値も同時に取得をして一緒にSDカードに記録をしたいと思います。花が咲く植物などは、積算温度で開花予測などができるので、SDカードにためたデータをもとにして、開花予測プログラムなども作ることができますね。簡単に今回の仕様をまとめると、
- 土壌の乾きを感知して観葉植物に水をあげる
- 土壌センサ、温度センサ、光センサの値をSDカードに記録する
この2点をメインにデバイスを作成していきます。
土壌センサを作成する
土の渇きを測るために、土壌センサを用意しましょう。既製品では、Arduino用土壌湿度センサなどがありますが、今回もっと手軽な方法を試してみます。Arduino用土壌湿度センサは2本の金属の抵抗値をセンサ値として入力できるようになっています。土壌の水分量が多いときは、電気が流れやすい状態なので抵抗値が低くなり、乾いた状態だと電機が流れにくいため抵抗値が高くなります。この仕組みがわかれば専用のセンサを利用しなくとも、くぎ2本で簡単に試すことができます。
※長期で運用する場合、鉄くぎだとさびて値が変わってきますのでその場合は、Arduino用土壌湿度センサや別の素材のくぎを利用するなどしてください

写真5 くぎ2本で土壌センサを代用
くぎ2本を導線につなぎます。回路は光センサなどと同じような回路になります。

図5 土壌センサ回路

写真6 土壌にセンサを設置
まずこの状態で、Analogピン2番にさした土壌センサの値をAnalogInputでそのまま読み込んでみます。途中水を鉢に加えてみると、900~1000だった数値が600台になっていることがわかりますね。

図6 土壌センサの数値
水をあげると抵抗値が低くなるので、この数値を利用して、ある一定の抵抗値まで高くなる=土が乾いている → 水をあげるという処理にします。
水やり機構を実装する
水をあげる機構はさまざまな方法がありますが、安価に手軽にできる方法を考えてみました。100円均一にあるシャンプーボトルなどのプッシュノズルを利用して、サーボと組み合わせて、プッシュノズルを押して水を供給する方法です。
大量の水が必要な大きな植物の場合は、電池式の灯油ポンプを活用して、水やりを作成している方もいますので、植物のサイズに合わせていろいろ工夫してみてください。

写真7 100円均一にあるプッシュ型のボトル、プッシュノズルを使います

写真8 サーボによる水やり機構
3種類ほどシャンプーボトルを買って試したのですが、今回利用したサーボでは力が弱いため、2種類はシャンプーノズルのばねの力にサーボが負けて押すことができませんでした。弱い場合はサーボの電源を別の電池で供給するなどの工夫が必要ですね。水やり機構の作成に苦労しつつも何とか完成です。

写真9 観葉植物監視デバイスが完成

図7 観葉植物監視デバイス回路
プログラムに土壌センサの入力と、条件を満たしたときにサーボの動作を加えて動かします。今回は、「土の抵抗値が700以上(任意の値)の時5回プッシュする」としました。
プログラム3: 水やりプログラム
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | #include <SPI.h> #include <SD.h> #include <Servo.h> const int chipSelect = 4; Servo myservo; int pos = 0; int sensorValue = 0; // variable to store the value coming from the sensor int sensorPin = A0; void setup() { myservo.attach( 9 ); Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print( "Initializing SD card..." ); pinMode(4, OUTPUT); if (!SD.begin(chipSelect)) { Serial.println( "Card failed, or not present" ); return ; } Serial.println( "card initialized." ); } void loop() { String dataString = "" ; for ( int analogPin = 0; analogPin < 3; analogPin++) { int sensor = analogRead(analogPin); if (analogPin == 0) { //光センサの値 dataString += "Light:"; dataString += String(sensor); dataString += ",Temp:"; } else if(analogPin == 1){ //温度センサの値 dataString += String(modTemp(sensor)); dataString += ",Ground:"; } else if(analogPin == 2){ //土壌センサの値 sensorValue = analogRead(sensorPin); dataString += String(sensorValue); //土の抵抗値が700以上(任意の値)の時5回プッシュする if(sensorValue > 700){ for ( int u=0;u<5;u++){ pos = 180; myservo.write( pos ); delay(1500); pos = 0; myservo.write( pos ); delay(1500); pos = 180; myservo.write( pos ); } } } } File dataFile = SD.open( "datalog.txt" , FILE_WRITE); if (dataFile) { dataFile.println(dataString); dataFile.close(); Serial.println(dataString); } else { Serial.println( "error opening datalog.txt" ); } } //温度センサーの値を摂氏度℃に変換 float modTemp( int analog_val){ float tv = map(analog_val,0,1023,0,5000); // センサー値を電圧に変換する float temp = map(tv,300,1600,-30,100) ; return temp; } |
まとめ
今回はmicro SDカードの読み書きに加えて、これまで利用してきた各種センサを組み合わせてデバイスを作成してみました。次回からは、赤外線センサを利用してリモコンなどに使われる信号を解析し、家電などを操作するお手軽ホームコントローラーの作成に挑戦してみます!