Digital Input Trigger

I am new to microcontrollers and C programming. I am using an Orangutan SVP-1284 controller.

I have 2 external square wave sources, each around 30 Hz. I need to make two time measurements from them. First is just a simple frequency counter to display the frequency of each signal individually. This is basically just the time from the beginning of one pulse to the beginning of the next pulse. The second is to measure the phase shift between the two of them. Assuming I feed them into two of the Digital Inputs, say D2 and D3, I need to start a timer on the leading edge of one and stop the timer on the leading edge of the other. I’ve been though the Pololu documentation, but cannot find a way to trigger only when the pins first go high or low.

Any help would be greatly appreciated.

Hi Kirk,

Take a look at the pulse library: pololu.com/docs/0J18/8 located in the Pololu AVR Library Command Reference guide. I have used this to measure pulse widths and frequency but not to measure phase. There is a structure member called lastPCTime which may help.

Mike

Hi Mike,

Yes, that is exactly what I was looking for. Thank you. I had looked at the Library command reference (pololu.com/docs/0J18) online, but immediately downloaded the pdf version from the link at the top of the page. Turns out the pdf and online versions are different and the pulse info is not in the pdf, no wonder I missed it.

I am however still having troubles that stem from just not knowing what I am doing, (the being new to this part). In AVR Studio, I choose new project, select AVR GCC, check Create Initial File and Folder. Once in the project, I go to the Project tab, select Config Options, go to the library tab and include libpolou_atmega1284p.a. I then start the program with ‘#include <pololu/orangutan.h>’ and ‘int main ()’. Is this basically correct? I have tried a few variations on the rest and have not gotten anything to work. If anyone has time and would be willing to post code that just prints the results of the getlasthighpulse function or if anyone has a frequency counter they could share I would really appreciate it. I’m sure I’m just making basic syntax mistakes and would really like a quick sample to look at.

One error that I frequently get:
…/Timer.c:29: error: ‘getLastHighPulse’ undeclared (first use in this function)

Hello.

Have you seen the example programs that are included with the Pololu AVR Library? I recommend you start by trying to understand and modify those. The pulsein1 and pulsein2 examples show two ways to measure pulses using the OrangutanPulseIn code. I think pulsein2 measures the duty cycle and frequency of the PWM signal used to play various notes on the buzzer, so that might be the closest to what you’re trying to do. If you have any questions or trouble getting them to work, please let me know.

- Ben

Thanks Ben, I had missed those. I seem to have the frequency counter part working just fine on two pins now, but I am still having trouble measuring the delay between the two. Again, the input on each pin is a square wave of about 30 hz (from two different sources) and the goal is to measure their phase difference. For the purpose of troubleshooting, I have stripped out all of the working parts and re-written a short bit to just show the start time of each input and then to display the difference between them. I have tried a few different versions of this, but I am not getting the result I need. Usually both inputs report the same time or very close to it and the difference jumps around, and is never correct when verified with a scope. I’m sure I’m just using the commands wrong, but I’m out of ideas. Any help would be appreciated.

Kirk

Below is a sample of one non-working version. Compiles without errors or warnings, but does not produce the correct result.

#include <pololu/orangutan.h>
const unsigned char pulseInPins[] = { IO_C0, IO_C1 };
int main()

{
pulse_in_start(pulseInPins, 2);
set_digital_input(IO_C0, PULL_UP_ENABLED);
set_digital_input(IO_C1, PULL_UP_ENABLED);
clear(); // clear LCD
time_reset();

while (1) // main loop
{
struct PulseInputStruct pulse_info;

//Select pin 0 (IO_C0) as input
//Read last Pin Change time for Pin 0 in ticks and convert to milliseconds
//Set start_time variable to last Pin Change time for Pin 0 in milliseconds
get_pulse_info(0, &pulse_info);
long start_time = (pulse_to_microseconds(pulse_info.lastPCTime)/1000);

//Select pin 1 (IO_C1) as input
//Read last Pin Change time for Pin 1 in ticks and convert to milliseconds
//Set stop_time variable to last Pin Change time for Pin 1 in milliseconds
get_pulse_info(1, &pulse_info);
long stop_time = (pulse_to_microseconds(pulse_info.lastPCTime)/1000);

//Display Values of start_time and stop_time
lcd_goto_xy(0, 0);
print_long(start_time);

lcd_goto_xy(9, 0);
print_long(stop_time);

if (start_time > stop_time)
{
long delta = (start_time - stop_time);
lcd_goto_xy(0,1);
print("-");
print_unsigned_long(delta);
}
else
{
long delta = (stop_time - start_time);
lcd_goto_xy(0,1);
print("+");
print_unsigned_long(delta);
}
delay_ms(500);
}
}

I haven’t really looked at your code in detail (it would help if you could provide information about what kind of results you’re getting), but one problem is that you aren’t necessarily measuring the time difference between the same edge on both channels. The member lastPCTime just holds the time that the last pin change occurred, but it doesn’t tell you whether that was a rising edge or a falling edge. If you want to measure the phase difference between your two signals you want the time difference between the rising edge on one and the rising edge on the other (or the falling edge and falling edge). At the very least, you need to know which two edges you have measured the time difference between. You can tell which type of edge happened at lastPCTime by looking at the current state of the channel. If the pulse_info member inputState is 1, the lastPCTime is the time of the last rising edge on that channel, else it is the time of the last falling edge.

Also, when you post code, please use the [ code ][/ code ] tags or press the “code” button so that it is formatted nicely and easier to read.

- Ben