input TCRT5000L output serial print of the input high time period in msec

Hi

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.

What is a "trct5000l"? How is it connected to the Arduino? What are you able to read from it?

Hi
Sorry had a typo on the input device it should have read TCRT5000L, which is a reflective optical sensor with a transistor output.

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);
}

Enjoy! Let me know how it works out for you.

Hi cederlakeinstruments

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

sprintf(log, "crossing %d, interval %d", transition, (unsigned int)(start - lastBall))

exit status 1
'_lastBall' was not declared in this scope.

Does this mean something is missing in the setup?
also should I have put this

unsigned int transition = 0;
  unsigned int start = 0;
  char log[50];

in set up?

Thanks again for your help

You declared _lastBall in setup(). It went out of scope immediately, since setup() ended immediately after declaring the variable. Move that line before setup().

unsigned int _lastBall = 0;
void 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.

Hi there

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);


}

Try this.

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 Cedarlakeinstruments

The code worked, thank you very much for your time and effort.

The milliseconds recorded for the detection of the ball could use an additional digit, so recording

12.5 say instead of 12 to give better resolution of speed, is this possible?

Thanks again

Using micros() instead of millis() will provide microsecond resolution.

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.

The math is probably correct, but sprintf is interpreting the unsigned values as signed ones, try changing the %d to %u

Time value, whether from millis() or micros() are unsigned long, not unsigned int.

Hi

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.

I tried the micro, changing %d to %u, and long instead of int in all combinations.

But, I'm not going to tell you what happened, or what the code looks like...

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.

That puts you in the minority, then.

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 :slight_smile:

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);
}
  transition = (unsigned long)( millis() - start);

There is no need to cast an unsigned long to unsigned long.