Sistema accesso Fingerprint Scanner TTL GT-511C3 – quarta parte

Eccoci arrivati alla quarta ed ultima parte del Fingerprint Scanner TTL GT-511C3 per il controllo degli accessi con impronta digitale.

Fingerprint Scanner TTL GT-511C3 IV parte

Leggi gli articoli precedenti per ricapitolare dove eravamo arrivati con questo progetto e come l’ho fatto evolvere:

Riassumendo:

il lettore era collegato ad un display lcd che mostrava messaggi e richieste all’utente e ad un pulsante che serviva per cambiare lo stato del led che simulava la serratura e che, se premuto 2 volte a distanza temporale ravvicinata, effettuava il reset dei dati ed il restart della scheda.

Il sistema, all’avvio, richiedeva la registrazione delle impronte di almeno 2 dita e di una sequenza che veniva considerata una sequenza root (cioè una sequenza che permetteva, oltre a cambiare lo stato del led, anche di accedere ad un menu che dava la possibilità di aggiungere dita e/o sequenze).

Con l’evoluzione odierna ho aggiunto ulteriori funzionalità:

  • Devi assegnare un nome ad ogni sequenza
  • Devi esplicitare, per ogni sequenza aggiunta, se si tratta di una sequenza di root o standard
  • Puoi cancellare una sequenza inserita precedentemente
  • Ho aggiunto un nuovo pulsante che ti permette di far scadere le sequenze

Esplicitiamo i singoli punti.

Dare un nome ad una sequenza:

nell’ottica di poter cancellare le sequenze, ho aggiunto la funzionalità che ti permette di dare un nome ad una sequenza appena creata. Il nome è una stringa alfabetica (solo lettere) di massimo 8 caratteri inseribile usando i pulsanti del display LCD. Vedi la parte di descrizione del codice per ulteriori dettagli.

Esplicitare tipo sequenza:

Dopo aver assegnato il nome alla sequenza, devi dire al sistema se la sequenza è standard o root.

Cancellazione sequenza:

dall’elenco delle sequenze immesse a sistema, puoi sceglierne una da cancellare a patto, ovviamente, che non sia l’ultima sequenza di tipo root rimasta. La selezione avviene con i tasti del display

Pulsante per far scadere le sequenze:

l’idea che c’è dietro è che una sequenza deve avere una validità temporale limitata e poi deve essere cambiata.

Quando, per aprire, immetti la tua sequenza, il sistema controlla se questa è scaduta (confrontando la data attuale con quella di creazione della sequenza) e se è scaduta ti chiede di cambiare la sequenza con un’altra.

Poiché la memoria dati è già al limite con la configurazione attuale, l’aggiunta di un ulteriore modulo e l’inclusione della relativa libreria, potrebbe portare alla sua saturazione; ho quindi deciso di non montare il modulo RTC e di simulare la scadenza con il secondo pulsante alla pressione del quale tutte le sequenze scadono.

I dati relativi alle sequenze vengono sempre scritti (e letti all’avvio) nelle eeprom arduino.

Lo schema di salvataggio, però, a causa dei nuovi dati, varia leggermente:

EEPROM BYTE Contenuto
0 Numero di dita registrate
1 Numero di sequenze registrate
2 id dito#1 sequenza#1
3 id dito#2 sequenza#1
4 id dito#3 sequenza#1
5 id dito#4 sequenza#1
6 Tipo sequenza#1 (root o standard)
7 nome seq#1 carattere#1
8 nome seq#1 carattere#2
9 nome seq#1 carattere#3
10 nome seq#1 carattere#4
11 nome seq#1 carattere#5
12 nome seq#1 carattere#6
13 nome seq#1 carattere#7
14 nome seq#1 carattere#8
15 nome seq#1 carattere#9
16 id dito#1 sequenza#2
17 id dito#2 sequenza#2
18 id dito#3 sequenza#2
19 id dito#4 sequenza#2
20 Tipo sequenza#2 (root o standard)
21 nome seq#2 carattere#1
22 nome seq#2 carattere#2
23 nome seq#2 carattere#3
24 nome seq#2 carattere#4
25 nome seq#2 carattere#5
26 nome seq#2 carattere#6
27 nome seq#2 carattere#7
28 nome seq#2 carattere#8
29 nome seq#2 carattere#9

 

Lo schema elettrico varia leggermente per l’aggiunta del secondo pulsante:

collegamento 4_reader

 

 

 

 

