Photo Electric Counter/ Conveyor Belt Counter

Hello,
I have this code which is NOT mine I've only tweaked the delay so that when it senses an input it doesn't add dozens of "Counts" at once.

The problem I'm having is every time it "counts" an object for TOO LONG, with the object still in-front of the photo electric laser the moment the object passes through it adds an additional count because the reflector is now visible again. Originally this code was NOT designed to be used with a Photo electric reflective laser and just a infrared laser that wouldn't normally reflect an additional input back.

Again this only appears to be happening for as long as the object can't clear the laser relatively fast, if it sweeps by their no problem; but if it stays there even momentarily then it counts the first time than once more when it leaves the beam.

int ir_pin = 8;
int counter = 0;
int hitObject = false;

void setup() {
  Serial.begin(9600);
  pinMode(ir_pin,INPUT);
}

void loop() {

   int val = digitalRead(ir_pin);
   
   if( (val == 0) && (hitObject == false) ){
        counter++;
        hitObject = true;
        Serial.print("Counter = ");delay(600);
        Serial.println( counter);
   }else if( (val ==1) && (hitObject == true) ){
        hitObject = false;
   }
}    

Any ideas on how I could possibly adjust this code to IGNORE the reflective input once the object passes through? I thought of something primitive like maybe collectively making each "count" equal have of a normal input? so If I'm getting 1000 objects and it's counting 2000 etc..

Look at when there is a state change and avoid using delay( ).

Not a clue what means, the lasers states are NO/NC and it's NC, the NC signal is on my "ir_pin" and whenever the laser gets interrupted it switches the NC and produces a count; I created a lazy solution for now by just upping the latency to be longer than the time it would take for an object to pass through it; it's set too 4000 MS which is working until an object sits in it's beam for that long. Which it shouldn't.

How quickly can objects appear and how fast can they transit ?

essentially I'm placing this laser on a box tape machine but it's manually loaded by workers and I've never seen them put a box in the machine faster than 10 seconds. And the conveyer moves pretty slow, not sure on the speed honestly. Currently this appears to work pretty well, I'm also going to add a commercial 110v limit switch, for a mechanical counter measure to ensure accuracy throughout the day.

Made a few changes.

Added a heartbeat LED on pin 13 to show that the code was running.
Added a reset switch on pin 12 to clear the count.
Added a filter timeout when the object has gone by the sensor.

See if you can follow these changes, if you don't ask questions you wont learn anything.

//********************************************************************************
//Version    YY/MM/DD    Description
//1.00       22/09/20    Running sketch
//
//
//

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

#define resetTIMER             millis()

#define DETECTED               LOW
#define notDETECTED            HIGH

#define CLOSED                 LOW
#define OPENED                 HIGH

#define PUSHED                 LOW
#define notPUSHED              HIGH

#define ENABLED                true
#define DISABLED               false

#define RUNNING                true
#define notRUNNING             false

#define LEDon                  HIGH
#define LEDoff                 LOW

//                                            Resistor     LED
const byte heartbeatLED      = 13;    //+5V----[220R]----[A->|-K]----GND
const byte resetSwitch       = 12;    //between the pin and GND
const byte ir_pin            = 8;

bool detectedFlag            = DISABLED;

byte lastResetSwitchState;
byte lastIr_pin              = notDETECTED;

int count;

//timing stuff
unsigned long heartbeatTime;
unsigned long switchTime;
unsigned long detectedTime;

unsigned long interval = 1000ul; //add a wait time

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

  pinMode(heartbeatLED, OUTPUT);

  pinMode(resetSwitch, INPUT_PULLUP);
  pinMode(ir_pin, INPUT_PULLUP);

} //END of setup()


