Learn to code

ARDUINO & CODES

Previous Post
Create a Marble Maze / Labyrinth for Arduino
Next Post
Making an autonomous BeerPong Robot Car with Arduino

Creating a proximity touch password lockbox with Neopixels and Arduino

in Arduino Project

In this project tutorial, you will create an Arduino Proximity / Touch Lockbox with NeoPixels inside. I came up with this project for a Christmas present. The box contains a present for someone that can be opened after unlocking the code.

The code of this lockbox consists of touching the right combination of panels in the led of the box, which lights up when touched, to open the box.

What you will need to know?

Before continuing with this guide, you may want to check out any topics from the list below that sound unfamiliar.

Parts you will need

Cutting out all the pieces

So the first thing you want to do is to cut out all the elements for the box. There are quite a lot of elements for making this box.

    • cut out two pieces 24 cm by 24 cm for the top and bottom
    • cut out two 4 pieces of 24 by 10 cm for the sides, front and back
    • cut out three pieces of 10 cm by 5 cm for the sides of the drawer
    • cut out one piece of 10 by 15 cm for the buttom of the drawer
    • cut out one piece of 10 by 7 cm for the inner front besides the drawer
    • cut out 36 pieces of 4 cm by 2 cm to create the sides for the box for the LEDs.
    • Cut out 9 pieces of 5 cm by 5 cm to cover the boxes of the LEDs.
    • The back and front are cut to pieces of 15 cm by 10 and 10 cm by 5. One is used for the drawer while the other is used to get acces to the Arduino
    • The servo is places, after everything is mounted between two LED boxes.
    • At the drawer there you have to make an opening to create space for the servo to turn in to.

Building Warning! The most difficult part of the box is to attach the servo motor and align it with the drawer that is coming out of the box. In the example there is a bit of slack in the lock. 

 

Prepare the materials

The first thing you will need to do is to make holes in the lid of the box. There is a gap of 3 cm between the holes.

Wholes in lid

Attaching the Copper Foil

After you cut out all the pieces, you can move forward attach the copper foil to the project. This is a vital part since the copper foil allows the box to sense touch through the foam board. After you placed all the copper foil around the wholes in the lid of the box you need to solder wires to it.

Soldering wires to the copper foil can be difficult. Soler some soldering on the copper foil and keep it warm. Attach the wire to the copper and put some more soldering on the wire. If you never have done this before practice a bit before applying it on this project.

BreadBoard Layout

After you attached the copper foil with wires to the lid it is time to build are circuit.

Soldering the NeoPixels 

After you finished attaches 9 wires to the copper foil you can start creating the NeoPixel strip. From the strip, you can cut out 9 LEDs and solder them together. After you have done that you can attach these to the sides of the NeoPixel boxes. The Servo motor is mounted between two boxes.

Remember, you have to attach enough wire between the NeoPixels in order to mount them nicely into the boxes. Also, these strip before continuing your build. You can use a simple sketch in previous tutorials to determine if your strip is working.

 

Adding Hobbyglass

You can now close the NeoPixel boxes with hobbyglass on the top and at the back a panel with a picture.

The box is opened by touching the right panels. In the example used in this project there a 5 stamps from one country. The other stamps are  from different countries. So in order to open the box you will need to touch these 5 panels.

 

Mounting everything

Now you can mount everything together before continuing to the code part of this project.

The Code

// Proximity Touch LockBox
// wwww.arduinoplatform.com

#include <MPR121.h> // This is the library of BareConductive
#include <Wire.h> // This enables you to communicate with I2C / TWI devices
#include <Adafruit_NeoPixel.h> // The library for the NeoPixels
#include <Servo.h>// The Library for the Servo Motor.

#define numElectrodes 9 // The number of electrodes in use

//define NeoPixel Pin and Number of LEDs
#define PIN 5
#define NUM_LEDS 50
//create a NeoPixel strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

boolean oldSwitchState[] = {LOW, LOW, LOW, LOW, LOW};
boolean newSwitchState[] = {LOW, LOW, LOW, LOW, LOW};
boolean LEDstatus[] = {LOW, LOW, LOW, LOW, LOW,};

