Arduino controlling coin payout hopper

Hello I'm currently building a penny pusher arcade game for my daughter and as an elaborate saving box!

To be built into it, I'm putting a change machine to swap £1 into 10x10p coins. I've been given a coin hopper - when you connect 12v dc to the hopper it spits out coins. Each time a coin is ejected, it passes an optical sensor which sends a pulse.

My arduino needs to 1. Sense a button has been switched (coin into the machine) 2. Turn on a 12v supply 3. Count 10 pulses for 10 dispensed coins 3. Turn off the 12v supply

I have a few duemilanove boards so ideally I would like to use one of these. However, it has stumped me on two occasions - 1. Turning on a 12v supply and 2. Counting the pulses from the optical sensor.

In honest my electronics is pretty useless so although I appreciate relays will need to be used to turn on the 12v supply from my logic output on the arduino - I know nothing more than that.

Could anyone link me to similar projects that I could copy and modify code from for either of these two issues or ideally give me some specific advice as to the sort of code I'll need for this?

Appreciate your help in advance. Chris

Here is some code I wrote real quick it is untested and may not work but it should provide a outline to work off of.

int CoinButton_pin = 1;
int Relay_pin = 2;
int optical_pin = 3;

int coinCounter = 0; // this is variable used to count the coins until 10

void setup()
{
pinMode(Relay_pin,OUTPUT);
pinMode(CoinButton_pin,INPUT);
pinMode(optical_pin,INPUT);
}

void loop()
{
if (digitalRead(CoinButton_pin) == 1) //assuming the coin button returns HIGH when a coin passes through it
{
digitalWrite(Relay_pin,HIGH);

while(coinCounter < 10)
{

if (digitalRead(optical_pin) == 1) //assuming the optical device returns HIGH when a pulse is sensed
{ 
coinCounter+=1;
}

} //end while loop
coinCounter = 0;
 digitalWrite(Relay_pin,LOW);
} // end the if statment of coin button pressed


} // end void loop

please note this code is untested and may not work.

I would add a timer as a security, to escape the while loop and turn the relay off, if it happens that there are not enough 10p coins in the machine or other potentially blocking situations ;)

Hello, many thanks for your suggestions.
It has taken me a few days to get the arduino board. Ive uploaded the code but something isnt quite right.

I`ve got two buttons attached - one as the coin insert button and one to replicate the pulses sent from the hopper as my ten pulses - i.e pushing the button ten times.

I`ve just changed the code a touch as the relay is active LOW.

However, you don`t have to press the pulse button 10 times, just once and it shuts the relay off! Press coin insert button and it correctly turns the relay on but then just one click of the pulse button and it goes off.

Is this just because I`m trying to use the button to replicate the pulses??

Any help appreciated.

int CoinButton_pin = 2;
int Relay_pin = 13;
int optical_pin = 3;

int coinCounter = 0; // this is variable used to count the coins until 10

void setup()
{
pinMode(Relay_pin,OUTPUT);
pinMode(CoinButton_pin,INPUT);
pinMode(optical_pin,INPUT);
digitalWrite(Relay_pin, LOW);
}

void loop()
{
if (digitalRead(CoinButton_pin) == 1) //assuming the coin button returns HIGH when a coin passes through it
{
digitalWrite(Relay_pin,LOW);

while(coinCounter < 1000)
{

if (digitalRead(optical_pin) == 1) //assuming the optical device returns HIGH when a pulse is sensed
{ 
coinCounter+=1;
}

} //end while loop
coinCounter = 0;
 digitalWrite(Relay_pin, HIGH);
} // end the if statment of coin button pressed


} // end void loop

okay I think I know what is wrong with the code. I added a delay try it now

int CoinButton_pin = 2;
int Relay_pin = 13;
int optical_pin = 3;

int coinCounter = 0; // this is variable used to count the coins until 10

void setup()
{
pinMode(Relay_pin,OUTPUT);
pinMode(CoinButton_pin,INPUT);
pinMode(optical_pin,INPUT);
digitalWrite(Relay_pin, LOW);
}

void loop()
{
if (digitalRead(CoinButton_pin) == 1) //assuming the coin button returns HIGH when a coin passes through it
{
digitalWrite(Relay_pin,LOW);

while(coinCounter < 1000)
{

if (digitalRead(optical_pin) == 1) //assuming the optical device returns HIGH when a pulse is sensed
{ 
coinCounter+=1;
delay(1000);
}

} //end while loop
coinCounter = 0;
 digitalWrite(Relay_pin, HIGH);
} // end the if statment of coin button pressed


} // end void loop

