Timer3 PWM and SPI on Atmega1284P

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

Hello to all!

I have a problem with my project. Let me explain..
I need to use in the same microcontroller the SPI and the Timer3 PWM but i know that this two devices are incompatible if i use them in the same time.
So i read some post on how resolve this problem and the solution is to use the software PWM instead the hardware PWM, but the procedure is not very clear for me.
Please someone can give me some detail on how i can implement the software PWM using Timer3 of the Atmega 1284P?

 

I need two channels PWM because i need to drive two ESC. All the other timers are busy and I use a 16Mhz system clock.

This topic has a solution.
Last Edited: Sun. Sep 13, 2015 - 07:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a code example for soft generation of servo signals:

https://www.avrfreaks.net/comment...

/Lars

 

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

Thank you so much Lars! laugh

 

Now i study your code and i try to implement it in my project! 
But i have a question about software PWM: the jitter it's a problem if i use the soft PWM to control a ESC?
The my application (quadcopter control system) use three interrupt and my main loop cycle run about at 31Hz. 
The first interrupt fire every 16uS (this is my timer resolution) and i need it for generate the sample time (the logic is the same of the AVR221 application note code).
I have another two source of interrupt: another timer that fire every 29 uS and an external interrupt that fire two times every loop cycle (i need it to read a sonar measure).
So with this configuration, in your opinion the soft pwm work well form my application?

 

Ps i have read something about the jitter from the avr136 application note.

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

Yes jitter from other ISR can for sure be a problem. I think you have to try it but I have to say I find it hard to believe that you need interrupts with that frequency.

 

Is this what you are talking about?

#define TIME_INTERVAL   157

/*! \brief Timer interrupt to control the sampling interval
 */
#pragma vector = TIMER0_OVF_vect
__interrupt void TIMER0_OVF_ISR( void )
{
  static uint16_t i = 0;
  if(i < TIME_INTERVAL)
    i++;
  else{
    gFlags.pidTimer = TRUE;
    i = 0;
  }
}

 

It's only counting to 157, surly can be done with a lot less interrupting (using the prescaler).

/Lars

 

 

Last Edited: Sat. Sep 12, 2015 - 05:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you have to try it but I have to say I find it hard to believe that you need interrupts with that frequency.

You think rigth! smiley

 

In reality i use this timer with this frequency for implement a "timer class". I use it to measure the execution time of my pieces of code and with a modification i use it to create the sample time for the control loop. This is the result:

 

ISR(TIMER2_OVF_vect)  // resolution of 16[us]
{
	
	if(sample_time_count < sample_time)
	{
		sample_time_count++;
	}
	else{
		flag_timer = 1;
		sample_time_count = 0;
	}
	
	timer_count += 0x100; // 0x100 = 256*0.0625 = 16[us]
}

However it's no problem change this "class" and reduce the number of interrupt.

But how about the others interrupt?

 

ISR(INT0_vect)
{
	if(sonar_flag) // the echo is arrived!
	{
		sonar_flag     = 0;
		EICRA = (1<<ISC01);  // set falling edge
		t0 = sonar_counter;
	}
	else // the echo is finish
	{
		TCCR0B =  0x0;    // stop timer-counter0
		unsigned long t1 = sonar_counter;
		tot_counter     = (float)( (t1-t0)*SONAR_TIMER_RESOLUTION );// time width receive impulse [us]
		
		EIMSK =  0x0;    // disable int0
		EICRA = ( (1<<ISC01) | (1<<ISC00) ); // rising edge
		
		measure_flag = 1; // the measure is ready
	}
}

ISR(TIMER0_COMPA_vect) // resolution of 29[us]
{
	if (sonar_counter >= MAX_SONAR_COUNT)
	{
		TCCR0B =  0x0;    // stop timer-counter0
		EIMSK  =  0x0;    // disable int0
		EICRA = ( (1<<ISC01) | (1<<ISC00) ); // rising edge
				
		tot_counter = (float)(MAX_SONAR_COUNT * SONAR_TIMER_RESOLUTION);
		
		measure_flag = 1;
	} 
	else
	{
		sonar_counter++;   // increment the counter of 29[us]
	}
	
}

These are the others two ISR routine. I think that the first isn't a problem because it fire two time in one loop. But the last routine is a problem, right?

To over this problem I thought about using another AVR (Attiny 4313) for interfacing to the SPI device. So the Atmega 1284 communicates with the attiny via usart and I leave free the Timer3 for the ESC control.
In your opinion this choise have a sense? Have you some suggestion on how i resolve this problem?

Note that to obtain a clean signal pwm is crucial for the proper functioning of the control system of the quadcopter!

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Again you will have to test this I think. It is likely the motors will not react fast enough to make it matter if the signal is not perfect all the time.

But if you have a free USART why not run SPI with that ("USART in SPI Mode") and PWM with timer3?

/Lars

 

Last Edited: Sun. Sep 13, 2015 - 02:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But if you have a free USART why not run SPI with that ("USART in SPI Mode") and PWM with timer3?

I'm not an expert and i not know this functionality!

I will read the datasheet!
Thank you very much Lars! laugh

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

Thank you so much Lars!!

You helped me a lot! laugh