Running seperate loops for Serial vs Stand Alone

I am using the Arduino Fingerprint Scanner Library's "Enroll" template to gather fingerprints for a simple Biometric Alarm system. I have written my own loop for the alarm itself (simple Neopixel and buzzer). How can I write them together so that the "Enroll" loop only activate when the Serial is plugged in, and the alarm loop is initiated when the Arduino is stand alone?

This is my first Arduino project but I do have a bit of JAVA programming experience. This is for a college final that is due Monday 12/18/17 so any help will be greatly appreciated.

I'm sure the solution is simple I am just not familiar with the Syntax.

How can we possibly comment on code that we cannot see? Please read the How to use this forum and post your code as described in topic #7.

Because you do not need to see the code. That is why I did not post it. If you are not smart enough to figure out what I am asking then it is not your help that I need.

Simpler question: What is the "Command" to instruct a loop to run only if the Serial is connected but remain dormant otherwise.

nmurray1227:
Simpler question: What is the "Command" to instruct a loop to run only if the Serial is connected but remain dormant otherwise.

It is not a simpler question because the answer depends on knowing how you have structured your program.

If you want help, post your program and don't put yourself on a pedestal above the rest of us.

In the meantime, maybe have a look at Planning and Implementing a Program

...R

I’m not putting myself on a pedestal above anybody. I am simply frustrated with this project and am looking for an easy answer. I apologize if I came off as a jackass. I have many other programming projects that I am working on and this one is taking up valuable time. Below is a pastebin to a version of the code. This one is receiving this compile error…

exit status 1
‘getFingerprintEnroll’ was not declared in this scope

I have combined many versions already, all with their own unique issues that I have been working out.

I also need to know how to get the alarm to shut down and re-arm after checking for, and finding, a fingerprint match that has been previously stored when the Serial was available.

The best way of getting a forum such as this to debug your program is to trim the program down to the minimum size which compiles AND still shows the problem. Usually that shows you where the problem is and then you don't even need to post the code.

No, I'm not clicking on the wastebin link because

  1. You didn't make it a clickable link
  2. It's probably thousands of lines of code
  3. You trimmed too much out of the error message so we can't even see what line it was errored on
  4. I probably don't have the libraries you have (and didn't link to) so I couldn't compile it anyway to get the same error.

I apologize about the link. The Error message was a simple mistake. I had and extra bracket brought in from a paste. I do however still get this error message…

c:\program files (x86)\arduino\hardware\tools\avr\bin…/lib/gcc/avr/4.9.2/…/…/…/…/avr/bin/ar.exe: unable to rename ‘core\core.a’; reason: File exists

exit status 1
Error compiling for board Arduino/Genuino Uno.[/i]

The code is 280 lines of code so far. I am reading the thread that “Robin” has written and suggested and have found that adding to an existing template is not the way to go. I have set myself up for failure. I have posted another link that is clickable. If you can find a fix that would be appreciated, otherwise I am going to continue to read this thread and try to produce a miracle by Monday.

the libraries are:

#include <Adafruit_Fingerprint.h>
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>

This is the code from PasteBin - I am in an unusually generous mood. It would have been easier for the OP to paste the code here than in PasteBin

…R

#include <Adafruit_NeoPixel.h>
#define NUMPIXELS      8
#define PIN            6
Adafruit_NeoPixel Neo = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#include <Adafruit_Fingerprint.h>

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

uint8_t id;

void setup()  
{
  Serial.begin(9600);
  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  delay(100);
  Serial.println("\n\nAdafruit Fingerprint sensor enrollment");

  // set the data rate for the sensor serial port
  finger.begin(57600);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  Neo.begin();
  pinMode(10, OUTPUT);
  pinMode(7, INPUT);
  
}

uint8_t readnumber(void) {
  uint8_t num = 0;
  
  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}

