Arduinoのスリープ制御

Arduinoのスリープ設定はどのようにするかを、私自身の例をあげて説明します。なぜそんな設定が必要なのか、不思議に思われるかもしれませんが、バッテリ駆動のプロジェクトでは、大きなメリットがあります。Arduinoをスリープにすることで、消費電流を抑え、Arduinoの動作時間を延長でき、バッテリ交換の頻度が少なくてすみます。また、マイコンや外部デバイスを常時動作させる必要のない多くのIoTプロジェクトでも非常に有効です。

最初のサンプルコードでは、2つの押ボタンと2つのLEDを使用して、ボードが動作中のときと割り込みボタンが押されたときを表示することにします。 ボードが動作しているときは、13番ピンに接続されたLEDが点滅します。12番ピンに接続されている押ボタンを押すと、Arduinoはスリープモードになり、13番ピンのLEDは点滅しなくなります。ボードを起動させるには、2番ピンに付いているボタンを押す必要があります。このボタンが押されると、10番ピンに接続されたLEDが点灯し、割り込みがかかったことを示します。

初期サンプルコード

//These are the two libraries that are needed 
#include <avr/interrupt.h>
#include <avr/sleep.h>

/* Here we set up our inputs and outputs.  LEDs connected to pins 10 and 13 and pushbuttons attached to 2 and 12 */
int ledPin = 13;
int sleepPin = 12;
int interruptPin = 10;
int wakePin = 2;
//sleepStatus is set up to keep track of the button input on pin 12.
int sleepStatus = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);        
  pinMode(interruptPin, OUTPUT);   
  pinMode(sleepPin, INPUT_PULLUP);  
  pinMode(wakePin, INPUT_PULLUP);

/* Next we have to enable an interrupt.  

The function is set up like this attachInterrupt(pin, function, triggerMode)  

PIN – can be either a 0 to call out digital pin 2 or 1 to call out digital pin 3.

FUNCTION – This is the function that will be run while in the interrupt

TRIGGER MODE – this will be the mode of the interrupt pin.  
It can be one the following:
	LOW – a low level trigger
	CHANGE – a change in level trigger
	RISING – a rising edge trigger
	FALLING – a falling edge trigger

The IDLE sleep mode is the only mode that can use CHANGE, RISING, and FALLING modes.*/


attachInterrupt(0, wakeUpNow, LOW);
}

void sleepNow()
{
//print message to serial monitor to let the user know board has gone to sleep
Serial.println("going to sleep");
//delay is added to allow user to get the full message on the serial monitor before going to sleep
delay(15);

//enables the sleep mode
sleep_enable();

// This is where we enable the interrupt, the reason it is done here is so that if the button is pressed accidently it doesn’t interrupt the running program.  
attachInterrupt(0,wakeUpNow, LOW);


/* The next line is where we choose the sleep mode we want to use for this code.  There are a few options to choose from, each with their own uses.  For more information on the sleep modes, please review the Atmega8 datasheet at [http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf](http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf)

The 5 different options for sleep modes, they are listed below from least power savings to most power savings:
	SLEEP_MODE_IDLE
	SLEEP_MODE_ADC
	SLEEP_MODE_PWR_SAVE
	SLEEP_MODE_STANDBY
	SLEEP_MODE_PWR_DOWN

For this sketch, we will be using the most power savings possible so we choose SLEEP_MODE_PWR_DOWN */

//sleep mode is set here
set_sleep_mode(SLEEP_MODE_PWR_DOWN);


//This is where the device is actually put to sleep
sleep_mode();

//Here is where the device begins to wake up.

//First thing that is done is to disable the sleep mode
sleep_disable();

//disables the interrupt on pin 2 so the wakeUpNow code will not be executed during normal run time
detachInterrupt(0);

//wait 1 second so the user can notice the LED signaling the interrupt
delay(1000);
digitalWrite (interruptPin, LOW);
}

void wakeUpNow()  //This is the code that runs when the interrupt button is pressed and interrupts are enabled
{
digitalWrite(interruptPin, HIGH);
}

