Why we get errors like this

Hi everyone,

We’re working on an automated car washing machine project and have the following components: an Arduino, jumpers, a coin acceptor, buttons, and a power source to run everything.

Here’s the situation:
We’ve connected all the components with jumpers and written a working Arduino code using the Arduino IDE. On some days, everything runs smoothly and synchronizes perfectly. However, on other days, even though the setup (jumpers, Arduino, code, and components) remains exactly the same, we face issues.

The main problem lies in coin recognition. Specifically, our code currently supports recognizing 3 types of coins (pennies), but this part frequently malfunctions.

Has anyone experienced similar issues with inconsistent behavior in Arduino projects? Could it be related to hardware (e.g., jumpers, power source, coin acceptor) or perhaps the code itself? We’re open to any suggestions to troubleshoot this issue.

you need to post the code and possibly a wiring diragram

const int coin = 2; // Coin mechanism pin
const int buttonPin = 3; // Button pin
const int outputPin = 4; // Output pin (5V output)

boolean insert = false;
volatile int pulse = 0;
unsigned long balance = 0;
unsigned long lastInterruptTime = 0;
const unsigned long debounceDelay = 50; // Debounce delay in milliseconds
const unsigned long pulseTimeout = 100; // Maximum pulse wait time
const unsigned long pulseCompleteTimeout = 1000; // Additional time to complete pulses

unsigned long pulseStartTime = 0; // Start time of the pulse
unsigned long lastPulseTime = 0; // Last pulse time
boolean buttonPressed = false; // Button press state
unsigned long buttonPressStart = 0; // Start time of button press

void setup() {
pinMode(coin, INPUT); // Set coin pin as input
pinMode(buttonPin, INPUT_PULLUP); // Enable pull-up resistor for the button
pinMode(outputPin, OUTPUT); // Set output pin as output

digitalWrite(outputPin, LOW); // Initialize output as LOW

Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(coin), coinInterrupt, RISING); // Attach interrupt to the coin pin
delay(1000);
}

void loop() {
// Check if the button is pressed
if (digitalRead(buttonPin) == LOW && !buttonPressed) {
buttonPressed = true;
buttonPressStart = millis();

Serial.println("Button pressed");

// Deduct 50 pennies if there is enough balance
if (balance >= 50) {
balance -= 50;
digitalWrite(outputPin, HIGH); // Set output HIGH
Serial.println("50 pennies deducted, Output HIGH for 5 seconds");
} else {
Serial.println("Insufficient balance! Cannot deduct 50 pennies.");
}
}

// Turn off the output after 5 seconds
if (buttonPressed && millis() - buttonPressStart >= 5000) {
buttonPressed = false;
digitalWrite(outputPin, LOW); // Set output LOW
Serial.println("5 seconds elapsed: Output LOW");
}

// Coin mechanism logic
if (insert) {
insert = false;

// Update balance based on pulse count
if (pulse == 1) {
balance += 10; // 1 pulse = 10 pennies
Serial.println("1 pulse detected: 10 pennies added");
} else if (pulse == 2) {
balance += 20; // 2 pulses = 20 pennies
Serial.println("2 pulses detected: 20 pennies added");
} else if (pulse == 5) {
balance += 50; // 5 pulses = 50 pennies
Serial.println("5 pulses detected: 50 pennies added");
} else {
Serial.println("Unknown pulse count detected");
}

pulse = 0; // Reset pulse counter
Serial.print("Balance: ");
Serial.println(balance);
}

// Timeout check: Trigger insert if pulse duration exceeds the limit
if (pulse > 0 && millis() - pulseStartTime > pulseTimeout) {
insert = true;
}

// Trigger insert if pulse completion time exceeds the limit
if (millis() - lastPulseTime > pulseCompleteTimeout && pulse > 0) {
insert = true;
}
}

// Interrupt function for the coin mechanism
void coinInterrupt() {
unsigned long currentTime = millis();

// Debounce to ignore rapid triggers
if (currentTime - lastInterruptTime > debounceDelay) {
if (pulse == 0) {
pulseStartTime = currentTime; // Record the time when the first pulse starts
}
pulse++; // Increment pulse count
lastPulseTime = currentTime; // Record the time of the last pulse
}

lastInterruptTime = currentTime;
}

here it is, unfortunately i can't send you wiring diagram now

Please select all code in post #3, click the <CODE/> button and save the post. This will make it easier to read and copy and the forum software will display it correctly.

Could you please put your code within CODE tags. This makes is so much easier for everyone to read.
(sorry sterretje, posts crossed)

Could the coin reader itself be having problems recognizing coins?

What kind of malfunctions are you experiencing?

Might the jumper wires be picking up some kind of interference?

