Solved: Controlling three 230V sockets with timed relays

Hello, I'm new here.

What I'm doing?
I'm moving my chilli plants inside for the winter, and for those I need some timing for the electric devices. I have:
-A bubbler, which is the same thing as in aquarium, making air bubbles. And noise.
-A fan, to strenghten the stems of the chillies, and making noise.
-A light for obvious reasons
All the things require 230V.

This is the idea: PICTURE
You can find more by googling "hydroponics", if interested.

What do I want?
As you could imagine, I don't want to keep the gadgets on at all times, so I look at Arduino as a solution. I want to have:
-Separate timers for all the devices and for every weekday.
-Button to start/stop the fan manually. The timer will still have to start it at the next alarm after I've manually stopped it.

What can I do?
I'm a machinist/electrician and I have done some electronic projects such as vacuum tube amplifiers, wheel/pedal set for computer, and many smaller projects. I also did Arduino Ambilight for my TV some years ago, but I just modified programs made by other people. Shortly: I know the basics of electronics and programming.

My set of hardware
(links to the exact devices I've ordered)
-Aruino UNO
-DS2321 RTC
-5V 4-Channel Relay Module Shield
-AC 100V-240V Converter Adapter DC 9V 1A Power Supply
-Plus a 4-socket extension cord to be modified so everything fits inside (the fourth socket will be for powering the Arduino)

What I've done so far?
This far I've managed to do some research and order the hardware. I hope it's all suitable for my project?
I've written the program. Mostly by copypasting the examples and modifying them to my needs. It's too long for pasting here, so it's attached as a file.

The help that I would need
-is for you, a-very-kind-more-experienced-than-me-programmer-who-has-some-time-to-waste-to-help-a-newbie, to check through my program and point out if there's errors.
The code is not finished, I believe I have to at least replace every Serial.println("Turn the light on"); with digitalWrite(fanPin, HIGH); etc etc.

Tweaking and becoming a better programmer
I have made a separate alarm for light/fan/air * on/off * every weekday. That's 327=42 alarms. That's not a pretty code I admit, but I think it'll work... But I hate to make such a long program for such an easy and repetitive task.

There must be a way to do it in a more simple way. At least I tried to make it a bit easier to adjust, that's why there's variables for weekday-times and weekend-times. I don't have to adjust EVERY day separately.

There must be a more elegant way to do this, and I would love to see your approach for the problem.

Oh, and I dodn't forget the the wiring, did I?
There shouldn't be anything spectacular. Power to Arduino, 230V to/from the relays, wire the push-button and that's it...?

---UPDATE---
I'm not using TimeAlarms anymore and I attached the finished code (Alarm_2.0.ino) in the first post. Alarm.ino is the original attachment mentioned in the OP.

Alarm.ino (8.32 KB)

alarm_2.0.ino (8.51 KB)

I've finished the code, I think. I added pinmodes and changed the Serial.println's to digitalWrite. Now it even fits to this message:

#include <TimeLib.h>
#include <TimeAlarms.h>

AlarmId id;



int WHLON = 8; // Week hour for light on
int WMLON = 0; // Week minute for light on
int WHFON = 8; // Week hour for fan on
int WMFON = 0; // Week minute for fan on
int WHAON = 7; // Week hour for air on
int WMAON = 30; // Week minute for air on

int WHLOFF = 18; // Week hour for light off
int WMLOFF = 30; // Week minute for light off
int WHFOFF = 14; // Week hour for fan off
int WMFOFF = 50; // Week minute for fan off
int WHAOFF = 21; // Week hour for air off
int WMAOFF = 30; // Week minute for air off

int WEHLON = 8; // Weekend hour for light on
int WEMLON = 30; // Weekend minute for light on
int WEHFON = 8; // Weekend hour for fan on
int WEMFON = 0; // Weekend minute for fan on
int WEHAON = 8; // Weekend hour for air on
int WEMAON = 30; // Weekend minute for air on

int WEHLOFF = 18; // Weekend hour for light off
int WEMLOFF = 30; // Weekend minute for light off
int WEHFOFF = 8; // Weekend hour for fan off
int WEMFOFF = 0; // Weekend minute for fan off
int WEHAOFF = 22; // Weekend hour for air off
int WEMAOFF = 00; // Weekend minute for air off

//
//push-button
int buttonPin = 2;         // the number of the input pin
int fanPin = 13;       // the number of the output pin
int airPin = 12;
int lightPin = 11;

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 500;   // the debounce time, increase if the output flickers
//END push-button
//

void setup() {
  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor

  setTime(8, 29, 0, 1, 1, 16); // set time to Saturday 8:29:00am Jan 1 2016, comment this line out after first run

  pinMode(buttonPin, INPUT); //push-button
  pinMode(fanPin, OUTPUT); 
  pinMode(airPin, OUTPUT); 
  pinMode(lightPin, OUTPUT);

  // create the alarms, to trigger at specific times
  Alarm.alarmRepeat(dowMonday, WHLON, WMLON, 00, Mondaylighton);
  Alarm.alarmRepeat(dowMonday, WHLOFF, WMLOFF, 00, Mondaylightoff);
  Alarm.alarmRepeat(dowMonday, WHFON, WMFON, 00, Mondayfanon);
  Alarm.alarmRepeat(dowMonday, WHFOFF, WMFOFF, 00, Mondayfanoff);
  Alarm.alarmRepeat(dowMonday, WHAON, WMAON, 00, Mondayairon);
  Alarm.alarmRepeat(dowMonday, WHAOFF, WMAOFF, 00, Mondayairoff);

  Alarm.alarmRepeat(dowTuesday, WHLON, WMLON, 00, Tuesdaylighton);
  Alarm.alarmRepeat(dowTuesday, WHLOFF, WMLOFF, 00, Tuesdaylightoff);
  Alarm.alarmRepeat(dowTuesday, WHFON, WMFON, 00, Tuesdayfanon);
  Alarm.alarmRepeat(dowTuesday, WHFOFF, WMFOFF, 00, Tuesdayfanoff);
  Alarm.alarmRepeat(dowTuesday, WHAON, WMAON, 00, Tuesdayairon);
  Alarm.alarmRepeat(dowTuesday, WHAOFF, WMAOFF, 00, Tuesdayairoff);

  Alarm.alarmRepeat(dowWednesday, WHLON, WMLON, 00, Wednesdaylighton);
  Alarm.alarmRepeat(dowWednesday, WHLOFF, WMLOFF, 00, Wednesdaylightoff);
  Alarm.alarmRepeat(dowWednesday, WHFON, WMFON, 00, Wednesdayfanon);
  Alarm.alarmRepeat(dowWednesday, WHFOFF, WMFOFF, 00, Wednesdayfanoff);
  Alarm.alarmRepeat(dowWednesday, WHAON, WMAON, 00, Wednesdayairon);
  Alarm.alarmRepeat(dowWednesday, WHAOFF, WMAOFF, 00, Wednesdayairoff);

  Alarm.alarmRepeat(dowThursday, WHLON, WMLON, 00, Thursdaylighton);
  Alarm.alarmRepeat(dowThursday, WHLOFF, WMLOFF, 00, Thursdaylightoff);
  Alarm.alarmRepeat(dowThursday, WHFON, WMFON, 00, Thursdayfanon);
  Alarm.alarmRepeat(dowThursday, WHFOFF, WMFOFF, 00, Thursdayfanoff);
  Alarm.alarmRepeat(dowThursday, WHAON, WMAON, 00, Thursdayairon);
  Alarm.alarmRepeat(dowThursday, WHAOFF, WMAOFF, 00, Thursdayairoff);

  Alarm.alarmRepeat(dowFriday, WHLON, WMLON, 00, Fridaylighton);
  Alarm.alarmRepeat(dowFriday, WHLOFF, WMLOFF, 00, Fridaylightoff);
  Alarm.alarmRepeat(dowFriday, WHFON, WMFON, 00, Fridayfanon);
  Alarm.alarmRepeat(dowFriday, WHFOFF, WMFOFF, 00, Fridayfanoff);
  Alarm.alarmRepeat(dowFriday, WHAON, WMAON, 00, Fridayairon);
  Alarm.alarmRepeat(dowFriday, WHAOFF, WMAOFF, 00, Fridayairoff);

  Alarm.alarmRepeat(dowSaturday, WEHLON, WEMLON, 00, Saturdaylighton);
  Alarm.alarmRepeat(dowSaturday, WEHLOFF, WEMLOFF, 00, Saturdaylightoff);
  //  Alarm.alarmRepeat(dowSaturday,WEHFON,WEMFON,00,Saturdayfanon);
  //  Alarm.alarmRepeat(dowSaturday,WEHFOFF,WEMFOFF,00,Saturdayfanoff);
  Alarm.alarmRepeat(dowSaturday, WEHAON, WEMAON, 00, Saturdayairon);
  Alarm.alarmRepeat(dowSaturday, WEHAOFF, WEMAOFF, 00, Saturdayairoff);

  Alarm.alarmRepeat(dowSunday, WEHLON, WEMLON, 00, Sundaylighton);
  Alarm.alarmRepeat(dowSunday, WEHLOFF, WEMLOFF, 00, Sundaylightoff);
  //  Alarm.alarmRepeat(dowSunday,WEHFON,WEMFON,00,Sundayfanon);
  //  Alarm.alarmRepeat(dowSunday,WEHFOFF,WEMFOFF,00,Sundayfanoff);
  Alarm.alarmRepeat(dowSunday, WEHAON, WEMAON, 00, Sundayairon);
  Alarm.alarmRepeat(dowSunday, WEHAOFF, WEMAOFF, 00, Sundayairoff);


}

void loop() {
  digitalClockDisplay();
  Alarm.delay(0);


//
//Push-button as a switch for switching the fan manually on/off
  reading = digitalRead(buttonPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();
  }

  digitalWrite(fanPin, state);

  previous = reading;
//END push-button
//
}

// functions to be called when an alarm triggers:
void Mondaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Mondaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Mondayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Mondayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Mondayairon() {
  digitalWrite(airPin, HIGH);
}
void Mondayairoff() {
  digitalWrite(airPin, LOW);
}

void Tuesdaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Tuesdaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Tuesdayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Tuesdayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Tuesdayairon() {
  digitalWrite(airPin, HIGH);
}
void Tuesdayairoff() {
  digitalWrite(airPin, LOW);
}

void Wednesdaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Wednesdaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Wednesdayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Wednesdayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Wednesdayairon() {
  digitalWrite(airPin, HIGH);
}
void Wednesdayairoff() {
  digitalWrite(airPin, LOW);
}

void Thursdaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Thursdaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Thursdayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Thursdayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Thursdayairon() {
  digitalWrite(airPin, HIGH);
}
void Thursdayairoff() {
  digitalWrite(airPin, LOW);
}

void Fridaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Fridaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Fridayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Fridayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Fridayairon() {
  digitalWrite(airPin, HIGH);
}
void Fridayairoff() {
  digitalWrite(airPin, LOW);
}

void Saturdaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Saturdaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Saturdayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Saturdayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Saturdayairon() {
  digitalWrite(airPin, HIGH);
}
void Saturdayairoff() {
  digitalWrite(airPin, LOW);
}

void Sundaylighton() {
  digitalWrite(lightPin, HIGH);
}
void Sundaylightoff() {
  digitalWrite(lightPin, LOW);
}
void Sundayfanon() {
  digitalWrite(fanPin, HIGH);
}
void Sundayfanoff() {
  digitalWrite(fanPin, LOW);
}
void Sundayairon() {
  digitalWrite(airPin, HIGH);
}
void Sundayairoff() {
  digitalWrite(airPin, LOW);
}




void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}

