Coin Acceptor Pulses Number and Coin Matching

Hello,

I am writing after lots of hours searching the forum and other websites.
I am new to Arduino and I am trying to find out how can I do the matching for the Coins inserted to a Multi Coin Acceptor.
I used the code of the Makezine and added some of my own.
All I want to do is match if 2 pulses then it is 1euro coin and when 5 pulses it is 2euro coin.
I want this to happen fast (as soon as the coin is inserted) and move a Servo bit I am having a little trouble.

For example:

#include <Servo.h>
Servo coinservo;  // create servo object to control a servo


const int coinInt = 0;
//Attach coinInt to Interrupt Pin 0 (Digital Pin 2). Pin 3 = Interrpt Pin 1.

int pulseCount = 0; // Pulse counter

volatile float coinsValue = 0.00;
//Set the coinsValue to a Volatile float
//Volatile as this variable changes any time the Interrupt is triggered

int coinsChange = 0;                  
//A Coin has been inserted flag

void setup()
{
  Serial.begin(9600);                 
//Start Serial Communication

  attachInterrupt(coinInt, coinInserted, RISING);   
//If coinInt goes HIGH (a Pulse), call the coinInserted function
//An attachInterrupt will always trigger, even if your using delays
}

void coinInserted() {
//The function that is called every time it receives a pulse


  coinsValue = coinsValue + 0.05;  
//As we set the Pulse to represent 5p or 5c we add this to the coinsValue

  coinsChange = 1;                           
//Flag that there has been a coin inserted
}

void pulseCounter(){
  pulseCount++;
  Serial.print("COUNTER:");
  Serial.println(pulseCount);  
}

void servoOpen() {
  Serial.println("SERVO OPEN");
  coinservo.attach(6); //Attach servo
  coinservo.write(90); // tell servo to go to position 0
  delay(300); // Delay is needed in order to move the servo.Otherwise won't move.
  coinservo.write(1);  // tell servo to go to position 0
  delay(300); // Delay is needed in order to move the servo.Otherwise won't move.
  coinservo.detach();
}

void loop(){
  
  if(coinsChange == 1){ //Check if a coin has been Inserted

    pulseCounter(); // Call the Pulse counter


    coinsChange = 0; //unflag that a coin has been inserted

    if (pulseCount > 2){
      
      servoOpen(); //Open coin servo if coin is 1euro / 2euro
    }

    Serial.print("Pulses:");
    Serial.println(pulseCount);
    
    digitalWrite(ledPin, LOW);   // sets the LED off

    Serial.print("Credit: £");
    Serial.println(coinsValue);
//Print the Value of coins inserted
  }

//      pulseCount = 0; //Set Pulses back to 0
}

And all the problem comes with the pulseCount set back to 0...

use code tags instead of quote tags for code.

Like this:

#include <Servo.h>
Servo coinservo;  // create servo object to control a servo

const int coinInt = 0;
//Attach coinInt to Interrupt Pin 0 (Digital Pin 2). Pin 3 = Interrpt Pin 1.

int pulseCount = 0; // Pulse counter

volatile float coinsValue = 0.00;
//Set the coinsValue to a Volatile float
//Volatile as this variable changes any time the Interrupt is triggered

int coinsChange = 0;                 
//A Coin has been inserted flag

void setup()
{
  Serial.begin(9600);                 
  //Start Serial Communication

  attachInterrupt(coinInt, coinInserted, RISING);   
  //If coinInt goes HIGH (a Pulse), call the coinInserted function
  //An attachInterrupt will always trigger, even if your using delays
}

void coinInserted() {
  //The function that is called every time it receives a pulse

  coinsValue = coinsValue + 0.05; 
  //As we set the Pulse to represent 5p or 5c we add this to the coinsValue

  coinsChange = 1;                           
  //Flag that there has been a coin inserted
}

void pulseCounter() {
  pulseCount++;
  Serial.print("COUNTER:");
  Serial.println(pulseCount); 
}

void servoOpen() {
  Serial.println("SERVO OPEN");
  coinservo.attach(6); //Attach servo
  coinservo.write(90); // tell servo to go to position 0
  delay(300); // Delay is needed in order to move the servo.Otherwise won't move.
  coinservo.write(1);  // tell servo to go to position 0
  delay(300); // Delay is needed in order to move the servo.Otherwise won't move.
  coinservo.detach();
}

void loop() {
   if(coinsChange == 1){ //Check if a coin has been Inserted
    pulseCounter(); // Call the Pulse counter

    coinsChange = 0; //unflag that a coin has been inserted

    if (pulseCount > 2){
      servoOpen(); //Open coin servo if coin is 1euro / 2euro
    }

    Serial.print("Pulses:");
    Serial.println(pulseCount);
   
    digitalWrite(ledPin, LOW);   // sets the LED off

    Serial.print("Credit: £");
    Serial.println(coinsValue);
    //Print the Value of coins inserted
  }

  //      pulseCount = 0; //Set Pulses back to 0
}

