Duty Cycle adjustment Fast PWM Mode - avr

As per the datasheet of Atmega328, Timer0 fast PWM mode can be selected by setting WGM02:00 to either 011 or 111.
When we set Fast PWM mode using 111, TOV Flag set on TOP. Also TOP is equal to OCR0A. Now ON time of PWM is controlled using OCRA. When compare match occurs, OCA0 is cleared (COM0A1:COM0A0 = 10) and it is set at the bottom.
Now my question is if TCNT clears after reaching TOP (that is nothing but OCR0A), how can we alter On time with WGM02:00=111? I am not quite clear from data sheet. Even waveforms are also little confusing. Or is it that TCNT always counts from 0x00 to 0xff irrespective of TOV flag in this case?

Since OCRA is in use, you have to use the other OC registers, e.g. OCRB. OCA will still follow the directions given to it by COM0A, but is significantly less useful for that.

While using the output compare unit register (OCR0A) to define the top value of the counter (WGM02:WGM00=111), you can only toggle the logical level at the corresponding pin (OCA0) when a compare match between TCNT0 & OCRA0 occurs. Hence, you can't control the duty cycle (always 50%). This is just like the ctc mode, except that the double buffering feature of the output compare unit is enabled in fast PWM mode. Look at the datasheet, the last paragraph in the description of fast PWM mode:
A frequency (with 50% duty cycle) waveform output in fast PWM mode can
be achieved by setting OC0x to toggle its logical level on each
compare match (COM0x1:0 = 1). The waveform generated will have a
maximum frequency of fOx0 = fclk_I/O/2 when OCR0A is set to zero.
This feature is similar to the OC0A toggle in CTC mode, except the
double buffer feature of the Output Compare unit is enabled in the
fast PWM mode.
However, you can use timer 1 to control the frequency and the duty cycle, by setting the input capture unit register (ICR1) to define the TOP value of the counter, and then the output compare unit register (OCR1A) will be free to make the corresponding pin (OC1A) take action (set or clr) when a compare match occurs.

Related

Multiple PWM Channels on PIC

I use the PIC16F88 for my project, with XC8 compiler.
What I'm trying to achieve is to control 4 LEDs with 4 buttons, when you press a buttons it increases the duty cycle of the corresponding LED by 10%.
When you press the button on RB0 it increases the duty cycle of the LED on RB4, and so on.
Every LED is independent, therefore it can have a different duty cycle.
The problem is that the PIC i'm using only have one PWM module on either RB0 or RB3 (using CCPMX bit).
After some research I decided to implement software PWM to have four different channels, each channels would control one duty cycle, but most of the sources I found didn't provide any explanation on how to do it.
Or is there a way to mirror PWM to multiple pins ?
Thanks by advance for helping me out.
Mirroring is not an option.
PWM is relatively simple. You have to set PWM frequency (which you will not change) and PWM duty cycle (which you need to change in order to have 0-100% voltage range). You have to decide about resolution of PWM, voltage step that you need (built in PWM for example is 8-bit and has 0-255 steps).
Finally, you have to set timer to interrupt based on PWM frequency * PWM resolution. In Timer ISR routine you need to check resolution counts and PWM value of all your channels. Resolution count will have to reset when resolution value is reached (and start to count from 0 again, all outputs go HIGH here, also). When PWM value of output is reached you have to toggle (pull it LOW) corresponding pin (and reset it back to HIGH with every resolution count reset).
This is only one way of doing it, involves only one timer and should be most simple since your PIC is low with resources.
Hope it helps...

Independent modes of Output Compare Pins A and B in Atmega328

I was looking at Atmega328. Atmel has given lot of features in timer section. But I observed that Output Compare A and Output Compare B modes of operation depends on WGM bits and cannot be set differently for both. For Example: I cannot select OCA pin in Fast PWM mode and OCB in Normal mode/CTC mode. Either both have to be in normal mode or both in fast PWM or other modes.
Can anyone confirm this? May be atmel could have added a feature where in both OCA and OCB be operated in independent modes.
Since both OCxA and OCxB use the same counter, it cannot be used it in different counting modes simultaneously. One single value cannot in the same time count repeatedly from zero to top, and in the same time to top and then downward to zero, or count to particular independent value (CTC). It has no sense.
But using COMxxx bits in TXCCRxA, you can configure compare match unit to be not connected to the output, therefore, to be used as if in "Normal mode".
When WGM bits set to 111 you can use the timer in mixed PWM/CTC mode: timer will count up to OCRA value, while OCRB (in range 0...OCRA) will be used to generate PWM output.
In Timer1 you can set WGM bits to 1110 to enable CTC up to value of the ICR1 register, while both outputs could be used to generate PWM waveform, you can disconnect any PWM output in COM1xx bits, and use it as "normal", to generate the interrupt request, without value output to the OC1x pin.

IR emitter and PWM output

I have been using FRDM_KL46Z development board to do some IR communication experiment. Right now, I got two PWM outputs with same setting (50% duty cycle, 38 kHz) had different voltage levels. When both were idle, one was 1.56V, but another was 3.30V. When the outputs were used to power the same IR emitter, the voltages were changed to 1.13V and 2.29V.
And why couldn't I use one PWM output to power two IR emitters at the same time? When I tried to do this, it seemed that the frequency was changed, so two IR receivers could not work.
I am not an expert in freescale, but how are you controlling your pwm? I'm guessing each pwm comes from a separate timer, maybe they are set up differently. Like one is in 16 bit mode (the 3.3V) and the other in 32 (1.56v) in that case even if they have the same limit in the counter ((2^17 - 1) / 2) would be 50% duty cycle of a 16 bit timer. But in a 32 bit, that same value would only be 25% duty so, one output would be ~1/2 the voltage of the other. SO I suggest checking the timer setup.
The reason the voltage changed is because the IR emmiters were loading the circuit. In an ideal situation this wouldn't happen, but if a source is giving too much current the voltage usually drops a bit.

VHDL pulse generator on the press of a button

I want to generate a clock that is high for say .5 secs once I press a button on the FPGA board. At all other times I want the clock to be 0.
If I press the button again I should again get a .5 sec high time and then again the clock should become 0 and remain 0 until I again press the button.
I want to achieve it using VHDL code.
I have a clock available with me as input whose frequency is 10^8 Hz.
Start by drawing a block diagram of hardware that will implement your desired function. Refine each of the pieces until you have something that is quantifiable in some way as hardware (flip-flop, multiplexer, decrementer, "and" gate, zero detect, ...).
If you are stuck with doing your block diagram, think about how you can connect the hardware elements I identified above to create the function.
Once you have your block diagram, if you are still stuck, then do a search on a particular hardware element and you should be able to find a template for it.

Frequency divider by any integer 1-16

I have implemented a frequency divider by the powers of 2. Now I am interested in doing a divider by any integer number from 1 to 16. Yes, I have tried but yet no ideas. How can I approach this problem?
I want to use common elements like multiplexers, flip flops and so on. Not asking for a complete solution, even though it would be great.
That is normally the job of a PLL many FPGA have some PLL on chip.
Or try a counter that resets when limit (0-15) is reached.
Each time limit is reached toggle clock.
The value for 1:1 clock needs special handling, maybe a clock bypass.
A better way would be to run the counter at double frequency to avoid the mux.
Instead of an incrementing counter a decrementing counter that loads the configured value on zero would do as well.

Resources