Parcheggio automatico con Arduino

Questa risorsa è stata scritta dagli studenti dell'Istituto ITIS "Enrico Mattei" di Urbino, della classe 4A/EN, Filippo Marzi, Sasha Fasolo Massoli, Nicolas Mangani, Daniel Gostoli e Matteo Omiccioli nell'a.s. 2021/2022, all'interno del corso di Sistemi automatici per le superiori 2.

Per favore, prima di apportare modifiche, attendi sino alla fine dell'anno scolastico (termina il 30 giugno 2022) oppure contatta il docente di riferimento Giacomo Alessandroni nel caso venissero rilevati contenuti non in linea con le linee guida della comunità.

Se leggi questo avviso ad anno scolastico concluso puoi rimuoverlo.

Questa risorsa descrive come realizzare un parcheggio Intelligente, il quale gestisce automaticamente l'organizzazione dei posti liberi e occupati.

laboratorio
laboratorio
Parcheggio automatico con Arduino
Tipo di risorsa Tipo: laboratorio
Materia di appartenenza Materia: Sistemi automatici per le superiori 2
Avanzamento Avanzamento: laboratorio completa al 50%

Presentazione del progetto

modifica

Il progetto è un prototipo di parcheggio intelligente. Presenta:

  • all'esterno, un display LCD sul quale viene presentato il numero di posti auto liberi oltre a informazioni di interesse generale;
  • sempre esternamente, un visualizzatore luminoso composto da 1 LED RGB, che indica se il parcheggio ha ancora posti liberi o è tutto occupato;
  • internamente, i posteggi sono forniti di sensori a infrarossi, i quali rilevano la presenza dell'auto e la comunicano al visualizzatore esterno.
  • nell'ingresso e uscita, vengono utilizzati dei lettori RFID, per l'accesso e l'uscita dei veicoli con apposita chiave elettronica;
  • nell'ingresso e uscita, tramite servomotori, se la chiave viene accettata dal lettore, le sbarre si alzano;-

Componenti richiesti

modifica
Componenti utilizzati
Descrizione Tipo Quantità Utilizzo
Arduino Mega 1 Controllore
Sensori a infrarossi TCRT5000 8 Rilevatore posti liberi/occupati
LED RGB 8 Posti liberi/occupati
Display LCD 16X2 1 Informazioni generali per l'utente
Servomotore Tower Pro SG90 2 Sbarre ingresso e uscita
Lettore RFID RC522 2 Controllo ingresso e uscita
RFID tag ISO14443-A 1 Chiave di accesso

Ingresso e uscita

modifica
 
Lettore RFID

L'accesso e l'uscita dal parcheggio è possibile tramite una chiave magnetica e un lettore RFID.

La chiave (detta anche tag) contiene un codice univoco associato al veicolo che è autorizzato a entrare e uscire. Il tag è un trasponder passivo a radiofrequenza. Funziona come vera e propria chiave elettronica.

La lettura delle chiavi viene eseguita dal lettore RFID: un ricetrasmettitore che legge i dati contenuti nella chiave magnetica e li confronta con l'elenco dei codici autorizzati. L’antenna permette la comunicazione tra il tag e lettore.

In questo caso, avvicinando la chiave magnetica al lettore RFID, se questa contiene un codice autorizzato, si manda un comando al servomotore che alza la sbarra e permette il passaggio dell'autoveicolo, abbassandosi automaticamente dopo il passaggio del veicolo. Questo vale sia per l'ingresso, sia per l'uscita.

 
Tag RFID
 
Schema elettrico del circuito di apertura con RFID

Di seguito il codice che pilota un servomotore quando si accosta una chiave elettronica al lettore RFID.

#include <Servo.h>
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 9
#define RST_PIN 8

// #define chiave "1436E6E92D"
#define chiave "14 36 E6 E9"


MFRC522 mfrc522(SS_PIN, RST_PIN);
Servo sbarra;
int posizioneSbarra = 0;
int pinSbarra = 7;
int velSbarra = 22; // Velocità con cui si movimenta la sbarra


