Skip to content

Commit c982d0a

Browse files
committed
corrected some typos in README.md
Signed-off-by: Zakaria <[email protected]>
1 parent 33c031d commit c982d0a

File tree

1 file changed

+18
-18
lines changed

1 file changed

+18
-18
lines changed

README.md

+18-18
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Please also note that:
1212

1313
* It's assumed the reader has a basic understanding of C programming
1414
* If you plan on making an inverter please read the safety section
15-
* Feel free to colaborate on improving this repo
15+
* Feel free to collaborate on improving this repo
1616

1717

1818
## Table of Contents
@@ -40,15 +40,15 @@ Pulse width modulation’s (PWM) main use is to control the voltage supplied to
4040

4141
![Figure 1-1](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/basicPWM_3.png?raw=true "Figure 1.1")
4242

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.
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.
4444

4545
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/basicPWM_4.png?raw=true "Figure")
4646

4747
### Typical microcontroller PWM implementation
4848

4949
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.
5050

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.
5252

5353
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/sawtooth_counter_1.png?raw=true "Figure")
5454

@@ -66,11 +66,11 @@ In this chapter we'll step through the code found in the folder sPWM_basic, and
6666

6767
### sPWM_Basic
6868

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.
7070

7171
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/lookup_2.png?raw=true "Figure")
7272

73-
The code assumes implementation on a Arduino Uno but is likely compatable with other boards. see Compatability.
73+
The code assumes implementation on an Arduino Uno but is likely compatible with other boards. see Compatibility.
7474

7575
Lets walk through the code.
7676

@@ -84,7 +84,7 @@ int lookUp2[] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
8484

8585
```
8686
87-
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
8888
8989
```c
9090
void setup(){
@@ -105,7 +105,7 @@ void setup(){
105105
1 TOV1 Flag interrupt enable.
106106
*/
107107
```
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.
109109

110110
```c
111111
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
114114
pinMode(13,OUTPUT);
115115
}
116116
```
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.
118118
119119
```c
120120
void loop(){; /*Do nothing . . . . forever!*/}
@@ -138,11 +138,11 @@ ISR(TIMER1_OVF_vect){
138138
```
139139
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 .
140140
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.
142142
143143
### sPWM_generate_lookup_table
144144
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:
146146
147147
```c
148148
#include <avr/io.h>
@@ -166,7 +166,7 @@ void setup(){
166166
lookUp[i] = (int)(temp+0.5); // Round to integer.
167167
}
168168
```
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.
170170

171171
```c
172172
ISR(TIMER1_OVF_vect){
@@ -190,15 +190,15 @@ ISR(TIMER1_OVF_vect){
190190
num++;
191191
}
192192
```
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.
194194
195195
## Testing the Signal
196196
197197
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.
198198
199-
### Viewing Pulse Widths with an Osilloscope
199+
### Viewing Pulse Widths with an Oscilloscope
200200
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.
202202
203203
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/PulseOscill_1.png?raw=true "Figure")
204204
@@ -212,15 +212,15 @@ Here we aim to view a smooth sinusoidal wave by smoothing the output of the micr
212212
213213
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/filterOscill_2.png?raw=true "Figure")
214214
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.
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.
216216
217217
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/smoothed_2.png?raw=true "Figure")
218218
219219
Alternatively a potentiometer can be used as a variable resistor as shown in the figure below.
220220
221221
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/trimpot_RCfilter_2.png?raw=true "Figure")
222222
223-
This allows the fc to be varied. The followwing five figures show the result of changing the potentiometer and therefore the amount of filtering.
223+
This allows the fc to be varied. The following five figures show the result of changing the potentiometer and therefore the amount of filtering.
224224
225225
![Figure what](https://github.com/Terbytes/Arduino-Atmel-sPWM/blob/master/im/smothing_1.png?raw=true "Figure")
226226
@@ -244,14 +244,14 @@ It is recommended to change #define SinDivisions (200) to 50, 200 and 400 in ord
244244
245245
Please let me know if you got the code to work on a device that's not listed here
246246
247-
Compatability list:
247+
Comparability list:
248248
249249
* Arduino Uno
250250
* Arduino Nano
251251
* Arduino mega2560
252252
253253
## Safety
254254
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.
256256
257257
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

Comments
 (0)