void loop()
{
// turns the LED on
  digitalWrite(ledPin, HIGH);   
// waits for a second         
  delay(1000);         
// turns the LED off                  
  digitalWrite(ledPin, LOW); 
// waits for a second            
  delay(1000);          
//This is where the sleep pin is read.  It is only active when the LED is off.                 
  sleepStatus = digitalRead(sleepPin);   

//If button is pressed, device will run the sleepNow function                                         
  if (sleepStatus == LOW) {            
      sleepNow();                      
      }
}

初期コードの配線図

Scheme-It図面へのリンク: Arduino Uno

Arduinoを起動させるリアルタイムクロック(RTC)を追加

次に、ボタンでArduinoをスリープさせたり起動させたりするのではなく、RTCを追加してこれを制御することにします。 Adafruitの部品1528-1598-ND を使用します。このRTCを選んだのは、割り込みを内蔵しているからです。 もともとDS1307のブレークアウトボードを持っていたのですが、割り込みが入っていないことがすぐにわかったので、このプロジェクトでは使えませんでした。また、このプロジェクトを動かすためにダウンロードしたライブラリもいくつかあります。以下は、私が.zip形式のライブラリファイルをダウンロードしたサイトへのリンクです。

ライブラリへのリンク:

GitHub - PaulStoffregen/Time: Time library for Arduino - これはArduino用のタイムキーピングライブラリです。

GitHub - JChristensen/DS3232RTC: Arduino Library for Maxim Integrated DS3232 and DS3231 Real-Time Clocks - このライブラリはDS3231用で、Arduinoを起動するために必要なアラームが含まれています。

RTCを追加したコード


#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <DS3232RTC.h>      // https://github.com/JChristensen/DS3232RTC  this is the library for the DS2331 RTC


//RTC Module global variables

// Sets the wakeup interval in minutes
const int time_interval = 5; 
// LED connected to digital pin 13
int ledPin = 13;            
// active LOW, RTC will interrupt this pin momentarily to wake up
int wakePin = 2;            


void setup() {

  // set up the serial monitor
Serial.begin(9600);
//Set up the led pin as an output
  pinMode(ledPin, OUTPUT);
//Set pin d2 to input using the built-in pullup resistor
  pinMode(wakePin, INPUT_PULLUP); 
//turning LED on
  digitalWrite(ledPin, HIGH); 


// These next few lines of code initialize the alarms to known values, clear the flags, and clear the alarm interrupt flags
  RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
  RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
  RTC.alarmInterrupt(ALARM_1, false);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.squareWave(SQWAVE_NONE);

  /* Uncomment this section to set the time on the RTC.  Make sure to comment out after the first time
     it is set or you will continue to reset the time everytime the sketch is uploaded.  Also note that the clock is 24 hour format.

    tmElements_t tm;
   // the next few lines set the clock to the correct hour, minute, and second.  Remember 24 hour format so 4pm = hour 16 
    tm.Hour = 8;               
    tm.Minute = 19;
    tm.Second = 00;
   
   // set the correct date on the RTC
    tm.Day = 04;
    tm.Month = 5;
    tm.Year = 2019 - 1970; // in order to set the year correctly, just change the 2019 and leave the “- 1970” to get the correct offset
    
    RTC.write(tm);    // write the date and time to the RTC
          
  */

  
  time_t t; //create a temporary time variable so we can set the time and read the time from the RTC
  t = RTC.get(); //Gets the current time of the RTC
  RTC.setAlarm(ALM1_MATCH_MINUTES , 0, minute(t) + time_interval, 0, 0); // Setting alarm 1 to go off in the amount of minutes that we have the time interval constant set to 
  RTC.alarm(ALARM_1); // clear the alarm flag
  RTC.squareWave(SQWAVE_NONE); // configure the INT/SQW pin for "interrupt" operation (disable square wave output)
  RTC.alarmInterrupt(ALARM_1, true); // enable interrupt output for Alarm 1
}



void loop() {
  delay(5000);//wait 5 seconds before going to sleep. When in a project, we would it is best to make this short as possible
  sleepNow();  // run the sleepNow function

}


