Making a coin handling part for my Vending Machine

Hi everyone,

I am doing a Vending Machine project using the Arduino MEGA2560 as the controller board and it accepts 25 cents, 1 dollar, and 2 dollars coins. At the moment, I am struggling with the coin handling compartment. Although I have a general idea of how to build it, I still do not know exactly how to accomplish my idea. Basically, I will build a ramp with an area equal to the thickness of a $2 coin so that when a coin is inserted into the machine, it will roll down the ramp. Then I will use 2 TCRT5000 IR Sensors and install them apart from each other. When the coin rolls down the ramp and block the light of the first IR Sensor, the Arduino will start a Timer and generate pulses as the coin continues to roll down and hit the second sensor. Arduino then stops the Timer and counts how many pulses it generated during the coin rolling down from one sensor to the other. The amount of pulses will determine what type of coin is that.

That was my general idea of how to do that specific task but I do not know how to do it in term of programming. I have watched bunch of videos about Arduino Registers, External Interrupts, Timer Interrupts of Sparkfun as well as other similar posts about those topics but I still could not understand thoroughly of how to start a Timer when the coin hits the first sensor and stop Timer when it hits the second sensor and how to generate and count pulses along the way to determine precisely different types of coins.

If anyone has any ideas or better ways to accomplish this, please respond to this posts. Any helps would be appreciated! Thank you.

If you’ve not ruled out a ready made one, google for:
Arduino coin acceptor

6v6gt:
If you’ve not ruled out a ready made one, google for:
Arduino coin acceptor

Hi 6v6gt,

Thank you for your suggestion. I have already done a little research on that one before and admittedly it would make my life easier if my professor allowed me to use that ready made one. Because this is a final year project for Electronics Engineering Technologist program, he takes this project very seriously in term of building your own project versus buying pieces and simply connect them together. But, I will ask him.

Assuming I have ruled out that read made one, any other ideas of how to accomplish that mentioned task would be appreciated!

Maybe you need just one sensor. The amount of time the sensor is blocked is an indication of the size of the coin.
Simply start a timer when the sensor is first blocked, say:
uint32_t myTimer = millis() ;

When the sensor is no longer blocked, the elapsed time in milliseconds is:
millis() - myTimer;

I would still take a look at how others have solved this- they have been making coin acceptors for maybe 100 years, learn from others even if you build your own, I have seen several pure mechanical coin sorters over at https://www.thingiverse.com/ for 3D printing, maybe sort mechanically then count.

Many engineers get a bit of inspiration from those that have went before, many times improving on what others have done.

6v6gt:
Maybe you need just one sensor. The amount of time the sensor is blocked is an indication of the size of the coin.
Simply start a timer when the sensor is first blocked, say:
uint32_t myTimer = millis() ;

When the sensor is no longer blocked, the elapsed time in milliseconds is:
millis() - myTimer;

I have thought of the same solution as your suggestion but I am still unclear of how to program the Arduino to start a timer when the coin hits the sensor and stop the timer when it already goes past the sensor. Would you have any sample codes to demonstrate that process. It would be extremely appreciated if you could post them here so I could learn something new about this method. Thank you kindly.

saildude:
I would still take a look at how others have solved this- they have been making coin acceptors for maybe 100 years, learn from others even if you build your own, I have seen several pure mechanical coin sorters over at https://www.thingiverse.com/ for 3D printing, maybe sort mechanically then count.

Many engineers get a bit of inspiration from those that have went before, many times improving on what others have done.

Hi saildude,

Initially I tried to build a pure mechanical count sorter by hand using construction papers and scissors and it did not turn out well since it does need the involvement of precise machine cutting or 3D printing which assumably costs more than my available budget. Therefore, I decided to go to the electronic route instead. Definitely I will look into the website you suggested for future references. Thank you for your response.

Any other suggestions or helps would be appreciated!

Look at the state change detection example in the IDE.

When the signal goes LOW (or HIGH, depending on your sensor), record the current value of millis() (or micros() if your coin passes by really fast). When it goes HIGH again, calculate the difference with the then current value of millis().

The first approach is to test the sensor continuously in a loop using digitalRead(). Act on a change.
From no_detection to detection, start the timer as previously indicated. On change from detection to no_detection determine the elapsed time.
The second, more advanced approach, depending on the timing resolution required, is to use interrupts.

But start just by connecting the sensor to the arduino and play with it.
You may find you get more accurate performance in this application by partially covering the sensor to reduce the width of the baem.

I don't know where you are from, but here in the US many schools are adding 3D printing labs for the students. Also here in the US as well I am told Europe groups of people are banding together in "Maker Groups or Labs" for lack of a better term to buy equipment and for a small monthly fee people can get access to the equipment and people who are skilled using the different types of equipment.

