Puzzle Box with Arduino IoT Bundle

Protect your valuables with a puzzle.

Components and Supplies

Apps and Online Services

About This Project

Create a Puzzle Box with the help of the Arduino Cloud!

Keeping your valuable items away from prying eyes can be hard sometimes unless you put them 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 a Nutshell

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 Cloud. An LED will help you guess, giving you color feedback: 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. To create our puzzle box we will need the following components:

  • Buzzer
  • RGB LED
  • 3 potentiometers
  • Servo motor
Arduino IoT Bundle

Learning Goals

  • Introducing the Arduino Cloud
  • Introducing the Arduino IoT Remote app
  • Playing a melody with the piezo buzzer
  • Creating an Arduino Cloud Dashboard

Want to Know More

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.

Setting up the Arduino Cloud

If you are new to the Arduino Cloud, check out our Getting Started Guide.

Template

To connect your board to the Arduino 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.

Thing overview
Thing overview

We will start by setting up the Arduino Cloud by following the steps below:

  • Creating a Thing
  • Attaching a Device
  • Adding Variables
  • Adding Network credentials
Arduino IoT Bundle

Variables

We will start by adding four variables:

  • display
    -
    String
    -
    READ & WRITE

  • sliderOne
    -
    INT
    -
    READ & WRITE

  • sliderThree
    -
    TIME
    -
    READ & WRITE

  • sliderTwo
    -
    INT
    -
    READ & WRITE

Dashboard

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:

  • Slider widget -> sliderOne
  • Slider widget -> sliderTwo
  • Slider widget -> sliderThree
Arduino IoT Bundle

Setup Hardware & Sketch

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 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.

Arduino IoT Bundle
Arduino IoT Bundle

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 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}

Display

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.

Arduino IoT Bundle
Arduino IoT Bundle

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 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.

Arduino IoT Bundle
Arduino IoT Bundle

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 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 feedback to help people guess the combination, the closer they get to the right value the warmer the color of the LED, spanning from blue, aqua, yellow and red.

RGB LED
RGB LED

RGB LED

Arduino IoT Bundle
Arduino IoT Bundle
Arduino IoT Bundle
Arduino IoT Bundle

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 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}

Connect It to the Arduino Cloud

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 an RGB which will tell you how close you are to the right combination.

  • Note that we will use the function
    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){...}
  • Note that the initial value is set to 1, it will change only if you modify the values of the sliders on the Cloud dashboard. If you reset the board the combination will be back to the default value.

A boolean variable bool start = true; is used to detect when the combination has already been guessed, 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 value
60The 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.

