I would like to know how we can vary the duty cycle in CTC mode in AVR micro controller. In CTC mode, frequency can be varied using OCR0A register (Timer0) assuming some prescaler value. Do we need to make use of OCR0B register (value Must be less than OCR0A) to vary the duty cycle? On OCR0B interrupt, we can change the state of the OCA0 pin I guess.
The CTC mode only allows you to change the frequency of interrupts/pin state changes.
If you want to drive the duty cycly of a signal instead of its frequency, then you have to use a PWM waveform generation mode.
Related
When I initialise two PWM pins on ESP32 using micropython I found the two pins are always on the same PWM frequency.
motorPin1 = machine.PWM(Pin(21, mode=Pin.OUT))
motorPin1.duty(512)
motorPin1.freq(10)
motorPin2 = machine.PWM(Pin(22, mode=Pin.OUT))
motorPin2.duty(300)
motorPin2.freq(200)
In the above example, both motorPin1 & motorPin2 end up on the same frequency. Also if the frequency on one pin is updated, it will also update the frequency on the other (to the same frequency). Duty cycle can be controlled separately but not frequency.
I eventually found ESP32 has pwm 'channels' which are driven/timed in pairs. So for example, if you have two PWM pins assigned to channels 0 & 1, they will always run at the same frequency.
The micropython PWM interface doesn't expose the PWM channel assigned to a pin.
How do people setup PWM pins in micropython with the appropriate PWM channels to allow separate control of the frequency?
Unfortunately this hardware functionality is not currently available in MicroPython - there is an open PR to add this: https://github.com/micropython/micropython/pull/3608
You could look into bit-banging or utilising timers if your needs are more basic, otherwise you could provide support for getting the PR merged!
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...
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.
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.
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.