void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

It's late here and I'm on the way to bed, but I can make one suggestion.
Change this:-long time = 0;        // the last time the output pin was toggledto this:-unsigned long time = 0;        // the last time the output pin was toggled
'long' isn't large enough to store the value of 'millis()', and will lead to problems in your long-running code.

There must be another way to do that time-check. Soudns a bit too complicated to use a million billion digit long number when measuring numbers up to 2000'ish...
My reference: millis() - Arduino Reference

I believe I found a solution to simplify this. This is going to be an alarm timer, so adding a 500ms delay to the code won't matter. That way if I hold the button, the state of the fanPin will toggle LOW/HIGH in 500ms intervals, right?

Sucks that I don't have my hardware yet, but does this look like it has a chance to work?

void loop() {
  digitalClockDisplay();
  Alarm.delay(500);


//
//Push-button as a switch for switching the fan manually on/off
  reading = digitalRead(buttonPin);


  if (reading == HIGH)
    {
      if (digitalRead(fanPin == HIGH)
        digitalWrite(fanPin, LOW);
       else
        digitalWrite(fanPin, HIGH);
     }

  

//END push-button
//
}

Soudns a bit too complicated to use a million billion digit long number when measuring numbers up to 2000'ish...

You are using one variable or constant, declared unsigned long, to represent a time period. That is not complicated.

That way if I hold the button, the state of the fanPin will toggle LOW/HIGH in 500ms intervals, right?

Not with that snippet.

OK, I admit, the "complicated" is very much a matter of who do you ask. Correction: sounds a bit too complicated to me.

"Not with that snippet."
Please tell me why not. I'll write my thoughts, so you can correct me more easily:

Alarm.delay(500); // The program stops here for 500ms


  reading = digitalRead(buttonPin); // This line reads the state of push-button's pin


  if (reading == HIGH) // If the button is pressed, do the next bit between the {} thingies (what are those called...?)
    {
      if (digitalRead(fanPin == HIGH)  // if the fan is ON
        digitalWrite(fanPin, LOW); //then turn it OFF
       else // if the fan is NOT ON
        digitalWrite(fanPin, HIGH); // turn it ON 
     }

What did I do wrong?

Why do you think you can perform digitalRead() and digitalWrite() on the same pin?

Have you declared the pin as INPUT or OUTPUT elsewhere?

Hint: digitalWrite(pin,HIGH) will turn on the input pullup resistor of a pin declared as INPUT.

"Why do you think you can perform digitalRead() and digitalWrite() on the same pin?"

Because why not? I'm a newbie, I don't know what not to think. That's why I did a bit of googling beforehand and found this: How to find out output pin state? - Syntax & Programs - Arduino Forum
Is this last post by RoyK in the link false?

Yes, I've declared the pin as OUTPUT:

.
.
.
int buttonPin = 2;         // the number of the input pin
int fanPin = 13;       // the number of the output pin
int airPin = 12;
int lightPin = 11;

.
.
.
void setup() {
.
.
.

  pinMode(buttonPin, INPUT); //push-button
  pinMode(fanPin, OUTPUT); 
  pinMode(airPin, OUTPUT); 
  pinMode(lightPin, OUTPUT);

The post is wrong.

You can't read the actual state of an output pin, except using another input pin.

digitalRead() from an output pin will return only what the processor has requested. Those are not necessarily the same and it is not good programming practice to assume so. As I already pointed out, digitalWrite to an input pin does do something, but can result in unexpected behavior.

Furthermore, if you are concerned about system reliability, you will probably want some means to know that when the Arduino commands the fan on, it actually is on. Since there is an AC system in between, that is not so easy.

"You can't read the actual state of an output pin, except using another input pin."

Thank you for the knowledge and solution. One more wire it is.

I'm going to assume that if there's a control signal sent to the fan relay, the fan is then on.

Why do you have a special function for light on, light off, fan on, fan off etc for each day of the week?
ie Saturdaylighton, Sundaylighton etc.
Why not just 'lightOn', 'lightOff' etc, called every day as needed? You have seven times the required functions.

Don't read the value of an output pin that your program controls, and especially don't waste another pin for reading it.
If you want to toggle the fan pin, just store the state in a boolean variable, then toggle the fan on/off like this:-

fanState ^= 1;  // Toggles the state
digitalWrite(fanPin, fanState);

Declare 'fanState' as a global variable. And don't forget to change the value of 'fanState' appropriately in any functions that turn the fan on and off automatically.

You seem to have your own ideas on debouncing a button press, so I'll leave you to that. Sometimes trial-and-error is the best way to learn.

Ok, good morning after a good nights sleep.

Regarding the debouncing, I didn't understand the example code correctly, so I wrote my own "worse, I knew, but suitable for this project) code for it. Today I decided to improve it and I started to write my own edge-detecting code and I ended up with the same result, but without the flicker-filter. I reread the example code and description, and I understood it now, so I'm using it now. I also changed the code so the button is grounding and the pull-up resistor is turned on. I changed the debounce time to 3000, so I have to press the button for three seconds for the switch to activate, am I right?
Link to the tutorial I'm talking about: https://www.arduino.cc/en/tutorial/switch

"Why do you have a special function for light on, light off, fan on, fan off etc for each day of the week?
ie Saturdaylighton, Sundaylighton etc.
Why not just 'lightOn', 'lightOff' etc, called every day as needed? You have seven times the required functions."

This is what I said in the first post. I don't like my original approach either. I can imagine two more ways to approach the task. One is (in a pseudo-like code) "is it monday? is it 8 hours? is it 30 minutes? If yes, turn on the lights"... And the same question for every day and time. That's a bit more simple than my original version.

Did I do the weekday() - queries correctly?
And now we are not using TimeAlarms anymore, so I could take out the "#include <TimeAlarms.h>" line and change "Alarm.delay" to "delay", right?

Again, huge thanks for helping!

#include <TimeLib.h>
#include <TimeAlarms.h>

AlarmId id;


int WHLON = 8; // Week hour for light on
int WMLON = 0; // Week minute for light on
int WHFON = 8; // Week hour for fan on
int WMFON = 0; // Week minute for fan on
int WHAON = 7; // Week hour for air on
int WMAON = 30; // Week minute for air on

int WHLOFF = 18; // Week hour for light off
int WMLOFF = 30; // Week minute for light off
int WHFOFF = 14; // Week hour for fan off
int WMFOFF = 50; // Week minute for fan off
int WHAOFF = 21; // Week hour for air off
int WMAOFF = 30; // Week minute for air off

int WEHLON = 8; // Weekend hour for light on
int WEMLON = 30; // Weekend minute for light on
int WEHFON = 8; // Weekend hour for fan on
int WEMFON = 0; // Weekend minute for fan on
int WEHAON = 8; // Weekend hour for air on
int WEMAON = 30; // Weekend minute for air on

int WEHLOFF = 18; // Weekend hour for light off
int WEMLOFF = 30; // Weekend minute for light off
int WEHFOFF = 8; // Weekend hour for fan off
int WEMFOFF = 0; // Weekend minute for fan off
int WEHAOFF = 22; // Weekend hour for air off
int WEMAOFF = 00; // Weekend minute for air off



int buttonPin = 2;         // the number of the input pin
int fanPin = 13;       // the number of the output pin
int airPin = 12;
int lightPin = 11;

int fanState = 0;
int airState = 0;
int lightState = 0;

int reading = 0;
int previous = 0;
unsigned long time = 0;         // the last time the output pin was toggled
long debounce = 3000;   // the debounce time, increase if the output flickers


void setup() {
  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor

  setTime(8, 29, 0, 1, 1, 16); // set time to Saturday 8:29:00am Jan 1 2016, comment this line out after first run

  pinMode(buttonPin, INPUT); //push-button
  digitalWrite(buttonPin, HIGH); //turn on the pull-up resistor
  pinMode(fanPin, OUTPUT);
  pinMode(airPin, OUTPUT);
  pinMode(lightPin, OUTPUT);

}

void loop()
{
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display


  reading = digitalRead(buttonPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == LOW && previous == HIGH && millis() - time > debounce) {
    fanState ^= 1;
    time = millis();
  }

  digitalWrite(fanPin, fanState);
  digitalWrite(airPin, airState);
  digitalWrite(lightPin, lightState);

  previous = reading;


/////////FAN ON/////////////
  if ((weekday()) == 1 || (weekday()) == 7) // If it's sunday or saturday
  {
    if ((hour()) == WEHFON && (minute()) == WEMFON) // Time-check
      fanState = 1; //Turn on the fan
  }
  else // It must not be monday - friday then
  {
    if ((hour()) == WHFON && (minute()) == WMFON) // Time-check
      fanState = 1; //Turn on the fan
  }

  
/////////FAN OFF/////////////
    if ((weekday()) == 1 || (weekday()) == 7) // If it's sunday or saturday
  {
    if ((hour()) == WEHFOFF && (minute()) == WEMFOFF) // Time-check
      fanState = 0; //Turn off the fan
  }
  else // It must not be monday - friday then
  {
    if ((hour()) == WHFOFF && (minute()) == WMFOFF) // Time-check
      fanState = 0; //Turn off the fan
  }


/////////AIR ON/////////////
  if ((weekday()) == 1 || (weekday()) == 7) // If it's sunday or saturday
  {
    if ((hour()) == WEHAON && (minute()) == WEMAON) // Time-check
      airState = 1; //Turn on the air
  }
  else // It must not be monday - friday then
  {
    if ((hour()) == WHAON && (minute()) == WMAON) // Time-check
      airState = 1; //Turn on the air
  }

  
/////////AIR OFF/////////////
    if ((weekday()) == 1 || (weekday()) == 7) // If it's sunday or saturday
  {
    if ((hour()) == WEHAOFF && (minute()) == WEMAOFF) // Time-check
      airState = 0; //Turn off the air
  }
  else // It must not be monday - friday then
  {
    if ((hour()) == WHAOFF && (minute()) == WMAOFF) // Time-check
      airState = 0; //Turn off the air
  }


/////////LIGHT ON/////////////
  if ((weekday()) == 1 || (weekday()) == 7) // If it's sunday or saturday
  {
    if ((hour()) == WEHLON && (minute()) == WEMLON) // Time-check
      lightState = 1; //Turn on the light
  }
  else // It must not be monday - friday then
  {
    if ((hour()) == WHLON && (minute()) == WMLON) // Time-check
      lightState = 1; //Turn on the light
  }

  
/////////LIGHT OFF/////////////
    if ((weekday()) == 1 || (weekday()) == 7) // If it's sunday or saturday
  {
    if ((hour()) == WEHLOFF && (minute()) == WEMLOFF) // Time-check
      lightState = 0; //Turn off the light
  }
  else // It must not be monday - friday then
  {
    if ((hour()) == WHLOFF && (minute()) == WMLOFF) // Time-check
      lightState = 0; //Turn off the light
  }


  
}







void digitalClockDisplay() {
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}

void printDigits(int digits) {
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

I can imagine an easier way, and this is how I would like to do it: "On monday 8.30 turn the lights on". But i believe it would require event-driven programming, which is completely opposite that Arduino IDE uses.
umm... am I right?

Instead of this:-

pinMode(buttonPin, INPUT); //push-button
digitalWrite(buttonPin, HIGH); //turn on the pull-up resistor

This is better:-pinMode(buttonPin,INPUT_PULLUP);

And I'd move this:-   previous = reading;into this:-

if (reading == LOW && previous == HIGH && millis() - time > debounce)
{
    fanState ^= 1;
    time = millis();
}

Personally, I'd write to the pin at the same time, too.

And you really should do the display timing with a 'millis()'-based delay, not 'delay()'. (Now that you've learned the basics, that's not hard to do.) Then, after making your debounce value more reasonable, you'll get an immediate response when you press the button. You shouldn't need more than 100mS to 250mS as a maximum for a debounce delay. Less if you're quick at removing your finger. 3 seconds is unnecessary, and it could be up to 4 seconds with your 1 second blocking delay for display updates.

Definitely get rid of this:-Alarm.delay(1000); // wait one second between clock displayWhen used with "TimeAlarms", it blocks everything except the alarm stuff. When used without, it's just plain blocking, and might as well be 'delay()' as you suggested.

As you mentioned, since you're no longer using "TimeAlarms", get rid of everything related.
If I compile with "TimeAlarms" included, with your code using 'Alarm.delay(1000)', 6790 bytes of flash memory and 387 bytes of SRAM are used.
If I compile without "TimeAlarms", just using 'delay(1000)', 5798 bytes of flash memory and 319 bytes of SRAM are used.
(But as I suggested, get rid of all blocking delays and you'll have much nicer operation.)

There might be more, but it's getting late here and I have a few things to do. The above will get you a few steps closer to finished.

Are you really going to all of this trouble just to grow chillis. :smiley:

OldSteve:
Instead of this:-

pinMode(buttonPin, INPUT); //push-button

digitalWrite(buttonPin, HIGH); //turn on the pull-up resistor


This is better:-`pinMode(buttonPin,INPUT_PULLUP);`

And I'd move this:-`   previous = reading;`into this:-

if (reading == LOW && previous == HIGH && millis() - time > debounce)
{
    fanState ^= 1;
    time = millis();
}



Personally, I'd write to the pin at the same time, too.

-I actually stumbled upon that INPUT_PULLUP myself also. Seems smarter. Thank you.
-"Previous" will be moved, thank you for pointing it out.
-Personally I like when all the writes are in one place. :slight_smile:
-About the delay, I will be removing all the TimeAlarm stuff. At first I didn't care about having a 1s delay in the code, but maybe I'll tweak it just for fun.
-I actually want the button to have ~3s delay, so i have to press it long for it to work. In case one of my dogs steps on the button etc...

"Are you really going to all of this trouble just to grow chillis. :D"

Well I coul've bought a timer for a bit cheaper and without the effort of making everything myself. :smiley:

Sivonen:
-I actually want the button to have ~3s delay, so i have to press it long for it to work. In case one of my dogs steps on the button etc...

Fair enough, if you actually want that behaviour.

"Are you really going to all of this trouble just to grow chillis. :D"

Well I coul've bought a timer for a bit cheaper and without the effort of making everything myself. :smiley:

I just meant that it had crossed my mind that it might be a different sort of plant.

Anyway, I agree that often we can buy something more cheaply that would do what we want, but where's the fun in that?

OldSteve:
Personally, I'd write to the pin at the same time, too.

-Personally I like when all the writes are in one place. :slight_smile:

I was just looking at this from a perfectionist point of view, assuming the 1 second delay was going to stay. There was a delay between setting the state and writing it to the pin. Otherwise, the way you have it is fine. :slight_smile:

Haha, no I'm not growing any funny-tobacco. :smiley: :grinning:

Pics

Sivonen:
Haha, no I'm not growing any funny-tobacco. :smiley: :grinning:

Pics

So I see, unless the leaf shape has changed considerably in recent times.

And again I didn't get how the button-switch debounce works. How hard can it be... :o
It doesn't require me to hold the button for the set debounce time -say 200ms-, it just won't read the next press until after 200ms.
So if I set the debounce time to 3000ms, it just turns on/off on a touch, but won't work again until 3000ms is passed.
That's not how I intended it to be.
I want it to work like a car stereo or playstation 2. Hold the power button for three seconds and it'll trigger.

New piece of code:

  current = digitalRead(buttonPin);

  // if the button state changes to pressed, remember the start time
  if (current == LOW && previous == HIGH && (millis() - firstTime) > 200) {
    firstTime = millis();
  }

  millis_held = (millis() - firstTime);

  // This if statement is a basic debouncing tool, the button must be pushed for at least
  // 100 milliseconds in a row for it to be considered as a push.
  if (millis_held > 3000)
  {
    fanState ^= 1;
  }

  previous = current;

Source CLICK

And the clock, without delaying the whole program.

void loop()
{
  if(second() != prevtime)
  {
  prevtime = second();
  digitalClockDisplay();
  }

jremington:
You can't read the actual state of an output pin, except using another input pin.

Your claim is contradicted by the ATmega328P datasheet.