Slot Machine Treat Dispenser
An Arduino-powered slot machine that dispenses cat treats, complete with spinning reels and parental controls via Arduino Cloud.
Devices & Components
1
Arduino® UNO R4 WiFi
Software & Tools
Arduino IDE
Project description
Code
js
1/* 2 Arduino IoT Cloud integration 3 4 The following variables are automatically generated and updated when changes are made to the Thing 5 6 int treat; 7 bool on; 8 9 Variables which are marked as READ/WRITE in the Cloud Thing will also have functions 10 which are called when their values are changed from the Dashboard. 11 These functions are generated with the Thing and added at the end of this sketch. 12*/ 13 14#include "thingProperties.h" 15#include <AccelStepper.h> 16 17// Stepper motors 18AccelStepper stepperX(1, 12, 13); 19AccelStepper stepperY(1, 3, 6); 20AccelStepper stepperZ(1, 4, 7); 21 22 23// Using 1/8 stepping on stepper motors 24const long STEPS_PER_REV = 1600; 25const long STEPS_PER_SQUARE = 200; // 8 "squares" on each wheel 26 27 28// DC motor 29const int motor_pwm = 9; 30const int motor_dir = 10; 31 32// LEVER switch 33const int switchPin = 11; // Z+ endstop pin on CNC shield 34bool lastSwitchState = false; 35 36 37// tracking slot machine positions 38int Xpos = 0; 39int Ypos = 0; 40int Zpos = 0; 41 42// tracking attempts 43int attemptCounter = 0; 44 45// reel symbol positions 46String reelX[] = {"bowl", "mouse", "bow", "fish", "cat", "bowl", "paw", "fish"}; 47String reelY[] = {"bowl", "bow", "bowl", "fish", "paw", "mouse", "fish", "cat"}; 48String reelZ[] = {"bowl", "bow", "fish", "cat", "mouse", "bowl", "paw", "fish"}; 49 50 51void checkWin() { 52 // Get the current symbols based on positions 53 String symbolX = reelX[Xpos]; 54 String symbolY = reelY[Ypos]; 55 String symbolZ = reelZ[Zpos]; 56 57 Serial.print("Symbols: ("); 58 Serial.print(symbolX); 59 Serial.print(", "); 60 Serial.print(symbolY); 61 Serial.print(", "); 62 Serial.print(symbolZ); 63 Serial.print(") at positions ("); 64 Serial.print(Xpos); 65 Serial.print(", "); 66 Serial.print(Ypos); 67 Serial.print(", "); 68 Serial.print(Zpos); 69 Serial.println(")"); 70 71 72 // Check if all three symbols match 73 if (symbolX == symbolY && symbolY == symbolZ) { 74 Serial.println("YOU WIN!!"); 75 76 motorForward(40); 77 78 delay(350); 79 motorStop(); 80 81 motorBackward(80); 82 delay(100); 83 motorStop(); 84 } 85} 86 87void doJitter(AccelStepper &stepper) { 88 89 int jitterAmount = 40; 90 91 stepper.move(jitterAmount); 92 while (stepper.distanceToGo() != 0) { 93 stepper.run(); 94 stepperX.run(); 95 stepperY.run(); 96 stepperZ.run(); 97 } 98 99 stepper.move(-jitterAmount * 2); 100 while (stepper.distanceToGo() != 0) { 101 stepper.run(); 102 stepperX.run(); 103 stepperY.run(); 104 stepperZ.run(); 105 } 106 107 stepper.move(jitterAmount); 108 while (stepper.distanceToGo() != 0) { 109 stepper.run(); 110 stepperX.run(); 111 stepperY.run(); 112 stepperZ.run(); 113 } 114} 115 116void runSequence() { 117 118 attemptCounter++; 119 120 int slotX, slotY, slotZ; 121 122 // Force win every nth attempt, depending on the value of "treat" selected in dashboard 123 124 if (treat > 0 && attemptCounter % treat == 0) { 125 126 // Pick a random target position for reel X 127 int winPos = random(0, 8); 128 String winSymbol = reelX[winPos]; 129 130 // Find the closest position on Y and Z that shows the same symbol 131 int winPosY = -1, winPosZ = -1; 132 for (int pos = 0; pos < 8; pos++) { 133 if (reelY[pos] == winSymbol) winPosY = pos; 134 if (reelZ[pos] == winSymbol) winPosZ = pos; 135 } 136 137 slotX = (winPos - Xpos + 8) % 8; 138 slotY = (winPosY - Ypos + 8) % 8; 139 slotZ = (winPosZ - Zpos + 8) % 8; 140 } 141 else{ 142 slotX = random(0, 8); 143 slotY = random(0, 8); 144 slotZ = random(0, 8); 145 } 146 147 148 Xpos = (Xpos + slotX) % 8; 149 Ypos = (Ypos + slotY) % 8; 150 Zpos = (Zpos + slotZ) % 8; 151 152 long targetX = slotX * STEPS_PER_SQUARE; 153 long targetY = slotY * STEPS_PER_SQUARE; 154 long targetZ = slotZ * STEPS_PER_SQUARE; 155 156 long moveX = (10 * STEPS_PER_REV) + targetX; 157 long moveY = (12 * STEPS_PER_REV) + targetY; 158 long moveZ = (14 * STEPS_PER_REV) + targetZ; 159 Serial.print("move values "); 160 Serial.println(moveX); 161 stepperX.moveTo(moveX); 162 stepperY.moveTo(moveY); 163 stepperZ.moveTo(moveZ); 164 165 bool xJittered = false; 166 bool yJittered = false; 167 bool zJittered = false; 168 169 170 while (!xJittered || !yJittered || !zJittered) { 171 stepperX.run(); 172 stepperY.run(); 173 stepperZ.run(); 174 175 if (!xJittered && stepperX.distanceToGo() == 0) { 176 doJitter(stepperX); 177 xJittered = true; 178 } 179 180 if (!yJittered && stepperY.distanceToGo() == 0) { 181 doJitter(stepperY); 182 yJittered = true; 183 } 184 185 if (!zJittered && stepperZ.distanceToGo() == 0) { 186 doJitter(stepperZ); 187 zJittered = true; 188 } 189 190 191 } 192 // Check if the combination is in list 193 checkWin(); 194 195 digitalWrite(8, HIGH); 196 197 // Reset positions so moveTo works correctly next run 198 stepperX.setCurrentPosition(0); 199 stepperY.setCurrentPosition(0); 200 stepperZ.setCurrentPosition(0); 201} 202 203void setup() { 204 205 Serial.begin(9600); 206 delay(1500); 207 208 initProperties(); 209 ArduinoCloud.begin(ArduinoIoTPreferredConnection); 210 211 pinMode(8, OUTPUT); 212 digitalWrite(8, HIGH); // steppers disabled 213 214 pinMode(switchPin, INPUT_PULLUP); 215 216 217 pinMode(motor_pwm, OUTPUT); 218 pinMode(motor_dir, OUTPUT); 219 220 221 // Stop motor initially 222 digitalWrite(motor_dir, LOW); 223 digitalWrite(motor_pwm, 0); 224 225 randomSeed(analogRead(A0)); 226 227 stepperX.setMaxSpeed(6000); 228 stepperX.setAcceleration(20000); 229 230 stepperY.setMaxSpeed(6000); 231 stepperY.setAcceleration(20000); 232 233 stepperZ.setMaxSpeed(6000); 234 stepperZ.setAcceleration(20000); 235} 236 237void loop() { 238 239 ArduinoCloud.update(); 240 241 // Read switch (active LOW) 242 bool currentSwitchState = !digitalRead(switchPin); 243 244 245 // When physical switch just turned on AND "ON" button on dashboard is on 246 if (currentSwitchState && !lastSwitchState && on) { 247 digitalWrite(8, LOW); // enable steppers 248 runSequence(); 249 } 250 251 lastSwitchState = currentSwitchState; 252 253 254} 255 256void onOnChange() { 257 258} 259 260 261void onTreatChange(){ 262 263} 264 265 266void motorForward(int speed) { 267 digitalWrite(motor_dir, HIGH); 268 analogWrite(motor_pwm, speed); 269} 270 271void motorBackward(int speed) { 272 digitalWrite(motor_dir, LOW); 273 analogWrite(motor_pwm, speed); 274} 275 276void motorStop() { 277 analogWrite(motor_pwm, 0); 278}
Comments
Only logged in users can leave comments