Making a coin handling part for my Vending Machine

maxkeeblehcm:
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.

What happens if a small coin travels more slowly and thus blocks the sensor long enough to be seen as a larger coin?

When does timer 2 start?

Your description is a bit confusing, timer1 and timer2 are variables to hold the value of millis() at the time the coin triggers the sensors, they are not timers that you are starting and/or stopping.

There is no reason for you to be concerned with millis() overflow, your calculation of the time interval as timer2 - timer1 will be correct unless you are expecting the coin to take a bit over 49 days to travel between sensors. The problem with overflow isn't that the value of millis() will reach the maximum value for an unsigned 32-bit integer and wrap around to zero, but that the time interval will exceed the number of milliseconds that can be represented by an unsigned 32-bit integer. If the number wraps around to zero during the measurement interval, because of the way math with unsigned integers works, the calculation will still give you an accurate difference between timer1 and timer2.

You might want to consider using micros() instead of millis() for better accuracy, the overflow time for micros() is only 70 minutes, but again no problem with your application.

dougp:
What happens if a small coin travels more slowly and thus blocks the sensor long enough to be seen as a larger coin?

When does timer 2 start?

Hi dougp,

There was actually no timer 2. My description was a little confusing to understand. My apologies.

There are 2 sensors to record the time at the moments a coin goes past sensors. I called them T1 and T2. The first sensor records T1 and second sensor records T2. After recording T1 and T2, I subtract T1 from T2 to find the time interval of that coin. Different types of coins give out different time intervals as I have tested them out. But you were right about the mistaking types of coins says the $1 if travels fast enough will get detected as $2 since their diameters are slightly different. Although I have improved my codes a little bit, that problem still some times appears.

Thank you for your questions and if you have any advice on that, please let me know.

david_2018:
Your description is a bit confusing, timer1 and timer2 are variables to hold the value of millis() at the time the coin triggers the sensors, they are not timers that you are starting and/or stopping.

There is no reason for you to be concerned with millis() overflow, your calculation of the time interval as timer2 - timer1 will be correct unless you are expecting the coin to take a bit over 49 days to travel between sensors. The problem with overflow isn't that the value of millis() will reach the maximum value for an unsigned 32-bit integer and wrap around to zero, but that the time interval will exceed the number of milliseconds that can be represented by an unsigned 32-bit integer. If the number wraps around to zero during the measurement interval, because of the way math with unsigned integers works, the calculation will still give you an accurate difference between timer1 and timer2.

You might want to consider using micros() instead of millis() for better accuracy, the overflow time for micros() is only 70 minutes, but again no problem with your application.

Hi david_2018,

Thank you for explaining the overflow concern. My apologies on the confusing description. I have already change those variable names to something more meaningful. I have also used micros() as you suggested for better accuracy and it worked very well. I will post my follow-up codes and please have a look at it.

Hi everyone,

I am doing a quick update on my programming progress. I was able to figure the Timer Intervals of 3 different types of coins and wrote some codes for them. There was also an “Undetected Coin” part where the Time Interval was outside of those ranges as specified in the comments. Here is the code:

// Pins
const uint8_t   sensor_start = 2;
const uint8_t   sensor_stop = 3;
const uint8_t   led_start = 5;
const uint8_t   led_stop = 6;

// Timers
uint32_t current_time = 0;
uint32_t T1 = 0;
uint32_t T2 = 0;
uint32_t elapsed_time = 0;

// Global variable ISRs checking 
uint8_t flag = 0;

void setup() 
{
  // Set up INPUTS and OUTPUTS
  Serial.begin(9600);
  pinMode(sensor_start, INPUT);
  pinMode(sensor_stop, INPUT);
  pinMode(led_start, OUTPUT);
  pinMode(led_stop, OUTPUT);
  digitalWrite(led_start, LOW);
  digitalWrite(led_stop, LOW);
  
  // Enable ISR when condition met
  attachInterrupt(digitalPinToInterrupt(sensor_start), Start_Timer, LOW);
  attachInterrupt(digitalPinToInterrupt(sensor_stop), Stop_Timer, LOW);
}

void loop() 
{  
  if(flag == 1)
  {
    digitalWrite(led_stop, LOW);  // Red LED indicates that coin went past 2nd sensor
    digitalWrite(led_start, HIGH);  // Green LED indicates that coin went past 1st sensor
    
    current_time = micros();  // Mark the time the coin hits the 1st sensor 
    T1 = current_time;  // Store current time to T1 
          
    delay(100);  
  }

  else if(flag == 2)
  {
    digitalWrite(led_start, LOW);
    digitalWrite(led_stop, HIGH);

    current_time = micros();  // Mark the time the coin hits the 2nd sensor
    T2 = current_time;  // Store current time to T2
    
    elapsed_time = T2 - T1; // Time interval of a coin

    Coin_Detector();  //Jump to Coin_Detector code
    
    delay(200);
  }  

  flag = 0;
  delay(100);
}

void Coin_Detector()
{
  // If time interval of 25cents is between 48799us and 60000us
  if ((48799 < elapsed_time) && (elapsed_time < 60000))  
  {
    Serial.print("You have inserted 25cents");  // Display message on Serial Monitor
    Serial.println();        
  }
  
  // If time interval of $1 is between 40000us and 45000us    
  else if ((40000 < elapsed_time) && (elapsed_time < 45000))  
  {
    Serial.print("You have inserted $1"); // Display message on Serial Monitor
    Serial.println();        
  }

  // If time interval of $2 is between 30000us and 38000us
  else if ((30000 < elapsed_time) && (elapsed_time < 38000)) 
  {
    Serial.print("You have inserted $2"); // Display message on Serial Monitor
    Serial.println();        
  }

  //If the time interval is outside of those ranges
  else
  {
    Serial.print("Coin undetected");  // Display message on Serial Monitor
    Serial.println();                 
  }                     
}
  
// Enable ISR Start Timer to set flag = 1
void Start_Timer()
{
  flag = 1;
}

// Enable ISR Stop Timer to set flag = 2
void Stop_Timer()
{
  flag = 2;
}

I have been testing those coins (with a ramp mechanism that I built) and adjusting those ranges around for each type of coins to minimize the detecting error (e.g the $1 coin if rolls fast enough can be detected as a $2 coin or vice versa). It worked 7 out of 10 times but is still flawed. Anyone could think of any solution to eliminate that problem would be appreciated.

At the moment, I am working on a metal detecting device to detect a real coin vs fake coin says a silver or bronze coin vs a plastic coin. My general concept was to make some sorts of magnetic field circuit by using inductor, capacitors and Arduino board. Different material will affect the magnetic field differently and I could use that result to determine if it is a real or fake coin. Please anyone who has experience in this gives me some suggestions on how to approach to a good solution.

Thank you for your time and effort in responding to this post.

maxkeeblehcm:
I have been testing those coins (with a ramp mechanism that I built) and adjusting those ranges around for each type of coins to minimize the detecting error (e.g the $1 coin if rolls fast enough can be detected as a $2 coin or vice versa). It worked 7 out of 10 times but is still flawed.

Use one sensor to measure diameter, the time the sensor is blocked. Use time from first sensor blocking to second sensor blocking to determine speed. Apply the speed reading as a correction factor to filter out coin speed and arrive at a true width number. Hey, it might work!