If the coin acceptor does not recognize differences in coin size or weight, or have the mechanism to "weigh" a coin (the new TL being aluminum, and floats on water), problems will occur.

  • Always show us a good schematic of your proposed circuit.
    Show us good images of your ‘actual’ wiring.
    Give links to components.

  • Make sure all voltages are okay and nothing is running hot.

  • Poor wiring connections are often indicated.

  • Using interrupts is problematic in Arduino projects, suggest you consider using input change in state polling.

should the coin input be configued as INPUT_PULLUP, enabling the internal pull-up resistor

is it really necessary to use an interrupt? why not monitor the coin pin, debounce with a simple 20 msec delay.

why not adjust the balance and decrement the pulse for each increment of pulse?

My suggestion is a lot less complicated.

Strip your code down to include only the coin acceptor, and some serial prints for debugging.

Make that bulletproof, then throw all the other stuff back in.

look this over
confused by your use of multiple timers

// 
const byte PinLed  =  4;;
const byte PinInp [] = { 2, 3 };

enum { Coin, But };                     // symbol/index values for inputs

enum { Off = HIGH, On = LOW };

// -------------------------------------
int  Ninp      = sizeof(PinInp);
byte inpState [2];
const int NoInp = -1;

int
chkInp ()
{
    for (int n = 0; n < Ninp; n++)  {
        byte inp = digitalRead (PinInp [n]);

        if (inpState [n] != inp)  {
            inpState [n]  = inp;
            delay (20);

            if (LOW == inp)
                return n;
        }
    }
    return NoInp;
}

// -----------------------------------------------------------------------------
const unsigned long MsecOnPeriod = 5000;
unsigned long msecTmr;

bool tmr;
int  balance;

void
loop (void)
{
    unsigned long msec = millis ();

    if (tmr && msec - msecTmr >= MsecOnPeriod)  {
        tmr = false;
        digitalWrite (PinLed, Off);
    }

    switch (chkInp ())  {
    case Coin:
        balance += 10;
        Serial.println (balance);
        break;

    case But:
        if (50 <= balance)  {
            balance -= 50;
            digitalWrite (PinLed, On);
            tmr     = true;
            msecTmr = msec;
        }
        else
            Serial.println ("insufficent balance");
        break;
    }
}

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

    pinMode (PinLed, OUTPUT);
    digitalWrite (PinLed, Off);

    for (int n = 0; n < Ninp; n++)  {
        pinMode (PinInp [n], INPUT_PULLUP);
        inpState [n] = digitalRead (PinInp [n]);
    }
}

sorry i'm a newbie here i edited it with code tags, so i think problem is not in the coin acceptor because you first adjust the coin acceptor itself with how much pulse it gonna give you for each penny, in our case: 1 impulse for 10 penny, 2 impulse for 20 penny and 3 impulse for 50 penny, when you insert a coin in coin acceptor works perfectly it recognizes every coin with certain impulses but however in the arduino ide(in serial monitor) it don't displays it correctly. So as i stated in the first post it’s like this:

one day, we gather to test everything, and everything works perfectly. Feeling happy, we go home. The next day, when we meet again for final checks, we face issues with coin recognition. We adjust the code accordingly, everything works, and we go home happy again.
This cycle has been repeating for a week now.

our coin acceptor model(it is CH-926):

you are right but all the hardware things are with my friend so i can't post hardware stuff now, we will try to get all things fixed up today maybe we will buy some new arduino or jumpers i don't know. Because as i said in first post someday all the things works perfectly and another day not so i think the problem is in our hardware because "code" is a static thing, there is no such thing as working one day and not working the next
Btw nothing runs hot.

will try this, thank y'all for making time for our problem

When we connect the coin port to the Arduino with a cable and measure the pulses, we randomly receive values like 3000 pulses. We are using CH 926 coin acceptor, can someone write a basic code for getting up balance for certain pulses like, 1-10,2-20,5-50,
or just modify our code `#include <TM1637Display.h>

#define COIN_PIN 2  // Coin acceptor sinyal pini (Interrupt destekli olmalı)
#define CLK 3       // TM1637 Clock pini
#define DIO 4       // TM1637 Data pini

TM1637Display display(CLK, DIO);
volatile int pulseCount = 0;
int balance = 0;

void coinInterrupt() {
    pulseCount++;  // Gelen pulse sayısını artır
}

void setup() {
    pinMode(COIN_PIN, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(COIN_PIN), coinInterrupt, FALLING);
    display.setBrightness(7); // Ekran parlaklığı ayarı
    display.showNumberDec(balance);
}

void loop() {
    if (pulseCount > 0) {
        delay(200); // Gürültü engellemek için kısa bir gecikme
        int count = pulseCount;
        pulseCount = 0; // Pulse sayacını sıfırla

        // Gelen pulse sayısına göre bakiye ekleme
        if (count == 1) balance += 10;
        else if (count == 2) balance += 20;
        else if (count == 5) balance += 50;

        display.showNumberDec(balance); // Bakiyeyi ekranda göster
    }

}`

