この製品はType A USB端子(この前まで全てのPCについていた、いわゆる普通のUSB端子)がついており、ここから5Vを引き出すこともできます。ちなみに太陽光パネル・鉛電池と合わせてもっていると、災害のときにスマホの充電に役に立ちます。2018年胆振東部地震のときにも、部屋にあったスペアを使いました。
ここでは例として、毎時00分に起き、10秒だけリレー(第11回参照)をONにし、またすぐにスリープに入るシステムをつくります。Arduino UNO版とArduino Pro Mini版の接続を示しますが、スケッチはどちらも同じです。なお、第7回の手順に沿って、RTCの時刻合わせは済んでいるものとします。
UNO版(電源はUSBからとるものとして省略しています。VinとGNDに電池をつないでもいいです)
Pro Mini版
#include <Enerlib.h>
#include <DS3232RTC.h>
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <avr/power.h>
Energy energy;
bool rtcint = true; // RTC interruptを作動させるフラグ
int RelayPin=9; // リレーに信号を送るピン
void setup(void)
{
setSyncProvider(RTC.get); // ここでRTCの時刻をもとにArduinoの時刻を合わせる
if(timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
delay(1000);
/* ----- Setting up RTC alarm ----- */
RTC.alarmInterrupt(1, false); //秒に関するアラームをクリア
RTC.alarmInterrupt(2, false); //分に関するアラームをクリア
RTC.oscStopped(true); //このへんはまあ気にしない
//RTC.alarm(2); //今回は2系統のアラームは使わない
RTC.alarm(1); //アラームのフラグをクリア
attachInterrupt(0, alcall, FALLING); //アラームが作動するとピンの電圧が下がる(FALLING)ので、その際は関数alcallを実行
//RTC.setAlarm(ALM2_EVERY_MINUTE , 0, 0, 0); //今回は使わないが、例えばこれでもよい
RTC.setAlarm(ALM1_MATCH_MINUTES, 0, 0, 0, 0);
//RTC.alarmInterrupt(2, true); //今回は2系統のアラームは使わない
RTC.alarmInterrupt(1, true); //アラームを有効化
/* ----- Preparation of relay operation ----- */
pinMode(RelayPin, OUTPUT);
digitalWrite(RelayPin, LOW);
}
void loop(void)
{
if (rtcint)
{
rtcint = false;
//RTC.alarm(2);
RTC.alarm(1); //次にもう一度アラームが効くように、ここで再びフラグをクリア
/* Turn on the relay */
digitalWrite(RelayPin, HIGH); //リレーをON
delay(10000); //10秒待つ
digitalWrite(RelayPin, LOW); //リレーをOFF
}
/* Enter sleep */
energy.PowerDown();
}
void alcall() {
rtcint = true;
}
注意が必要なのは、シリアル変換モジュールのRXとPro MiniのTX、シリアル-USB変換モジュールのTXとPro MiniのRX、というように、TXとRXは互い違いに接続することです。TはTransmit(送信)、RはReceive(受信)ですので。Arduino IDE(ソフトウェア)では、「ツール」の「ボード」から「Arduino Pro or Pro Mini」を選んで、さらに「プロセッサ:"Atmega328 (3.3V 8MHz)"」を選び、「シリアルポート」に現れている「COM X」(XはPCが自動的にアサインする数字)を選びます。あとの使い方はArduino UNOと同じです。ピンアサインもUNOと同じで、A4・A5がそれぞれI2C通信のSDA・SCLになります。2つだけちょっとおかしな位置にあるピンなので、わかりやすいです。
Pro Miniの電源関係はややわかりづらいので説明しておきます。シリアル-USB変換モジュールを介して先の写真のようにつないでいるとき、Vccに直接3.3Vちょうど(PCからの5V供給を、このモジュールが3.3Vに制御してくれています)が送られています。Vccはマイコンの動作電圧そのものになるので、ここに例えば4.2Vを送れば、全体が4.2Vで動くことになり、RTCやSDカードなどの周辺装置にもVcc端子を介して4.2Vがかかります。この程度なら問題はないですし、3.3Vモデルに5Vをかけても、少なくとも長い時間でなければ壊れたことはありません。一方、「RAW」という端子がありますが、ここに電圧をかけると、電圧レギュレータを介して3.3Vに調整されてからシステムに電圧がかかります。では常にこのRAW端子に電圧をかければよいということになりそうですが、3.3Vに減圧する以上、入力電圧は3.3Vよりある程度大きくなくてはなりません。3.3Vちょうどくらいの電圧をRAW端子にかけるとうまく動作しないことがあるので注意が必要です。エネループ3本(3.9~4.2V)をRAW端子・GND端子につないで動作させるのがちょうどよいようです(12Vまでかけてよいようなので、もちろん4本つないでも構いません。電圧レギュレータによるエネルギーロスが大きくなるだけです)。
さて、Pro Mini 3.3V 8MHzの省電力性能がよくわかりました。しかし、この電流はあくまで単体での消費電力であり、実際にはこれにRTCだのSDカードだのセンサーだのつけることになります。これらのモジュールは、それぞれおよそ1mAほど消費し、マイコンがスリープしても消費は続くので、4つつければスリープ時でも5~6mA消費することになってしまいます(2500mAhのエネループプロで約400時間、2~3週間程度)。少しでも省電力化するためにできることとしては、Arduinoそのものや、RTCなどモジュールについているLEDをもぎとることです。これにより、それぞれ0.5mAくらいずつ消費を減らすことができます(誰も見ていないロガーボックスの中で光り続けるほど無駄なことはない)。
データロガーには、データそのものとともに、データを取得した時刻を記録する機能が必要です。Arduinoには時計が内蔵されていますが、電源が切れるたびにリセットされます(1970年1月1日などにタイムスリップします)。これでは不便なので、時計(RTC: Real Time Clock)モジュールを取り付けます。このRTCモジュールにはコイン電池をつなぎ、常に給電させておきます。RTCモジュール自体は非常に省電力なので、コイン電池で数年持ちます。
#include <ds3232rtc.h> //http://github.com/JChristensen/DS3232RTC
#include <time.h> //http://www.arduino.cc/playground/Code/Time
#include <timelib.h>
#include <wire.h> //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
void setup(void)
{
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
/* ----- Initialisation of time ----- */
setTime(23, 8, 00, 9, 2, 2020); // set the system time in Arduino [Hour, Min, Sec, Day, Month, Year]
RTC.set(now()); // set the RTC time according to Arduino (Need to activate only when the RTC module has to be re-set)
if(timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
delay(1000);
}
void loop(void)
{
}
#include <SPI.h>
#include <SD.h>
#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>
const int chipSelect = 10; // Arduino UNOでは10、Arduino MEGAでは53
void setup(void)
{
/* ----- Setting up serial communication with PC ------ */
/* ここでUSBを介してPCとシリアル通信を始める。9600はシリアル通信のボーレート */
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
//何らかの問題があってシリアルポートに接続できないときは、このループにトラップされる
}
/* ----- Initialisation of SD card ------ */
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");
// don't do anything more:
return;
}
Serial.println("card initialized.");
/* ----- Setting time based on RTC ----- */
setSyncProvider(RTC.get); // ここでRTCの時刻をもとにArduinoの時刻を合わせる
if(timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
delay(1000);
}
void loop(void)
{
int ainput; //読み取ったbit数:intは整数
float vinput; //bit数を電圧に変換したもの:floatは浮動小数点数
/* データの読み取り */
ainput=analogRead(A0); //ピンA0から電圧をbitとして読む
vinput=5000.0*ainput/1024; //上記を電圧mVに変換
//ここで5000.0でなく5000とすると、整数としてvinputにキャストされてしまう)
//粗い値になったり、おかしな値になったりする
/* PCのシリアルモニタに表示 */
Serial.print(year());Serial.print("/");Serial.print(month());Serial.print("/");Serial.print(day());Serial.print(" ");
Serial.print(hour());Serial.print(":");Serial.print(minute());Serial.print(":");Serial.print(second());Serial.println("");
Serial.print(ainput);
Serial.println(" bit"); //" bit"と表示、printではなくprintlnとすることで改行する
Serial.print(vinput);
Serial.println(" mV"); //" mV"と表示、printではなくprintlnとすることで改行する
/* SDカードに書き込み */
File dataFile = SD.open("datalog.csv", FILE_WRITE);
if (dataFile)
{
dataFile.print(year());dataFile.print("/");dataFile.print(month());dataFile.print("/");dataFile.print(day());dataFile.print(" ");
dataFile.print(hour());dataFile.print(":");dataFile.print(minute());dataFile.print(":");dataFile.print(second());dataFile.print(" ");
dataFile.print(ainput);
dataFile.print(" bit, "); //" bit"と表示
dataFile.print(vinput);
dataFile.println(" mV"); //" mV"と表示、printではなくprintlnとすることで改行する
}
dataFile.close();
delay(2000); //2000ミリ秒=2秒の停止
}