.. note::
Bonjour et bienvenue dans la communauté SunFounder Raspberry Pi & Arduino & ESP32 sur Facebook ! Plongez plus profondément dans l'univers du Raspberry Pi, Arduino et ESP32 avec d'autres passionnés.
**Pourquoi nous rejoindre ?**
- **Support d'experts** : Résolvez les problèmes après-vente et les défis techniques avec l'aide de notre communauté et de notre équipe.
- **Apprendre & Partager** : Échangez des astuces et des tutoriels pour améliorer vos compétences.
- **Aperçus exclusifs** : Bénéficiez d'un accès anticipé aux annonces de nouveaux produits et à des avant-premières.
- **Remises spéciales** : Profitez de réductions exclusives sur nos nouveaux produits.
- **Promotions et cadeaux festifs** : Participez à des concours et promotions spéciales pour les fêtes.
👉 Prêt à explorer et créer avec nous ? Cliquez sur [|link_sf_facebook|] et rejoignez-nous dès aujourd'hui !
.. _py_pi5_password_lock:
3.1.9 Serrure à Code
================================
Introduction
----------------
Dans ce projet, nous utiliserons un clavier matriciel et un écran LCD pour créer
une serrure à combinaison. Le LCD affichera une invite correspondante pour saisir
le mot de passe sur le clavier. Si le mot de passe est correct, "Correct" sera affiché.
Sur la base de ce projet, nous pouvons ajouter des composants électroniques
supplémentaires, tels qu'un buzzer, une LED, etc., pour créer divers effets lors de
la saisie du mot de passe.
Composants nécessaires
------------------------------
Dans ce projet, nous aurons besoin des composants suivants.
.. image:: ../python_pi5/img/4.1.14_password_lock_list.png
:width: 800
:align: center
.. Il est plus pratique d'acheter un kit complet, voici le lien :
.. .. list-table::
.. :widths: 20 20 20
.. :header-rows: 1
.. * - Nom
.. - ÉLÉMENTS DANS CE KIT
.. - LIEN
.. * - Kit Raphael
.. - 337
.. - |link_Raphael_kit|
.. Vous pouvez également les acheter séparément avec les liens ci-dessous.
.. .. list-table::
.. :widths: 30 20
.. :header-rows: 1
.. * - INTRODUCTION DES COMPOSANTS
.. - LIEN D'ACHAT
.. * - :ref:`gpio_extension_board`
.. - |link_gpio_board_buy|
.. * - :ref:`breadboard`
.. - |link_breadboard_buy|
.. * - :ref:`wires`
.. - |link_wires_buy|
.. * - :ref:`resistor`
.. - |link_resistor_buy|
.. * - :ref:`i2c_lcd1602`
.. - |link_i2clcd1602_buy|
.. * - :ref:`keypad`
.. - \-
Schéma de câblage
---------------------
============ ======== ======== ===
T-Board Name physical wiringPi BCM
GPIO18 Pin 12 1 18
GPIO23 Pin 16 4 23
GPIO24 Pin 18 5 24
GPIO25 Pin 22 6 25
GPIO17 Pin 11 0 17
GPIO27 Pin 13 2 27
GPIO22 Pin 15 3 22
SPIMOSI Pin 19 12 10
SDA1 Pin 3
SCL1 Pin 5
============ ======== ======== ===
.. image:: ../python_pi5/img/4.1.14_password_lock_schematic.png
:align: center
Procédure expérimentale
----------------------------
**Étape 1 :** Construire le circuit.
.. image:: ../python_pi5/img/4.1.14_password_lock_circuit.png
**Étape 2 :** Accéder au dossier du code.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/python-pi5
**Étape 3 :** Exécuter le programme.
.. raw:: html
.. code-block::
sudo python3 3.1.9_PasswordLock.py
Une fois le code lancé, utilisez le clavier pour saisir le mot de passe : 1984.
Si "CORRECT" s'affiche sur l'écran LCD1602, cela signifie que le mot de passe est
correct ; sinon, "WRONG KEY" apparaîtra.
.. note::
* Si vous rencontrez l'erreur ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'``, vous devez consulter :ref:`i2c_config` pour activer le I2C.
* Si vous obtenez l'erreur ``ModuleNotFoundError: No module named 'smbus2'``, exécutez la commande ``sudo apt install python3-smbus2``.
* Si l'erreur ``OSError: [Errno 121] Remote I/O error`` apparaît, cela signifie que le module est mal câblé ou que le module est endommagé.
* Si le code et le câblage sont corrects, mais que l'écran LCD ne s'affiche toujours pas, essayez d'ajuster le potentiomètre à l'arrière pour augmenter le contraste.
.. warning::
Si une erreur indiquant ``RuntimeError: Cannot determine SOC peripheral base address`` apparaît, consultez :ref:`faq_soc`.
**Code**
.. note::
Vous pouvez **Modifier/Réinitialiser/Copier/Exécuter/Arrêter** le code ci-dessous. Mais avant cela, vous devez accéder au chemin du code source tel que ``davinci-kit-for-raspberry-pi/python-pi5``. Après avoir modifié le code, vous pouvez l'exécuter directement pour voir l'effet.
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
class Clavier:
def __init__(self, broches_lignes, broches_colonnes, touches):
"""
Initialize the Keypad with specified row and column pins and keys.
:param rows_pins: List of GPIO pins for the rows.
:param cols_pins: List of GPIO pins for the columns.
:param keys: List of keys in the keypad layout.
"""
self.lignes = [DigitalOutputDevice(pin) for pin in broches_lignes] # Configuration des broches de lignes
self.colonnes = [Button(pin, pull_up=False) for pin in broches_colonnes] # Configuration des broches de colonnes
self.touches = touches # Disposition des touches du clavier
def lire(self):
"""
Read and return a list of keys that are currently pressed.
:return: List of pressed keys.
"""
pressed_keys = []
for i, row in enumerate(self.rows):
row.on() # Activate current row
for j, col in enumerate(self.cols):
if col.is_pressed:
index = i * len(self.cols) + j
pressed_keys.append(self.keys[index])
row.off() # Deactivate row after checking
return pressed_keys
# Configuration pour la vérification du mot de passe
LONGUEUR = 4
mot_de_passe = ['1', '9', '8', '4'] # Mot de passe prédéfini
essai = ['0', '0', '0', '0'] # Stockage de la saisie utilisateur
index_touche = 0 # Index pour les touches saisies
def check():
"""
Check if the entered password matches the preset password.
:return: 1 if match, 0 otherwise.
"""
for i in range(LENS):
if password[i] != testword[i]:
return 0
return 1
def setup():
"""
Setup the keypad and LCD display.
"""
global keypad, last_key_pressed
# Pin configuration for keypad
rows_pins = [18, 23, 24, 25]
cols_pins = [10, 22, 27, 17]
keys = ["1", "2", "3", "A",
"4", "5", "6", "B",
"7", "8", "9", "C",
"*", "0", "#", "D"]
# Initialisation du clavier et du LCD
keypad = Keypad(rows_pins, cols_pins, keys)
last_key_pressed = []
LCD1602.init(0x27, 1) # Initialize LCD
LCD1602.clear()
LCD1602.write(0, 0, 'WELCOME!')
LCD1602.write(2, 1, 'Enter password')
sleep(2)
def loop():
"""
Main loop for handling keypad input and password verification.
"""
global keyIndex, LENS, keypad, last_key_pressed
while True:
pressed_keys = keypad.read()
if pressed_keys and pressed_keys != last_key_pressed:
if keyIndex < LENS:
LCD1602.clear()
LCD1602.write(0, 0, "Enter password:")
LCD1602.write(15 - keyIndex, 1, pressed_keys[0])
testword[keyIndex] = pressed_keys[0]
keyIndex += 1
if keyIndex == LENS:
if check() == 0:
LCD1602.clear()
LCD1602.write(3, 0, "WRONG KEY!")
LCD1602.write(0, 1, "please try again")
else:
LCD1602.clear()
LCD1602.write(4, 0, "CORRECT!")
LCD1602.write(2, 1, "welcome back")
keyIndex = 0 # Reset key index after checking
last_key_pressed = pressed_keys
sleep(0.1)
try:
setup()
loop()
except KeyboardInterrupt:
LCD1602.clear() # Efface l'écran LCD en cas d'interruption
**Explication du Code**
#. Le script importe des classes pour gérer les périphériques de sortie numérique et les boutons depuis la bibliothèque gpiozero. Il importe également la fonction ``sleep`` du module ``time`` pour ajouter des délais dans l'exécution du script. De plus, la bibliothèque ``LCD1602`` est importée pour contrôler l'affichage sur l'écran LCD1602.
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
#. Définit une classe personnalisée pour gérer le clavier matriciel. Elle initialise le clavier avec les broches spécifiées pour les rangées et les colonnes et fournit une méthode ``read`` pour détecter les touches pressées.
.. code-block:: python
class Keypad:
def __init__(self, rows_pins, cols_pins, keys):
"""
Initialize the Keypad with specified row and column pins and keys.
:param rows_pins: List of GPIO pins for the rows.
:param cols_pins: List of GPIO pins for the columns.
:param keys: List of keys in the keypad layout.
"""
self.rows = [DigitalOutputDevice(pin) for pin in rows_pins] # Row pins setup
self.cols = [Button(pin, pull_up=False) for pin in cols_pins] # Column pins setup
self.keys = keys # Keypad key layout
def read(self):
"""
Read and return a list of keys that are currently pressed.
:return: List of pressed keys.
"""
pressed_keys = []
for i, row in enumerate(self.rows):
row.on() # Activate current row
for j, col in enumerate(self.cols):
if col.is_pressed:
index = i * len(self.cols) + j
pressed_keys.append(self.keys[index])
row.off() # Deactivate row after checking
return pressed_keys
#. Met en place le système de vérification du mot de passe. ``LONGUEUR`` définit la longueur du mot de passe. ``mot_de_passe`` est le mot de passe correct prédéfini, tandis que ``essai`` est utilisé pour stocker la saisie de l'utilisateur. ``index_touche`` suit la position actuelle dans la saisie de l'utilisateur.
.. code-block:: python
# Configuration pour la vérification du mot de passe
LONGUEUR = 4
mot_de_passe = ['1', '9', '8', '4'] # Mot de passe prédéfini
essai = ['0', '0', '0', '0'] # Stockage de la saisie utilisateur
index_touche = 0 # Index pour les touches saisies
#. Fonction pour comparer le mot de passe saisi (``essai``) avec le mot de passe prédéfini (``mot_de_passe``) et retourner le résultat.
.. code-block:: python
def check():
"""
Check if the entered password matches the preset password.
:return: 1 if match, 0 otherwise.
"""
for i in range(LENS):
if password[i] != testword[i]:
return 0
return 1
#. Initialise le clavier et l'affichage LCD. Affiche un message de bienvenue et des instructions pour entrer le mot de passe.
.. code-block:: python
def setup():
"""
Setup the keypad and LCD display.
"""
global keypad, last_key_pressed
# Pin configuration for keypad
rows_pins = [18, 23, 24, 25]
cols_pins = [10, 22, 27, 17]
keys = ["1", "2", "3", "A",
"4", "5", "6", "B",
"7", "8", "9", "C",
"*", "0", "#", "D"]
# Initialisation du clavier et du LCD
keypad = Keypad(rows_pins, cols_pins, keys)
last_key_pressed = []
LCD1602.init(0x27, 1) # Initialize LCD
LCD1602.clear()
LCD1602.write(0, 0, 'WELCOME!')
LCD1602.write(2, 1, 'Enter password')
sleep(2)
#. Boucle principale pour gérer la saisie du clavier et la vérification du mot de passe. Met à jour l'affichage sur le LCD en fonction du mot de passe saisi et fournit un retour d'information si le mot de passe est correct ou incorrect.
.. code-block:: python
def loop():
"""
Main loop for handling keypad input and password verification.
"""
global keyIndex, LENS, keypad, last_key_pressed
while True:
pressed_keys = keypad.read()
if pressed_keys and pressed_keys != last_key_pressed:
if keyIndex < LENS:
LCD1602.clear()
LCD1602.write(0, 0, "Enter password:")
LCD1602.write(15 - keyIndex, 1, pressed_keys[0])
testword[keyIndex] = pressed_keys[0]
keyIndex += 1
if keyIndex == LENS:
if check() == 0:
LCD1602.clear()
LCD1602.write(3, 0, "WRONG KEY!")
LCD1602.write(0, 1, "please try again")
else:
LCD1602.clear()
LCD1602.write(4, 0, "CORRECT!")
LCD1602.write(2, 1, "welcome back")
keyIndex = 0 # Reset key index after checking
last_key_pressed = pressed_keys
sleep(0.1)
#. Exécute la configuration et entre dans la boucle principale. Permet une sortie propre du programme à l'aide d'une interruption clavier (Ctrl+C), en nettoyant l'affichage du LCD.
.. code-block:: python
try:
setup()
loop()
except KeyboardInterrupt:
LCD1602.clear() # Clear LCD display on interrupt