Arduino IoT Bundle
Arduino IoT Bundle
Arduino IoT Bundle
Arduino IoT Bundle

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 31
2#define NOTE_C1 33
3#define NOTE_CS1 35
4#define NOTE_D1 37
5#define NOTE_DS1 39
6#define NOTE_E1 41
7#define NOTE_F1 44
8#define NOTE_FS1 46
9#define NOTE_G1 49
10#define NOTE_GS1 52
11#define NOTE_A1 55
12#define NOTE_AS1 58
13#define NOTE_B1 62
14#define NOTE_C2 65
15#define NOTE_CS2 69
16#define NOTE_D2 73
17#define NOTE_DS2 78
18#define NOTE_E2 82
19#define NOTE_F2 87
20#define NOTE_FS2 93
21#define NOTE_G2 98
22#define NOTE_GS2 104
23#define NOTE_A2 110
24#define NOTE_AS2 117
25#define NOTE_B2 123
26#define NOTE_C3 131
27#define NOTE_CS3 139
28#define NOTE_D3 147
29#define NOTE_DS3 156
30#define NOTE_E3 165
31#define NOTE_F3 175
32#define NOTE_FS3 185
33#define NOTE_G3 196
34#define NOTE_GS3 208
35#define NOTE_A3 220
36#define NOTE_AS3 233
37#define NOTE_B3 247
38#define NOTE_C4 262
39#define NOTE_CS4 277
40#define NOTE_D4 294
41#define NOTE_DS4 311
42#define NOTE_E4 330
43#define NOTE_F4 349
44#define NOTE_FS4 370
45#define NOTE_G4 392
46#define NOTE_GS4 415
47#define NOTE_A4 440
48#define NOTE_AS4 466
49#define NOTE_B4 494
50#define NOTE_C5 523
51#define NOTE_CS5 554
52#define NOTE_D5 587
53#define NOTE_DS5 622
54#define NOTE_E5 659
55#define NOTE_F5 698
56#define NOTE_FS5 740
57#define NOTE_G5 784
58#define NOTE_GS5 831
59#define NOTE_A5 880
60#define NOTE_AS5 932
61#define NOTE_B5 988
62#define NOTE_C6 1047
63#define NOTE_CS6 1109
64#define NOTE_D6 1175
65#define NOTE_DS6 1245
66#define NOTE_E6 1319
67#define NOTE_F6 1397
68#define NOTE_FS6 1480
69#define NOTE_G6 1568
70#define NOTE_GS6 1661
71#define NOTE_A6 1760
72#define NOTE_AS6 1865
73#define NOTE_B6 1976
74#define NOTE_C7 2093
75#define NOTE_CS7 2217
76#define NOTE_D7 2349
77#define NOTE_DS7 2489
78#define NOTE_E7 2637
79#define NOTE_F7 2794
80#define NOTE_FS7 2960
81#define NOTE_G7 3136
82#define NOTE_GS7 3322
83#define NOTE_A7 3520
84#define NOTE_AS7 3729
85#define NOTE_B7 3951
86#define NOTE_C8 4186
87#define NOTE_CS8 4435
88#define NOTE_D8 4699
89#define NOTE_DS8 4978
90/* notes in the melody: */
91int melody[] = {
92 NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
93};
94/* note durations: 4 = quarter note, 8 = eighth note, etc.: */
95int noteDurations[] = {
96 4, 8, 8, 4, 4, 4, 4, 4
97};
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 value
62The 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.

Arduino IoT Bundle
Arduino IoT Bundle
Arduino IoT Bundle
Arduino IoT Bundle

To use the servo motor we need to

#include "Servo.h"
at the top of our code as well as set the 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 value
69The 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 potentiometers to 0.

Build Your Puzzle Box

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.

Want to Know More?

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.

Full Code