I have also seen reference to some public libraries adding 3D printer labs.

So just a heads up to keep your eyes and ears open

Good luck

If there is a significant difference in the diameter of the coins, you could measure the size by measuring how tall the coin is, instead of how long it takes to pass a sensor (which would presumably also require that you measure how fast the coin was traveling). If the coins are conductive, a few finger contacts along the side of the coin path may work, or a line of vertical narrow optical sensors.

If you are not going to use interrupts, then an additional sensor to detect coin insertion would probably be a good idea, to give the code time to get into the size detection routine before the coin initially reaches the sensors.

wvmarle:
Look at the state change detection example in the IDE.

When the signal goes LOW (or HIGH, depending on your sensor), record the current value of millis() (or micros() if your coin passes by really fast). When it goes HIGH again, calculate the difference with the then current value of millis().

Hi wvmarle,

Thank you for your suggestion. I will try using millis() or micros() commands since I have never used them before.

6v6gt:
The first approach is to test the sensor continuously in a loop using digitalRead(). Act on a change.
From no_detection to detection, start the timer as previously indicated. On change from detection to no_detection determine the elapsed time.
The second, more advanced approach, depending on the timing resolution required, is to use interrupts.

But start just by connecting the sensor to the arduino and play with it.
You may find you get more accurate performance in this application by partially covering the sensor to reduce the width of the baem.

Thank you for giving me more details in programming the task. I will try playing around with those commands and probably approaching the more advanced method as using interrupts as you mentioned.

saildude:
I don't know where you are from, but here in the US many schools are adding 3D printing labs for the students. Also here in the US as well I am told Europe groups of people are banding together in "Maker Groups or Labs" for lack of a better term to buy equipment and for a small monthly fee people can get access to the equipment and people who are skilled using the different types of equipment.

I have also seen reference to some public libraries adding 3D printer labs.

So just a heads up to keep your eyes and ears open

Good luck

Thank you saildude. I believe there are only a few numbers of 3D printers in my school and they are used by faculties most of the time to create more testing equipment for Robotics students. So, I need to wait in line for long to have access to one of their machines since the printers are always busy. But I will keep my eyes and ears open as you suggested.

david_2018:
If there is a significant difference in the diameter of the coins, you could measure the size by measuring how tall the coin is, instead of how long it takes to pass a sensor (which would presumably also require that you measure how fast the coin was traveling). If the coins are conductive, a few finger contacts along the side of the coin path may work, or a line of vertical narrow optical sensors.

If you are not going to use interrupts, then an additional sensor to detect coin insertion would probably be a good idea, to give the code time to get into the size detection routine before the coin initially reaches the sensors.

Hi david_2018,

Thank you for your suggestion. There is a slightly difference in diameter of 25 cents coin in comparison to 1 dollar and 2 dollars coin but not so much between 1 dollar coin and 2 dollars coin. Is there any particular sensors that could actually read the size of the coin precisely? If so, could you please let me know its name and the website that sells it?

Any other suggestions or ideas would be greatly appreciated!

Just out of curiosity, which country's currency are you using?

david_2018:
Just out of curiosity, which country's currency are you using?

I am using Canadian currency.

maxkeeblehcm:
I am using Canadian currency.

Ah, ok. Then looks like the following dimensions:
25 cents = 23.88mm
1 dollar = 26.5 mm (note this is the thickest coin, at 1.95mm)
2 dollars = 28 mm

There seems to be quite a variety in the metal content over the years, and some size differences if you go back far enough.

Hi everyone,

I want to make a quick update on my progress of programming this task. I have been spending hours on learning and trying out the Direct Registers Access and External Interrupts codes and I started to understand quite a bit of how to use and manipulate them. Here are the codes that I tried to applied:

// Pins
const uint8_t sensor1 = 2;
const uint8_t analog_sensor1 = A0;
const uint8_t sensor2 = 3;
const uint8_t analog_sensor2 = A1;
const uint8_t led = 5;

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

  // disable global interrupt 
  cli();
  
  // Set 2 sensors pin to be input
  PORTD |= (1 << sensor1);
  PORTD |= (1 << sensor2);

  // Set LED pin to be output
  DDRD |= (1 << led);

  // Condidition (Low level) of INT0 generates interrupt
  EICRA &= ~(1 << ISC01);
  EICRA &= ~(1 << ISC00);

  // Condition (Low level) of INT1 generates interrupt
  EICRA &= ~(1 << ISC10);
  EICRA &= ~(1 << ISC11);

  // Enable interrupts for INT0 and INT1
  EIMSK |= (1 << INT0);
  EIMSK |= (1 << INT1);

  //Enable global interrupts
  sei();
}

void loop() 
{
  // Pretend doing something
  delay(500);
}

