In the previous video 6 we wrote code to have a day & night cycle, operated from a switch panel with a toggle switch and an indicator LED. Our ‘virtual customer’, the Tech Company, was happy with our design. It’s on the market and the module is selling well. Now they see potential for a unit that not just controls one light group … they want to have one that controls multiple light groups. Can we make a prototype again? Yes we can!
The User Requirement Specifications are:
‘cycle on/off’ toggle switch
- We have the indicator LED that shows if the cycle is on/off
- 3 light groups should be switched in a day/night cycle
- The lights should not switch on and off all at the same time, that would not look realistic. The sequence they propose is:
- house lights on
- station lights on
- street lights on
- house lights off (it really is night now)
- house lights on (it is morning now)
- street lights off
- house lights off
- station lights off
OK … sounds doable. Read on below the video …
Let’s start with the code we had in video 6 and work from there. We add a series of 6 #defines to specify the delay times, all in seconds. We add 2 #defines for the output pins of the house lights and station lights. Then let’s write the lights on/off sequence as specified, with the delays in between:
// USER CONFIGURATION
#define NIGHT_TIME 3 // [s] (all timers use seconds)
#define DAY_TIME 3
#define TIME1 1 // play with these times
#define TIME2 1 // to get the sequence you like
#define TIME3 2
#define TIME4 1
#define TIME5 1
#define TIME6 1
// END USER CONFIGURATION
#define CYCLE_ON_OFF_SWITCH 2 // input pin for on/off toggle switch
#define LIGHTS_A 8 // output pin to FET module A
#define LIGHTS_B 9 // output pin to FET module B
#define LIGHTS_C 10 // output pin to FET module C
#define PANEL_LED A5 // output pin to switch panel LED
void setup() {
pinMode(CYCLE_ON_OFF_SWITCH, INPUT_PULLUP);
pinMode(LIGHTS_A, OUTPUT);
pinMode(LIGHTS_B, OUTPUT);
pinMode(LIGHTS_C, OUTPUT);
pinMode(PANEL_LED, OUTPUT);
}
void loop() {
if (digitalRead(CYCLE_ON_OFF_SWITCH ) == LOW) { // cycle switch on
digitalWrite(PANEL_LED, HIGH);
digitalWrite(LIGHTS_A, HIGH); // it is evening now
delay(TIME1 * 1000);
digitalWrite(LIGHTS_B, HIGH);
delay(TIME2 * 1000);
digitalWrite(LIGHTS_C, HIGH);
delay(TIME3 * 1000);
digitalWrite(LIGHTS_A, LOW); // it is night now
delay(NIGHT_TIME * 1000);
digitalWrite(LIGHTS_A, HIGH); // it is morning now
delay(TIME4 * 1000);
digitalWrite(LIGHTS_C, LOW);
delay(TIME5 * 1000);
digitalWrite(LIGHTS_A, LOW);
delay(TIME6 * 1000);
digitalWrite(LIGHTS_B, LOW); // it is day now
delay(DAY_TIME * 1000);
}
else {
digitalWrite(PANEL_LED, LOW); // cycle switch off
}
}
Time to test. Yes … this works OK. Amazing how much we can do already with just a handful different statements: digitalRead/Write, if/else, delay().
This is nice, although after some time it starts to get somewhat predictable. How can we make it more varied? Simple … we can use the random(min,max) command.
x = random(2, 7);
This command gives variable ‘x’ a random number with a minimum of 2 and with a maximum of 6. Yes, 6 … strangely enough the maximum number being generated is the stated upper limit – 1.
delay(random(1, 5) * 1000);
This gives us a delay varying from 1 till 4 seconds, which is what we are going to use in the test phase. We are of course going to use two #defines so we can easily configure the min / max values used in the random statement. The code now looks like this:
// USER CONFIGURATION
#define NIGHT_TIME 4 // [s]
#define DAY_TIME 4
#define MIN_TIME 1 // [s] play with these times
#define MAX_TIME 5 // [s] to get the sequence you like
// END USER CONFIGURATION
#define CYCLE_ON_OFF_SWITCH 2 // input pin for on/off toggle switch
#define LIGHTS_A 8 // output pin to FET module A
#define LIGHTS_B 9 // output pin to FET module B
#define LIGHTS_C 10 // output pin to FET module C
#define PANEL_LED A5 // output pin to switch panel LED
void setup() {
pinMode(CYCLE_ON_OFF_SWITCH, INPUT_PULLUP);
pinMode(LIGHTS_A, OUTPUT);
pinMode(LIGHTS_B, OUTPUT);
pinMode(LIGHTS_C, OUTPUT);
pinMode(PANEL_LED, OUTPUT);
}
void loop() {
if (digitalRead(CYCLE_ON_OFF_SWITCH ) == LOW) { // cycle switched on
digitalWrite(PANEL_LED, HIGH);
digitalWrite(LIGHTS_A, HIGH);
delay(random(MIN_TIME, MAX_TIME) * 1000);
digitalWrite(LIGHTS_B, HIGH);
delay(random(MIN_TIME, MAX_TIME) * 1000);
digitalWrite(LIGHTS_C, HIGH);
delay(random(MIN_TIME, MAX_TIME) * 1000);
digitalWrite(LIGHTS_A, LOW);
delay(NIGHT_TIME * 1000);
digitalWrite(LIGHTS_A, HIGH);
delay(random(MIN_TIME, MAX_TIME) * 1000);
digitalWrite(LIGHTS_C, LOW);
delay(random(MIN_TIME, MAX_TIME) * 1000);
digitalWrite(LIGHTS_A, LOW);
delay(random(MIN_TIME, MAX_TIME) * 1000);
digitalWrite(LIGHTS_B, LOW);
delay(DAY_TIME * 1000);
}
else {
digitalWrite(PANEL_LED, LOW); // cycle switched off
}
}
The test looks good. On to the next project. As expected, our virtual customer, the Tech Company, likes to have another way of configuring the day and night times. The way it is now, the end user needs to tinker in the code and then upload it. They want to ship the units with the code pre-installed, which means the timer values need to be changed via some sort of user interface. We’re going to try different ways to accomplish that in the next couple of videos.
— 0 —
Why use #define instead of const?
LikeLike
We have not covered the use of variables yet, and what a byte is, or an integer or a long. There is a whole lot of discussion among ‘code purists’ on when / why a constant is better to use and when a #define will do. The arguments for or against are quite technical and are too far away from the intended audience of this video series.
LikeLike