time.h counting hours for garduino

Hi all!

first off, thanks for trying to help. Im a newbie so go easy :wink:

im trying to build a garduino and using the new time.h library.
what i want to do:

the plant light for my little pepper mint plants is connected to a relay thats all hooked up and working.

every day, at 10pm, I want the light to go on and stay on for 16 hours.
Then it will be off for 8. same thing again, the next day.

I want to be able to track the amount of hours the plants were subject to light in form of a simple integer to be able to display it on the lcd screen. Perhaps days would be nice too.

I am stumped here, not even a start.

Thanks a lot! :-/

I am stumped here, not even a start.

Here's one way how you could break up the task into small and manageable task where you can start from pretty much zero to get to a finished product. How long the steps will take you depends on you, some will be easier, some will require more work. This should resolved the problem of not knowing where to start.

Step 1: Write a program that blinks a led without using the function delay(). You'll find something in the tutorials using millis().

Step 2: Modify your program from Step 1 to blink 16 hour on, 8 hours off. Hint: 8 hours are 836001000 = 28800000 milliseconds, 16 hours are twice as much.

You now have your basic light control and it will work perfectly as long as you started your Arduino at the beginning of the correct phase. Main problems is, what happens if the Arduino loses power and restarts? It doesn't know that it's 10pm.

Step 3: Add your counter for illumination time. I would count only minutes where the power is on. Format it nicely and send it out every minute on the serial port.

Step 4: Here we get new hardware: Add a LCD display and display the text you sent out on the serial port in Step 3. Add other nice information to make the display interesting for example how long until light goes on or off again. This additional information can be done in step 3 too.

Step 5: More new hardware, replace the driving of the LED by actually switching the light on and off. I guess you will want some sort of relay for that plus the necessary driving circuity. You can find a tutorial how to do this properly.

Now you have something useful that controls your light and also gives you a display on what's going on. The last big problem to solve is what happens when the Arduino loses power.

Step 6: Get more hardware to retrieve or keep the current time. Here is the place to look at the Time library, which comes bundles with the DS1307RTC library. So using a DS1307 Real Time Clock is probably a good and cheap solution (you can get such modules from most vendors like Sparkfun). Depending on where you are, you might have other alternatives available such as a DCF77 receiver, GPS signals or others. By now you should already have enough experience to integrate a module with an existing library. Play around with your new module in a separate sketch until you can retrieve the correct time.

Step 7: Apply what you learned in Step 6 to your program from Step 5 so that the time is read via the Time library with now() instead of with millis(). One consequence is that you'll do your calculations of illumination time in seconds instead of in milliseconds, those 8 hours are only 28800 and not 28800000.

Now your controller is nearly finished. It will do waht you want. The last drawback is only, that on a power loss, the total illumination time will be lost. Thus a little more programming comes up with:

Step 8: Update the current illumination total every hour to the EEPROM. Don't update the EEPROM all the time, it only takes a limited amount of writing before it dies. On startup of the Arduino read that value to continue counting from there. Also add a button to allow you to reset the counter for those situation when you start a new batch of plants. At this point, you will be able to read the Arduino documentation on your own to find the EEPROM library or a tutorial how to read a button.

Step 9: Build a nice enclosure for your lighting controller.

Step 10: Use it and have fun eating, snorting or smoking your plants.

That's all there is. If you encounter problems at any step, it'll be easier for you to get help here, because you will be able to ask specific questions for very concrete problems and those are the questions which get the best and quickest answers. And please, make sure you did all previous steps before asking questions about a later one. Some of the Steps have an increase in complexity where you should get some experience before attempting one of the later ones.

Korman

Don't forget the 28800000 is treated as an integer, which it is not. 28800000UL is treated as an unsigned long, which it is.

okay, thank you all so much for the amazing replies Korman and PaulS, im starting to build some ideas in me brains :slight_smile:

a couple of things:

  • to clarify, i got the relay circuit working. However its a 3vdc on the coil relay but im driving it with 5v right now. I had made a voltage split with two resistors but the 3.2 v were too little for the relay to switch. I tried my cell phone battery and at 3.7 v it switches fine. any suggestions?

  • I had thought of using millis() but i wanted to find out how to use the new time.h library. Is that even possible for a project like mine?

  • I would prefer to write to my eeprom less than every hour, say every day. I want to make a capacitor circuit that senses power failure and serves as backup.

  • I do not want my arduino hooked up to a computer, this will be a standalone project where I will have a button that lets me cycle through readings and adjust variables with switches and potentiometers.

  • Using other hardware is a great idea but i dont quite understand why you suggest that, since the arduino lets me count time, accurate to about a second a day. or did i misunderstand something?

if you need any info on my setup, let me know :smiley:

Thanks for the great step write out! You guys are amazing!!

xxlbreed

About your relay, please check out the Tutorial like this, this or this. It's not only about voltage but the current is important too. If your relay draws too much current, you'll fry your Arduino port.

About the time library: Just go ahead and use it. If you want to just measure seconds you can replace millis() by now() (and divide all values by 1000 for delays). In case you want to know what time it is, you need to set the time once in the Arduino.

