Coin Hopper Problem

When i insert any bill, always dispensing 5 coins.

I inserted 20 bill = 4 coins, still dispensing 5 coins
When I inserted 50 bill = 10 coins, still dispensing 5 coins
And when I inserted 100 = 20 coins, still dispensing 5 coins

Need help what is the problem with my code

//**************Variables ****************
volatile byte hopperPulseCount = 0;  // a counter to track the number of coins dispensed
volatile unsigned long pulseTime;  // stores the time of the last pulse
int coinValue = 0;      // number of 10 pence coins to dispense based on bill value

//***********************************************************************************************

//************Pins Used *******************
int hopperPin = 2;  // pin2 as optical count input 
int billAcceptorPin = 3;  // pin3 as bill acceptor input
int relayPin = 7;  // pin7 output relay

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

  //**** pinModes *************
  pinMode(hopperPin, INPUT_PULLUP);       // hopper optical count is an input
  pinMode(billAcceptorPin, INPUT_PULLUP); // bill acceptor input
  pinMode (relayPin, OUTPUT);      // relay pin output
  digitalWrite(relayPin, HIGH);   // turn off relay - active LOW.
  digitalWrite(hopperPin, HIGH); // use the internal pullup resistor on the hopper optical input  

  attachInterrupt(0, hopper, FALLING); // Hopper - attach a PinChange Interrupt to our pin on the falling edge - link to hopper function
}

void loop()
{  
  // Check for bill insertion signal from the bill acceptor
  if (digitalRead(billAcceptorPin) == HIGH)  
  {
    // Read the number of pulses from the bill acceptor
    int pulses = countPulses();

    // Determine the coin value based on the number of pulses
    coinValue = calculateCoinValue(pulses);

    // Process the coin value and dispense coins
    dispense(coinValue);
  }
}

//******INTERRUPT detecting pulses from the hopper
void hopper()           //function called when a coin is ejected from the hopper
{
  hopperPulseCount++;
}

int countPulses() {
  int pulses = 0;
  unsigned long startTime = millis(); // Start time for timeout

  // Wait for the pulse to start
  while (digitalRead(billAcceptorPin) == LOW) {
    if (millis() - startTime > 1000) { // Timeout after 1 second
      return 0; // No pulse detected
    }
  }

  // Count the pulses while the signal is high
  while (digitalRead(billAcceptorPin) == HIGH) {
    pulses++;
    delay(10); // Adjust delay as needed based on the pulse duration
  }

  return pulses;
}


int calculateCoinValue(int pulses) {
  // Determine the coin value based on the number of pulses
  switch (pulses) {
    case 2:
      return 20; // 20 pence coins
    case 5:
      return 50; // 50 pence coins
    case 10:
      return 100; // 100 pence coins
    default:
      return 0; // Unknown or unsupported number of pulses
  }
}

void dispense(int coinsToDispense)
{
  digitalWrite(relayPin, LOW);   // turn on relay - active LOW.
  delay(50);  
  hopperPulseCount = 0;

  while (hopperPulseCount < coinsToDispense / 10)     
  {
    // Wait until the required number of coins are dispensed
  }
  
  delay(50);    // wait to ensure the coin has enough momentum to leave hopper but not long enough for another coins to dispense!
  digitalWrite(relayPin, HIGH);   // turn off relay - active LOW.  
}

still had no idea, the printing in pulse reaches 1000+ when i insert a bill

Can you help me with my code or suggest what should I do.

You don't want to be checking for when the pin is high, you need to check for it changing from low to high.

Do you see the difference?

Use the techniques shown in the Arduino IDE example "StateChangeDetection".

like this?

17:18:53.904 -> Number of pulses detected: 2119

17:19:17.220 -> Number of pulses detected: 2224

17:19:34.495 -> Number of pulses detected: 1623

17:19:35.579 -> Number of pulses detected: 6

17:20:09.886 -> Number of pulses detected: 3320

No, I meant can you see the difference between the following two situations:
State Change Detection

Here's a sample of code that shows how you can count pulses from a bill acceptor.
It is based on the techniques introduced in the "StateChangeDetection" example.

You would have to add the part to dispense the coins.

I've tested it with a range of pulses from 1Hz to 100Hz.


int billAcceptorPin = 3;

int billAcceptorPinState = LOW;
int lastBillAcceptorPinState = LOW;

int credit = 0;
int baseUnit = 5; // Number of £/€/$ per pulse

void setup() {
  Serial.begin(9600);
}

void loop() {
  billAcceptorPinState = digitalRead(billAcceptorPin);
  if (billAcceptorPinState != lastBillAcceptorPinState)  {
    if (billAcceptorPinState == HIGH) {
      credit = credit + baseUnit;
      Serial.println(credit);
    }
  }
  lastBillAcceptorPinState = billAcceptorPinState;
}
  • Channel 1 - Pulses from Bill Acceptor.
  • Channel 2 - Serial output.

20 pulses x base unit of 5 counts up to 100:
Screenshot 2024-03-27 162010

i think my wirings in bill acceptor is wrong

my bill acceptor is a tb74

image

what i did was i combine the yellow,green,orage, and purple

