.. note::
¡Hola! Bienvenido a la Comunidad de Entusiastas de SunFounder para Raspberry Pi, Arduino y ESP32 en Facebook. Profundiza tus conocimientos en Raspberry Pi, Arduino y ESP32 junto a otros entusiastas.
**¿Por qué unirte?**
- **Soporte de Expertos**: Resuelve problemas postventa y desafíos técnicos con la ayuda de nuestra comunidad y equipo.
- **Aprende y Comparte**: Intercambia consejos y tutoriales para mejorar tus habilidades.
- **Previsualizaciones Exclusivas**: Obtén acceso anticipado a anuncios de nuevos productos y adelantos.
- **Descuentos Especiales**: Disfruta de descuentos exclusivos en nuestros productos más recientes.
- **Promociones Festivas y Sorteos**: Participa en sorteos y promociones de temporada.
👉 ¿Listo para explorar y crear con nosotros? ¡Haz clic en [|link_sf_facebook|] y únete hoy!
.. _py_pi5_password_lock:
3.1.9 Cerradura con Contraseña
================================
Introducción
-------------
En este proyecto, utilizaremos un teclado y una pantalla LCD para crear
una cerradura de combinación. La pantalla LCD mostrará un mensaje correspondiente
para que ingreses tu contraseña en el teclado. Si la contraseña es correcta,
aparecerá "Correcto".
Sobre la base de este proyecto, se pueden añadir componentes electrónicos
adicionales, como un zumbador o LED, para agregar diferentes efectos al
ingresar la contraseña.
Componentes Necesarios
------------------------------
En este proyecto, necesitaremos los siguientes componentes.
.. image:: ../python_pi5/img/4.1.14_password_lock_list.png
:width: 800
:align: center
.. Es definitivamente conveniente comprar un kit completo, aquí está el enlace:
.. .. list-table::
.. :widths: 20 20 20
.. :header-rows: 1
.. * - Nombre
.. - ELEMENTOS EN ESTE KIT
.. - ENLACE
.. * - Kit Raphael
.. - 337
.. - |link_Raphael_kit|
.. También puedes comprarlos por separado en los enlaces a continuación.
.. .. list-table::
.. :widths: 30 20
.. :header-rows: 1
.. * - INTRODUCCIÓN DE COMPONENTES
.. - ENLACE DE COMPRA
.. * - :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`
.. - \-
Diagrama del Circuito
---------------------------
============ ======== ======== ===
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
Procedimientos Experimentales
------------------------------------
**Paso 1:** Construye el circuito.
.. image:: ../python_pi5/img/4.1.14_password_lock_circuit.png
**Paso 2:** Cambia el directorio.
.. raw:: html
.. code-block::
cd ~/davinci-kit-for-raspberry-pi/python-pi5
**Paso 3:** Ejecuta.
.. raw:: html
.. code-block::
sudo python3 3.1.9_PasswordLock.py
Después de ejecutar el código, utiliza el teclado para ingresar la
contraseña: 1984. Si aparece "CORRECTO" en la pantalla LCD1602, la
contraseña es correcta; de lo contrario, aparecerá "CONTRASEÑA INCORRECTA".
.. note::
* Si aparece el error ``FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-1'``, consulta :ref:`i2c_config` para habilitar el I2C.
* Si aparece el error ``ModuleNotFoundError: No module named 'smbus2'``, ejecuta ``sudo apt install python3-smbus2``.
* Si aparece el error ``OSError: [Errno 121] Remote I/O error``, significa que el módulo está mal cableado o está dañado.
* Si el código y el cableado están correctos, pero la LCD aún no muestra contenido, ajusta el potenciómetro en la parte trasera para aumentar el contraste.
.. warning::
Si aparece el mensaje de error ``RuntimeError: Cannot determine SOC peripheral base address``, consulta :ref:`faq_soc`
**Código**
.. note::
Puedes **Modificar/Restablecer/Copiar/Ejecutar/Detener** el código a continuación. Pero antes de eso, necesitas ir a la ruta del código fuente, como ``davinci-kit-for-raspberry-pi/python-pi5``. Después de modificar el código, puedes ejecutarlo directamente para ver el efecto.
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
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] # Configuración de pines de filas
self.cols = [Button(pin, pull_up=False) for pin in cols_pins] # Configuración de pines de columnas
self.keys = keys # Diseño de las teclas del teclado
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() # Activa la fila actual
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() # Desactiva la fila después de verificar
return pressed_keys
# Configuración de verificación de contraseña
LENS = 4
password = ['1', '9', '8', '4'] # Contraseña predefinida
testword = ['0', '0', '0', '0'] # Almacenamiento de la entrada del usuario
keyIndex = 0 # Índice para las teclas ingresadas
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
# Configuración de pines para el teclado
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"]
# Inicializar el teclado y la LCD
keypad = Keypad(rows_pins, cols_pins, keys)
last_key_pressed = []
LCD1602.init(0x27, 1) # Inicializar la 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 # Restablecer el índice de teclas después de verificar
last_key_pressed = pressed_keys
sleep(0.1)
try:
setup()
loop()
except KeyboardInterrupt:
LCD1602.clear() # Limpiar la pantalla LCD al interrumpir
**Code Explanation**
#. The script imports classes for managing digital output devices and buttons from the gpiozero library. It also imports the sleep function from the time module, enabling the addition of delays in the script's execution. Additionally, the LCD1602 library is imported for controlling the LCD1602 display.
.. code-block:: python
#!/usr/bin/env python3
from gpiozero import DigitalOutputDevice, Button
from time import sleep
import LCD1602
#. Defines a custom class for managing the keypad. It initializes the keypad with specified row and column pins and provides a ``read`` method to detect pressed keys.
.. 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
#. Sets up the password verification system. ``LENS`` defines the length of the password. ``password`` is the preset correct password, while ``testword`` is used to store the user's input. ``keyIndex`` tracks the current position in the user's input.
.. code-block:: python
# Password verification setup
LENS = 4
password = ['1', '9', '8', '4'] # Preset password
testword = ['0', '0', '0', '0'] # User input storage
keyIndex = 0 # Index for input keys
#. Function to compare the entered password (``testword``) with the preset password (``password``) and return the result.
.. 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
#. Initializes the keypad and LCD display. Displays a welcome message and instructions for entering the password.
.. 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"]
# Initialize keypad and 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)
#. The main loop for handling keypad input and password verification. It updates the LCD display based on the entered password and provides feedback if the password is correct or 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)
#. Runs the setup and enters the main loop. Allows for a clean exit from the program using a keyboard interrupt (Ctrl+C), clearing the LCD display.
.. code-block:: python
try:
setup()
loop()
except KeyboardInterrupt:
LCD1602.clear() # Clear LCD display on interrupt