ISR(INT0_vect)
{
  Serial.print("Analog Sensor 1 = ");
  Serial.print(analog_sensor1);
  Serial.println();

  PORTD |= (1 << led);
}

ISR(INT1_vect)
{
  Serial.print("Analog Sensor 2 = ");
  Serial.print(analog_sensor2);
  Serial.println();

  PORTD &= ~(1 << led);
}

This code basically turned on and off an LED if the 2 sensors detected a coin presence and it worked as expected. I also tried reading the Analog Value of 2 sensors to see if I could use something out of those values. My next attempt for tomorrow will be adding a timer to the codes in order to get the "start_timer" when it hits the first sensor and get the "stop_timer" when it hits the second sensor. Then, the "elapsed_time" will be determined by subtracting "start_timer" from "stop_timer".

I also have another thought of generating pulses when the coin hits the first sensor and stopping generating pulses when it hits the second sensor. Depending on how many pulses got generated during its travel time will determine the size of that coin. Would it guarantee better accuracy in detecting coin sizes? I would love to hear everyone's opinions on that method. Please let me know if it is possible to program such an idea.

Also, does Timer Interrupt play any roles in determining precisely how many pulses generated over a period of time. If so, could you please give me some ideas of how to accomplish it by using Timer Interrupt?

Thank you for all your time and effort in responding to my post!

Impressive! You really go it the hard way. Direct register calls are not necessary in this application; I rarely use them myself, only when really needed.

You could also use the following command for the interrupt:

attachInterrupt(digitalPinToInterrupt(sensor1), FALLING);

Much easier than those register calls.

But there are other things you go terribly wrong: you're using print statements in your ISR. That's bad. Nowadays this does work, but Serial requires interrupts, which are disabled when you're inside an ISR. Furthermore those print statements don't do anything useful: they just show the pin number of the analog pin.

You probably want to do an analogRead() on those pins to get the current value - a function which itself may or may not work in an ISR, I don't know how it's implemented. The ADC itself also uses interrupts, to signal a reading is ready.

Polling the pins will be fast enough for your coin acceptor. No need for interrupts or direct port manipulation.

Finally, I'm sure you can come up with better names than "analog_sensor1" for the pins.

Direct port instructions are not needed in setup, and make the code harder to read. It is understandable to use direct port manipulation in the interrupt service routines, because it is generally better to have an ISR be as fast as possible, but then you completely negate the savings by doing an analog read and a print. Much better to set a flag and do those in the main code.

I also have another thought of generating pulses when the coin hits the first sensor and stopping generating pulses when it hits the second sensor. Depending on how many pulses got generated during its travel time will determine the size of that coin. Would it guarantee better accuracy in detecting coin sizes? I would love to hear everyone's opinions on that method.

I don't really see how generating pulses and counting them would play any part. Seems like a lot of extra code to set up a pulse generator, then more code to count pulses. I would think the micros() function would be fast enough, but if not then one of the internal counters could be used.

You would probably get higher accuracy if you used the time interval between the two sensors to determine the velocity of the coin, and the time it takes to pass the 2nd sensor to do the width measurement. Don't assume the coin will always be traveling at the same velocity, unless you have a mechanism to guarantee that. The ISR for the first sensor could record the time the coin reaches the sensor, then the ISR for the 2nd sensor could record the time the coin reaches the sensor and the time it leaves, and set a flag letting the main code know it had completed detecting a coin. As others have pointed out, I'm not sure if you even need the speed of an ISR, the times intervals involved are not that short, but it depends on what else you will be doing in the code.

wvmarle:
Impressive! You really go it the hard way. Direct register calls are not necessary in this application; I rarely use them myself, only when really needed.

You could also use the following command for the interrupt:

attachInterrupt(digitalPinToInterrupt(sensor1), FALLING);

Much easier than those register calls.

But there are other things you go terribly wrong: you're using print statements in your ISR. That's bad. Nowadays this does work, but Serial requires interrupts, which are disabled when you're inside an ISR. Furthermore those print statements don't do anything useful: they just show the pin number of the analog pin.

You probably want to do an analogRead() on those pins to get the current value - a function which itself may or may not work in an ISR, I don't know how it's implemented. The ADC itself also uses interrupts, to signal a reading is ready.

Polling the pins will be fast enough for your coin acceptor. No need for interrupts or direct port manipulation.

Finally, I'm sure you can come up with better names than "analog_sensor1" for the pins.

Thank you for pointing out my mistakes in coding. There are still many unintentional errors that I have surely made without noticing and I will come up with better names for those variables. I have also applied the interrupt command that you mentioned but I just wanted to learn a little bit about using direct port manipulation and direct register call. I guess it is not necessary for this application since it will make it harder to read and debug the codes.

