Aren Davey's annoying toy
Warm-up Project Overview: "Annoy Toy" by Nora Xi
"Annoying Toy" - Sylvia Ker
Detailed Circuit behind the Board
Arduino and wiring
Detailed Circuit behind the Board (2)
Detailed circuit
Arduino and breadboard wiring
Nora Xi - Project Demo Video
Aren Davey - Project Demo Video
Hengyue Zhao - Project Demo Video
Sylvia Ker - Project Demo Video
When the Annoying toy is plugged into power, the speaker make a noise. When the white button attached to the bottom is pressed, the two little bright eyes light up blue while it is pressed. When the button is let go, the motor starts to move back and fourth. If you turn the stick on the left side, the pitch of the sound increases and decreases. When the stick is turned while the button is pressed, the eyes spin with purple pupils light up, like the Annoying Toy is looking in circles. If you only press the button, the bright eyes turn blue on and off and the motor is activated to move side to side. If you only turn the stick on the left, the sound changes, and the lights are off. If you reach out your hand to stop the speaker, and have your hand go between the break-beam sensor, the sound stops and the motor is freezes. Ultimately, its purpose is to be a toy to joggle your mind, making you want to make it less chaotic as you play with it.
Unit test for LED light, rotary encoder, and button
Laser cutting testing process.
Unit test of break beam, speaker, led, motor, and button.
Circuit overall
Partial circuit of combining LED, motor, button, and breakbeam sensor together.
Sylvia: Overall, coming up with the idea for the project was pretty fun, and the general idea of the code and using the components was not challenging. What was challenging, however, was learning the specific code needed to use these components. For example, there was an unexpected issue with the rotary encoder not working when there is a delay in the loop. Additionally, we ran into a power issue that was unexpected. We stayed along the idea we had in the beginning, but if we could not figure out how to decrease the delay in the loop, we may have had to change the rotary encoder code.
Nora: This warm-up project was really fun. I was responsible for working on the interaction between LEDs, the rotary encoder, and the buttons. I learned a lot about using LEDs and the rotary encoder—for example, how different libraries (even though they seem really similar) can behave differently, and how some libraries display colors in unexpected ways (for instance, the PololuLedStrip<LEDSTRIPPIN1> library sometimes shows red for colors we didn’t set as red). Working with the rotary encoder was also challenging, since DT and CLK signals can be confusing. Overall, it was a fun and not-too-difficult warm-up!
Aren: I really enjoyed the concept for this project. It was nice to write in Arduino code again after not doing so for a while. The most challenging part was combining multiple files of Arduino code and ensuring that everything worked together in the end. It was a bit of an arduous process since I had to confirm that there were no bugs in the code before I started to merge, reassign pins so that they were not assigned to two components, and check that the code was legible as we were mixing different programming styles together. Regardless, it was fun and challenging.
Zimeng: A few years ago I tried making a drawing machine with Arduino, and coming back to it this time felt quite different. The focus was more on physical computing, which helped me better understand circuits and the interactions between different components. I was mainly responsible for designing and fabricating the board, and although it was just two small panels with a few components, we still went through a few iterations of testing and improvement. Along the way, I learned some new ways of wiring and got more familiar with the lab equipment. Overall, this warm-up was very fun and served as a great refresher and preparation for the bigger project ahead—designing equipment for disabled children. I’m really looking forward to the next challenge!
Hengyue: This technical warm-up project helped me quickly understand how a team collaborates to build an Arduino prototype. Equally important, it also gave me hands-on experience with Autodesk Fusion. Using Fusion, I was able to create an initial outer casing design, which went through several iterations. One key insight was that the casing could not be developed in isolation, it is only one subsystem within the larger prototype. Its evolution required continuous communication and coordination with other team members to ensure proper integration.
Functional Block Diagram:
Electrical Schematic:
/*
F2025 62-423 Technical Warmup - Annoying Toy
This is a object that is very annoying and tries its very best to stop you from shutting it up.
Interactions:
Speaker screams in high pitch when connected to power.
Speaker changes pitch when encoder is turned.
Motor swivels when button is pressed.
Eyes light up when button is held.
Eyes spin when button is pressed and encoder is turned.
Speaker and motor shut off when break beam is triggered.
Pin mapping:
Arduino pin | role | details
------------------------------
2 input rotary encoder
3 input rotary encoder
5 input breakbeam
6 output motor servo
7 output LED ring
8 output buzzer speaker
9 input push button
10 output LED ring
11 output external LED for debugging
Adapted code/information from these sources:
https://forum.arduino.cc/t/use-a-push-button-as-a-toggle-switch/486589
https://courses.ideate.cmu.edu/60-223/f2025/home
https://github.com/mathertel/RotaryEncoder/tree/master/examples
*/
#include <Servo.h>
#include <PololuLedStrip.h>
Servo servo;
const int breakbeamPin = 5;
const int ledPin = 11;
const int buttonPin = 9;
const int pinCLK = 2;
const int pinDT = 3;
const int buzzerPin = 8;
const int LEDSTRIPPIN1 = 7;
const int LEDSTRIPPIN2 = 10;
const int NUMLEDS = 12;
volatile int toneCounter = 0;
volatile int lightCounter = 0;
int servoPos =30;
int currentButtonReading = 0;
int buttonState = LOW;
int motorState;
bool ledState = false;
int prevButtonState = LOW;
bool clockwise = true;
int breakbeamState = 0;
int lastBreakbeamState = 0;
unsigned long time = 0; // the last time the output pin was toggled
unsigned long debounce = 400UL;
int lastCLKState;
//LED
PololuLedStrip<LEDSTRIPPIN1> ledStrip1;
PololuLedStrip<LEDSTRIPPIN2> ledStrip2;
rgb_color colors[NUMLEDS];
// Make some named colors of variable type "rgb_color".
// Black is all LEDs off, and white is all LEDs on.
rgb_color black = rgb_color(0, 0, 0);
rgb_color white = rgb_color(255, 255, 255);
// Each rainbow color is either one LED fully on and others
// off (that's red, green, and blue) or some mixture of them
// at varying strengths.
rgb_color red = rgb_color(255, 0, 0);
rgb_color orange = rgb_color(255, 75, 0);
rgb_color yellow = rgb_color(255, 255, 0);
rgb_color green = rgb_color(0, 255, 0);
rgb_color blue = rgb_color(0, 0, 255);
rgb_color indigo = rgb_color(75, 0, 130);
void setup() {
servo.attach(6);
pinMode(ledPin, OUTPUT);
pinMode(breakbeamPin, INPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(pinCLK, INPUT);
pinMode(pinDT, INPUT);
pinMode(buzzerPin, INPUT);
digitalWrite(breakbeamPin, HIGH);
lastCLKState = digitalRead(pinCLK);
Serial.begin(9600);
tone(buzzerPin, 1200);
}
void loop() {
//encoder code that changes pitch of speaker
int currentCLKState = digitalRead(pinCLK);
if (currentCLKState != lastCLKState) {
if (digitalRead(pinDT) != currentCLKState) {
toneCounter++;
} else {
toneCounter--;
}
tone(buzzerPin, abs(1100 + toneCounter * 5));
}
currentButtonReading = digitalRead(buttonPin);
if (currentButtonReading == LOW) {
//turn on the lights with button
if (prevButtonState == HIGH) {
for (int i = 0; i < NUMLEDS; i++) {
colors[i] = blue;
}
}
//encoder changes the lights when turned when button is pressed.
if (currentCLKState != lastCLKState) {
if (digitalRead(pinDT) != currentCLKState) {
lightCounter++;
} else {
lightCounter--;
}
if (lightCounter < 0) lightCounter = NUMLEDS - 1;
if (lightCounter >= NUMLEDS) lightCounter = 0;
for (int i = 0; i < NUMLEDS; i++) {
colors[i] = blue;
}
colors[lightCounter] = indigo;
}
ledStrip1.write(colors, NUMLEDS);
ledStrip2.write(colors, NUMLEDS);
} else {
// if button not pressed, turn off the lights
for (int i = 0; i < NUMLEDS; i++) {
colors[i] = black;
}
ledStrip1.write(colors, NUMLEDS);
ledStrip2.write(colors, NUMLEDS);
}
//motor on and off
if (currentButtonReading == HIGH && prevButtonState == LOW && millis() - time > debounce) {
if (buttonState == HIGH) {
buttonState = LOW;
Serial.println("OFF");
if (motorState == LOW) {
motorState = HIGH;
}
ledState = !ledState;
} else {
buttonState = HIGH;
Serial.println("ON");
motorState = HIGH;
ledState = !ledState;
}
time = millis();
}
prevButtonState = currentButtonReading;
lastCLKState = currentCLKState;
//breakbeam
breakbeamState = digitalRead(breakbeamPin);
if (ledState) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
if (breakbeamState && !lastBreakbeamState) {
Serial.println("unbroken");
}
if (!breakbeamState && lastBreakbeamState) {
Serial.println("broken");
motorState = LOW;
noTone(buzzerPin);
}
lastBreakbeamState = breakbeamState;
//motor movements
if (motorState == HIGH) {
if (clockwise) {
servoPos++;
} else {
servoPos--;
}
if (servoPos == 100) {
clockwise = false;
} else if (servoPos == 30) {
clockwise = true;
}
delay(2);
servo.write(servoPos);
}
}