measuring pulse width input on PIND

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The mega168 has pin change interrupts available for all I/O pins. Using that will be much more accurate than polling.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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
   }
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ccccc

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
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

KISS - Keep It Simple Stupid!