bool reset(); // resets the Code

//arrays that store the passwords
int code[5] = {0, 0, 0, 0, 0};
int password[5] = {10, 5, 10, 5, 10};

int counter = 0;

Servo myservo; // create servo object to control a servo

void setup() {
  myservo.write(124);
  Serial.begin( 9600 );
  Wire.begin();

  // Setup MPR121
  // you can change the number of the treshold to adjust the sensitivity.
  MPR121.begin( 0x5A );
  MPR121.setInterruptPin( 4 );
  MPR121.setTouchThreshold( 10 );
  MPR121.setReleaseThreshold( 10 );

  // attach servo to pin 9
  myservo.attach(9);

  // start the strip and blank it out
  strip.begin();
  strip.show();
}

void loop()

{
  // check if 5 buttons touch pads are on and check the password
  if (counter == 5) {
    if (code[0] == password[0] && code[1] == password[1] && code[2] == password[2] && code[3] == password[3] && code[4] == password[4]) {

      myservo.write(50);

      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);

      strip.show();
      delay(100);
      reset();
    }
    else {

      Strobe(0xff, 0x00, 0x00, 10, 50, 1000);
      Strobe(0xff, 0x00, 0x00, 10, 50, 1000);

      delay(50);
      reset();

    }
  }

  if (MPR121.touchStatusChanged()) {
    MPR121.updateTouchData();
    for (int i = 0; i < numElectrodes; i++) {
      if (MPR121.isNewTouch(i)) {
        newSwitchState[i] = MPR121.isNewTouch(i);
        Serial.print("electrode ");
        Serial.print(i, DEC);
        Serial.print(" was just touched ");
        Serial.print(code[i]);

        if (newSwitchState[i] != oldSwitchState[i]) {
          if ( LEDstatus[i] == LOW ) {

            LEDstatus[i] = HIGH;
            switch (i) {

              case 0:
                code[0] = 10;
                strip.setPixelColor(0, 0, 216, 0);
                strip.show();
                counter ++;
                break;

              case 1:
                code[1] = 5;
                strip.setPixelColor(1, 255, 0, 0);
                strip.show();
                counter ++;
                break;

              case 2:
                code[2] = 10;
                strip.setPixelColor(2, 255, 255, 0);
                strip.show();
                counter ++;
                break;

              case 3:
                code[3] = 5;
                strip.setPixelColor(3, 51, 204, 51);
                strip.show();
                counter ++;
                break;

              case 4:
                code[4] = 10;
                strip.setPixelColor(4, 255, 0, 0);
                strip.show();
                counter ++;
                break;

              case 5:
                strip.setPixelColor(5, 255, 0, 0);
                strip.show();
                counter ++;
                break;

              case 6:
                strip.setPixelColor(6, 255, 0, 0);
                strip.show();
                counter ++;
                break;

              case 7:
                strip.setPixelColor(7, 255, 0, 0);
                strip.show();
                counter ++;
                break;

              case 8:
                strip.setPixelColor(8, 255, 0, 0);
                strip.show();
                counter ++;
                break;

            }

          }
          else                    {

            LEDstatus[i] = LOW;
            switch (i) {

              case 0:
                code[0] = 10;
                strip.setPixelColor(0, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 1:
                code[1] = 1;
                strip.setPixelColor(1, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 2:
                code[2] = 0;
                strip.setPixelColor(2, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 3:
                code[3] = 1;
                strip.setPixelColor(3, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 4:
                code[4] = 10;
                strip.setPixelColor(4, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 5:
                strip.setPixelColor(5, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 6:
                strip.setPixelColor(6, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 7:
                strip.setPixelColor(7, 0, 0, 0);
                strip.show();
                counter --;
                break;

              case 8:
                strip.setPixelColor(8, 0, 0, 0);
                strip.show();
                counter --;
                break;
            }
          }
        }
        oldSwitchState[i] = newSwitchState[i];

      } else if (MPR121.isNewRelease(i)) {

        newSwitchState[i] = MPR121.isNewTouch(i);
        Serial.print("electrode ");
        Serial.print(i, DEC);
        Serial.println(" was just released");
        oldSwitchState[i] = newSwitchState[i];

      }
    }
  }
}

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause) {
  for (int j = 0; j < StrobeCount; j++) {
    setAll(red, green, blue);
    showStrip();
    delay(FlashDelay);
    setAll(0, 0, 0);
    showStrip();
    delay(FlashDelay);
  }

  delay(EndPause);
}

//functions for the NeoPixel
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif

}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.show();
#endif

}

Code Explanation

In this project you will be using various libraries to make the coding easier. Firstly, there is the bareconductive MPR121 library. You can download this at GITHUB. The other libraries that are used can be downloaded in the library menu of the Arduino IDE.

So, the sketch will enable you to detect touch through the conductive material. Furthermore, this sketch allows you to detect how many sensors have been touched. If you get close to the sensor the NeoPixel corresponding to that proximity sensor will light up. The state of the proximity sensor is remembered in an array. If you touch the proximity sensor again the NeoPixel will turn off and the state that the NeoPixel is off is also remembered.

The code checks whether 5 proximity sensors have a state in which the NeoPixel is on. Then it compares the password with the array that is holding the code of the NeoPixels.

In the case below, the proximity sensors 0 till 5 should be turned on to enable to lock to be opened.

Soldering the NeoPixels 

The first part of the code is to include all the libraries that are necessary for the MPR121 touch board to function, the servo to turn on and off course the library to light the NeoPixels.

// Proximity Touch LockBox
// wwww.arduinoplatform.com

#include <MPR121.h> // This is the library of BareConductive
#include <Wire.h> // This enables you to communicate with I2C / TWI devices
#include <Adafruit_NeoPixel.h> // The library for the NeoPixels
#include <Servo.h>// The Library for the Servo Motor.

#define numElectrodes 9 // The number of electrodes in use

//define NeoPixel Pin and Number of LEDs
#define PIN 5
#define NUM_LEDS 50
//create a NeoPixel strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);



Declare the variables

As in every sketch that you will make, this one also needs variables to work with.

Firstly, there a couple of boolean variables that we will use to determine the state of the individual proximity touch “buttons”. In order to remember the state of the proximity button, there needs to be an old and a new state. Furthermore, the boolean LEDstatus allows us to ensure that the NeoPixel is on / off.

An array is created to store the code that is associated with the different proximity touch buttons. An array is also used for the password.

Since we want to check whether or not the right combination is we will need a counter that enables us to follow how many poximity buttons are active.

boolean oldSwitchState[] = {LOW, LOW, LOW, LOW, LOW};
boolean newSwitchState[] = {LOW, LOW, LOW, LOW, LOW};
boolean LEDstatus[] = {LOW, LOW, LOW, LOW, LOW,};

bool reset(); // resets the Code

//arrays that store the passwords
int code[5] = {0, 0, 0, 0, 0};
int password[5] = {10, 5, 10, 5, 10};

int counter = 0;

Servo myservo; // create servo object to control a servo

Void setup() part

In the setup part of this code you will write a position to the servo so that you can use it as a lock. Serial communication is initiated so you can send information to the Serial Monitor.

Next is the setup of the MPR121 board. There are a couple of parameters that you can adjust for the MPR121. If you decide to use a different interruptPin than 4 you can adjust it there. You can set the threshold to make the proximity/touch more sensitive. Lower numbers will create more sensitivity.

void setup() {
  myservo.write(124);
  Serial.begin( 9600 );
  Wire.begin();

  // Setup MPR121
  // you can change the number of the treshold to adjust the sensitivity.
  MPR121.begin( 0x5A );
  MPR121.setInterruptPin( 4 );
  MPR121.setTouchThreshold( 10 );
  MPR121.setReleaseThreshold( 10 );

  // attach servo to pin 9
  myservo.attach(9);

  // start the strip and blank it out
  strip.begin();
  strip.show();
}

Unlock Code

In the first part of the void loop() the code is presented that will open the box. In this part, we will need to do three things. Determine when to check the code, if the code matches the password the box should unlock. Therefore, move the servo motor to a position that enables you to open the drawer. Finally, you will need some code if the conditions of the above are not met.

The counter enables you to check whether or not five proximity buttons are activated. If that condition is passed another if statement is checking whether or not the code matches the password.  If the condition is TRUE the servo will move and the NeoPixels will light up accordingly to the code written in the strobe function. After the strobe effect has occurred the sketch resets.

{
  // check if 5 buttons touch pads are on and check the password
  if (counter == 5) {
    if (code[0] == password[0] && code[1] == password[1] && code[2] == password[2] && code[3] == password[3] && code[4] == password[4]) {
      myservo.write(50);
      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
      strip.show();
      delay(100);
      reset();
    }
    else {
      Strobe(0xff, 0x00, 0x00, 10, 50, 1000);
      Strobe(0xff, 0x00, 0x00, 10, 50, 1000);
      delay(50);
      reset();
    }
  }

Sensing touch

This part of the code is checking whether or not there is a new touch on the proximity buttons. It will loop through all the electrodes (wires) attached to the MPR121. Remember, that you defined numElecrtrodes correctly.

If there is new touch information is send to the Serial Monitor so that you can see which electrode was activated. The variable newSwitchState is updated with the current state of the electrode. This is part is crucial you are going to use the MPR121 and the electrodes as a touch button.

If there is a new touch the NeoPixel should light up. Therefore, we will also need an IF Statement that checks whether or not the NeoPixel is on. This is where we will use the variable LEDstatus. LEDstatus checks if the NeoPixel is on / off and updates the variable.

if (MPR121.touchStatusChanged()) {
    MPR121.updateTouchData();
    for (int i = 0; i < numElectrodes; i++) {
      if (MPR121.isNewTouch(i)) {
        newSwitchState[i] = MPR121.isNewTouch(i);
        Serial.print("electrode ");
        Serial.print(i, DEC);
        Serial.print(" was just touched ");
        Serial.print(code[i]);
        if (newSwitchState[i] != oldSwitchState[i]) {
          if ( LEDstatus[i] == LOW ) {
            LEDstatus[i] = HIGH;

Switch Statement

The interesting part of this sketch is the switch statement. Since we loop through all the electrodes and retrieve information from them we can use a switch statement to perform code for every electrode individually.

Case 0 – 5 will also update the array code with the correct code for the password. Every case adds +1 from the counter if the electrode is touched. When the electrode is touched again it will deduct -1 from the counter. The array is updated with the wrong password code if the NeoPixel is off.

See the electrode/touch area on the lockbox as a switch that can be turned on and off. When it is turned on the right code of the electrode is placed in the array and the NeoPixel of that electrode is turned on.

If the electrode/touch area is touched again, the NeoPixel will be turned off and the wrong code of the electrode is placed in the array.

The last element is updating the oldswitchstate for the newswitchstate.

 else if (MPR121.isNewRelease(i)) {
        newSwitchState[i] = MPR121.isNewTouch(i);
        Serial.print("electrode ");
        Serial.print(i, DEC);
        Serial.println(" was just released");
        oldSwitchState[i] = newSwitchState[i];

Release electrode

After you touched the proximity area you will also release this area. Again, the sketch is remembering in the newSwitchState that the electrode is released. The oldSwitchState is also replaced with the new release state. This is vital since the loop starts over again and you will need to know the state in which the proximity area is in.

else if (MPR121.isNewRelease(i)) {
        newSwitchState[i] = MPR121.isNewTouch(i);
        Serial.print("electrode ");
        Serial.print(i, DEC);
        Serial.println(" was just released");
        oldSwitchState[i] = newSwitchState[i];

NeoPixel Functions

The functions below are used for lighting up the NeoPixel strip.

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause) {
  for (int j = 0; j < StrobeCount; j++) {
    setAll(red, green, blue);
    showStrip();
    delay(FlashDelay);
    setAll(0, 0, 0);
    showStrip();
    delay(FlashDelay);
  }
  delay(EndPause);
}
//functions for the NeoPixel
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
}
void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.show();
#endif


Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.
You need to agree with the terms to proceed

Menu