Bonjour à tous,
Et bonne année !
J'ai donc testé 2 solutions :
- Solution basée sur les librairies RocketScream_LowPowerAVRZero.h et RocketScream_RTCAVRZero.h :
- mise en veille de l'arduino pendant 15 minutes entre chaque contrôle de luminosité
- désactivation de tous les pins non utilisés
- Solution basée sur l'exemple proposée par OldSurferDude.
- mise en veille de l'arduino pendant 15 minutes par cycles de 8 secondes entre chaque contrôle de luminosité
Je pense en fait que la solution 1 s'appuie sur les mêmes fonctionnalités de base que la 2 pour la partie mise en veille.
Je mets les codes plus bas.
Avant cela, j'ai refait convenablement (avec un multimètre, au lieu de me fier à la conso affichée par ma source de tension) les mesures de consommation. En effet, je ne comprenais pas pourquoi mon panneau ne suffisait pas malgré toutes les marges prises pour son dimensionnement.
Résultat :
- Lorsque le servo est en mouvement : 60mA
- Servo au "repos" : 45 mA
Je pense que cette énorme conso par rapport à d'autres retours d'expérience est due au servo. En effet, même au repos, il compense le moindre mouvement...
Voici les consommations mesurées :
- Solution 1
- Servo en mouvement : 50 mA
- Servo au repos et mise en veille pour 15 minutes : 25 mA
- Solution 2
- Servo en mouvement : 60 mA
- Servo au repos et mise en veille pour 15 minutes : 35 mA
Mon interprétation :
- La désactivation des pins fait gagner 10 mA
- La mise en veille fait gagner 10 mA
- Ma conso élevée est due à l'utilisation d'une servomoteur, et je ne reviendrai pas dessus, donc je dois faire avec.
Les conséquences :
- positif : ma batterie tient maintenant la charge et sa tension augmente chaque jour malgré le temps pas terrible
- négatif : la mise en veille de l'arduino entraîne l'arrêt de la commande du servomoteur, et le moindre coup de vent referme ma porte... Je ne sais pas s'il est possible de mettre en veille tout en maintenant l'état d'une broche en sortie, mais ça m'étonnerait... S'il y a une solution (peut-être hardware ?), je suis intéressé
- je vais donc tester en mettant simplement en place la désactivation des pins inutilisés, et voir si ça suffit à limiter suffisamment la consommation...
Les codes :
- Solution 1 :
#include <Servo.h>
// *********************************** Optim Conso ***********************************
#include <RocketScream_LowPowerAVRZero.h>
#include <RocketScream_RTCAVRZero.h>
// Example on a 32-pin ATMega4808
//const uint8_t unusedPins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
// A0 --> Light sensor
// 9 --> LED
// 10 --> Servo
const uint8_t unusedPins[] = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
// --- DBG ---
// 25 --> Serial output
//const uint8_t unusedPins[] = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
// ********************************* Optim Conso End *********************************
// --- CONSTANTS
// Validation constants
const long DELAY_CHECK = 1200000; // The delay between each status check (ms) when not validated
const long DELAY_RECHECK = 120000; // The delay between each status check (ms) when validated
const int VALIDATIONS_NUMBER = 3; // Number of checks to be validated before moving the door
// LED constants
const int LED = 9; // The pin the LED is attached to
const int LED_FADE_DELAY = 30; // Delay betwing each fading step
const int LED_FADE_STEP = 5; // Step for fading the LED
const int LED_BLINK_SHORT = 30; // Short blink duration
const int LED_BLINK_LONG = 850; // Long blink duration
const int LED_BLINK_MAX = 1000; // Max blink duration
// Servo constants
const int SERVO = 10; // The pin the servo is attached to
const int SERVO_MOVE_DELAY = 60; // Delay to move the door slowly
// Light sensor constants
const int LIGHT_SENSOR = A0; // The pin the light sensor is attached to
const int LIGHT_THRESHOLD_HIGH = 65; // Threshold for door opening
const int LIGHT_THRESHOLD_LOW = 30; // Threshold for door closing
// --- OBJECTS
Servo servoDoor; // Servo for the door opening and closing
// --- VARIABLES
unsigned int iValidatedChecks; // The counter of validated checks
bool bStatus; // Door status : 0 = closed ; 1 = open
int iLightValue; // Value of the light sensor [0;800]
void setup() {
// --- DBG ---
//Serial.begin(9600);
// *********************************** Optim Conso ***********************************
uint8_t index;
for (index = 0; index < sizeof(unusedPins); index++) {
pinMode(unusedPins[index], INPUT_PULLUP);
LowPower.disablePinISC(unusedPins[index]);
}
// ********************************* Optim Conso End *********************************
// Outputs
pinMode(LED, OUTPUT); // Pin of the LED
pinMode(SERVO, OUTPUT); // Pin of the LED
servoDoor.attach(SERVO); // Pin of the servo
// Inputs
pinMode(LIGHT_SENSOR, INPUT); // Pin of the light sensor
// Variables initialization
iValidatedChecks = 0;
// *********************************** Optim Conso ***********************************
/* true: external 32.768 kHz crystal */
/* false: internal 32.768 kHz ULP oscillator */
RTCAVRZero.begin(false);
/* Time in seconds, true: repeat, false: once */
RTCAVRZero.enableAlarm(DELAY_CHECK/1000, true);
// ********************************* Optim Conso End *********************************
// Start by opening the door
openDoor();
}
void loop() {
// LED fading : cycle start
fadeLed(LED, 1);
// Get the light value
iLightValue = analogRead(A0);
// --- DBG --- indicate light value away from computer
//int iLightValueC = (int)(iLightValue / 100);
//int iLightValueD = (int)((iLightValue - 100 * iLightValueC) / 10);
//int iLightValueI = iLightValue - 100 * iLightValueC - 10 * iLightValueD;
//blinkLed(LED, LED_BLINK_LONG, 2);
//blinkLed(LED, LED_BLINK_SHORT, iLightValueC);
//blinkLed(LED, LED_BLINK_LONG, 2);
//blinkLed(LED, LED_BLINK_SHORT, iLightValueD);
//blinkLed(LED, LED_BLINK_LONG, 2);
//blinkLed(LED, LED_BLINK_SHORT, iLightValueI);
//blinkLed(LED, LED_BLINK_LONG, 2);
// If the door is closed
if (bStatus == 0) {
// If the light is upper than the threshold, increment the number of validated checks. Othewise, set back the number of validated checks to 0
if (iLightValue > LIGHT_THRESHOLD_HIGH) iValidatedChecks++;
else iValidatedChecks = 0;
// Indicate the number of validated checks
blinkLed(LED, LED_BLINK_SHORT, iValidatedChecks);
// If the number of validated checks is sufficient, open the door
if (iValidatedChecks == VALIDATIONS_NUMBER) {
openDoor();
iValidatedChecks = 0;
}
}
// If the door is open
else if (bStatus == 1) {
// If the light is lower than the threshold, increment the number of validated checks. Othewise, set back the number of validated checks to 0
if (iLightValue < LIGHT_THRESHOLD_LOW) iValidatedChecks++;
else iValidatedChecks = 0;
// Indicate the number of validated checks
blinkLed(LED, LED_BLINK_SHORT, iValidatedChecks);
// If the number of validated checks is sufficient, close the door
if (iValidatedChecks == VALIDATIONS_NUMBER) {
closeDoor();
iValidatedChecks = 0;
}
}
// --- DBG ---
// String sDbg = "Luminosité : " + String(iLightValue) + "\nEtat : " + String(bStatus) + "\nContrôles validés : " + String(iValidatedChecks) + "\n";
// Serial.println(sDbg); delay(1000); // For leting time to the Serial.println before LowPower.standby
// Delay before next status check
if (iValidatedChecks > 0) delay(DELAY_RECHECK);
// *********************************** Optim Conso ***********************************
// else delay(DELAY_CHECK);
else LowPower.standby();
// ********************************* Optim Conso End *********************************
}
void fadeLed(int iLed, int iFadeNumber){
for (int iIncrement = 1; iIncrement <= iFadeNumber; iIncrement++) {
for (int iLedFadeBrihtness = 0; iLedFadeBrihtness <=255; iLedFadeBrihtness += LED_FADE_STEP) {
analogWrite(iLed, iLedFadeBrihtness);
delay(LED_FADE_DELAY);
}
for (int iLedFadeBrihtness = 255; iLedFadeBrihtness >=0; iLedFadeBrihtness -= LED_FADE_STEP) {
analogWrite(iLed, iLedFadeBrihtness);
delay(LED_FADE_DELAY);
}
}
}
void blinkLed(int iLed, int iDelay, int iBlinkNumber) {
for (int iIncrement = 1; iIncrement <= iBlinkNumber; iIncrement++) {
digitalWrite(iLed, LOW);
delay(LED_BLINK_MAX - iDelay);
digitalWrite(iLed, HIGH);
delay(iDelay);
}
digitalWrite(iLed, LOW);
delay(LED_BLINK_MAX - iDelay);
}
void openDoor() {
blinkLed(LED, LED_BLINK_LONG, 1);
for (int iAngle = 0; iAngle <=180; iAngle ++){
servoDoor.write(iAngle);
delay(SERVO_MOVE_DELAY); // Delay to move the door slowly
}
bStatus = 1;
}
void closeDoor() {
blinkLed(LED, LED_BLINK_LONG, 1);
for (int iAngle = 180; iAngle >=0; iAngle --){
servoDoor.write(iAngle);
delay(SERVO_MOVE_DELAY); // Delay to move the door slowly
}
bStatus = 0;
}
- Solution 2 :
#include <Servo.h>
// ****************************** Optim Conso ******************************
#include <avr/sleep.h>
// **************************** Optim Conso End ****************************
// --- CONSTANTS
// Validation constants
const long DELAY_CHECK = 1200000; // The delay between each status check (ms) when not validated
const long DELAY_RECHECK = 120000; // The delay between each status check (ms) when validated
const int VALIDATIONS_NUMBER = 3; // Number of checks to be validated before moving the door
// LED constants
const int LED = 9; // The pin the LED is attached to
const int LED_FADE_DELAY = 30; // Delay betwing each fading step
const int LED_FADE_STEP = 5; // Step for fading the LED
const int LED_BLINK_SHORT = 30; // Short blink duration
const int LED_BLINK_LONG = 850; // Long blink duration
const int LED_BLINK_MAX = 1000; // Max blink duration
// Servo constants
const int SERVO = 10; // The pin the servo is attached to
const int SERVO_MOVE_DELAY = 60; // Delay to move the door slowly
// Light sensor constants
const int LIGHT_SENSOR = A0; // The pin the light sensor is attached to
const int LIGHT_THRESHOLD_HIGH = 65; // Threshold for door opening
const int LIGHT_THRESHOLD_LOW = 30; // Threshold for door closing
// --- OBJECTS
Servo servoDoor; // Servo for the door opening and closing
// --- VARIABLES
unsigned int iValidatedChecks; // The counter of validated checks
bool bStatus; // Door status : 0 = closed ; 1 = open
int iLightValue; // Value of the light sensor [0;800]
void setup() {
// --- DBG ---
//Serial.begin(9600);
// Outputs
pinMode(LED, OUTPUT); // Pin of the LED
pinMode(SERVO, OUTPUT); // Pin of the LED
servoDoor.attach(SERVO); // Pin of the servo
// Inputs
pinMode(LIGHT_SENSOR, INPUT); // Pin of the light sensor
// ****************************** Optim Conso ******************************
RTC_init();
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode to POWER DOWN mode
sleep_enable(); // Enable sleep mode, but not going to sleep yet
// **************************** Optim Conso End ****************************
// Variables initialization
iValidatedChecks = 0;
// Start by opening the door
openDoor();
}
void loop() {
// LED fading : cycle start
fadeLed(LED, 1);
// Get the light value
iLightValue = analogRead(A0);
// --- DBG --- indicate light value away from computer
//int iLightValueC = (int)(iLightValue / 100);
//int iLightValueD = (int)((iLightValue - 100 * iLightValueC) / 10);
//int iLightValueI = iLightValue - 100 * iLightValueC - 10 * iLightValueD;
//blinkLed(LED, LED_BLINK_LONG, 2);
//blinkLed(LED, LED_BLINK_SHORT, iLightValueC);
//blinkLed(LED, LED_BLINK_LONG, 2);
//blinkLed(LED, LED_BLINK_SHORT, iLightValueD);
//blinkLed(LED, LED_BLINK_LONG, 2);
//blinkLed(LED, LED_BLINK_SHORT, iLightValueI);
//blinkLed(LED, LED_BLINK_LONG, 2);
// If the door is closed
if (bStatus == 0) {
// If the light is upper than the threshold, increment the number of validated checks. Othewise, set back the number of validated checks to 0
if (iLightValue > LIGHT_THRESHOLD_HIGH) iValidatedChecks++;
else iValidatedChecks = 0;
// Indicate the number of validated checks
blinkLed(LED, LED_BLINK_SHORT, iValidatedChecks);
// If the number of validated checks is sufficient, open the door
if (iValidatedChecks == VALIDATIONS_NUMBER) {
openDoor();
iValidatedChecks = 0;
}
}
// If the door is open
else if (bStatus == 1) {
// If the light is lower than the threshold, increment the number of validated checks. Othewise, set back the number of validated checks to 0
if (iLightValue < LIGHT_THRESHOLD_LOW) iValidatedChecks++;
else iValidatedChecks = 0;
// Indicate the number of validated checks
blinkLed(LED, LED_BLINK_SHORT, iValidatedChecks);
// If the number of validated checks is sufficient, close the door
if (iValidatedChecks == VALIDATIONS_NUMBER) {
closeDoor();
iValidatedChecks = 0;
}
}
// --- DBG ---
//String sDbg = "Luminosité : " + String(iLightValue) + "\nEtat : " + String(bStatus) + "\nContrôles validés : " + String(iValidatedChecks) + "\n";
//Serial.println(sDbg); delay(1000); // in order to let time to the Serial.println before the DeepSleep()
// Delay before next status check
if (iValidatedChecks > 0) delay(DELAY_RECHECK);
// ****************************** Optim Conso ******************************
// else delay(DELAY_CHECK);
else DeepSleep();
// **************************** Optim Conso End ****************************
}
void fadeLed(int iLed, int iFadeNumber){
for (int iIncrement = 1; iIncrement <= iFadeNumber; iIncrement++) {
for (int iLedFadeBrihtness = 0; iLedFadeBrihtness <=255; iLedFadeBrihtness += LED_FADE_STEP) {
analogWrite(iLed, iLedFadeBrihtness);
delay(LED_FADE_DELAY);
}
for (int iLedFadeBrihtness = 255; iLedFadeBrihtness >=0; iLedFadeBrihtness -= LED_FADE_STEP) {
analogWrite(iLed, iLedFadeBrihtness);
delay(LED_FADE_DELAY);
}
}
}
void blinkLed(int iLed, int iDelay, int iBlinkNumber) {
for (int iIncrement = 1; iIncrement <= iBlinkNumber; iIncrement++) {
digitalWrite(iLed, LOW);
delay(LED_BLINK_MAX - iDelay);
digitalWrite(iLed, HIGH);
delay(iDelay);
}
digitalWrite(iLed, LOW);
delay(LED_BLINK_MAX - iDelay);
}
void openDoor() {
blinkLed(LED, LED_BLINK_LONG, 1);
for (int iAngle = 0; iAngle <=180; iAngle ++){
servoDoor.write(iAngle);
delay(SERVO_MOVE_DELAY); // Delay to move the dorr slowly
}
bStatus = 1;
}
void closeDoor() {
blinkLed(LED, LED_BLINK_LONG, 1);
for (int iAngle = 180; iAngle >=0; iAngle --){
servoDoor.write(iAngle);
delay(SERVO_MOVE_DELAY); // Delay to move the dorr slowly
}
bStatus = 0;
}
// ****************************** Optim Conso ******************************
void RTC_init(void)
{
while (RTC.STATUS > 0) ; /* Wait for all register to be synchronized */
RTC.CLKSEL = RTC_CLKSEL_INT1K_gc; // Run low power oscillator (OSCULP32K) at 1024Hz for long term sleep
RTC.PITINTCTRL = RTC_PI_bm; // PIT Interrupt: enabled */
RTC.PITCTRLA = RTC_PERIOD_CYC8192_gc | RTC_PITEN_bm; // Set period 8 seconds (see data sheet) and enable PIC
}
ISR(RTC_PIT_vect)
{
RTC.PITINTFLAGS = RTC_PI_bm; // Clear interrupt flag by writing '1' (required)
}
void DeepSleep() {
for (int iLoops = 1; iLoops <= DELAY_CHECK / 8000; iLoops++){
sleep_cpu();
}
}
// **************************** Optim Conso End ****************************