//********************************************************************************
void loop()
{
  //*************************************                  h e a r t b e a t   T I M E R
  //to see if the sketch is blocking,
  //toggle the heartbeat LED every 500ms
  if (resetTIMER - heartbeatTime >= 500)
  {
    //restart the TIMER
    heartbeatTime = resetTIMER;

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************                  s w i t c h   T I M E R
  //is it time to check the inputs and switches ?
  if (resetTIMER - switchTime >= 50)
  {
    //restart the TIMER
    switchTime = resetTIMER;

    //go and check the switches
    checkSwitches();
  }

  //*************************************                  d e t e c t e d   T I M E R
  //if enabled, has TIMER expired
  if (detectedFlag == ENABLED && millis() - detectedTime >= interval)
  {
    //the TIMER has expired
    detectedFlag = DISABLED;
  }


} //END of loop()


//********************************************************************************
//checking inputs for a change in state
void checkSwitches()
{
  //*********************************************            r e s e t S w i t c h
  byte currentState = digitalRead(resetSwitch);

  //**********************
  //was there a change in state ?
  if (lastResetSwitchState != currentState)
  {
    //update to the new state
    lastResetSwitchState = currentState;

    //**********************
    //is the switch closed ?
    if (currentState == CLOSED)
    {
      count = 0;

      Serial.print("Count reset = ");
      Serial.println(count);
    }

  } //END of    resetSwitch code


  //*********************************************            i r _ p i n
  currentState = digitalRead(ir_pin);

  //**********************
  //was there a change in state ?
  if (lastIr_pin != currentState)
  {
    //update to the new state
    lastIr_pin = currentState;

    //has the item been detected ?
    if (currentState == DETECTED)
    {
      //if the TIMER is running, don't proceed
      if (detectedFlag == DISABLED)
      {
        count++;

        Serial.print("Counter = ");
        Serial.println(count);
      }
    }

    //the item has gone by
    else
    {
      //enable the TIMER
      detectedFlag = ENABLED;

      //reset the delay TIMER
      detectedTime = resetTIMER;
    }

  } //END of    ir_pin code

  //*********************************************
  //next switch/input code
  //*********************************************

} //END of   checkSwitches()


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

1 Like

Hey Larry,

This works GREAT way better than the other one I found, it COMPLETELY solved the reflector issue, followed your steps without a hick-up, will incorporate both the reset switch and status led into the finished product! thanks again!

Hey Larry,

I'm just a hobbyist in this but I'm a licensed commercial journeyman here in new england, trying to get into this code stuff! similar to how you designated pins for other functions; how would I dedicate certain pins to add or subtract a count? like lets say in the event of a malfunction? so in theory I'd like to make pin 9 ADD 1, and have pin 10 SUBTRACT 1, any thoughts?

Added Increment switch pin 7

Added Decrement switch pin 6


Do you follow what is being done in the sketches ?



// https://forum.arduino.cc/t/photo-electric-counter-conveyor-belt-counter/1033927/9

//********************************************************************************
//  Version    YY/MM/DD    Description
//  1.00       22/09/20    Running sketch
//  1.01       22/09/21    Added Increment and Decrement switches
//
//
//

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

#define resetTIMER             millis()

#define DETECTED               LOW
#define notDETECTED            HIGH

#define CLOSED                 LOW
#define OPENED                 HIGH

#define PUSHED                 LOW
#define notPUSHED              HIGH

#define ENABLED                true
#define DISABLED               false

#define RUNNING                true
#define notRUNNING             false

#define LEDon                  HIGH
#define LEDoff                 LOW

//                                            Resistor     LED
const byte heartbeatLED      = 13;    //+5V----[220R]----[A->|-K]----GND
const byte resetSwitch       = 12;    //between the pin and GND
const byte ir_pin            = 8;
const byte incrementSwitch   = 7;     //between the pin and GND
const byte decrementSwitch   = 6;     //between the pin and GND

bool detectedFlag            = DISABLED;

byte lastIr_pin              = notDETECTED;
byte lastResetSwitchState;
byte lastIncrementSwitchState;
byte lastDecrementSwitchState;

int count;

//timing stuff
unsigned long heartbeatTime;
unsigned long switchTime;
unsigned long detectedTime;

unsigned long interval = 1000ul; //add a wait time

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

  pinMode(heartbeatLED, OUTPUT);

  pinMode(resetSwitch, INPUT_PULLUP);
  pinMode(ir_pin, INPUT_PULLUP);
  pinMode(incrementSwitch, INPUT_PULLUP);
  pinMode(decrementSwitch, INPUT_PULLUP);


} //END of setup()


