/*
Seems to kinda work.
Pressing the "Play" buttonon the IR remote starts the
Traffic cycle. Now need to find a way to stop the cycle
until the "Play" button is pressed again.
Traffic LEDs cycle (tcycles) times then wait for a time
till the cycle is complete (tcompCycl).
After the Traffic cycle is complete the servo lowers
the WigWag arms and the WiWag LEDs cycle (wcycles) times
but start only after the traffic cycle is completed.
Should try to find a way to make the traffic and
WigWag cycle independantly ???
There is a randomly variable Pause cycle between the end
of the WigWag cycle and the start of the next traffic cycle.
A 5 minute wait is 300000 millis.
*/
/*
Pin codes for WokWi IR remote:
Power 162, Menu 226, Test 34, Plus 2, Return 194, Rewind 224
Play 168, FFwd 144, 0 104, Minus 152, Clear 176, 1 48
2 24, 3 122, 4 16, 5 56, 6 90, 7 66, 8 74, 9 82
*/
#include <Servo.h>
#include <IRremote.h>
#define IR_RECEIVE_PIN 12 // IR data is on pin 12
#define IR_BUTTON_2 24 // code from button 2 is "24"
#define IR_BUTTON_5 56 // code from button 2 is "24"
#define IR_BUTTON_Play 168 // code from button 2 is "24"
#define wLED_R_PIN 7 // define the WigWag Rt LED to be on pin 7
#define wLED_L_PIN 8 // define the WigWag Lt LED to be on pin 8
#define tLED_1_PIN 9 // define the Red LED to be on pin 9
#define tLED_2_PIN 10 // define the Yel LED to be on pin 10
#define tLED_3_PIN 11 // define the Grn LEDs to be on pin 11
byte tstep = 0; // init a variable for the traffic step count
byte tcycle = 1; // init a variable for the traffic cycle counter
byte tcycles = 5; // init a variable for the traffic number of cycles
unsigned long tONtime = 1000; // init a variable for the "ON" time for the traffic LEDs
unsigned long tprevmillis = 0; // init a variable to preserve a time stamp of traffic LEDs
unsigned long tstrtFlsh = 0; // init a variable to preserve a time stamp for the start of the traffic Flash cycle
unsigned long tendFlsh = 0; // init a variable to preserve a time stamp for the end of the traffic Flash cycle
unsigned long tcompCycl = 18000; // set a time for the traffic complete cycle
byte wstep = 0; // init a variable for the WigWag step count
byte wcycle = 1; // init a variable for the WigWag cycle counter
byte wcycles = 10; // init a variable for the number of WigWag cycles
unsigned long wONtime = 500; // init a variable for the "ON" time for the LEDs
unsigned long wprevmillis = 0; // init a variable to preserve a time stamp of WigWag LEDs
unsigned long wstrtFlsh = 0; // init a variable to preserve a time stamp for the start of the WigWag Flash cycle
unsigned long wendFlsh = 0; // init a variable to preserve a time stamp for the end of the WigWag Flash cycle
unsigned long wcompCycl = 8000; // set a time for the complete WigWag cycle
long spin = 0; // init a variable for spinning your wheels
unsigned long pprevmillis = 0; // init a variable to preserve a time stamp for the end of the pause cycle
unsigned long strtWait; // init a variable to preserve a time stamp to pass to the wait function
unsigned long compCycl; // init a variable for a complete cycle to pass to the wait function
int servpos = 0; // init a variable to store the servo pos'n
Servo myservo; // create servo object to control a servo for WiWag arm
class tLed // define class for a traffic LED
{
private:
byte tpin; // init a variable for which pin (LED) to address
public:
tLed(byte tpin) // init an LED to a pin
{
// Use 'this->' to make the difference between the
// 'pin' attribute of the class and the
// local variable 'pin' created from the parameter.
this->tpin = tpin;
tinit();
}
void tinit()
{
pinMode(tpin, OUTPUT); // set the LED pins to "OUTPUT" mode
// Always try to avoid duplicate code.
// Instead of writing digitalWrite(pin, LOW) here,
// call the function off() which already does that
toff();
}
void ton() // function to turn an LED "ON"
{
do
{
digitalWrite(tpin, HIGH);
} while (millis() - tprevmillis <= tONtime);
tprevmillis = millis(); // preserve this time stamp of traffic LEDs
}
void toff() // function to turn an LED "OFF"
{
digitalWrite(tpin, LOW);
}
}; // don't forget the semicolon at the end of the class
// Create your objects in the global scope so you can
// get access to them in the setup() and loop() functions
tLed tled1(tLED_1_PIN); // make an object for the Red LED
tLed tled2(tLED_2_PIN); // make an object for the Yel LED
tLed tled3(tLED_3_PIN); // make an object for the Grn LED
class wLed // define class for a WigWag LED
{
private:
byte wpin; // init a variable for which pin (LED) to address
public:
wLed(byte wpin) // init an LED to a pin
{
// Use 'this->' to make the difference between the
// 'pin' attribute of the class and the
// local variable 'pin' created from the parameter.
this->wpin = wpin;
winit();
}
void winit()
{
pinMode(wpin, OUTPUT); // set the LED pins to "OUTPUT" mode
// Always try to avoid duplicate code.
// Instead of writing digitalWrite(pin, LOW) here,
// call the function off() which already does that
woff();
}
void won() // function to turn an LED "ON"
{
do
{
digitalWrite(wpin, HIGH);
} while (millis() - wprevmillis <= wONtime);
wprevmillis = millis(); // preserve this time stamp of WigWag LEDs
}
void woff() // function to turn an LED "OFF"
{
digitalWrite(wpin, LOW);
}
}; // don't forget the semicolon at the end of the class
// Create your objects in the global scope so you can
// get access to them in the setup() and loop() functions
wLed wled1(wLED_R_PIN); // make an object for the Right LED
wLed wled2(wLED_L_PIN); // make an object for the Left LED
void setup()
{
// Serial.begin(115200);
// Serial.println(F("\nStart"));
IrReceiver.begin(IR_RECEIVE_PIN); // init IR rcvr to get data on pin 12
myservo.attach(6); // attaches the servo on pin 6 to the servo object
/*
if analog input pin 5 is unconnected, random analog
noise will cause the call to randomSeed() to generate
different seed numbers each time the sketch runs.
randomSeed() will then shuffle the random function.
*/
randomSeed(analogRead(5));
}
void Traffic() // function to flash the traffic LEDs
{
/*
This is the Traffic LED check loop.
Program flow gets here 1st after initializing everything
and doing the "void setup()" function
It then calls the "tLed class".
*/
tstrtFlsh = millis(); // preserve this time stamp of the start of the traffic Flash cycle
for (tcycle = 1; tcycle <= tcycles; tcycle++) // go thru a preset number (tcycles) of traffic Flash cycles
{
for (tstep = 0; tstep <= 3; tstep++) // cycle thru the 3 steps (colours)
{
switch (tstep)
{
case 0:
tled1.ton(); // pass the object to turn the Red LED "ON" to the LED class (tLed)
tled2.toff(); // pass the object to turn the Yel LED "OFF" to the LED class (tLed)
tled3.toff(); // pass the object to turn the Grn LED "OFF" to the LED class (tLed)
break;
case 1:
tled1.toff(); // pass the object to turn the Red LED "OFF" to the LED class (tLed)
tled2.ton(); // pass the object to turn the Yel LED "ON" to the LED class (tLed)
tled3.toff(); // pass the object to turn the Grn LED "OFF" to the LED class (tLed)
break;
case 2:
tled1.toff(); // pass the object to turn the Red LED "OFF" to the LED class (tLed)
tled2.toff(); // pass the object to turn the Yel LED "OFF" to the LED class (tLed)
tled3.ton(); // pass the object to turn the Grn LED "ON" to the LED class (tLed)
break;
default: // need this to turn off Grn LED (3) at the end of the cycle
tled1.toff(); // pass the object to turn the Red LED "OFF" to the LED class (tLed)
tled2.toff(); // pass the object to turn the Yel LED "OFF" to the LED class (tLed)
tled3.toff(); // pass the object to turn the Grn LED "OFF" to the LED class (tLed)
break;
}
}
tendFlsh = millis(); // preserve this time stamp of the end of the traffic Flash cycle
}
strtWait = tstrtFlsh; // set some Traffic variables
compCycl = tcompCycl; // to pass to the wait function
wait(strtWait, compCycl); // call the wait function with these variables
tcycle = 1; // reset the traffic cycle count
// tprevmillis = millis(); // preserve this time stamp of traffic LEDs
wprevmillis = millis(); // preserve this time stamp of WigWag LEDs
// pprevmillis = millis(); // preserve this time stamp of pause cycle
}
void WigWag() // function to flash the WigWag LEDs
{
for (servpos = 90; servpos <= 180; servpos += 1) // set the servo to lower the WigWag arm
{ // goes from 90 degrees to 180 degrees in steps of 1 degree
myservo.write(servpos); // tell servo to go to position in variable 'servpos'
delay(15); // waits 15ms for the servo to reach the position
}
wprevmillis = millis(); // preserve this time stamp of WigWag LEDs
/*
This is the WigWag LED check loop.
Program flow gets here 2nd after initializing everything
and doing the "void setup()" function
and doing the "tLed class" function.
It then calls the "wLed class".
*/
wstrtFlsh = millis(); // preserve this time stamp of the start of the WigWag Flash cycle
for (wcycle = 1; wcycle <= wcycles; wcycle++) // go thru a preset number (wcycles) of WigWag Flash cycles
{
for (wstep = 0; wstep <= 2; wstep++) // cycle thru the 2 steps
{
switch (wstep)
{
case 0:
wled1.won(); // pass the object to turn the Right LED "ON" to the LED class (wLed)
wled2.woff(); // pass the object to turn the Left LED "OFF" to the LED class (wLed)
break;
case 1:
wled1.woff(); // pass the object to turn the Right LED "OFF" to the LED class (wLed)
wled2.won(); // pass the object to turn the Left LED "ON" to the LED class (wLed)
break;
default: // need this to turn off Left LED at the end of the cycle
wled1.woff(); // pass the object to turn the Right LED "OFF" to the LED class (wLed)
wled2.woff(); // pass the object to turn the Left LED "OFF" to the LED class (wLed)
break;
}
}
wendFlsh = millis(); // preserve this time stamp of the end of the Flash cycle
}
strtWait = wstrtFlsh; // set some WigWag variables
compCycl = wcompCycl; // to pass to the wait function
wait(strtWait, compCycl); // call the wait function with these variables
wcycle = 1; // reset the WigWagcycle count
// wprevmillis = millis(); // preserve this time stamp of WigWag LEDs
// tprevmillis = millis(); // preserve this time stamp of traffic LEDs
pprevmillis = millis(); // preserve this time stamp of pause cycle
for (servpos = 180; servpos >= 90; servpos -= 1) // set the servo to raise the WigWag arm
{ // goes from 180 degrees to 90 degrees
myservo.write(servpos); // tell servo to go to position in variable 'servpos'
delay(15); // waits 15ms for the servo to reach the position
}
}
void Pause() // function to pause for a while
{
// generate a random number between 1000 and 5000
spin = random(1000, 5000); // set a time to pause between WigWag cycle and traffic cycle
do
{
} while ((millis() - pprevmillis) <= spin); // a (pause) loop to pause between WigWag and traffic cycles
// pprevmillis = millis(); // preserve this time stamp of pause cycle
tprevmillis = millis(); // preserve this time stamp of traffic LEDs
}
void wait(unsigned long, unsigned long) // function to wait for a while
{
while (((millis() - strtWait) <= compCycl)) // a loop to wait for one cycle to complete
{
}
}
void loop()
{
if (IrReceiver.decode()) // see if there is data available
{
// IrReceiver.resume();
int command = IrReceiver.decodedIRData.command; // and read the data
switch (command)
{
case IR_BUTTON_Play: // do this if button 2 is pressed
{
tprevmillis = millis(); // preserve this time stamp of traffic LEDs
Traffic(); // call the function to flash the traffic LEDs
WigWag(); // call the function to flash the WigWag LEDs
Pause(); // call the function to pause bewteen cycles
break;
}
case IR_BUTTON_2: // do this if button 2 is pressed
{
IrReceiver.resume();
break;
}
default:
{
// do nothing
}
}
// IrReceiver.resume();
}
}
/*
void loop() // a loop to make the LEDs do what we want
{
Traffic(); // call the function to flash the traffic LEDs
WigWag(); // call the function to flash the WigWag LEDs
Pause(); // call the function to pause bewteen cycles
}
*/
// Serial.print(F("Step = ")); Serial.println(step);
/*
*/