void sleepNow() {
  sleep_enable();//Enabling sleep mode
  attachInterrupt(0, wakeUpNow, LOW);//attaching a interrupt to pin d2
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep

  digitalWrite(ledPin, LOW); //turning LED off
  time_t t;// creates temporary time variable
  t = RTC.get(); //gets current time from RTC
  Serial.println("Sleep  Time: " + String(hour(t)) + ":" + String(minute(t)) + ":" + String(second(t))); //prints time stamp on serial monitor
  delay(1000); //wait one second to allow the LED to be turned off before going to sleep
  sleep_cpu();//heres where the Arduino is actually put to sleep
  

  Serial.println("just woke up!");//next line of code executed after the interrupt
  digitalWrite(ledPin, HIGH); //turns the LED on
  t = RTC.get();//get the new time from the RTC
  Serial.println("WakeUp Time: " + String(hour(t)) + ":" + String(minute(t)) + ":" + String(second(t))); //Prints time stamp
  
//Set New Alarm
  int alarmTime = 0; //temporary variable to store the new alarm time in minutes
  
//the next few lines are to roll the alarm over when it gets near the next hour
if (minute(t) <= (60-time_interval))
  {
    alarmTime = minute(t) + time_interval;
  }
  else
  {
    alarmTime = (minute(t) + time_interval) - 60;
  }

  RTC.setAlarm(ALM1_MATCH_MINUTES , 0, alarmTime, 0, 0); // set new alarm


// The next few lines of code I use for troubleshooting.  This way I can make sure the clock is waking up at the correct time 

 Serial.print("The next alarm will go off at: ");
    
//These lines are to print the correct hour that the next alarm will go off
if ((minute(t) <= 60-time_interval) && (hour(t) <= 22))
    {
      Serial.print(hour(t));
    }
    else if ((minute(t) >= 60-time_interval) && (hour(t) <= 22))
    {
      Serial.print(hour(t) + 1);
    }
    else
    {
      Serial.print(0);
    }
  
    Serial.print(":"); // print a colon symbol
    
//print the correct minute, including leading zero if less than 10
if (alarmTime <= 9)
    {
      Serial.print("0");
    }
    Serial.println(alarmTime);

  //Last thing we do is clear the alarm flag
  RTC.alarm(ALARM_1);

}

void wakeUpNow()  //This is the code that happens when the interrupt is activated
 { 
  Serial.println("Interrrupt Fired");//Print message to serial monitor
  sleep_disable();//Disable sleep mode
  detachInterrupt(0); //Removes the interrupt from pin 2;
}

RTCを追加した配線図


Scheme it Diagramへのリンク: Arduino Uno-RTC Sleep

温湿度センサと土壌水分センサを追加

その使い方の一例を紹介するため、スタンドアロンのプラント監視システムを作ることにしました。そのために、土壌水分プローブ(1568-1670-ND)、および温湿度センサ(1528-1172-ND)を使用します。このプログラムでは、気温と一緒に土壌の水分量もチェックします。このスケッチでは湿度を省くことにしましたが、数行のコードを元に戻すことで湿度のチェックも可能です。

この監視システムは、土壌の水分が低すぎないかどうかを確認するものです。もし一定の水分量以下になると、ポンプやソレノイドを作動させます。この例では、ポンプやソレノイドの代わりにLEDをインジケータとして使用しています。

このスケッチでは、MPL115A2ライブラリをインストールする必要があります。これは、Include Libraryの下のSketchメニューの下にあるManage Librariesボタンからインストールできます。また、zipファイルはこちらにあります: GitHub - adafruit/Adafruit_MPL115A2: Driver for the Adafruit MPL115A2 barometric pressure sensor breakout

温湿度センサと土壌水分センサを追加したコード


#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <DS3232RTC.h>      // https://github.com/JChristensen/DS3232RTC  this is the library for the DS2331 RTC
#include <Wire.h>
#include <Adafruit_MPL115A2.h>

Adafruit_MPL115A2 mpl115a2;

//RTC Module global variables

