Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
kunalpowar1203
PostPosted: Apr 05, 2012 - 04:03 AM
Newbie


Joined: Mar 05, 2012
Posts: 9


hi. am doing a project which asks for taking 1 square wave signal of 50% duty cycle as input, get its characteristics and generate 2 signals which are in quadrature and of same frequency. am using ATmega32. the input signal frequency can vary from 100Hz to 60kHz. as of now i'am using the Input capture unit to deduce the period of the input signal and use the same to produce the output signal.
but the code is not working as expected for a sample input signal of 20kHz.
according to calculations, ICR1 register should have a value of 0x0229. but the output signal frequency is oly about 5kHz. when i manually write
tim = (0x029)/(11.0592*4), the output is proper 20kHz. am not understanding what the pronlem is.. help...

Code:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/pgmspace.h>
volatile uint16_t pul = 65530;
double tim = 0;


ISR(TIMER1_CAPT_vect)
{
   pul = ICR1H;
   TCNT1 = 0;
}


int main(void)
{
   sei();
   DDRA = 0xFF;
   DDRD = 0x00;
   DDRC = 0xFF;
 
   TCCR1A = 0x00;
   TCNT1 = 0x0000;   
   TCCR1B = 0x40;
   
   TCCR1B = 0x41;
   TIMSK &= 0x20;
   TIMSK |= 0x21;
   _delay_ms(100);
   
   while(1)
   {
      tim = pul/(11.0592*4);   
      PORTA = 0x0C;
      _delay_us(tim);
      PORTA = 0x06;
      _delay_us(tim);
      PORTA = 0x03;
      _delay_us(tim);
      PORTA = 0x09;
      _delay_us(tim);      
   }

}
$ Fixed code tags - JS $
 
 View user's profile Send private message  
Reply with quote Back to top
Visovian
PostPosted: Apr 05, 2012 - 06:44 AM
Posting Freak


Joined: Aug 07, 2007
Posts: 1477
Location: Czech

Code:
ISR(TIMER1_CAPT_vect)
{
   pul = ICR1H;
Why do you read only high byte?
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Apr 05, 2012 - 02:24 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 25922
Location: Wisconsin USA

First, digest this recent thread:
http://www.avrfreaks.net/index.php?name ... hase+shift

Quote:

and of same frequency.

I read that, and thought that the output signal had the same frequency plus another signal phase-shifted 90 degrees. But the we see

Quote:

tim = pul/(11.0592*4);

??? IS this your AVR's frequency?

In any case, tell at least an example of the desired output frequency for an input frequency of a given value.

You say you are achieving about 5kHz on the output. That is 200us per period. Given the floating point math and the delays ... that sounds about right. there is no reason for floating-point math to manipulate "small" integer values.

Next, I'd use a timer and output compare channels to assist rather than the variable length delays.

IIRC (you'll need to ask the GCC gurus) using _delay_us_() with a variable parameter will not give you the expected time as it does everything in floating point.

The access of "pul" in the mainline will need to be done with interrupts off.



Quote:

TCCR1B = 0x40;

TCCR1B = 0x41;


An interesting instruction sequence.

For best ICP operation, let the timer free-run and subtract prev from new to get the period. With a low prescaler your method of resetting TCNT is bound to be inaccurate.

=============
For an input signal of 20kHz that is a 50us period. GCC is not known for skinny ISRs; let's give you a time budget of 10us for the ICP interrupt. Lack of global register variables is also a hindrance for calculating new-prev, but let's say it can be done in 10us.

60kHz max is only 16us per period. And there are two outputs, so any leap-frog method is going to get very tight on time.

At this time I can't even recommend what I think might be the "best" approach. Give more info and we'll go over it again. what is the AVR's clock speed? What is the min and max input frequency? What is the transfer function for output frequency? and the resulting max output frequency?
 
 View user's profile Send private message  
Reply with quote Back to top
kunalpowar1203
PostPosted: Apr 07, 2012 - 02:05 PM
Newbie


Joined: Mar 05, 2012
Posts: 9


sorry... correction.. its actually
pul = ICR1;
 
 View user's profile Send private message  
Reply with quote Back to top
kunalpowar1203
PostPosted: Apr 09, 2012 - 05:00 AM
Newbie


Joined: Mar 05, 2012
Posts: 9


the controller is clocked to 11.0592MHz. the method I'm using to produce 2 signals of the same frequency but phase shifted by 90deg is by rotating a binary sequence 1100 through the portA low register. first i find the input signal 'period' using ICR. then i rotate the register every 'peroid/4' seconds.
so for a sample input signal of 20kHz, the period should be 50u sec. so
tim = pul / 11.0592 gives the value 50u sec. where pul is the ICR1 value for every rising edge.
if this works right, the output signal will also be 20kHz. which is not happening.

to find out if its the problem with delay_us, i disabled all interrupts and manually wrote tim = 50. and then the output was as expected.
so the problem is with the statement pul = ICR1.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Apr 09, 2012 - 02:36 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 25922
Location: Wisconsin USA

Quote:

so the problem is with the statement pul = ICR1.

No, it isn't.

I will re-state a few things from my more extensive post above:

-- At 20kHz you have a 50us period to do all of your output setting. That is ~550 cycles at your clock rate.
Quote:

tim = pul/(11.0592*4);

-- This is likely to take more cycles than that by itself.

Quote:

_delay_us(tim);

-- This is likely to take more cycles than that by itself.


====================
I went on to think about how this could be done with interrupts and output compare. If you want to dedicate an entire AVR to the task then you could poll timer ticks instead of using the variable delay, which isn't going to do what you think.

Also, I see >>no<< reason to have the floating point work in there, and indeed your AVR's frequency should be immaterial. The input capture gives you ICR1 counts for the period of the signal. Shouldn't you then just wait for 1/4 of those counts for each of your output stages?

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits