3

I want to run cameras at a remote site from external batteries as long as possible. I need power-miser Arduino to switch battery power on/off at set intervals (e.g. 5 min) during daytime only. I am a beginner with Arduino and electronics.

Have set up 'breadboard' arduino with mosfet module for switching the power supply and RTC module, both from Freetronics (http://www.freetronics.com.au/collections/modules/products/real-time-clock-rtc-module#.V-i-S8knuPs). Following their recommendation I'm using RTC library here: http://rweather.github.io/arduinolibs/index.html

I need to refine the crude hour-based script below. Weatherley library returns separate objects e.g date.day, time.hour etc. Is there a simple way to convert to date-time object? Then calculate sunrise and sunset times based on latitude?

  #include <JeeLib.h> //  power saving library
  ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup jeelip watchdog
  #include <SoftI2C.h> // rweather lib for RTC module 
  #include <DS3232RTC.h> //rweather lib for RTC module 
  SoftI2C i2c(A4, A5); // assign pins to SDA and SCL
  DS3232RTC rtc(i2c);
  RTCTime time;
  int gatePin = 12;   //  mosfet Gate connected to digital pin
  int startHour = 6; // want to replace with sunrise time 
  int endHour = 19; // want to replace with sunset time

void setup()
{
 pinMode(gatePin, OUTPUT);   //  output pin for mosfet module
}

void loop()
{ // main loop starts here
  rtc.readTime(&time);  //get current time
  if (time.hour >= startHour && time.hour < endHour) // check daytime
  {   // if condition begins here
      while(time.hour < endHour ) // daytime operating period 

      {   //  while loop (day) begins here 
      digitalWrite(gatePin, HIGH);   // turn on gate for power supply 
      Serial.flush(); //needed before sleepy 
      Sleepy::loseSomeTime(30000); // low power wait
      digitalWrite(gatePin, LOW);    // turn off gate for power supply
      Serial.flush(); // needed before sleepy
      for (int i=0; i <= 3; i++){
        Sleepy::loseSomeTime(65000); // low power wait
        } // end for loop
      rtc.readTime(&time);   
      } // end while loop (day)    
      } //  if condition (daytime) ends here   
else
  { // else condition (night time) starts here
    while (time.hour >= endHour || time.hour < startHour ) 
    { // while loop (night) begins here
    for (int i=0; i <= 59; i++){ 
    Serial.flush(); // needed before sleepy
    Sleepy::loseSomeTime(65000); // low power wait
    } // end for loop
    rtc.readTime(&time); 
    } // while loop (night) ends here
// need to refine timing else hour-long wait periods can run past the end of night period
  } // else condition (night) ends here
} //  main loop ends here

I will be very grateful for advice, many thanks in advance!

EDIT: Part of my original question could be answered - see below about time-date format without using RTC. Issues with RTC appear harder than I expected. I think they will need a new question later.

  • I'd suggest using a light sensor. That way you can safe power if it is e.g.heavily clouded in the evening and therefor dark earlier. – Gerben Sep 26 '16 at 18:42
  • Light sensor not suitable in this situation. The cameras will be used for scientific project (monitor bird activity at their nests). Therefore need to record images atset time intervals for each day from sunrise to sunset. Also I need to learn about date-time programming in Arduino for further development from this basic script. – jules Sep 27 '16 at 6:50
  • 1
    There is a potential solution in a helpful answer to my question about understanding compiler error text. – jules Sep 27 '16 at 7:08
  • 1
    Clarification - my comment above does not refer to complete solution to this question. Answer to q about understanding compiler error has a good explanation and solution for TestRTC compiler error - see below in this question. – jules Sep 27 '16 at 7:35
  • I didn't mean to suggest removing the RTC. merely to suggest using a light sensor to detect sinrise and sunset. That way you don't have to enter latitude and longitude. Also data will still be collected if the time is wrong somehow (accidental reset of the RTC e.g.). So – Gerben Sep 27 '16 at 14:42
4

Is there a simple way to convert to date-time object?

Not with this library. But you can find other libraries supporting the DS3232 which work with the Arduino Time library[]. This time library provides both the date and time in a single object, either:

  • a time_t, which is just the number of seconds elapsed since a standard “epoch”
  • a tmElements_t struct, which has the date and time broken into separate elements (year, month, day, hour...).

Then calculate sunrise and sunset times based on latitude?

There are quite a few algorithms describes on the Web for that. The more accurate ones are also the more complex.

#include <SoftI2C.h>

Doesn't your Arduino have a hardware I2C port? That would be more efficient than software emulation.

Serial.flush(); //needed before sleepy

It's only needed if you are actually using the serial port.

Edit: I saw on your other question that you have been bitten by an incompatibility between the Arduino Time library and the file time.h from avr-libc. Now I just noticed that avr-libc includes the functions sun_rise() and sun_set() that you may find handy. Not sure they will play well with the Arduino time libraries though. One possible incompatibility is the fact that they use different epochs for defining time_t (year 1970 v.s. 2000).

  • Many thanks and sorry I don't fully understand. Using SoftI2C.h because I followed example doing it that way. Unsure whether my RTC module and atmega chip will communicate without it. Started with Uno board connected to laptop via USB, using serial window to see what was happening. At that point had to add Serial.flush(). Left it in, being unsure if needed later. Have moved the atmega chip from Uno to a breadboard with no 'peripherals' in order to minimise power usage. How do I determine whether "hardware I2C port" is available or not? Many thanks for patience with total beginner! – jules Sep 26 '16 at 9:15
  • @jules: All the peripherals of the Arduino Uno are part of the ATmega328P chip. Thus you still have them on a “barebones” Uno (i.e. the bare ATmega). The I2C port (called TWI by Atmel) is available on pins PC4 = A4 = SDA and PC5 = A5 = SCL. You would use this port through the standard Wire library. – Edgar Bonet Sep 26 '16 at 10:06
  • Great to know I have required hardware, thanks. I installed DS3232 and Time libraries you linked above. TestRTC, the example sketch for tecsmith DS3232 library gave compile errors that I cannot understand. Error text too long to add here. Any advice on how to resolve this? – jules Sep 26 '16 at 12:01
  • Checked both two new libraries are present, Wire was already installed. Compile TestRTC has exit status 1 'tmElements_t' does not name a type – jules Sep 26 '16 at 12:23
  • @jules: TestRTC has #include <Time.h> on line 46. Did it find that header? Don't you have typedef struct {...} tmElements_t, TimeElements, *tmElementsPtr_t; in it? – Edgar Bonet Sep 26 '16 at 20:18
2

I hope I am allowed to summarise progress. Edgar Bonet's answer above pointed me in the right direction regarding date-time format and I want to 'accept' that answer, although it did not resolve my difficulties with RTC. I need to ask a new question about RTC later.

Using the Time library Edgar Bonet recommended, I managed to set and change date-time format, and calculate duration between date-time instances. I hope my example below could perhaps be useful for other beginners. If anyone has suggestions to improve this example, please add them.

    #include <TimeLib.h> // https://github.com/PaulStoffregen/Time
    time_t tstart;

    void setup()  {
    Serial.begin(9600);
    // assume no RTC available therefore set date-time in this sketch
    // when serial monitor opens, date-time will be set as follows
    setTime(8,30,0,17,10,2016); // (hr,min,sec,day,mnth,yr); 
    tstart = now();
    Serial.print("Started at: "); 
    digitalClockDisplay(); 
    Serial.println();
    } 

    void loop(){    
    Serial.println("Waiting...");
    delay(20000 + random(500, 5000) );
    Serial.println();
    time_t tnow = now(); 
    Serial.print("Now it is: ");
    digitalClockDisplay(); 
    time_t duration = tnow - tstart;
    Serial.print("Duration since start: ");
    showDuration(duration);
    Serial.println();
    Serial.println();
    } 

    // function to print current date-time
    // modified from example in TimeLib
    void digitalClockDisplay(){
      Serial.print("Date: ");
      Serial.print(day());
      Serial.print("-");
      Serial.print(month());
      Serial.print("-");
      Serial.print(year()); 
      Serial.print("  Time: ");
      Serial.print(hour());
      printDigits(minute());
      printDigits(second());
      Serial.println(); 
    }
    // utility function from TimeLib 
    // to print leading zeros
    void printDigits(int digits){
      Serial.print(":");
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }

    // function from example TimeRTCLog
    void showDuration(time_t duration){
    // prints the duration in days, hours, minutes and seconds
      if(duration >= SECS_PER_DAY){
         Serial.print(duration / SECS_PER_DAY);
         Serial.print(" day(s) "); 
         duration = duration % SECS_PER_DAY;     
      }
      if(duration >= SECS_PER_HOUR){
         Serial.print(duration / SECS_PER_HOUR);
         Serial.print(" hour(s) "); 
         duration = duration % SECS_PER_HOUR;     
      }
      if(duration >= SECS_PER_MIN){
         Serial.print(duration / SECS_PER_MIN);
         Serial.print(" minute(s) "); 
         duration = duration % SECS_PER_MIN;     
      }
      Serial.print(duration);
      Serial.print(" second(s) ");   
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.