#include <Servo.h>
#include <Arduino.h>
/*Siming Ren, student # 300354794
Final exam. This program perform a sequence of tasks as specified.The tasks involve
the interactions between inputs(push buttons) and outputs (servo motor, LEDs).
*/
// Assign inputs and outputs ports to meaning variable name
int button_a = 2; //Button A to input port 2
int button_b = 12; //Button b to input port 12
int button_c = 8; //Button c to input port 8
int button_d = 7; //Button d to input port 7
int pos = 0; //Store the position used in task 2 where buttonb is involved
//The next four variables are modified inside ISR and therefore declared as volatile type
volatile int amberLED = 5; //Amberled to output port 5
volatile int blueLED = 6; //Amberled to output port 6
volatile int greenLED = 10; //Amberled to output port 10
volatile int redLED = 9; //Amberled to output port 9
volatile int defaultbehavior = 1; //Initialize the default behavior changed in ISR to be on
long randomState; //Stores the random LED port number for task 2
Servo myservo; //servo motor instance declaration
unsigned long previousT; //Previous time used to compute elapsed time for millis()
//This function has the same affect as delay() except it does not use delay(), it takes specified interval as argument and returns nothing
void Delay(long interval){
previousT = millis(); //Get and store previous time using millis()
unsigned long currentT = previousT; //Make current time the same as previous time initially
while (currentT - previousT < interval){ //Continously checking if elapsed time has reached time interval, if so, function returns
currentT = millis(); //Cntinously update current time
}
}
//This function blinks each LED twice
void blinktwice(int lednumber)
{
//this loop blinks argument led twice
for(int i = 0; i < 2; i++)
{
digitalWrite(lednumber,LOW); //led turned on for 150 ms
Delay(250); //Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber,HIGH); //led turned off for 150 ms
Delay(250);//Invoke Delay() funtion defined above with 250 ms interval
}
}
//This function blinks each four times
void blinkfour(int lednumber)
{
//this loop blinks argument led twice
for(int i = 0; i < 4; i++)
{
digitalWrite(lednumber,LOW); //led turned on for 150 ms
Delay(250); //Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber,HIGH); //led turned off for 150 ms
Delay(250);//Invoke Delay() funtion defined above with 250 ms interval
}
}
//This function alternately blinks 2 LEDS three times, in total of six times
void blinkthree(int lednumber1, int lednumber2)
{
//this loop alternately blinks 2 LEDs for three times, each blink sequence count as 1 time
for(int i = 0; i < 3; i++)
{
digitalWrite(lednumber1,LOW); //led turned on for 150 ms
Delay(50); //Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber1,HIGH); //led turned off for 150 ms
Delay(50);//Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber2,LOW); //led turned on for 150 ms
Delay(50); //Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber2,HIGH); //led turned off for 150 ms
Delay(50);//Invoke Delay() funtion defined above with 250 ms interval
}
}
//This function alternately blinks 2 LEDS five times, in total of 10 times
void blinkfive(int lednumber1, int lednumber2)
{
//this loop alternately blinks 2 LEDs for five times, each blink sequence count as 1 time
for(int i = 0; i < 5; i++)
{
digitalWrite(lednumber1,LOW); //led turned on for 150 ms
Delay(50); //Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber1,HIGH); //led turned off for 150 ms
Delay(50);//Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber2,LOW); //led turned on for 150 ms
Delay(50); //Invoke Delay() funtion defined above with 250 ms interval
digitalWrite(lednumber2,HIGH); //led turned off for 150 ms
Delay(50);//Invoke Delay() funtion defined above with 250 ms interval
}
}
//ISR: This ISR is the definition of the rising edge triggered interrupt of pushbutton A
void defaultstatetrigger(){
myservo.write(145); //Move servo to position 145
if (defaultbehavior == 1){ //If default is on currently, disable it when rising edge is detected
defaultbehavior = 0;
} else{
defaultbehavior = 1; //If default is off currently, enable it when rising edge is detected
}
}
void setup() {
// put your setup code here, to run once:
//setup digital input pins for the push buttons
pinMode(button_a, INPUT);
pinMode(button_b, INPUT);
pinMode(button_c, INPUT);
pinMode(button_d, INPUT);
// setup digital output pins for the LEDs
pinMode(amberLED, OUTPUT);
pinMode(blueLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(redLED, OUTPUT);
myservo.attach(11); //attach pin 11 as the servo control port
attachInterrupt(0,defaultstatetrigger,RISING);
}
void loop() {
//Turn off all LEDs initially
digitalWrite(amberLED,HIGH);
digitalWrite(blueLED,HIGH);
digitalWrite(greenLED,HIGH);
digitalWrite(redLED,HIGH);
//If default behavior is enabled, perform blink five times, otherwise turn off all leds and move servo to 145
if(defaultbehavior==1){
blinkfive(amberLED, greenLED);
blinkfive(blueLED, redLED);
} else{
digitalWrite(amberLED,HIGH);
digitalWrite(blueLED,HIGH);
digitalWrite(greenLED,HIGH);
digitalWrite(redLED,HIGH);
}
//Task 3: LED chaser that blinks each led twice in the specified sequence
while(digitalRead(button_c)){
blinktwice(greenLED); //Blink green LED twice
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(redLED); //Blink red LED twice
//Break if button_a is released, all LEDs turned off
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(blueLED); //Blink blue LED twice
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(amberLED); //Blink amber LED twice
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(amberLED);
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(blueLED);
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(redLED);
if (digitalRead(button_c)==LOW){
break;
}
blinktwice(greenLED);
if (digitalRead(button_c)==LOW){
break;
}
}
//Task 2: Oscillate the servo between 10 and 120 degrees in a smooth manner
while (digitalRead(button_b)){
for (pos = 10; pos <= 120; pos += 1) { // moves from 10 degrees to 120 degrees in step of 1
myservo.write(pos); // Go the pos
Delay(8); // Delay 8 ms
}
for (pos = 120; pos >= 10; pos -= 1) { // moves from 120 degrees to 10 degrees in step of 1
myservo.write(pos); // Go to pos
Delay(8); //Delay 8 ms
}
}
//Task 4: Random state selector
while(digitalRead(button_d)){
//generate a random state between 1 and 3
randomState = random(1,4);
//If random state generated is 1, perform the following tasks
if (randomState == 1){
myservo.write(30); //Move servo to 30 degrees
blinktwice(greenLED); //Blink greenLED 2 times
}
//If random state generated is 2, perform the following tasks
else if (randomState == 2){
myservo.write(90); //Move servo to 90 degrees
blinkthree(redLED, blueLED); //Alternately blinks red and blue LEDs 3 times
} else {
myservo.write(150); //Move servo to 150 degrees
blinkfour(amberLED);
}
//Break the loop is button_d is released, stops the tasks
if (digitalRead(button_b)==LOW){
break;
}
}
}