Deep Sleep mode, wake up and time approach

Hay, i just started this awsome dream project : An embeded and self power Automated Chicken Door !

1 Program start
F2 The user will use a potentiometer and LCD screen to select :
--- the current time / the time to close the door / and the time to open the door.
F3 The program will be enter in deep sleep mode to save electricity.
F4 the progran can wake-up alone when it's time to open or close the door.
F5 And the user can wake-up the program with a push bouton to read the set-up with LCD.

All my problems are about the point 4 :
I got a Arduino UNO v3 board and a Arduino NANO v2 and i have'nt got a RTC.

Have you got some ideas about how to count the time ? I don't need a lot of precision (around 10 minutes will be OK).

At this moment : My program look like this

https://create.arduino.cc/editor/BenoitP/03adf3f1-89fe-4456-ae31-e0ab620fc860/preview

My program look like this

Post your code here, or your problem there.

?

You can use the WatchDog timer to wake up but this is quite inaccurate and the timing may vary by quite a lot if the chip-temperature changes. You could also use a 32KHz crystal / oscillator on Timer2 which will yield much more stable timing and less power consumption than the WatchDog. But the rest of the components on the NANO will still consume power, so if you really want low power consumption, you should use an ATmega328P (or maybe even an ATtiny85) as stand-alone.

http://www.gammon.com.au/power

BenoitP:
?

You expect us to go find your code. That is far less likely to get people to help you than if you post your code HERE properly. Read the stickies BEFORE you reply again.

The putting it to sleep can be an issue here. The watch dog timer is what you would want to use. However, the max time is 8 sec. You would need to chain the watchdog until it hits your time, than perform work.

The button press is easy, attach to interrupt pin and you are good to go.

I suggest you read this. https://www.gammon.com.au/forum/?id=11497

I get it that the RTC will be the better solution.

But is it possible to go without this ?
Maybe i could reverse the system like this :

The hardware set-up will be :

  • The Arduino Nano
  • A Motor able to open a 150g door (i get it from an old video recorder)
  • A pack of rechargeable battery
  • A solar panel
  • A Photoresistance

1 - I check the sun with the photores
2 - If the door is close and the sun is high > Open the door ! And deep in sleepmode during among 10 hours.
3 - Wake-up from deepsleep and start to check the light evry 20 minutes.
4 - If the sun is down and the door open ! It's time to save chikens and to close the door ! And after this hard day of working going to a new deepsleep among 8 hours.
5 - Wake-up from deepsleep and start to check the light (go back to point 1)

With this process I would like your advice about the possible solutions for saving power and asume a little time's slide of the arduino.

Actually, I can see you staying in a deep sleep and only waking up when its light or dark.

When it is dark it will be low. When it is light it will be high. Attach to one of the interrupt pins and some simple state management with detection of HIGH and LOW on the interrupt pin and this might work.

I do something very similar

As mentioned, see Nick Gammon’s discussion on power saving.

FYI

Use low current 5v relays or power them from a different supply.

An RTC can be added to the cct. above.

See this also:
“Narcoleptic only shuts down the CPU. It does not shut down
** anything else consuming current - LEDs, or the USB to serial chip.”

Thanks for you anwsers. I need some time to check evrythings.

@larryd what's the name of the software do you used for show this hardware plans ?
I will add my plan to the project.

And the picture of the door (the mecanic part is over and ready to work).

I use WINQCAD, no longer available.

However there are many other schematic/PCB programs you can use.

Kicad, Eagle, EasyEDA are three examples.

I tried to implement Watchdogtimer and power deep sleep (I’m waiting for the RTC).

I would like to sleep during among 8 hours.

how can I calcul the slide in time of the chip ? because i already see that’s with this code (this below) I loose 10 sec evry 10 minutes.

Do you see some points I can add to save power or improve the code ?

All your advices could save life of chickens :wink:

You can read my code here

#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

volatile bool flag_wdt=HIGH;                           // flag of watchdog
ISR(WDT_vect) {                                        // Watchdog Interrupt Service est exécité lors d'un timeout du WDT
  if(flag_wdt == LOW){flag_wdt = HIGH;}                // Reset watchdog flag
}    

// ----------------------------------------------------------------------------------- start_BROCHES

const int pin_BATT_MESURE   = A0;       // Déclaration : pin Mesure de la batterie d'alim. moteur
const int pin_Photo_Sensor  = A1;       // Déclaration : pin Photoresistance
const int pin_Moteur_PWM    = 3;        // Déclaration : pin Moteur PWM
const int pin_Moteur_1      = 4;        // Déclaration : pin Moteur 1
const int pin_Moteur_2      = 2;        // Déclaration : pin Moteur 2

const int pin_LED_GREEN     = 13;        // Déclaration : pin OK
const int pin_LED_ORANGE    = 12;        // Déclaration : pin HALF
const int pin_LED_RED       = 11;        // Déclaration : pin DOWN


// ----------------------------------------------------------------------------------- end_BROCHES

bool  DOOR_STATE  = LOW  ;                      // LOW = FERMEE // HIGH = Ouvert
int Mesure_Photo_sensor = 0;

// -----------------------------------------------------------------------------------

void setup_my_watchdog(const byte interval) {
  MCUSR = 0;                              // reset various flags
  WDTCSR |= 0b00011000;                   // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;        // set WDIE, and appropriate delay
  wdt_reset();
}

