This is the second part of a series of three posts about KnockBox project: in this one, I am going to talk about its electronics components and software.
For this project, we need the following components:
- one piezo;
- one servo motor;
- one 100uF capacitor;
- three LEDs (one red, one green and one blue);
- three buttons;
- three 220Ω resistances, three 10kΩ resistances and one 1MΩ resistance.
Let’s analyze in detail the components used.
The piezo is the core: it is the sensor that “feels” knocks. Calculating the elapsed time from one knock and another, we can distinguish different rhythms and compare them with the registered one.
The servo motor is used to open and lock the box: I will discuss of this in the next post. However, I have to say that when a motor starts to move, it draws more current than if it were already in motion. This will cause a dip in the voltage on your board. By placing a 100uf capacitor across power and ground, you can smooth out any voltage changes that may occur. Be very careful: make sure you are connecting the cathode to the ground (it’s the side with a black stripe down the side) and the anode to power. If you put capacitors in backwards, they can explode.
The three LEDs are supposed to communicate the status of the system. The green one means that the box is open; the red one that it is locked; the blue one means that an input has been registered.
The three buttons activate three different behaviours of KnockBox:
- Closing the box;
- Playing the registered rhythm;
- Record a new rhythm.
These tre functions can be activated only if the box has been opened.
The resistances allow the other components to work correctly.
The software of KnockBox is just one Arduino sketch: because of its difficulty compared to every code I have posted since now, it’s better to discuss it in detail. It is based on the OOP (Object-Oriented Programming) paradigm, and I tried to keep it as clean and simple as possible.
The sketch is composed of two classes,
Box, and two typical Arduino functions
Rhythm handle inputs and rhythms. It uses three costants:
RHYTHM_SIZE = 10: the maximum number of intervals between two knocks in the registered rhythm (it means that the rhythm cannot be composed of more than 10 intervals, that means 11 knocks).
TOLERANCE = 150: tolerance in milliseconds calculated when the input is compared with the registered rhythm. It means that, if in the rhythm the first interval is 500ms, than an input of 400ms is valid, while one of 700ms is not.
TRESHOLD = 20: the minimum value of the input to be considered valid. If the piezo sensor receive an input less than this value, it is ignored.
Rhythm provides in total 10 functions:
Rhythm(): the constructor. It initialize a compile-time pre-defined rhythm.
void getRhythm(int *rhythm_a): it copies the registered rhythm in the array pointed by
void setRhythm(const int rhythm_a[RHYTHM_SIZE]): it sets a new rhythm. It requires as argument an array of integers, of size
RHYTHM_SIZEthat stores the values in milliseconds of the intervals of the new rhythm.
int getActualSize() const: it returns an integer that is the real numbers of intervals in the registered rhythm. This function is needed because the registered rhythm’s size can also be less than
RHYTHM_SIZE. If this happens, the array is filled with
-1values (for example, a rhythm of 4 knocks, so 3 intervals, is saved in this way:
[INTERVAL_1, INTERVAL_2, INTERVAL_3, -1, -1, -1, -1, -1, -1, -1].
int getActualSize(const int rhythm_a[RHYTHM_SIZE]) const: it is the same as the previous function, but it returns the number of intervals of the argument rhythm
void play() const: it plays the registered rhythm,
void play(const int rhythm_a[RHYTHM_SIZE]) const: it plays the argument rhythm
int listenForKnock() const: it waits for an input o value equal or greater than
TRESHOLDand returns the time in milliseconds elapsed from the function call to the knock.
void listenForRhythm(int *rhythm_a): it listens for a whole rhythm and save its intervals in the array of size
RHYTHM_SIZEpointed by the argument
boolean checkRhythm(): it records a rhythm and compare it with the registered one, applying a tolerance in milliseconds of value
TOLERANCE. It returns
TRUEif the rhythm coincide,
Box handle the operations of opening and locking the box. It provides 5 functions:
Box(): the constructor. It initializes the servo motor, lock the box and turn the red LED on.
boolean isLocked() const: it returns
TRUEif the box is locked,
void openBox(): it activates the servo motor to open the box and turn the green LED on.
void closeBox(): it activates the servo motor to lock the box and turn the red LED on.
void recordNewRhythm(Rhythm *rhythm): it records a new rhythm and plays it. If the closing button is pressed, than the recording is canceled. If the recording button is pressed, the new rhythm is saved and the box locked. The argument
*rhythmpoint to the
Finally, the functions
loop(): the first one initializes Arduino pins for input or output; the second one, performs the correct operations according to the received input.
If you want to observe KnockBox running, see again the video at the beginning of this post.