Alright, I tried the interrupt approach... it works beautifully. I hooked my '168 up with the 20x4 LCD, took it to school (I'm an EE student) and fed it a TTL-level square wave from a decent function generator. It measures pulsewidths down to about 16 µs (in 4 µs increments as per the micros() function) on a 15 kHz square wave. I confirmed the readings with an oscilloscope.
At shorter durations/higher frequencies, the code would still spit out readings, but they weren't accurate. Somewhere between 16 and 20 kHz, the readings would start fluctuating all over the place. 15 kHz with a short enough duty cycle would result in a reading stuck at 12 µs, despite the actual duration being shorter. I assume these limitations are a matter of the time it takes to execute the interrupt code.
The code:
Code:
#include <LiquidCrystal.h>
void displayUpdate(unsigned long present, unsigned long toggle, unsigned long interval, unsigned long total);
void interruptZero();
LiquidCrystal lcd(4,7,5,8,9,10,11);
unsigned long presentTime;
unsigned long onToggleTime;
unsigned long intervalTime;
unsigned long totalTime;
unsigned long lastUpdate;
void setup()
{
lcd.begin(20,4); //initialize display
lcd.clear();
pinMode(2,INPUT); //set pin 2 to receive pwm signal
attachInterrupt(0,interruptZero,CHANGE); //declare the interrupt and set it to run any time the pin (#2) state changes
}
void loop()
{
presentTime = micros(); //make note of the present time for display purposes
if(presentTime > (lastUpdate + 100000)) //update display every 10th of a second
{
displayUpdate(presentTime,onToggleTime,intervalTime,totalTime);
lastUpdate = presentTime;
}
}
void interruptZero()
{
if(digitalRead(2)>0) //if the PWM input pin is high when interrupt called, update onToggleTime
{
onToggleTime = micros();
}
else //otherwise, update intervalTime and calculate totalTime
{
intervalTime = micros() - onToggleTime;
totalTime = totalTime + intervalTime;
}
}
void displayUpdate(unsigned long present, unsigned long toggle, unsigned long interval, unsigned long total) //display update sub
{
lcd.setCursor(0,0);
lcd.print("clock: ");
lcd.print(present);
lcd.setCursor(0,1);
lcd.print("togPoint: ");
lcd.print(toggle);
lcd.setCursor(0,2);
lcd.print("interval: ");
lcd.setCursor(10,2);
lcd.print(interval);
lcd.setCursor(0,3);
lcd.print("tally: ");
lcd.print(total);
}