Calculating Speed with Two Sensors

A few things first.

  1. I do have tubing to restrict the vision of the sensor which seems to work (about an inch over the sensor itself)

  2. I am using one digital and one analog PIR sensor, mainly to prove a point that it can be done with both so my code will be a little more complex than if (sensor == HIGH) do blah blah but thats not the hard, I have figured that out. I thought initally this would conflict as each sensor would be off and cause error but only about 75% of the time do I get a crazy value so most of the time it says I walked by going 3 mph, pretty standard, then couple times later, BOOM, I'm moving at 50 mph, a little suspicious.

  3. I am constantly polling each sensor in my main loop, my code above is what I have in one of my state machines (even though I am not using switch case like you suggested, it still works nonetheless). I will post whole code for anyone that is confused.

  4. I do like you switch case and I wish I had more time to go back through and clean my code up (as you can tell I'm not the best at it) however I am closing in on the project due date.

Again, I can't fathom why multiple outputs are working perfectly then all of sudden an extreme value appears.

/*
*/

#include <LiquidCrystal.h>
#include <SD.h>

const int chipSelect = 17;
String message1, message2, message3;
int digitalVal, analogVal, newDigital, newAnalog, newAnalogVal;
int digitalPin = 2;
int analogPin = A0;
int calibrationTime = 60;        
int counter, counterLeft, counterRight = 0;
float t1, t0, countTime, concentration;
float speed_0, trueSpeed;
float time0, time1, delayTime ;
float timeout1, timeout0;

LiquidCrystal lcd(0, 13, 9, 4, 5, 6, 7);


void setup() {
 delay(2000);
 
 lcd.begin(16,2);
 lcd.clear();
 lcd.setCursor(0,0);
 
 Serial.begin(9600);
 while(!Serial) {
 ;
 }
 
 // Wait for sensors to calibrate (60s)
  Serial.print("calibrating sensor ");
  lcd.print("Calibrating");
  lcd.setCursor(0,1);
  lcd.print("Sensor");
  lcd.setCursor(0,0);
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    lcd.print("done");
    lcd.setCursor(0,1);
    Serial.println("SENSOR ACTIVE");
    lcd.print("SENSOR ACTIVE");
    lcd.setCursor(0,0);

    delay(50);
 
 Serial.print("Initializing SD card...");
  lcd.print("Initializing SD");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("SD card failed, or not present");
    lcd.setCursor(0,1);
    lcd.print("SD card failed");

    // don't do anything more:
    return;
  }
  Serial.println("SD card initialized."); 
  lcd.setCursor(0,0);
  lcd.print("SD card initialized."); 
  delay(1000);
  lcd.clear();
  
  pinMode(analogPin, INPUT); // Analog Pin (A0) - PIR Sensor
  pinMode(digitalPin, INPUT); // Digital Pin (D2) - PIR Sensor   
 
  File dataFile = SD.open("ricelake.txt", FILE_WRITE);
  if (dataFile)
  {
    dataFile.println(", , , ,"); //Just a leading blank line, incase there was previous data
    String header = "Speed | From Left | From Right | Concentration";
    dataFile.println(header);
    dataFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
}

void computeData_0() // calculates speed, direction and concentration 
{  
   t0 = millis(); // timestamp for calculating data

   timeout0 = millis();
  
   while(digitalVal == LOW){ // wait for digital sensor to go HIGH
       digitalVal = digitalRead(digitalPin);
       if ((float)millis() - timeout0 > 800) return; // timeout after 800ms (0.8 s) 
   }
   
   time0 = ((float)millis() - t0) / 1000; // time between sensor dections (secs)
   delay(5000); // delay long time to ensure sensor is stable
   
   delayTime = millis();        
   if (((float)millis() - delayTime) > 300){ // wait 300ms until Digital Pin is LOW
        
        newDigital = digitalRead(digitalPin); // Check digital sensor
                
            if (newDigital == LOW ){ //check case to see if digitalRead is LOW
            }
        }
   
   speed_0 = (4 / time0) * 0.681818; // calculates speed (mph), distance of 4 ft
   
   
   
   if (speed_0 > 60 || speed_0 < 1) return; // Check for crazy values and omit if so

   else if (speed_0 < 60 || speed_0 > 1){
     
        countTime = ((t0)/1000) / 60; // minutes since program started
        counter++;   // Add 1 to counter
        counterLeft++; // Add 1 to counterLeft
        trueSpeed = speed_0; // redeclare speed variable  
        concentration = counter / countTime; // calculates concentration (vehicles/min)
        displayData(); // displays data  
   }
}

void computeData_1() // calculates speed, direction and concentration 
{ 
   t1 = millis(); // timestamp for calculating data

   timeout1 = millis(); 
  
   while(!(analogVal <= 400 || analogVal >= 600)){
       analogVal = analogRead(analogPin);
       if ((float)millis() - timeout1 > 800) return; // timeout after 800ms (0.8 s)
   }
  
   time1 = ((float)millis() - t1) / 1000; // time between sensor dections (secs)
   delay(5000); // delay long time to ensure sensor is stable 

  
   delayTime = millis();        
   if (((float)millis() - delayTime) > 300){ // wait 300ms until Digital Pin is LOW
        
        newAnalog = analogRead(analogPin); // check to see motion is done
        newAnalogVal = newAnalog + 500; // absolute value idea  
        
            if (newAnalogVal > 600 ){ //check case to see if digitalRead is LOW
            }
        }

    speed_0 = (4 / time1) * 0.681818; // calculates speed (mph)

    if (speed_0 > 60 || speed_0 < 1) { // If speed is crazy small or large, omit it
      
        
      
        return; 
    }
    else if (speed_0 < 60 || speed_0 > 1) {
     
        countTime = ((t1)/1000) / 60; // minutes since program started
        counter++;   // Add 1 to counter
        counterRight++; // Add 1 to counterLeft
        trueSpeed = speed_0; // redeclare speed variable 
        concentration = counter / countTime; // calculates concentration (vehicles/min)
        displayData(); // display data    
   }
}

void displayData(){ // displays/saves data to Serial, LCD, and SD file
 
   // Displays Speed
 
   lcd.print("Speed=");
   lcd.print(trueSpeed);
   lcd.print(" MPH");
   lcd.setCursor(0,1);
   lcd.print("R = ");
   lcd.print(counterRight);
   lcd.print(", L = ");
   lcd.print(counterLeft);
  
  // open the file, note that only one file can be open at a time,
  // so you have to close this one before opening another.
  
  File dataFile = SD.open("ricelake.txt", FILE_WRITE);
  if (dataFile) {
    
    
    dataFile.print(trueSpeed);
    dataFile.print("        ");
    dataFile.print(counterLeft);
    dataFile.print("           ");
    dataFile.print(counterRight);
    dataFile.print("           ");
    dataFile.println(concentration);
    
    //dataFile.println(trafficData);
    dataFile.close();
    
    // print to the serial port too:
    Serial.print(trueSpeed);
    Serial.print("        ");
    Serial.print(counterLeft);
    Serial.print("            ");
    Serial.print(counterRight);
    Serial.print("            ");
    Serial.println(concentration);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening ricelake.txt");
  }    
  
}

void loop() {
  
  lcd.setCursor(0,0); // set cursor to Row 1, Col 1

  analogVal = analogRead(analogPin);
  digitalVal = digitalRead(digitalPin);
  
  if (analogVal <= 400 || analogVal >= 600) {

        computeData_0();
  }
 
  else if (digitalVal == HIGH) {
        
        computeData_1();  
  }
  
  else if (analogVal <= 400 || analogVal >= 600 && digitalVal == HIGH) {
        
  }
}

Again I apologize for the code as it is everywhere but in general it has been working so far minus this little hiccup of random outputs.