Arduinoを使って距離と時間データをSDカードに記録しました

超音波距離センサとRTCモジュールとSDモジュールを同時に使うの?

  • Arduino UNO R3に、超音波距離センサ、RTC(実時間)モジュール、SDモジュールを接続し、距離データと時間データをSDカードに記録します。また検出した距離に応じてLEDを光らせます。

必要な部品は?

RTC(実時間)モジュール(DS1307)1個
SDモジュール (microSDカードスロット)1個
超音波センサモジュール (HC-SR04)1個
LED 赤色1個
LED 緑色1個
抵抗 (220Ω)2個
抵抗 (1KΩ)1個
タクトスイッチ1個
Arduino UNO R31個
  • 部品をブレッドボードで接続しました

どのような動作をするの?

  • 距離が50cm以内に反射物を検出すると、緑のLEDを点灯します。(5秒以上検出しないと消灯します。)
  • 緑のLEDが点灯状態で50cm以内の反射物を10回以上検出しすると赤のLEDを点灯します。
  • RESET SWを押すと、緑と赤のLEDを消灯します。(赤のLEDはRESET SWで消灯できます。)
  • 検出の状態を1秒間隔でSDカードに記録します。
  • 検出距離を50cmとしていますが、検出距離は変更可能です。
  • SDカードには下記のデータをCSVファイルで記録します。

どのような使い方があるの?

  • 動物を捕獲する檻の奥にこのセンサを設置して、赤のLEDが光るタイミングで檻を閉じて動物を捕まえるとかの利用があるかもしれません。
  • 檻の奥に距離センサを置いて赤のLEDが点灯すると入り口の戸を落とすイメージです。

スケッチのコードは?

//www.arduinomakesiteasy.com
//2022.5.4
//
// 1) Elegoo 実時間モジュール DS1307
// 2) Elegoo 超音波距離センサ HC-SR04
// 3) 秋田通商 SDモジュール
//

//ライブラリインクルード
#include <Wire.h>
#include <DS3231.h>
#include "SR04.h"
#include "SPI.h" 
#include "SD.h"

//SDカード設定
File myFile;                //クラス指定
const int chipSelect = 10;  //チップセレクトピン指定

//超音波距離センサ設定
#define TRIG_PIN 7
#define ECHO_PIN 6
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
int USdistance;

//実時間モジュール設定
DS3231 clock;
RTCDateTime dt;

//LED設定
#define DetectLED 3
#define FoundLED 5
const int DetectDistance=50;

//RESET
#define ResetSW 2

//一般変数
int i,j,k,val;

//ファイル作成・更新時のタイムスタンプを記録するスケッチ------------------------------
char timestamp[30];

// call back for file timestamps
void dateTime(uint16_t *date, uint16_t *time) {
 sprintf(timestamp, "%02d:%02d:%02d %2d/%2d/%2d \n",dt.hour,dt.minute,dt.second,dt.month,dt.day,dt.year-2000);
 // return date using FAT_DATE macro to format fields
 *date = FAT_DATE(dt.year,dt.month,dt.day);
 // return time using FAT_TIME macro to format fields
 *time = FAT_TIME(dt.hour,dt.minute,dt.second);
}
//------------------------------------------------------------------------------

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

  //実時間モジュールの初期化
  Serial.println("Initialize RTC module");
  // Initialize DS3231
  clock.begin();
 
  //スケッチのコンパイル時の時刻をRTCモジュールに書き込む
  //1回目はこのままコンパイル実行する、
  //2回目にコメントアウトして再度コンパイル実行する
  clock.setDateTime(__DATE__, __TIME__);    

  //SDカードの初期化
  Serial.println("Initializing SD card...");
  
  if (!SD.begin(chipSelect)) {
    Serial.println("Initialization failed or does not exist");
    while (1);
  }
  Serial.println("Initialization done.");
  Serial.println();

  //ファイル作成・更新時のタイムスタンプを記録するスケッチ------------------------------
  SdFile::dateTimeCallback(dateTime);
  sprintf(timestamp, "%02d:%02d:%02d %2d/%2d/%2d \n",dt.hour,dt.minute,dt.second,dt.month,dt.day,dt.year-2000);
  //------------------------------------------------------------------------------

  //LED初期化
  pinMode(DetectLED, OUTPUT);
  pinMode(FoundLED, OUTPUT);
  digitalWrite(DetectLED, LOW);
  digitalWrite(FoundLED, LOW);

  //ResetSW初期化
  pinMode(ResetSW, INPUT);

  //一般変数の初期化
  i=0;
  j=0;
  k=0;  
  val=0;
  
  delay(1000);  
  
  //シリアルログの最初の行に表示項目を表示する
  Serial.print("Year,");
  Serial.print("Month,");
  Serial.print("Day,");
  Serial.print("Hour,");
  Serial.print("Minuts,");
  Serial.print("Second,");
  Serial.print("Distance(cm),");  
  Serial.print("Detect Flag#1,");  
  Serial.println("Detect Flag#2");  

  //ログデータの最初の行に記録項目を記入する
  myFile = SD.open("DATA_LOG.csv", FILE_WRITE); //SDカードをオープンする 
  myFile.print("Year,");
  myFile.print("Month,");
  myFile.print("Day,");
  myFile.print("Hour,");
  myFile.print("Minuts,");
  myFile.print("Second,");
  myFile.print("Distance(cm),");   
  myFile.print("Detect Flag#1,");   
  myFile.println("Detect Flag#2");     
  myFile.close(); 	//SDカードをクローズする   
}

void loop()
{
  //シリアルログの表示
  dt = clock.getDateTime();
  Serial.print(dt.year);   Serial.print(",");
  Serial.print(dt.month);  Serial.print(",");
  Serial.print(dt.day);    Serial.print(",");
  Serial.print(dt.hour);   Serial.print(",");
  Serial.print(dt.minute); Serial.print(",");
  Serial.print(dt.second); Serial.print(",");
    
  USdistance=sr04.Distance();
  Serial.print(USdistance); Serial.print(",");  
  Serial.print(i); Serial.print(",");  
  Serial.println(k);  
   
  //SDカードへの書き込み
  myFile = SD.open("DATA_LOG.csv", FILE_WRITE); 

  myFile.print(dt.year);   myFile.print(",");
  myFile.print(dt.month);  myFile.print(",");
  myFile.print(dt.day);    myFile.print(",");
  myFile.print(dt.hour);   myFile.print(",");
  myFile.print(dt.minute); myFile.print(",");
  myFile.print(dt.second); myFile.print(",");
  myFile.print(USdistance);myFile.print(","); 
  myFile.print(i); myFile.print(",");
  myFile.println(k);

  myFile.close();

  //検出距離がDetectDistanceより小さな場合の処理
  if (USdistance <DetectDistance && k==0) {i+=1; digitalWrite(DetectLED, HIGH);}
  if (i >0 && k==0) {j+=1;}
  if (j-i>5 && k==0) { i=0; j=0; digitalWrite(DetectLED, LOW);}
  if (i>10 && k==0) { k=1; digitalWrite(FoundLED, HIGH);}

  //RsetSWが押された場合
  val=digitalRead(ResetSW);
  if (val==0) {
    i=0;
    j=0;
    k=0;
    digitalWrite(DetectLED, LOW);
    digitalWrite(FoundLED, LOW);
    }    
 
  delay(1000);  // 1秒間待つ 
}

回路図は?

  • 部品点数が多いのでFritzingで配線図を書くと見難くなるので見づらくなるのでKiCADで回路図を書きました。
関連する記事は?

ご質問、誤植の指摘などありましたら。「問い合わせ 」のページからお願いします。