Counting pulses -> switch case

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 )

I would recommend that you stop copying the pulse count variable's content. If you are trying to determine the value of all coins inserted, then the number of pulses PER COIN is irrelevant.

arnix: @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.

Trying changing it to:

#define pulseThreshold 450 // for alberichi coin sorter

Sorry I didn't notice that before.

If you are trying to determine the value of all coins inserted, then the number of pulses PER COIN is irrelevant.** Can you help me out to code this ?

@BigBobby it's set to 450, the posted code has the old value..

arnix:
@BigBobby
it’s set to 450, the posted code has the old value…

Did you notice that I changed your “byte” to a “#define”? The problem when you just changed the number to 450 was that it doesn’t fit into a byte. Unless you set “File->Preferences->Compiler Warnings->All,” you wouldn’t see the warning generated by trying to initialize a byte to 450.

Here is the code with the byte changed to a #define, using the test data you posted to simulate your interrupt:

#include "Arduino.h"

//#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.
//***************************
#define pulseThreshold 450 // for alberichi coin sorter
//***************************
void setup()
{
  Serial.begin(9600);
  //lcd.begin(16, 2);
  pinMode (2,INPUT_PULLUP);
  // simulate this -> attachInterrupt(0, coinacceptor, FALLING);
}

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

  simulate_coinacceptor();

  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 5:
         Serial.println("5 EUR");
         newCoinInserted = 0;
         break;
      }
}

//*****Simulate INTERUPT for coin pulse ****************

uint32_t test_millis[] = {8877,                                // 1 EUR
                          41092, 41491,                        // 2 EUR
                          96512, 96911, 97311, 97712, 98111};  // 5 EUR
uint8_t test_idx = 0;

void simulate_coinacceptor()
{
  // When millis() is the time you saw in your test data, act like I received a pulse.
  if(millis() == test_millis[test_idx])
  {
    // coinacceptor() funcion
    coinPulseCount++;
    pulseTime = test_millis[test_idx];

    // increment index
    if(test_idx < (sizeof(test_millis)/sizeof(*test_millis) - 1))
      test_idx++;
    else
      test_idx = 0;
  }
}

This is the output (with your case 3 changed to a case 5):

New coin 1 EUR
New coin 2 EUR
New coin 5 EUR

You say you got this code as an example? I’ve never made a vending machine, but I imagine it’s common for the microprocessor to keep track of how many coins it’s received of each type. The coin sorter only has so much space for each so it’d be useful for the micro to know when it’s almost full for one type.

Your variable newCoinInserted might be clearer as an enum, as that’s how it’s used in the code. It’s not the first code, however, that didn’t want to use an enum to set EUR1 = 1, EUR2 = 2, and EUR5 = 5.

The simulation part is working OK. So you are suggesting that there was a problem in variable definition ? If so, can i comment the simulation part out and try if this will work with real coins ?

arnix: The simulation part is working OK. So you are suggesting that there was a problem in variable definition ? If so, can i comment the simulation part out and try if this will work with real coins ?

Yes, when you tried setting the variable to 450 you needed a type that is larger than a byte.

The simplest thing, however, is to just #define it so that you don't have to worry about what type is needed to hold the value.

Yes, if you comment out the simulation part and put your interrupt handler back, it should work as you expect. Alternatively, you could just change your code to #define pulseThreshold as 450 (and change your case for EUR5 to 5 instead of 3).

Hell yea ! :-)

I want firstly thank to everybody involved on this topic ( and alnath from - general electronics subforum ). This topic is solved by suggestion from BigBobby and mistake was really stupid one :-) As mentioned before pulseThreshold 450 variable should be changed to #define pulseThreshold 450.

@BigBobby This code was form one other poster. It was not a sample from manufacturer. I work with coin machines and such stuff for some time now and if you are in Europe then you should go with Comestero or Alberichi coin products. Those are two main brands and really reliable ones. Lately they all go on CCTALK protocol and this is quite good solution because you can pull out bunch of usefull data.

OK. I will update the code for my needs. Thank you all once again !

I made one PCB that is connected directly to arduino MEGA board.
In this “development process” i changed the COIN pin position from 2 to 32.

According to this i can not use attachInterrupt(0, coinacceptor, FALLING) any more.
How should i change this code to fit arduino mega board and this new change?

How should i change this code to fit arduino mega board and this new change?

You changed the pin from one that handles external interrupts to one that does not. No amount of hoping is going to enable code that relies on external interrupts to work when the external interrupts quit happening.

Hi to all. The project with coin selector is working quite good but i run into one weird situation. The problem is completely HW based but it can be solved with SW change.

Situation: When there is AC spike ( power problems etc. ), coin selector somehow reads impulse and this is processed like coin insertion ( eg. one EUR ). To solve this with SW, i have to define one variable that will have range from 100 - 450 ms and everything inside this range can be accepted as coin. The rest should be "disabled".

How to make this ? How to scan this ms range ?

Code --> post 23

Arnix

arnix: Situation: When there is AC spike ( power problems etc. ), coin selector somehow reads impulse and this is processed like coin insertion ( eg. one EUR ). To solve this with SW, i have to define one variable that will have range from 100 - 450 ms and everything inside this range can be accepted as coin. The rest should be "disabled".

You're saying you only want to accept pulses that occur within a 100-450ms window? What even starts this window? How do you know that you won't get electrical noise during this period?

I dont know. But its very small possibility that something happens in this time. The electrical spike last longer and i will add additional HW to prevent such situations, but it may happen.

If it happens i want to be ready :-)

It seems a better plan might be to verify the pulse has a minimum width for you to recognize it as a pulse?

Your electrical noise probably results in glitches that are on the order microseconds. The pulses from your coin counter are likely milliseconds.

If you improve your interrupt so that it only counts pulses that are larger than a specified amount it would be a more effective way to deal with this noise.

If you improve your interrupt so that it only counts pulses that are larger than a specified amount it would be a more effective way to deal with this noise.

** How can i "improve " it. ? Sorry am not following you in this part.

From your earlier posts it looks like the pulses are 100ms wide?

I mean to improve it by doing something like this:

#define COIN_PIN         2
#define MIN_PULSE_WIDTH  50

volatile byte           coinPulseCount=0;     // a counter to see how many times the pin has changed - which coin inserted
volatile unsigned long  pulseTime;            // this stores the time of the last pulse.
unsigned long  tempTime;                      // this stores the time of the rising edge of the last pulse.
boolean waitForFall = false;                  // this stores if we have previously received a rising edge and we're now looking for a falling edge.

void setup()
{
  Serial.begin(9600);
  pinMode (COIN_PIN, INPUT_PULLUP);
  attachInterrupt(0, coinacceptor, FALLING);
}

void loop()
{

}

//*****INTERUPT for coin pulse ****************
void coinacceptor()
{
  unsigned long new_time = millis();

  // If this is a rising edge, record the time to see how long the pulse is
  if(digitalRead(COIN_PIN))
  {
    waitForFall = true;
    tempTime = new_time;
  }
  // If this is a falling edge, check if the pulse width is above a minimum amount to filter out noise spikes.
  else if(waitForFall && (new_time - tempTime > MIN_PULSE_WIDTH))
  {
    coinPulseCount++;
    pulseTime = new_time;
    waitForFall = false;
  }
}