Remember the controller runs very very fast. The loop() function is done many times while you press the button and before you release it. Each time, the "pulse ON" condition is true, and the counter is incremented . If you want to count a number of times a button is pressed, you must enter a condition sequence when it is HIGH, and wait for it to be LOW before you end the sequence.

Edit : I've just read your post..... a delay works, but you don't know if the input went LOW.... if a coin gets stuck in the machine, the counter will still be incremented ;)

Hi guys, I now see what is happening - when I press the button once, it senses multiple pulses.

The delay sort of work but of course messes up if you push the button too quick.

The actual signal from the hopper is a HIGH pulse:

http://youtu.be/KyQjaJj6ABY

Will I experience a similar problem when this is the input or can I then remove the delay and all will be fine?

Chris

I think the answer is in my previous post ;) you don't need a delay, just check the signal goes LOW before you leave the "ON" sequence.

alnath: I think the answer is in my previous post ;) you don't need a delay, just check the signal goes LOW before you leave the "ON" sequence.

Im sorry. Im not very experienced with Arduino - not sure how to check the signal goes low!?

Chris

craynerd:

alnath: I think the answer is in my previous post ;) you don't need a delay, just check the signal goes LOW before you leave the "ON" sequence.

Im sorry. Im not very experienced with Arduino - not sure how to check the signal goes low!?

Chris

Check that it is the opposite of HIGH, for example: if(digitialRead(Pin) == 0){}

The question I have is how fast can a coin fall through the dispenser? From what I understand the dispenser is basically a switch, correct? If so, how fast can the switch be triggered by coins? Can more than one fall through at once? You'll probably want to add some form of debounce (for example a short delay after it detects a high) as if it is a switch, switches tend to rapidly alternate between on and off (bounce) when being pressed until it settles. However, as said before you'd do something where everytime through the loop you first detect if it was HIGH (==1) wait some short delay, set a flag, and then when you go through the loop again, check to see if the switch is now LOW ( == 0 ) before looking for another high again.

The hopper can only dispense one coin at a time but at a fast rate of up to 7 coins each second! Consequently, the 10 coins will be dispensed within 2 seconds!

I posted a video of the hopper and logic probe attached to the optical output a few posts above,

I can see where you are going with this checking the high, low pulse with a short delay... I just can't see how to write it based around the code I posted above.

Any more information, advice or sample code appreciated!

Chris

I must admit I haven’t watched the video yet :wink:

Here is a piece of code, part of it copy/paste of the previous example in this thread.
It is not tested, and written quickly, but it should work :

unsigned long start_time ;
unsigned long critical_time = 500 ; //maybe it is a bit too long ;)
int optical_pin = 3 ;
int coinCounter = 0;
byte flag_alarm = 0 ;    // alarm flag


	while(coinCounter < 10)
	{
		if(digitalRead(optical_pin) == HIGH )
		{
			start_time = millis();
			coinCounter+=1;
			while(digitalRead(optical_pin) == HIGH)
			{
				if((millis() - start_time) >	critical_time) // something is wrong 
				{
					flag_alarm = 1;    // you can use the flag to launch an alarm .....
					break;  // get out of there ;)
				}
			}
		}
	} //end of while loop
	coinCounter = 0;
	digitalWrite(Relay_pin, LOW);
	if(flag_alarm == 1 )
	{
		// alarm or ....
	}

It assumes the relay stays switched ON to launch the 10 coins.
The timer alarm is optional, and you’ll have to change the “interval” value .
edit : and change the type of ‘critical_time’ too … we don’t need an ‘unsigned long’ :wink:

edit 2 : it assumes also that the optical_pin is HIGH then LOW each time a coin is thrown

Hello again

Thanks a lot for your continued help!

Ive tried to put in the new de-bounce code provided by alnath but something still isnt correct. Pressing the tactile switch for “coin in” starts the relay and hopper but then it only dispenses a couple of coins and goes off.

I just want to confirm - I am no longer using a button to replicate the pulses but the actual hopper itself which sends a pulse each coin dispenced. The relay is active LOW.

I am using a standard tactile switch to initiate the hopper into action which momentarily goes HIGH when pressed- this switch replicated a £1 coin entering the machine and initiating the dispensing of coins.

Code so far:

int CoinButton_pin = 2;
int Relay_pin = 13;
int optical_pin = 3;

unsigned long start_time ;
unsigned long critical_time = 500 ; //maybe it is a bit too long ;)
byte flag_alarm = 0 ;    // alarm flag

int coinCounter = 0; // this is variable used to count the coins until 10