boolean alarmArmed = true;
void loop()                     
//Begin Alarm Loop
{
 while (alarmArmed == true) {
    Neo.show();
    if (digitalRead(7) > 0) {
      alarmArmed = false;
    }
  }//End Alarm OFF

  //Begin Alarm ON
  while (alarmArmed == false) {
    digitalWrite(10, HIGH);
    Neo.setPixelColor(0, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(2, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(4, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(6, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(1, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(3, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(5, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(7, 0, 0, 255);
    Neo.show();
    delay(100);
    digitalWrite(10, LOW);
    Neo.setPixelColor(0, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(2, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(4, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(6, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(1, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(3, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(5, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(7, 0, 255, 0);
    Neo.show();
    delay(100);
    
  Serial.println("Ready to enroll a fingerprint!");
  Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");
  id = readnumber();
  if (id == 0) {// ID #0 not allowed, try again!
     return;
  }
  Serial.print("Enrolling ID #");
  Serial.println(id);
  
  while (!  getFingerprintEnroll() );
}

uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println(".");
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      break;
    default:
      Serial.println("Unknown error");
      break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  
  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  Serial.println("Place same finger again");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.print(".");
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      break;
    default:
      Serial.println("Unknown error");
      break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  
  // OK converted!
  Serial.print("Creating model for #");  Serial.println(id);
  
  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }   
  
  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }   
}

@nmurray1227, if you want a responsive program you need to stop using WHILE because it blocks until it completes.

It will also make it much easier to develop and debug if you break your program into short single purpose functions that each only take a brief time to complete and return to loop()

Have you studied the link I gave you in Reply #3 ?

...R

Ill try to remember all of this “etiquette” as I am new here and am actually enjoying the process of programming a micro processor (despite these issues). I have posted a different link to another version which is the one I will stick with and try to tweak. here it is:

#include <Adafruit_NeoPixel.h>

#include <Adafruit_Fingerprint.h>

/***************************************************
  This is an example sketch for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit BMP085 Breakout
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/



#define NUMPIXELS      8
#define PIN            6
Adafruit_NeoPixel Neo = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

uint8_t id;

void setup()    //********************************************************************************************************************************************SETUP
{
  Serial.begin(9600);
  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  delay(100);
  Serial.println("\n\nAdafruit Fingerprint sensor enrollment");

  // set the data rate for the sensor serial port
  finger.begin(57600);

  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) {
      delay(1);
    }
  }
  Neo.begin();
  pinMode(10, OUTPUT);
  pinMode(7, INPUT);



}


uint8_t readnumber(void) {
  uint8_t num = 0;

  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}

boolean alarmArmed = true;
void loop()     // *****************************************************************************************************************************************MAIN LOOP
{
  Serial.println("Ready to enroll a fingerprint!");
  Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");
  id = readnumber();
  if (id == 0) {// ID #0 not allowed, try again!
     return;
  }
  Serial.print("Enrolling ID #");
  Serial.println(id);
  
  while (!  getFingerprintEnroll() );



  //*************************Alarm Codes Follows**********************
  //Begin Alarm OFF
  while (alarmArmed == true) {
    Neo.show();
    if (digitalRead(7) > 0) {
      alarmArmed = false;
    }
  }//End Alarm OFF

  //Begin Alarm ON
  while (alarmArmed == false) {
    digitalWrite(10, HIGH);
    Neo.setPixelColor(0, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(2, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(4, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(6, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(1, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(3, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(5, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(7, 0, 0, 255);
    Neo.show();
    delay(100);
    digitalWrite(10, LOW);
    Neo.setPixelColor(0, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(2, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(4, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(6, 0, 0, 255);
    Neo.show();
    Neo.setPixelColor(1, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(3, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(5, 0, 255, 0);
    Neo.show();
    Neo.setPixelColor(7, 0, 255, 0);
    Neo.show();
    delay(100);

    }

  }



//*******************************************************************************Enroll Methods**************************************************

uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  Serial.println("Place same finger again");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.print(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK converted!
  Serial.print("Creating model for #");  Serial.println(id);

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }
}

@Robin2 I am working my way through the thread now.

I am unsure of how I am going to complete this project without using the template as my skill level is definitely to low to re-write the fingerprint enrollment code. I do have plans on learning and eventually mastering this these projects but as of right now I am running out of time.

Well, to start with "only when serial is plugged in" is actually impossible on most Arduinos. There is no difference between "unplugged" and "nobody is sending anything right now".

Perhaps just a timeout, so if it hasn't received any serial inputs in the first 30 seconds, then it exits the enrollment phase. Maybe something like this:

const unsigned long MAX_ENROL_TIME = 30000; //millliseconds - time to wait to do enrollment during startup
unsigned long lastSerialCharSeen = 0;  //time in millis() that we last got a serial input
boolean enrollment = true;  //we start in enrollment mode
void loop() {
  int c = -1; //-1 means no character read
  if(Serial.available()) {
    lastSerialCharSeen = millis();
    c = Serial.read();
  }

  if(enrollment && millis() - lastSerialCharSeen > MAX_ENROL_TIME) {
    enrollment = false;
    Serial.println("Enrollment finished - starting alarm mode");
  }
  
  if(enrollment) {
    doEnrollmentStuff(c);
  } else {
    doAlarmStuff();
  }
}

I am currently re-writing and re-structuring the code as I go through @Robin2’s thread.

As a side note to this issue, I am getting the below error message. This keeps happening to me with different sketches. Some, I am sure, have no compiler errors. I have fixed a few buy uninstalling(deleting all associated files) the fingerprint library(which doesn’t turn orange in the IDE like the other libraries) and reinstalling it. Very inconvenient. Why does this keep happening?

c:/program files (x86)/arduino/hardware/tools/avr/bin/…/lib/gcc/avr/4.9.2/…/…/…/…/avr/lib/avr5/crtatmega328p.o:(.init9+0x0): undefined reference to `main’

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino/Genuino Uno.

Here what I have just started writing if it helps:

#include <Adafruit_NeoPixel.h>
#define PIXEL_COUNT 8
#define PIN  6
Adafruit_NeoPixel Neo = Adafruit_NeoPixel(PIXEL_COUNT, PIN, NEO_GRB + NEO_KHZ800);


void setup() {
  // put your setup code here, to run once:
  Neo.begin();
  pinMode(10, OUTPUT);
  pinMode(7, INPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

}

void enrollFingerprints() {

}

void alarmArmed() {
  Neo.show();
  digitalWrite(10, LOW);
}

void alarmTriggered() {
  digitalWrite(10, HIGH);
  Neo.setPixelColor(0, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(2, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(4, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(6, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(1, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(3, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(5, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(7, 0, 0, 255);
  Neo.show();
  delay(100);
  digitalWrite(10, LOW);
  Neo.setPixelColor(0, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(2, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(4, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(6, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(1, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(3, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(5, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(7, 0, 255, 0);
  Neo.show();
  delay(100);
}

void checkValidFingerprint() {

}

That is a rather odd set of error messages you're getting. I'm sure there's some simple solutions if you plug those into Google. It may be an incorrect or corrupted Arduino installation.

The orangeness of keywords from libraries is kind of hit-or-miss. Not all library writers include the keywords file. It also highlights keywords from any library installed, not just the ones you are using.

Ok everybody. Here is an update. I have been working on the code and I think I am almost there. I have all of the parts written, it is compiling, and it is uploading fine but it isn’t quite doing what I want it to do yet. The goal is to allow the serial to enter multiple ID’s if necessary (only allowing 1 before entering into alarm mode) but times out and enters alarm mode when Serial remains inactive for a preset amount of time. Then while alarm is armed, it waits until it receives a “1” from an inferred sensor(digitalPin7). The alarm is then triggered and sounds(buzzer = digitalPin10) while waiting for a valid(preset) fingerprint to be scanned. When the fingerprint is verified the alarm resets and awaits another trigger. Where is my newbie showing?

#include <Adafruit_NeoPixel.h>
#define PIXEL_COUNT 8
#define PIN  6
Adafruit_NeoPixel Neo = Adafruit_NeoPixel(PIXEL_COUNT, PIN, NEO_GRB + NEO_KHZ800);

#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

uint8_t id;

void setup() {
  Serial.begin(9600);

  finger.begin(57600);

  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) {
      delay(1);
    }
  }


  Neo.begin();
  pinMode(10, OUTPUT);
  pinMode(7, INPUT);

}

uint8_t readnumber(void) {
  uint8_t num = 0;

  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}

const unsigned long MAX_ENROL_TIME = 5000; //millliseconds - time to wait to do enrollment during startup
unsigned long lastSerialCharSeen = 0;  //time in millis() that we last got a serial input
boolean enrollment = true;  //we start in enrollment mode
boolean alarmReady = true;
void loop() {
  int c = -1; //-1 means no character read
  if (Serial.available()) {
    lastSerialCharSeen = millis();
    c = Serial.read();
  }

  if (enrollment && millis() - lastSerialCharSeen > MAX_ENROL_TIME) {
    enrollment = false;
    Serial.println("Enrollment finished - starting alarm mode");
  }

  if (enrollment) {
    enrollFingerprints();
  } else {
    if (alarmReady == true) {
      alarmArmed();
      if  (digitalRead(7) > 0) {
        alarmReady = false;
      }
    }
    if (alarmReady == false) {
      alarmTriggered();
    }
  }
}

void enrollFingerprints() {
  Serial.println("Ready to enroll a fingerprint!");
  Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");
  id = readnumber();
  if (id == 0) {// ID #0 not allowed, try again!
    return;
  }
  Serial.print("Enrolling ID #");
  Serial.println(id);

  while (!  getFingerprintEnroll() );
}

void alarmArmed() {
  Neo.show();
  digitalWrite(10, LOW);
}

void alarmTriggered() {
  digitalWrite(10, HIGH);
  Neo.setPixelColor(0, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(2, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(4, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(6, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(1, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(3, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(5, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(7, 0, 0, 255);
  Neo.show();
  delay(100);
  digitalWrite(10, LOW);
  Neo.setPixelColor(0, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(2, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(4, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(6, 0, 0, 255);
  Neo.show();
  Neo.setPixelColor(1, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(3, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(5, 0, 255, 0);
  Neo.show();
  Neo.setPixelColor(7, 0, 255, 0);
  Neo.show();
  delay(100);
  checkValidFingerprint();
}

void checkValidFingerprint() {
  int p = -1;
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    alarmReady = true;
  }
  else {
    while (p != FINGERPRINT_OK) {
      p = finger.fingerFastSearch();
      if (p == FINGERPRINT_OK) {
        alarmReady = true;
      }
    }
  }
}

uint8_t getFingerprintEnroll() {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  Serial.println("Place same finger again");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        break;
      case FINGERPRINT_NOFINGER:
        Serial.print(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        break;
      default:
        Serial.println("Unknown error");
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK converted!
  Serial.print("Creating model for #");  Serial.println(id);

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }
}

What do you expect this statement to do?

if (enrollment && millis() - lastSerialCharSeen > MAX_ENROL_TIME) {

It sure isn't calculating an elapsed time since the last serial character.

I don't know what it is supposed to do since I didn't write it. If you read the thread, you would see that someone else suggested it. I simply copied and tried it out. It looks like that is what it is trying to do.

It would be more helpful if you would maybe say how to make it do that instead of just being sarcastic and telling me what it doesn't do and leaving no help in your reply at all. Thanks :slight_smile:

@avr_fred Does this make more sense? I researched millis() a bit and tried to fix it...

Here are the relevant sections:

unsigned long enrollTimeout = 0;

if (Serial.available()) {
    enrollTimeout = millis();
    c = Serial.read();
  }

  if (enrollment && enrollTimeout > MAX_ENROL_TIME) {
    enrollment = false;
    Serial.println("Enrollment finished - starting alarm mode");
  }

I'm not sure where this fits into the bigger picture

  if (enrollment && millis() - lastSerialCharSeen > MAX_ENROL_TIME) {
    enrollment = false;
    Serial.println("Enrollment finished - starting alarm mode");
  }

It sets the variable enrollment to false but I don't see where in the program it is set back to true. Is it intended to be a one-time enrollment process? If so why not put it in setup() ?

It often makes logic easier to see if you avoid complex IF statements. Try, for example

if (enrollment == true) {
  if (millis() - lastSerialCharSeen > MAX_ENROL_TIME) {

...R

quote author=avr_fred link=msg=3526386 date=1513482432]
What do you expect this statement to do?

if (enrollment && millis() - lastSerialCharSeen > MAX_ENROL_TIME) {

It sure isn't calculating an elapsed time since the last serial character.

[/quote]
It is, so long as some other code (included in my original suggestion) updates the lastSerialCharSeen with the millis() each time it finds Serial.available() is true.

The original specification didn't say if it is possible or necessary to return to enrollment mode at any time. However, this version does allow you to set it back to true. Murray's version in post#17 doesn't - that's a one-time-only thing.

Murray, your post in #14 is a very clear description of what you want it to do. What does it actually do? What is it doing wrong?

I note that you've kept the original "blocking" enrollment function, with lots of delay()s. That can stay, but the readNumber() function which sits and waits for serial input, that also needs to update lastSerialcharSeen. Then you can delete the bit of code I put at the top of loop(), since you aren't using it. Note that the while(!Serial.available()) loop should also check if the timeout expires. I think that might be where you're getting stuck.