Writing every hour will last your EEPROM for at least 11 Years, writing once per day it will last 270 years. Both should be good enough.

Hooking up your Arduino to a computer in the early steps is good for development, it makes development a lot easier and you don't have to deal initially with interfacing the display, which can be confusing for beginners. Later on you'll add an LCD with buttons to make it independent. That was the point of splitting it in different steps and I put it there for good a good reason. If you start to work on the full solution, you probably end up totally confused and with no clue what is all causing problems. Better to start in small steps where you take the time to understand each single step and make sure it works before taking the next one. That way, the added confusion will just be from the new stuff because you'll know the old stuff is already working properly. That's one of the secrets for a successful development project.

The Real Time Clock (eg Sparkfun DS1307 RTC Module) is just there to keep an accurate time while the Arduino is turned off or has no power. If you set the time correctly every time the power of your Arduino is lost and it restarts, that's fine too, you can live without it. In this case skip Step 6 and just go on to Step 7 and add the Time-library anyway.

Korman

About your relay, please check out the Tutorial like this, this or this. It's not only about voltage but the current is important too. If your relay draws too much current, you'll fry your Arduino port.

thanks for these, some very useful info here. thanks!!

Writing every hour will last your EEPROM for at least 11 Years, writing once per day it will last 270 years. Both should be good enough.

I was assuming far less time - good to know :smiley:

About the time library: Just go ahead and use it. If you want to just measure seconds you can replace millis() by now() (and divide all values by 1000 for delays). In case you want to know what time it is, you need to set the time once in the Arduino.

this is what i wanted to learn in this post. How do I use this instead of millis()? I dont get that... i looked at the arduino playground for it but it did not really help me understand...

Hooking up your Arduino to a computer in the early steps is good for development, it makes development a lot easier and you don't have to deal initially with interfacing the display, which can be confusing for beginners. Later on you'll add an LCD with buttons to make it independent. That was the point of splitting it in different steps and I put it there for good a good reason. If you start to work on the full solution, you probably end up totally confused and with no clue what is all causing problems. Better to start in small steps where you take the time to understand each single step and make sure it works before taking the next one. That way, the added confusion will just be from the new stuff because you'll know the old stuff is already working properly. That's one of the secrets for a successful development project.

agreed, very true.. I misunderstood when you first wrote that.

The Real Time Clock (eg Sparkfun DS1307 RTC Module) is just there to keep an accurate time while the Arduino is turned off or has no power. If you set the time correctly every time the power of your Arduino is lost and it restarts, that's fine too, you can live without it. In this case skip Step 6 and just go on to Step 7 and add the Time-library anyway.

Ill look into this, great idea makes more sense now :wink:

Great help there. cant stop sayin thanks!!

Here's a blink without delay (every 2 minutes) with millis(). The code was ripped out from http://arduino.cc/en/Tutorial/BlinkWithoutDelay

const int ledPin =  13;
const unsigned long interval = 120000[glow]UL[/glow];

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  static int ledState = LOW;
  static unsigned long previousTime = 0;
  unsigned long currentTime = millis();

  if(currentTime - previousTime > interval) { 
    previousTime = currentTime;    
    if (ledState == LOW) {
      ledState = HIGH;
    }
    else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }
}

The UL in yellow is to make sure the big numbers are correctly treated as unsigned long.

And here's the same with now() and Time.h. The differences are marked in yellow.

[glow]#include <Time.h>[/glow]
const int ledPin =  13;      
const unsigned long interval = [glow]120UL[/glow];

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  static int ledState = LOW;
  static unsigned long previousTime = 0;
  unsigned long currentTime = [glow]now()[/glow];

  if(currentTime - previousTime > interval) { 
    previousTime = currentTime;    
    if (ledState == LOW) {
      ledState = HIGH;
    }
    else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }
}

More about the Time library here: Arduino Playground - Time

That's all there is. Now off you go to play with that stuff yourself and make the light and the dark phase of different length etc. That's a good start to learn.

Korman

exactly what i needed!!

awesome!

and btw, i wont be smoking the plants, ill be making tea with my mint plants :wink: got 4000 seeds on ebay for $1 :smiley: haha

cant waiiitt to get home and try this out.

When it works you could enhance the application by adding fading in and fading out the light. like - YouTube then your mint plants doesn't get stressed by the sudden light/darness and they will taste better :slight_smile:

When it works you could enhance the application by adding fading in and fading out the light. like http://www.youtube.com/watch?v=91OitvwqCe8 then your mint plants doesn't get stressed by the sudden light/darness and they will taste better

Not sure how you are thinking of this. I am usint a T8 plant light tube, with a relay. Could you explain? It sounds very interesting to me.

xxlbreed

So ive been tinkering with the code.. cant figure out how to alternate between 8h on and 12h off?

(the light will do the opposite, it will be on 12h, and off 8. Due to the spdt relay - connected that way so i dont stress the coil too long ...)

