Counting pulses -> switch case

Hi.

Am using a modified code from Mr. Raynerd (coin machine) for my purposes but i can not find what am missing in the pulse count.

If i insert one euro i will get:

new coin - 1 EUR -----> OK

But if i insert 2 or 5 i will get :

new coin - 1 EUR
new coin - 1 EUR

new coin - 1 EUR
new coin - 1 EUR
new coin - 1 EUR
new coin - 1 EUR
new coin - 1 EUR

So, it's counting OK but it doesn't go into case 2 / 3.

Code:

//#include <LiquidCrystal.h>
//LiquidCrystal lcd(12, 11, 6, 5, 4, 3);

//**************Variables ****************
volatile byte           coinPulseCount=0;         // a counter to see how many times the pin has changed - which coin inserted
volatile byte           hopperPulseCount = 0;     // a counter to she how many coins have been ejected
volatile unsigned long  pulseTime;                //this stores the time of the last pulse.
byte                    newCoinInserted;          // a place to put our last coin pulse count
byte                    coinValue = 0;            // number of pulses required to dispence each coin type.
//***************************
byte pulseThreshold = 200; // for alberichi coin sorter
//***************************
void setup()
{
  Serial.begin(9600);
  //lcd.begin(16, 2);
  pinMode (2,INPUT_PULLUP);
  attachInterrupt(0, coinacceptor, FALLING);
}

//*****************************************************
void loop()
{
  //lcd.setCursor(1,0);
  //lcd.print(coins);

  if (coinPulseCount >0 && millis()- pulseTime > pulseThreshold)  
      {
        newCoinInserted = coinPulseCount; 
        Serial.print("New coin ");
        coinPulseCount = 0; 
      }


  switch (newCoinInserted) {
      
      case 1:
        Serial.println("1 EUR "); 
        newCoinInserted = 0;        
        break;

      case 2:
         Serial.println("2 EUR");
         newCoinInserted = 0;
         break;

      case 3:
         Serial.println("5 EUR");
         newCoinInserted = 0;
         break;
      }
}

//*****INTERUPT for coin puls ****************
    void coinacceptor()      
    {
      coinPulseCount++;
      pulseTime = millis();   
    }

Ideas ?

u are using the wrong value for the switch --

switch (newCoinInserted)

u want
switch(coinPulseCount)

Those are not counts they are coin types. The debug output says you are only inserting 1 euro coins.

Mark

arnix:
Hi.

Am using a modified code from Mr. Raynerd (coin machine) for my purposes but i can not find what am missing in the pulse count.

If i insert one euro i will get:

new coin - 1 EUR -----> OK

But if i insert 2 or 5 i will get :

new coin - 1 EUR
new coin - 1 EUR

new coin - 1 EUR
new coin - 1 EUR
new coin - 1 EUR
new coin - 1 EUR
new coin - 1 EUR

So, it's counting OK but it doesn't go into case 2 / 3.

Code:

//#include <LiquidCrystal.h>

//LiquidCrystal lcd(12, 11, 6, 5, 4, 3);

//Variables ****************
volatile byte          coinPulseCount=0;        // a counter to see how many times the pin has changed - which coin inserted
volatile byte          hopperPulseCount = 0;    // a counter to she how many coins have been ejected
volatile unsigned long  pulseTime;                //this stores the time of the last pulse.
byte                    newCoinInserted;          // a place to put our last coin pulse count
byte                    coinValue = 0;            // number of pulses required to dispence each coin type.
//
*************
byte pulseThreshold = 200; // for alberichi coin sorter
//***************************
void setup()
{
  Serial.begin(9600);
  //lcd.begin(16, 2);
  pinMode (2,INPUT_PULLUP);
  attachInterrupt(0, coinacceptor, FALLING);
}

//*****************************************************
void loop()
{
  //lcd.setCursor(1,0);
  //lcd.print(coins);

if (coinPulseCount >0 && millis()- pulseTime > pulseThreshold) 
      {
        newCoinInserted = coinPulseCount;
        Serial.print("New coin ");
        coinPulseCount = 0;
      }

switch (newCoinInserted) {
     
      case 1:
        Serial.println("1 EUR ");
        newCoinInserted = 0;       
        break;

case 2:
        Serial.println("2 EUR");
        newCoinInserted = 0;
        break;

case 3:
        Serial.println("5 EUR");
        newCoinInserted = 0;
        break;
      }
}

