Serial monitor give wrong values in another sketch involving universal coin slot

Hello!

I’m kinda new to arduino. I’m making a project (vending machine) involving a coin slot and an arduino mega 2560.

I made a test sketch to try if my coin slot works. It seems to be working right with this:

const int coinPin = 21;
volatile int credits = -1;

void setup() {
  Serial.begin(9600);
  pinMode(coinPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(coinPin), coinInserted, RISING);
}

void loop(){            
  Serial.println(credits);
}

void coinInserted(){
  credits++;
}

But when I inserted this ^ code to the code of my actual project, the serial monitor now gives random numbers.

(I highlighted the codes that were from my test sketch)

String order_no;
int product_none;

void productFind() {
  if(order_no == "01" || order_no == "05" || order_no == "13"){
    product_none = 0;
  } else product_none = 1;
}

//------------------------------------------------------------------------------------------------

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const int coinPin = 21; //******************** THIS ONE

volatile int credits = -1; //******************** THIS ONE

const char cancelButton = '*',
  confirmButton = '#';

int digitCounterOrder = 8,
  error = 0,
  confirm = 0;
  
char  key;

const byte ROWS = 4,
  COLS = 4;

char keyDisplay[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

const byte rowPins[ROWS] = {5, 4, 3, 2},
  colPins[COLS] = {10, 8, 7, 6};

Keypad kPad = Keypad(makeKeymap(keyDisplay), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27, 16, 2);  

void setup(){
  lcd.init();
  lcd.backlight();
  
  Serial.begin(9600); 

  pinMode(coinPin, INPUT_PULLUP); //******************** THIS ONE
  attachInterrupt(digitalPinToInterrupt(coinPin), coinInserted, RISING); //******************** THIS ONE

}

void loop(){
  lcd.setCursor(0, 0);  
  lcd.print("Credits: ");
  lcd.print(credits);
  lcd.setCursor(0,1);
  lcd.print("Order: #");

  Serial.println(credits); //******************** THIS ONE
  
  key = kPad.getKey();

  if (key){

    if(key == cancelButton){
      reset();
    }

    if(key == confirmButton){
      productFind();
      errorFind();
      if(error == 0){
        confirmOrder();
      } else {
        error = 0;
      }
      reset();
    }
    
    if(digitCounterOrder == 10){
      retypeOrder();
    }
    
    lcd.setCursor(digitCounterOrder, 1);
    if(!(key == cancelButton || key == confirmButton)){
      lcd.print(key);
      order_no += key;
    }
    digitCounterOrder++;

  }
  
}

void coinInserted(){ //******************** LASTLY, THIS
  credits++; 
}

void reset(){
  digitCounterOrder = 7;
  lcd.setCursor(digitCounterOrder, 1);
  lcd.print("   ");
  order_no = "";
}

void retypeOrder(){
  digitCounterOrder = 8;
  lcd.setCursor(digitCounterOrder, 1);
  lcd.print("   ");
  order_no = "";
}

void errorFind(){
  if(order_no.length() == 1){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Please enter a");
    lcd.setCursor(0,1);
    lcd.print("two digit number");
    delay(3000);
    lcd.clear();
    error = 1;
  } else if(product_none == 1){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" There is no");
    lcd.setCursor(0,1);
    lcd.print("    product #");
    lcd.print(order_no);
    delay(3000);
    lcd.clear();
    error = 1;
  } else{
    confirm = 1;
  }
}

void confirmOrder(){
  lcd.clear();
  while(confirm == 1){
    lcd.setCursor(0,0);
    lcd.print("Are you sure you");
    lcd.setCursor(0,1);
    lcd.print("want to buy #");
    lcd.print(order_no);
    lcd.print("?");
    
    key = kPad.getKey();
    
    if(key == cancelButton){
      confirm = 0;
      lcd.clear();
    } else if(key == confirmButton){
      lcd.clear();
      confirm = 0;
      takeOrder();
    }
  }
  
}

void takeOrder(){
  // --------------- LOADING ---------------
  int d;
  for(int c = 0; c<=30; c++){
    if(c<=15) d=c;
    if(c>15) d=c-16;
    lcd.setCursor(d, 0);
    lcd.print(".");
    delay(100);
    if(c>5){
      lcd.setCursor(c - 6, 0);
      lcd.print(" ");
    }
    if(d>5){
      lcd.setCursor(d - 6, 0);
      lcd.print(" ");
    }
    lcd.setCursor(d, 1);
    lcd.print(".");
    delay(100);
    if(c>5){
      lcd.setCursor(c - 6, 1);
      lcd.print(" ");
    }
    if(d>5){
      lcd.setCursor(d - 6, 1);
      lcd.print(" ");
    }
  }
  // --------------- /LOADING ---------------
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" Thank you");
  lcd.setCursor(0,1);
  lcd.print("     Take care!");
  delay(5000);
  lcd.clear();
}

This ^ code gives the serial monitor these:

If you’d mind asking, this is my wiring:
Imgur

I already visited soooooo many links about this coin slot with arduino project, but they provide different codes and circuits. The test sketch I made, and this wiring, are the only things that made my coin slot work right for me (the serial monitor gives the right values/credits).

Any help will be very much appreciated! Thank you in advance!

The interrupt pin that I used is pin 21, because pin 2, 3, 18, 19, and 20, (other interrupt pins for mega 2560) doesn’t seem to work right. When I use those pins, the coinInserted function keeps on working (the credits keep on increasing) even though I am not inserting any coins yet.
I didn’t use any pulldown/pullup resistors, but my test sketch seems to work fine.
I think you shouldn’t mind that the credits variable starts at -1, because it gives me a value of 1 when I start it (though I have no idea why lol).

I’m very sorry if my code is irritating for you as it may seem unorganized(?). Thank you for your consideration.

When you have a multi-byte variable that is incremented in an ISR you need to briefly disable interrupts in loop() when you read the variable - otherwise there is a risk that part of the variable will be updated while the other part is being read. And it is best to take a copy of it and use the copy until the next time you read the variable. Something like this

void loop() {
   previousCredits = latestCredits; // save the value before updating it
   noInterrupts();
     latestCredits = credits;
   interrupts();
   Serial.println(latestCredits);

...R

I tried adding that to my code

String order_no;
int product_none;

void productFind() {
  if(order_no == "01" || order_no == "05" || order_no == "13"){
    product_none = 0;
  } else product_none = 1;
}

//----------------------------------------------------------------------------------------------------------------------------------------------------------

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const int coinPin = 21;

volatile int credits = -1;

int previousCredits,
  latestCredits;

const char cancelButton = '*',
  confirmButton = '#';

int digitCounterOrder = 8,
  error = 0,
  confirm = 0;
  
char  key;

const byte ROWS = 4,
  COLS = 4;

char keyDisplay[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

const byte rowPins[ROWS] = {5, 4, 3, 2},
  colPins[COLS] = {10, 8, 7, 6};

Keypad kPad = Keypad(makeKeymap(keyDisplay), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27, 16, 2);  

void setup(){
  lcd.init();
  lcd.backlight();
  
  Serial.begin(9600);

  pinMode(coinPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(coinPin), coinInserted, RISING);

}

void loop(){
  lcd.setCursor(0, 0);  
  lcd.print("Credits: ");
  lcd.print(credits);
  lcd.setCursor(0,1);
  lcd.print("Order: #");

  previousCredits = latestCredits; //**********
  
  noInterrupts(); //**********
  latestCredits = credits; //**********
  interrupts(); //**********
   
  Serial.println(latestCredits); //**********
  //Serial.println(previousCredits);
  
  key = kPad.getKey();

  if (key){

    if(key == cancelButton){
      reset();
    }

    if(key == confirmButton){
      productFind();
      errorFind();
      if(error == 0){
        confirmOrder();
      } else {
        error = 0;
      }
      reset();
    }
    
    if(digitCounterOrder == 10){
      retypeOrder();
    }
    
    lcd.setCursor(digitCounterOrder, 1);
    if(!(key == cancelButton || key == confirmButton)){
      lcd.print(key);
      order_no += key;
    }
    digitCounterOrder++;

  }
  
}

void coinInserted(){
  credits++;
}

void reset(){
  digitCounterOrder = 7;
  lcd.setCursor(digitCounterOrder, 1);
  lcd.print("   ");
  order_no = "";
}

void retypeOrder(){
  digitCounterOrder = 8;
  lcd.setCursor(digitCounterOrder, 1);
  lcd.print("   ");
  order_no = "";
}

void errorFind(){
  if(order_no.length() == 1){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Please enter a");
    lcd.setCursor(0,1);
    lcd.print("two digit number");
    delay(3000);
    lcd.clear();
    error = 1;
  } else if(product_none == 1){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" There is no");
    lcd.setCursor(0,1);
    lcd.print("    product #");
    lcd.print(order_no);
    delay(3000);
    lcd.clear();
    error = 1;
  } else{
    confirm = 1;
  }
}

void confirmOrder(){
  lcd.clear();
  while(confirm == 1){
    lcd.setCursor(0,0);
    lcd.print("Are you sure you");
    lcd.setCursor(0,1);
    lcd.print("want to buy #");
    lcd.print(order_no);
    lcd.print("?");
    
    key = kPad.getKey();
    
    if(key == cancelButton){
      confirm = 0;
      lcd.clear();
    } else if(key == confirmButton){
      lcd.clear();
      confirm = 0;
      takeOrder();
    }
  }
  
}

void takeOrder(){
  // --------------- LOADING ---------------
  int d;
  for(int c = 0; c<=30; c++){
    if(c<=15) d=c;
    if(c>15) d=c-16;
    lcd.setCursor(d, 0);
    lcd.print(".");
    delay(100);
    if(c>5){
      lcd.setCursor(c - 6, 0);
      lcd.print(" ");
    }
    if(d>5){
      lcd.setCursor(d - 6, 0);
      lcd.print(" ");
    }
    lcd.setCursor(d, 1);
    lcd.print(".");
    delay(100);
    if(c>5){
      lcd.setCursor(c - 6, 1);
      lcd.print(" ");
    }
    if(d>5){
      lcd.setCursor(d - 6, 1);
      lcd.print(" ");
    }
  }
  // --------------- /LOADING ---------------
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" Thank you");
  lcd.setCursor(0,1);
  lcd.print("     Take care!");
  delay(5000);
  lcd.clear();
}

