Keeping time with switch and sensor

Hi,

I want to keep the time to calculate the velocity of the liquids in my viscometer project.

Switch is attached to servo and starts the time.Reflective Object Sensor sense the liquids and stops the time.After some calculation with this elapsed time,i will get the viscosity of the liquid.

I wrote the code like this but it didn't work.Because when I switched ''on'' it keeps going to take the ''startTime''.Is there anyway to get startTime for once even so the switch sends a signal that is ''HIGH''.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Servo.h>
Servo myservo;
int switchStart = 4; //this switch connects to servo and it starts the time
int sensorStop = A2; //Reflective Object Sensor that stops the time
int switchState;
int sensorState;
unsigned long currentTime ;
unsigned long startTime ;
unsigned long elapsedTime ;

void setup() {

  Serial.begin(9600);
  pinMode(switchStart, INPUT);
  pinMode(sensorStop, INPUT);
  myservo.attach(41);
  lcd.init();
  lcd.backlight();
}

void loop() {

  switchState = digitalRead(switchStart);
  sensorState = digitalRead(sensorStop);
  switchState = map(switchState, 0, 1, 0, 180);
  myservo.write(switchState);

  if (switchState == HIGH   && sensorState == LOW) {

      startTime = millis();
      delay(5);

  }


  if (switchState == HIGH && sensorState == HIGH) {

      currentTime = millis();
      elapsedTime = (currentTime - startTime);

      Serial.println(elapsedTime);
      lcd.setCursor(0, 0);
      lcd.print(elapsedTime);

  }
}

Note: instead of using button,the switch is more useful for my project to re-make the experiment.

I do not get it.

  switchState = digitalRead(switchStart);
  sensorState = digitalRead(sensorStop);
  switchState = map(switchState, 0, 1, 0, 180);
  myservo.write(switchState);

  if (switchState == HIGH  && sensorState == LOW) {

switchState had a LOW or a HIGH (first line). Then map(...) was used on it (third line). I would like to believe that LOW==0 and HIGH==1 but cannot be sure that this is true now or in the future. Once map(...) gets used, switchState might be anything. Then there is an 'if' statement that asks (among other things) whether switchState is HIGH. Even if it was HIGH before the map(...) call, what is it after the map(...) call?

Furthermore,

To post:

  1. Use CTRL-T in the Arduino IDE to autoformat your code.
  2. Paste the autoformatted code between code tags (the </> button)
    so that we can easily see and deal with your code.

Yeah I see my mistake thanks a lot.I was trying to move the servo arm 180degree when switch is ''on''.That means HIGH==1 as you say.
So the order of the line should be like this: (Isn't it?)

void loop() {

  switchState = digitalRead(switchStart);
  sensorState = digitalRead(sensorStop);

  if (switchState == HIGH  && sensorState == LOW) {
    myservo.write(180);
    startTime = millis();
    delay(5);

  }

  if (switchState == HIGH && sensorState == HIGH) {

    currentTime = millis();
    elapsedTime = (currentTime - startTime);

    Serial.println(elapsedTime);
    lcd.setCursor(0, 0);
    lcd.print(elapsedTime);

  }
}

My purpose is that activating the servo by the switch and at the same time I would like to start the time.When servo is moved 180degree the stopper in the glass funnel releases the liquid.The liquid moves inside the glass pipe.At the end of the pipe there is a Reflective Object Sensor.When this sensor sense the liquid,it should stop the time.So,I can be able to get the time interval between these two actions.This is my purpose but I couldnt start the time by switch.When I turn on the switch it will stay on that position until the experiment complited.How can I do that?

Problem is that you are resetting the timer and driving the server continuously once the switch is turned HIGH and while waiting for the sensor to kick off. When it does, the timer will have been reset just moments before during the previous loop execution since at that time the switch was HIGH and the sensor LOW.

You need a way to prevent the first if-statement from running once the experiment starts, until the sensor kicks off. A flag that keeps track of whether or not the servo has been commanded to open the valve, and which gets reset once the sensor kicks (or the switch turns LOW).

Try this:

bool experimentRunning = false;

void loop() {
  switchState = digitalRead(switchStart);
  sensorState = digitalRead(sensorStop);
  if (!experimentRunning && switchState == HIGH  && sensorState == LOW) {
    myservo.write(180);
    startTime = millis();
    experimentRunning = true;
    delay(5);
  }
  if (experimentRunning && switchState == HIGH && sensorState == HIGH) {
    elapsedTime = (millis() - startTime);
    Serial.println(elapsedTime);
    lcd.setCursor(0, 0);
    lcd.print(elapsedTime);
    experimentRunning = false;  // or you could do this whenever switchState becomes LOW. This resets the experiment.
  }
}

You don't need currentTime variable. It's a waste of memory to do that. So I got rid of it.

Thanks AxeMurderer.Your code works well.However, in the second if loop the time is stopping for every drop of the liquids.For the first drop of the liquids your code gives the time interval as I desired.However, liquids are falling until the total amount of the liquid in glass funnel is consumed.Other than first drop,code is resetting it self and gives the time between the drops.How can I make the sensor sense and stop the timing for the first drop of the liquid?

I have tried to get the information as analog like this but nothing changed;

void loop() {

  switchState = digitalRead(switchStart);
  sensorState = analogRead(sensorStop);

  if (!experimentRunning && switchState == HIGH  && sensorState > 1000) {
    myservo.write(180);
    startTime = millis();
    experimentRunning = true;
    delay(5);
  }
  if (experimentRunning && switchState == HIGH && sensorState < 1000) {
    elapsedTime = (millis() - startTime);
    Serial.println(elapsedTime);
    lcd.setCursor(0, 0);
    lcd.print(elapsedTime);
    experimentRunning = false;  // or you could do this whenever switchState becomes LOW. This resets the experiment.
  }
  if (switchState == LOW) {
    myservo.write(0);           // to close the valve to prepare the system for the second experiment
  }
}

When the sensor sense nothing digital read is 1 and when it sense something it reads 0. So I have corrected the LOW and HIGH like this ;

void loop() {

  switchState = digitalRead(switchStart);
  sensorState = digitalRead(sensorStop);

  if (!experimentRunning && switchState == HIGH  && sensorState == HIGH) {
    myservo.write(180);
    startTime = millis();
    experimentRunning = true;
    delay(5);
  }
  if (experimentRunning && switchState == HIGH && sensorState == LOW) {
    elapsedTime = (millis() - startTime);
    Serial.println(elapsedTime);
    lcd.setCursor(0, 0);
    lcd.print(elapsedTime);
    experimentRunning = false;  // or you could do this whenever switchState becomes LOW. This resets the experiment.
  }
  if (switchState == LOW) {
    myservo.write(0);           // to close the valve to prepare the system for the second experiment
  }
}

By the way, I am sorry for my poor english and replying late.We have got 8 hours differences :slight_smile: