This shows you the differences between two versions of the page.
pm:lab:lab0xc0-3 [2020/03/29 20:28] dumitru.tranca |
pm:lab:lab0xc0-3 [2020/03/31 17:01] (current) constantin.ghilinta [Generating PWM using ATmega Timers] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Laboratorul 0xC3: PWM, Counters and External Interrupts ====== | + | ===== Laboratorul 0xC2: PWM, Counters and External Interrupts ====== |
This lab covers the topics of PWM, H-bridge drivers and reading encoders using external interrupts. | This lab covers the topics of PWM, H-bridge drivers and reading encoders using external interrupts. | ||
For more in-depth knowledge about the capabilities and the timing peripherals and how to program them you can find more information in the ATmega324 datasheet ({{:pm:doc8272.pdf|Datasheet ATmega324}}). | For more in-depth knowledge about the capabilities and the timing peripherals and how to program them you can find more information in the ATmega324 datasheet ({{:pm:doc8272.pdf|Datasheet ATmega324}}). | ||
+ | |||
+ | |||
===== PWM (Pulse Width Modulation) ===== | ===== PWM (Pulse Width Modulation) ===== | ||
Line 20: | Line 22: | ||
In the following schematic, we can see that Q1 connects the output to the positive voltage supply (Vmax) and Q2 connects the ouput to the negative voltage supply (Vmin). Q1 and Q2 are controlled by a more complex circuit (transistor driving circuit), based on the signals given by the microcontroller (MCU). | In the following schematic, we can see that Q1 connects the output to the positive voltage supply (Vmax) and Q2 connects the ouput to the negative voltage supply (Vmin). Q1 and Q2 are controlled by a more complex circuit (transistor driving circuit), based on the signals given by the microcontroller (MCU). | ||
- | {{ :pm:lab:lab3:vmax_vmin_comut.png?500 |}} | + | {{ :pm:lab:lab3:vmax_vmin_push_pull.png?500 |}} |
- | The transistor driving circuit is sometimes necessary because of the different voltage levels of the MCU and the voltages of the power supplies. | + | NPN and N-MOS transistors and NPN IGBT transistors are preferred to be used both on the high side and on the low side (to connect Vmax and Vmin) because of the mobility of electrons, compared to the mobility of holes in P-channel solid state components. |
+ | Furthermore, besides the main argument regarding mobility of electronics, design techniques and drivers are in favor of N-channel transistors. N-channel Mosfets, NPN IGBT transistors, to be turned on, need a positive impulse in their control pin (gate or base). Direct logic control is easier to manage and to follow in schematic. | ||
+ | For a more details please study specialized documents related to power electronics, inverters and drivers. | ||
+ | From the bill of materials viewpoint, it is always cheaper to increase the number of one component than to increase the number of component types. | ||
+ | The transistor driving circuit is sometimes necessary because of the different voltage levels of the MCU and the voltages of the power supplies. | ||
+ | <note important>Control Q1 and Control Q2 signals in the push-pull totem-pole topology DOES NOT come directly from the microcontroller. These signals should be generated with a driving circuit, through impulse transformers or driving optocouplers. Because the voltages of Vmax and Vlow are way different than the operating voltage of the microcontroller, connecting ControlQ1 and ControlQ2 directly to the microcontroller will result in a short circuit and the destruction of the microcontroller and the transistors. </note> | ||
<note important>All the voltages are measured with respect to GND, unless otherwise is explicitly noted.</note> | <note important>All the voltages are measured with respect to GND, unless otherwise is explicitly noted.</note> | ||
The output signal delivered to the load will look similar to the one showed in the next figure: | The output signal delivered to the load will look similar to the one showed in the next figure: | ||
- | {{ :pm:lab:lab3:pwm.png?500 |}} | + | {{ :pm:lab:lab3:pwm.png?550 |}} |
As we can observe, in one cycle (of duration T=T1+T2) the signal is switched between Vmax and Vmin. | As we can observe, in one cycle (of duration T=T1+T2) the signal is switched between Vmax and Vmin. | ||
Line 84: | Line 91: | ||
For example, the following signal is switched ON to 10V for 7.5ms and OFF (to 0V) for another 2.5ms (T=10ms, d=0.75). | For example, the following signal is switched ON to 10V for 7.5ms and OFF (to 0V) for another 2.5ms (T=10ms, d=0.75). | ||
- | {{ :pm:lab:lab3:pwm_unipolar.png?500 |}} | + | {{ :pm:lab:lab3:pwm_unipolar.png?550 |}} |
- | \begin{equstudation} | + | \begin{equation} |
V_{avg}=\frac{7.5ms}{10ms} \cdot 10=0.75 \cdot 10 = 7.5V | V_{avg}=\frac{7.5ms}{10ms} \cdot 10=0.75 \cdot 10 = 7.5V | ||
\end{equation} | \end{equation} | ||
Line 93: | Line 100: | ||
Example of PWM used to generate a sinusoidal waveform: | Example of PWM used to generate a sinusoidal waveform: | ||
- | {{ :pm:lab:pwm_sin_simulation.png?300 |}} | + | {{ :pm:lab:pwm_sin_simulation.png?550 |}} |
=== PWM on LEDs === | === PWM on LEDs === | ||
Line 100: | Line 107: | ||
The LED can be connected from the output of the MCU to GND with a resistor and it will light up when the MCU pin is driven HIGH. The resistor is used to limit the current through the LED. | The LED can be connected from the output of the MCU to GND with a resistor and it will light up when the MCU pin is driven HIGH. The resistor is used to limit the current through the LED. | ||
- | {{ :pm:lab:lab3:r_limit.png?200 |}} | + | {{ :pm:lab:lab3:r_limit.png?350 |}} |
The LED can be connected from the power supply to the MCU pin and it will light up when the MCU pin is driven LOW (the current will flow from Vcc to the MCU pin). | The LED can be connected from the power supply to the MCU pin and it will light up when the MCU pin is driven LOW (the current will flow from Vcc to the MCU pin). | ||
- | {{ :pm:lab:lab3:ledrgb.png?100 |}} | + | {{ :pm:lab:lab3:ledrgb.png?230 |}} |
If we need to power a high power load or a higher power LED we can use a transistor to switch on and off the load. | If we need to power a high power load or a higher power LED we can use a transistor to switch on and off the load. | ||
R1 can be replaced with a constant current supply | R1 can be replaced with a constant current supply | ||
- | {{ :pm:lab:lab3:high_power_led.png?300 |}} | + | {{ :pm:lab:lab3:high_power_led.png?400 |}} |
=== Delivering PWM for DC brushed motors and other loads === | === Delivering PWM for DC brushed motors and other loads === | ||
Line 118: | Line 125: | ||
In the next schematic, L1 is our load that might have an inductive characteristics. In order to protect the transistor, we use the flyback diode D1. | In the next schematic, L1 is our load that might have an inductive characteristics. In order to protect the transistor, we use the flyback diode D1. | ||
The PWM will be generated by the microcontroller and will control the base of Q1. | The PWM will be generated by the microcontroller and will control the base of Q1. | ||
- | {{ :pm:lab:lab3:flyback_diode_example.png?300 |}} | + | {{ :pm:lab:lab3:flyback_diode_example.png?500 |}} |
== H Bridge principles and examples == | == H Bridge principles and examples == | ||
Line 169: | Line 176: | ||
* Wait For T2 | * Wait For T2 | ||
- | he issue here would be that we need to determine how much time does the code before this sequence or after it take to execute. | + | The issue here would be that we need to determine how much time does the code before this sequence or after it take to execute. |
Another solution would be to use timer interrupts and in the ISR to change the state of the pin. | Another solution would be to use timer interrupts and in the ISR to change the state of the pin. | ||
In this manner, we will at least have a precise timing, but we will generate many interrupts that might affect our code in some situations. | In this manner, we will at least have a precise timing, but we will generate many interrupts that might affect our code in some situations. | ||
Line 184: | Line 191: | ||
First, we need to identify the PWM capable pins. We can identify by looking for the alternative functionality OCnX | First, we need to identify the PWM capable pins. We can identify by looking for the alternative functionality OCnX | ||
- | {{ :pm:lab:lab3:atmega324_pwm_pins.png?300 |}} | + | {{ :pm:lab:lab3:atmega324_pwm_pins.png?450 |}} |
=== Fast PWM mode === | === Fast PWM mode === | ||
Line 191: | Line 198: | ||
//The counter counts from BOTTOM to TOP then restarts from BOTTOM. In non-inverting Compare Output mode, the Output Compare (OCnx) is cleared on the compare match between TCNTn and OCRnx, and set at BOTTOM. In inverting Compare Output mode output is set on compare match and cleared at BOTTOM. Due to the single-slope operation, the operating frequency of the fast PWM mode can be twice as high as the phase correct and phase and frequency correct PWM modes that use dual-slope operation. This high frequency makes the fast PWM mode well suited for power regulation, rectification, and DAC applications. High frequency allows physically small sized external components (coils, capacitors), hence reduces total system cost.// | //The counter counts from BOTTOM to TOP then restarts from BOTTOM. In non-inverting Compare Output mode, the Output Compare (OCnx) is cleared on the compare match between TCNTn and OCRnx, and set at BOTTOM. In inverting Compare Output mode output is set on compare match and cleared at BOTTOM. Due to the single-slope operation, the operating frequency of the fast PWM mode can be twice as high as the phase correct and phase and frequency correct PWM modes that use dual-slope operation. This high frequency makes the fast PWM mode well suited for power regulation, rectification, and DAC applications. High frequency allows physically small sized external components (coils, capacitors), hence reduces total system cost.// | ||
- | {{ :pm:lab:lab3:fast_pwm_timing.png |}} | + | {{ :pm:lab:lab3:fast_pwm_timing.png |}} (source {{:pm:doc8272.pdf|ATmega324 Datasheet}}) |
+ | |||
+ | From {{:pm:doc8272.pdf|ATmega324 Datasheet}} in Chapte 15-17 you can read more about timers. | ||
+ | Configuration bits are found in TCCRnA, TCCRnB and TCCRnC (configuration is dependent on the timer specs). | ||
Line 198: | Line 209: | ||
We can configure the timers in different ways, so that the timers count up to overflow, to ICRn or to OCRnA. | We can configure the timers in different ways, so that the timers count up to overflow, to ICRn or to OCRnA. | ||
+ | |||
+ | Configuring/selecting different modes can be done using the Waveform Generation Mode bits (WGM) | ||
+ | Let's see the WGM config bits for Timer 1. | ||
+ | {{ :pm:lab:wgm.png?700 |}} (source {{:pm:doc8272.pdf|ATmega324 Datasheet}})) | ||
+ | |||
+ | After we choose the WGM bits for 8-bit FAST PWM we need to choose a normal port operation: OCn set when timer rolls from TOP to BOTTOM and OCn is cleared on compare match with OCRn. | ||
+ | The selection of this functionality is done using the COM bits for Fast PWM mode. | ||
+ | |||
+ | {{ :pm:lab:com0_bits.png?600 |}} (source {{:pm:doc8272.pdf|ATmega324 Datasheet}}) | ||
+ | Last but not least, remember: <note>a timer, in order to do it's job, needs a clock source. Thus, we need to select the proper clock source.</note> | ||
+ | The Clock Source bits for timer 1 need to be set in TCCR1B. For other timers check the datasheet. | ||
+ | {{ :pm:lab:cs-bits_timer1.png?600 |}} (source {{:pm:doc8272.pdf|ATmega324 Datasheet}}) | ||
+ | |||
+ | <note important>The output frequency of a fast PWM pin is dependent on the prescaller and the clock frequency of the MCU. According to Section 17.7.3 | ||
+ | \begin{equation} | ||
+ | f_{OCnX}=\frac{f_{clk\_IO}}{2 \cdot N \cdot 256} | ||
+ | \end{equation} </note> | ||
+ | |||
Let now try a simple example with OC1A as output (PD5) set to fast PWM (8 bit) with a top at 0xFF. | Let now try a simple example with OC1A as output (PD5) set to fast PWM (8 bit) with a top at 0xFF. | ||
Line 206: | Line 235: | ||
TCCR1A |= _BV(WGM10); //Just WGM10 is in TCCR1A | TCCR1A |= _BV(WGM10); //Just WGM10 is in TCCR1A | ||
- | //WGM11, WGM12 and WGM13 will be set in TCCR1B | + | //WGM12 will be set in TCCR1B |
TCCR1B |= _BV(WGM12); | TCCR1B |= _BV(WGM12); | ||
Line 227: | Line 256: | ||
are preferred for motor control applications when using more than one PWM signals. | are preferred for motor control applications when using more than one PWM signals. | ||
- | {{ :pm:lab:lab3:phase_correct_pwm_timing.png?400 |}} | + | {{ :pm:lab:lab3:phase_correct_pwm_timing.png?500 |}} |
These two types of PWMs are relevant just when using PWMs on more than one channel and they help reducing interference, glitches, minimizing electromagnetic emissions (EMI) and for other complex systems and electronics. | These two types of PWMs are relevant just when using PWMs on more than one channel and they help reducing interference, glitches, minimizing electromagnetic emissions (EMI) and for other complex systems and electronics. | ||
Line 268: | Line 297: | ||
For our demonstration we have wired the output signals of the encoder to the pins PD2 and PD3 that can handle external interrupts INT0 and INT1 | For our demonstration we have wired the output signals of the encoder to the pins PD2 and PD3 that can handle external interrupts INT0 and INT1 | ||
+ | |||
+ | We would need to implement the following functionality: | ||
+ | |||
+ | * On rising edge for signal A | ||
+ | * Verify the state of B. If it is LOW, it's one direction, if it's HIGH, the motor is rotating in the other way | ||
+ | |||
+ | Detecting a rising edge or a falling edge using interrupts can be configured in EICRA using the ISC bits (as described in the datasheet). | ||
+ | |||
+ | {{ :pm:lab:lab3:eicra_interrupts.png?500 |}} | ||
+ | {{ :pm:lab:lab3:iscn_bits.png?500 |}} | ||
+ | |||
+ | In the end, to enable the interrupts don't forget to set the bits for the interrupt you wish to activate in the EIMSK register. | ||
+ | {{ :pm:lab:eimsk.png?500 |}} | ||
+ | |||
+ | In the {{:pm:doc8272.pdf|Datasheet ATmega324}} you can find in Chapter 13 - External interrupts more details and descriptions. | ||
+ | |||
+ | Testing the rising edge can be done through external interrupts or through continuous polling. | ||
Line 273: | Line 319: | ||
For this lab we will have the following schematic | For this lab we will have the following schematic | ||
- | {{:pm:lab:lab3_covid_pwm.png?1000|}} | + | {{:pm:lab:lab3:lab3_covid.png?1000|}} |
We can see that we have a full H bridge made with discrete components connected to PD4 and PD5. | We can see that we have a full H bridge made with discrete components connected to PD4 and PD5. | ||
Line 283: | Line 329: | ||
===== Tasks ===== | ===== Tasks ===== | ||
+ | Sketch is available here: {{:pm:lab:lab3:lab2_0xc2.zip|}} | ||
1. Compile the code sketch in the archive and run it. | 1. Compile the code sketch in the archive and run it. | ||
a. Watch the signals on the oscilloscope (Right click the oscilloscope when the instrument is running and click on Digital Scope). (1p) | a. Watch the signals on the oscilloscope (Right click the oscilloscope when the instrument is running and click on Digital Scope). (1p) | ||
b. Let the voltage showed by the voltmeter settle and read the voltage displayed. How is this value related to the PWM duty cycle and power rail? (0.5p) | b. Let the voltage showed by the voltmeter settle and read the voltage displayed. How is this value related to the PWM duty cycle and power rail? (0.5p) | ||
- | c. Open the serial virtual terminal and watch for messages. Analyze the code and see where these messages are sent from. | + | c. Open the serial virtual terminal and watch for messages when you press PB2. Analyze the code and see where these messages are sent from (0.5p). |
- | 2. Using external interrupts (you have a start-point using INT2 ISR in the sketch) or continuous polling technique, implement the following functionality: When PB2 is pressed change the direction of revolution of the motor and send a message to the serial terminal using UART0 that the direction has been changed. | + | 2. Using external interrupts or continuous polling technique, implement the following functionality: When PB2 is pressed change the direction of revolution of the motor and send a message to the serial terminal using UART0 that the direction has been changed. |
- | <note tip>To change the revolution direction toggle pin PD4</note> (2.5p) | + | <note tip>To change the revolution direction toggle pin PD4</note> (3p) |
3. At this moment the H bridge is controlled through a bit-banging PWM. | 3. At this moment the H bridge is controlled through a bit-banging PWM. | ||
Line 297: | Line 344: | ||
* TIMER1_COMPB_vect clears PD5 to LOW (when counter reaches OCR1B) | * TIMER1_COMPB_vect clears PD5 to LOW (when counter reaches OCR1B) | ||
- | a. Modify TIMER1 config to a 8-bit Fast PWM mode with a frequency between 1kHz and 20kHz (using CS12 CS11 and CS10) | + | a. Modify TIMER1 config to a 8-bit Fast PWM mode with a frequency between 1kHz and 20kHz (using CS12 CS11 and CS10) (2p) |
- | b. Modify the code so that the duty cycle is incremeted by 10\% (the dutycycle is computed as: 100 * OCR1A/255) every 2 secons (a delay in main loop between increments of OCR1A is enough for that). Incrementing OCR1A with 25 is considered accurate enough to simulate the increase of 10%. <note important>Do not set OCR1A to 255. When the duty cycle would reach more than 100%, reset it to 1%</note> | + | b. Modify the code so that the duty cycle is incremeted by 10\% (the dutycycle is computed as: 100 * OCR1A/255) every 2 seconds (a delay in main loop between increments of OCR1A is enough for that). Incrementing OCR1A with 25 is considered accurate enough to simulate the increase of 10%. <note important>Do not set OCR1A to 255. When the duty cycle would reach more than 100%, reset it to 1%</note>(1p) |
+ | |||
+ | 4. At this moment we have motor that can spin in both directions and it has a little bit on inertia in the simulated model. | ||
+ | Identify, using external interrupt INT0 ( or continuous polling on digital inputs) on rising edge or using continuous polling (verifying in main loop), what is the direction of revolution and send the information to the virtual terminal. (2p) | ||
- | 4. At this moment we have | ||
+ | * Responsabili: [[cristi.tranca@gmail.com | Cristi Trancă]] | ||