millis() causes entire program to restart

Hey everyone,

I am developing a payment system using RFID cards, and I want to use multiple RFID-RC522 readers at once so that they can read cards (almost) simultaneously.

To do this, I used the millis() function, but for some reason, it causes my whole program to stop and restart. The rest of the code works, so I don’t know what I am doing wrong.

Below you can see a snippet of the code (the millis() function is right at the bottom).

Thank you in advance :).

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <SPI.h>
#include <MFRC522.h>
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
};
float nums[5] ={};
byte rowPins[ROWS] = {8, 7, 6, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {4, 3, A0, A1}; //connect to the column pinouts of the keypad
int decimal =0;
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); 
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13; 
#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above
float price = 0;
char MoneyLeft = 10;
MFRC522 mfrc522(SS_PIN, RST_PIN); 
String value = "A9 A4 DE 8B";// Create MFRC522 instance
float cost = 0;
int c = 0;
boolean add =false;
int buzzPin = 2;
int buzztime = 500;
int t= 0;
float nrofElements;
float addition = 0;
const int buzzer =2;
boolean entered[6] = {};
String thirdscan;
String lastscan;
String currentScan="";
bool lunchTime=false;
int repeat =1;
bool newItem;
int firstid=0;
int actualfirstid;
int secondid=0;
int thirdid=0;
bool newline=false;
int indexForLastNum;
int totalItems;
unsigned long previousTime;
unsigned long currentTime;

String serialnumbers[] = {"A9 A4 DE 8B", "0A FA 82 16"}; //accounts
String names[] = {"Alex", "Marta"};
float account[] = {10, 20};
bool schoolLunch[] = {true, false};

int snackCount[]= {0,0,0,0,0,0,0,0,0,0,0,0};
String snackName[]= {"Coffee", "Croissant", "A. Juice", "Cookie", "Brezel", "Cherry Pastry", "Pingui", "Water", "C. Croissant", "Laugen", "Cheese Brzl", "Panini"};
float snackPrice[]={1.50, 1.30, 1.70, 1.5, 0.7, 1.6, 0.8, 1.2, 1.70,0.8,1.4,2.4,};
bool foodType[]= {false, true, false, true, true};
int drinkCount=0;
int foodCount=0;

void setup() {
 Serial.begin(9600);   // Initialize serial communications with the PC
  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();   
 lcd.init();
  lcd.backlight();// Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
  mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
  Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));

 pinMode(buzzer, OUTPUT);

}

void loop() {
  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
lcd.setCursor(0,0);


  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;

  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();


  content.toUpperCase();
  for (c = 0; c <= 1; c++){
       if (content.substring(1) == serialnumbers[c]) //change here the UID of the card/cards that you want to give access
  {
      tone(buzzer, 1600);
        delay(100);// ...for 0.1 sec
        noTone(buzzer);
        lcd.clear();
      if (lunchTime){
        Lunch(c, content.substring(1), thirdscan);
        
      }
      else{
        Snack(content.substring(1), c, lastscan);
      }
  }
  }
  
  lastscan = content.substring(1);
  currentScan ="";
}


void Lunch(int i, String currentScan, String beforelastScan){
  lcd.clear();
  lcd.setCursor(0,0);
  currentTime=millis();
  if (currentTime-previousTime >= 1500){
  if (currentScan=="A9 A4 DE 8B"){
    lcd.print("Snack Time");
    lunchTime=false;
  
    
  }
  else{
  if (schoolLunch[i] == false){
    lcd.print("Home lunch");
    
  }
  else{
    lcd.print("School lunch :)");
    
  }
  }
  previousTime=currentTime;
}
}

I can't see anything that might cause the program to restart because you are using millis(). The more likely culprit is your use of the String class.

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

What Arduino are you using?

...R

how did you get it to compile without defining "Snack"?

Which "Arduino" are you using?
Anything ESP8266-based (or ESP32) can result resetting when using millis() without yield().

gcjr:
how did you get it to compile without defining "Snack"?

The code I shared is just a snippet of the entire code. I defined Snack() further down.

runaway_pancake:
Which "Arduino" are you using?
Anything ESP8266-based (or ESP32) can result resetting when using millis() without yield().

I'm just using the Arduino Uno.

Thank you for your answers :)))

alexoort:
The code I shared is just a snippet of the entire code

Then perhaps you should post the entire code?

Or visit https://snippets-r-us.com

Grumpy_Mike:
Or visit https://snippets-r-us.com

hahaha. Sorry for not uploading the code, it’s just that it’s pretty long…

Payment_system.ino (9.85 KB)

Immediately obvious errors from the compiler:

/home/test/Downloads/Payment_system/Payment_system.ino: In function 'Snack(String, int, String)':
/home/test/Downloads/Payment_system/Payment_system.ino:220:32: warning: iteration 1 invokes undefined behavior [-Waggressive-loop-optimizations]
               thirdid += nums[x];
                          ~~~~~~^
/home/test/Downloads/Payment_system/Payment_system.ino:219:31: note: within this loop
             for (int x = 4; x <= 5; x++) {
                             ~~^~~~
/home/test/Downloads/Payment_system/Payment_system.ino:392:13: warning: iteration 5 invokes undefined behavior [-Waggressive-loop-optimizations]
     nums[x] = 0;
     ~~~~~~~~^~~
/home/test/Downloads/Payment_system/Payment_system.ino:391:21: note: within this loop
   for (int x = 0; x <= 5; x++) {
                   ~~^~~~

You are going out of bounds here…

      for (int x=4;x<=5;x++){
    thirdid += nums[x];
    }

since nums is delcared as an array with 5 elements (0…4).

There are a lot of examples throughout your code where you are iterating from 1 to … N when you should probably be starting from 0.

Your keypad input input should be cleaned up. I would suggest using single char constants rather than integers (e.g.)

key = keypad.getkey();
if ( key >= '0' and key <= '9' ) {
  // it is numeric
  //...

I would also suggest that you store all the values in a char array until the user presses enter and then do the conversion to a numeric value [atof()]. It will simplify your code.