.. note::
Ciao, benvenuto nella SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community su Facebook! Approfondisci l'esplorazione del Raspberry Pi, Arduino ed ESP32 con altri appassionati.
**Perché unirti a noi?**
- **Supporto esperto**: Risolvi i problemi post-vendita e le sfide tecniche con l'aiuto della nostra comunità e del nostro team.
- **Impara e condividi**: Scambia consigli e tutorial per migliorare le tue competenze.
- **Anteprime esclusive**: Accedi in anteprima agli annunci di nuovi prodotti e alle anticipazioni esclusive.
- **Sconti speciali**: Approfitta di sconti esclusivi sui nostri prodotti più recenti.
- **Promozioni e omaggi festivi**: Partecipa a omaggi e promozioni speciali durante le festività.
👉 Sei pronto a esplorare e creare con noi? Clicca su [|link_sf_facebook|] e unisciti oggi stesso!
.. _2.2.10_py:
2.2.10 Modulo RFID MFRC522
==============================
Introduzione
-------------------
La Radio Frequency Identification (RFID) si riferisce a tecnologie che utilizzano
la comunicazione wireless tra un oggetto (o tag) e un dispositivo di interrogazione
(o lettore) per tracciare e identificare automaticamente tali oggetti.
Alcune delle applicazioni più comuni di questa tecnologia includono catene di fornitura
al dettaglio, catene di fornitura militari, metodi di pagamento automatizzati, tracciamento
e gestione dei bagagli, monitoraggio dei documenti e gestione farmaceutica, solo per citarne alcuni.
In questo progetto, utilizzeremo RFID per leggere e scrivere informazioni.
Componenti necessari
------------------------------
In questo progetto avremo bisogno dei seguenti componenti.
.. image:: ../img/list_2.2.7.png
È sicuramente conveniente acquistare un kit completo, ecco il link:
.. list-table::
:widths: 20 20 20
:header-rows: 1
* - Nome
- ELEMENTI IN QUESTO KIT
- LINK
* - Kit Raphael
- 337
- |link_Raphael_kit|
Puoi anche acquistarli separatamente dai link sottostanti.
.. list-table::
:widths: 30 20
:header-rows: 1
* - INTRODUZIONE AI COMPONENTI
- LINK PER L'ACQUISTO
* - :ref:`cpn_gpio_extension_board`
- |link_gpio_board_buy|
* - :ref:`cpn_breadboard`
- |link_breadboard_buy|
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_mfrc522`
- |link_mfrc522_rfid_buy|
Schema elettrico
--------------------
.. image:: ../img/image331.png
Procedura sperimentale
--------------------------
**Passo 1:** Costruisci il circuito.
.. image:: ../img/image232.png
**Passo 2:** Configura SPI (consulta :ref:`spi_configuration` per ulteriori dettagli. Se hai già configurato SPI, salta questo passaggio.)
**Passo 3:** Vai nella cartella del codice.
.. raw:: html
.. code-block::
cd ~/raphael-kit/python
**Passo 4:** Eseguire ``2.2.10_write.py``.
.. raw:: html
.. code-block::
sudo python3 2.2.10_write.py
**Passo 5:** Dopo aver eseguito il programma, inserire il testo che si desidera scrivere (fino a 16 caratteri), come "welcome", e premere Invio per confermare. Dopo di ciò, il programma mostrerà "Data has been written to the card". Infine, premere ``Ctrl+C`` per interrompere l'esecuzione del codice.
.. code-block::
Please place your RFID card on the reader...
Press Ctrl-C to stop.
RFID card detected!
Card UID: 9BF6210B
Please enter data to write to the card (up to 16 characters): welcome
Block 8 authentication successful
4 backdata &0x0F == 0x0A 10
Data written
Data has been written to the card
Reading data from block 8:
Sector 8 [119, 101, 108, 99, 111, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0]
**Passo 6:** Ora eseguire ``2.2.10_read.py`` per leggere le informazioni sul tag o la scheda che è stata scritta.
.. raw:: html
.. code-block::
sudo python3 2.2.10_read.py
**Passo 7:** Dopo l'esecuzione, verranno visualizzate le seguenti informazioni.
.. code-block::
Please place your RFID card on the reader...
Press Ctrl-C to stop.
RFID card detected!
Card UID: 9BF6210B
Block 8 authentication successful
Sector 8 [119, 101, 108, 99, 111, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0]
MFRC522_Read return type: , Data: [119, 101, 108, 99, 111, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Sector 8 [119, 101, 108, 99, 111, 109, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Read data: welcome
Analisi del codice di ``2.2.10_write.py``
---------------------------------------------
Questo script Python scrive dati forniti dall'utente su una scheda RFID usando il lettore RFID MFRC522. Lo script verifica continuamente la presenza di una scheda, richiede all'utente di inserire i dati da scrivere e conferma le operazioni di scrittura e lettura riuscite.
#. Importazione dei moduli
* ``MFRC522``: Importa le funzioni e le classi necessarie per le operazioni del lettore RFID.
* ``signal`` e ``time``: ``signal`` è usato per gestire la terminazione tramite SIGINT (Ctrl+C), e ``time`` per aggiungere ritardi nel ciclo principale.
#. Variabile globale
* ``continue_reading``: Controlla il ciclo principale, permettendo di terminare il programma impostando il valore a ``False``.
.. code-block:: python
continue_reading = True
#. Gestione del segnale:
* Funzione ``end_read``: Questa funzione viene attivata quando viene rilevato ``Ctrl+C`` (SIGINT). Imposta ``continue_reading`` su ``False``, permettendo di terminare il programma.
* ``signal.signal(signal.SIGINT, end_read)``: Associa il segnale SIGINT (Ctrl+C) a ``end_read``, così, se interrotto, il programma mostrerà un messaggio e si chiuderà in modo ordinato.
.. code-block:: python
signal.signal(signal.SIGINT, end_read)
#. Configurazione del lettore RFID:
* ``rfid_reader``: Un'istanza della classe ``MFRC522``, utilizzata per controllare le operazioni del lettore RFID.
* ``default_key``: Un elenco di 6 byte, di solito ``0xFF`` per ogni byte. Questa è la chiave di autenticazione predefinita per la maggior parte delle schede RFID.
.. code-block:: python
# Creare un'istanza della classe MFRC522
rfid_reader = MFRC522.MFRC522()
# Definire la chiave predefinita (6 byte, di default tutti 0xFF)
default_key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
#. Istruzioni per l'utente
Lo script stampa istruzioni nella console, informando l'utente di posizionare la scheda RFID sul lettore e utilizzare ``Ctrl+C`` per uscire.
.. code-block:: python
print("Please place your RFID card on the reader...")
print("Press Ctrl-C to stop.")
#. Ciclo principale: Rilevamento, Scrittura e Lettura dei Dati
* **Rilevamento della Scheda**: Lo script chiama continuamente ``MFRC522_Request`` per rilevare le schede RFID. Se una scheda viene rilevata (``status == rfid_reader.MI_OK``), procede al passaggio successivo.
.. code-block:: python
(status, TagType) = rfid_reader.MFRC522_Request(rfid_reader.PICC_REQIDL)
# Se una scheda viene rilevata
if status == rfid_reader.MI_OK:
print("RFID card detected!")
...
else:
# Attendere un po' prima di riprovare
time.sleep(0.5)
* **Recupero dell'UID della Scheda**: Chiama ``MFRC522_SelectTagSN`` per recuperare l'identificatore unico (UID) della scheda. Se riuscito, l'UID viene convertito in una stringa esadecimale e stampato. L'UID è necessario per l'autenticazione.
.. code-block:: python
(status, uid) = rfid_reader.MFRC522_SelectTagSN()
# Se l'UID è stato recuperato, continuare
if status == rfid_reader.MI_OK:
# Stampare l'UID
uid_str = ''.join(['%02X' % i for i in uid])
print("Card UID: %s" % uid_str)
...
else:
print("Unable to get card UID")
* **Preparazione dei Dati**:
* **Richiesta di Inserimento**: All'utente viene richiesto di inserire i dati da scrivere sulla scheda (fino a 16 caratteri).
* **Troncamento dei Dati**: I dati vengono troncati a 16 caratteri se l'utente inserisce di più.
* **Conversione da Stringa a Byte**: L'input dell'utente viene convertito in una lista di byte, riempita fino a 16 byte, come richiesto dal formato di archiviazione della scheda RFID.
.. code-block:: python
write_data = input("Please enter data to write to the card (up to 16 characters): ")
# Assicurarsi che i dati non superino i 16 caratteri
write_data = write_data[:16]
# Convertire la stringa in una lista di byte, riempire fino a 16 byte
data_to_write = [0x00]*16
string_bytes = write_data.encode('utf-8')
for i in range(len(string_bytes)):
data_to_write[i] = string_bytes[i]
* **Specificare il Numero di Blocco**: Lo script specifica il blocco 8 per scrivere i dati. Nota: i numeri di blocco devono evitare i blocchi di intestazione del settore, generalmente l'ultimo blocco in ogni settore, poiché sono usati per informazioni di controllo.
.. code-block:: python
block_num = 8 # Per esempio, scegliere il blocco 8
* **Autenticazione della Scheda**: ``MFRC522_Auth`` autentica il blocco specificato usando la chiave predefinita e l'UID. Se l'autenticazione è riuscita, lo script procede con la scrittura dei dati.
.. code-block:: python
status = rfid_reader.MFRC522_Auth(rfid_reader.PICC_AUTHENT1A, block_num, default_key, uid)
if status == rfid_reader.MI_OK:
print("Autenticazione del blocco %d riuscita" % block_num)
...
else:
print("Autenticazione fallita")
rfid_reader.MFRC522_StopCrypto1()
* **Scrittura dei Dati sulla Scheda**: ``MFRC522_Write`` scrive i dati preparati sul blocco specificato della scheda RFID. Dopo la scrittura, un messaggio conferma che i dati sono stati scritti correttamente sulla scheda.
.. code-block:: python
rfid_reader.MFRC522_Write(block_num, data_to_write)
print("Data has been written to the card")
**Punti Chiave**
* **Terminazione Ordinata**: Lo script cattura SIGINT (Ctrl+C) per terminare in modo sicuro e stampare un messaggio, consentendo il completamento di qualsiasi operazione in corso prima di uscire.
* **Interazione con l'Utente**: Richiede all'utente di inserire dati, consentendo la personalizzazione dei dati ogni volta che la scheda viene scritta.
* **Autenticazione**: Garantisce che l'accesso al blocco specificato sia gestito in modo sicuro.
* **Formattazione dei Dati**: Converte i dati della stringa in un formato di lista di byte compatibile.
Spiegazione del Codice per ``2.2.10_read.py``
-----------------------------------------------
Questo script Python utilizza un **lettore RFID (MFRC522)** per leggere dati dalle schede RFID. Lo script è strutturato per controllare continuamente la presenza di schede, recuperare i dati e gestire in modo ordinato le richieste di uscita tramite gestione dei segnali.
#. Importazione dei Moduli:
* ``MFRC522``: Questo modulo fornisce metodi per interagire con il lettore RFID MFRC522.
* ``signal`` e ``time``: Utilizzati per gestire la terminazione dello script (es. ``Ctrl+C``) e controllare i tempi di alcune operazioni.
#. Variabili Globali:
* ``continue_reading``: Una variabile booleana che controlla il ciclo principale di lettura, permettendo allo script di interrompersi in modo ordinato quando si preme ``Ctrl+C``.
.. code-block:: python
continue_reading = True
#. Gestione dei Segnali:
* Funzione ``end_read``: Questa funzione viene attivata quando viene rilevato ``Ctrl+C`` (SIGINT). Imposta ``continue_reading`` su ``False``, permettendo allo script di uscire in modo ordinato.
* ``signal.signal(signal.SIGINT, end_read)``: Collega il segnale SIGINT (Ctrl+C) a ``end_read``, in modo che, se interrotto, lo script mostri un messaggio e si chiuda ordinatamente.
.. code-block:: python
signal.signal(signal.SIGINT, end_read)
#. Configurazione del Lettore RFID:
* ``rfid_reader``: Un'istanza della classe ``MFRC522``, utilizzata per le operazioni del lettore RFID.
* ``default_key``: Una lista di 6 byte, tipicamente ``0xFF`` per ogni byte. Questa è la chiave di autenticazione predefinita per la maggior parte delle schede RFID.
* ``block_num``: Specifica il numero di blocco da leggere dalla scheda RFID, qui impostato al blocco ``8``. Il numero di blocco deve corrispondere a quello utilizzato durante la scrittura dei dati.
.. code-block:: python
# Creare un'istanza della classe MFRC522
rfid_reader = MFRC522.MFRC522()
# Definire la chiave predefinita (6 byte, di default tutti 0xFF)
default_key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
# Definire il numero di blocco da leggere (deve corrispondere al blocco utilizzato durante la scrittura)
block_num = 8 # Per esempio, blocco 8
#. Istruzioni per l'Utente
Lo script stampa istruzioni nella console, informando l'utente di posizionare la scheda RFID sul lettore e di utilizzare ``Ctrl+C`` per uscire.
.. code-block:: python
print("Please place your RFID card on the reader...")
print("Press Ctrl-C to stop.")
#. Ciclo Principale: Rilevamento della Scheda RFID e Lettura dei Dati.
* **Scansione delle Schede**: Il ciclo principale chiama continuamente ``MFRC522_Request`` per rilevare le schede RFID. Se una scheda viene rilevata, procede ai passaggi successivi.
.. code-block:: python
(status, TagType) = rfid_reader.MFRC522_Request(rfid_reader.PICC_REQIDL)
if status == rfid_reader.MI_OK:
print("RFID card detected!")
...
else:
# Se non viene rilevata nessuna scheda, attendere un breve periodo prima di riprovare
time.sleep(0.5)
* **Recupero dell'UID della Scheda**: Usa ``MFRC522_SelectTagSN`` per ottenere l'identificatore unico (UID) della scheda. Se riuscito, converte l'UID in una stringa esadecimale e lo stampa. Questo UID è necessario per autenticare la scheda.
.. code-block:: python
(status, uid) = rfid_reader.MFRC522_SelectTagSN()
# Se l'UID è stato recuperato con successo, procedere
if status == rfid_reader.MI_OK:
# Convertire la lista UID in una stringa esadecimale
uid_str = ''.join(['%02X' % i for i in uid])
print("Card UID: %s" % uid_str)
...
else:
print("Unable to get card UID")
* **Autenticazione della Scheda**: ``MFRC522_Auth`` autentica l'accesso al blocco specificato usando la chiave predefinita e l'UID della scheda. Se l'autenticazione riesce, lo script passa alla lettura dei dati dal blocco.
.. code-block:: python
status = rfid_reader.MFRC522_Auth(rfid_reader.PICC_AUTHENT1A, block_num, default_key, uid)
if status == rfid_reader.MI_OK:
print("Autenticazione del blocco %d riuscita" % block_num)
...
else:
print("Autenticazione fallita, codice di stato: %s" % status)
rfid_reader.MFRC522_StopCrypto1()
* **Lettura dei Dati**:
* ``MFRC522_Read`` legge i dati dal blocco specificato.
* ``data``: Questa variabile contiene i dati grezzi del blocco se l'operazione di lettura ha successo.
* Lo script converte ogni byte in ``data`` in caratteri e rimuove eventuali byte nulli di padding (``\x00``). I dati elaborati vengono quindi stampati.
.. code-block:: python
read_status, data = rfid_reader.MFRC522_Read(block_num)
print(f"MFRC522_Read return type: {type(read_status)}, Data: {data}")
if read_status == rfid_reader.MI_OK and data:
print(f"Settore {block_num} {data}")
# Convertire i dati in byte a stringa e rimuovere eventuali byte nulli di padding
read_data = ''.join([chr(byte) for byte in data]).rstrip('\x00')
print("Dati letti: %s" % read_data)
else:
print("Lettura dei dati fallita, codice di stato: %s" % read_status)
* ``MFRC522_StopCrypto1`` viene chiamato per fermare la crittografia e reimpostare la comunicazione della scheda.
.. code-block:: python
# Fermare la crittografia sulla scheda
rfid_reader.MFRC522_StopCrypto1()
* **Attesa tra le Letture**: Se non viene rilevata alcuna scheda, il ciclo si interrompe per 0,5 secondi prima di riprovare.
.. code-block:: python
else:
# Se non viene rilevata nessuna scheda, attendere un breve periodo prima di riprovare
time.sleep(0.5)
**Punti Chiave**
* **Uscita Ordinata**: Lo script cattura il segnale ``SIGINT`` per una terminazione ordinata, consentendo al lettore RFID di completare qualsiasi operazione in corso.
* **Gestione del Blocco e dell'UID**: Usa il blocco e l'UID come componenti chiave nella lettura dei dati da una scheda RFID, con una corretta gestione di autenticazione e errori di lettura.
* **Design Modulare**: L'uso di funzioni dedicate dal modulo ``MFRC522`` rende lo script leggibile e modulare, semplificando operazioni RFID come autenticazione e lettura dei dati.
Immagine del fenomeno
------------------------------
.. image:: ../img/image233.jpeg