AttachInterrupt Problem(?)

[This may seem multi-posting, but I think it's more appropriate to make a new post. This is a much more narrow problem compared to my last post, so continuing my last thread may be very confusing.]

Hi!

I am testing my universal coin slot with an Arduino Mega 2560.

I have two sketches for testing my coin slot.

In this sketch, when I insert a coin, the led blinks x times based on the pulse given by the coin inserted. (ex. 1 peso gives 1 pulse; 5 peso gives 5 pulses)

const int coinPin = 2;

void setup() {
  Serial.begin(9600);
  pinMode(coinPin, INPUT_PULLUP);
}

void loop(){  
  int coinState = digitalRead(coinPin);
  Serial.println(coinState);
}

Example serial monitor output:

1
1
1
1
1
1
1
1
1
1
1
0 //Inserted a 1 peso coin
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0 //Inserted a 10 peso coin
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1

But in this sketch with the attachInterrupt():

const int coinPin = 2;
volatile int credits = 0;

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

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

void coinInserted(){
  credits++;
}

even though I'm not inserting any coins, the serial monitor gives these:

0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4 //I'm not yet even inserting any coins!!!!!
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
7
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
8
9
9
9
9
9
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
12
16
16
16
16
26
26
26
26
38
38
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39
39

The credits variable keeps on incrementing from time to time without any coin being inserted in the coin slot. But I expected that with the attachInterrupt function, the credits++ or the coinInserted() would only work if the coin slot gave pulses.

I used both sketches with my same circuit
I used the same signal(coin) pins.

I needed to use attachInterrupt instead of just the loop function for the utilization of the coin slot because the loop function would contain more stuff for my actual project.

I already visited so many links involving a universal coin slot with Arduino but trying them doesn't give me the results I need. Most of them give me the same problem.

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

How is coinPin wired ?

I needed to use attachInterrupt instead of just the loop function for the utilization of the coin slot because the loop function would contain more stuff for my actual project.

If that is the case then you have almost certainly written the other code in loop() wrongly. Do not write code that blocks the free running of the loop() function.

Take a look at Using millis() for timing. A beginners guide and Several things at the same time

WizOne,

An interrupt is not the right thing to use to detect something that happens relatively slowly. Although I can’t see your circuit I would imagine putting a coin in a coin slot produces a pulse of similar length to someone pressing a button. I imagine it is a few tens to a few hundred milliseconds long. If that’s not true and it’s actually micro seconds then apologies and maybe an interrupt is appropriate. Assuming I am right then don’t use an interrupt.

An interrupt is for something that happens very quickly, unpredictably and can be dealt with quickly. A button press is well outside these requirements.

There is more than one way to read such an input, here is some code that demonstrates one way to do it. Feel free to modify it and use it as you need.

/* Simple button debounce for 4 buttons. Increments a count and sends the updated count to the serial monitor once per button press */
/* Tested on an Uno */
/* Connect simple push to make buttons between 0V and pin 2, 0V and pin 3, 0V and pin 4 and between 0V and pin 5 */

#define noOfButtons 4     //Exactly what it says; must be the same as the number of elements in buttonPins
#define bounceDelay 20    //Minimum delay before regarding a button as being pressed and debounced
#define minButtonPress 3  //Number of times the button has to be detected as pressed before the press is considered to be valid

const int buttonPins[] = {2, 3, 4, 5};      // Input pins to use, connect buttons between these pins and 0V
unsigned long previousMillis[noOfButtons];  // Timers to time out bounce duration for each button
uint8_t pressCount[noOfButtons];            // Counts the number of times the button is detected as pressed, when this count reaches minButtonPress button is regared as debounced 
uint8_t testCount[noOfButtons];             //Test count, incremented once per button press

void setup() {
  uint8_t i;
  uint32_t baudrate = 115200;
  Serial.begin(baudrate);
  Serial.println("");
  Serial.print("Serial port connected: ");
  Serial.println(baudrate);
  for (i = 0; i < noOfButtons; ++i) {
    pinMode(buttonPins[i], INPUT_PULLUP);
    Serial.print("Testcount ");
    Serial.print(i);
    Serial.print(" = ");
    Serial.println(testCount[i]);
  }
}

void loop() {
  debounce();
  delay(10);     //Your other code goes here instead of this delay. DO NOT leave this delay here, it's only for demonstration.
}

void debounce() {
  uint8_t i;
  unsigned long currentMillis = millis();
  for (i = 0; i < noOfButtons; ++i) {
    if (digitalRead(buttonPins[i])) {             //Input is high, button not pressed or in the middle of bouncing and happens to be high
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        pressCount[i] = 0;                        //Set the number of times the button has been detected as pressed to 0
      }
    else {
      if (currentMillis - previousMillis[i] > bounceDelay) {
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        ++pressCount[i];
        if (pressCount[i] == minButtonPress) {
          ++testCount[i];
          Serial.print("Button ");
          Serial.print(i);
          Serial.print(" testcount = ");
          Serial.println (testCount[i]);
        }
      }
    }
  }
}
attachInterrupt(digitalPinToInterrupt(coinPin), coinInserted, RISING);

shouldn’t that be ‘FALLING’ ?
It still shouldn’t be firing the interrupt like that though.

1 Like

OP's earlier Thread

IMHO it would be best to click Report to Moderator and ask to have the two Threads merged so we can see all the info in one place.

...R

1

How is coinPin wired ?

It’s with a pull-up resistor shown here. Without it, the coin pin seems to be a floating pin

If that is the case then you have almost certainly written the other code in loop() wrongly. Do not write code that blocks the free running of the loop() function.

The sketch of my actual project contains the codes that are in my second sketch in this post. It also gives the same pattern of output (“the credits variable keeps on incrementing from time to time”).

But if you’d mind asking, it’s this:

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 = 2;

volatile int credits = 0;

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);

  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++;

  }
  
}

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 ---------------
  // --------------- START CORRESPONDING MOTOR ---------------
}

