できること

第22回 Arduinoでパーツやセンサを使ってみよう~SDカード編(その2)

P1180703

前回、micro SDカードスロットDIP化キットを利用してmicro SDカードを使う準備を行いました。今回は、micro SDカードに値を書き込み、温度センサ、光センサと組み合わせて利用する方法、さらに発展として土壌センサを利用して、デスクの上の観葉植物の状態を監視して水をあげる、ちょっと役に立つ?!デバイスを作ってみます。

今回の電子工作レシピ

完成までの時間目安:120分
必要なパーツ

イーサネットシールドでmicro SDカードと通信を同時に

micro SDカードを利用する方法はいくつかあります。電子工作の手間を省きたい方は、SDカードシールドやイーサネットシールド、ArduinoワイヤレスSDシールドなどにもSDカードソケットが搭載されているので、手軽にSDカードを利用することができます。

今回は、第6回記事でも登場したイーサネットシールドのmicro SDカードアダプタを使います。micro SDカードとLANケーブルによる通信の2つの機能を1つのシールドで実現できるので便利ですね。

写真1 イーサネットシールド

写真1 イーサネットシールド

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

図1 イーサネットシールドの利用可能pin

図1 イーサネットシールドの利用可能pin

イーサネットシールドでmicro SDカードを利用してみる

さっそくmicro SDカードを使ってみます。

写真2 イーサネットシールドに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カードを読み込むプログラム

Code-Example
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 シリアルモニターで確認

図2 シリアルモニターで確認

イーサネットシールドでもmicro SDカードの内容を読み込むことができました。

温度センサ、光センサと組み合わせて記録してみる

micro SDカードの準備ができたので、温度センサ、光センサの取得をした値を記録します。温度センサ、光センサの使い方を忘れてしまった方は第7回の記事をおさらいしてみてください。

回路は下記の通りです。

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

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

写真3 温度センサと光センサの回路

写真3 温度センサと光センサの回路

プログラムは、温度センサと光センサの数値をAnalogInputで入力し、その値をmicro SDカードに書き込みます。プログラム上の赤文字の部分が、実際にmicro SDカードに値を書き込む処理になります。ArduinoのSDカードライブラリでは、SD.open(“ファイル名”,”書き込みモード”)でSDカードの準備を行い、ファイルが開いた場合は、その内容をFile型の変数に渡してその後の書き込みや読み込みなどの処理を行います。ひととおり処理を行った後は、.close()でファイルを閉じるのを忘れないようにしましょう。

プログラム2:温度センサ、光センサの値をmicro SDカードに書き込むプログラム

Code-Example
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カードに書き込み

図4 温度センサと光センサの値をSDカードに書き込み

無事に書き込みできましたね。

観葉植物監視デバイスを作ってみる!

micro SDカードの読み込み、書き込みもできたので、いよいよ使えるデバイスを作って行きたいと思います。

観葉植物、部屋においてあると癒やされるのですが、毎日水をやるのはなかなか手間ですよね。筆者は、旅行や出張などで家をあけて、帰ってきたら枯れてしまっていたことが数知れず。そんな悩みを今回解決しちゃいましょう。

写真4 デスクの観葉植物

写真4 デスクの観葉植物

観葉植物監視デバイスの仕様を決める!

まずデバイスの仕様を決めましょう。水やりの負担を減らしたいので、土が乾いたことを土壌センサで検出して自動的に水をあげる仕様が良いですね。また、温度センサと光センサの値も同時に取得をして一緒にSDカードに記録をしたいと思います。花が咲く植物などは、積算温度で開花予測などができるので、SDカードにためたデータをもとにして、開花予測プログラムなども作ることができますね。簡単に今回の仕様をまとめると、

  • 土壌の乾きを感知して観葉植物に水をあげる
  • 土壌センサ、温度センサ、光センサの値をSDカードに記録する

この2点をメインにデバイスを作成していきます。

土壌センサを作成する

土の渇きを測るために、土壌センサを用意しましょう。既製品では、Arduino用土壌湿度センサなどがありますが、今回もっと手軽な方法を試してみます。Arduino用土壌湿度センサは2本の金属の抵抗値をセンサ値として入力できるようになっています。土壌の水分量が多いときは、電気が流れやすい状態なので抵抗値が低くなり、乾いた状態だと電機が流れにくいため抵抗値が高くなります。この仕組みがわかれば専用のセンサを利用しなくとも、くぎ2本で簡単に試すことができます。

※長期で運用する場合、鉄くぎだとさびて値が変わってきますのでその場合は、Arduino用土壌湿度センサや別の素材のくぎを利用するなどしてください

写真5 くぎ2本で土壌センサを代用

写真5 くぎ2本で土壌センサを代用

くぎ2本を導線につなぎます。回路は光センサなどと同じような回路になります。

図5 土壌センサ回路

図5 土壌センサ回路

写真6 土壌にセンサを設置

写真6 土壌にセンサを設置

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

図6 土壌センサの数値

図6 土壌センサの数値

水をあげると抵抗値が低くなるので、この数値を利用して、ある一定の抵抗値まで高くなる=土が乾いている → 水をあげるという処理にします。

水やり機構を実装する

水をあげる機構はさまざまな方法がありますが、安価に手軽にできる方法を考えてみました。100円均一にあるシャンプーボトルなどのプッシュノズルを利用して、サーボと組み合わせて、プッシュノズルを押して水を供給する方法です。

大量の水が必要な大きな植物の場合は、電池式の灯油ポンプを活用して、水やりを作成している方もいますので、植物のサイズに合わせていろいろ工夫してみてください。

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

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

写真8 サーボによる水やり機構

写真8 サーボによる水やり機構

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

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

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

図7 観葉植物監視デバイス回路

図7 観葉植物監視デバイス回路

プログラムに土壌センサの入力と、条件を満たしたときにサーボの動作を加えて動かします。今回は、「土の抵抗値が700以上(任意の値)の時5回プッシュする」としました。

プログラム3: 水やりプログラム

Code-Example
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カードの読み書きに加えて、これまで利用してきた各種センサを組み合わせてデバイスを作成してみました。次回からは、赤外線センサを利用してリモコンなどに使われる信号を解析し、家電などを操作するお手軽ホームコントローラーの作成に挑戦してみます!

アバター画像

電子工作や新しいデバイスをこよなく愛するエンジニア。日常生活のちょっとしたことを電子工作で作って試して、おもしろく過ごしたいと日々考えています。

RoboMaster 2019 参戦ファーストステップガイド