ATmega328PB - mapping Fast-PWM to several IO-Ports?

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

Dear AVRfreaks,

 

on my ATmega328PB I'm using OC1A with fast PWM on Timer1 (cpu clk 8MHz, PWM frequency 1.9kHz, 12 Bit).
I need to have 4 separate output ports with the same PWM, which can be enabled separatly.
Actually I'm doing this with an external hardware circuit, but it takes a lot of additional components and space on my PCB.

 

Would it possible to do this with the ATmega itself?
Maybe some kind of mapping the Timer1-PWM with software to 4 IO-ports, to be enabled separatly?

 

Many thanks!

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

Why should it be 328BP?
It is not appropriate for your purpose.

With careful choice of device to use, you will get four PWM outputs without resorting to external hardware.
xmega and mega4809 are candidates.

Last Edited: Fri. Jan 3, 2020 - 02:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mega4809 is quite a nice proposal.

But ATmega328pb is already been used, and I don't want to rewrite the complete software, as PWM is just one of the features used.

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

...btw. I've just checked the ATmega4809 in MPLAB, and it seems to have just 3 channels of 16 Bit PWM in TCA0 and in TCBn only 8 Bit PWMs.

Multiple output assignments are not recommended.

So one 16 Bit PWM is still missing..

 

 

 

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

High-speed PWM by TIMER1 can output two PWM waveforms by using ICR1 for TOP.
mega32U4 has two of these 16bit timers. (TIMER1 & 3)
It is up to you to choose between modifying the software or creating external hardware.

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

kabasan wrote:
mega32U4 has two of these 16bit timers. (TIMER1 & 3)

 

Remember that the Mega328PB the OP is using is different from the other Mega328. It has 3x 16 bit timers each with 2 PWM channels, so using 2 should be enough to solve the problem.

 

edit: anyway, the Mega4809 could do several copies of one timer output using the event system and/or the CCL.

Last Edited: Sat. Jan 4, 2020 - 02:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

WIth the 4809's event system and/or configurable custom logic (CCL) I'm guessing you could map one PWM to multiple outputs.

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

Oh, I forgot the difference between "PB".
You don't need to change devices.
I'm sorry.

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

OK, thanks guys!

I think I remain with my hardware solution, as it isn't worth the effort of migrating the complete system.

I hoped there would be a way with maybe some smart Timer-IRQ using on the 328PB...

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

I wrote test code for mega328PB to apologize.
The following code outputs PWM waveforms of any duty independent of the four pins (PB1, PB2, PD0, PD2).
Since OC3B and OC4B do not work, I used a combination of OC1A, OC1B, OC3A, and OC4A.

 

#include<avr/io.h>
#define ICR_TOP 4210    /* 1.9kHz@8MHz */

int main(){
    DDRB = (1 << DDB1) | (1 << DDB2);   // OC1A, OC1B
    DDRD = (1 << DDD0) | (1 << DDD1);   // OC3A, OC4A
    DDRD = 0xFF;

    ICR1 = ICR3 = ICR4 = ICR_TOP - 1;
    OCR1A = ICR_TOP / 10 - 1;       // OC1A 10%
    OCR1B = ICR_TOP / 10 * 2 - 1;   // OC1B 20%
    OCR3A = ICR_TOP / 10 * 3 - 1;   // OC3A 30%
    OCR4A = ICR_TOP / 10 * 4 - 1;   // OC4B 40%
    TCCR1A = (1 << COM1A1) | (1 << COM1A0) | (1 << COM1B1) | (1 << COM1B0) | (1 << WGM11);
    TCCR3A = TCCR4A = (1 << COM1A1) | (1 << COM1A0) | (1 << WGM11);
    TCCR1B = TCCR3B = TCCR4B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
    
    while(1){
    }
}

 

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

Many thanks kabasan, I'll give it a try when I have build up the new hardware!

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

At the rather low freq of 1900 Hz, you can easily use an interrupt-based PWM, assuming you don't have other interrupts that might block or delay the response.  However, the uncertain latency means you might get a slight jitter, limiting the effective number of bits.

Each PWM edge can trigger the irq & the irq determines which pins respond.  Seems a bit of a rube-goldberg workaround.
 

but it takes a lot of additional components 

Why?  All it would take is a quad "and" gate & 4 lines to select the enabled outputs.  If the AVR was doing all of the work, you'd need 4 pins anyhow.  So this only costs 1  quad and gate & 1 extra pin (PWM & 4 selects)

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. Jan 5, 2020 - 12:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think, what the OP wants is 12 bit resolution. With the MCU running @ 8MHz, this gives a maximum PWM frequency of 8000000/4096 = 1953 Hz

 

Since the timer is running at maximum frequency, it would be feasible to use an interrupt, except for extreme cases near 0% and 100% duty cycle. For example, if you want 1-99% working (i.e. 0-1% and 99-100% will not work well), then the ISR will have to execute in less than 1% of 4096 cycles, that is, in less than 41 cycles.

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

You could program 0 &100% as special cases (perhaps not needing the IRQ)...The timer should likely be in PWM mode so it is creating the variable width (steps of 128 ns  [1900Hz, 4096 widths])

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!