Multiple alarms during defined period. RTC?

Hi Folks,

Looking for any help with the following:

Concept:
Need to feed my baby fish very frequently during the day. They need to be fed about every 20 mins or so during daylight hours - lets say from 7am to 7pm, every day of the week. That would be approx. 36 alarm repeats. Working to real time is pretty critical (hence the RTC) as the fish will not feed at night, so need the code to recognise this and cease from 7pm to 7am.

What I have so far:

Arduino Uno

The actual physical feeding side is pretty much sorted - 2x 6v motors (1 dispenser, 1 spreader) run off a 2 relay module. Each motor has its own manual pot at this stage to get the delivery right. These will operate and shut down at the same time to get the feed to the fish. Easy enough to do on a short relay test sketch and works fine, but need to tie into the 'alarm timing' bit.

1 x DS3232 RTC

which works fine as a clock. I have run the test sketch and all is ok.

Ordered a couple of DS1307 RTC's just to cover my bases (not yet arrived).

What I would like to know:

Is it possible to change the specs of the TimeAlarm.h library to include 36 odd alarms per day or will I be pushing things to far? I have read the links to doing this (i.e increasing from 6 alarms) but this is my first crack at programming anything so do not want to change things that are just going to make more of a mess.

Is it possible to 'start' an alarm 'window' at 7am and 'end' the alarm window at 7pm everyday?

The closest sketch I have found to doing this using an RTC is

What are your thoughts on doing it this way?

Any help kindly appreciated.

Thanks

night, so need the code to recognise this and cease from 7pm to 7am.

Night is not necessarily 7 pm to 7 am. Depending on the latitude and time of year, that's not even necessarily a close approximation.

Just (fish) food for thought. A light sensor might make sense as part of your control system.

which works fine as a clock.

What else do you need it to work as?

Ordered a couple of DS1307 RTC's just to cover my bases (not yet arrived).

Why, since you already have a working clock?

Is it possible to change the specs of the TimeAlarm.h library to include 36 odd alarms per day

Yes, but why? If you know that you want to feed the fish every 20 minutes, does it matter if it is at 7:13, 7::33, and 7:53 vs. 7:00, 7:20, and 7:40? Either way, you can feed them whenever you like. The even numbers are conceptually easier to work with (minutes() %20 == 0), but that can be (minutes() % 20 == 13) just as easily.

Is it possible to 'start' an alarm 'window' at 7am and 'end' the alarm window at 7pm everyday?

Yes, but again, why? The clock knows whether it is AM or PM. In the feedFish() routine, check to see if it is AM (and feed the fish) or PM (and do nothing).

What are your thoughts on doing it this way?

I wouldn't. But, then, I know how to use a clock.

You're making it rather more complex than necessary. Take a look at the blink without delay example sketch. It uses millis to flash an LED. You can use the same technique to control a 20 minute period. Whenever the 20 minutes is up, read the RTC. If the hour is in the right range, feed the fish.

I'd use the Time library to sync the software with the hardware RTC. Then it's just a matter of initiating the feeding process at fixed intervals between two times of day.

This omits several details, but the central logic is straightforward:

    time_t currentTime, startTime, endTime;
    static time_t lastFeeding;
    const time_t FEEDING_INTERVAL = 20 * 60;    //time_t is seconds, so 20 * 60 = 20 minutes
    
    currentTime = now();
    if (currentTime >= startTime and currentTime <= endTime) {
        if (currentTime - lastFeeding >= FEEDING_INTERVAL) {
            lastFeeding = currentTime;
            feedTheFish();
        }
    }

The DS3232 will be much more accurate than the DS1307. I wrote a library for the DS3232, although for basic use, DS1307 libraries should work.

I'd approach the project in two steps. First, use fixed times as the start and end times, e.g. 7:00 AM and 7:00 PM. Second, if it is advantageous, the start and end times could be synchronized to the local sunrise and sunset times. Here is a project I did that has an algorithm for calculating sunrise and sunset given latitude and longitude.

I don't suppose your baby goldfish are up to reading clocks yet and probably just have a daily cycle driven by daylight. Why don't you use the same simple approach to feed them? You can detect whether it's daylight using a quid's worth of LDR and a line of code - much easier and cheaper than connecting up an RTC and getting the code working to read/set it.

