Accurate time calculation circuit in Mili seconds for relay pick up and drop time measurements

Hello everyone,

Thanks in advance.

I am creating a circuit for measuring the relay pick up and drop time measurements calculation. I have received the accurate measurements but after 1 or 2 operation my lcd display goes with characters. And I am planning to use lm 7805 ic to step down the voltage which is parallel to relay 24 volt and it's given to aurdino through an opto coupler.

If any one have the better solution for accurate and robust circuit. Please help me.

I share my codings below,

#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

unsigned long time_start;
unsigned long time_end;
unsigned long time;

int PD_start; // value of the start-Photodiode
int PD_end; // value of the end-Photodiode
int Werte[100];
long start;
int i;
//unsigned long d = 320000;
float multiplier;

#define FASTADC 1

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup()
{
Serial.begin(9600);

pinMode(8, INPUT);
digitalWrite(8, HIGH);
pinMode(9, INPUT);
digitalWrite(9, LOW);
lcd.begin(16, 2);
lcd.clear();

#if FASTADC

cbi(ADCSRA,ADPS2) ; // ADPS2 auf 0 gesetzt
sbi(ADCSRA,ADPS1) ; // ADPS1 auf 1 gesetzt
sbi(ADCSRA,ADPS0) ;

#endif
multiplier = 0.70;

lcd.clear();
lcd.setCursor(1,0);
lcd.print("Initializing...");
lcd.setCursor(10,1);
lcd.print("A/");

delay(1000);

// ADPS2 ADPS1 ADPS0 Division factor
// 0 0 0 1 nicht schneller als 2
// 0 0 1 2
// 0 1 0 4
// 0 1 1 8
// 1 0 0 16
// 1 0 1 32
// 1 1 0 64
// 1 1 1 128 (Standard)

}

void loop()

{
lcd.clear();
lcd.setCursor(1,0);
lcd.print("SELECT T1/T2");
delay(1000);
if(digitalRead(8) == LOW)
{
lcd.clear();
lcd.setCursor(1,0);
lcd.print("T1 SELECTED");
delay(1000);

Serial.print(analogRead(A0));
Serial.print(" ");
Serial.println(analogRead(A1));
delay(100);

PD_start = analogRead(A0);   // measuring the brightness of the starting-PD without projectile
delay(20);
PD_end = analogRead(A1);     // measuring the brightness of the ending-PD without projectile
delay(1000);

lcd.clear();
Serial.print("PD-start: ");
Serial.print(PD_start);
Serial.print(" , PD-end: ");
Serial.println(PD_end);

lcd.setCursor(0,0); // to be added for testing
lcd.print("PD1: ");
lcd.print(PD_start);
lcd.setCursor(0,1);
lcd.print("PD2: ");
lcd.print(PD_end);

delay(2000);

lcd.clear();

lcd.setCursor(0,0);
lcd.print("start test");
lcd.setCursor(0,1);
lcd.print("...             ");

delay(10); 

unsigned long d = 200000;
while(analogRead(A0) < 200) //while(analogRead(A0) > PD_start * multiplier)
{
// waiting for the projectile
}

time_start = micros();      // start-time in µs

while(analogRead(A1) < 200) // while(analogRead(A1) > PD_end * multiplier)
   {
    // waiting for the projectile
   }

time_end = micros();        // end-time in µs

time = time_end - time_start;   // flight-time in µs

PD_start = analogRead(A0);   // newly added measuring the brightness of the starting-PD without projectile
delay(20);
PD_end = analogRead(A1);     // measuring the brightness of the ending-PD without projectile
delay(1000);
Serial.print("Time: ");
Serial.println(time);

lcd.clear(); // newly added  

lcd.setCursor(0,0); // to be added for testing
lcd.print("PD1: ");
lcd.print(PD_start);
lcd.setCursor(0,1);
lcd.print("PD2: ");
lcd.print(PD_end);

delay(1000);
lcd.clear(); // newly added
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.clear();

lcd.setCursor(0,0);
lcd.print("t = ");
lcd.setCursor(4,0);
lcd.print(time);
lcd.print(" us");

if(time < d)

{
lcd.setCursor(1,1);
lcd.print("PASS");
delay(100);
}
else{
lcd.setCursor(1,1);
lcd.print("FAIL");
delay(100);
}
delay(50000);
}

if(digitalRead(9) == HIGH)

{

lcd.clear();

lcd.setCursor(1,0);
lcd.print("T2 SLECTED");
delay(1000);

 Serial.print(analogRead(A2));
Serial.print("   ");
Serial.println(analogRead(A3));
delay(100);

PD_start = analogRead(A2);   // measuring the brightness of the starting-PD without projectile
delay(20);
PD_end = analogRead(A3);     // measuring the brightness of the ending-PD without projectile
delay(1000);

lcd.clear();
Serial.print("PD-start: ");
Serial.print(PD_start);
Serial.print(" , PD-end: ");
Serial.println(PD_end);

lcd.setCursor(0,0);
lcd.print("PD1: ");
lcd.print(PD_start);
lcd.setCursor(0,1);
lcd.print("PD2: ");
lcd.print(PD_end);

delay(2000);

lcd.clear();

lcd.setCursor(0,0);
lcd.print("start test");
lcd.setCursor(0,1);
lcd.print("...             ");

delay(10); 

unsigned long d = 50000;
while(analogRead(A2) > PD_start * multiplier)
{
// waiting for the projectile
}

time_start = micros();      // start-time in µs

while(analogRead(A3) > PD_end * multiplier)
   {
    // waiting for the projectile
   }

time_end = micros();        // end-time in µs

time = time_end - time_start;   // flight-time in µs


 PD_start = analogRead(A2);   //  newly added measuring the brightness of the starting-PD without projectile
delay(20);
PD_end = analogRead(A3);     // measuring the brightness of the ending-PD without projectile
delay(1000);


lcd.clear();// newly addded 
lcd.setCursor(0,0);
lcd.print("PD1: ");
lcd.print(PD_start);
lcd.setCursor(0,1);
lcd.print("PD2: ");
lcd.print(PD_end);

delay(2000);





Serial.print("Time: ");
Serial.println(time);

lcd.clear();// newly addded 
 lcd.setCursor(0,0);
lcd.print("                ");
lcd.setCursor(0,1);
lcd.print("                ");
    
lcd.setCursor(0,0);
lcd.print("t = ");
lcd.setCursor(4,0);
lcd.print(time);
lcd.print(" us");

    if(time < d)

{
lcd.setCursor(1,1);
lcd.print("PASS");
delay(100);
}
else{
lcd.setCursor(1,1);
lcd.print("FAIL");
delay(100);
}

 delay(50000);

}

}

