Create a Puzzle Box with the help of the Arduino IoT Cloud!
Keeping your valuable items away from prying eyes can be hard sometimes, unless you put it in a big safe or something similar... but who has room for that? Instead, create your own puzzle box using the components from the IoT Bundle and some cardboard! We can't guarantee the safety of your belongings, but at least it will be a fun deterrent for potential thieves. Of course, we advise you to stash your candy in there... not actual valuables.
In order to open the box, which is held closed with a servo motor, you will have to turn the potentiometers until you get the right combination. The combination can be set through the dashboard on the Arduino IoT Cloud. An LED will help you guess, giving you colour feedbacks: the closer you are, the warmer the color. When the right combination is guessed, the box will open and a victorious melody will start playing, revealing whatever you have locked inside. In order to create our puzzle box we will need the following components:
This tutorial is part of a series of experiments that familiarize you with the Arduino RP2040 and IoT. All experiments can be built using the components contained in the IoT Bundle.
If you are new to the Arduino IoT Cloud, check out our Getting Started Guide.
To connect your board to the Arduino IoT Cloud, we will use the Puzzle Box Template. This template installs a specific sketch on your board and creates a dashboard that allows you to interact with your board: you don't need to write any code at all!
See the image below to understand how to set it up.
We will start by setting up the Arduino IoT Cloud by following the steps below:
We will start by adding four variables:
Before we upload the code to the board, let's create the dashboard with the sliders. We can navigate to Dashboards > Build Dashboard > ADD, then we can add four widget and link them to the variable as the following:
Now we are ready to go. Upload this sketch and play with the sliders to see the result in the serial monitor.
1#include "thingProperties.h"2void setup() {3 /* Initialize serial and wait for port to open: */4 Serial.begin(9600);5 /* This delay gives the chance to wait for a Serial Monitor without blocking if none is found */6 delay(1500);7 /* Defined in thingProperties.h */8 initProperties();9 /* Connect to Arduino IoT Cloud */10 ArduinoCloud.begin(ArduinoIoTPreferredConnection);11 setDebugMessageLevel(2);12 ArduinoCloud.printDebugInfo();13}14void loop() {15 ArduinoCloud.update();16}17void onSliderOneChange() {18 /* Add your code here to act upon SliderValue1 change */19 Serial.print("New combination: ");20 Serial.print(sliderOne);21 Serial.print(" ");22 Serial.print(sliderTwo);23 Serial.print(" ");24 Serial.println(sliderThree);25}26void onSliderTwoChange() {27 /* Add your code here to act upon SliderValue2 change */28 Serial.print("New combination: ");29 Serial.print(sliderOne);30 Serial.print(" ");31 Serial.print(sliderTwo);32 Serial.print(" ");33 Serial.println(sliderThree);34}35void onSliderThreeChange() {36 /* Add your code here to act upon SliderValue3 change */37 Serial.print("New combination: ");38 Serial.print(sliderOne);39 Serial.print(" ");40 Serial.print(sliderTwo);41 Serial.print(" ");42 Serial.println(sliderThree);43}44void onDisplayChange() {45 /* Add your code here to act upon Display change */46}
Add Potentiometers
Now it's time to connect our potentiometers, which are used to open your puzzle box. To read the value of the potentiometers we will only need an analogRead() on the correct pin. We are connecting them to Analog pins 0, 1, 2.
Note that the value of a potentiometer spans from 0 to 1023 making the combination impossible to guess. To map those values from 0 to 9 we will use the map() function,
1int PotOne = map(analogRead(A0), 0, 1023, 0, 9);
You won't see any changes until you build your interface in the next step but you can take a look at how to map the values from the potentiometers.
1#include "thingProperties.h"2void setup() {3 /* Initialize serial and wait for port to open: */4 Serial.begin(9600);5 /* This delay gives the chance to wait for a Serial Monitor without blocking if none is found */6 delay(1500);7 /* Defined in thingProperties.h */8 initProperties();9 /* Connect to Arduino IoT Cloud */10 ArduinoCloud.begin(ArduinoIoTPreferredConnection);11 setDebugMessageLevel(2);12 ArduinoCloud.printDebugInfo();13}14void loop() {15 ArduinoCloud.update();16 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);17 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);18 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);19}20void onSliderOneChange() {21 /* Add your code here to act upon SliderValue1 change */22 Serial.print("New combination: ");23 Serial.print(sliderOne);24 Serial.print(" ");25 Serial.print(sliderTwo);26 Serial.print(" ");27 Serial.println(sliderThree);28}29void onSliderTwoChange() {30 /* Add your code here to act upon SliderValue2 change */31 Serial.print("New combination: ");32 Serial.print(sliderOne);33 Serial.print(" ");34 Serial.print(sliderTwo);35 Serial.print(" ");36 Serial.println(sliderThree);37}38void onSliderThreeChange() {39 /* Add your code here to act upon SliderValue3 change */40 Serial.print("New combination: ");41 Serial.print(sliderOne);42 Serial.print(" ");43 Serial.print(sliderTwo);44 Serial.print(" ");45 Serial.println(sliderThree);46}47void onDisplayChange() {48/* Add your code here to act upon Display change */49}
Dashboard
We already have one dashboard allowing you to set the combination to your puzzle box. But now we are going to create a new one so you can use your phone to check the current position youāre at.
Start by creating a new dashboard, add a messenger widget and link it to the display variable. For printing the potentiometer values to the display you can use the following logic:
1String numberOne = String(PotOne);2String numberTwo = String(PotTwo);3String numberThree = String(PotThree);
Then simply assign all three strings to our display variable to see them in the messenger widget.
1display =String(numberOne + numberTwo + numberThree);
You will see a new message appear every time you turn one of the potentiometers.
Upload this code to see it working:
1#include "thingProperties.h"2void setup() {3 /* Initialize serial and wait for port to open: */4 Serial.begin(9600);5 /* This delay gives the chance to wait for a Serial Monitor without blocking if none is found */6 delay(1500);7 /* Defined in thingProperties.h */8 initProperties();9 /* Connect to Arduino IoT Cloud */10 ArduinoCloud.begin(ArduinoIoTPreferredConnection);11 setDebugMessageLevel(2);12 ArduinoCloud.printDebugInfo();13}14void loop() {15 ArduinoCloud.update();16 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);17 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);18 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);19 String numberOne = String(PotOne);20 String numberTwo = String(PotTwo);21 String numberThree = String(PotThree);22 display =String(numberOne + numberTwo + numberThree);23}24void onSliderOneChange() {25 /* Add your code here to act upon SliderValue1 change */26 Serial.print("New combination: ");27 Serial.print(sliderOne);28 Serial.print(" ");29 Serial.print(sliderTwo);30 Serial.print(" ");31 Serial.println(sliderThree);32}33void onSliderTwoChange() {34 /* Add your code here to act upon SliderValue2 change */35 Serial.print("New combination: ");36 Serial.print(sliderOne);37 Serial.print(" ");38 Serial.print(sliderTwo);39 Serial.print(" ");40 Serial.println(sliderThree);41}42void onSliderThreeChange() {43 /* Add your code here to act upon SliderValue3 change */44 Serial.print("New combination: ");45 Serial.print(sliderOne);46 Serial.print(" ");47 Serial.print(sliderTwo);48 Serial.print(" ");49 Serial.println(sliderThree);50}51void onDisplayChange() {52/* Add your code here to act upon Display change */53}
LCD
You could also use the LCD screen that comes with the kit, though we recommend using the dashboard because not all the components fit on the breadboard at the same time.
Note: The LCD has a 5V operating voltage, so you have to enable the 5V pad on the back of the board by soldering it. See here for more details.
We are using a 220 Ohm resistor and the brightness can be regulated by changing the output value of the Analog pin 3 from 0 to 255 with 0 being the maximum value. Add the following line inside void setup().
1analogWrite(A3, 0);
Upload this code to see "hello, world!" on your display.
1#include "thingProperties.h"2#include "LiquidCrystal.h"3/* initialize the library by associating any needed LCD interface pin with the arduino pin number it is connected to LCD screen pins */4const int rs = 12,5en = 11,6d4 = 2,7d5 = 3,8d6 = 4,9d7 = 5;10LiquidCrystal lcd(rs, en, d4, d5, d6, d7);11void setup() {12 /* Initialize serial and wait for port to open: */13 Serial.begin(9600);14 /* This delay gives the chance to wait for a Serial Monitor without blocking if none is found */15 delay(1500);16 /* Defined in thingProperties.h */17 initProperties();18 /* Connect to Arduino IoT Cloud */19 ArduinoCloud.begin(ArduinoIoTPreferredConnection);20 setDebugMessageLevel(2);21 ArduinoCloud.printDebugInfo();22 analogWrite(A3, 0); /* Set the brightness to its maximum value */23 /* set up the LCD's number of columns and rows: */24 lcd.begin(16, 2); /* Print a message to the LCD. */25 lcd.print("hello, world!");26}27void loop() {28 ArduinoCloud.update();29 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);30 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);31 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);32 String numberOne = String(PotOne);33 String numberTwo = String(PotTwo);34 String numberThree = String(PotThree);35 display =String(numberOne + numberTwo + numberThree);36}37void onSliderOneChange() {38 /* Add your code here to act upon SliderValue1 change */39 Serial.print("New combination: ");40 Serial.print(sliderOne);41 Serial.print(" ");42 Serial.print(sliderTwo);43 Serial.print(" ");44 Serial.println(sliderThree);45}46void onSliderTwoChange() {47 /* Add your code here to act upon SliderValue2 change */48 Serial.print("New combination: ");49 Serial.print(sliderOne);50 Serial.print(" ");51 Serial.print(sliderTwo);52 Serial.print(" ");53 Serial.println(sliderThree);54}55void onSliderThreeChange() {56 /* Add your code here to act upon SliderValue3 change */57 Serial.print("New combination: ");58 Serial.print(sliderOne);59 Serial.print(" ");60 Serial.print(sliderTwo);61 Serial.print(" ");62 Serial.println(sliderThree);63}64void onDisplayChange() {65/* Add your code here to act upon Display change */66}
RGB LED
We will use the RGB LED as a feedback to help people guessing the combination, the closer they get to the right value the warmer the colour of the LED, spanning from blue, aqua, yellow and red.
RGB LED
To control the RGB we can use the following logic:
1setColor(0, 0, 255); /* blue */ 2 delay(1000); 3 setColor(0, 255, 255); /* aqua */4 delay(1000); 5 setColor(255, 255, 0); /* yellow */6 delay(1000); 7 setColor(255, 0, 0); /* Red */8 delay(1000);
You can use this example sketch to see the RGB in action!
1#include "thingProperties.h"2#include "LiquidCrystal.h"3/* RGB LED pins */4int redPin = 6;5int greenPin = 8;6int bluePin = 7;7bool start = true;8/* initialize the library by associating any needed LCD interface pin with the arduino pin number it is connected to LCD screen pins */9const int rs = 12,10en = 11,11d4 = 2,12d5 = 3,13d6 = 4,14d7 = 5;15LiquidCrystal lcd(rs, en, d4, d5, d6, d7);16void setup() {17 /* Initialize serial and wait for port to open: */18 Serial.begin(9600);19 /* This delay gives the chance to wait for a Serial Monitor without blocking if none is found */20 delay(1500);21 /* Defined in thingProperties.h */22 initProperties();23 /* Connect to Arduino IoT Cloud */24 ArduinoCloud.begin(ArduinoIoTPreferredConnection);25 setDebugMessageLevel(2);26 ArduinoCloud.printDebugInfo();27 analogWrite(A3, 0); /* Set the brightness to its maximum value */28 /* set up the LCD's number of columns and rows: */29 lcd.begin(16, 2); /* Print a message to the LCD. */30 pinMode(redPin, OUTPUT);31 pinMode(greenPin, OUTPUT);32 pinMode(bluePin, OUTPUT);33}34void loop() {35 ArduinoCloud.update();36 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);37 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);38 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);39 lcd.setCursor(0, 0);40 lcd.print(PotOne);41 lcd.setCursor(2, 0);42 lcd.print(PotTwo);43 lcd.setCursor(4, 0);44 lcd.print(PotThree);45 String numberOne = String(PotOne);46 String numberTwo = String(PotTwo);47 String numberThree = String(PotThree);48 display =String(numberOne + numberTwo + numberThree);49 setColor(0, 0, 255); /* blue */50 delay(1000); 51 setColor(0, 255, 255); /* aqua */52 delay(1000); 53 setColor(255, 255, 0); /* yellow */54 delay(1000); 55 setColor(255, 0, 0); /* Red */56 delay(1000);57}58void onSliderOneChange() {59 /* Add your code here to act upon SliderValue1 change */60 Serial.print("New combination: ");61 Serial.print(sliderOne);62 Serial.print(" ");63 Serial.print(sliderTwo);64 Serial.print(" ");65 Serial.println(sliderThree);66}67void onSliderTwoChange() {68 /* Add your code here to act upon SliderValue2 change */69 Serial.print("New combination: ");70 Serial.print(sliderOne);71 Serial.print(" ");72 Serial.print(sliderTwo);73 Serial.print(" ");74 Serial.println(sliderThree);75}76void onSliderThreeChange() {77 /* Add your code here to act upon SliderValue3 change */78 Serial.print("New combination: ");79 Serial.print(sliderOne);80 Serial.print(" ");81 Serial.print(sliderTwo);82 Serial.print(" ");83 Serial.println(sliderThree);84}85/* Send RGB values to the LED pins */86void setColor(int red, int green, int blue) {87 analogWrite(redPin, red);88 analogWrite(greenPin, green);89 analogWrite(bluePin, blue);90}91void onDisplayChange() {92/* Add your code here to act upon Display change */93}
Now we are starting to put things together: we have connected the potentiometers to unlock the box, created two dashboards for setting the combination and seeing your current position, as well as installed a RGB which will tell you how close you are to the right combination.
giveColorFeedback()
to set the color of the RGB LED when the absolute value of each potentiometer is closer than a certain threshold to the correct combination.1void giveColorFeedback(int PotOne, int PotTwo, int PotThree){...}
A boolean variable bool start = true; is used to detect when the combination has already been guessed, so to avoid reopening the the box at every loop.
Upload this example sketch and turn the potentiometers to see it in action.
1#include "LiquidCrystal.h"2#include "SPI.h"3#include "thingProperties.h"4/* RGB LED pins */5int redPin = 6;6int greenPin = 8;7int bluePin = 7;8/* LCD screen pins */9const int rs = 12,10 en = 11,11 d4 = 2,12 d5 = 3,13 d6 = 4,14 d7 = 5;15bool start = true;16LiquidCrystal lcd(rs, en, d4, d5, d6, d7);17void setup() {18 pinMode(redPin, OUTPUT);19 pinMode(greenPin, OUTPUT);20 pinMode(bluePin, OUTPUT);21 analogWrite(A3, 0); /* set the brightness of the LCD screen to the maximum value */22 Serial.begin(9600);23 delay(1500);24 initProperties();25 ArduinoCloud.begin(ArduinoIoTPreferredConnection);26 setDebugMessageLevel(2);27 ArduinoCloud.printDebugInfo();28 lcd.begin(16, 2); /* begin LCD screen with 16 columns and 2 rows */29}30void loop() {31 ArduinoCloud.update();32 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);33 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);34 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);35 lcd.setCursor(0, 0);36 lcd.print(PotOne);37 lcd.setCursor(2, 0);38 lcd.print(PotTwo);39 lcd.setCursor(4, 0);40 lcd.print(PotThree);41 String numberOne = String(PotOne);42 String numberTwo = String(PotTwo);43 String numberThree = String(PotThree);44 display =String(numberOne + numberTwo + numberThree);45 if (start) {46 giveColorFeedback(PotOne, PotTwo, PotThree);47 if (PotOne == sliderOne && PotTwo == sliderTwo && PotThree == sliderThree) 48 {49 blinkGreenLed();50 start = false;51 }52 }53 if (!start) {54 if (PotOne == 0 && PotTwo == 0 && PotThree == 0) {55 start = true;56 }57 }58}59/* Give feedback based on how close the potentiometer are to the combination value60The more it's close the warmer is the color of the LED */61void giveColorFeedback(int PotOne, int PotTwo, int PotThree) {62 if (abs(PotOne - sliderOne) <= 1 && abs(PotTwo - sliderTwo) <= 1 && abs(PotThree - sliderThree) <= 1 ) {63 /* Red */64 setColor(255, 0, 0);65 }66 else if (abs(PotOne - sliderOne) <= 3 && abs(PotTwo - sliderTwo) <= 3 && abs(PotThree - sliderThree) <= 3 ) {67 /* yellow */68 setColor(255, 255, 0);69 }70 else if (abs(PotOne - sliderOne) <= 4 && abs(PotTwo - sliderTwo) <= 4 && abs(PotThree - sliderThree) <= 4 ) {71 /* aqua */72 setColor(0, 255, 255);73 }74 else {75 /* blue */76 setColor(0, 0, 255);77 }78}79void blinkGreenLed() {80 for (int a = 0; a < 2; a++) {81 for (int b = 0; b <= 255; b += 5) {82 setColor(0, b, 0);83 delay(5);84 }85 for (int b = 255; b >= 0; b -= 5) {86 setColor(0, b, 0);87 delay(5);88 }89 }90 for (int b = 0; b <= 255; b += 5) {91 setColor(0, b, 0);92 delay(5);93 }94}95void initLCD() {96 Serial.println(">>> begin LCD");97 lcd.begin(16, 2);98 lcd.print(" Initialising");99 100 delay(100);101}102void onSliderOneChange() {103 /* Add your code here to act upon SliderValue1 change */104 Serial.print("New combination: ");105 Serial.print(sliderOne);106 Serial.print(" ");107 Serial.print(sliderTwo);108 Serial.print(" ");109 Serial.println(sliderThree);110}111void onSliderTwoChange() {112 /* Add your code here to act upon SliderValue2 change */113 Serial.print("New combination: ");114 Serial.print(sliderOne);115 Serial.print(" ");116 Serial.print(sliderTwo);117 Serial.print(" ");118 Serial.println(sliderThree);119}120void onSliderThreeChange() {121 /* Add your code here to act upon SliderValue3 change */122 Serial.print("New combination: ");123 Serial.print(sliderOne);124 Serial.print(" ");125 Serial.print(sliderTwo);126 Serial.print(" ");127 Serial.println(sliderThree);128}129/* Send RGB values to the LED pins */130void setColor(int red, int green, int blue) {131 analogWrite(redPin, red);132 analogWrite(greenPin, green);133 analogWrite(bluePin, blue);134}135void onDisplayChange() {136/* Add your code here to act upon Display change 137}
Buzzer
We will use the buzzer to play a melody when the box is opened. Connect the buzzer to digital pin 10, as shown in the picture below.
Now, navigate into the Arduino Web Editor through Thing > Sketch tab > open full editor. This will open up our automatically generated sketch in the full Arduino Web Editor. Next we need to add an extra tab containing all the necessary notes to play the song. Click the arrow on the right side to add a new tab called
"Melody.h"
and add the code below.1#define NOTE_B0 312#define NOTE_C1 333#define NOTE_CS1 354#define NOTE_D1 375#define NOTE_DS1 396#define NOTE_E1 417#define NOTE_F1 448#define NOTE_FS1 469#define NOTE_G1 4910#define NOTE_GS1 5211#define NOTE_A1 5512#define NOTE_AS1 5813#define NOTE_B1 6214#define NOTE_C2 6515#define NOTE_CS2 6916#define NOTE_D2 7317#define NOTE_DS2 7818#define NOTE_E2 8219#define NOTE_F2 8720#define NOTE_FS2 9321#define NOTE_G2 9822#define NOTE_GS2 10423#define NOTE_A2 11024#define NOTE_AS2 11725#define NOTE_B2 12326#define NOTE_C3 13127#define NOTE_CS3 13928#define NOTE_D3 14729#define NOTE_DS3 15630#define NOTE_E3 16531#define NOTE_F3 17532#define NOTE_FS3 18533#define NOTE_G3 19634#define NOTE_GS3 20835#define NOTE_A3 22036#define NOTE_AS3 23337#define NOTE_B3 24738#define NOTE_C4 26239#define NOTE_CS4 27740#define NOTE_D4 29441#define NOTE_DS4 31142#define NOTE_E4 33043#define NOTE_F4 34944#define NOTE_FS4 37045#define NOTE_G4 39246#define NOTE_GS4 41547#define NOTE_A4 44048#define NOTE_AS4 46649#define NOTE_B4 49450#define NOTE_C5 52351#define NOTE_CS5 55452#define NOTE_D5 58753#define NOTE_DS5 62254#define NOTE_E5 65955#define NOTE_F5 69856#define NOTE_FS5 74057#define NOTE_G5 78458#define NOTE_GS5 83159#define NOTE_A5 88060#define NOTE_AS5 93261#define NOTE_B5 98862#define NOTE_C6 104763#define NOTE_CS6 110964#define NOTE_D6 117565#define NOTE_DS6 124566#define NOTE_E6 131967#define NOTE_F6 139768#define NOTE_FS6 148069#define NOTE_G6 156870#define NOTE_GS6 166171#define NOTE_A6 176072#define NOTE_AS6 186573#define NOTE_B6 197674#define NOTE_C7 209375#define NOTE_CS7 221776#define NOTE_D7 234977#define NOTE_DS7 248978#define NOTE_E7 263779#define NOTE_F7 279480#define NOTE_FS7 296081#define NOTE_G7 313682#define NOTE_GS7 332283#define NOTE_A7 352084#define NOTE_AS7 372985#define NOTE_B7 395186#define NOTE_C8 418687#define NOTE_CS8 443588#define NOTE_D8 469989#define NOTE_DS8 497890/* notes in the melody: */91int melody[] = {92 NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C493};94/* note durations: 4 = quarter note, 8 = eighth note, etc.: */95int noteDurations[] = {96 4, 8, 8, 4, 4, 4, 4, 497};98void playMelody() {99 /* iterate over the notes of the melody: */100 for (int thisNote = 0; thisNote < 8; thisNote++) {101 /* to calculate the note duration, take one second divided by the note type. */102 /*e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.*/103 int noteDuration = 1000 / noteDurations[thisNote];104 tone(10, melody[thisNote], noteDuration);105 /* to distinguish the notes, set a minimum time between them. */106 /* the note's duration + 30% seems to work well: */107 int pauseBetweenNotes = noteDuration * 1.30;108 delay(pauseBetweenNotes);109 /* stop the tone playing: */110 noTone(10);111 }112}
Now, we need to go back to our main sketch to play the melody. In order to use the notes we need to add " #include "Melody.h" " at the top of our code and inside setup() we need to add our buzzerPin as Output. To test our melody we can call playMelody() inside loop() if the combination has been set right.
1#include "LiquidCrystal.h"2#include "SPI.h"3#include "thingProperties.h"4#include "Melody.h"5/* RGB LED pins */6int redPin = 6;7int greenPin = 8;8int bluePin = 7;9/* LCD screen pins */10const int rs = 12,11 en = 11,12 d4 = 2,13 d5 = 3,14 d6 = 4,15 d7 = 5;16bool start = true;17LiquidCrystal lcd(rs, en, d4, d5, d6, d7);18void setup() {19 pinMode(redPin, OUTPUT);20 pinMode(greenPin, OUTPUT);21 pinMode(bluePin, OUTPUT);22 analogWrite(A3, 0); /* set the brightness of the LCD screen to the maximum value */23 Serial.begin(9600);24 delay(1500);25 initProperties();26 ArduinoCloud.begin(ArduinoIoTPreferredConnection);27 setDebugMessageLevel(2);28 ArduinoCloud.printDebugInfo();29 lcd.begin(16, 2); /* begin LCD screen with 16 columns and 2 rows */30}31void loop() {32 ArduinoCloud.update();33 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);34 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);35 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);36 lcd.setCursor(0, 0);37 lcd.print(PotOne);38 lcd.setCursor(2, 0);39 lcd.print(PotTwo);40 lcd.setCursor(4, 0);41 lcd.print(PotThree);42 String numberOne = String(PotOne);43 String numberTwo = String(PotTwo);44 String numberThree = String(PotThree);45 display =String(numberOne + numberTwo + numberThree);46 if (start) {47 giveColorFeedback(PotOne, PotTwo, PotThree);48 if (PotOne == sliderOne && PotTwo == sliderTwo && PotThree == sliderThree) 49 {50 blinkGreenLed();51 start = false;52 playMelody();53 }54 }55 if (!start) {56 if (PotOne == 0 && PotTwo == 0 && PotThree == 0) {57 start = true;58 }59 }60}61/* Give feedback based on how close the potentiometer are to the combination value62The more it's close the warmer is the color of the LED */63void giveColorFeedback(int PotOne, int PotTwo, int PotThree) {64 if (abs(PotOne - sliderOne) <= 1 && abs(PotTwo - sliderTwo) <= 1 && abs(PotThree - sliderThree) <= 1 ) {65 /* Red */66 setColor(255, 0, 0);67 }68 else if (abs(PotOne - sliderOne) <= 3 && abs(PotTwo - sliderTwo) <= 3 && abs(PotThree - sliderThree) <= 3 ) {69 /* yellow */70 setColor(255, 255, 0);71 }72 else if (abs(PotOne - sliderOne) <= 4 && abs(PotTwo - sliderTwo) <= 4 && abs(PotThree - sliderThree) <= 4 ) {73 /* aqua */74 setColor(0, 255, 255);75 }76 else {77 /* blue */78 setColor(0, 0, 255);79 }80}81void blinkGreenLed() {82 for (int a = 0; a < 2; a++) {83 for (int b = 0; b <= 255; b += 5) {84 setColor(0, b, 0);85 delay(5);86 }87 for (int b = 255; b >= 0; b -= 5) {88 setColor(0, b, 0);89 delay(5);90 }91 }92 for (int b = 0; b <= 255; b += 5) {93 setColor(0, b, 0);94 delay(5);95 }96}97void initLCD() {98 Serial.println(">>> begin LCD");99 lcd.begin(16, 2);100 lcd.print(" Initialising");101 102 delay(100);103}104void onSliderOneChange() {105 /* Add your code here to act upon SliderValue1 change */106 Serial.print("New combination: ");107 Serial.print(sliderOne);108 Serial.print(" ");109 Serial.print(sliderTwo);110 Serial.print(" ");111 Serial.println(sliderThree);112}113void onSliderTwoChange() {114 /* Add your code here to act upon SliderValue2 change */115 Serial.print("New combination: ");116 Serial.print(sliderOne);117 Serial.print(" ");118 Serial.print(sliderTwo);119 Serial.print(" ");120 Serial.println(sliderThree);121}122void onSliderThreeChange() {123 /* Add your code here to act upon SliderValue3 change */124 Serial.print("New combination: ");125 Serial.print(sliderOne);126 Serial.print(" ");127 Serial.print(sliderTwo);128 Serial.print(" ");129 Serial.println(sliderThree);130}131/* Send RGB values to the LED pins */132void setColor(int red, int green, int blue) {133 analogWrite(redPin, red);134 analogWrite(greenPin, green);135 analogWrite(bluePin, blue);136}137void playMelody() {138 /* iterate over the notes of the melody: */139 for (int thisNote = 0; thisNote < 8; thisNote++) {140 /* to calculate the note duration, take one second divided by the note type. */141 /*e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. */142 int noteDuration = 1000 / noteDurations[thisNote];143 tone(10, melody[thisNote], noteDuration);144 /* to distinguish the notes, set a minimum time between them. */145 /* the note's duration + 30% seems to work well: */146 int pauseBetweenNotes = noteDuration * 1.30;147 delay(pauseBetweenNotes);148 /* stop the tone playing: */149 noTone(10);150 }151}152void onDisplayChange() {153/* Add your code here to act upon Display change */154}
Servo Motor
Note: for the servo motor you will need a 9V battery which is not included in the IoT Bundle! Alternatively you can use another external power supply such as a phone charger with open ended cables.
The servo motor is the lock of our box, we will need it to turn 90 degrees when the combination is correct, so that the box will open. Connecting the servo only requires three wires though you will need a 9V battery to power the servo motor. Connect 9V, GND and pin9 as shown below.
To use the servo motor we need to
#include "Servo.h"
at the top of our code as well as set starting position to 0 and include the Servo myservo
object. Now we can create two functions, one for opening the box and one for closing it.1#include "LiquidCrystal.h"2#include "SPI.h"3#include "thingProperties.h"4#include "Melody.h"5#include "Servo.h"6int pos = 0;7Servo myservo;8/* RGB LED pins */9int redPin = 6;10int greenPin = 8;11int bluePin = 7;12/* LCD screen pins */13const int rs = 12,14 en = 11,15 d4 = 2,16 d5 = 3,17 d6 = 4,18 d7 = 5;19bool start = true;20LiquidCrystal lcd(rs, en, d4, d5, d6, d7);21void setup() {22 pinMode(redPin, OUTPUT);23 pinMode(greenPin, OUTPUT);24 pinMode(bluePin, OUTPUT);25 analogWrite(A3, 0); /* set the brightness of the LCD screen to the maximum value */26 Serial.begin(9600);27 delay(1500);28 initProperties();29 ArduinoCloud.begin(ArduinoIoTPreferredConnection);30 setDebugMessageLevel(2);31 ArduinoCloud.printDebugInfo();32 lcd.begin(16, 2); /* begin LCD screen with 16 columns and 2 rows */33myservo.attach(9);34myservo.write(pos);35}36void loop() {37 ArduinoCloud.update();38 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);39 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);40 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);41 lcd.setCursor(0, 0);42 lcd.print(PotOne);43 lcd.setCursor(2, 0);44 lcd.print(PotTwo);45 lcd.setCursor(4, 0);46 lcd.print(PotThree);47 String numberOne = String(PotOne);48 String numberTwo = String(PotTwo);49 String numberThree = String(PotThree);50 display =String(numberOne + numberTwo + numberThree);51 if (start) {52 giveColorFeedback(PotOne, PotTwo, PotThree);53 if (PotOne == sliderOne && PotTwo == sliderTwo && PotThree == sliderThree) 54 {55 blinkGreenLed();56 start = false;57 open_the_box();58 playMelody();59 }60 }61 if (!start) {62 if (PotOne == 0 && PotTwo == 0 && PotThree == 0) {63 start = true;64 close_the_box();65 }66 }67}68/* Give feedback based on how close the potentiometer are to the combination value69The more it's close the warmer is the color of the LED */70void giveColorFeedback(int PotOne, int PotTwo, int PotThree) {71 if (abs(PotOne - sliderOne) <= 1 && abs(PotTwo - sliderTwo) <= 1 && abs(PotThree - sliderThree) <= 1 ) {72 /* Red */73 setColor(255, 0, 0);74 }75 else if (abs(PotOne - sliderOne) <= 3 && abs(PotTwo - sliderTwo) <= 3 && abs(PotThree - sliderThree) <= 3 ) {76 /* yellow */77 setColor(255, 255, 0);78 }79 else if (abs(PotOne - sliderOne) <= 4 && abs(PotTwo - sliderTwo) <= 4 && abs(PotThree - sliderThree) <= 4 ) {80 /* aqua */81 setColor(0, 255, 255);82 }83 else {84 /* blue */85 setColor(0, 0, 255);86 }87}88void blinkGreenLed() {89 for (int a = 0; a < 2; a++) {90 for (int b = 0; b <= 255; b += 5) {91 setColor(0, b, 0);92 delay(5);93 }94 for (int b = 255; b >= 0; b -= 5) {95 setColor(0, b, 0);96 delay(5);97 }98 }99 for (int b = 0; b <= 255; b += 5) {100 setColor(0, b, 0);101 delay(5);102 }103}104void open_the_box() {105 for (pos = 0; pos <= 90; pos += 1) { /* goes from 0 degrees to 90 degrees */106 myservo.write(pos); /* tell servo to go to position in variable 'pos' */107 delay(15); /* waits 15ms for the servo to reach the position */108 }109}110void close_the_box() { 111 for (pos = 90; pos >= 0; pos -= 1) { /* goes from 90 degrees to 0 degrees */112 myservo.write(pos); /* tell servo to go to position in variable 'pos' */113 delay(15); /* waits 15ms for the servo to reach the position */114 }115}116void initLCD() {117 Serial.println(">>> begin LCD");118 lcd.begin(16, 2);119 lcd.print(" Initialising");120 121 delay(100);122}123void onSliderOneChange() {124 /* Add your code here to act upon SliderValue1 change */125 Serial.print("New combination: ");126 Serial.print(sliderOne);127 Serial.print(" ");128 Serial.print(sliderTwo);129 Serial.print(" ");130 Serial.println(sliderThree);131}132void onSliderTwoChange() {133 /* Add your code here to act upon SliderValue2 change */134 Serial.print("New combination: ");135 Serial.print(sliderOne);136 Serial.print(" ");137 Serial.print(sliderTwo);138 Serial.print(" ");139 Serial.println(sliderThree);140}141void onSliderThreeChange() {142 /* Add your code here to act upon SliderValue3 change */143 Serial.print("New combination: ");144 Serial.print(sliderOne);145 Serial.print(" ");146 Serial.print(sliderTwo);147 Serial.print(" ");148 Serial.println(sliderThree);149}150/* Send RGB values to the LED pins */151void setColor(int red, int green, int blue) {152 analogWrite(redPin, red);153 analogWrite(greenPin, green);154 analogWrite(bluePin, blue);155}156void onDisplayChange() {157/* Add your code here to act upon Display change */158}
Note that in order to turn the servo back and close the box all you'll have to do is to turn all potentiometer to 0.
It wouldn't be a box without a box, so download the case file below and use it as guide to build your own. Note that we used a 2mm cardboard.
This tutorial is part of a series of experiments that familiarize you with the Arduino IoT Bundle. All experiments can be built using the components contained in the IoT Bundle.