CANDYBINATION
October 22nd, 2024 by Isaac Cheaz
Prof: Inmi Lee
Context
The idea to make a candy slot machine was arbitrary in a sense. I think it started with the lesson about the random function in Arduino, in which we could generate a random number within a specified range. This, coupled with my partner's Las Vegas background resulted in the brainstorming of a slot machine.
The introduction of servo motors and the wide variety of sensors also lead us to this project. We had the motors to create movement that would entertain the user, LEDs to create an unique effect, and sensors/buttons for the user's input.
The project, at face value, could be compared to a generic slot machine found in casinos. However, where it differ from them is the puzzle we implemented on the front of machine, that would unlock a button upon completion. The project also doesn't include the payment-to-play system and made it so the user had to think a little before spinning the candy themed reels.
The mentioning of candy should already hint a little to the intended audience of the machine. It was intended for children since the size of machine was rather small and candy is usually enjoyed by the youth.
Designing
Understanding how users were gonna interact with the project was a little bit overlooked during planning since it was noticed during the construction of the parts. We knew from the start that most of our things were going to be made out of cardboard, being strong and also very flexible in its uses.
Along with cardboard, the use popsicle sticks were also considered, something more rigid that would be used to hold things together. There weren't many options in terms of materials, the project needed to be made of something easy to work with and that would be able to hold all the components and wires inside of it without breaking.
Back to materials, wood would've also been a strong candidate. During the presentation, I saw a handful of people using it in their project and it seemed to do a very good job as cardboard. However, with the lack of experience in woodworking, it was hard for us to cut the pieces and paste them together. The final decision to use cardboard is also due to the class offering it before the construction phase of the midterm. Basically, fate was screaming at us to use cardboard.
Fun Fact
In terms of interaction, the "Candybination" machine originally had a lever in which you could pull to spin the reels. But, since there were going to be nobs (to unlock the next stage), we figured that due to its size and people's past experiences with slot machines that it would be the first thing they would try interacting with. The lever would be hooked to a servo, which would lock it when it had power and allow the user to pull when we cut the power. We later realized the complexity and the issues that came along with it, and balancing the benefits with the disadvantages, we decided to scrap it.
Production
The first significant step in our process was finding an idea and going off from there. When the idea of a slot machine was suggested to Professor Inmi, she was instantly skeptical of the idea and recommended we thought of something more interactive and interesting. The second idea was even worse, being a finger based (very one dimensional interaction) machine, something similar to a rhythm game. Ultimately, the final idea was a tweaked version of the first one and in end, got a very hesitant green light from Inmi.
Code
The next step was significant step was the coding, to test the code, a simple prototype was built using cardboard and hooked it up to an Arduino. Even with the introduction of millis() and many other unique functions, we still somewhat sticked to the basics. One thing that was added, which wasn't taught in class was creating new functions using void and adding them to the loop. The code was long and complicated, with issues popping up left and right as went.
Major issues such as the lack of parallel execution of functions and the long, confusion if statements was a struggle, especially since we were both not that familiar with the more complex functions of Arduino. My contribution to the coding was fairly insignificant, since I only helped Brandon look over the code for errors and areas we could do differently
Brandon & Tony
We worked long hours in the IMA lab after our classes...
A funny story I would like to add is that, in one of the 5 hour sessions we did in the IMA lab, one of our close friends came to check out our project. After a few looks at the code, he decided to try to code it himself, self-teaching himself Arduino (since it was similar to C++) and giving us insights on where he would make the code less redundant.
The last significant step was the building process. Compared to the coding, cutting cardboard and designing was less complicated. Surprisingly, our two sheets of cardboards were used efficiently, with some leftover after the finished build. The first prototype (before the paint) looked similar to a house, very rectangular and bland.
Although, after adding the side contraption and realizing the lack of space available for the servo, I suggested and made the roof curved. The final build looked very nice, with little to no wire being seen and the design matching the theme of our project title: *candy*.
1.
Honestly, we cheated a little in the section of User Testing since we couldn't wait to show our friends the amazing project we created in IMA. They gave very good suggestions and where our project could be improved before the day of the User Testing. Still, even though I expected very little room for improvement, on the day of the testing, I was surprised.
2.
Also, there were also recommended tweaks from students that required no physical change to the structure of the machine, but instead in the code. Like, the LEDs could flash when the user skipped the first stage and would be a subtle hint to what they should interact with.
3.
My classmates and Professor Inmi showed me that there is always room for improvement. For example, the machine was rather small, so it was hard for the user to see the spinning reels after they pressed the button. We were recommended to put legs on the machine, or find a way to prop it up to eye level.
Working on the midterm...
Brandon (Cat Ears Ver.)
Conclusion
The goals for this project was to take an adult concept of gambling and turn it into a game that children could play by solving puzzles. For me, the definition of interaction is a conversation between the user and machine. The user talks and the machine listens, then it responds. And we can see this in our machine, the user talks to the machine by twisting the nobs and pressing the buttons, and the machine listens by receiving the input and responds by actuating the motors. However, this example also shows that it isn't really a conversation, but orders from the user to do only one thing. Instead of picturing as a conversation, its more of a domino effect where tipping the first piece could be compared to the user twisting the first nob.
Improvements
During the presentation, Andy mentioned a jackpot win to give the users a bigger incentive to keep playing the game. And I agree with his suggestion, if someone plays the same game for over 5 times and the same thing happens, then eventually it'll get boring. Switching up the win could break that mundane cycle when the user interacts with our machine.
Setbacks
No project doesn't come without its setbacks. Luckily, ours only had a few. One, choosing the motors. At the beginning, the idea was to use stepper motors since they could spin faster and hold a bigger reel. But servo motors beat steppers at one thing: precision. With the 180 servos, we could control the exact degree they would turn to, which we needed for the slot machine. Figuring this out took multiple nights and a lot of code testing. In the end, there were sacrifices in the "authenticity" of a slot machine, since the roll was cut in half and it would go up and down instead of spin 360.
The second issue was the wires going out of they sockets or unhooking from the pins. This only started happening when we connected the potentiometers. At first we tried using female to male wires to hook them up and tape to keep them in place. It didn't work. So in the end, the solution was a getting a roll of alligator clips and using them to hold them in place more securely. Still, after a lot of disconnection and troubleshooting with the spaghetti of cables, the wires were able to stay on consistently.
Final Words
"Finishing the project, I thought I would be more accomplished. I had the thought that it wasn't good enough since it felt very one-dimensional. I was comparing my project to my peer's and theirs's seemed more interactive while ours felt like dials and button. Although, one thing I did feel accomplished by was the cable management we had, no other group had that and ours felt more slick."
Disassembly
CODE
#include <Servo.h>
Servo servo1;
Servo servo2;
Servo servo3;
int icon1;
int icon2;
int deg1;
int deg2;
int i = 0;
int buzzer = 9;
///
int poten1 = A0;
int poten2 = A1;
int poten3 = A2;
int led1 = 10;
int led2 = 11;
int led3 = 12;
int thresh1 = random(50, 950);
int thresh2 = random(50, 950);
int thresh3 = random(50, 950);
int status1;
int status2;
int status3;
int lever = 12;
////
int state = 1;
int ministate = 1;
////
int button = 2;
int buttonON = 0;
int play = 1;
void setup() {
Serial.begin(9600);
pinMode(poten1, INPUT);
pinMode(poten2, INPUT);
pinMode(poten3, INPUT);
pinMode(buzzer, OUTPUT);
pinMode(lever, INPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);
servo1.attach(3);
servo2.attach(5);
servo3.attach(7);
servo3.write(0);
}
void loseSound() {
tone(buzzer, 400);
delay(100);
tone(buzzer, 300);
delay(100);
tone(buzzer, 200);
delay(100);
tone(buzzer, 400);
delay(100);
tone(buzzer, 300);
delay(100);
tone(buzzer, 200);
delay(100);
tone(buzzer, 400);
delay(100);
tone(buzzer, 300);
delay(100);
tone(buzzer, 200);
delay(100);
tone(buzzer, 100);
delay(100);
}
void state1() {
int potenread1 = analogRead(poten1);
int potenread2 = analogRead(poten2);
int potenread3 = analogRead(poten3);
if (digitalRead(button) ==1 && buttonON == 0) {
buttonON =1;
blink();
delay(100);
blink();
buttonON = 0;
}
if (status1==1 && status2 ==1 && status3==1) {
state = 2;
buttonON = 0;
}else {
if (potenread1 >= thresh1 - 50 && potenread1 <= thresh1 + 50){
digitalWrite(led1, HIGH);
status1 = 1;
} else {
status1 = 0;
digitalWrite(led1, LOW);
}
if (potenread2 >= thresh2 - 50 && potenread2 <= thresh2 + 50){
digitalWrite(led2, HIGH);
status2 = 1;
} else {
status2 = 0;
digitalWrite(led2, LOW);
}
if (potenread3 >= thresh3 - 50 && potenread3 <= thresh3 + 50){
digitalWrite(led3, HIGH);
status3 = 1;
} else {
status3 = 0;
digitalWrite(led3, LOW);
}
}
delay(10);
}
void state2() {
if (digitalRead(button) == 1 && buttonON == 0) {
buttonON = 1;
randomSeed(analogRead(A4));
icon1 = random(1,4);
randomSeed(analogRead(A4));
icon2 = random(1,4);
if (play ==1) {
icon1 = 2;
icon2 = 2;
play = 0; }
if (icon1 == 1) {
deg1 = 30;}
if (icon1 == 2) {
deg1 = 100;}
if (icon1 == 3) {
deg1 = 160;}
if (icon2 == 1) {
deg2 = 160;}
if (icon2 == 2) {
deg2 = 90;}
if (icon2 == 3) {
deg2 = 20;}
i = 2;
ministate = 2;
}
if (ministate ==2) {
if (i >0) {
servo1.write(180);
servo2.write(0);
delay(500);
servo1.write(0);
servo2.write(180);
delay(500);
i -=1;
} else {
servo1.write(deg1);
servo2.write(deg2);
delay(500);
ministate = 1;
if (icon1 == icon2) {
state = 3;} else if (icon1 != icon2) {
servo3.write(0);
loseSound();
noTone(buzzer);
buttonON = 0;
state = 1;
thresh1 = random(50,950);
thresh2 = random(50,950);
thresh3 = random(50,950);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
status1 = 0;
status2 = 0;
status3 = 0;
}
}
}
}
void blink() {
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
delay(200);
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
delay(200);
}
void resetLights() {
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
status1 = 0;
status2 = 0;
status3 = 0;
}
void loop() {
if (state == 1) {
state1();
}
if (state == 2) {
state2();
}
if (state ==3) {
tone(buzzer, 400);
blink();
tone(buzzer, 600);
blink();
tone(buzzer, 800);
blink();
tone(buzzer, 900);
servo3.write(0);
blink();
tone(buzzer, 1000);
delay(2000);
servo3.write(90);
delay(500);
servo3.write(0);
noTone(buzzer);
tone(buzzer, 900);
delay(100);
tone(buzzer, 1000);
delay(100);
tone(buzzer, 900);
delay(100);
tone(buzzer, 1000);
delay(100);
noTone(buzzer);
randomSeed(analogRead(A4));
thresh1 = random(50, 950);
randomSeed(analogRead(A4));
thresh2 = random(50, 950);
randomSeed(analogRead(A4));
thresh3 = random(50, 950);
resetLights();
buttonON = 0;
state = 1;
}
}