//********************************************************************************
void loop()
{
  //*************************************                  h e a r t b e a t   T I M E R
  //to see if the sketch is blocking,
  //toggle the heartbeat LED every 500ms
  if (resetTIMER - heartbeatTime >= 500)
  {
    //restart the TIMER
    heartbeatTime = resetTIMER;

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************                  s w i t c h   T I M E R
  //is it time to check the inputs and switches ?
  if (resetTIMER - switchTime >= 50)
  {
    //restart the TIMER
    switchTime = resetTIMER;

    //go and check the switches
    checkSwitches();
  }

  //*************************************                  d e t e c t e d   T I M E R
  //if enabled, has TIMER expired
  if (detectedFlag == ENABLED && millis() - detectedTime >= interval)
  {
    //the TIMER has expired
    detectedFlag = DISABLED;
  }


} //END of loop()


//********************************************************************************
//checking inputs for a change in state
void checkSwitches()
{
  //*********************************************            r e s e t S w i t c h
  byte currentState = digitalRead(resetSwitch);

  //**********************
  //was there a change in state ?
  if (lastResetSwitchState != currentState)
  {
    //update to the new state
    lastResetSwitchState = currentState;

    //**********************
    //is the switch closed ?
    if (currentState == CLOSED)
    {
      count = 0;

      Serial.print("Counter reset = ");
      Serial.println(count);
    }

  } //END of    resetSwitch code


  //*********************************************            i r _ p i n
  currentState = digitalRead(ir_pin);

  //**********************
  //was there a change in state ?
  if (lastIr_pin != currentState)
  {
    //update to the new state
    lastIr_pin = currentState;

    //has the item been detected ?
    if (currentState == DETECTED)
    {
      //if the TIMER is running, don't proceed
      if (detectedFlag == DISABLED)
      {
        count++;

        Serial.print("Counter = ");
        Serial.println(count);
      }
    }

    //the item has gone by
    else
    {
      //enable the TIMER
      detectedFlag = ENABLED;

      //reset the delay TIMER
      detectedTime = resetTIMER;
    }

  } //END of    ir_pin code


  //*********************************************            i n c r e m e n t S w i t c h
  currentState = digitalRead(incrementSwitch);

  //**********************
  //was there a change in state ?
  if (lastIncrementSwitchState != currentState)
  {
    //update to the new state
    lastIncrementSwitchState = currentState;

    //**********************
    //is the switch closed ?
    if (currentState == CLOSED)
    {
      count = count + 1;

      Serial.print("Counter = ");
      Serial.println(count);
    }

  } //END of    incrementSwitch code


  //*********************************************            d e c r e m e n t S w i t c h
  currentState = digitalRead(decrementSwitch);

  //**********************
  //was there a change in state ?
  if (lastDecrementSwitchState != currentState)
  {
    //update to the new state
    lastDecrementSwitchState = currentState;

    //**********************
    //is the switch closed ?
    if (currentState == CLOSED)
    {
      count = count - 1;

      //do not go less than zero
      if (count < 0)
      {
        count = 0;
      }

      Serial.print("Counter = ");
      Serial.println(count);
    }

  } //END of    decrementSwitch code

  //*********************************************
  //next switch/input code
  //*********************************************

} //END of   checkSwitches()


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

EDIT

Added some comments

1 Like

i'd normally say this is a debounce issue which an IR detector would typically not have, but might have if the object is wobbling

consider

int ir_pin  = 8;
int counter = 0;

byte irLst;

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

    pinMode  (ir_pin,INPUT_PULLUP);
    irLst = digitalRead  (ir_pin);
}

void loop  () {
    byte ir = digitalRead  (ir_pin);
    if  (irLst != ir)  {
        irLst = ir;
        delay  (50);     // debounce  (may need to adjust

        if  (LOW == ir)  {
            counter++;
            Serial.print    ("Counter = ");
            Serial.println  ( counter);
        }
    }
}

IF your laser is pulsed you may also pick up the off-on of the laser.

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