// Kayla Frost - 300390878
// ENGR 1190 Final Exam, April 20 2025
// include servo library for the Servo motor
#include <Servo.h>
// include FastLED library for the NeoPixel ring
#include <FastLED.h>
// define pin numbers to led colors
int aled = 11; // amber led is attached to pin 11
int bled = 10; // blue led is attached to pin 10
int rled = 9; // red led is attached to pin 9
int gled = 8; // green led is attached to pin 8
// define pin numbers to button letters
int butd = 6; // yellow/amber button is attached to pin 6
int butc = 7; // blue button is attached to pin 7
int butb = 3; // green button is attached to pin 3
int buta = 2; // red button is attached to pin 2
int servoPin = 12; // servo is attached to pin 12
Servo myservo; // the servo motor is called myservo
int pos = 0; // variable to store servo motor's position (in degrees)
#define neoNumCells 16 // the neopixel has 16 cells
#define neoData 13 // neopixel is attached to pin 13
// define neopixel array with number of cells in ring (16 cells)
CRGB NeoArray[neoNumCells];
// interrupt function prototype
//void buttonA_interrupt();
//
bool startInterrupt = false;
//
int buttonAPressCount = 0;
void setup() // put your setup code here, to run once:
{
// define all pins connected to leds as outputs
pinMode(aled, OUTPUT);
pinMode(bled, OUTPUT);
pinMode(rled, OUTPUT);
pinMode(gled, OUTPUT);
// define all pins connected to buttons as inputs
pinMode(butd, INPUT);
pinMode(butc, INPUT);
pinMode(butb, INPUT);
pinMode(buta, INPUT);
// initially, turn all LEDs off (located in pins 8 to 11)
for (int pin = 8; pin <= 11; pin++)
{
digitalWrite(pin, HIGH); // in specified pin, turn LED to high (off)
}
// serial monitor to print stuff
Serial.begin(9600);
// attach servo motor to its pin (pin 12)
myservo.attach(servoPin);
// move servo motor to an initial position of 20 degrees
myservo.write(20);
//fastLED.addLeds from library
// < NEOPIXEL , data> (array name , number of cells)
FastLED.addLeds<NEOPIXEL, neoData>(NeoArray, neoNumCells);
// initially, change all pixel cells on the neopixel to black
for (int x = 0; x <= 15; x++) // x represents the pixel cell number from cell 0 to cell 15
{
NeoArray[x] = CRGB::Black; // change cell to black
FastLED.show();
}
// set up rising interrupt --> call interrupt function ??
//attachInterrupt(digitalPinToInterrupt(buta), buttonA_interrupt, RISING);
}
void loop() // put your main code here, to run repeatedly:
{
int servo_pos = 0; // variable to hold servo motor's position (in degrees) for Task 2 and 3
/*
Task 2:
While button B (GREEN) is pressed,
slow rotate the servo back and forth from 20° to 125°,
stopping at every intermediate single degree position for 12 ms.
On forward stroke, turn on:
green LED at 25°, red LED at 49°, blue LED at 81°, amber LED at 100°
On return stroke, turn off LEDs at the same positions stated above
*/
/*
while (digitalRead(butb)) // while button B is pressed, it returns true, so task 2's while loop will run
{
// FORWARD STROKE
for (servo_pos = 20; servo_pos <= 125; servo_pos++) // position begins at 20°, increments 1° each loop, and ends at 125°
{
myservo.write(servo_pos); // assign the position in degrees to the motor
delay(12); // wait 12 ms before moving to next position
if (servo_pos == 25) // when servo reaches 25°
{
digitalWrite(gled, LOW); // turn on green LED
}
if (servo_pos == 49) // when servo reaches 49°
{
digitalWrite(rled, LOW); // turn on red LED
}
if (servo_pos == 81) // when servo reaches 81°
{
digitalWrite(bled, LOW); // turn on blue LED
}
if (servo_pos == 100) // when servo reaches 100°
{
digitalWrite(aled, LOW); // turn on amber LED
}
}
// RETURN STROKE
for (servo_pos = 125; servo_pos >= 20; servo_pos--) // position begins at 125°, decrements 1° each loop, and ends at 20°
{
myservo.write(servo_pos); // assign the position in degrees to the motor
delay(12); // wait 12 ms before moving to next position
if (servo_pos == 25) // when servo reaches 25°
{
digitalWrite(gled, HIGH); // turn off green LED
}
if (servo_pos == 49) // when servo reaches 49°
{
digitalWrite(rled, HIGH); // turn off red LED
}
if (servo_pos == 81) // when servo reaches 81°
{
digitalWrite(bled, HIGH); // turn off blue LED
}
if (servo_pos == 100) // when servo reaches 100°
{
digitalWrite(aled, HIGH); // turn off amber LED
}
}
}*/
/*
Task 3:
While button C (BLUE) is pressed,
slow rotate the servo back and forth from 20° to 175°,
stopping at every intermediate 5° position for 60 ms.
On forward stroke, illuminate each Neopixel cell in a Red, Green, Blue pattern every 10°,
starting when the servo is at 25°
(i.e. when the servo is at 25°, set the zeroeth cell to Red;
when the servo is at 35° set the first cell to Green;
when the servo is at 45° set the second cell to Blue, and so on.)
On return stroke, turn off each Neopixel cell in reverse order every 10°,
starting when the servo is at 170°
(i.e. when the servo reaches 170°, turn off the 15th cell;
when the servo reaches 160°, turn off the 14th cell, and so on.)
while (digitalRead(butc)) // while button C is pressed, it returns true, so task 3's while loop will run
{
int cell = 0; // variable holds the neopixel cell number
// FORWARD STROKE
for (servo_pos = 20; servo_pos <= 175; servo_pos += 5) // position begins at 20°, increments 5° each loop, and ends at 175°
{
myservo.write(servo_pos); // assign the position in degrees to the motor
delay(60); // wait 60 ms before moving to next position
if (servo_pos == 25 || servo_pos == 55 || servo_pos == 85 || servo_pos == 115 || servo_pos == 145 || servo_pos == 175)
{
NeoArray[cell] = CRGB::Red; // change cell to red
FastLED.show();
cell++; // increment cell number to move to the next cell on the neopixel
}
if (servo_pos == 35 || servo_pos == 65 || servo_pos == 95 || servo_pos == 125 || servo_pos == 155)
{
NeoArray[cell] = CRGB::Green; // change cell to green
FastLED.show();
cell++; // increment cell number to move to the next cell on the neopixel
}
if (servo_pos == 45 || servo_pos == 75 || servo_pos == 105 || servo_pos == 125 || servo_pos == 165)
{
NeoArray[cell] = CRGB::Blue; // change cell to blue
FastLED.show();
cell++; // increment cell number to move to the next cell on the neopixel
}
}
// RETURN STROKE
int givenPosition = 170; // represents the position of the motor we are looking for (starts at 170°)
cell = 15; // change cell to cell 15, because it turns black starting from the end
for (servo_pos = 175; servo_pos >= 20; servo_pos -= 5) // position begins at 175°, decrements 5° each loop, and ends at 20°
{
myservo.write(servo_pos); // assign the position in degrees to the motor
delay(60); // wait 60 ms before moving to next position
if (servo_pos == givenPosition) // when the motor's position matches the next one we're looking for
{
NeoArray[cell] = CRGB::Black; // change cell to red
FastLED.show();
cell--; // decrement cell number to move to the next cell on the neopixel
givenPosition -= 10; // change given position to 10 degrees
}
}
}
Task 1 but without the interrupt
One blink of the discrete Green LED.
Two blinks of the discrete Red LED.
Three blinks of the discrete Blue LED.
Four blinks of the discrete Amber LED
*/
/*if (startInterrupt)
{
int randomLED = 0; // integer to hold randomly generated number for Task 1
// generate random number between pins for LEDs (between 8 and 11)
randomLED = random(gled, aled + 1); // website says (min, max - 1)
//digitalWrite(bled, LOW); // led on
if (randomLED == gled) // if random led pin number matches the green led pin number
{
// blink the green led one time
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
}
if (randomLED == rled) // if random led pin number matches the red led pin number
{
// blink the red led two times
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
}
if (randomLED == bled) // if random led pin number matches the blue led pin number
{
// blink the blue led three times
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
}
if (randomLED == aled) // if random led pin number matches the amber led pin number
{
// blink the amber led four times
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
digitalWrite(randomLED, LOW); // led on
delay(150); // on for 150ms
digitalWrite(randomLED, HIGH); // led off
delay(150); // off for 150 ms
}
// half a second pause between next random selection
// (because sometimes the same led is picked twice in a row and it blinks double without a break between)
delay(500);
}
if (!startInterrupt)
{
digitalWrite(gled, HIGH); // led off
digitalWrite(rled, HIGH); // led off
digitalWrite(bled, HIGH); // led off
digitalWrite(aled, HIGH); // led off
} */
/* Task 4:
While Button D is pressed (Blink time: ON for 75 ms & OFF for 75ms):
1. Create an up counting sequencer on the Neopixel ring that illuminates
the ith cell in Red, the [i+4th] cell in Green, the [i+8th] cell in Blue, and the [i+12th] cell in Orange.
2. Create a synchronized back and forth sequencer with the discrete LEDs in the following manner:
– Sequentially single blink the Green, Red, Blue, and, Amber discrete LEDs in sync with Neopixel cells 0 to 3.
– Sequentially single blink the Amber, Blue, Red, and, Green discrete LEDs in sync with Neopixel cells 4 to 7.
– Sequentially single blink the Green, Red, Blue, and, Amber discrete LEDs in sync with Neopixel cells 8 to 11.
– Sequentially single blink the Amber, Blue, Red, and, Green discrete LEDs in sync with Neopixel cells 12 to 15.
*/
while(digitalRead(butd))
{
for(int pix = 0; pix < neoNumCells; pix++)
{
int redCell = pix % neoNumCells;
int greenCell = (pix+4) % neoNumCells;
int blueCell = (pix+8) % neoNumCells;
int orangeCell = (pix+12) % neoNumCells;
NeoArray[redCell] = CRGB::Red;
NeoArray[greenCell] = CRGB::Green;
NeoArray[blueCell] = CRGB::Blue;
NeoArray[orangeCell] = CRGB::Orange;
FastLED.show();
if(pix == 0 || pix == 7 || pix == 8 || pix == 15)
{
digitalWrite(gled, LOW);
delay(75);
digitalWrite(gled, HIGH);
delay(75);
}
if(pix == 1 || pix == 6 || pix == 9 || pix == 14)
{
digitalWrite(rled, LOW);
delay(75);
digitalWrite(rled, HIGH);
delay(75);
}
if(pix == 2 || pix == 5 || pix == 10 || pix == 13)
{
digitalWrite(bled, LOW);
delay(75);
digitalWrite(bled, HIGH);
delay(75);
}
if(pix == 3 || pix == 4 || pix == 11 || pix == 12)
{
digitalWrite(aled, LOW);
delay(75);
digitalWrite(aled, HIGH);
delay(75);
}
delay(75);
NeoArray[redCell] = CRGB::Black;
NeoArray[greenCell] = CRGB::Black;
NeoArray[blueCell] = CRGB::Black;
NeoArray[orangeCell] = CRGB::Black;
FastLED.show();
delay(75);
}
}
}
/*void buttonA_interrupt()
{
buttonAPressCount++; // increments each time the interrupt function is called
int countRemainder = buttonAPressCount % 2;
if(countRemainder == 0)
{
startInterrupt = true;
}
if(countRemainder == 1)
{
startInterrupt = false;
}
}*/