I am using a VL53L1X sensor to count cans as they pass on a conveyor.
If the can is in the range of between 30 and 70 I then increment my counter.
The problem I have is that when a can passes the sensor, I get multiple readings and subsequent counts.
I must only read the can once when it is within the range.
I have tried multiple solutions found on the net (Thanks Granny Google) but nothing seems to work.
Could someone please steer me in the right direction?
My Code:
/*
This example shows how to take simple range measurements with the VL53L1X. The
range readings are in units of mm.
*/
#include <Wire.h>
#include <VL53L1X.h>
VL53L1X sensor;
volatile int myReading;
volatile int myCount = 0;
void setup() {
while (!Serial) {}
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000); // use 400 kHz I2C
sensor.setTimeout(500);
if (!sensor.init()) {
Serial.println("Failed to detect and initialize sensor!");
while (1)
;
}
// Use long distance mode and allow up to 50000 us (50 ms) for a measurement.
// You can change these settings to adjust the performance of the sensor, but
// the minimum timing budget is 20 ms for short distance mode and 33 ms for
// medium and long distance modes. See the VL53L1X datasheet for more
// information on range and timing limits.
sensor.setDistanceMode(VL53L1X::Long);
sensor.setMeasurementTimingBudget(50000);
// Start continuous readings at a rate of one measurement every 50 ms (the
// inter-measurement period). This period should be at least as long as the
// timing budget.
sensor.startContinuous(50);
}
void loop() {
myReading = (sensor.read());
if ((myReading >= 30) && (myReading <= 70)) {
myCount++;
Serial.print("GOTCHA");
}
if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
Serial.println();
}
I think you just need to "wait" for the detected can to go away from the sensor.
Just to describe it (I won't change your code dicretly because you need to understand what is going on, instead of a dummy copy/paste ), after a can is detecetd you should add a "do...while" loop with a sensor reading, then small delay inside (e.g. "delay(100)") and as exit condition if the distance falls below a value higher than max distance allowed (maybe 100 or more).
Is that a TOF sensor? If so it is not the best choice for this application as it will 'see' that can for a long time.
How wide is the conveyor, in other words can more than one can get by any sensor at one time? What keeps the cans upright?
If you can be sure the cans stay upright and only one can pass at a time, a simple photoelectric setup will work. If not, it's not easy.
Thanks,
The problem is that the cans are on their sides.
The bottom of the can is domed and has a ridge around the circumference (Aerosol can).
I have tried with a IR sensor, but readings are not consistent.
myReading = (sensor.read());
if ((myReading >= 30) && (myReading <= 70)) {
int i = 0;
do {
delay(100);
i++; // increase i by 1
myCount++;
Serial.println("GOTCHA");
} while (i == 1); // repeat
}
That do..while won't exactly cycle and won't read the sensor.
If you set "i=0", and inside you have "i++", it'll be equals to 1 so the first time will cycle but not a second time, so you just added 100 ms delay, nothing more.
Ok, the code I was suggesting you to add is:
myReading = (sensor.read());
if ((myReading >= 30) && (myReading <= 70)) {
Serial.println("GOTCHA");
// Wait for the can to go away...
do {
// Adjust/reduce this delay to make sure you won't "jump" over the next can
delay(100);
// Change this condition based on your sensor reading value
// for "no can is in sight"...
} while (sensor.read() <= 70);
You could maybe implement some sort of non blocking delay and a flag variable that becomes true once a reading is available, then have the flag variable reset after the non blocking delay time surpasses. That way, the code will get the first reading and not take subsequent readings due to the flag variable, then the flag will reset once the non blocking interval has passed
Yes, there are many ways to do the same task, but your suggestion is surely valid if the code must also do other things. In this case it looks like a blocking delay is enough.
The VL53L1x is an IR sensor but that can measures distance. I see no need to know the distance to know if a can is there or not. If you could not make a simple IR breakbeam work, chances are that you will never make the VL53 work.
Hi Jim,
The problem with a simple IR sensor is that the can distance varies because of the domed base. The TOF sensor allows me to compensate for this.
The do / while loop used in this manner is a common trick. The sensor in this case is limited to 20 readings a second, so the pattern works well.
In the case of using the same logic as a lazy switch debounce, for example, the fact that the test that finally allows the loop to exit may come very near some more excitement, so
// Wait for the can to go away...
do {
// Adjust/reduce this delay to make sure you won't "jump" over the next can
delay(100);
// Change this condition based on your sensor reading value
// for "no can is in sight"...
} while (sensor.read() <= 70);
delay(100);
Stretching the reading that triggered the exit one last delay period.
Here I also wonder if the exit test should be identical, viz:
// Wait for the can to go away...
do {
// Adjust/reduce this delay to make sure you won't "jump" over the next can
delay(100);
// Change this condition based on your sensor reading value
// for "no can is in sight"...
} while (sensor.read.read() >= 30 && sensor.read() <= 70);
delay(100);
In any case, it is better to read the sensor once. So I end up with
myReading = (sensor.read());
if (myReading >= 30 && myReading <= 70) {
Serial.println("GOTCHA");
do {
delay(100);
myReading = (sensor.read());
} while (myReading >= 30 && myReading <= 70);
delay(100);
where as @docdoc had commented, adjust the delay and the "no can" exit test expression.
This can also be programmed in a manner so as to avoid delay() if/when that becomes important. Detecting a change of state and implementing a kind of debouncing for the signal would allow total non-blocking sensor sensing.