void setup()
{
  Serial.begin(9600);                     // Ouverture Port Serie
  Serial.print("Let's rock \t \n");
  delay(900);
  
  // OUTPUT
  pinMode(pin_Moteur_PWM,    OUTPUT);      // Sortie PWM > Moteur PWM
  pinMode(pin_Moteur_1,      OUTPUT);      // Sortie 1
  pinMode(pin_Moteur_2,      OUTPUT);      // Sortie 2

  pinMode(pin_LED_GREEN,     OUTPUT);      // Sortie led verte  OK
  pinMode(pin_LED_ORANGE,    OUTPUT);      // Sortie led orange HALF
  pinMode(pin_LED_RED,       OUTPUT);      // Sortie led rouge  DOWN

} // -----------------------------------------------------------------------------------

void enterSleep(int hour_to_sleep) {
  int i=0;                                // Create a counter
  //time_to_sleep = 360*hour_to_sleep;   // how many 10sec i need to sleep ? 6*60*hour(s)

  // ---------------------------- START Save power -------------------
  power_adc_disable();                  // ADC OFF
  power_spi_disable();                  // SPI OFF
  //power_twi_disable();                  // ? OFF
  power_usart0_disable();               // USART et USB COM OFF
  power_timer0_disable();               // Timer 0 OFF (attention timer0 utilisé par millis ou delay)
  //power_timer1_disable();               // Timer 1 OFF
  //power_timer2_disable();               // Timer 2 OFF
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // Configures the Atmega168 for the specified sleep mode
 
  for(i=0 ; i< hour_to_sleep ; i++){       
    setup_my_watchdog(0b100001);          // Set-up first watchdog 8sec
    sleep_enable();                       // Enables the sleep mode to be entered;
    sleep_mode();                         // Entre dans le mode veille choisi
    // -----------------------------------// program restart here after watchdog 8sec timeout
    sleep_disable();                      // First : disable sleep mode
    setup_my_watchdog(0b000111);          // Set-up new watchdog 2sec
    sleep_enable();                       // Enables the sleep mode to be entered;
    sleep_mode();                         // Entre dans le mode veille choisi
    // -----------------------------------// program restart here after watchdog 2sec timeout
  }

  power_adc_enable();                  // ADC ON
  power_timer0_enable();               // Timer 0 ON
  power_usart0_enable();               // USART et USB COM OFF
}

void loop() {
  
  bool SUN_STATE = HIGH;
  
  while (1) {
    
//   function_test_Batt();
    power_adc_enable();                       // ADC ON
    SUN_STATE = function_read_light();
    power_adc_disable();                      // ADC OFF

//    if (DOOR_STATE==LOW && SUN_STATE==HIGH) {           // Porte fermée & présence lumière
//      Serial.print("Monter la porte \t \n");
//      actionMoteur(-1, 100);                             // MONTER LA PORTE
//    }
//    
//    if (DOOR_STATE==HIGH && SUN_STATE==LOW) {           // Porte fermée & présence lumière
//      Serial.print("Descendre la porte \t \n");
//      actionMoteur(1, 100);                             // DESCENDRE LA PORTE
//    }

    Serial.print("I will take a rest go back in 2 minutes \t \n");
    delay(900);
    enterSleep(120);                                      // Save power entersleep mode for x hours
    Serial.print("OK !!! I'm OK !  \t \n");
    delay(900);
    
  } // -----------------------------------------------------------------------------------
} // end ofloop




bool function_read_light(){

    Mesure_Photo_sensor = analogRead(pin_Photo_Sensor); // Lance une mesure de Soleil
    
    Serial.print("Sensor = ");  Serial.print(Mesure_Photo_sensor);  Serial.print("\t \n");
    
    if   (Mesure_Photo_sensor >= 600) { return HIGH;} // JOUR
    else                              { return LOW;}  // NUIT
}

void actionMoteur(int sens, int pourcentage) {
  int a, b, puissance;

  // Définir le sens de rotation
  switch (sens) {
    case 1 :  { a = 1; b = 0; }  break;
    case -1:  { a = 0; b = 1; }  break;
    default:  { a = 0; b = 0; }  break;
  }

  puissance = map(pourcentage, 0, 100, 0, 255);   // Réglage puissance
    
  // Roule ma poule !
  analogWrite (pin_Moteur_PWM, puissance);
  digitalWrite(pin_Moteur_1, a);
  digitalWrite(pin_Moteur_2, b);

  Serial.print(" START MOTEUR \t\n");
  delay(5000);

  // Freinage
  analogWrite (pin_Moteur_PWM, 0);
  digitalWrite(pin_Moteur_1, 0);
  digitalWrite(pin_Moteur_2, 0);
  Serial.print(" FREINAGE MOTEUR \t\n"); 
}

void function_test_Batt(){
  int Mesure_BATT=0;
  Mesure_BATT = analogRead(pin_BATT_MESURE);          // Lance une mesure de la valeur de la batterie du moteur A0
  int range_Mesure_BATT = map(Mesure_BATT, 0, 1023, 0, 4);

  switch (range_Mesure_BATT) {
    case 0:{digitalWrite(pin_LED_RED, HIGH);digitalWrite(pin_LED_ORANGE, LOW);digitalWrite(pin_LED_GREEN, LOW);}break;   // Batterie DOWN
    case 1:{digitalWrite(pin_LED_RED, HIGH);digitalWrite(pin_LED_ORANGE, HIGH);digitalWrite(pin_LED_GREEN, LOW);}break;
    case 2:{digitalWrite(pin_LED_RED, LOW);digitalWrite(pin_LED_ORANGE, HIGH);digitalWrite(pin_LED_GREEN, LOW);}break;   // Batt HALF
    case 3:{digitalWrite(pin_LED_RED, LOW);digitalWrite(pin_LED_ORANGE, HIGH);digitalWrite(pin_LED_GREEN, HIGH);}break;
    case 4:{digitalWrite(pin_LED_RED, LOW);digitalWrite(pin_LED_ORANGE, LOW);digitalWrite(pin_LED_GREEN, HIGH);}break;   // Batt OK
    default:  {}  break;
   }
}