Pin read with Micros not working

Hi

I wrote this sketch below to read a pulse (400us HIGH and 400us LOW ) using micros but my effort is total rubbish!

PulseIn is a 1000 times better than what I wrote but not very accurate.

Please help there must be a better option.

unsigned long start, finished, elapsed;
 
void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT); // start - Stop input pulse
}
 
void displayResult()
{
  elapsed=finished-start;
  Serial.println(elapsed);
  delay(500);
}
 
void loop()
{
  if (digitalRead(2)==HIGH)
  {
    start=micros();
  }
  if (digitalRead(2)==LOW)
  {
    finished=micros();
    displayResult();
  }
}

This is the Serial monitor output.

8
500088
1000396
12
8
500084
1000388
12
12
8
500092
1000392
8
500084
1000396
4
500084
1000384
8
500088
1000388
12

You will need pin change detection; detect when the pin goes high, not when it is high. As it stands currently, you keep setting the start variable while the pin is high.

You might also suffer from button bounce. When you press or release a button, it goes a few times high-low-high... or vice versa.

What is the source of your signal?

Thanks

I do not know how to change the pin detection in C.

Done the same thing with a PIC a few years back in assembler,still finding my way around Arduino.

My pulses is generated with a PIC that increments PORTB every 1uS from PORTB I get 1,2,4,8,16uS on a rotary

switch.

These pulses is then divide by 10 the output is again divided by 10 ....6 times on a 2nd rotary switch.

Now I select 4uS times 100 and this is my 400uS HI pulse.

I do not know how to change the pin detection in C.

Look at the StateChangeDetection example in the IDE

I found this example on the Forum page just a few post down from mine.

I modify the code by removing the leds and use one input and micros.

The readings is much closer but still not 400uS.

Thanks for the advice I will look into that.

while(digitalRead(2)==HIGH);
start = micros();

while(digitalRead(2)==LOW);
finished = micros();

displayResult();

My reading varies between 348uS and 360uS.(Should be 400uS) with the above changes.

I modified the StateChange example - unless I made a messup of it but this is even worse.

This 40 000uS.

4293967132
1000972
1000972
4293966604
4293966604
1000960
1000960
4293966604
4293966604
1000976
1000976

And this is my code ,

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to

const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses

int buttonState = 0;         // current state of the button

int lastButtonState = 0;     // previous state of the button

uint32_t start,elapseTime,endtime;

void setup()
{
 
  pinMode(buttonPin, INPUT); // initialize the button pin as a input
  
  pinMode(ledPin, OUTPUT);// initialize the LED as an output:
  
  Serial.begin(9600);// initialize serial communication:
}
void loop() 
{
  buttonState = digitalRead(buttonPin);// read the pushbutton input pin:

  if (buttonState != lastButtonState) // compare the buttonState to its previous state
  {
    if (buttonState == HIGH) // if the state has changed, increment the counter
    {
      start = micros(); // if the current state is HIGH then the button went from off to on:
    }
    else 
    {
      endtime = micros();// if the current state is LOW then the button went from on to off:
    }
   
  }
 
  lastButtonState = buttonState; // save the current state as the last state, for next time through 

  elapseTime = endtime - start ;

  Serial.println(elapseTime);

  delay(500);
  

}

What is the purpose of the 500 millisecond delay between each read of the input ?

There is an example in the IDE called ‘blink without delay’.
Use this technique to replace your delay().

If you want accurate timing, try the Input Capture feature of Timer1. It will record the time of a pulse edge with a resolution of 1 clock tick (1/16th of a microsecond). Read the time of the falling edge and subtract the time of the rising edge to get the pulse width. Because it is a hardware function you have to use the ICP1 (Input Capture Pin, Timer1) pin which, on the Arduino UNO, is Pin 8. Because the time is saved in the Input Capture Register before the interrupt is signaled, there is no problem with interrupt latency.

// Measures the width of positive pulses on Arduino UNO Pin 8 (ICP1)
// Should work for up to 65535 clock cycles (4095 microseconds)
void setup()
{
  Serial.begin(115200);

  noInterrupts ();  // protected code
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;

  TIFR1 |= (1 << ICF1); // clear Input Capture Flag so we don't get a bogus interrupt

  // start Timer 1, no prescaler
  TCCR1B |= (1 << CS10); // plus Input Capture Edge Select (rising on D8)
  TCCR1B |= (1 << ICES1); // Input Capture Edge Select (1=Rising, 0=Falling)

  TIMSK1 |= (1 << ICIE1); // Enable Timer 1 Input Capture Interrupt Enable
  interrupts ();
}

volatile uint16_t PulseTime = 0;

ISR(TIMER1_CAPT_vect)
{
  static uint16_t RisingEdgeTime = 0;
  static uint16_t FallingEdgeTime = 0;

  if (PulseTime == 0)
  {
    if (TCCR1B & (1 << ICES1))
    {
      // Rising Edge
      RisingEdgeTime = ICR1;
      TCCR1B &= ~(1 << ICES1); // Switch to Falling Edge
    }
    else
    {
      // Falling Edge
      FallingEdgeTime = ICR1;
      TCCR1B |= (1 << ICES1); // Switch to Rising Edge
      PulseTime = FallingEdgeTime - RisingEdgeTime;
    }
  }
}

void loop()
{
  uint16_t pulseTime = 0;
  noInterrupts();
  pulseTime = PulseTime;
  interrupts();

  // If a sample has been measured
  if (pulseTime)
  {
    // Display the pulse length in microseconds
    Serial.println(pulseTime / 16.0, 2);

    delay(1000);  // Slow down output

    // Request another sample
    noInterrupts();
    PulseTime = 0;
    interrupts();
  }
}