Vediamo il codice dello sketch:

#include <LiquidCrystal.h>
#include <EEPROM.h>
#include "FPS_GT511C3.h"
#include "SoftwareSerial.h"
#include <avr/io.h>
#include <avr/wdt.h>

#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {} 

struct sequenza {
  byte seq[4];
  byte root;
  char nome[9];
};

char nome_sequenza[9];
sequenza seq[2];
byte tot_root=0;
byte seqroot;
boolean scadenza = false;

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
FPS_GT511C3 fps(12, 13);
byte dita_registrate;
byte sequenze;
boolean serratura_aperta=true;
byte led = 11;
double intervallo,intervallo2;


void setup()
{
  byte i,j;

  Serial.begin(9600);  
  lcd.begin(16, 2);
  pinMode (10,OUTPUT);
  dita_registrate=EEPROM.read(0);
  sequenze=EEPROM.read(1);
  fps.Open();
  if (sequenze>0)
  {
    for (i = 0; i<sequenze; i++)
    {
      for(j=0;j<4;j++)
      {
        seq[i].seq[j]=EEPROM.read(2+i*14+j);
      }
      seq[i].root=EEPROM.read(2+i*14+4);
      tot_root+=seq[i].root;
      for(j=0;j<9;j++)
      {
        seq[i].nome[j]=EEPROM.read(2+i*14+j+5);
     }
    }
  }
  digitalWrite(10,LOW);
  if (serratura_aperta) digitalWrite(led,HIGH);
  else digitalWrite(led,LOW);
  attachInterrupt(0, apre_chiude, FALLING);
  attachInterrupt(1, scade, FALLING);
}

void loop() 
{
  int pulsante;
  byte apertura;
  byte i;
  
  if (dita_registrate<1) inizializza();
  digitalWrite(led,serratura_aperta);
  pulsante=analogRead(0);
  if (pulsante<1000)
  {
    int sequenza[4];
    digitalWrite(10,HIGH);
    fps.SetLED(true);
    lcd.clear();
    lcd.print("Press finger #1");
    if (put_finger()==1) return;
    fps.CaptureFinger(true);
    int id1 = fps.Identify1_N();
    if(id1 < dita_registrate)
    {
      lcd.clear();
      lcd.print("Remove finger");
      if (remove_finger()==1) return;
      sequenza[0]=id1;
      lcd.clear();
      lcd.print("Press finger #2");
      if (put_finger()==1) return;
      fps.CaptureFinger(true);
      int id2 = fps.Identify1_N();
      if(id2 < dita_registrate)
      {
        lcd.clear();
        lcd.print("Remove finger");
        if (remove_finger()==1) return;
        sequenza[1]=id2;
        lcd.clear();
        lcd.print("Press finger #3");
        if (put_finger()==1) return;
        fps.CaptureFinger(true);
        int id3 = fps.Identify1_N();
        if(id3 < dita_registrate)
        {
          lcd.clear();
          lcd.print("Remove finger");
          if (remove_finger()==1) return;
          sequenza[2]=id3;
          lcd.clear();
          lcd.print("Press finger #4");
          if (put_finger()==1) return;
          fps.CaptureFinger(true);
          int id4 = fps.Identify1_N();
          if(id4 < dita_registrate)
          {
            sequenza[3]=id4;
            for(i = 0;i<sequenze;i++)
            {
              if(sequenza[0]==seq[i].seq[0] && sequenza[1]==seq[i].seq[1] && sequenza[2]==seq[i].seq[2] && sequenza[3]==seq[i].seq[3])
              {
                if(seq[i].root==1)
                {
                  lcd.clear();
                  lcd.print("RT SEQ ");
                  lcd.print(seq[i].nome);
                  delay(2000);
                  lcd.clear();
                  fps.SetLED(false);
                  if (scadenza) cambia_sequenza(i);
                  apre_chiude();
                  mostra_menu();
               }
               else
               {
                  lcd.clear();
                  lcd.print("STD SEQ ");
                  lcd.print(seq[i].nome);
                  delay(2000);
                  lcd.clear();
                  fps.SetLED(false);
                  if (scadenza) cambia_sequenza(i);
                  digitalWrite(10,LOW);
                  apre_chiude();
                  return;
                }
              }
            }
            if (i==sequenze)
            {
              lcd.clear();
              lcd.print("BAD SEQUENCE");
              delay(2000);
              lcd.clear();
              fps.SetLED(false);
              digitalWrite(10,LOW);
              return;
            }  
          }
          else
          {
            lcd.clear();
            lcd.print("BAD FINGER #4");
            delay(2000);
            lcd.clear();
            fps.SetLED(false);
            digitalWrite(10,LOW);
            return;
          }
        }
        else
        {
          lcd.clear();
          lcd.print("BAD FINGER #3");
          delay(2000);
          lcd.clear();
          fps.SetLED(false);
          digitalWrite(10,LOW);
          return;
        }
      }
      else
      {
        lcd.clear();
        lcd.print("BAD FINGER #2");
        delay(2000);
        lcd.clear();
        fps.SetLED(false);
        digitalWrite(10,LOW);
        return;
      }
    }
    else
    {
      lcd.clear();
      lcd.print("BAD FINGER #1");
      delay(2000);
      lcd.clear();
      fps.SetLED(false);
      digitalWrite(10,LOW);
      return;
    }
  }
}