But the serial monitor still gives me these values

1320
2700
4080
5460
6840
8220
9600
11040
12480
13920
15360
16800
18240
19680
21120
22560
24000
25440
26880
28320
29760
31200
32640
-31396
-29896
-28396
-26896
-25396
-23896
-22396
-20896
-19396
-17896
-16396
-14896
-13396
-11896
-10396
-8956
-7516
-6076
-4636
-3196
-1756
-316
1004
2384
3764
5144
6524
7904
9284
10664
12104
13544
14984
16424
17864
19304
20744
22184
23624
25064
26504
27944
29384
30824
32264
-31772
-30272
-28772
-27272
-25772
-24272
-22772
-21272
-19772
-18272
-16772
-15272
-13772
-12272
-10772
-9272
-7832
-6392
-4952
-3512
-2072
-632
688
2068
3448
4828
6208
7588
8968
10348
11788
13228
14668
16108
17548
18988
20428
21868
23308
24748
26188
27628
29068
30508
31948
-32148
-30648
-29148
-27648
-26148
-24648
-23148
-21648
-20148
-18648
-17148
-15648
-14148
-12648
-11148
-9648
-8208
-6768
-5328
-3888
-2448
-1008
372
1692
3072
4452

It’s like a repeated cycle of incrementing to 32k-ish, becomes negative, incrementing to zero.

An int data type can hold numbers from -32768 to 32767. An unsigned int can hold 0 to 65531. If you want larger numbers use long or unsigned long. See Arduino data types.

I kinda narrowed down the problem. I removed all the lcd codes from my loop function:
(I put the whole code but I only want to emphasize the loop function)

String order_no;
int product_none;

void productFind() {
  if(order_no == "01" || order_no == "05" || order_no == "13"){
    product_none = 0;
  } else product_none = 1;
}

//----------------------------------------------------------------------------------------------------------------------------------------------------------

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const int coinPin = 21;

volatile int credits = -1;

int previousCredits,
  latestCredits;

const char cancelButton = '*',
  confirmButton = '#';

int digitCounterOrder = 8,
  error = 0,
  confirm = 0;
  
char  key;

const byte ROWS = 4,
  COLS = 4;