charavge:
And all the problem comes with the pulseCount set back to 0...

Yes. You only want to set it back to 0 after you have have used the existing value to do something. Right now, it gets set back to 0 every time through the loop.

Move it to here:

    if (pulseCount > 2){
      servoOpen(); //Open coin servo if coin is 1euro / 2euro
      pulseCount = 0; //Set Pulses back to 0
    }

OK but this is not right because if I don't want to move servo at 5 pulses it will still move.

I want to do something like:

case 1 pulse
do something
case 2 pulses
do something
case 5 pulses
do something

The big problem is the loop and I can't get over it.
I must find a way to loop the pulses fast enough, get the pulses count and then do what I want (including setting pulses counter to 0).

All topics in here write about milis() but I don't think this is about milis().
There has to be another way.

What I understand is that Every time a Pulse is sent the attachInterupt() function is triggered.
If 5 pulses are sent, then 5 times it will be triggered.
So I guess it is the appropriate place to add a PulseCounter.

Now the problem is when all pulse sending has stopped I need to get the number of pulses and
1)do whatever I need with this counter
2) set counter back to 0 when I have finished.

I tried using several functions but it still won't do it because the key is the triggering.
I don't have the appropriate knowledge for this.
If anybody does please give us a tip.

charavge:
What I understand is that Every time a Pulse is sent the attachInterupt() function is triggered.
If 5 pulses are sent, then 5 times it will be triggered.
So I guess it is the appropriate place to add a PulseCounter.

Now the problem is when all pulse sending has stopped I need to get the number of pulses and
1)do whatever I need with this counter
2) set counter back to 0 when I have finished.

I tried using several functions but it still won't do it because the key is the triggering.
I don't have the appropriate knowledge for this.
If anybody does please give us a tip.

So this problem is not a coding problem, it's a design problem.

How do you know the difference between 1, 2 and 5 pulses? Or even more simply, what is the difference between 1 pulse and 2 pulses? How do you know this is the end of the pulses, or if another one is coming? There are a few possible answers, but the most likely one for you is that after receiving a pulse, start a timer. If no more pulses are received in that timeframe, that's the end of the pulses. If a pulse is received within the timeframe, increase the pulse count and restart the timer.

So, the first question is, in the case of 2 pulses, how many milliseconds will there be between pulses? The answer to that should tell you how long your pulse timeout should be (it must be quite a bit larger than the expected pulse period).

Once you know the answer, just a set a "pulseReceived = true;" in the ISR, then in the main loop "if (pulseReceived == true) { pulseReceived = false; lastPulseReceivedTime = millis();}"

When the millis() - lastPulseReceivedTime > some value, the value in count is 1,2 or 5. Do something, then set the count back to 0.

Thanks a lot! I understood exactly what I had to do from what you said, though I didn't know how to do it and searched the web a bit.
It was very explanatory and the keys in the whole idea I think is 1)when calling an ISR everything else stops and 2) that we can check that the pulses stopped with checking if there has passed time from last pulse (here 200ms).

I found this code at: Wise time with Arduino: Interrupt-based sketch for Adafruit coin acceptor
Just changed it a little because I don't use an LCD 16*2.

#define COIN_PIN 2

void setup()
{
  // Debugging output
  Serial.begin(9600);

  Serial.println("Ready...");
  
  pinMode(COIN_PIN, INPUT);
  attachInterrupt(0, coinISR, RISING);  // COIN wire connected to D2;
}


// total amount of money collected;
float money = 0.0;

// gets incremented by the ISR;
// gets reset when coin was recognized (after train of pulses ends);
volatile int pulses = 0;
volatile long timeLastPulse = 0;


// executed for every pulse;
void coinISR()
{
  pulses++;
  timeLastPulse = millis();
}


void loop()
{

  long timeFromLastPulse = millis() - timeLastPulse;
  if (pulses > 0 && timeFromLastPulse > 200)
  {
    // sequence of pulses stopped; determine the coin type;
    if (pulses == 2)
    {
      Serial.println("2 pulses");
      money += .1;
    }
    else if (pulses == 5)
    {
      Serial.println("5 pulses");
      money += .25;
    }
    else if (pulses == 10)
    {
      Serial.println("10 pulses");
      money += 1.0;
    }
    else if (pulses == 15)
    {
      Serial.println("Received tooney (15 pulses)");
      money += 2.0;
    }
    else
    {
      Serial.print("Unknown coin: ");
      Serial.print(pulses);
      Serial.println(" pulses");
    }

    pulses = 0;
  }
}

So it all happens with millis().
Thanks again!

Yep. Sounds like you have a good understanding of it now. Congrats.

BTW, you can do a switch(pulses) instead of multiple ifs.