byte inizializza()
{
  byte ritorno;
  byte exit=0;
  byte stato_menu=0;
  byte ristampa = 1;
  digitalWrite(10,HIGH);
  lcd.clear();
  lcd.print("INIZIALIZZAZIONE...");
  fps.DeleteAll();
  delay(2000);
  dita_registrate=0;
  sequenze=0;
  EEPROM.write(0,0);
  EEPROM.write(1,0);
  fps.SetLED(true);
  ritorno=Enroll(0);
  while (ritorno != 0) ritorno=Enroll(0);
  EEPROM.write(0,1);
  dita_registrate = 1;
  fps.SetLED(false);
  while (exit==0)
  {
    int pulsante;
    if (ristampa==1)
    {
      switch(stato_menu)
      {
        case 0:
          lcd.clear();
          lcd.print("Add finger   <--");
          lcd.setCursor(0,1);
          lcd.print("Add sequence");
          break;
        case 1:
          lcd.clear();
          lcd.print("Add finger");
          lcd.setCursor(0,1);
          lcd.print("Add sequence  <--");
          break;
        case 2:
          lcd.clear();
          lcd.print("Add sequence");
          lcd.setCursor(0,1);
          lcd.print("Del sequence  <--");
          break;
        case 3:
          lcd.clear();
          lcd.print("Del sequence");
          lcd.setCursor(0,1);
          lcd.print("Exit          <--");
          break;
      }
    }
    ristampa=0;
    pulsante=analogRead(0);
    if ((pulsante>190) && (pulsante<220))
    {
      ristampa=1;
      stato_menu-=1;
      if (stato_menu<0) stato_menu = 3;
      delay(300);
    }
    if ((pulsante>390) && (pulsante<430))
    {
      ristampa=1;
      stato_menu+=1;
      if (stato_menu>3) stato_menu = 0;
      delay(300);
    }
    if ((pulsante>800) && (pulsante<840))
    {
      if (stato_menu==0)
      {
        fps.SetLED(true);
        lcd.clear();
        lcd.print("Record new finger");
        delay(2000);
        ritorno = Enroll(dita_registrate+1);
        if (ritorno==0)
        {
          ristampa=1;
          lcd.clear();
          lcd.print("Finger added!!");
          dita_registrate+=1;
          EEPROM.write(0,dita_registrate);
          delay(2000);
        }
        fps.SetLED(false);
      }
      if (stato_menu==1)
      {
        fps.SetLED(true);
        ristampa=1;
        add_sequence();
        fps.SetLED(false);
      }
      if (stato_menu==2)
      {
        ristampa=1;
        del_seq();
      }
      if (stato_menu==3)
      {
        if (sequenze > 0 && tot_root>0) exit=1;
        else
        {
          ristampa=1;
          lcd.clear();
          lcd.print("You have to add");
          lcd.setCursor(0,1);
          lcd.print("one root seq");
          delay(2000);
        }
      }
    }   
  }
  digitalWrite(10,LOW);
}

