You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are two properties to a PWM signal, the frequency which is determined by the period of the signal and the duty cycle which is determined by the high-time of the signal. The signal in figure above has a period of 250μS which means it switches at 4KHz. The duty-cycle is the percent high time in each period, in the last figure the duty-cycle is 60% because of the high-time and period of 150μS and 250μS respectively. It is the duty-cycle that determines average output voltage. In figure above the duty-cycle of 60% with 5V switching voltage results in 3V average output as shown by the red line. After filtering the output a stable analogue output can be achieved. the figure below shows PWM signals with 80% and 10% duty-cycles. By dynamically changing the duty-cycle, signals other than a flat output voltage can be achieved.
43
+
There are two properties to a PWM signal, the frequency which is determined by the period of the signal and the duty cycle which is determined by the high-time of the signal. The signal in figure above has a period of 250μS which means it switches at 4KHz. The duty-cycle is the percent high time in each period, in the last figure the duty-cycle is 60% because of the high-time and period of 150μS and 250μS respectively. It is the duty-cycle that determines average output voltage. In figure above the duty-cycle of 60% with 5V switching voltage results in 3V average output as shown by the red line. After filtering the output, a stable analogue output can be achieved. the figure below shows PWM signals with 80% and 10% duty-cycles. By dynamically changing the duty-cycle, signals other than a flat output voltage can be achieved.
This section describes how micro-controllers use timers/counters to implement a PWM signal, this description relies heavily on the figure below. Here the blue line represents a counter that resets after 16000, this gives the period of the PWM and also the switching frequency (fs), if this micro has a clock source of 16MHz, then fs will be 16×10^6/16×10^3 = 1KHz.
50
50
51
-
The two other values of 11200 and 800 shown as the gree and red line, they represent compare output values of the micro. When the counter reaches this values the micro can change the output of some pins. In this case two pins are set to HIGH when the counter resets and then Set low when the counter reaches each of the output compare values. This determines the high time and therefore duty-cycle of the PWM. It's important to understand how a PWM is typcialy set up in a micro, as the explanation of the code in the next section will not make sense otherwise.
51
+
The two other values of 11200 and 8000 shown as the green and red line, they represent compare output values of the microcontroller. When the counter reaches this values, the microcontroller can change the output of some pins. In this case two pins are set to HIGH when the counter resets and then Set low when the counter reaches each of the output compare values. This determines the high time and therefore duty-cycle of the PWM. It's important to understand how a PWM is typically set up in a microcontroller, as the explanation of the code in the next section will not make sense otherwise.
@@ -66,11 +66,11 @@ In this chapter we'll step through the code found in the folder sPWM_basic, and
66
66
67
67
### sPWM_Basic
68
68
69
-
The following C code implements an sPWM on a Atmel micro-controller. The signal is generated on two pins, one responsible for the positive half of the sine wave and the other pin the negative half. The sPWM is generated by running an (ISR) every period of the PWM in order to dynamically change the duty-cycle. This is done by changing the values in the registers OCR1A and OCR1B from values in a look up table. There are two look up tables for each of the two pins, lookUpTable1 and lookUpTable2 and both have 200 values. The first half of lookUpTable1 has sin values from 0 to π and the second half is all zeroes. The first half of lookUpTable2 is all zeroes and the second half has sin values from 0 to π as shown in figure below.
69
+
The following C code implements an sPWM on an Atmel micro-controller. The signal is generated on two pins, one responsible for the positive half of the sine wave and the other pin the negative half. The sPWM is generated by running an (ISR) every period of the PWM in order to dynamically change the duty-cycle. This is done by changing the values in the registers OCR1A and OCR1B from values in a look up table. There are two look up tables for each of the two pins, lookUpTable1 and lookUpTable2 and both have 200 values. The first half of lookUpTable1 has sin values from 0 to π and the second half is all zeroes. The first half of lookUpTable2 is all zeroes and the second half has sin values from 0 to π as shown in figure below.
We are going to be adressing the registeres on the atmel chip as well as using interrupts so the <avr/io.h> and <avr/interrupt.h> headers are nessisary. From there we have two arrays which have a two half sinusoidal signal entered in
87
+
We are going to address the registers on the atmel chip as well as using interrupts so the <avr/io.h> and <avr/interrupt.h> headers are necessary. From there we have two arrays which have a two half sinusoidal signal entered in
88
88
89
89
```c
90
90
void setup(){
@@ -105,7 +105,7 @@ void setup(){
105
105
1 TOV1 Flag interrupt enable.
106
106
*/
107
107
```
108
-
Here the timer registered have been initilised. If you ar interested in the deatails you can look up the 328p data sheet, but for now what's important is that we have set up a PWM for two pins and it call in interrupt routine for every period of the PWM.
108
+
Here the timer register have been initialised. If you are interested in the details you can look up the ATMEGA328p datasheet, but for now what's important is that we have set up a PWM for two pins and it call in interrupt routine for every period of the PWM.
109
109
110
110
```c
111
111
ICR1 = 1600; // Period for 16MHz crystal, for a switching frequency of 100KHz for 200 subdevisions per 50Hz sin wave cycle.
@@ -114,7 +114,7 @@ Here the timer registered have been initilised. If you ar interested in the deat
114
114
pinMode(13,OUTPUT);
115
115
}
116
116
```
117
-
ICR1 is another register that contains the length of the counter before resetting, since we have no prescale on our clock, this defines the period of the PWM to 1600 clock cycles. Then we enable interrupts. Next the two pins are set as outputs, the reason why pinMode() is not used is because the pins might change on different arduinos, they might also change on different Atmel micros, however you are using an arduino with a 328p, then this code will work. Lastly pinMode() is used to set pin 13 as an out put, we will use this later as a trigger for the osilliscope, how ever it is not nessisary.
117
+
ICR1 is another register that contains the length of the counter before resetting, since we have no prescale on our clock, this defines the period of the PWM to 1600 clock cycles. Then we enable interrupts. Next the two pins are set as outputs, the reason why pinMode() is not used is because the pins might change on different arduinos, they might also change on different Atmel micros, however you are using an arduino with a 328p, then this code will work. Lastly pinMode() is used to set pin 13 as an output, we will use this later as a trigger for the oscilloscope, however it is not necessary.
118
118
119
119
```c
120
120
void loop(){; /*Do nothing . . . . forever!*/}
@@ -138,11 +138,11 @@ ISR(TIMER1_OVF_vect){
138
138
```
139
139
This interrupt service routine is call every period of the PWM, and every period the duty-cycle is change. This done by changing the value in the registers OCR1A and OCR1B to the next value of the look up table as this registers hold the compare values that set the output pins low when reached as per figure .
140
140
141
-
Therefore each period the registeres OCR1x are loaded with the next value of their look up tables by using num to point to the next value in the array, as each period num is incremented and checked that it is below 200, if it is not below 200 in is reset to 0. The other two lines involving trig and digitalWrite are there two toggle a pin as a trigger for an osilloscope and does not impact the sPWM code.
141
+
Therefore in each period the registers OCR1x are loaded with the next value of their look up tables by using num to point to the next value in the array, as each period num is incremented and checked that it is below 200, if it is not below 200 in is reset to 0. The other two lines involving trig and digitalWrite are there two toggle a pin as a trigger for an osilloscope and does not impact the sPWM code.
142
142
143
143
### sPWM_generate_lookup_table
144
144
145
-
The rest of this section discusses some modifications to this code, namely we can make generate the lookup table at the start of the code, the benifits of this is we change change the switching frequency as well as the sPWM frequency. Code for this can be found in the sPWM_generate_lookup_table folder. The start of the code looks like this:
145
+
The rest of this section discusses some modifications to this code, namely we can make generate the lookup table at the start of the code, the benefit of this is we change the switching frequency as well as the sPWM frequency. Code for this can be found in the sPWM_generate_lookup_table folder. The start of the code looks like this:
146
146
147
147
```c
148
148
#include <avr/io.h>
@@ -166,7 +166,7 @@ void setup(){
166
166
lookUp[i] = (int)(temp+0.5); // Round to integer.
167
167
}
168
168
```
169
-
Notice that only the first half of the sine wave is generated, because of the way this code implements the sPMW where each of the two pins are responisble for different halves of the signal, only half the sine wave is needed. However it does require a modification to the interrupt service routine.
169
+
Notice that only the first half of the sine wave is generated, because of the way this code implements the sPMW where each of the two pins are responsible for different halves of the signal, only half the sine wave is needed. However it does require a modification to the interrupt service routine.
170
170
171
171
```c
172
172
ISR(TIMER1_OVF_vect){
@@ -190,15 +190,15 @@ ISR(TIMER1_OVF_vect){
190
190
num++;
191
191
}
192
192
```
193
-
Both output compare registers ORC1x have the same values loaded into them each period, however the output compare for each pin is enabled and disable in turns by toggling two bits in the TCCR1A resgister. It is toggle each time the look up table index (num) is reset, however it is delayed by one clock cycle, this is because when values are loaded into OCR1x registered, is is buffered where as changes in TCCR1A is implemented imediately, see the 328p datasheet for more details.
193
+
Both output compare registers ORC1x have the same values loaded into them each period, however the output compare for each pin is enabled and disable in turns by toggling two bits in the TCCR1A register. It is toggle each time the look up table index (num) is reset, however it is delayed by one clock cycle, this is because when values are loaded into OCR1x registered, is buffered whereas changes in TCCR1A is implemented immediately, see the 328p datasheet for more details.
194
194
195
195
## Testing the Signal
196
196
197
197
This chapter discusses ways to test and monitor the sPWM signal, the first section discusses using as oscilloscope which is the best method to verify the signal however an alternate and cheaper method is to use a small speaker. The 50hz signal and the underlying switching frequency is easy to hear.
198
198
199
-
### Viewing Pulse Widths with an Osilloscope
199
+
### Viewing Pulse Widths with an Oscilloscope
200
200
201
-
Here we aim to view the individual pulses that make up the sPWM to see if they look how we would expect, that is thin pulses becoming thick and then thin again. If you are using the code sPWM_generate _lookup_table I recommend lowering the switching frequency of the sPWM by changing #define SinDivisions(200) to #define SinDivisions (50). This will make the pulses easier to see as there will be fewer of them. If you are using the Uno pin 13 will be toggled every period of the sine and so can be used as a trigger for the osilloscope. the figure below shows the wiring to the Ardurino Uno.
201
+
Here we aim to view the individual pulses that make up the sPWM to see if they look how we would expect, that is thin pulses becoming thick and then thin again. If you are using the code sPWM_generate _lookup_table I recommend lowering the switching frequency of the sPWM by changing #define SinDivisions(200) to #define SinDivisions (50). This will make the pulses easier to see as there will be fewer of them. If you are using the Uno pin 13 will be toggled every period of the sine and so can be used as a trigger for the oscilloscope. the figure below shows the wiring to the Arduino Uno.
The purpose of the filter is to remove the much higher switching frequency (fs) and leave only the 50Hz sine wave. The cut-off frequency (fc) of the filter determined is by fc = 1/2πRC, and it should lie somewhere between fs and 50Hz, closer to 50Hz is more optimal. fs is determined by the line of code #define SinDivisions (a number) in sPWM_generate_lookup_table. The switching frequency is given by fs = SinDivisions×50Hz. Using an arbitrary number for SinDivisions may produce unexpected results, I recommend using 50,200 and 400 to produced fs’s of 2.5, 10 and 20 KHz respectively. The filtered signal is shown in the figure below.
215
+
The purpose of the filter is to remove the much higher switching frequency (fs) and leave only the 50Hz sine wave. The cut-off frequency (fc) of the filter determined is by fc = 1/2πRC, and it should lie somewhere between fs and 50Hz, closer to 50Hz is more optimal. fs is determined by the line of code #define SinDivisions (a number) in sPWM_generate_lookup_table. The switching frequency is given by fs = SinDivisions×50Hz. Using an arbitrary number for SinDivisions may produce unexpected results, I recommend using 50,200 and 400 to produced fs’s of 2.5, 10 and 20 kHz respectively. The filtered signal is shown in the figure below.
@@ -244,14 +244,14 @@ It is recommended to change #define SinDivisions (200) to 50, 200 and 400 in ord
244
244
245
245
Please let me know if you got the code to work on a device that's not listed here
246
246
247
-
Compatability list:
247
+
Comparability list:
248
248
249
249
* Arduino Uno
250
250
* Arduino Nano
251
251
* Arduino mega2560
252
252
253
253
## Safety
254
254
255
-
This section is to briefly discuss safety in regards to making an inverter that steps up to mains voltage whether that be 110 or 230. First of all I don't encourage it, I'd prefer that you didn't and I take no responsibilty for your actions. Remember 30mA can be leathal, mains voltage deserves respect.
255
+
This section is to briefly discuss safety in regards to making an inverter that steps up to mains voltage whether that be 110 or 230. First of all, I don't encourage it, I'd prefer that you didn't and I take no responsibility for your actions. Remember 30mA can be lethal, mains voltage deserves respect.
256
256
257
257
If you still choose to do so, take basic precautionary steps like: Invest in some terminals and make sure that any high voltage part of the circuit is not touchable; don't modify it while it's power up; Don't do it alone.
0 commit comments