0

I'm working on a vending machine project and I'm using CH-926 and an Arduino Uno for that. I've already set the coin accepter for different number of coins and respective output pulses. I'm unable to get the desired output for this. With every coin I insert the output varies even when I put the same coin.

int pulse = 0;

void coin_value() {
  pulse = pulse + 1;
}

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  Serial.println("Ready to be collected");
}

void loop() {
  if (digitalRead(2) == HIGH) {
    attachInterrupt(0, coin_value, FALLING);

    if (pulse == 3) {
      Serial.println("50");
    }
    if (pulse == 2) {
      Serial.println("20");
    }
    if (pulse == 1) {
      Serial.println("10");
    }
  }

  pulse = 0;
}

For each coin there are different specific pulses which helps to recognize the coin.int pulse=0;.

So when I insert coin 1 then the output should be 10, for coin 2 the output should be 20 and for coin 3 the output should be 50.

  • Don't cross post. You already asked this on SO. – gre_gor Jan 18 at 16:34
  • However he was asked on Stack Overflow to ask the question here, which he did. – Nick Gammon Jan 18 at 21:34
  • what does this actually mean? I'm unable to get the desired output for this ..... what do you expect? .... what do you actually get? – jsotola Jan 18 at 22:35
  • @NickGammon The question should be only on one site. If found a better site for it, he should delete the old one. – gre_gor Jan 18 at 23:16
  • @gre_gor I've flagged the SO post for deletion. However Sumit Kumar could help by self-deleting, if the system lets him. – Nick Gammon Jan 19 at 0:20
1

First of all you said

So when I insert coin 1 then the output should be 10, for coin 2 the output should be 20 and for coin 3 the output should be 50.

Yes coin 3 would be 50 but it does not means that coin 3 has 3 impulses(he will have 5 impulse), I recommend to you always use this formula:

Coin_Value = Pulse_Count * Denomination.

I don't recommend to you use 3 Impulses from coin acceptor Because you don't have 15 cent and 30 cent coins. In most cases Coin acceptors have:

1/4 1/2 1 2 4 5 8 10 impulses

Generally I prefer to save all data in variables

So lets get to variables for code

const int coinIntPin = 2;          //interruptPin 0 is digital pin 2
volatile boolean newCoin = false;                  
volatile int pulseCount;          //counts pulse for 
volatile int timeOut = 0;         //counts timeout after last coin inserted
float coinType;
float denomination = 0.50;         // in my case 1 Pulse = 0.50 $
int max_impulse = 4;              // this is the maximum impulses I use
volatile long timeFPulse = 0;     // to determine when First impulse was interrupted
volatile long interval;           // to determine interval from first and last impulse

And always use attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); It is recommended by Arduino as below:

void setup(){
    Serial.begin(9600);              
    attachInterrupt(digitalPinToInterrupt(coinIntPin), coinInserted, FALLING);

}

And I will give you rest of code:

void coinInserted(){
    newCoin = true; 
    timeFPulse = millis();
    pulseCount++; 
}

void loop()
{

     while (newCoin == true)
    {
            interval = millis() - timeFPulse;  //interval from first and last impulse
            if(pulseCount == max_impulse || (interval > 500 && pulseCount > 0)) //Max_impulse will avoid any extra impulses for any reason.
            { 
// This is the reason why I recommended to you use 1 2 4 5 10 20 Impulses instead of 3 7 9 etc...
              coinType = pulseCount * denomination; 
              newCoin = false;
              sendData();
              delay(5);

             }  

    }
}


void sendData(){
  Serial.print("Do what ever you want. Inserted Money = ");
  Serial.println(coinType);
  coinType = 0;  // remove if you want to save Coins and print sum of inserted coins
  pulseCount = 0;  // remove if you want to save impulses determined by coin acceptor
}

And Finally look at ( interval > 500 ) If you have different max impulses you must change 500 to (impulse length * Max impulses + 100); so if you have max 10 impulses you must enter 1100 and not 500 (in my case);

0

Your code is faulty in a number of respects.


  1. pulse should be declared volatile, i.e.

    volatile int pulse = 0;
    

    That is because it can change in an interrupt service routine.


  1. You should only do attachInterrupt once, in setup.

  1. Your code to display the count will be timing dependent. What if you happen to display the count after one pulse has arrived, but before they all have? Then you set the count back to zero.

Better would be something like this, untested however:

volatile int pulse = 0;

void coin_value() {
  pulse = pulse + 1;
}

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  Serial.println("Ready to be collected");
  attachInterrupt(0, coin_value, FALLING);
}

void loop() {

  if (pulse > 0)
    {
    delay (1000);   // let the other pulses arrive
    if (pulse == 3) {
      Serial.println("50");
    }
    if (pulse == 2) {
      Serial.println("20");
    }
    if (pulse == 1) {
      Serial.println("10");
    }
    pulse = 0;  // clear for next time
  }

}

(Edited to add)

Even then your test for 1/2/3 might fail if the coin acceptor sends the pulses twice. Then you might get 2/4/6 pulses. You probably need to display something if there is another count, eg.

  if (pulse == 3) {
    Serial.println("50");
  }
  else if (pulse == 2) {
    Serial.println("20");
  }
  else if (pulse == 1) {
    Serial.println("10");
  }
  else {
     Serial.print ("Unexpected number of pulses: ");
     Serial.println (pulse);
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.