That behavior is typical of a bad connection and an open (floating) port pin. Check the correctness and continuity of all the wiring using multimeter.

I think you missed the pull-up resistor (10k) between Counter pin and +5V.

They're using INPUT_PULLUP, which IME, is sufficient for most acceptors if you're not too far away.

@salamkalbasa how long is the cable between the arduino and your coin acceptor, and did you also connect a common ground?

Also, simplify your code until you get this working. First step is to just print pulseCount without any modifcations.

And the second step is to properly deal with your volatile variable. Assuming you are using an UNO, you can not atomically deal with a 16 bit value while interrupts are enabled.

void loop() {
    noInterrupts();
    int count = pulseCount;
    interrupts();
    
    if (count > 0) {
        delay(200); // Gürültü engellemek için kısa bir gecikme
        noInterrupts();
        pulseCount = 0; // Pulse sayacını sıfırla
        interrupts();
        ...

You're right, I missed that pinmode(), sorry. But I (almost) always prefer to use external resistors, and googling around about this device (even on this very forum) the arduino built in pullup resistor looks like it works but the readings cannot be precise enough to make sure the count is the right one, especially on longer cables.

First of all, what is the exact model ot the coin acceptor? I see there are at least two versions.
Then, how it's powered and connected to Arduino? It's a 12V device, are you sure the power adapter you're using is correct for the device?
And are you sure you correctly programmed the coin acceptor? See here.
Lastly: to help us help you, please, always, always include the complete code. You missed an "#include" statement, and a closing bracket. And help us also by translating your comments in english to make it easier to read...

Anyway, as far as I can see that's not exactly the way to deal with a coin acceptor like that (even if I never used that CH926), and I don't like much the use of delay().
Impulses belonging to a single coin are close apart, so if enough time has passed after the last impulse we can assume that all incoming impulses were received and we have a proper number of impulses recorded in the variable and we can determine which coin was inserted.
This can be accomplished in many ways, one is the following (I wrote it "on the fly" so it's up to you to test it):

#include <TM1637Display.h>

#define COIN_PIN 2  // Coin acceptor sinyal pini (Interrupt destekli olmalı)
#define CLK 3       // TM1637 Clock pini
#define DIO 4       // TM1637 Data pini
// Minimum ms to detect a pulse "pause"
#define PULSE_PAUSE 100

TM1637Display display(CLK, DIO);

volatile int pulseCount = 0;
// Time of last pulse received
volatile unsigned long tmrLastPulse = 0;

int balance = 0;

void coinInterrupt() {
  pulseCount++;
  tmrLastPulse = millis();
}

void setup() {
  pinMode(COIN_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(COIN_PIN), coinInterrupt, FALLING);
  display.setBrightness(7); // Ekran parlaklığı ayarı
  display.showNumberDec(balance);
}

void loop() {
  if (tmrLastPulse > 0 && millis() - tmrLastPulse >= PULSE_PAUSE) {
    // Ok, we can go on checking the pulses received
    int count = pulseCount;
    tmrLastPulse = 0;
    // The following statements depend on the coin acceptor programming
    if (count == 1) balance += 10;
    if (count == 2) balance += 20;
    if (count == 5) balance += 50;
    // Show the result
    display.showNumberDec(balance);
  }
}

how are you dealing with mechanical switch bounce?

better off not using an interrupt.

# define COIN_PIN 2  // Coin acceptor sinyal pini (Interrupt destekli olmal─▒)
# define CLK 3       // TM1637 Clock pini
# define DIO 4       // TM1637 Data pini

TM1637Display display (CLK, DIO);

int pulseCount = 0;
int balance = 0;

byte coinLast;

// -----------------------------------------------------------------------------
void loop ()
{
    byte coin = digitalRead (COIN_PIN);
    if (coinLast != coin)  {
        coinLast  = coin;
        delay (20);         // debounce

        if (LOW == coin)    // active
            pulseCount++;
    }

    if (pulseCount > 0) {
        int count = pulseCount;
        pulseCount = 0; // Pulse sayac─▒n─▒ s─▒f─▒rla

        // Gelen pulse say─▒s─▒na g├╢re bakiye ekleme
        if (count == 1)       balance += 10;
        else if (count == 2)  balance += 20;
        else if (count == 5)  balance += 50;

        display.showNumberDec (balance); // Bakiyeyi ekranda g├╢ster
    }
}

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

    pinMode (COIN_PIN, INPUT_PULLUP);
    coinLast = digitalRead (COIN_PIN);

    display.setBrightness (7); // Ekran parlakl─▒─ƒ─▒ ayar─▒
    display.showNumberDec (balance);
}