// Sets the wakeup interval in minutes
const int time_interval = 5; 
// LED connected to digital pin 13
int ledPin = 13;            
// active LOW, RTC will interrupt this pin momentarily to wake up
int wakePin = 2;            
// LED connected to digital pin 10
int pumpLED = 10;
//variable for storing the soil moisture value
int moistureVal = 0;
//input for the moisture sensor
int soilPin = A0;
//pin used to power the soil moisture sensor
int soilPower = 7;

void setup() {

// set up the serial monitor
  Serial.begin(9600);
//Set up the led pin as an output
  pinMode(ledPin, OUTPUT);
//Set pin d2 to input using the built-in pullup resistor
  pinMode(wakePin, INPUT_PULLUP); 
//turning LED on
  digitalWrite(ledPin, HIGH); 
//Set D7 as an OUTPUT
  pinMode(soilPower, OUTPUT);
// Set to LOW so no power is flowing through the sensor
  digitalWrite(soilPower, LOW);
//Set D10 as an output
  pinMode(pumpLED, OUTPUT);
//starting the temp/humidity sensor
  mpl115a2.begin();

// These next few lines of code initialize the alarms to known values, clear the flags, and clear the alarm interrupt flags
  RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
  RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
  RTC.alarm(ALARM_1);
  RTC.alarm(ALARM_2);
  RTC.alarmInterrupt(ALARM_1, false);
  RTC.alarmInterrupt(ALARM_2, false);
  RTC.squareWave(SQWAVE_NONE);

  /* Uncomment this section to set the time on the RTC.  Make sure to comment out after the first time
     it is set or you will continue to reset the time everytime the sketch is uploaded.  Also note that the clock is 24 hour format.

    tmElements_t tm;
   // the next few lines set the clock to the correct hour, minute, and second.  Remember 24 hour format so 4pm = hour 16 
    tm.Hour = 8;               
    tm.Minute = 19;
    tm.Second = 00;
   
   // set the correct date on the RTC
    tm.Day = 04;
    tm.Month = 5;
    tm.Year = 2019 - 1970; // in order to set the year correctly, just change the 2019 and leave the “- 1970” to get the correct offset
    
    RTC.write(tm);    // write the date and time to the RTC
          
  */

  
  time_t t; //create a temporary time variable so we can set the time and read the time from the RTC
  t = RTC.get(); //Gets the current time of the RTC
  RTC.setAlarm(ALM1_MATCH_MINUTES , 0, minute(t) + time_interval, 0, 0); // Setting alarm 1 to go off in the amount of minutes that we have the time interval constant set to 
  RTC.alarm(ALARM_1); // clear the alarm flag
  RTC.squareWave(SQWAVE_NONE); // configure the INT/SQW pin for "interrupt" operation (disable square wave output)
  RTC.alarmInterrupt(ALARM_1, true); // enable interrupt output for Alarm 1
}



void loop() {
  delay(5000);//wait 5 seconds before going to sleep. When in a project, we would it is best to make this short as possible
  sleepNow();  // run the sleepNow function

}


void sleepNow() {
  sleep_enable();//Enabling sleep mode
  attachInterrupt(0, wakeUpNow, LOW);//attaching a interrupt to pin d2
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep

  digitalWrite(ledPin, LOW); //turning LED off
  time_t t;// creates temporary time variable
  t = RTC.get(); //gets current time from RTC
  Serial.println("Sleep  Time: " + String(hour(t)) + ":" + String(minute(t)) + ":" + String(second(t))); //prints time stamp on serial monitor
  delay(1000); //wait one second to allow the LED to be turned off before going to sleep
  sleep_cpu();//heres where the Arduino is actually put to sleep

  Serial.println("just woke up!");//next line of code executed after the interrupt
  digitalWrite(ledPin, HIGH); //turns the LED on
  t = RTC.get();//get the new time from the RTC
  Serial.println("WakeUp Time: " + String(hour(t)) + ":" + String(minute(t)) + ":" + String(second(t))); //Prints time stamp

  getTempAndSoil(); //Run the TempAndSoil function
  
//Set New Alarm
  int alarmTime = 0; //temporary variable to store the new alarm time in minutes
  
//the next few lines are to roll the alarm over when it gets near the next hour
if (minute(t) <= (60-time_interval))
  {
    alarmTime = minute(t) + time_interval;
  }
  else
  {
    alarmTime = (minute(t) + time_interval) - 60;
  }

  RTC.setAlarm(ALM1_MATCH_MINUTES , 0, alarmTime, 0, 0); // set new alarm


// The next few lines of code I use for troubleshooting.  This way I can make sure the clock is waking up at the correct time 

 Serial.print("The next alarm will go off at: ");
    
//These lines are to print the correct hour that the next alarm will go off
if ((minute(t) <= 60-time_interval) && (hour(t) <= 22))
    {
      Serial.print(hour(t));
    }
    else if ((minute(t) >= 60-time_interval) && (hour(t) <= 22))
    {
      Serial.print(hour(t) + 1);
    }
    else
    {
      Serial.print(0);
    }
  
    Serial.print(":"); // print a colon symbol
    
//print the correct minute, including leading zero if less than 10
if (alarmTime <= 9)
    {
      Serial.print("0");
    }
    Serial.println(alarmTime);

  //Last thing we do is clear the alarm flag
  RTC.alarm(ALARM_1);

}

