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

Cortesemente, prima di inserire i commenti leggi il regolamento

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

10 comments

Skip to comment form

    • Antonio on 22 dicembre 2014 at 19:20
    • Reply

    Ciao prima di tutto ti faccio i miei complimenti per il sito e per il tuo impegno nel condividere i tuoi progetti con noi.

    Sto effettuando questo progetto anche io con una piccola variazione invece del led ho messo un servo che muove una maniglia. Comunque ho un problema e volevo chiedere se mi potevi dare una mano, ho preso tutti i pezzi che hai preso anche tu per farlo il più simile possibile al tuo progetto, oggi mi è arrivato lo schermo con i pulsanti ma è leggermente diverso dal tuo di poco, e secondo me devo cambiare qualche collegamento. Ma vorrei una tua opinione lo schermo è questo non so se posso mettere il link, se non posso ti chiedo di toglierlo se possibile( http://www……com/it/shield/268-LCD-1602-Keypad-Shield-Fo.html ) non voglio fare pubblicità o altro è solo per farti vedere che schermo sto usando, comunque collego tutto come da tua immagine ma quando carico lo sketch lo schermo rimane blu senza far vedere scritte o altro, ho provato a vedere se lo schermo funziona e funziona bene e lo stesso vale per il sensore di impronte ma entrambi insieme non vanno. Mi puoi dire se ho sbagliato qualcosa, secondo me i collegamenti sbagliati sono il positivo e il negativo che alimentano i pulsanti e il led.

    Grazie e buon Natale 😀

    1. Ciao Antonio,
      il progetto non è mio, lo ha realizzato Michele che certamente vorrà risponderti di persona.
      Ho controllato il link e mi sembra che il tuo LCD sia una versione non più in commercio del prodotto che ha utilizzato Michele, una sorta di versione di test 0.1 o precedente ( non si vede )
      Ti consiglio di fare dei test e verificare i pin con cui controlli questa versione di display e che tipo di segnali arrivano dai pulsanti per adattare lo sketch di Michele al tuo progetto.
      Il link è stato annullato per non fare pubblicità al sito.

        • Antonio on 29 dicembre 2014 at 13:06
        • Reply

        Grazie mille, comunque per sicurezza ho preferito comprare lo stesso schermo che è riportato nel link 😀

        1. Ciao,
          ti ho risposto nella seconda parte.
          Michele

    • Emin ozuberk on 21 gennaio 2016 at 13:43
    • Reply

    Hi !
    I am from turkey and planning on a project that includes fingerprint gt-511c3 arduiono uno and android application.your works influanced me alot but i dont know how include the system hc-06 bluetooth module on software part.How can ı control and comınıcate both of them on arduino uno?

    would you support me about it?

    1. Hi Emin,
      you can read my post and combine the sketch.
      if you don’t understand some programs, you can mark in the comments your doubts.
      I ‘ll try to help you.

      • Emin ozuberk on 21 gennaio 2016 at 18:44
      • Reply

      Sir the program above does not invole bluetooth module..
      maybe I couldnt express my self perfectly..To understand each other more clear ı wıll send you a link which is almost perfect close to I want.My project will be a version of this.if you please examine the link below I am absolutely sure you will understand my idea.

      Student attendance tracking system
      https://www.youtube.com/watch?v=sAtcB1M4ifk

      1. Hi Emin,
        i don’t write sketch for you.
        I can only suggest you read my articles and understand how to write code, yourself.
        Otherwise, ask the author of videos to help .

    • Emin ozuberk on 23 gennaio 2016 at 09:19
    • Reply

    sir first of all thank you for the reply. Is there any article about bluetooth on your web site..Because if it is, I couldnt find it also there is a misunderstanding between you and me..I dont ask you to wraite a sketch for me..I just hope maybe you guide me and give me some exapmles about bluetooth skecth with other serial devices.

    1. Hi Emin,
      you can use a search function in the blog to find all posts on bluetooth.

Lascia un commento

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.