byte Enroll(byte enrollid)
{
  boolean result;
  byte enr_result;
  
  lcd.clear();
  digitalWrite(10,HIGH);
  lcd.print("Record finger ");
  lcd.print(enrollid);
  enr_result=fps.EnrollStart(enrollid);
  if (enr_result==0)
  {
    while(fps.IsPressFinger() == false) delay(100);
    result = fps.CaptureFinger(true);
    if (result)
    {
      enr_result=fps.Enroll1();
      if (enr_result ==0)
      {
        lcd.clear();
        lcd.print("Remove finger");
        while(fps.IsPressFinger() == true) delay(100);
        lcd.clear();
        lcd.print("Press again");
        while(fps.IsPressFinger() == false) delay(100);
        result = fps.CaptureFinger(true);
        if (result)
        {
          enr_result=fps.Enroll2();
          if (enr_result ==0)
          {
            lcd.clear();
            lcd.print("Remove finger"); 
            while(fps.IsPressFinger() == true) delay(100);
            lcd.clear();
            lcd.print("Press again");
            while(fps.IsPressFinger() == false) delay(100);
            result = fps.CaptureFinger(true);
            if (result)
            {
              lcd.clear();
              lcd.print("Remove finger");
              enr_result = fps.Enroll3();
              if (enr_result == 0)
              {
                lcd.clear();
                lcd.print("Enrolling OK");
                delay(2000);
                return 0;
              }
              else
              {
                lcd.clear();
                lcd.print("Enrolling KO:");
                lcd.setCursor(0,1);
                switch(enr_result)
                {
                  case 1:
                    lcd.print("Generic error");
                    break;
                  case 2:
                    lcd.print("Too bad FPrint");
                    break;
                  case 3:
                    lcd.print("FPrint exists");
                    break;
                }
                delay(2000);
                return 1;
              }
            }
            else
            {
              lcd.clear();
              lcd.print("Failed 3rd read");
              delay(2000);
              return 1;
             }
          }
          else
          {
            lcd.clear();
            lcd.print("Enroll failed:");
            lcd.setCursor(0,1);
            switch(enr_result)
            {
                case 1:
                  lcd.print("Generic error");
                  break;
                case 2:
                  lcd.print("Too bad FPrint");
                   break;
                case 3:
                  lcd.print("FPrint exists");
                  break;
            }
            delay(2000);
            return 1;
          }     
        }
        else       
        {
          lcd.clear();
          lcd.print("Failed 2nd read");
          delay(2000);
          return 1;
        }
      }
      else
      {
        lcd.clear();
        lcd.print("Enroll failed:");
        lcd.setCursor(0,1);
        switch(enr_result)
        {
            case 1:
              lcd.print("Generic error");
              break;
            case 2:
              lcd.print("Too bad FPrint");
               break;
            case 3:
              lcd.print("FPrint exists");
              break;
        }
        delay(2000);
        return 1;
      }
    }
    else
    {
        lcd.clear();
        lcd.print("Failed 1st read");
        delay(2000);
        return 1;
    }
  }
  else
  {
    lcd.clear();
    lcd.print("Enroll failed:");
    lcd.setCursor(0,1);
    switch(enr_result)
    {
        case 1:
          lcd.print("Reader DB full");
          break;
        case 2:
          lcd.print("ID ");
          lcd.print(enrollid);
          lcd.print(" invalid");
          break;
        case 3:
          lcd.print("ID ");
          lcd.print(enrollid);
          lcd.print(" busy");
          break;
    }
    delay(2000);
    return 1;
  }
}