here is my code right now. I removed all tries that i made.. I wish i was better at coding ..

#include <Time.h>


const int lightPin = 8;
const int pumpPin = 9;
const int pumpButtonPin = 11;
const unsigned long interval = 12UL;

int pumpState= LOW;
int pumpButtonState;
int lastPumpButtonState = LOW;

long lastDebounceT2 = 0;
long debounceDelay = 50;
static unsigned long previousTime = 0UL;

void setup()
{
  pinMode(lightPin, OUTPUT);
  pinMode(pumpPin, OUTPUT);

  pinMode(pumpButtonPin, INPUT);
}


void loop()
{
  static int lightState = LOW;

  unsigned long currentTime = now();

  int pumpReading = digitalRead(pumpButtonPin);

  if(currentTime - previousTime == interval)
  {
    
    previousTime = currentTime;
    current = previousTime;

    if(lightState == LOW)
    {
      lightState = HIGH; 
    } 
    else
    {
      lightState = LOW;
    }
    digitalWrite(lightPin, lightState);
  }


  if(pumpReading != lastPumpButtonState)
  {
    lastDebounceT2 = millis();
  }


  if((millis()-lastDebounceT2) > debounceDelay)
  {
    pumpButtonState = pumpReading;
  }


  digitalWrite(pumpPin, pumpButtonState);

  lastPumpButtonState = pumpReading;

}

At the moment, you switch every 12 seconds. If you want to modify the periods of light and dark, you need to make a variable out of interval (get rid of const in the declaration) and set it to the right length in the same place where you set lightstate to HIGH or LOW.

Also, as a side note, the following is better than using == for time intervals.

if(currentTime - previousTime [glow]>=[/glow] interval)

Although for your code and using seconds it won't matter much and it's very unlikely that the second you need will be missed.

Korman

ohh boy why didnt i think of that.. .i was messing with for loops and counting stuff, dividing by 12 and the remainder by 2 and .... ughh..

//thanks..

static unsigned long previousTime = 0UL;

The static keyword is not required on global variables. They are static by default (that is, on each iteration of a function, they are not reset).

  if(currentTime - previousTime == interval)

With currentTime and previousTime being unsigned long, it is unlikely that the difference will consistently EQUAL interval. If the difference is greater than interval, you will have a very long wait for another chance.

Due to the spdt relay - connected that way so i dont stress the coil too long ...)

This implies that you have the wrong hardware. There are latching relays that, I think, would serve you better. Set a pin HIGH, the relay changes state, and relaxes (no current draw). Set a pin LOW, the relay changes state, and relaxes (no current draw).

const unsigned long interval = 12UL;

12 milliseconds. The plants are even going to notice a 12 millisecond flash of light.

12 milliseconds. The plants are even going to notice a 12 millisecond flash of light.

that is actually 12 seconds and i had that in there to test with leds not my relays..

This implies that you have the wrong hardware. There are latching relays that, I think, would serve you better. Set a pin HIGH, the relay changes state, and relaxes (no current draw). Set a pin LOW, the relay changes state, and relaxes (no current draw).

its a 5 pin relay. when looking at it from the bottom, there are 3 on the left, 2 on the right. The hot power comes in center left side, the other two left side pins are the coil. The ones on the right side are the states of the switches. only one can have power at the time. when the coil engages a switch it flips to the other pin on the right hand side.
I can make a graphic if youd like..

With currentTime and previousTime being unsigned long, it is unlikely that the difference will consistently EQUAL interval. If the difference is greater than interval, you will have a very long wait for another chance.

figured it wouldnt be a biggie with counting in seconds... but changed it anyway to >=

The static keyword is not required on global variables. They are static by default (that is, on each iteration of a function, they are not reset).

good call, thanks , i missed that.

that is actually 12 seconds and i had that in there to test with leds not my relays..

Nope. millis() deals in microseconds, not seconds.

I don't see that you posted a link to the relay that you have, but typical relays require power to hold it in one position (either open or closed). A latching relay only requires power to change the position (open to closed or closed to open).

Relays, other than solid state relays, typically require a lot of current - more than an Arduino pin can deliver.

I'd like to see a link to the relay that you have.

http://www.rapidonline.com/netalogue/specs/60-4660e.pdf

there you go ...

Nope. millis() deals in microseconds, not seconds.

that is true but i think that in my code it is seconds because I am not using millis() but instead the Time.h library and the now() function..
i tried it out and measured the time ... it is 12 seconds..

btw the 2 relays use my 3.3v rail to switch states. and 2 ardu dig pins..

I just planted some jalapeno pepper seeds, mint seeds and italian basil.

Looking to get a peppermint plant some time this week to add to the seeds.. FYI peppermint does not have seeds because its a sterile hybrid.
The mint seeds are going to be crosses of all kinds of mint plants..

10 - 14 days before we start seeing anything .. cant waitt!!

updating the code with new functions soon.. adding lcd, 2 buttons and a potentiometer to navigate menu options..., moisture sensors and a water system code that partially eliminates my button .. that i am using now to control the pump..

wish me luck :smiley: