Serrure à gestes sans contact : Accès sécurisé avec APDS-9960 et Arduino
Composants et fournitures
| SparkFun APDS-9960 | × | 1 |
| Arduino UNO | × | 1 |
| LED RVB diffuse cathode commune | × | 1 |
| Adafruit LCD standard - 16x2 blanc sur bleu | × | 1 |
| Résistance 4,75 k ohm | × | 2 |
| Fils de connexion (générique) | × | 1 |
| Résistance 1 k ohm | × | 1 |
Applications et services en ligne
- Arduino IDE
À propos de ce projet
*Le capteur APDS-9960 ne fonctionne pas avec l'Arduino Nano ou Mega 2560 (d'après mes tests).
Ce projet est facile à réaliser et à utiliser. N'hésitez pas à utiliser n'importe quel type de servo ou mécanisme de verrouillage avec ce projet. Il est conçu comme une plateforme de départ pour une serrure basée sur les gestes. Passons à la construction !
Matériel
J'ai obtenu la plupart de mes pièces sur Amazon.com et le capteur APDS-9960 chez Sparkfun. Vous ne pouvez utiliser qu'un Arduino Uno ou Micro 3,3V pour l'instant, car aucune autre carte ne fonctionne pour une raison obscure.
Assemblage
Connectez le LCD comme indiqué. Si vous n'avez pas de potentiomètre 10k, utilisez une résistance de 1k entre le contraste et GND. Le capteur APDS-9960 devra être décalé en niveau si vous utilisez l'Arduino Uno. Voici ce que j'ai fait : prenez les broches SCL et SDA et connectez-les à une résistance de 4,7k, puis tirez-les vers le haut en connectant la résistance de 4,7k au 3,3V. Ensuite, connectez-les à A4 et A5, respectivement (voir le schéma). L'Arduino peut fonctionner sur une pile 9V avec un connecteur jack DC.
Boîtier
J'ai utilisé une simple boîte en carton et découpé des trous pour y faire passer les composants. Vous pourriez souder tout cela sur une plaque à pastilles, mais je l'ai laissé sur la plaque d'essai et connecté des fils de liaison aux composants. Une fois terminé, cela ressemblait à ceci :