void add_sequence ()
{
  byte sequenza[4];
  byte id;
  byte i,j;
  
  lcd.clear();
  lcd.print("Press finger #1");
  while(fps.IsPressFinger() == false) delay(100);
  fps.CaptureFinger(true);
  id = fps.Identify1_N();
  if(id < dita_registrate)
  {
    sequenza[0]=id;
    lcd.clear();
    lcd.print("Remove finger");
    while(fps.IsPressFinger() == true) delay(100);
    lcd.clear();
    lcd.print("Press finger #2");
    while(fps.IsPressFinger() == false) delay(100);
    fps.CaptureFinger(true);
    id = fps.Identify1_N();
    if(id < dita_registrate)
    {
      sequenza[1]=id;
      lcd.clear();
      lcd.print("Remove finger");
      while(fps.IsPressFinger() == true) delay(100);
      lcd.clear();
      lcd.print("Press finger #3");
      while(fps.IsPressFinger() == false) delay(100);
      fps.CaptureFinger(true);
      id = fps.Identify1_N();
      if(id < dita_registrate)
      {
        sequenza[2]=id;
        lcd.clear();
        lcd.print("Remove finger");
        while(fps.IsPressFinger() == true) delay(100);
        lcd.clear();
        lcd.print("Press finger #4");
        while(fps.IsPressFinger() == false) delay(100);
        fps.CaptureFinger(true);
        int id = fps.Identify1_N();
        if(id < dita_registrate)
        {
          sequenza[3]=id;
          while(nome_seq()==1) delay(100);
          delay(1000);
          while(is_root()==1) delay(100);
          lcd.clear();
          lcd.print("Sequence added!!");
          seq[sequenze].seq[0]=sequenza[0];
          seq[sequenze].seq[1]=sequenza[1];
          seq[sequenze].seq[2]=sequenza[2];
          seq[sequenze].seq[3]=sequenza[3];
          seq[sequenze].root=seqroot;
          tot_root+=seqroot;
          strcpy(seq[sequenze].nome,nome_sequenza);
          for(j=0;j<4;j++)
          {
            EEPROM.write(2+sequenze*14+j,seq[sequenze].seq[j]);
          }
          EEPROM.write(2+sequenze*14+4,seq[sequenze].root);
          for(j=0;j<9;j++)
          {
            EEPROM.write(2+sequenze*14+j+5,seq[sequenze].nome[j]);
          }
          sequenze+=1;
          EEPROM.write(1,sequenze);
        }
        else
        {
          lcd.clear();
          lcd.print("Error finger 4");
          delay(2000);
        }
      }
      else
      {
        lcd.clear();
        lcd.print("Error finger 3");
        delay(2000);
      }
    }
    else
    {
      lcd.clear();
      lcd.print("Error finger 2");
      delay(1000);
    }
  }
  else
  {
    lcd.clear();
    lcd.print("Error finger 1");
    delay(2000);
  }
}

void open_lock()
{
  if (serratura_aperta == false)
  {
    serratura_aperta=true;
    digitalWrite(led,HIGH);
  }
}

void close_lock()
{
  if(serratura_aperta)
  {
    serratura_aperta = false;
    digitalWrite(led,LOW);
  }
}

void mostra_menu()
{
  int timeout=0;
  byte stato_menu=0;
  byte ristampa = 1;
  while (timeout < 5000)
  {
    int pulsante;
    if (ristampa==1)
    {
      switch(stato_menu)
      {
        case 0:
          lcd.clear();
          lcd.print("Add finger   <--");
          lcd.setCursor(0,1);
          lcd.print("Add sequence");
          break;
        case 1:
          lcd.clear();
          lcd.print("Add finger");
          lcd.setCursor(0,1);
          lcd.print("Add sequence  <--");
          break;
        case 2:
          lcd.clear();
          lcd.print("Add sequence");
          lcd.setCursor(0,1);
          lcd.print("Del sequence  <--");
          break;
        case 3:
          lcd.clear();
          lcd.print("Del sequence");
          lcd.setCursor(0,1);
          lcd.print("Lock/unlock   <--");
          break;
      }
    }
    ristampa=0;
    pulsante=analogRead(0);
    if ((pulsante>190) && (pulsante<220))
    {
      ristampa=1;
      stato_menu-=1;
      if (stato_menu<0) stato_menu = 3;
      timeout=0;
      delay(300);
    }
    else if ((pulsante>390) && (pulsante<430))
    {
      ristampa=1;
      stato_menu+=1;
      if (stato_menu>3) stato_menu = 0;
      timeout=0;
      delay(300);
    }
    else if ((pulsante>800) && (pulsante<840))
    {
      if (stato_menu==0)
      {
        fps.SetLED(true);
        lcd.clear();
        lcd.print("Record new finger");
        delay(2000);
        int ritorno = Enroll(dita_registrate+1);
        if (ritorno==0)
        {
          ristampa=1;
          lcd.clear();
          lcd.print("Finger added!!");
          dita_registrate+=1;
          EEPROM.write(0,dita_registrate); 
          delay(2000);
        }
        fps.SetLED(false);
      }
      if (stato_menu==1)
      {
        fps.SetLED(true);
        ristampa=1;
        add_sequence();
        fps.SetLED(false);
      }
      if(stato_menu==2)
      {
        fps.SetLED(false);
        del_seq();
        ristampa=1;
      }
      if (stato_menu==3)
      {
        lock_unlock();
      }
    }
    else if (pulsante>1000)
    {
      timeout +=200;
      delay(200);
    }
  }
  digitalWrite(10,LOW);
}

void apre_chiude()
{
  double delta;
  
  intervallo2=millis();
  delta = intervallo2 - intervallo;
  if (delta>500 && delta<1000)
  {
    EEPROM.write(0,0);
    EEPROM.write(1,0);
    Reset_AVR();
  }  
  else intervallo=intervallo2;
  lock_unlock();
}