//*****INTERUPT for coin puls ****************
    void coinacceptor()     
    {
      coinPulseCount++;
      pulseTime = millis(); 
    }




Ideas ?

Are you sure that your coin sorter outputs its pulses within 200ms? It seems that it should be since 200ms is an eternity in embedded programming, but your output suggests that it isn't.

From your output, when you input a 2 EUR you definitely get 2 pulses, as evidenced by printing case 1 twice. When you input a 5 EUR you definitely get 5 pulses, as evidenced by printing case 1 five times.

The problem seems to be that your ((millis() - pulseTime) > pulseThreshold) is designed to wait 200ms for all of the pulses to be received before processing the final value of coinPulseCount, but for whatever reason 200ms isn't long enough.

Try changing pulseThreshold from 200ms to 2000ms and see if it fixes it. If it does, you should investigate how long it should really take the coin sorter to output 2 or 5 pulses when you input a 2 or 5 EUR coin.

Thank you guys for fast reply.
@ backwoodsjack & holmes4

I can not change the value to coinPulseCount because i will get output like:
1 EUR = 1111111111111new coin 111111111111new coin .
2 EUR = 1111111111111new coin 111111111111new coin 1111111111111new coin 111111111111new coin .
5 EUR = the same but 5 times

Its simpler to do it with newCoinInserted.

@bigBobby
This coin machine should have 200ms between pulses to read them correctly.
How can i implement this part in the code ?

Shortly, i can never enter case 2 / 3 and it must be because reading time.

//-------------------------------------------------
I have used this code for main testing and the situation is the same as with the upper code:

volatile int coin = 0;
void setup()
{
Serial.begin(9600);
pinMode (2,INPUT_PULLUP);
attachInterrupt(0, coinIN, FALLING);
}
void coinIN()
{
coin = coin + 1;
}
void loop()
{
if (coin==1)
{
Serial.println("one");
coin = 0;
}
if (coin==2)
{
Serial.println("two");
coin = 0;
}
if (coin==5)
{
Serial.println("five");
coin = 0;
}
}

OUTPUT:
one

one
one

one
one
one
one
one

arnix:
@BigBobby
This coin machine should have 200ms between pulses to read them correctly.
How can i implement this part in the code ?

Wow...so they really do output their pulses more than 200ms apart? I've never made a vending machine before, but I do suppose they operate slowly (on the order of seconds) so I guess that 200ms makes sense (even though that's pretty slow compared to what most microprocessors do).

In that case your solution should be to just increase pulseThreshold to the maximum value that the pulses could ever be apart (the datasheet must say the pulses are 200ms apart +/- ?ms).

The code you have now will wait no longer than 200ms for two consecutive pulses. If your hardware will always space the pulses out more than 200ms, then your code must wait for longer than that to count the 2 and 5 pulses together.

Time between pulses can be programmed directly on coin machine. Lowest,as far as i know is 50ms.
Mine is preprogramed at 200ms. I guess :slight_smile: because i dont have scope near me.

Anyhow, i changed pulseThreshold from 50 to 30000 but there ware no changes.
There must be some other way to "group" this signals.

Can i display pulse time and time between pulses on serial monitor ?

A.

Can i display pulse time and time between pulses on serial monitor ?

Permission is granted.

Permission is granted.

Beam me up Scotty :slight_smile: :slight_smile:

Now that i have permission, can you share some ideas / code :-). ?
Regards !

Now that i have permission, can you share some ideas / code :-). ?

   Serial.print("The value of interest is: ");
   Serial.println(theValueOfInterest);

:slight_smile: . Let me be more exact :slight_smile:

Can you share some code sample, based on my existing code in the upper topic :slight_smile: :), on how to display pulse time and time between pulses, on serial monitor ? It would be great help if you would use variables from my main code :slight_smile:

Btw. keep in mind that english is my second language :).