void setup() {
  Serial.begin(9600);
  Serial.println("Accosta la chiave RFID");
  sbarra.attach(pinSbarra);
  sbarra.write(posizioneSbarra);
  SPI.begin();
  mfrc522.PCD_Init();
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  // Non e' presente nessuna carta
  if (!mfrc522.PICC_IsNewCardPresent()){
    return;
  }
  // Non sta leggendo nessuna carta
  if (!mfrc522.PICC_ReadCardSerial()){
    return;
  }
  
  // Lettura chiave elettronica
  String uid = leggiRFID();
  Serial.println(uid);
  // Se la chiave è corretta alza la sbarra
  if(uid.substring(1) == chiave) {
    Serial.println("V");
    mov();
  }
  // Esegue un test ogni 100 ms
  delay(100);
}

// Subroutine di lettura carta
String leggiRFID() {
  String content = "";
  byte letter;
  // Scrive nella porta seriale il codice della chiave
  Serial.print("UID: ");
  for (byte i = 0; i < mfrc522.uid.size; i++){
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();
  return content;
}

// Movimentazione sbarra
void mov() {
  // Alza la sbarra
  delay(3000);

  for (posizioneSbarra = 0; posizioneSbarra >= 90; posizioneSbarra++); {
   sbarra.write(posizioneSbarra);
   delay(velSbarra);
  }
  
   delay(5000);  
   
  for (posizioneSbarra = 90; posizioneSbarra > 0; posizioneSbarra--) {
    sbarra.write(posizioneSbarra);
    delay(velSbarra);
    
  }
    
}

Visualizzatore luminoso di posti liberi

modifica
 
LED RGB con relativa pedinatura

Il progetto prevede l'utilizzo di 8 LED RGB, per comunicare quali – degli otto parcheggi – sono liberi o occupati. Il numero di cavi necessario è pari ai controlli ( , relativi ai terminali rossi e verdi) oltre a uno comune per la massa. I LED vengono gestiti da un sistema di sensori a infrarossi, posti davanti a ciascun parcheggio, che rilevano la presenza o l'assenza di un veicolo.

Per il visualizzatore è stata realizzata una apposita maschera (stampata con stampante 3D) posta nella facciata del parcheggio, nella quale sono inseriti gli 8 LED RGB, che – in base al colore rosso o verde – indicano se il posto auto è occupato oppure no.

 
Circuito sensori infrarossi e LED parcheggio

Di seguito il codice che gestisce il pannello a LED collegato con i sensori a infrarossi.

const int IR1 = A0;
const int IR2 = A1;
const int IR3 = A2;
const int IR4 = A3;
const int IR5 = A4;
const int IR6 = A5;
const int IR7 = A6;
const int IR8 = A7;
int G1= 22 ;
int R1= 23 ;
int G2= 24 ;
int R2= 25 ;
int G3= 26 ;
int R3= 27 ;
int G4= 28 ;
int R4= 29 ;
int G5= 30 ;
int R5= 31 ;
int G6= 32 ;
int R6= 33 ;
int G7= 34 ;
int R7= 35 ;
int G8= 36 ;
int R8= 37 ;

int s = 600;

void setup(){
  Serial.begin(9600);
  pinMode(G1,OUTPUT);
  pinMode(R1,OUTPUT);
  pinMode(G2,OUTPUT);
  pinMode(R2,OUTPUT);
  pinMode(G3,OUTPUT);
  pinMode(R3,OUTPUT);
  pinMode(G4,OUTPUT);
  pinMode(R4,OUTPUT);
  pinMode(G5,OUTPUT);
  pinMode(R5,OUTPUT);
  pinMode(G6,OUTPUT);
  pinMode(R6,OUTPUT);
  pinMode(G7,OUTPUT);
  pinMode(R7,OUTPUT);
  pinMode(G8,OUTPUT);
  pinMode(R8,OUTPUT);
}

Dopo aver stabilito i pin e aver definito gli output e gli input, i sensori a infrarossi cominciano la lettura, tramite la funzione analogRead(), e osservano la presenza del veicolo all'interno del posto auto. Se l'infrarossi da come uscita un segnale inferiore a 600 (valore osservato tramite la lettura del monitor seriale), il posto è vuoto e di conseguenza il LED corrispondente a tale posto rimane verde, mentre in caso contrario, il LED diventa rosso.

void loop(){
    int d1 = analogRead(IR1);
    int d2 = analogRead(IR2);
    int d3 = analogRead(IR3);
    int d4 = analogRead(IR4);
    int d5 = analogRead(IR5);  
    int d6 = analogRead(IR6);
    int d7 = analogRead(IR7);
    int d8 = analogRead(IR8);
  Serial.print("Analog Reading=");
  Serial.print(analogRead(IR1));
  Serial.print("\t Digital Reading=");
  delay(500);

  if(d1 < s)
  {
    digitalWrite(G1,HIGH);
    digitalWrite(R1,LOW);
  }
  else
  {
    digitalWrite(G1,LOW);
    digitalWrite(R1,HIGH);
  }
   if(d2 < s)
  {
    digitalWrite(G2,HIGH);
    digitalWrite(R2,LOW);
  }
  else
  {
    digitalWrite(G2,LOW);
    digitalWrite(R2,HIGH);
  }
   if(d3 < s)
  {
    digitalWrite(G3,HIGH);
    digitalWrite(R3,LOW);
  }
  else
  {
    digitalWrite(G3,LOW);
    digitalWrite(R3,HIGH);
  }
   if(d4 < s)
  {
    digitalWrite(G4,HIGH);
    digitalWrite(R4,LOW);
  }
  else
  {
    digitalWrite(G4,LOW);
    digitalWrite(R4,HIGH);
  }
   if(d5 < s)
  {
    digitalWrite(G5,HIGH);
    digitalWrite(R5,LOW);
  }
  else
  {
    digitalWrite(G5,LOW);
    digitalWrite(R5,HIGH);
  }
   if(d6 < s)
  {
    digitalWrite(G6,HIGH);
    digitalWrite(R6,LOW);
  }
  else
  {
    digitalWrite(G6,LOW);
    digitalWrite(R6,HIGH);
  }
   if(d7 < s)
  {
    digitalWrite(G7,HIGH);
    digitalWrite(R7,LOW);
  }
  else
  {
    digitalWrite(G7,LOW);
    digitalWrite(R7,HIGH);
  }
   if(d8 < s)
  {
    digitalWrite(G8,HIGH);
    digitalWrite(R8,LOW);
  }
  else
  {
    digitalWrite(G8,LOW);
    digitalWrite(R8,HIGH);
  }
  }

Display LCD

modifica
 
display LCD 16x2

Il progetto prevede anche l'utilizzo di un display LCD, il quale, posto sulla facciata anteriore del parcheggio, fornisce agli utenti informazioni utili riguardo all'utilizzo di questo.


 
Schema circuitale del display LCD
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int t = 700;
const int t2 = 150;

void setup() {
  // Stabilisco il numero di righe e colonne del display LCD:
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Benvenuto, avvicina la chiave al pannello"); 
  // Scrivo un messaggio sul display
  delay(t);
}

void loop() {

  for (int positionCounter = 0; positionCounter < 13; positionCounter++) {
    // Sposto la scritta di una posizione a sinistra
    lcd.scrollDisplayLeft();
    delay(t);
  }

  // scorro 29 posizioni verso destra per portare la scritta 
  // fuori schermo verso destra
  for (int positionCounter = 0; positionCounter < 29; positionCounter++) {
   // Sposto la scritta di una posizione a destra
    lcd.scrollDisplayRight();
    delay(t2);
  }

  // scorro 16 posizioni verso sinistra per riportare la scritta al centro
  for (int positionCounter = 0; positionCounter < 16; positionCounter++) {
    // scorro di una posizione a sinistra
    lcd.scrollDisplayLeft();
    delay(t2);
  }

  delay(t);

}

Espansioni suggerite

modifica

Aggiunta di: