Indoor gardening, control the on/off state of many things using a DS3231.

Hello.

I am a little lost regarding a project of mine, I had a plan but it was based upon that there is a struct that turned out to be a class within a library, I am researching if there is any problems re-writing that class into a struct since it pretty much is a struct anyway, a class containing a number of uint8_t variables.

But I am looking for advice on how to efficiently determine the times during a day that different things will turn on/off.

I don't know where you live but where I live in Sweden I consider tomato's to be extremely overvalued since the tomato's available in the stores here lacks taste completely in comparison to the tomato's I have eaten in Greece and Italy. So I have invested in a little grow tent in order to find out if tomato's grown under white LED's with UV supplementation will create better tomato's than those in the stores, I like tomato's but I never enjoy them which I hope to change.

But I can't accomplish what needs to be done manually since I need to control the following things(some of these could be controlled with a mains connected timer but since I have to use a RTC and relays to control some of the things I might as well control all things like that instead of relying upon 4 mains-connected timer switches):
The following list is not mentioning all the different kinds of sensors that are used to determine certain parameters such as magnetic door sensor.

  • Control the ON/OFF times of the white LED's, with provisions to switch between 18h sun/6h dark and 12h sun/12h dark.
  • Control the ON/OFF of the UV LED's, these shall be on for a certain amount of minutes each time, and a certain number of periods each day(for example 30min 4 times a day), and there will be a sensor of some kind to detect if the tent door is open or not, if the tent door is open then the UV LED's should be turned off no matter what and then continue when the door closes(I am using mainly UVA but also a strong UVB LED so exposure to that is something I don't want to risk.
  • Control of a mains driven circulation fans, I want "heavy winds" some time and "wind-less" other time to simulate nature and strengthen then stems with harsh "winds".
  • There will in the end be other things which I am going to make some experiments with such as speakers that will play bird song during "sun-up" and "sun-down"(I can't recall what some people think this accomplishes when cultivating plants indoors but I simply have to look deeper into that fascinating idea).
  • There will also be a PID control-loop controlling the speed of the intake-fan and extraction fan as well as a heater element using the information from a temperature sensor and a humidity sensor in order to maintain temperature and relative humidity but these things are not really of concern for this thread since they have nothing to do with the DS3231 time-keeping part of the project

The goal is to create a fully automatic system so in the end there might be a hydroponics system installed which needs control also but that isn't relevant until I have successfully accomplished these already listed tasks.

I am using a library found at http://www.RinkyDinkElectronics.com/ but I think my DS3231 module is broken, I can write the time to the DS3231 but no matter what I do the time isn't being updated, I can write the time 14:09(0 seconds) and then read from the DS3231 and indefinitely get back the value 14:09. But I will go ahead with the project while I get a new module.

So I have this library from the above mentioned site which contains 2 class definitions:

class Time
{
public:
 uint8_t hour;
 uint8_t min;
 uint8_t sec;
 uint8_t date;
 uint8_t mon;
 uint16_t year;
 uint8_t dow;

 Time();
};

class DS3231
{
 public:
 DS3231(uint8_t data_pin, uint8_t sclk_pin);
 void begin();
 Time getTime();
 void setTime(uint8_t hour, uint8_t min, uint8_t sec);
 void setDate(uint8_t date, uint8_t mon, uint16_t year);
 void setDOW();
 void setDOW(uint8_t dow);

 char *getTimeStr(uint8_t format=FORMAT_LONG);
 char *getDateStr(uint8_t slformat=FORMAT_LONG, uint8_t  eformat=FORMAT_LITTLEENDIAN, char divider='.');
 char *getDOWStr(uint8_t format=FORMAT_LONG);
 char *getMonthStr(uint8_t format=FORMAT_LONG);
 long getUnixTime(Time t);

 void enable32KHz(bool enable);
 void setOutput(byte enable);
 void setSQWRate(int rate);
 float getTemp();

 private:
 uint8_t _scl_pin;
 uint8_t _sda_pin;
 uint8_t _burstArray[7];
 boolean _use_hw;

 void _sendStart(byte addr);
 void _sendStop();
 void _sendAck();
 void _sendNack();
 void _waitForAck();
 uint8_t _readByte();
 void _writeByte(uint8_t value);
 void _burstRead();
 uint8_t _readRegister(uint8_t reg);
 void _writeRegister(uint8_t reg, uint8_t value);
 uint8_t _decode(uint8_t value);
 uint8_t _decodeH(uint8_t value);
 uint8_t _decodeY(uint8_t value);
 uint8_t _encode(uint8_t vaule);
#if defined(__arm__)
 Twi *twi;
#endif
};

This library is compatible with Arduino Due which is the one I am using.
So these classes will be incorporated within my own classes in some way.

My first idea is this:
Replace the Time class with a Time struct containing the same variables, in the main sketch create an instance of said struct and initialize a pointer pointing to it, this pointer will be passed to methods within each of my own classes when they are called in order for these methods to gain access to the current time and thus be able to calculate when the time to change state has arrived.

At this moment I can't recall what problem I ran into yesterday when I sat down and worked for 4 hours trying to start implementing this...

But I sort of suspect that there is a simpler or easier way to go about this, if not then I am still not certain about how I would calculate the ON/OFF actions for the different objects.

I have planned on writing classes such as(these are not complete, I am just writing them up as I go in order to illustrate the concept):

class LEDwhite
{
    public:
      setOnTime();
      setOffTime();
      checkTime(struct *t);

}

class LEDuv
{
    public:
      setOnTimeDuration();
      setOnTimeOccurance();
      checkTime(struct *t);
      pauesActivity();
      resumeActivity():
}

// the following would be added into the exiting DS3231 library:
class DS3231
{
    public:
      defineEndOfAndStartOfDay(uint8_t hour, uint8_t min);
  /* and some wrapper method for existing methods
      implementing mechanism for setting the time of 
      the RTC in order to set it up to the appropriate 
      time and date and year
  */
}

And similar classes for all the other types of objects that are to be controlled, such as circulation fans maybe, I am so confused right now that I can't really see if I am onto any sort of viable idea, I can't even recall exactly what I wanted to ask for advice about specifically.

Assuming the used DS3231 library will work the same if I switch that Time class with a struct then I think this will work and the loop would look like this in pseudo code:

void loop()
{
    t = rtc.getTime();

    growLight.checkTime(&t);
    uvLight.checkTime(&t)
    uvLight.checkDoorSensor();

    sensorValue = readSensors();
    actOnSensorData(sensorValue);
    updatePID(sensorValue);

    writeToSDcard(&t, sensorValue); // data logging for later analysis.
}

I'm sure I have left out several important tasks that needs to be done in the end.
I guess I am looking for alternative ideas about how to go about this hole RTC time-keeping action-controlling situation.

In any case I am in the process of writing up everything that I need the project to accomplish to figure out what classes, what functions and mechanisms that I need to implement, I hope I managed to convey the necessary information without too much effort on the reader.

I really appreciate any and all inputs, ideas, criticism or whatever thoughts you might have about this hole idea/project, there is no question about if this will be implemented, I already own the tent and equipment so I have to solve this in one way or another.

Kind regards.

If the clock isn't changing use a DS3231 library that allows you to do something like this

if (rtc.GetIsRunning() == false) rtc.SetIsRunning(true);

Replace the Time class with a Time struct containing the same variables,

Explain why you want to do that.

Assuming the used DS3231 library will work

Did you already connect the hardware? Did you try that chip without the rest (to ensure it's working)?

I get the impression that you're thinking about the advanced stuff while you haven't ensured the base things in your project are running.

Connect the RTC and get it running.

Connect the relay boards (or whatever you plan to use there) and get each of them running separately.

Get the fan hardware running without the rest of the hardware.

You don't need an RTC to use the Time library OR to keep time. The RTC just helps to keep the time accurate, and runs when the power is off.

Get your project running without the RTC before adding it. No need to make any changes to the Time library for either implementation -- you just need to learn how to use it effectively.

For switching devices on a daily basis, seconds or minutes past midnight are convenient choices for if statements.