byte put_finger()
{
  int timeout = 0;
  while(fps.IsPressFinger() == false)
  {
    delay(100);
    timeout+=100;
    if (timeout > 3000)
    {
      fps.SetLED(false);
      digitalWrite(10,LOW);
      return 1;
    }
  }
  return 0;
}

byte remove_finger()
{
  int timeout = 0;
  while(fps.IsPressFinger() == true)
  {
    delay(100);
    timeout+=100;
    if (timeout > 3000)
    {
      fps.SetLED(false);
      digitalWrite(10,LOW);
      return 1;
    }
  }
  return 0;
}

byte nome_seq()
{
  byte cursore = 0;
  byte uscita=0;
  byte aggiorna=1;
  char tmp_name[9]="a";
  int pulsante2;
  
  while (uscita==0)
  {
    if (aggiorna>0)
    {
      aggiorna=0;
      lcd.clear();
      lcd.print("Seq Name");
      lcd.setCursor(0,1);
      lcd.print(tmp_name);
      lcd.setCursor(8,1);
      lcd.print("********");
    }
    pulsante2=analogRead(0);
    if (pulsante2<180)
    {
      aggiorna=1;
      if (cursore < 8) cursore ++;
      tmp_name[cursore]='a';
      tmp_name[cursore+1]='';
    }
    if(pulsante2 > 600 && pulsante2 < 650)
    {
      aggiorna=1;
      if (cursore > 0) cursore--;
      tmp_name[cursore+1]='';
    }
    if (pulsante2>180&&pulsante2<230)
    {
      aggiorna=1;
      tmp_name[cursore]--;
      if (tmp_name[cursore]<'a') tmp_name[cursore]='z';
    }
    if (pulsante2>385&&pulsante2<435)
    {
      aggiorna=1;
      tmp_name[cursore]++;
      if (tmp_name[cursore]>'z') tmp_name[cursore]='a';
    }
    if (pulsante2>795&&pulsante2 <845)
    {
      while(analogRead(0)<1000) delay(100);
      aggiorna=1;
      lcd.clear();
      lcd.print("select = OK");
      lcd.setCursor(0,1);
      lcd.print("other = BACK");
      while(analogRead(0)>1000) delay(5);
      pulsante2=analogRead(0);
      if (pulsante2>795&&pulsante2<825)
      {
        uscita = 1;
        strcpy(nome_sequenza,tmp_name);
      }
      else aggiorna=1;
    }
    delay(200);     
  }
  return 0;
}

byte is_root()
{
  int pulsante;
  
  while (analogRead(0)<1000) delay(10);
  lcd.clear();
  lcd.print("Root Seq?");
  lcd.setCursor(0,1);
  lcd.print("Select to conf.");
  while (analogRead(0)>1000) delay(10);
  pulsante=analogRead(0);
  if (pulsante>795&&pulsante<825)
  {
    seqroot=1;
  }
  else seqroot=0;
  delay(1000);
  return 0;
}

void del_seq()
{
  int aggiorna=1;
  int stato = 0;
  int exit=0;
  int pulsante;
  int i,j,k;
  
  while (analogRead(0)<1000) delay(10);
  strcpy(seq[sequenze].nome,"Cancel");
  while (exit==0)
  {
    if(aggiorna==1)
    {
      aggiorna=0;
      if (sequenze==0) return;
      if (stato==0)
      {
        lcd.clear();
        lcd.print(seq[stato].nome);
        lcd.print("  <--");
        lcd.setCursor(0,1);
        lcd.print(seq[stato+1].nome);
      }
      else
      {
        lcd.clear();
        lcd.print(seq[stato-1].nome);
        lcd.setCursor(0,1);
        lcd.print(seq[stato].nome);
        lcd.print("  <--");          
      }
    }
    pulsante=analogRead(0);
    if ((pulsante>190) && (pulsante<220))
    {
      aggiorna=1;
      stato--;
      if (stato<0) stato = sequenze;
     delay(300);
    }
    else if ((pulsante>390) && (pulsante<430))
    {
      aggiorna=1;
      stato++;
      if (stato>sequenze) stato = 0;
      delay(300);
    }
    else if ((pulsante>790) && (pulsante<850))
    {
      if (stato==sequenze)
      {
        delay(1000);
        return;
      }
      else
      {
        lcd.clear();
        lcd.print("Delete ");
        lcd.print(seq[stato].nome);
        lcd.setCursor(0,1);
        lcd.print("Press select");
        while(analogRead(0)<1000) delay (10);
        while(analogRead(0)>1000) delay (10);
        pulsante=analogRead(0);
        if ((pulsante>790) && (pulsante<850))
        {
          if (seq[stato].root==1) tot_root--;
          if (tot_root==0)
          {
            tot_root ++;
            lcd.clear();
            lcd.print("ERROR: last root");
            delay(2000);
            return;
          }
          for (i = stato; i< (sequenze -1);i++)
          {
            seq[i].root=seq[i+1].root;
            EEPROM.write(2+i*14+4,seq[i].root);
            for (j=0;j<4;j++) 
            {
              seq[i].seq[j]=seq[i+i].seq[j];
              EEPROM.write(2+i*14+j,seq[i].seq[j]);
            }
            strcpy(seq[i].nome,seq[i+1].nome);
            for(k=0;k<9;j++)
            {
              EEPROM.write(2+i*14+k+5,seq[i].nome[k]);
            }
            sequenze --;
            EEPROM.write(1,sequenze);
          }
        }
      }
    }
  }
}