Code
Code Arduino (C/C++)
/* Connexions matérielles : IMPORTANT : L'APDS-9960 n'accepte que 3,3V !
Broche Arduino | Broche APDS-9960 | Fonction
3.3V | VCC | Alimentation
GND | GND | Masse
A4 | SDA | Données I2C
A5 | SCL | Horloge I2C
2 | INT | Interruption
Ressources : Inclure Wire.h et SparkFun_APDS-9960.h
*/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <LiquidCrystal.h>
#include <Servo.h>
#define PINSIZE 6
#define SERVOPIN 9
// Longueur du mot de passe en gestes
#define APDS9960_INT 2 // Doit être une broche d'interruption
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);
Servo servo;
uint8_t proximity_data = 0;
int red_led = A1;
int green_led = A2;
int pageNum = 0; // La « page » LCD
String secret[PINSIZE] = {"UP", "DOWN", "UP", "UP", "RIGHT", "LEFT"}; // Mot de passe ici. Doit être en MAJUSCULES. Peut être "UP", "DOWN", "LEFT", ou "RIGHT"
String currentGesture = "";
int numRight = 0;
SparkFun_APDS9960 apds = SparkFun_APDS9960(); // Initialisation de la bibliothèque APDS-9960
int isr_flag = 0;
void setup() {
// Configurer la broche d'interruption en entrée
pinMode(APDS9960_INT, INPUT);
lcd.begin(16, 2);
servo.attach(SERVOPIN);
servo.write(0);
servo.detach();
// Initialiser le port série
Serial.begin(9600);
Serial.print("Votre mot de passe fait ");
Serial.print(PINSIZE);
Serial.println(" gestes de long.");
Serial.println();
Serial.println(F("----------------"));
Serial.println(F("Serrure APDS-9960"));
Serial.println(F("----------------"));
// Initialiser la routine de service d'interruption
attachInterrupt(0, interruptRoutine, FALLING);
// Initialiser l'APDS-9960 (configurer I2C et valeurs initiales)
if (apds.init()) {
Serial.println(F("Initialisation APDS-9960 terminée"));
} else {
Serial.println(F("Quelque chose s'est mal passé pendant l'initialisation de l'APDS-9960 !"));
}
if (!apds.setProximityGain(PGAIN_1X)) {
Serial.println(F("Erreur lors de la tentative de définition de PGAIN"));
}
if (apds.enableProximitySensor(false)) {
Serial.println(F("Capteur de proximité maintenant en marche"));
} else {
Serial.println(F("Erreur pendant l'initialisation du capteur !"));
}
// Démarrer le moteur de détection de gestes de l'APDS-9960
if (apds.enableGestureSensor(true)) {
Serial.println(F("Capteur de gestes maintenant en marche"));
} else {
Serial.println(F("Erreur pendant l'initialisation du capteur de gestes !"));
}
}
void loop() {
if (pageNum == 0) {
if (!apds.readProximity(proximity_data)) {
Serial.println("Erreur de lecture de la valeur de proximité");
} else {
Serial.println(proximity_data);
if ((proximity_data >= 40) && (pageNum == 0)) {
pageNum = 1;
delay(2000);
}
}
}
switch (pageNum) {
case 0:
LCDClear();
lcd.print("Verrouille-");
lcd.setCursor(0, 1);
lcd.print("approchez 8 cm.");
blinkRed();
LCDClear();
break;
case 1:
numRight = 0;
lcd.print("Entrez code...");
lcd.setCursor(0, 0);
for (int x = 0; x < PINSIZE; x++) {
Serial.println(x);
while (apds.isGestureAvailable() == false) {
}
if (isr_flag == 1) {
detachInterrupt(0);
handleGesture();
isr_flag = 0;
attachInterrupt(0, interruptRoutine, FALLING);
if (currentGesture != "NONE") {
if (currentGesture == secret[x]) {
LCDClear();
lcd.print("Suivant");
numRight += 1;
analogWrite(green_led, 255);
delay(1000);
allOff();
} else if (currentGesture != secret[x]) {
LCDClear();
lcd.print("Mauvais, retour");
lcd.setCursor(0, 1);
lcd.print("page principale.");
analogWrite(red_led, 255);
delay(1000);
allOff();
pageNum = 0;
break;
}
if (numRight == PINSIZE) {
pageNum = 2;
break;
}
} else if (currentGesture == "NONE") {
LCDClear();
lcd.print("Non reconnu :");
lcd.setCursor(0, 1);
lcd.print("Reessayez.");
x -= 1;
}
}
}
break;
case 2:
LCDClear();
lcd.print("Entrez maintenant.");
pageNum = 0;
servo.attach(SERVOPIN);
servo.write(90);
enter();
delay(1000);
servo.write(0);
break;
}
}
void interruptRoutine() {
isr_flag = 1;
}
void handleGesture() {
if (apds.isGestureAvailable()) {
switch (apds.readGesture()) {
case DIR_UP:
Serial.println("UP");
LCDClear();
lcd.print("Haut");
currentGesture = "UP";
break;
case DIR_DOWN:
Serial.println("DOWN");
LCDClear();
lcd.print("Bas");
currentGesture = "DOWN";
break;
case DIR_LEFT:
Serial.println("LEFT");
LCDClear();
lcd.print("Gauche");
currentGesture = "LEFT";
break;
case DIR_RIGHT:
Serial.println("RIGHT");
LCDClear();
lcd.print("Droite");
currentGesture = "RIGHT";
break;
case DIR_NEAR:
Serial.println("NEAR");
LCDClear();
lcd.print("Proche");
currentGesture = "NEAR";
break;
case DIR_FAR:
Serial.println("FAR");
LCDClear();
lcd.print("Loin");
currentGesture = "FAR";
break;
default:
Serial.println("NONE");
LCDClear();
lcd.print("Aucun");
currentGesture = "NONE";
}
}
}
void allOff() {
analogWrite(red_led, 0);
analogWrite(green_led, 0);
}
void blinkRed() {
analogWrite(red_led, 255);
delay(250);
allOff();
delay(250);
}
void LCDClear() {
lcd.clear();
lcd.setCursor(0, 0);
}
void enter() {
// Délai total de 16 secondes
for (int x = 0; x < 30; x++) {
analogWrite(green_led, 255);
delay(100);
allOff();
delay(100);
}
for (int x = 9; x > 0; x--) {
LCDClear();
lcd.print("Fermeture dans: ");
lcd.setCursor(0, 1);
lcd.print(x);
lcd.setCursor(1, 1);
lcd.print(" secondes...");
delay(1000);
}
LCDClear();
lcd.print("Fermeture");
}
Schémas

Processus de fabrication
- L'évolution et la fabrication des serrures à goupilles modernes
- Serrure à combinaison : conception, fabrication et évolution historique
- Alerte Soif Plante Intelligente – Capteur DIY pour une Hydratation Optimale
- Horloge à Mots Italienne avec Arduino Nano, NeoPixel, LCD et RTC
- Économisez les broches Arduino : clavier 4×3 sur 3 entrées analogiques
- Compteur kWh Sigfox fiable avec Arduino MKR Fox 1200
- Moniteur de température Bluetooth avec Arduino Nano
- Circuit d'entrée analogique isolée pour Arduino : Protection contre les parasites industriels
- Test Précis de Temps de Réaction avec Arduino UNO