How to measure pulse width using interrupts or hardware timers for arduino

Thread Starter

Vikram50517

Joined Jan 4, 2020
81
Hello y'all , I'm in a bit of a pickle. I want to measure the pulse width of my smartphone flashlight pulses. The circuit has a photodiode, which is connected to an op-amp and from the op-amp, i connected its output to arduino analog pin A0. The pulse width is around 750 us. I used a simple software snippet to measure pulse width, but it is missing pulses below 1 ms width. Basically my pulse is high when it has a voltage of above 19.52 mV , else it is a Low pulse. I want to measure the pulse width of the high pulses. Requesting help from the pros here. Let me Share my Sketch

Sketch:

C-like:
#define cellpin A0

const float mvc=4.88;

float counts=0;

float mv=0;

int ctr=0;

long int t1,t2;

void setup() {

// put your setup code here, to run once:

Serial.begin(9600); }


void loop() {

// put your main code here, to run repeatedly:

counts=analogRead(cellpin);

mv=counts*mvc; // this is the output voltage


if(mv>19.52 && ctr==0){


t1 = micros();

ctr=1; // ctr is used for detecting edges

}

if(mv<19.52 && ctr==1){

t2=micros();

Serial.print("The on-pulse duration in microsecond is "); /* if the output voltage(mv) is higher than 19.52 mV, consider it a high, else consider it a Low pulse.*/

Serial.println(t2-t1); // the pulse width in us


ctr=0;

t1=0;

t2=0;

}

}
 

KeithWalker

Joined Jul 10, 2017
2,351
Why don't you use the Arduino built-in pulseIn() function. It uses interrupts and will measure pulses fro 10uS to 3S.

The example prints the time duration of a pulse on pin 7.

C-like:
int pin = 7;

unsigned long duration;


void setup() {

Serial.begin(9600);

pinMode(pin, INPUT);

}


void loop() {

duration = pulseIn(pin, HIGH);

Serial.println(duration);

}
 
Last edited by a moderator:

Thread Starter

Vikram50517

Joined Jan 4, 2020
81
Tried it, pulse duration was just 0 , even when i flash , please corect me where i went wrong

Sketch:
#define cellpin A1
unsigned long duration;
const float mvc=4.88;
float counts=0;
float mv=0;
int ctr=0;
long int t1,t2;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); }

void loop() {
// put your main code here, to run repeatedly:
counts=analogRead(cellpin);
mv=counts*mvc; // this is the output voltage


if(mv>19.52){
duration = pulseIn(cellpin, HIGH);
Serial.println(duration);
}
 

sagor

Joined Mar 10, 2019
695
It can easily take 100us or more to do just the analog read, so you don't get to the pulsein statement until part of the pulse is over.
Also, with a 5V reference, the best resolution you can get is about 4.9mV, plus or minus a digit or two. So, if the pulse is not a pure square wave, but a sine wave (or smoothed/rounded square wave), you may be missing it altogether.
There may be some way to have an external voltage level detection of the 19.52mV and then trigger an interrupt to measure duration (skip measuring voltage with Arduino).
EDIT: Also, not sure if you can do analog read and a digital "pulsein" command on the same pin without some complications. Arduino has to switch modes. Also, pulsein looks for logic levels, like 2.4V or higher or 0.8v or lower (TTL levels as examples). Not sure if pulsein can distinguish between 100mV and 20mV, both would be low.
 

sagor

Joined Mar 10, 2019
695
Same issue with tachometer project, it would require a logic level (high) to trigger. The OP has only a 19-20mV signal, that will not trigger a digital input interrupt. He needs an external circuit to change 19mV+ to 4 to 5V
 

KeithWalker

Joined Jul 10, 2017
2,351
Yes, I agree. The pulse is not big enough for the Arduino to see it. It needs the photodiode to be connected to a comparator.
What exactly is the module you are using now? Is it a purchased module or one you have built yourself? Details please.
 

Thread Starter

Vikram50517

Joined Jan 4, 2020
81
Yes, I agree. The pulse is not big enough for the Arduino to see it. It needs the photodiode to be connected to a comparator.
What exactly is the module you are using now? Is it a purchased module or one you have built yourself? Details please.
Attached below is my reciever circuit, the op-amp is a LM-358 dual op-amp , with a 10 V Vcc. The Vout in the last stage is connected to arduino pin A0 , this is my setting
1650520745372.png


PS : The reciever perfectly works if my pulse width is above 3 ms, the problem comes if my pulse width is below 3 ms
 
Last edited:

KeithWalker

Joined Jul 10, 2017
2,351
Attached below is my reciever circuit, the op-amp is a LM-358 dual op-amp , with a 10 V Vcc. The Vout in the last stage is connected to arduino pin A0 , this is my setting.
PS : The reciever perfectly works if my pulse width is above 3 ms, the problem comes if my pulse width is below 3 ms
There are two problems with your circuit.
The first is your choice of op-amp. The LM358 has a typical slew rate of 0.3 V/us so a 5V output pulse will take 18uS to get there. Your circuit will be much slower because the 18pF feedback capacitor and output 0.1uF filter capacitor will integrate the step function of the input signal.

The absolute maximum rated input pin voltage of the Arduino is VCC + 0.5V. With a supply of 10V on the amplifier, there is a chance that the maximum output could overload the input pin and damage it.
 

KeithWalker

Joined Jul 10, 2017
2,351
There are two problems with your circuit.
The first is your choice of op-amp. The LM358 has a typical slew rate of 0.3 V/us so a 5V output pulse will take 18uS to get there. Your circuit will be much slower because the 18pF feedback capacitor and output 0.1uF filter capacitor will integrate the step function of the input signal.

The absolute maximum rated input pin voltage of the Arduino is VCC + 0.5V. With a supply of 10V on the amplifier, there is a chance that the maximum output could overload the input pin and damage it.

I recommend that you replace the LM358 with a comparator e.g. LM393, use a 5V supply and remove the feedback and filter circuits.
 
Top