void setup()
{
pinMode(Relay_pin,OUTPUT);
pinMode(CoinButton_pin,INPUT);
pinMode(optical_pin,INPUT);
digitalWrite(Relay_pin, HIGH);    //turn off relay on startup
}

void loop()
{

  if (digitalRead(CoinButton_pin) == 1) //Coin inserted - button goes high (currently a push switch)
  {
    digitalWrite(Relay_pin,LOW);    //Turn on relay - active low.

    while(coinCounter < 10)         
	{
		if(digitalRead(optical_pin) == HIGH )       //if the optical pin goes high
		{
			start_time = millis();             
			coinCounter+=1;                    // add one to counter         
			while(digitalRead(optical_pin) == HIGH)    
			{
				if((millis() - start_time) >	critical_time) // something is wrong 
				{
					flag_alarm = 1;    // you can use the flag to launch an alarm .....
					break;  // get out of there ;)
				}
			}
		}
	 } //end of while coin counter loop - i.e 10 coins dispenced

    }  // end of coin button if sttatement
  	                  
    coinCounter = 0;
    digitalWrite(Relay_pin, HIGH);

   if(flag_alarm == 1 )
	{
		// alarm or ....   NOTHING YET BUT I SEE ITS USE
	}

} // end void loop

Any more help would be much appreciated. As I say, pressing the tactile switch starts the hopper but instead on waiting for 10 pulses, it just goes off after a sort delay - 1 or 2 coins being dispensed.

Chris

craynerd:
Hello again

Thanks a lot for your continued help!

Ive tried to put in the new de-bounce code provided by alnath but something still isnt correct. Pressing the tactile switch for “coin in” starts the relay and hopper but then it only dispenses a couple of coins and goes off.

I just want to confirm - I am no longer using a button to replicate the pulses but the actual hopper itself which sends a pulse each coin dispenced. The relay is active LOW.

I am using a standard tactile switch to initiate the hopper into action which momentarily goes HIGH when pressed- this switch replicated a £1 coin entering the machine and initiating the dispensing of coins.

Code so far:

int CoinButton_pin = 2;

int Relay_pin = 13;
int optical_pin = 3;

unsigned long start_time ;
unsigned long critical_time = 500 ; //maybe it is a bit too long :wink:
byte flag_alarm = 0 ;    // alarm flag

int coinCounter = 0; // this is variable used to count the coins until 10

void setup()
{
pinMode(Relay_pin,OUTPUT);
pinMode(CoinButton_pin,INPUT);
pinMode(optical_pin,INPUT);
digitalWrite(Relay_pin, HIGH);    //turn off relay on startup
}

void loop()
{

if (digitalRead(CoinButton_pin) == 1) //Coin inserted - button goes high (currently a push switch)
  {
    digitalWrite(Relay_pin,LOW);    //Turn on relay - active low.

while(coinCounter < 10)         
{
if(digitalRead(optical_pin) == HIGH )       //if the optical pin goes high
{
start_time = millis();             
coinCounter+=1;                    // add one to counter         
while(digitalRead(optical_pin) == HIGH)   
{
if((millis() - start_time) > critical_time) // something is wrong
{
flag_alarm = 1;    // you can use the flag to launch an alarm …
break;  // get out of there :wink:
}
}
}
} //end of while coin counter loop - i.e 10 coins dispenced

}  // end of coin button if sttatement
                   
    coinCounter = 0;
    digitalWrite(Relay_pin, HIGH);

if(flag_alarm == 1 )
{
// alarm or …   NOTHING YET BUT I SEE ITS USE
}

} // end void loop





Any more help would be much appreciated. As I say, pressing the tactile switch starts the hopper but instead on waiting for 10 pulses, it just goes off after a sort delay - 1 or 2 coins being dispensed.

Chris

I do not see anywhere in your code where you are counting the pulses in from the Hopper ? Do you know what it is sending ? i.e. is it just raising a 5v signal or is it a proper pulse signal that you need to capture ?

How have you connected the hopper in ? Just straight into a digital pin ?

I would suggest you remove it to start with an emulate it with a push button until you can get your code right, once you have that you can then introduce the hopper back in.

Craig

Maybe you’ll need to hardware debounce the pulses, if there are several pulses for each coin.

Try this to find out if more than one pulse is sent with each coin :