char keyDisplay[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

const byte rowPins[ROWS] = {5, 4, 3, 2},
  colPins[COLS] = {10, 8, 7, 6};

Keypad kPad = Keypad(makeKeymap(keyDisplay), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x27, 16, 2);  

void setup(){
  lcd.init();
  lcd.backlight();
  
  Serial.begin(9600); //************************************************************************************************************************************

  pinMode(coinPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(coinPin), coinInserted, RISING);

}

void loop(){

  Serial.println(credits);
  
  key = kPad.getKey();

  if (key){

    if(key == cancelButton){
      reset();
    }

    if(key == confirmButton){
      productFind();
      errorFind();
      if(error == 0){
        confirmOrder();
      } else {
        error = 0;
      }
      reset();
    }
    
    if(digitCounterOrder == 10){
      retypeOrder();
    }
    
    if(!(key == cancelButton || key == confirmButton)){
      order_no += key;
    }
    digitCounterOrder++;

  }
  
}

void coinInserted(){
  credits++;
}

void reset(){
  digitCounterOrder = 7;
  lcd.setCursor(digitCounterOrder, 1);
  lcd.print("   ");
  order_no = "";
}

void retypeOrder(){
  digitCounterOrder = 8;
  lcd.setCursor(digitCounterOrder, 1);
  lcd.print("   ");
  order_no = "";
}

void errorFind(){
  if(order_no.length() == 1){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Please enter a");
    lcd.setCursor(0,1);
    lcd.print("two digit number");
    delay(3000);
    lcd.clear();
    error = 1;
  } else if(product_none == 1){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" There is no");
    lcd.setCursor(0,1);
    lcd.print("    product #");
    lcd.print(order_no);
    delay(3000);
    lcd.clear();
    error = 1;
  } else{
    confirm = 1;
  }
}

void confirmOrder(){
  lcd.clear();
  while(confirm == 1){
    lcd.setCursor(0,0);
    lcd.print("Are you sure you");
    lcd.setCursor(0,1);
    lcd.print("want to buy #");
    lcd.print(order_no);
    lcd.print("?");
    
    key = kPad.getKey();
    
    if(key == cancelButton){
      confirm = 0;
      lcd.clear();
    } else if(key == confirmButton){
      lcd.clear();
      confirm = 0;
      takeOrder();
    }
  }
  
}

void takeOrder(){
  // --------------- LOADING ---------------
  int d;
  for(int c = 0; c<=30; c++){
    if(c<=15) d=c;
    if(c>15) d=c-16;
    lcd.setCursor(d, 0);
    lcd.print(".");
    delay(100);
    if(c>5){
      lcd.setCursor(c - 6, 0);
      lcd.print(" ");
    }
    if(d>5){
      lcd.setCursor(d - 6, 0);
      lcd.print(" ");
    }
    lcd.setCursor(d, 1);
    lcd.print(".");
    delay(100);
    if(c>5){
      lcd.setCursor(c - 6, 1);
      lcd.print(" ");
    }
    if(d>5){
      lcd.setCursor(d - 6, 1);
      lcd.print(" ");
    }
  }
  // --------------- /LOADING ---------------
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" Thank you");
  lcd.setCursor(0,1);
  lcd.print("     Take care!");
  delay(5000);
  lcd.clear();
}

The lcd is not in my circuit yet. So I tried removing it in my code, and the serial monitor now gives the right values for my coin slot. My main question now is, why do those lcd codes mean so much for the coin slot codes even though they seem to be not related to each other?

P.S. To make things clear, what I did is I changed the loop function into that ^, from this:

void loop(){

  Serial.println(credits);

  lcd.setCursor(0, 0);
  lcd.print("Credits: ");
  lcd.print(credits);
  lcd.setCursor(0,1);
  lcd.print("Order: #");
  
  key = kPad.getKey();

  if (key){

    if(key == cancelButton){
      reset();
    }

    if(key == confirmButton){
      productFind();
      errorFind();
      if(error == 0){
        confirmOrder();
      } else {
        error = 0;
      }
      reset();
    }
    
    if(digitCounterOrder == 10){
      retypeOrder();
    }
    
    lcd.setCursor(digitCounterOrder, 1);
    if(!(key == cancelButton || key == confirmButton)){
      lcd.print(key);
      order_no += key;
    }
    digitCounterOrder++;

  }
  
}

Okay. I just realized that pin 21 is for the scl of lcd. Does anyone know what could be the reason why the other interrupt pins of mega 2560 (2, 3, 18, 19, 20) doesn't work right for my coin slot?

WizOne:
But the serial monitor still gives me these values

1320

2700
4080
5460
6840
8220
9600
11040

You have never told us what values would be correct.

…R

You appear to have 2 threads on the same subject
AttachInterrupt Problem