kuroの覚え書き

96の個人的覚え書き

RTC(I2C接続)、SDカード(SPI接続)、アナログセンサーをESP32-WROOM-32Eにつなぐ

というわけで、ESP32が使えるようになったので、早速アナログセンサーのロガーを作ってみる。

関係がありそうなピンだけ書き出してみるとこんな感じ。
あとはポチポチとつないでプログラムを書く。

#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 5;
int sensorPin0 = 4;    // select the input pin for the potentiometer
int sensorValue0 = 0;  // variable to store the value coming from the sensor

RTC_DS1307 RTC;
int serialStat = 0;

/**************************************************************************/
void setup() {
  Serial.begin(9600);
  delay(10000);
  if(Serial)
  {
    serialStat = 1;
  }
  else
  {
    serialStat = 0;
  }

// SD card  
  if(serialStat == 1)
  {
    Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
    if (!SD.begin(chipSelect))
    {
      Serial.println("Card failed, or not present");
    }
    Serial.println("card initialized.");
  }
  else
  {
    SD.begin(chipSelect);
  }

// RTC
  Wire.begin();
  RTC.begin();
  delay(1000);
  if(serialStat == 1)
  {
    if(!RTC.begin())
    {
      Serial.println("RTC failed");
    }
  }
  /* Set RTC with PC initially */
  // RTC.adjust(DateTime(__DATE__, __TIME__));
  // RTC.adjust(DateTime(2022, 10, 29, 0, 13, 30));

}
/**************************************************************************/
void timeRead(void)
{
  DateTime now = RTC.now();
  
  File dataFile = SD.open("/datalog.txt", FILE_WRITE);
  dataFile.print(now.year(),DEC);
  dataFile.print("/");
  dataFile.print(now.month(),DEC);
  dataFile.print("/");
  dataFile.print(now.day(),DEC);
  dataFile.print("_");
  dataFile.print(now.hour(),DEC);
  dataFile.print(":");
  dataFile.print(now.minute(),DEC);
  dataFile.print(":");
  dataFile.print(now.second(),DEC); 
  dataFile.close();
  if(serialStat == 1)
  {
    Serial.print(now.year(),DEC);
    Serial.print("/"); 
    Serial.print(now.month(),DEC);
    Serial.print("/"); 
    Serial.print(now.day(),DEC);
    Serial.print("_"); 
    Serial.print(now.hour(),DEC);
    Serial.print(":"); 
    Serial.print(now.minute(),DEC);
    Serial.print(":"); 
    Serial.println(now.second(),DEC);      
  }
}
/**************************************************************************/
void sensorReadSw(void)
{
  sensorValue0 = analogRead(sensorPin0);

  File dataFile = SD.open("/datalog.txt", FILE_APPEND);
  dataFile.print(", ");
  dataFile.print(sensorValue0);
  dataFile.println("");
  dataFile.close();
  if(serialStat == 1)
  {
    Serial.print("value0: "); Serial.println(sensorValue0);
  }
}
/**************************************************************************/
void loop() {  
  timeRead();
  delay(10);
  sensorReadSw();
  delay(59500);
}

これでおよそ1分間隔で時間とアナログセンサーのvalueを読み取ってSDカードに記録し、シリアルが繋がっていれば通信もする。
あとはスリープを使えるようにしてやればかなり省エネにできるのではなかろうか。

I2Cはアドレスさえ違えば数珠つなぎできるので、いろんなセンサーをつなぐことができる。アナログは16系統もある。
0,2,12,15ピンは動作モードでなにか制約があるらしい。
WIFIを使うときはADC2の系統は使えないらしい。

そのほかタッチセンサーとか磁気センサーとかいろいろ内蔵されているらしいが、使う日は来るだろうか。

訂正
ESP32のSD読み書きのライブラリはどうやらオリジナルのATMEGA(AVR)用のものとは異なっているようでいくつかの書式や動作に違いがあるようだ。

まず最も肝心なのがATMEGAではファイルにディレクトリを何もつけなかったときはトップディレクトリにファイルを作る仕様になっていたが、ESP32
では明示的に/datafile.txtのようにしなければならない。これに気が付かず、一向にファイルができないので、SDカードモジュールや接続が悪いんじゃないかと悩んだ。
次にFILE_WRITEは常に上書きとなる。同じファイルに追記したければFILE_APPENDを使う必要がある。

Arduino_IDEのスケッチ例にあるこーどではFS.hをインクルードしてもうちょっと複雑なコードになっているが、単純には上のような書式でOK。