What does that mean, please?

Welcome to the fora.

I scanned your code, await seeing it posted in good format and using one of the several ways you can get your code out to us looking pretty, ready to copy &c.

You can "Autoformat" using the IDE tool for that, then use "Copy for Forum", then paste it here.

Or use the </> tool in the message composition window.

Now the real question: do you have a version of all that code that does in no way use the LCD, so you can see the logic without the added complexity of running the display?

a7

Kind of malfunction.

Could please share me some circuit for measuring A to B timing accurate. This for 24 volt relay pick up and drop time measurements

You probably have no freewheeling diode on your relay, causing interference. Please edit your code and put it in code tags, as requested earlier in the thread. Please also post a schematic of your hardware.

Oh, they're the worst.

Relays are switches and their contacts bounce just like switches.

Work on this after you've resolved the 'going to characters' thing.

Or the relay is powered from the same supply as the controller. As stated, post a schematic, even a photo of a hand-drawn one, of the circuit as it is on the breadboard.

Please see the hand drawn circuit diagram.
Hope it will be understanding


It's a hand drawn. Thanks bro

Your hand drawn diagram is fine. But, why are you using analog pins for an obviously digital project?

I have used analog pins for fast reading of inputs as it's time based and for more accuracy. I wanted try the LM 7805 voltage regulators instead of resistor bridge circuit to step down voltage. But I have doubt that will it make delay for out put.

I tried the digital pins but the timings are not accurate. The relay operates in 20 Milliseconds. I need to measure this time accurate.

After some research in aurdino forum I have found this analog pin fast ADC is the best way to read in high speed.

I will try to add one free wheel diode to the relay side. I have isolated relay and controller using an opto coupler as well.

Thanks brothers. I never expected this much support from this forum. I am just beginner in aurdino

Then you need to use digital interrupts. One pin change interrupt for the relay command and another pin change interrupt for the relay contact change.

1 Like

It takes around 100 microseconds to read an analogue input using analogRead on an AVR, but only a handful of microseconds to digitalRead an input. Reading the port register directly is even quicker, if less portable

Furthermore, you are polling the analogRead() and will most surely not be reading it at the times you need it.

I don't have much idea about digital interrupts coding. Started learning of them.

You will love the opportunities they will open for you!

Hi all. I have tried some codes with interrupts now. Could you guys please check if you have time.
This interrupt pins will be connected to the relay and switch. So there will be a chance of de-bounce.

Can you please help me to avoid the switch de-bounce issue.
the code is given below

#include <LiquidCrystal_I2C.h>

#include <Wire.h>

#include <Adafruit_LiquidCrystal.h>

//int seconds = 0;

Adafruit_LiquidCrystal lcd_1(0);

unsigned long x;
unsigned long y;
unsigned long time;
int z;
int w;
long wait;
int test = 0;
int reset = 0;


void setup()