void scade()
{
  scadenza = true;
}

void cambia_sequenza (byte indice)
{
  byte sqz[4];
  byte id;
  byte j;
  int pulsante;
  
  lcd.clear();
  lcd.print("Seq expired");
  lcd.setCursor(0,1);
  lcd.print("Sel to change");
  while (pulsante=analogRead(0)<1000) delay(10);
  while (pulsante=analogRead(0)>1000) delay(10);
  pulsante=analogRead(0);
  if (pulsante<790||pulsante>850) return;
  fps.SetLED(true);
  lcd.clear();
  lcd.print("Press finger #1");
  while(fps.IsPressFinger() == false) delay(100);
  fps.CaptureFinger(true);
  id = fps.Identify1_N();
  if(id < dita_registrate)
  {
    sqz[0]=id;
    lcd.clear();
    lcd.print("Remove finger");
    while(fps.IsPressFinger() == true) delay(100);
    lcd.clear();
    lcd.print("Press finger #2");
    while(fps.IsPressFinger() == false) delay(100);
    fps.CaptureFinger(true);
    id = fps.Identify1_N();
    if(id < dita_registrate)
    {
      sqz[1]=id;
      lcd.clear();
      lcd.print("Remove finger");
      while(fps.IsPressFinger() == true) delay(100);
      lcd.clear();
      lcd.print("Press finger #3");
      while(fps.IsPressFinger() == false) delay(100);
      fps.CaptureFinger(true);
      id = fps.Identify1_N();
      if(id < dita_registrate)
      {
        sqz[2]=id;
        lcd.clear();
        lcd.print("Remove finger");
        while(fps.IsPressFinger() == true) delay(100);
        lcd.clear();
        lcd.print("Press finger #4");
        while(fps.IsPressFinger() == false) delay(100);
        fps.CaptureFinger(true);
        int id = fps.Identify1_N();
        if(id < dita_registrate)
        {
          sqz[3]=id;
          lcd.clear();
          lcd.print("Sequence added!!");
          seq[indice].seq[0]=sqz[0];
          seq[indice].seq[1]=sqz[1];
          seq[indice].seq[2]=sqz[2];
          seq[indice].seq[3]=sqz[3];
          for(j=0;j<4;j++)
          {
            EEPROM.write(2+indice*14+j,seq[indice].seq[j]);
          }
        }
        else
        {
          lcd.clear();
          lcd.print("Error finger 4");
          delay(2000);
        }
      }
      else
      {
        lcd.clear();
        lcd.print("Error finger 3");
        delay(2000);
      }
    }
    else
    {
      lcd.clear();
      lcd.print("Error finger 2");
      delay(1000);
    }
  }
  else
  {
    lcd.clear();
    lcd.print("Error finger 1");
    delay(2000);
  }
  fps.SetLED(false);
}

void lock_unlock()
{

  if (serratura_aperta)
  {
    close_lock();
    serratura_aperta = false;
  }
  else
  {
    open_lock();
    serratura_aperta=true;
  }
}

Analizziamo le differenze con la precedente versione:

righe 10-14. Introduce una struttura per valorizzare i dati delle sequenze: sequenza, tipo e nome.

Riga 17: definisce un array di strutture definite alle righe 10-14 per memorizzare i dati delle sequenze.