1#include "LiquidCrystal.h"
2#include "SPI.h"
3#include "thingProperties.h"
4#include "melody.h"
5#include "Servo.h"
6
7int pos = 0;
8Servo myservo;
9
10/* RGB LED pins */
11int redPin = 6;
12int greenPin = 8;
13int bluePin = 7;
14
15/* LCD screen pins */
16const int rs = 12,
17 en = 11,
18 d4 = 2,
19 d5 = 3,
20 d6 = 4,
21 d7 = 5;
22
23bool start = true;
24
25LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
26
27void setup() {
28 pinMode(redPin, OUTPUT);
29 pinMode(greenPin, OUTPUT);
30 pinMode(bluePin, OUTPUT);
31 analogWrite(A3, 0); /* set the brightness of the LCD screen to the maximum value */
32 Serial.begin(9600);
33 delay(1500);
34 initProperties();
35 ArduinoCloud.begin(ArduinoIoTPreferredConnection{{if .Broker}}, false, "{{.Broker}}"{{end}});
36 setDebugMessageLevel(2);
37 ArduinoCloud.printDebugInfo();
38 lcd.begin(16, 2); /* begin LCD screen with 16 columns and 2 rows */
39
40myservo.attach(9);
41myservo.write(pos);
42}
43
44void loop() {
45 ArduinoCloud.update();
46 int PotOne = map(analogRead(A0), 0, 1023, 0, 9);
47 int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);
48 int PotThree = map(analogRead(A2), 0, 1023, 0, 9);
49 lcd.setCursor(0, 0);
50 lcd.print(PotOne);
51 lcd.setCursor(2, 0);
52 lcd.print(PotTwo);
53 lcd.setCursor(4, 0);
54 lcd.print(PotThree);
55
56 String numberOne = String(PotOne);
57 String numberTwo = String(PotTwo);
58 String numberThree = String(PotThree);
59
60 display =String(numberOne + numberTwo + numberThree);
61
62 if (start) {
63 giveColorFeedback(PotOne, PotTwo, PotThree);
64 if (PotOne == sliderOne && PotTwo == sliderTwo && PotThree == sliderThree)
65 {
66 blinkGreenLed();
67 start = false;
68 open_the_box();
69 playMelody();
70 }
71 }
72 if (!start) {
73 if (PotOne == 0 && PotTwo == 0 && PotThree == 0) {
74 start = true;
75 close_the_box();
76 }
77 }
78}
79
80/* Give feedback based on how close the potentiometer are to the combination value
81The more it's close the warmer is the color of the LED */
82void giveColorFeedback(int PotOne, int PotTwo, int PotThree) {
83 if (abs(PotOne - sliderOne) <= 1 && abs(PotTwo - sliderTwo) <= 1 && abs(PotThree - sliderThree) <= 1 ) {
84 /* Red */
85 setColor(255, 0, 0);
86 }
87 else if (abs(PotOne - sliderOne) <= 3 && abs(PotTwo - sliderTwo) <= 3 && abs(PotThree - sliderThree) <= 3 ) {
88 /* yellow */
89 setColor(255, 255, 0);
90 }
91 else if (abs(PotOne - sliderOne) <= 4 && abs(PotTwo - sliderTwo) <= 4 && abs(PotThree - sliderThree) <= 4 ) {
92 /* aqua */
93 setColor(0, 255, 255);
94 }
95 else {
96 /* blue */
97 setColor(0, 0, 255);
98 }
99}
100
101void blinkGreenLed() {
102 for (int a = 0; a < 2; a++) {
103 for (int b = 0; b <= 255; b += 5) {
104 setColor(0, b, 0);
105 delay(5);
106 }
107 for (int b = 255; b >= 0; b -= 5) {
108 setColor(0, b, 0);
109 delay(5);
110 }
111 }
112 for (int b = 0; b <= 255; b += 5) {
113 setColor(0, b, 0);
114 delay(5);
115 }
116}
117
118void open_the_box() {
119 for (pos = 0; pos <= 90; pos += 1) { /* goes from 0 degrees to 90 degrees */
120 myservo.write(pos); /* tell servo to go to position in variable 'pos' */
121 delay(15); /* waits 15ms for the servo to reach the position */
122 }
123}
124
125void close_the_box() {
126 for (pos = 90; pos >= 0; pos -= 1) { /* goes from 90 degrees to 0 degrees */
127 myservo.write(pos); /* tell servo to go to position in variable 'pos' */
128 delay(15); /* waits 15ms for the servo to reach the position */
129 }
130}
131
132void initLCD() {
133 Serial.println(">>> begin LCD");
134 lcd.begin(16, 2);
135 lcd.print(" Initialising");
136
137 delay(100);
138}
139
140void onSliderOneChange() {
141 /* Add your code here to act upon SliderValue1 change */
142 Serial.print("New combination: ");
143 Serial.print(sliderOne);
144 Serial.print(" ");
145 Serial.print(sliderTwo);
146 Serial.print(" ");
147 Serial.println(sliderThree);
148}
149
150void onSliderTwoChange() {
151 /* Add your code here to act upon SliderValue2 change */
152 Serial.print("New combination: ");
153 Serial.print(sliderOne);
154 Serial.print(" ");
155 Serial.print(sliderTwo);
156 Serial.print(" ");
157 Serial.println(sliderThree);
158}
159
160void onSliderThreeChange() {
161 /* Add your code here to act upon SliderValue3 change */
162 Serial.print("New combination: ");
163 Serial.print(sliderOne);
164 Serial.print(" ");
165 Serial.print(sliderTwo);
166 Serial.print(" ");
167 Serial.println(sliderThree);
168}
169
170/* Send RGB values to the LED pins */
171void setColor(int red, int green, int blue) {
172 analogWrite(redPin, red);
173 analogWrite(greenPin, green);
174 analogWrite(bluePin, blue);
175}
176
177void onDisplayChange() {
178/* Add your code here to act upon Display change */
179}

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.