2
Thank you PerryBebbington! I’m analyzing it right now, Please bear with me as I still have a little knowledge in Arduino.

3

shouldn’t that be ‘FALLING’ ?

It gives the same thing though :frowning:
Anyways, thank you!

4

IMHO it would be best to click Report to Moderator and ask to have the two Threads merged so we can see all the info in one place.

I’m sorry about that. Though I’m kinda disregarding that post already. I’m making things clearer. I found out my problem at that time (I used pin 21 for the signal pin of my coin slot but it’s an SCL pin, which is necessary for my LCD). I guess in this post, the problem that has to be solved became more narrow. But thank you!

With a pull-up resistor shown here.

Do you know what happens inside the coin slot? I notice it has 12V connected to it. Are you sure that the output pin does not output 12V under any circumstances? Before I saw that I imagined something with some kind of mechanical switch that was connected as the output. Please make sure it does not output 12V as 12V would damage the Arduino as wired. Apologies if you have already dealt with this and I missed it.

PerryBebbington:
Do you know what happens inside the coin slot? I notice it has 12V connected to it. Are you sure that the output pin does not output 12V under any circumstances? Before I saw that I imagined something with some kind of mechanical switch that was connected as the output. Please make sure it does not output 12V as 12V would damage the Arduino as wired. Apologies if you have already dealt with this and I missed it.

The coin slot seems to be fine. Besides, it works with my first sketch in this post as I said.

The coin slot seems to be fine. Besides, it works with my first sketch in this post as I said.

OK, good, sorry, missed that! :confused:

const byte rowPins[ROWS] = {5, 4, 3, 2},

This shows a keypad connection to pin 2 which you are using as your interrupt pin.

But the keypad is not in your simplified test sketch.

When you disconnect the coin slot output signal from the pin2 connection, do you still see the unexpected increases in the count?

It's with a pull-up resistor shown here. Without it, the coin pin seems to be a floating pin

This is not typical unless you have long wires or a noisy environment. Typically INPUT_PULLUP should be sufficient.