void wakeUpNow()  //This is the code that happens when the interrupt is activated
 { 
  Serial.println("Interrrupt Fired");//Print message to serial monitor
  sleep_disable();//Disable sleep mode
  detachInterrupt(0); //Removes the interrupt from pin 2;
}

void getTempAndSoil()
{
  float  temperatureC = 0, tempF = 0;  //set up float variable to store Celsius and Fahrenheit temp

  temperatureC = mpl115a2.getTemperature(); //get temperature from the sensor
  tempF = (temperatureC * 1.8) + 32;  //convert the temperature from Celsius to Fahrenheit.
  Serial.print("Temp (*F): "); Serial.print(tempF, 1); Serial.println(" *F");  //Print the temperature to the Serial Monitor
  Serial.print("Soil Moisture = ");  
  //get soil moisture value from the function below and print it
  Serial.println(readSoil());
  addWater();  // Run the add water function
}

int readSoil()
{

  digitalWrite(soilPower, HIGH);//turn the soil moisture sensor on
  delay(10);//wait 10 milliseconds
  moistureVal = analogRead(soilPin);//Read the value from sensor
  digitalWrite(soilPower, LOW);//turn the soil moisture sensor off
  return moistureVal;//send current moisture value
}

void addWater()
{
  if (moistureVal <= 100)  //If the soil moisture gets too low (The value will need to be set to accompany the soil that you are using)
  {

//This is where you could change the code to run a relay, or run a water pump to water your plant.  I just flashed a LED as an example to show that the plant would need to be watered.
    for (int num = 0; num <= 10; num++)
    {
      digitalWrite(pumpLED, HIGH);
      delay(1000);
      digitalWrite(pumpLED, LOW);
      delay(1000);
      Serial.print("PUMP ON");
      Serial.println(num);
    }
  }
}

RTCとセンサを追加した配線図

Scheme it Diagramへのリンク:Arduino Uno-RTC and sensors Sleep

部品表

カートへのリンク:Digi-Key - Fast Add





PankajShilarkar

みなさん、こんにちは。
2番ピンにIRセンサを接続し、再起動と同時に割り込みとして使おうとしています。
また、ポンプを動かすための他の機能も実行しようと思っています。
プッシュピンを、スリープの起動/解除を読み取るIRセンサに変えればいいのかなと、ガイドラインに沿って試してみましたが全くうまくいきません。
次のようにコードをアップデートしようとしました。

#include <avr/interrupt.h>
#include <avr/sleep.h>
#define IRsensor 2
#define DCwater_pump 8

/* Here we set up our inputs and outputs. LEDs connected to pins 10 and 13 and pushbuttons attached to 2 and 12 */

int pumpState = 0;
int lastPumpState = 0;
int sleepStatus = 0;
int interruptPin = 10;
int wakePin = 2;