By the way, when you mentioned about "Polling the pins", is it an electronic terminology? What does it mean exactly if you would not mind me asking because I did not fully understand the term.

david_2018:
Direct port instructions are not needed in setup, and make the code harder to read. It is understandable to use direct port manipulation in the interrupt service routines, because it is generally better to have an ISR be as fast as possible, but then you completely negate the savings by doing an analog read and a print. Much better to set a flag and do those in the main code.
I don't really see how generating pulses and counting them would play any part. Seems like a lot of extra code to set up a pulse generator, then more code to count pulses. I would think the micros() function would be fast enough, but if not then one of the internal counters could be used.

You would probably get higher accuracy if you used the time interval between the two sensors to determine the velocity of the coin, and the time it takes to pass the 2nd sensor to do the width measurement. Don't assume the coin will always be traveling at the same velocity, unless you have a mechanism to guarantee that. The ISR for the first sensor could record the time the coin reaches the sensor, then the ISR for the 2nd sensor could record the time the coin reaches the sensor and the time it leaves, and set a flag letting the main code know it had completed detecting a coin. As others have pointed out, I'm not sure if you even need the speed of an ISR, the times intervals involved are not that short, but it depends on what else you will be doing in the code.

Thank you kindly for your suggestion and opinions on generating pulses. I will try setting up a flag variable to keep track of the process and micros() function to better the timing accuracy. I am having almost the same approach to the solution as you suggested in the last paragraph.

Also, would the data type of the variable "flag" be volatile or uint8_t and that "flag" could also help with resetting the millis() function because I do not really want the millis() function to keep going and taking up memories if that is how I understand the function works correctly?

maxkeeblehcm:
By the way, when you mentioned about "Polling the pins", is it an electronic terminology? What does it mean exactly if you would not mind me asking because I did not fully understand the term.

Just check the state every time loop() runs. Should be a couple thousand times a second or even more.

Hi everyone,

Just a quick update on what I have done with the coin detector programming so far. Basically, the way my program works is that when a coin hit the first sensor, it will start Timer 1 and as soon as the coin hits the second sensor, it will stop Timer 2 and calculate the Time Interval by subtracting Timer 1 from Timer 2. I am not adding the ISR in the program now because I just wanted to test it out first then if it works as expected, I will add the ISR to make it more efficiently. I am not sure if I am approaching the task in the right way so anyone please have a look at my codes and give me some feedback. This is the code:

// Pins
const uint8_t   sensor1 = 2;
const uint8_t   analog_sensor1 = A0;
uint16_t  analog_reading1;
const uint8_t   sensor2 = 3;
const uint8_t   analog_sensor2 = A1;
uint16_t  analog_reading2;
const uint8_t   led = 5;

// Timers
uint32_t timer1 = 0;
uint32_t timer2 = 0;
uint32_t elapsed_time = 0;

void setup() {
  Serial.begin(9600);
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

void loop() 
{
  if(digitalRead(sensor1) == LOW)
  {
    analog_reading1 = analogRead(analog_sensor1);
    Serial.print("Analog Sensor 1 = "); // Display analog value of sensor 1 
    Serial.print(analog_reading1);
    Serial.println();
    digitalWrite(led, HIGH);
    
    timer1 = millis();  // Start timer 1 
    
    Serial.print("Timer 1 = "); // Display value of Timer 1
    Serial.print(timer1);
    Serial.println();
  }

  else if(digitalRead(sensor2) == LOW)
  {
    analog_reading2 = analogRead(analog_sensor2);    
    Serial.print("Analog Sensor 2 = "); // Display analog value of sensor 2
    Serial.print(analog_reading2);
    Serial.println();
    digitalWrite(led, LOW);
    
    timer2 = millis();  // Start timer 2

    Serial.print("Timer 2 = "); // Display value of Timer 2
    Serial.print(timer2);
    Serial.println();

    elapsed_time = timer2 - timer1; // Time interval of a coin
    Serial.print(elapsed_time);
    Serial.println();
  }
  
  delay(80);
}

I have also done a little research on millis() overflow and how to prevent it. Is it really an important thing that I need to concern about? Would it affect the accuracy in detecting different types of coins?

At the moment, I am building a mechanism to put my circuit and program to test. Hopefully it will work as expected. Also, I am working on the metal detecting part which helps me to distinguish between a conductive material made of coin and a non-conductive material (fake coin, a piece of plastic with a same size of a coin for example). I have found this turorial on Instructables website: https://www.instructables.com/id/Simple-Arduino-Metal-Detector/ but I do not quite understand the author's program nor the circuit diagram.

Anyone who have experience in making or programming this Arduino Metal Dectector please give me a simple explanation of the circuit diagram and the program.

Thank you everyone for putting time and effort in participating in this thread!