Righe 41-55: cambia il modo di leggere i dati relativi alle sequenze dalle eeprom di arduino come illustrato all’inizio.

Riga 61: lega il secondo interrupt al pin 3 sul quale è collegato il pulsante che fa “scadere” le sequenze.

Righe 131 e 143: se la sequenza appena immessa è scaduta, prima di passare al menu, chiede che venga cambiata.

Righe 247-252: nuova voce di menu per cancellare una sequenza.

Riga 537: richiama la funzione che valorizza il nome della sequenza

Riga 539: Richiama la funzione che valorizza il tipo di sequenza

Riga 547: se la sequenza immessa è di tipo root incrementa il numero totale di sequenze root.

Righe 549-560: salvano su Eeprom i dati della nuova sequenza, incrementano il numero di sequenze registrate e lo scrivono sulla eeprom.

Righe 632-637: nuova voce di menu per cancellare una sequenza

Righe 761-827: Funzione per associare un nome ad una sequenza. La logica è la seguente:

Sul display viene mostrato un messaggio:

riga 1: “SEQ NAME”

riga 2:”<tmp_name> ********” . tmp_name contiene il nome temporaneo della sequenza.

Ogni volta che cambia qualcosa nel nome (aggiorna->1) il messaggio viene aggiornato col nuovo contenuto temporaneo del nome.

Se viene premuto il tasto down del display l’ultima lettera di tmp_name (la cui posizione è indicata dalla variabile cursore) cambia incrementando: aà b à c ecc. Se si preme down quando l’ultima lettera di tmp_name è la ‘z’ il valore viene reimpostato ad ‘a’ (righe 801-806)

Se viene premuto il tasto up il comportamento è analogo ma la lettera viene decrementata: dàcàb ecc. (righe 795-800).

Se viene premuto il tasto dx viene aggiunto un carattere (‘a’ di partenza) a tmp_name. Per farlo la variabile cursore viene incrementata (se minore di 8). In posizione cursore si aggiunge una ‘a’ ed in posizione cursore+1 si aggiunge un ‘’ (carattere di terminazione della stringa(righe 782-788).

Se viene premuto il tasto sx viene eliminato un carattere (se cursore > 0) semplicemente decrementando il valore di cursore e valorizzando il carattere alla posizione cursore con ‘’.

Righe 829-847: definisce se la sequenza è root o standard.

Alla riga 833 attende che venga rilasciato il pulsante premuto precedentemente poi, se viene premuto il tasto select (righe 840-843) la sequenza è root, se viene premuto un altro pulsante qualsiasi, la sequenza è standard.

Righe 849-946: funzione per la cancellazione di una sequenza.

Crea un menu sul display lcd in cui ogni riga è una sequenza precedentemente immessa.

L’ultima voce è “Cancel” che permette di uscire senza cancellare alcuna sequenza (alla riga 858 inserisco la voce “Cancel” dopo il nome dell’ultima sequenza).

La pressione dei tasti up e down (righe 883-896) aggiorna la lista sul display.

La pressione del tasto select fa partire la procedura di cancellazione. Se sei sull’ultima voce (“Cancel”) ritorna senza far nulla (righe 899-903).

Ti chiede poi una conferma e, se non stai cercando di cancellare l’ultima sequenza root presente, prosegue (righe 914-924).

La cancellazione comporta semplicemente un decremento del numero totale di sequenze: uno scorrimento di uno verso l’alto (nell’array delle sequenze) di tutte le sequenze successive a quella da cancellare, ed una scrittura dei dati aggiornati nelle eeprom (righe 925-941).

Righe 953-1049: funzione che chiede di far modificare una sequenza scaduta.

In questa versione semplificata tutte le sequenze scadono contemporaneamente alla pressione del secondo pulsante perché è stata utilizzata una variabile globale chiamata ‘scadenza’.

Come prima cosa chiede di confermare la volontà di cambiare sequenza. La pressione di un qualsiasi tasto diverso da select rimanda il cambiamento al prossimo inserimento di quella sequenza (riga 967).

Se si preme select chiede di immettere una nuova sequenza che sostituirà la precedente (righe 969-1009).

Se tutto procede senza errori sostituisce i dati della vecchia sequenza con i nuovi e salva nelle eeprom (righe 1010-1019).

Il video dimostrativo del Fingerprint Scanner TTL GT-511C3

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: https://www.mauroalfieri.it/elettronica/sistema-accesso-fingerprint-scanner-ttl-gt-511c3-quarta-parte.html

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.