// 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
//define the servo name and pin number
int servoPin = 12; // servo is attached to pin 12
// define the servo motor called myservo
Servo myservo;
// variable to store motor's position (in degrees)
int pos = 0;
// number of cells = 16 (given)
// NOTE: use #define or const int
#define neoNumCells 16
//define NeoPixel for pin it goes into
// NOTE: use #define or const int
#define neoData 13
// CRGB from library
// defines array with number of cells in ring
CRGB NeoArray[neoNumCells];
// integer to hold randomly generated number
int randomLED = 0;
void setup() // put your setup code here, to run once:
{
// all pins connected to leds are outputs
pinMode(aled, OUTPUT);
pinMode(bled, OUTPUT);
pinMode(rled, OUTPUT);
pinMode(gled, OUTPUT);
// all pins connected to buttons are inputs
pinMode(butd, INPUT);
pinMode(butc, INPUT);
pinMode(butb, INPUT);
pinMode(buta, INPUT);
// turn all LEDs off initially
for (int pin = 8; pin <= 11; pin++)
{
digitalWrite(pin, HIGH);
}
// serial monitor to print stuff
Serial.begin(9600);
// attach servo motor to pin 12
myservo.attach(servoPin);
// move servo to initial position of 20 degrees
myservo.write(20);
// for Task 1: shuffles random function
randomSeed(randomLED);
//fastLED.addLeds from library
// < NEOPIXEL , data> (array name , number of cells)
FastLED.addLeds<NEOPIXEL, neoData>(NeoArray, neoNumCells);
}
void loop() // put your main code here, to run repeatedly:
{
// Task 1: Random Discrete LED Blinker
while (digitalRead(buta)) // while button A is pressed (red)
{
// generate random number between pins for LEDs (between 8 and 11)
randomLED = random(gled, aled + 1); // website says (min, max - 1)
// used to test if random generator is working
//Serial.println(randomLED);
// blink twice with 150ms between
digitalWrite(randomLED, LOW);
delay(150);
digitalWrite(randomLED, HIGH);
delay(150);
digitalWrite(randomLED, LOW);
delay(150);
digitalWrite(randomLED, HIGH);
delay(150);
// large pause between next random selection
// because sometimes the same led is picked twice in a row
// and it blinks 4 times straight
delay(1000);
}
// Task 2: NeoPixel Colour LED Sequencer
while (digitalRead(butb)) // while button B is pressed (green)
{
// NOTE:
// I figured out the steps for a quarter of the neopixel
// then copied the code 3 more times and changed the colors accordingly.
// It's not the most efficient code, but it works and makes sense for me.
// first quarter
for (int pixel = 0; pixel <= 3; pixel++) // from index 0 to 3 is one quarter of the neopixel
{
// show initial colors
// ith cell - red
NeoArray[pixel] = CRGB::Red;
FastLED.show();
// [i+4]th cell - green
NeoArray[pixel + 4] = CRGB::Green;
FastLED.show();
// [i+8]th cell - dark turquoise
NeoArray[pixel + 8] = CRGB::DarkTurquoise;
FastLED.show();
// [i+12]th cell - blue
NeoArray[pixel + 12] = CRGB::Blue;
FastLED.show();
delay(150);
// back to black
NeoArray[pixel] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 4] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 8] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 12] = CRGB::Black;
FastLED.show();
}
// second quarter
for (int pixel = 0; pixel <= 3; pixel++)
{
// ith cell
NeoArray[pixel] = CRGB::Blue;
FastLED.show();
// [i+4]th cell
NeoArray[pixel + 4] = CRGB::Red;
FastLED.show();
// [i+8]th cell
NeoArray[pixel + 8] = CRGB::Green;
FastLED.show();
// [i+12]th cell
NeoArray[pixel + 12] = CRGB::DarkTurquoise;
FastLED.show();
delay(150);
// back to black
NeoArray[pixel] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 4] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 8] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 12] = CRGB::Black;
FastLED.show();
}
// third quarter
for (int pixel = 0; pixel <= 3; pixel++)
{
// ith cell
NeoArray[pixel] = CRGB::DarkTurquoise;
FastLED.show();
// [i+4]th cell
NeoArray[pixel + 4] = CRGB::Blue;
FastLED.show();
// [i+8]th cell
NeoArray[pixel + 8] = CRGB::Red;
FastLED.show();
// [i+12]th cell
NeoArray[pixel + 12] = CRGB::Green;
FastLED.show();
delay(150);
// back to black
NeoArray[pixel] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 4] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 8] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 12] = CRGB::Black;
FastLED.show();
}
// fourth quarter
for (int pixel = 0; pixel <= 3; pixel++)
{
// ith cell
NeoArray[pixel] = CRGB::Green;
FastLED.show();
// [i+4]th cell
NeoArray[pixel + 4] = CRGB::DarkTurquoise;
FastLED.show();
// [i+8]th cell
NeoArray[pixel + 8] = CRGB::Blue;
FastLED.show();
// [i+12]th cell
NeoArray[pixel + 12] = CRGB::Red;
FastLED.show();
delay(150);
// back to black
NeoArray[pixel] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 4] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 8] = CRGB::Black;
FastLED.show();
NeoArray[pixel + 12] = CRGB::Black;
FastLED.show();
}
}
// Task 3: Servo Oscillator
while (digitalRead(butc)) // while button C is pressed (blue)
{
// smooth rotation from 20 to 120 degrees
for (pos = 20; pos <= 120; pos++) // smooth = increment by 1 degree
{
myservo.write(pos);
delay(8); // 8 ms
}
// smooth rotation from 120 back to 20 degrees
for (pos = 120; pos >= 20; pos--) // smooth = decrement by 1 degree
{
myservo.write(pos);
delay(8); // 8 ms
}
}
// Task 4: NeoPixel + Servo Synced Motion
// NOTE: I cannot for the life of me get this thing to start at index 3. Sorry.
while(digitalRead(butd)) // while button D is pressed (yellow/amber)
{
// initial position of servo
pos = 15;
for (int index = 0; index <= 7; index++) // only first half of the ring, starting at index 0
{
if (index < 7) // so it doesn't move past 165 degrees
{
//move servo clockwise in 25 degree increments
myservo.write(pos + ( 25 * index));
}
// color cells
// lime colored cell index
int indexL = index;
// orange color cell index
int indexO = index + 8;
// one side of neopixel
NeoArray[indexL] = CRGB::Lime;
FastLED.show();
// other side of neopixel
NeoArray[indexO] = CRGB::DarkOrange;
FastLED.show();
delay(150);
// change cells back to black
// one side of neopixel
NeoArray[indexL] = CRGB::Black;
FastLED.show();
// other side of neopixel
NeoArray[indexO] = CRGB::Black;
FastLED.show();
delay(150);
}
// I just got half working, then I'll flip the colors for the other half of the ring
for (int index = 0; index <= 7; index++) // second half of the ring
{
if (index < 7) // so it doesn't move past 15 degrees
{
//move servo counterclockwise
myservo.write(165 - (25 * index));
}
// color cells (switch index calculations around)
// orange colored cell index
int indexO = index;
// lime color cell index
int indexL = index + 8;
// one side
NeoArray[indexL] = CRGB::Lime;
FastLED.show();
// other side
NeoArray[indexO] = CRGB::DarkOrange;
FastLED.show();
delay(150);
// cells back to black
// one side
NeoArray[indexO] = CRGB::Black;
FastLED.show();
// other side
NeoArray[indexL] = CRGB::Black;
FastLED.show();
delay(150);
}
}
}