{
  Serial.begin(9600);

  pinMode(8, INPUT);
  digitalWrite(8, HIGH);
  pinMode(9, INPUT);
  digitalWrite(9, LOW);
  pinMode(6, INPUT);
  digitalWrite(6, LOW);

  pinMode(3, INPUT);
  lcd_1.begin(16, 2);


  lcd_1.clear();
  lcd_1.setCursor(1, 0);
  lcd_1.print("Initializing...");
  lcd_1.setCursor(10, 1);
  lcd_1.print("A/");

  delay(1000);

  attachInterrupt(digitalPinToInterrupt(2), START, CHANGE);  //  function for creating external interrupts at pin2 on Rising (LOW to HIGH)
  attachInterrupt(digitalPinToInterrupt(3), STOP, CHANGE);   // change to be given for both
}

void loop() {


  z = 0;

  w = 0;

  lcd_1.clear();

  lcd_1.setCursor(1, 0);
  lcd_1.print("SELECT T1/T2");
  delay(1000);
  if (digitalRead(8) == LOW) {

    reset = 0;

    lcd_1.clear();

    lcd_1.setCursor(1, 0);
    lcd_1.print("T1 SELECTED");

    delay(1000);  // newly added

    z = 0;
    w = 0;  // variables newly added
    lcd_1.clear();

    lcd_1.setCursor(1, 0);
    lcd_1.print("Start test");
    delay(1000);



    Serial.flush();
    Serial.print("bx: ");
    Serial.print(x);
    Serial.print("bw: ");
    Serial.print(w);
    Serial.print("by: ");
    Serial.print(y);
    Serial.print("bz: ");
    Serial.print(z);



    interrupts();


    Serial.print("x: ");
    Serial.print(x);
    Serial.print("w: ");
    Serial.print(w);
    Serial.print("y: ");
    Serial.print(y);
    Serial.print("z: ");
    Serial.print(z);


    while (z < 1) {
      //wait for the input
    }

    while (z > w) {
      lcd_1.clear();
      lcd_1.begin(16, 2);
      lcd_1.setCursor(1, 0);
      lcd_1.print("error ");  //print error// error message
      delay(2000);
    }
    {

      time = y - x;
      lcd_1.clear();
      lcd_1.begin(16, 2);
      lcd_1.setCursor(1, 0);
      lcd_1.print("tim: ");
      lcd_1.print(time);
      delay(2000);
      lcd_1.setCursor(1, 1);

      lcd_1.print("L1 to Start");


      Serial.print("Ax: ");
      Serial.print(x);
      Serial.print("Aw: ");
      Serial.print(w);
      Serial.print("Ay: ");
      Serial.print(y);
      Serial.print("Az: ");
      Serial.print(z);



      while (reset < 1) {


        if (digitalRead(6) == HIGH) {
          reset = 1;
        }
      }
    }
  }

  if (digitalRead(9) == HIGH)

  {
    reset = 0;

    lcd_1.clear();

    lcd_1.setCursor(1, 0);
    lcd_1.print("T2 SELECTED");

    delay(1000);  // newly added

    z = 0;
    w = 0;  // variables newly added
    lcd_1.clear();

    lcd_1.setCursor(1, 0);
    lcd_1.print("Start test");
    delay(1000);



    Serial.flush();
    Serial.print("bx: ");
    Serial.print(x);
    Serial.print("bw: ");
    Serial.print(w);
    Serial.print("by: ");
    Serial.print(y);
    Serial.print("bz: ");
    Serial.print(z);



    interrupts();


    Serial.print("x: ");
    Serial.print(x);
    Serial.print("w: ");
    Serial.print(w);
    Serial.print("y: ");
    Serial.print(y);
    Serial.print("z: ");
    Serial.print(z);


    while (z < 1) {
      //wait for the input
    }

    while (z > w) {
      lcd_1.clear();
      lcd_1.begin(16, 2);
      lcd_1.setCursor(1, 0);
      lcd_1.print("error ");  //print error// error message
      delay(2000);
    }
    {

      time = y - x;
      lcd_1.clear();
      lcd_1.begin(16, 2);
      lcd_1.setCursor(1, 0);
      lcd_1.print("time: ");
      lcd_1.print(time);
      delay(1000);
      lcd_1.setCursor(1, 1);

      lcd_1.print("L1 to Start");


      Serial.print("Ax: ");
      Serial.print(x);
      Serial.print("Aw: ");
      Serial.print(w);
      Serial.print("Ay: ");
      Serial.print(y);
      Serial.print("Az: ");
      Serial.print(z);



      while (reset < 1) {


        if (digitalRead(6) == HIGH) {
          reset = 1;
        }
      }
    }
  }
}


void START() {
  x = millis();
  ++w;
}

void STOP() {
  y = millis();
  ++z;
}

(why have you changed names?)

When you were reading about interrupts, did you miss the bit about making shared variables volatile?