chronograph troubles

I'm relatively new to electronics and coding and this is the most complex project I've built so far. It is supposed to measure the light level changes in the tunnel using two LDR's to detect an object going though and calculate the speed but whenever I fire something through it it maxes out at 100 fps instead of the theoretical maximum of about 500 fps. Any idea as to why this might be happening

chronograph_v112341234.ino (1.99 KB)

I'm posting this again because I feel like i did a very bad job explaining it the first time. I'm building this for my potato cannon so it will be measuring a projectile that has a diameter of 3/4in. my current setup is a 2in pvc tube with two LDR's and two LED's on the opposite side.when an object passes through the LDR's detect the change in light from the LED's being blocked out. it seems to work but when I shoot something through it, it gives me a reading of exactly 100.0FPS out of a theoretical maximum of 500FPS based upon a possible 1ms time difference between the two sensors. i'm stumped as to why this is happening, any ideas?

const int LDR1 = A0;
const int LDR2 = A1;
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
unsigned long elapsedTime;
int b;
float fps;
int input_val1 = 0;
int input_val2 = 0;
int potPin = 2;
int val = 0; 
#include "SevSeg.h"

SevSeg sevseg;
void setup()
{
  Serial.begin(9600);
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true; 
  bool updateWithDelaysIn = true;
  byte hardwareConfig = COMMON_ANODE; 
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(90);
}

void loop()
{
  do{
    b = millis(); //start timer to display ambient light levels
    input_val1 = analogRead(LDR1); 
    sevseg.setNumber(input_val1);
    sevseg.refreshDisplay(); 
  }while (b < 5000);
  do{
    b = millis(); //allows 10 seconds to adjust the light level at which the sensors trigger using a potentiometer to ease ambient light polution 
   val = analogRead(potPin);
    sevseg.setNumber(val);
    sevseg.refreshDisplay(); 
  }while (b < 15000);
 do{
  {
  input_val1 = analogRead(LDR1); // check the value of the sensor until it drops below the set threshold
 Serial.print("LDR1 Value is: ");
 Serial.println(input_val1);
  }
}while(input_val1>=val);
 {
     startMillis = millis(); //start the first timer
   Serial.print("startMillis= "); 
  Serial.println(startMillis);
  }
 do{
 {
  input_val2 = analogRead(LDR2); // wait until the second sensor is triggered
  Serial.print("LDR2 Value is: ");
  Serial.println(input_val2);
}
   
 }while(input_val2>=val);
 {
      currentMillis = millis();// start another timer to subtract from the first one
 Serial.print("currentMillis= ");
Serial.println(currentMillis);
   }
  
   
 (elapsedTime = currentMillis - startMillis); //the time between the sensors
  Serial.print(elapsedTime);
  Serial.println(" miliseconds");
    
      
(fps = 0.5 / elapsedTime * 1000); //change time into feet per second through the known distance between the sensors
 Serial.print(fps, 4);
  Serial.println(" feet per second");

for (int i = 0; i < 10000000000000; i++)// just keep displaying the result
{
  sevseg.setNumber(fps, 1);
   sevseg.refreshDisplay();
} 
}

What is the response time of the LDR's you are using?

Just some low hanging fruit - it won't break it but makes it hard to read - also suggests you aren't too familiar with C. You have placed a superfluous set of brackets in several places. Often this means that the coder has made what they think are conditional blocks that actually have no conditional test:

  do {
    {
      input_val2 = analogRead(LDR2); // wait until the second sensor is triggered
      Serial.print("LDR2 Value is: ");
      Serial.println(input_val2);
    }

  } while (input_val2 >= val);
  {
    currentMillis = millis();// start another timer to subtract from the first one
    Serial.print("currentMillis= ");
    Serial.println(currentMillis);
  }

There are four extra brackets like that in here... it functions like:

  do {
    input_val2 = analogRead(LDR2); // wait until the second sensor is triggered
    Serial.print("LDR2 Value is: ");
    Serial.println(input_val2);
  } while (input_val2 >= val);

  currentMillis = millis();// start another timer to subtract from the first one
  Serial.print("currentMillis= ");
  Serial.println(currentMillis);

As I said, it's not just about form. It's possible you misinterpret the program flow.

Idahowalker:
What is the response time of the LDR's you are using?

it seems to be about 33ms

Two observations:

  • analogRead() is not very fast.
  • you are doing serial printing at the same time as detecting the LDR events, not wise.

You have overused braces {}, but that shouldn't cause a problem
You have two very long sections of blocking code in the loop(); 20=seconds!
Use CTRL-T to show the indents better.

while(input_val1>=val);

The semicolon ends the while statement and you have this syntax all over the code. The code following it will execute regardless of the while being evaluated as true or not.

There has to be a ton of warnings in the compile log. Scroll up in the text window at the bottom of the IDE and you are sure to find a lot of help.

aarg:
Two observations:

  • analogRead() is not very fast.
  • you are doing serial printing at the same time as detecting the LDR events, not wise.

is there a better alternative to analogread() in terms of speed. and i have separate code that I upload to the cannon that does not include the serial print because it is not needed for the final product.

SteveMann:
while(input_val1>=val);

The semicolon ends the while statement and you have this syntax all over the code.

@SteveMann, no, the while statement often looks like that when it is used with the 'do-while' construct. The confusion is another reason to avoid 'do-while' unless it actually makes sense. For example this:

  do {
    b = millis(); //start timer to display ambient light levels
    input_val1 = analogRead(LDR1);
    sevseg.setNumber(input_val1);
    sevseg.refreshDisplay();
  } while (b < 5000);

Looks a whole lot cleaner like this:

  while (millis() < 5000) { //start timer to display ambient light levels
    input_val1 = analogRead(LDR1);
    sevseg.setNumber(input_val1);
    sevseg.refreshDisplay();
  }

rectalblister:
i have separate code that I upload to the cannon that does not include the serial print because it is not needed for the final product.

It is unfair to not tell us that until now. The problem may be in the "separate" code. Please upload it.

aarg:
It is unfair to not tell us that until now. The problem may be in the "separate" code. Please upload it.

its the exact same copy pasted code just with the serialprints removed

const int LDR1 = A0;
const int LDR2 = A1;
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
unsigned long elapsedTime;
int b;
float fps;
int input_val1 = 0;
int input_val2 = 0;
int potPin = 2;
int val = 0;
#include "SevSeg.h"

SevSeg sevseg;
void setup()
{
  Serial.begin(9600);
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true;
  bool updateWithDelaysIn = true;
  byte hardwareConfig = COMMON_ANODE;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(90);
}

void loop()
{
  do {
    b = millis(); //start timer to display ambient light levels
    input_val1 = analogRead(LDR1);
    sevseg.setNumber(input_val1);
    sevseg.refreshDisplay();
  } while (b < 5000);
  do {
    b = millis(); //allows 10 seconds to adjust the light level at which the sensors trigger using a potentiometer to ease ambient light polution
    val = analogRead(potPin);
    sevseg.setNumber(val);
    sevseg.refreshDisplay();
  } while (b < 15000);
  do {
    {
      input_val1 = analogRead(LDR1); // check the value of the sensor until it drops below the set threshold
    }
  } while (input_val1 >= val);
  {
    startMillis = millis(); //start the first timer
   
  }
  do {
    {
      input_val2 = analogRead(LDR2); // wait until the second sensor is triggered
 
    }

  } while (input_val2 >= val);
  {
    currentMillis = millis();// start another timer to subtract from the first one
  }
  (elapsedTime = currentMillis - startMillis); //the time between the sensors

  (fps = 0.5 / elapsedTime * 1000); //change time into feet per second through the known distance between the sensors
  for (int i = 0; i < 10000000000000; i++)// just keep displaying the result
  {
    sevseg.setNumber(fps, 1);
    sevseg.refreshDisplay();
  }
}

rectalblister:
its the exact same copy pasted code just with the serialprints removed

I don't care. Post it. There is always the possibility of an error, unless you tested both with the cannon recently. Also, it will be easier to read.

SteveMann:
There has to be a ton of warnings in the compile log. Scroll up in the text window at the bottom of the IDE and you are sure to find a lot of help.

there are no warnings displayed but it would not shock me at all to find out that i have made numerous errors

Like this one

  for (int i = 0; i < 10000000000000; i++)// just keep displaying the result

The biggest number an int can hold is 32,767. It won't break the program, but "where there's smoke, there's fire".

10,000,000,000,000

unsigned long can hold 2^32 or
4,294,967,295
10,000,000,000,000

So you'll need to do some re-thinking there.

aarg:
Like this one

  for (int i = 0; i < 10000000000000; i++)// just keep displaying the result

yeah thats just there to keep it running i assumed that if i didn't get any sort of error message it was not a fatal flaw, i will still fix this though, but it still doesnt explain why the minimum time it can record it about 50ms.

Have you tried displaying the value of elapsedTime instead of fps? I'm suspicious you might be dividing by zero.

david_2018:
Have you tried displaying the value of elapsedTime instead of fps? I'm suspicious you might be dividing by zero.

i checked and elapsedTime does give me a number so i don't think that it is dividing by zero.

I think the problem might be what the first guy mentioned about the response time of the LDR's because a google search reveals that the response time of a LDR is about 50ms which is the exact discrepancy of my minimum time. so would switching it out for a photo transistor work to decrease the response time.

I just checked, divide by zero will not display 100.0 (at least on Serial) so that isn't it.

Should not make any difference, but try changing

  for (int i = 0; i < 10000000000000; i++)// just keep displaying the result
  {
    sevseg.setNumber(fps, 1);
    sevseg.refreshDisplay();
  }

to this:

  sevseg.setNumber(fps, 1);
  while (true)  {
    sevseg.refreshDisplay();
  }

I think the problem might be what the first guy mentioned about the response time of the LDR's because a google search reveals that the response time of a LDR is about 50ms which is the exact discrepancy of my minimum time. so would switching it out for a photo transistor work to decrease the response time.

That is a possibility, although 5mS will give 100.0fps using the equation in the sketch. How far apart are your sensors? The equation implies a 6" spacing.