Hi,
Is it possible to read the pulse width of an input PWM signal on PIND for atmega 168? If so how is it done exactly?
Hi,
Is it possible to read the pulse width of an input PWM signal on PIND for atmega 168? If so how is it done exactly?
could I do this
unsigned int pulse_width = duration; Start Timer at 50 Hz. while(PIND & (1 << PIND2)) { pulse_width++; } negative_pulse_width++; } // End timer after 4 cycles at 50 Hz Divide positive_pulse_width / 3 Divide negative_pulse_width / 3 pulse _width = positive_pulse_width / 3;
Does this seem right?
best to use the input capture feature of the AVR, so that you get accurate cycle measurements. You can measure in software, jsut be aware that you need to know how many cycles your measuring loop takes in order to calculate the time.
I don't have the choice to use ICP1. I am forced to use PIND. I need some way to tell when I have a rising edge or a falling edge in the input pulse to PIND?
The mega168 has pin change interrupts available for all I/O pins. Using that will be much more accurate than polling.
I read about pin change interrupts and that I can configure PIND as an alternate function for interrupt, but I did not understand it. Is there a tutorial or can anyone provide sample code for me?
Here is some code that I wrote to measure pin change interrupt. I am curious as to how to measure the counter before and after the interrupt so I can return the pulse-width from my pulsin function ?
WORD pulsein(int pin_number) { switch(pin_number) { case 4: PCMSK2 |= (1<<PCINT20); // tell pin change mask to listen to pin21 break; case 5: PCMSK2 |= (1<<PCINT21); // tell pin change mask to listen to pin20 break; case 1: PCMSK2 |= (1<<PCINT17); // tell pin change mask to listen to pin17 break; PCICR |= (1 << PCIE2); // enabled interrupts on PCINT23..16 pin SREG |= (1 << 7); // enable global interrupts } } SIGNAL (SIG_PCINT) { // One of pins 21, 20, or 17 just changed states // check if rising or lower based on pin input // start timer to measure pulse width // One of pins 21, 20, or 17 just changed states // check if rising edge on pin input TCCR2B |= (1 << CS22); while(PIND & (1 << PIN4)) //rising edge { // start timer to measure pulse width pulse_start = start timer } while(PIND & (1<<PIN5)) { // start timer to measure pulse width pulse_start = start timer } while(PIND & (1<<PIN1)) { // start timer to measure pulse width pulse_start = start timer } }
ccccc
Usually I still use timer for measuring pulse width signal. uint16_t measure(uint8_t PINx) { do { // Init timer as suitable for your need init_timer1(); // wait here if the signal if still low while(bit_is_clear(PIND,PINx)); // run the timer start_timer1(); //wait if the signal still high and overflow has not occured. while((bit_is_set(PIND,PINx)&&(bit_is_clear(TIFR1,TOV1)); // stop the timer stop_timer1(); // repeat if overflow } while(bit_is_set(TIFR1,TOV1)) return TCNT1; } uint16_t pulse1, pulse2 = 0; int main(void) { pulse1 = measure(PIN1); pulse2 = measure(PIN5); //.. //.. //.. //.. while(1); return 0 }
:D