i cant get a accurate pulse, should i rewire it? help pls

or maybe i need help setting up the tb74 bill acceptor

this is the current pulses i got,

Pulse/Signal

20 bill = 2 pulse
50 bill = 5 pulse
100 bill = 10 pulse

how do i change the tb74 to make the pulse into
20 bill = 4 pulse
50 bill = 10 pulse
100 bill = 20 pulse

this is my latest code now, but the pulse/signal still the same like this
20 bill = 2 pulse
50 bill = 5 pulse
100 bill = 10 pulse

how do i change the code to fix the pulse into like this
20 bill = 4 pulse
50 bill = 10 pulse
100 bill = 20 pulse

//**************Variables ****************
volatile byte hopperPulseCount = 0;  // a counter to track the number of coins dispensed
volatile unsigned long pulseTime;  // stores the time of the last pulse
int coinValue = 0;      // number of 10 pence coins to dispense based on bill value
volatile int totalPulses = 0; // Variable to store the total pulses detected

//***********************************************************************************************

//************Pins Used *******************
int hopperPin = 2;  // pin2 as optical count input 
int billAcceptorPin = 3;  // pin3 as bill acceptor input
int relayPin = 7;  // pin7 output relay
volatile bool pulseDetected = false; // Flag to indicate pulse detection

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

  //**** pinModes *************
  pinMode(hopperPin, INPUT_PULLUP);       // hopper optical count is an input
  pinMode(billAcceptorPin, INPUT_PULLUP); // bill acceptor input
  pinMode (relayPin, OUTPUT);      // relay pin output
  digitalWrite(relayPin, HIGH);   // turn off relay - active LOW.
  digitalWrite(hopperPin, HIGH); // use the internal pullup resistor on the hopper optical input  

  attachInterrupt(0, hopper, FALLING); // Hopper - attach a PinChange Interrupt to our pin on the falling edge - link to hopper function
  attachInterrupt(digitalPinToInterrupt(billAcceptorPin), handlePulse, FALLING); // Attach interrupt on falling edge
}


void loop() {
  // Check for bill insertion signal from the bill acceptor
  if (digitalRead(billAcceptorPin) == HIGH)  
  {
    // Wait for pulse detection
    while (!pulseDetected) {
      // Wait for the interrupt to set the flag
    }
    pulseDetected = false; // Reset the flag
    
    // Read the number of pulses from the bill acceptor
    int pulses = hopperPulseCount;

    // Update the total pulses detected
    totalPulses += pulses;

    // Print the total pulses detected
    Serial.print("Pulses detected: ");
    Serial.println(totalPulses);

    // Determine the coin value based on the number of pulses
    coinValue = calculateCoinValue(totalPulses);

    // Process the coin value and dispense coins
    dispense(coinValue);
  }
}

//******INTERRUPT detecting pulses from the hopper
void hopper()           //function called when a coin is ejected from the hopper
{
  hopperPulseCount++;
}

void handlePulse() {
  hopperPulseCount++; // Increment pulse count
  pulseDetected = true; // Set the flag to indicate pulse detection
}

int countPulses() {
  unsigned long startTime = millis(); // Start time for timeout
  while (!pulseDetected) {
    if (millis() - startTime > 1000) { // Timeout after 1 second
      return 0; // No pulse detected
    }
  }
  int pulses = hopperPulseCount;
  hopperPulseCount = 0; // Reset pulse count
  pulseDetected = false; // Reset pulse detection flag
  return pulses;
}


int calculateCoinValue(int pulses) {
  // Determine the coin value based on the number of pulses
  switch (pulses) {
    case 2:
      return 20; // 20 peso coins
    case 5:
      return 50; // 50 peso coins
    case 10:
      return 100; // 100 peso coins
    default:
      return 0; // Unknown or unsupported number of pulses
  }
}

void dispense(int coinsToDispense)
{
  digitalWrite(relayPin, LOW);   // turn on relay - active LOW.
  hopperPulseCount = 0;

  while (hopperPulseCount < coinsToDispense / 10)     
  {
    // Wait until the required number of coins are dispensed
  }
    // wait to ensure the coin has enough momentum to leave hopper but not long enough for another coins to dispense!
  digitalWrite(relayPin, HIGH);   // turn off relay - active LOW.  

  // Introduce a small delay to allow the hopper motor to settle
  //delay(100); // Adjust this delay as needed
}

In the code that I posted in reply #11, I missed out an important line from setup():

 pinMode(billAcceptorPin, INPUT_PULLUP);

The code worked for me, because I was supplying pulses from a function generator, as I do not have a bill acceptor.

Your bill acceptor needs a pullup resistor:
TB74 Pulse Interface

I think that you need to alter the DIP switches.

Change SW3 to on?

Different versions of the DIP settings can be found for other currencies at:
http://www.topvme.com/index.php/en/pi-en/ba-en/tb74 on the download tab.

I wasn't sure what your currency was, I see that 'pence' in the comments in the code in post #1 has now been changed to 'peso' in post #16.

Yes, i change that and now Im using a peso coin

I tried to change the code to multiply it by 2, but it doesnt work. I am not a good programmer in arduino.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.