Best Sensor for Coin Sorter

Greetings,

I am using an Arudino UNO with TCRT5000 IR Sensor Modules to count coins as they fall thru the slots. Code works, modules work. However, I am not getting consistent counting. Any thoughts on how to adjust the sensors? Use a different type of sensor?

Thanks,
Brad

Surely you can be more forthcoming with a description of the problem. Is it counting with no coins? Is it counting the same coin more than once? Is it not counting the second coin, but all others? Is it counting the last coin twice?

Paul

post your code and a schema of your wiring.

(see How to get the best out of this forum)

To answer the first reply, the count vs. non-count is random. Not sure if it is the speed of coin falling thru the sensor field, angle of the fall, angle of the sensor...

To address the second reply. I will post the code and image of the connections.

Then the problem is only non-counting, and not extra counting. Are the coins all the same size or are the missing counts smaller coins?
Paul

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

bool debug = false;
int displayTimeMilis = 3000;
bool starting = true;


int lightUmbral0 = 365;
int lightUmbral1 = 855;
int lightUmbral2 = 465;
int lightUmbral3 = 840;
int lightUmbral4 = 365;

int coinNumber0 = 0;          // Dime 10
bool coinPassing0 = false;
int coinNumber1 = 0;          // Penny 01
bool coinPassing1 = false;
int coinNumber2 = 0;          // Nickel 05
bool coinPassing2 = false;
int coinNumber3 = 0;          // Quarter 25
bool coinPassing3 = false;

//int tempNumber100 = 0;
float tempTotalMoney = 0;
bool showingCount = false;

int photocellPin0 = 0;     // 10
int photocellReading0;     // 10
int photocellPin1 = 1;     // 01
int photocellReading1;     // 01
int photocellPin2 = 2;     // 05
int photocellReading2;     // 05
int photocellPin3 = 3;     // 25
int photocellReading3;     // 25


void setup()
{
  analogWrite(6, 128);  // display
  analogWrite(9, 128);  // display
  // set up the LCD's number of columns and rows:

  lcd.begin();
  // Print a message to the LCD.
  lcd.setCursor(0, 0); // column, row
  lcd.print("Getting Started...");


  digitalWrite(1, HIGH);  // luz
  //Serial.begin(9600);

  delay(1000);        // INITIAL WAIT TIME

}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):


  if (starting) {

    photocellReading0 = analogRead(photocellPin0);
    photocellReading1 = analogRead(photocellPin1);
    photocellReading2 = analogRead(photocellPin2);
    photocellReading3 = analogRead(photocellPin3);

    delay(2000);        // INITIAL WAIT TIME

    photocellReading0 = analogRead(photocellPin0);
    photocellReading1 = analogRead(photocellPin1);
    photocellReading2 = analogRead(photocellPin2);
    photocellReading3 = analogRead(photocellPin3);

    delay(2000);        // INITIAL WAIT TIME

    coinNumber0 = 0;          // Dime 10
    coinPassing0 = false;
    coinNumber1 = 0;          // Penny 01
    coinPassing1 = false;
    coinNumber2 = 0;          // Nickel 05
    coinPassing2 = false;
    coinNumber3 = 0;          // Quarter 25
    coinPassing3 = false;

    starting = false;

  }


  lcd.setCursor(0, 1);
  // print the number of seconds since reset:

  photocellReading0 = analogRead(photocellPin0);
  photocellReading1 = analogRead(photocellPin1);
  photocellReading2 = analogRead(photocellPin2);
  photocellReading3 = analogRead(photocellPin3);


  if (photocellReading0 >= lightUmbral0) {

    coinPassing0 = false;
  }

  if (photocellReading0 < lightUmbral0 && !coinPassing0) {

    coinPassing0 = true;
    coinNumber0++;
  }

  if (photocellReading1 >= lightUmbral1) {

    coinPassing1 = false;
  }

  if (photocellReading1 < lightUmbral1 && !coinPassing1) {

    coinPassing1 = true;
    coinNumber1++;
  }

  if (photocellReading2 >= lightUmbral2) {

    coinPassing2 = false;
  }

  if (photocellReading2 < lightUmbral2 && !coinPassing2) {

    coinPassing2 = true;
    coinNumber2++;
  }

  if (photocellReading3 >= lightUmbral3) {

    coinPassing3 = false;
  }


  if (photocellReading3 < lightUmbral3 && !coinPassing3) {

    coinPassing3 = true;
    coinNumber3++;
  }


  if (debug) {

    // CLEAN LCD
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // end CLEAN LCD


    lcd.setCursor(0, 0); // column, Row
    lcd.print(photocellReading0);

    lcd.setCursor(5, 0); // column, Rowa
    lcd.print(photocellReading1);

    lcd.setCursor(10, 0); // column, Row
    lcd.print(photocellReading2);

    lcd.setCursor(0, 1); // column, Row
    lcd.print(photocellReading3);

    delay(500);

  }

  else if (!showingCount && millis() % displayTimeMilis < displayTimeMilis / 2) {

    showingCount = true;

    // CLEAN LCD
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // end CLEAN LCD

    lcd.setCursor(0, 0); // column, Row
    lcd.print("10=");
    lcd.setCursor(3, 0);
    lcd.print(coinNumber0);

    lcd.setCursor(8, 0); // column, Row
    lcd.print("01=");
    lcd.setCursor(11, 0);
    lcd.print(coinNumber1);

    lcd.setCursor(0, 1); // column, Row
    lcd.print("05=");
    lcd.setCursor(4, 1);
    lcd.print(coinNumber2);

    lcd.setCursor(8, 1); // column, Row
    lcd.print("25=");
    lcd.setCursor(12, 1);
    lcd.print(coinNumber3);

  } else if (showingCount && millis() % displayTimeMilis >= displayTimeMilis / 2)

  {

    showingCount = false;

    // CLEAN LCD
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // end CLEAN LCD


    lcd.setCursor(2, 0); // column, Row
    lcd.print("MONEY TOTAL:");

    tempTotalMoney = (coinNumber0 * 0.10) + (coinNumber1 * 0.01) + (coinNumber2 * 0.05) + (coinNumber3 * 0.25);

    lcd.setCursor(4, 1);
    lcd.print("$");
    lcd.setCursor(5, 1); // column, Row
    lcd.print(tempTotalMoney);

  }

}