void setup()
{

pinMode(IRsensor, INPUT);
pinMode(DCwater_pump, OUTPUT);
Serial.begin(9600);

/* Next we have to enable an interrupt.

The function is set up like this attachInterrupt(pin, function, triggerMode)

PIN – can be either a 0 to call out digital pin 2 or 1 to call out digital pin 3.

FUNCTION – This is the function that will be run while in the interrupt

TRIGGER MODE – this will be the mode of the interrupt pin.
It can be one the following:
LOW – a low level trigger
CHANGE – a change in level trigger
RISING – a rising edge trigger
FALLING – a falling edge trigger

The IDLE sleep mode is the only mode that can use CHANGE, RISING, and FALLING modes.*/

attachInterrupt(0, wakeUpNow, LOW);
}

void sleepNow()
{
//print message to serial monitor to let the user know board has gone to sleep
Serial.println(“going to sleep”);
//delay is added to allow user to get the full message on the serial monitor before going to sleep
delay(15);

//enables the sleep mode
sleep_enable();

// This is where we enable the interrupt, the reason it is done here is so that if the button is pressed accidently it doesn’t interrupt the running program.
attachInterrupt(0,wakeUpNow, LOW);

/* The next line is where we choose the sleep mode we want to use for this code. There are a few options to choose from, each with their own uses. For more information on the sleep modes, please review the Atmega8 datasheet at http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf

The 5 different options for sleep modes, they are listed below from least power savings to most power savings:
SLEEP_MODE_IDLE
SLEEP_MODE_ADC
SLEEP_MODE_PWR_SAVE
SLEEP_MODE_STANDBY
SLEEP_MODE_PWR_DOWN

For this sketch, we will be using the most power savings possible so we choose SLEEP_MODE_PWR_DOWN */

//sleep mode is set here
set_sleep_mode(SLEEP_MODE_PWR_DOWN);

//This is where the device is actually put to sleep
sleep_mode();

//Here is where the device begins to wake up.

//First thing that is done is to disable the sleep mode
sleep_disable();

//disables the interrupt on pin 2 so the wakeUpNow code will not be executed during normal run time
detachInterrupt(0);

//wait 1 second so the user can notice the LED signaling the interrupt
delay(1000);
digitalWrite (interruptPin, LOW);
}

void wakeUpNow() //This is the code that runs when the interrupt button is pressed and interrupts are enabled
{
digitalWrite(interruptPin, HIGH);
}

void loop()
{

pumpState = digitalRead(IRsensor);
if (pumpState != lastPumpState) {
if (pumpState == LOW) {
digitalWrite(DCwater_pump, HIGH);
Serial.println(“DC Pump is ON Now!!”);
delay(1000); //3000ms = 3 seconds, change this according to your needs.
digitalWrite(DCwater_pump, LOW);
Serial.println(“DC Pump is OFF Now!!”);
delay (500);
}

lastPumpState = pumpState;

}
//This is where the sleep pin is read. It is only active when the LED is off.
sleepStatus = digitalRead(IRsensor == LOW);

//If button is pressed, device will run the sleepNow function
if (sleepStatus == LOW) {
sleepNow();
}
}

もし、押ボタンを使わずにArduinoをスリープモードにしたい場合、どのようにすればよいか教えてください。

私がしたいことは、IRがローの状態が、たとえば1分間続くと、Arduinoをスリープさせ、IRが再びハイになるまでスリープを継続させることです。

初心者なので、これで動作するかどうか分かりません。サポートをお願いします。



Glenda_1324 DigiKey Employee

@DigiKey_Internal

どなたか、この件についてサポートできませんか?



Travis_Foss DigiKey Employee

PankajShilarkarさん、こんにちは。

お使いのIRセンサでは、作動時にハイかローか、どちらを出力しますか?

また、割り込みピンを起動用として使用している時に、そのピンを他の機能でも使用可能か確信が持てません。残念ながら、自宅で最初に使用していた機材が今、全て揃っていないので、試してみることもできません。

当初の設計では、ポンプを別電源から引き出していたと思います。12Vのポンプを使っていたので、すべて12Vのバッテリから動かしていたのだと思います。オリジナルのセットアップ写真があるかどうか分かりませんが少し探してみます。



JohnB

私はESP8266を使用しています。このチップをDS3231のSQWといっしょに使用した例はありますか?




オリジナル・ソース(英語)