Then just use a trivial change to the 'blink without delay' sketch to feed at whatever interval you want during daylight.

Wow, thank you all kindly for the quick response. Some great ideas - yes I am guilty of over complicating things - just shows my total lack of knowledge. I think i will have a go at all of them - for the practice - and to see which one I can best come to grips with. I am currently away with work, but will let you know how I get on and hopefully have something successful to share.

Most appreciated.

Hi Folks,

I have had a go at one of the suggestions to my previous question. I have linked in an LDR and after a few hours over a few days - I have the code working!. Just blinking an LED at this stage but I read the concept as going to plan. However, I have a couple more questions if I may:

  1. I understand how to adjust the time between feeds (long interval value), but I would like to be able to control the time of the feed as well. For example - When the LDR is receiving light the feeder will activate every 20mins, but I would like it to be active for only about 4-5 secs (dispensing food), then shut off, then after another 20 mins, the feeder dispenses again for 4-5 secs then shuts off and so on until it becomes dark and the LDR stops the loop. The way I read the code now is that food is dispensed every 20 mins for 20mins - that's alot of wasted feed! How would I do this without including a delay? Could I include for example #define ONTIME 4000, and put that in the loop somewhere? I presume this would go with the
    if (ledState == LOW)
    ledState = HIGH
    Not sure on this one..

  2. I have read that after 50 days or so the millis will reach a maximum number and cease operating. I will not always be able to reset the unit around this time, so is there any way to make the counting process reset itself - maybe at the end of the day when the LDR stops the loop when it gets dark? Or am I just misreading the code and as it stands it will run permanently without need for adjustment?

I have attached the code for some constructive criticism if you have time. This is my first attempt at altering any code so opens to all suggestions.

Thanks kindly.

/* Blink without Delay

Turns on and off a light emitting diode(LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.

The circuit:

  • LED attached from pin 13 to ground.
  • Note: on most Arduinos, there is already an LED on the board
    that's attached to pin 13, so no hardware is needed for this example.

created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/

// constants won't change. Used here to
// set pin numbers:
const int ledPin = 13; // the number of the LED pin
const int sensorPin = A0;

// Variables will change:
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
unsigned int sensorValue = 0;

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds) 20mins = 1,200,000 - this is the one to adjust for time BETWEEEN feeds.

void setup() {
// set the digital pin as output:
pinMode(13, OUTPUT);
pinMode(A0, INPUT);
Serial.begin (9600);

}

void loop()
{

//int rate = analogRead(sensorPin);
//float volts = (rate/1023.0) * 5.0;
//int rawRate = rate;

sensorValue = analogRead(sensorPin);

if (sensorValue >700); {

unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
if (ledState == LOW)
ledState = HIGH;
else ledState = LOW;
}
{
if(sensorValue<700)
ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);}
}
{

//Serial.print("Raw Rate: ");
//Serial.println(rawRate);

//Serial.print("Map Rate: ");
//Serial.println(rate);

//Serial.print("Volts DC: ");
//Serial.println(volts);
//Serial.println();

//Serial.print("Led state: ");
//Serial.println(ledState);

//delay(1000);

}
}

It isn't elegant, but if you don't need to do anything else during feeding (and given that the feeding duration is relatively small) you could implement the feeding as:

startFeeding();
delay(FeedDuration);
stopFeeding();

Execute that code every feeding interval during daylight hours using your existing code, and you have the basis of a solution.

  1. I have read that after 50 days or so the millis will reach a maximum number and cease operating.

No. It rolls over, back to 0. But, your wristwatch does the same thing, once or twice a day, and that never causes you grief, does it?

  if(currentMillis - previousMillis > interval) {

I'm willing to bet that if you gave these variables meaningful names, like now, lastStartFeedingTime, and timeBetweenFeedings, that how to modify the code to feed the critters only for a short period of time would become obvious. You start feeding them some time after you last fed them, so stopping feeding them some time after you start feeding them should be trivial.

To make life more complex for you......http://arduino-aquarium.blogspot.com/

Check this guys auto feeder. Seems easy and all it uses is a little stepper motor.