I really can't follow your logic. But, if you are doing ANYTHING with the LCD display while coins are falling, you will miss one or more.
Paul

How do you mean "do anything" with the LCD? Are you suggesting to not display the counts in real time? how would I store the counts etc, and display at the end of the session?

Brad

How is your code not counting multiple times the same coin as it loops and the coin is still in front of the sensor (code runs fast)

You should state change d├ętection or a small FSM

I am suggesting the display code for the LCD takes more time than you think.
Paul

You don't have 'debug' turned on, do you? Ignoring inputs for half a second would cause coins to be missed.

You can reduce the size and complexity of your sketch by using arrays:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

bool debug = false;
unsigned displayTimeMilis = 3000;
bool starting = true;


int lightUmbral[4] = {365, 855, 465, 840};
// int lightUmbral4 = 365;

int coinNumber[4];          // Dime 10, Penny 01, Nickel 05, Quarter 25
bool coinPassing[4];

//int tempNumber100 = 0;
float tempTotalMoney = 0;
bool showingCount = false;

int photocellPin[4] = {A0, A1, A2, A3};     // 10
int photocellReading[4];


void setup()
{
  analogWrite(6, 128);  // display
  analogWrite(9, 128);  // display
  // set up the LCD's number of columns and rows:

  lcd.begin();
  
  // Print a message to the LCD.
  lcd.setCursor(0, 0); // column, row
  lcd.print("Getting Started...");


  digitalWrite(1, HIGH);  // luz
  //Serial.begin(9600);

  delay(1000);        // INITIAL WAIT TIME

  for (int i = 0; i < 4; i++)
  {
    photocellReading[i] = analogRead(photocellPin[i]);
    coinNumber[i] = 0;
    coinPassing[i] = false;
  }
}

void loop()
{
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:

  for (int i = 0; i < 4; i++)
  {
    photocellReading[i] = analogRead(photocellPin[i]);

    if (photocellReading[i] >= lightUmbral[i])
    {
      coinPassing[i] = false;
    }
    else if (!coinPassing[i])
    {
      coinPassing[i] = true;
      coinNumber[i]++;
    }
  }

  if (debug)
  {
    // CLEAN LCD
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // end CLEAN LCD

    lcd.setCursor(0, 0); // column, Row
    lcd.print(photocellReading[0]);

    lcd.setCursor(5, 0); // column, Rowa
    lcd.print(photocellReading[1]);

    lcd.setCursor(10, 0); // column, Row
    lcd.print(photocellReading[2]);

    lcd.setCursor(0, 1); // column, Row
    lcd.print(photocellReading[3]);
  }
  else if (!showingCount && millis() % displayTimeMilis < displayTimeMilis / 2)
  {
    showingCount = true;

    // CLEAN LCD
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // end CLEAN LCD

    lcd.setCursor(0, 0); // column, Row
    lcd.print("10=");
    lcd.setCursor(3, 0);
    lcd.print(coinNumber[0]);

    lcd.setCursor(8, 0); // column, Row
    lcd.print("01=");
    lcd.setCursor(11, 0);
    lcd.print(coinNumber[1]);

    lcd.setCursor(0, 1); // column, Row
    lcd.print("05=");
    lcd.setCursor(4, 1);
    lcd.print(coinNumber[2]);

    lcd.setCursor(8, 1); // column, Row
    lcd.print("25=");
    lcd.setCursor(12, 1);
    lcd.print(coinNumber[3]);

  }
  else if (showingCount && millis() % displayTimeMilis >= displayTimeMilis / 2)
  {
    showingCount = false;

    // CLEAN LCD
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // end CLEAN LCD

    lcd.setCursor(2, 0); // column, Row
    lcd.print("MONEY TOTAL:");

    tempTotalMoney = (coinNumber[0] * 0.10)
                     + (coinNumber[1] * 0.01)
                     + (coinNumber[2] * 0.05)
                     + (coinNumber[3] * 0.25);

    lcd.setCursor(4, 1);
    lcd.print("$");
    lcd.setCursor(5, 1); // column, Row
    lcd.print(tempTotalMoney);
  }
}

Ummm, how would I know if Debug is turned on?

And I will give the code a try...

As long as you don't set the variable 'debug' to 'true' anywhere it will remain turned off.

bool debug = false;
.
.
.
  if (debug)
  {