void loop()
{

  if (digitalRead(CoinButton_pin) == 1) //Coin inserted - button goes high (currently a push switch)
  {
    digitalWrite(Relay_pin,LOW);    //Turn on relay - active low.

    while(coinCounter < 10)         
	{
		if(digitalRead(optical_pin) == HIGH )       //if the optical pin goes high
		{
			start_time = millis();             
			coinCounter+=1;                    // add one to counter         
			while(digitalRead(optical_pin) == HIGH)    
			{
				if((millis() - start_time) >	critical_time) // something is wrong 
				{
					flag_alarm = 1;    // you can use the flag to launch an alarm .....
					break;  // get out of there ;)
				}
			}
		}
	 } //end of while coin counter loop - i.e 10 coins dispenced

    }  // end of coin button if sttatement
    // print the coinCounter value on serial monitor (don't forget the Serial.begin(xxxx); in the setup()  )
    Serial.println(coinCounter);
    if(flag_alarm==0) 	                  // no coinCounter reset if alarm
       coinCounter = 0;
    digitalWrite(Relay_pin, HIGH);

    if(flag_alarm == 1 )
    {
         // print the coinCounter value on serial monitor 
         Serial.print("Alarm -  " );
         Serial.println(coinCounter);
	// alarm or ....   NOTHING YET BUT I SEE ITS USE
    }

} // end void loop

This way, you’ll see how many pulses were actually sent, and if you need a hardware debouncer
or if the timer is too short etc…

Hi Craig - yes it is a just a raised 5v back to low.

I thought this part of the code was counting the input from the hopper:

    while(coinCounter < 10)         
	{
		if(digitalRead(optical_pin) == HIGH )       //if the optical pin goes high
		{
			start_time = millis();             
			coinCounter+=1;

So each time the optical pin goes high it increments the coinCounter variable - when the coin counter greater than 10, it exits the loop, resets the counter and turns off the hopper/relay.

Is this not what happening then in the code?

Chris

alnath - sorry, I missed your post, I think we were posting at the same time.

I`ve never used the serial monitor before so will give this a go in a few minutes. I presumed from my test on the hopper that it was just one pulse each coin ejected:

http://www.youtube.com/watch?v=KyQjaJj6ABY

craynerd:
Hi Craig - yes it is a just a raised 5v back to low.

I thought this part of the code was counting the input from the hopper:

    while(coinCounter < 10)         
{
	if(digitalRead(optical_pin) == HIGH )       //if the optical pin goes high
	{
		start_time = millis();             
		coinCounter+=1;



So each time the optical pin goes high it increments the coinCounter variable - when the coin counter greater than 10, it exits the loop, resets the counter and turns off the hopper/relay.

Is this not what happening then in the code?

Chris

Yes but you will probably need to debounce this - although to you (and in the video) 7 coins a second seems fast to the arduino it is slow and there is a chance that it is not seeing the individual pulses

As stated use the Serial monitor to give you an idea of what is happening - although this will skew your results as it does block when outputting to serial.

The trick here is to get your debounce delay right - too long and you will miss pulses, too short and you will see phantom ones.

Have a look at this code and put it into your system in a counting loop to see how many times and how frequently the pulses are coming

http://arduino.cc/en/Reference/pulseIn

Craig

craigcurtin:

craynerd:
Hi Craig - yes it is a just a raised 5v back to low.

I thought this part of the code was counting the input from the hopper:

    while(coinCounter < 10)         
{
	if(digitalRead(optical_pin) == HIGH )       //if the optical pin goes high
	{
		start_time = millis();             
		coinCounter+=1;



So each time the optical pin goes high it increments the coinCounter variable - when the coin counter greater than 10, it exits the loop, resets the counter and turns off the hopper/relay.

Is this not what happening then in the code?

Chris

Yes but you will probably need to debounce this - although to you (and in the video) 7 coins a second seems fast to the arduino it is slow and there is a chance that it is not seeing the individual pulses

As stated use the Serial monitor to give you an idea of what is happening - although this will skew your results as it does block when outputting to serial.

The trick here is to get your debounce delay right - too long and you will miss pulses, too short and you will see phantom ones.

Have a look at this code and put it into your system in a counting loop to see how many times and how frequently the pulses are coming

http://arduino.cc/en/Reference/pulseIn

Craig

And you may want to jump over a lot of the hoops and look at doing this instead

http://playground.arduino.cc//Main/PinChangeIntExample

Craig

Yes, Craig, you are right, pulseIn() would give informations about the pulse rate, and using interruptions (whith pinChange or even sending pulses on INT0 pin) would be useful if we suspected we missed some pulses. the solution I gave aimed to be a simple one, just to see if the signal on optical_pin needed to be hardware-debounced. The last code I sent doesn't really debounce anything, it just counts each pulse if it comes up before the end of a 'critical delay' ;) BTW, the Serial.print won't affect the counter, it is called only when the while loop is over