Can anyone point me to an example of code perhaps close enough for me to modify for my project.
I am new at this very new, so bear with me.
I simply want to detect the passing of a roller ball with the TCRT5000L and to print out via the serial printer the time the output was high.( The time being proportional to speed, which is my interest). Subsequent balls times being printed on the next line. I have a TCRT5000L and an Arduino UNO. Thanking you in anticipation.
Hi
I have had some success with this sketch. The input works well producing a square wave in serial plotter.
/*
TCRT5000 IR Sensor Test Digital
Reads a digital input on pin 8, prints the result to the serial monitor
*/
void setup() {
Serial.begin(9600);
pinMode(8, INPUT);
}
void loop() {
int sensorValue = digitalRead(8);
Serial.println(sensorValue);}
To explain a little further the roller balls pass the sensor about every 12 sec.
I think the speed will produce a high at pin 8 for about 40msec.
Am I right in thinking that with 9600 baud rate sample time will be around 10msec
that an error of 10msec on rise and fall at pin 8 could produce an error of 20msec.
Thus my 40msec could be 40+- 20msec. If this is the case then I will have to
have two sensors say 150mm apart sensing the rising edge which would give
a 400msec +-20msec which I think would be OK.
Putting the error problem to one side I need to to 1) log each ball 2) log the time from the rise
of the last ball to the rise of this ball and 3) log the time the sensor is high or if two sensors have
to be used the time interval between the 2 sensors.
The aim is to log the time between successive balls and a time for each ball to pass a point giving
and indication of speed. If anyone can help with advice and or code I would appreciate it.
To get better results, you should attach the device to an interrupt pin, and attach a handler to the interrupt vector (attachInterrupt()) for that pin, using CHANGE, so you can know as soon as the sensor changes state, from LOW to HIGH or from HIGH to LOW.
Knowing which transition means the sensor has become blocked will be necessary to know which transition is the start and which is the end. Recording when the transitions happen will allow you to determine the duration, which has some relationship to speed.
Try this. I haven't tested it, but it should work, or at least point you in the right direction. Serial.print is asynchronous, so it shouldn't affect the overall timing by much. There is overhead in digitalRead() but it varies by Arduino speed, so there is that latency to think of.
Code assumes HIGH = ball not seen at sensor.
unsigned int _lastBall = 0;
loop()
{
unsigned int transition = 0;
unsigned int start = 0;
char log[50];
// Wait for ball
while (digitalRead(8) == HIGH);
start = millis();
// Ball at sensor, wait for it to pass
while (digitalRead(8) == LOW);
// Record time of crossing. Cast to unsigned int to handle rollovers
transition = (unsigned int)( millis() - start);
// Get time since last ball seen
sprintf(log, "crossing %d, interval %d", transition, (unsigned int)(start - _lastBall));
_lastBall = millis();
// Print data
Serial.println(log);
}
Thanks for the code
I wasn't sure if all the start up code was there but I ran it as below
void setup() {
// put your setup code here, to run once:
unsigned int _lastBall = 0;
}
void loop() {
// put your main code here, to run repeatedly:
unsigned int transition = 0;
unsigned int start = 0;
char log[50];
// Wait for ball
while (digitalRead(8) == HIGH);
start = millis();
// Ball at sensor, wait for it to pass
while (digitalRead(8) == LOW);
// Record time of crossing. Cast to unsigned int to handle rollovers
transition = (unsigned int)( millis() - start);
// Get time since last ball seen
sprintf(log, "crossing %d, interval %d", transition, (unsigned int)(start - _lastBall));
_lastBall = millis();
// Print data
Serial.println(log);
}
I got error Arduino:28: error: '_lastBall' was not declared in this scope
You declared _lastBall in setup(). It went out of scope immediately, since setup() ended immediately after declaring the variable. Move that line before setup().
Yes, like PaulS said, _lastBall should be defined outside any function. I use the underscore to indicate global variables. Leave your existing setup() as is.
Thanks for your advice.
I took unsigned int _lastBall = 0; out of "set up" and ran the sketch below.
It passed verify, I thought I was "home and dry" but the serial monitor showed nothing.
I tried various " Serial.begin(9600);" etc in set up as I had seen in examples but to no avail.
What am I doing wrong? Your assumption that "Code assumes HIGH = ball not seen at sensor."
I believe is wrong the output goes high when the ball is detected. As seen on serial plot when my original code was run, a nice square wave with a high as the ball passed in front of the sensor.
Could this be the problem, if so what do I need to change in the code?
unsigned int _lastBall = 0;
void setup()
{
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
unsigned int transition = 0;
unsigned int start = 0;
char log[50];
// Wait for ball
while (digitalRead(8) == HIGH);
start = millis();
// Ball at sensor, wait for it to pass
while (digitalRead(8) == LOW);
// Record time of crossing. Cast to unsigned int to handle rollovers
transition = (unsigned int)( millis() - start);
// Get time since last ball seen
sprintf(log, "crossing %d, interval %d", transition, (unsigned int)(start - _lastBall));
_lastBall = millis();
// Print data
Serial.println(log);
}
unsigned int _lastBall = 0;
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(8, INPUT);
Serial.println("Starting up...");
}
void loop() {
// put your main code here, to run repeatedly:
unsigned int transition = 0;
unsigned int start = 0;
char log[50];
Serial.println("Waiting for ball");
// Wait for ball
while (digitalRead(8) == LOW);
start = millis();
Serial.println("Got ball");
// Ball at sensor, wait for it to pass
while (digitalRead(8) == HIGH);
// Record time of crossing. Cast to unsigned int to handle rollovers
transition = (unsigned int)( millis() - start);
// Get time since last ball seen
sprintf(log, "crossing %d, interval %d", transition, (unsigned int)(start - _lastBall));
_lastBall = millis();
// Print data
Serial.println(log);
}
This should give you some insight into what's happening. After it's working, remove the extra print statements.
Hi Cederlakeinstruments
I tried that but both crossing and interval ran into negative figures.
At the moment I have a test rig which amounts to a ball pendulum.
the range of time for the crossing is about 10 -100msec as it slows down,the interval
around 500msec constant. The actual roller ball rig would produce
a crossing time about 20-50msec but the interval will be around 12sec
constant. So microsec OK for crossing and millisec for interval as long as they
don't go negative.
I tried various combinations micro and milli but nothing fell out right.
I tried the micro, changing %d to %u, and long instead of int in all combinations.
The best results are still the code of Nov6. Changing to micro was good for the crossing
but not for the interval. If a code could be designed changing the crossing only to micro leaving the
interval on millis I think that will do.
PaulS is correct, the timing functions are ulong, not uint. Sorry about that. I figured this would be over and done with in five minutes, but I don't want to leave you stuck now. But hey, at least it's free
What's the purpose of this exercise, anyway?
unsigned long _lastBall = 0;
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(8, INPUT);
Serial.println("Starting up...");
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long transition = 0;
unsigned long start = 0;
char log[50];
Serial.println("Waiting for ball");
// Wait for ball
while (digitalRead(8) == LOW);
start = millis();
Serial.println("Got ball");
// Ball at sensor, wait for it to pass
while (digitalRead(8) == HIGH);
// Record time of crossing. Cast to unsigned int to handle rollovers
transition = (unsigned long)( millis() - start);
// Get time since last ball seen
sprintf(log, "crossing %u, interval %u", transition, (unsigned long)(start - _lastBall));
_lastBall = millis();
// Print data
Serial.println(log);
}