You know what variables contain the values that are of interest TO YOU.

You know where the values are of interest, in the code.

YOU add the necessary Serial.print() statements.

I can get time between pulses but i can not detect how long is one pulse active.
E.g. i know that time between pulses is 400ms but that's all i can pull out.

If i insert 1 euro, i will get this result:
8877
If i insert 2 euros, i will get this result:
41092 , 41491
If i insert 5 euros, i will get this result:
96512,96911,97311,97712,98111
//----------------------------------------
Values are allways different but the time between is 395 - 400 ms.
So, how to group this signals, to get correct coin type readings.

So, how to group this signals, to get correct coin type readings.

I'm not understanding why you want to distinguish between types of coins. What difference does it make if I dump a 1 unit coin and two 2 unit coins into the machine vs. dumping one 5 unit coin?

In any case, as you've seen, the time between multiple pulses is relatively consistent.

The next step is to feed two 2 unit coins in as close together as possible, and record t1, t2, t3, and t4.

If t2 - t1 is about 400, and t4 - t3 is about 400, and t3 - t2 is significantly different from 400, then you have an idea how to distinguish a single coin.

If t3 - t2 is also about 400, you're screwed if you absolutely MUST know how many coins were inserted.

@arnix, in the above post #12, it seems like you have successfully counted euros. You know what the timings are. Why is that hard to code?

Maybe am missing something but variable -newCoinInserted - is the counter for last coin that is inserted in coin selector. According to this, program should enter into case 2 when i insert 2 euros, but it doesn't.

How can i count pulses ( on different way ) if i can not define time between coin insertion.
From practical point of view, no one can insert coins so fast (400ms) so do i set some waiting time ?
But then again, how would i know that 1 + 1 = 2 euros and not 1 + 1 Euro.

btw. relay should be triggered at 3 euros.

Maybe am missing something but variable -newCoinInserted - is the counter for last coin that is inserted in coin selector. According to this, program should enter into case 2 when i insert 2 euros, but it doesn't.

newCoinInserted is a lousy name. To me, it suggests that a new coin was inserted.

In any case, it is NOT the counter for the last coin's pulses, because you are NOT counting pulses PER COIN. You are counting total pulses for all coins ever inserted.

According to this, program should enter into case 2 when i insert 2 euros, but it doesn't.

If you reset the Arduino, and insert two 1 euro coins, it should execute the code in case 2. If you reset the Arduino, and insert one 2 euro coin, it should execute the code in case 2.

My question, that you have not answered, is: Do you really care whether one 2 euro coin was inserted vs. two 1 euro coins?

Do you have any links to some documentation about the pulses? It would be easier than trying to follow your ruminations.

Are you sure that changing pulseThreshold to 450 doesn't work? From the data you provided, it really should have.

  1. When you get a pulse, the interrupt runs and sets pulseTime to millis().
  2. The next time through loop(), coinPulseCount will > 0, but (millis() - pulseTime) will be very small.
  3. If you get another pulse within 450ms (pulseThreshold), then the interrupt runs, increments coinPulseCount again, and sets pulseTime to millis() again.
  4. It's only after you haven't gotten an interrupt in over 450ms that the if block will execute, setting the value of newCoinInserted.

From the data you provided, your pulses are 399-401ms apart. Your code looks like it should work, if pulseThreshold is set to 450ms.

@Paul_s
If you reset the Arduino, and insert one 2 euro coin, it should execute the code in case 2.
** If i reset arduino and put 2 euro coin in, i get code from case 1 (new coin - 1 EUR , new coin - 1 EUR )

Do you really care whether one 2 euro coin was inserted vs. two 1 euro coins?
** this is not so important.


@aarg
http://www.crownleisure.co.uk/Documents/Manuals/Alberici/AL05/05ing.pdf

It's not stated in doc file, but impulse length should be 100ms and time between 200ms ( 400 ms in our case )

@BigBobby
I agree with you and am thinking that this should work as you described but it doesn't.
If we can define some time frame then we can bind pulses with inserted coins, but as you pointed out, this should work this way. That's why i need help with code, and a way for defining this time frame.