Devices & Components
1
40 colored male-male jumper wires
1
Arduino Uno Rev3
1
Modulino™ Distance
1
16x2 LCD display with I²C interface
1
10k resistors (x4)
1
160 ohm resistor
1
100 ohm resistor
Software & Tools
1
Tinker cad
Project description
Code
Interactive Robot Desk Buddy Code
cpp
1#include <LiquidCrystal.h> 2 3// Pin defs 4const int BUTTON = 7; // Tickle button 5const int GAME = 3; // Minigame button 6const int PR = A5; // Photoresistor 7const int PIEZO = 2; // Buzzer 8const int FSR_PIN = A0; // Force Sensor 9 10// Distance sensor pins 11const int TRIG_PIN = 5; 12const int ECHO_PIN = 6; 13 14// LCD Pins 15const int RS = 8; 16const int E = 9; 17const int DB4 = 10; 18const int DB5 = 11; 19const int DB6 = 12; 20const int DB7 = 13; 21 22int prValue; 23int buttonState; 24int lastButtonState = LOW; 25int gameState; 26int buttonCount = 0; 27 28// Timing vars 29unsigned long lastSensorCheck = 0; 30const int sensorInterval = 150; // Check sensors every 150 ms 31 32// Melodies 33int laughNotes[] = { 34 440, 523, 587, 659, 587, 523 35}; 36int laughDurations[] = { 37 100, 100, 100, 100, 100, 200 38}; 39int laughLength = 6; 40 41int annoyedNotes[] = { 42 600, 520, 450, 400 43}; 44int annoyedDurations[] = { 45 180, 200, 230, 320 46}; 47int annoyedLength = 4; 48 49int sleepNotes[] = { 50 523, 494, 440, 392, 330 51}; 52int sleepDurations[] = { 53 200, 220, 250, 300, 500 54}; 55int sleepLength = 5; 56 57int singNotes[] = { 58 659, 784, 523, 587 59}; 60int singDurations[] = { 61 150, 150, 150, 300 62}; 63int singLength = 4; 64 65int sleepSingNotes[] = { 66 440, 494, 523, 494, 440, 392, 440, 392 67}; 68int sleepSingDurations[] = { 69 180, 180, 220, 180, 180, 200, 180, 220 70}; 71int sleepSingLength = 8; 72 73int awakeNotes[] = { 74 523, 659, 784, 988, 784, 659 75}; 76int awakeDurations[] = { 77 120, 120, 150, 170, 150, 200 78}; 79int awakeLength = 6; 80 81int startGameNotes[] = { 82 659, 784, 988, 1319 83}; 84int startGameDurations[] = { 85 120, 120, 150, 200 86}; 87int startGameLength = 4; 88 89// Game vars 90int obsPos; 91bool jumping; 92unsigned long jumpTimer = 0; 93unsigned long jumpDuration = 500; 94int score; 95 96LiquidCrystal lcd(RS, E, DB4, DB5, DB6, DB7); 97 98void setup() { 99 Serial.begin(9600); 100 101 pinMode(BUTTON, INPUT); 102 pinMode(GAME, INPUT); 103 pinMode(PR, INPUT); 104 pinMode(FSR_PIN, INPUT); 105 pinMode(PIEZO, OUTPUT); 106 107 pinMode(TRIG_PIN, OUTPUT); 108 pinMode(ECHO_PIN, INPUT); 109 110 lcd.begin(16, 2); 111} 112 113void loop() { 114 prValue = analogRead(PR); 115 116 if (prValue < 932) { 117 while (prValue < 932) { 118 sleep(); 119 } 120 } else { 121 // Waking up animation 122 playMelody(awakeNotes, awakeDurations, awakeLength); 123 lcd.setCursor(6, 0); 124 lcd.print("- - "); 125 lcd.setCursor(7, 1); 126 lcd.print("O "); 127 delay(1000); 128 129 lcd.setCursor(6, 0); 130 lcd.print("^ ^ "); 131 lcd.setCursor(7, 1); 132 lcd.print("- "); 133 delay(1000); 134 135 resetFace(); 136 delay(1000); 137 138 // Main awake loop 139 while (prValue >= 932) { 140 awake(); 141 } 142 143 // Faling asleep animation 144 playMelody(sleepNotes, sleepDurations, sleepLength); 145 lcd.setCursor(6, 0); 146 lcd.print("- - "); 147 lcd.setCursor(6, 1); 148 lcd.print("\\_/ "); 149 delay(1000); 150 151 lcd.setCursor(6, 0); 152 lcd.print("- - "); 153 lcd.setCursor(6, 1); 154 lcd.print(" O "); 155 delay(1000); 156 157 lcd.setCursor(6, 0); 158 lcd.print("- - "); 159 lcd.setCursor(6, 1); 160 lcd.print(" o "); 161 delay(1000); 162 } 163} 164 165void awake() { 166 buttonState = digitalRead(BUTTON); 167 168 // Tickle button logic 169 if (buttonState == HIGH && lastButtonState == LOW) { 170 buttonCount++; 171 172 if (buttonCount <= 3) { 173 lcd.setCursor(6, 0); 174 lcd.print("> < HAHA! "); 175 lcd.setCursor(6, 1); 176 lcd.print("\\_/ "); 177 playMelody(laughNotes, laughDurations, laughLength); 178 resetFace(); 179 } else { 180 lcd.setCursor(6, 0); 181 lcd.print("> < STOP! "); 182 lcd.setCursor(6, 1); 183 lcd.print(" ^ "); 184 playMelody(annoyedNotes, annoyedDurations, annoyedLength); 185 delay(500); 186 resetFace(); 187 } 188 } 189 190 lastButtonState = buttonState; 191 192 // Sensor checking loop (distance & force) 193 if (millis() - lastSensorCheck > sensorInterval) { 194 lastSensorCheck = millis(); 195 196 int forceValue = analogRead(FSR_PIN); 197 long distance = getDistance(); 198 199 // Force sensor priority 200 if (forceValue > 600) { 201 // Hard squeeze / squish 202 lcd.setCursor(6, 0); 203 lcd.print("X X Owie!"); 204 lcd.setCursor(6, 1); 205 lcd.print(" o "); 206 tone(PIEZO, 150, 200); // Low groan tone 207 delay(300); 208 resetFace(); 209 } 210 else if (forceValue > 100) { 211 // Gentle pet / soft touch 212 lcd.setCursor(6, 0); 213 lcd.print("<3 <3 Aw!"); 214 lcd.setCursor(6, 1); 215 lcd.print(" u "); 216 tone(PIEZO, 1046, 150); // Happy chirp 217 delay(300); 218 resetFace(); 219 } 220 // Distance sensor 221 else if (distance > 0 && distance < 60) { 222 // Too close, invading personal space 223 lcd.setCursor(6, 0); 224 lcd.print("O O Whoa!"); 225 lcd.setCursor(6, 1); 226 lcd.print(" o "); 227 tone(PIEZO, 988, 100); 228 } 229 else if (distance >= 60 && distance < 80) { 230 // Noticing user getting close 231 lcd.setCursor(6, 0); 232 lcd.print("o o Hmm? "); 233 lcd.setCursor(6, 1); 234 lcd.print(" - "); 235 } 236 else { 237 // Default happy state 238 resetFace(); 239 } 240 } 241 242 // Minigame button 243 gameState = digitalRead(GAME); 244 if (gameState == HIGH) { 245 runGame(); 246 } 247 248 // Random singing 249 int chance = random(1, 100); 250 if (chance == 10) { 251 lcd.setCursor(6, 0); 252 lcd.print("^ ^ "); 253 lcd.setCursor(6, 1); 254 lcd.print(" O LA LA"); 255 playMelody(singNotes, singDurations, singLength); 256 resetFace(); 257 } 258 259 prValue = analogRead(PR); 260 delay(30); 261} 262 263// Helper function - read distance (cm) 264long getDistance() { 265 digitalWrite(TRIG_PIN, LOW); 266 delayMicroseconds(2); 267 digitalWrite(TRIG_PIN, HIGH); 268 delayMicroseconds(10); 269 digitalWrite(TRIG_PIN, LOW); 270 271 long duration = pulseIn(ECHO_PIN, HIGH, 25000); 272 if (duration == 0) return 100; 273 return duration * 0.034 / 2; 274} 275 276// Helper function - cleanly reset face & wipe all trailing chars 277void resetFace() { 278 lcd.setCursor(6, 0); 279 lcd.print("^ ^ "); 280 lcd.setCursor(6, 1); 281 lcd.print("\\_/ "); 282} 283 284void sleep() { 285 lcd.setCursor(6, 0); 286 lcd.print("- - "); 287 lcd.setCursor(0, 1); 288 lcd.print(" "); 289 lcd.setCursor(7, 1); 290 lcd.print("- "); 291 delay(1000); 292 293 lcd.setCursor(6, 0); 294 lcd.print("- - "); 295 lcd.setCursor(7, 1); 296 lcd.print("o zZ "); 297 298 int chance = random(1, 50); 299 if (chance == 10) { 300 playMelody(sleepSingNotes, sleepSingDurations, sleepSingLength); 301 } 302 303 delay(1000); 304 prValue = analogRead(PR); 305} 306 307void playMelody(int notes[], int durations[], int length) { 308 for (int i = 0; i < length; i++) { 309 tone(PIEZO, notes[i], durations[i]); 310 delay(durations[i] + 20); 311 } 312 noTone(PIEZO); 313} 314 315void runGame() { 316 lcd.clear(); 317 318 obsPos = 15; 319 jumping = false; 320 score = 0; 321 322 delay(500); 323 playMelody(startGameNotes, startGameDurations, startGameLength); 324 325 while (true) { 326 lcd.clear(); 327 328 if (digitalRead(GAME) == HIGH && !jumping) { 329 jumping = true; 330 jumpTimer = millis(); 331 } 332 333 if (jumping && millis() - jumpTimer > jumpDuration) { 334 jumping = false; 335 } 336 337 if (jumping) { 338 lcd.setCursor(2, 0); 339 lcd.print("O"); 340 } else { 341 lcd.setCursor(2, 1); 342 lcd.print("O"); 343 } 344 345 if (obsPos >= 0) { 346 lcd.setCursor(obsPos, 1); 347 lcd.print("/\\"); 348 } 349 350 if (!jumping && obsPos == 2) { 351 lcd.clear(); 352 lcd.setCursor(4, 0); 353 lcd.print("GAME OVER"); 354 lcd.setCursor(4, 1); 355 lcd.print("Score: "); 356 lcd.print(score); 357 playMelody(sleepNotes, sleepDurations, sleepLength); 358 delay(2500); 359 360 lcd.clear(); 361 resetFace(); 362 return; 363 } 364 365 obsPos--; 366 367 if (obsPos < -1) { 368 obsPos = 15; 369 score++; 370 } 371 372 delay(120); 373 } 374}
Comments
Only logged in users can leave comments