PDA

View Full Version : sinusoidal PWM



bwaxing
- 28th February 2011, 08:45
Hi there,i'm new to this forum,m learning the PIC BASIC PRO programming and now i want to generate a sinusoidal pulse width modulated signal by using pic16f877 microcontroller,please i need some ideas on how to go about it and code example to start with....

ScaleRobotics
- 28th February 2011, 10:49
Hello and welcome to the forum.

Microchip has an application note for sine wave with the 16F series chip. They show two ways to do it, one with PWM and the next with a resistor ladder. http://ww1.microchip.com/downloads/en/AppNotes/00655a.pdf

The PIC18F2431 and PIC18F4431 have some great features for multi pwm sine waves. So recently most of the examples use this chip.

Here are a few examples: http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts

http://www.picbasic.co.uk/forum/showthread.php?t=14359

You can also enter a search for sine and get some more.

bwaxing
- 28th February 2011, 12:32
thanx..m working on them

bwaxing
- 2nd March 2011, 12:28
Hi,i've read the Microchip appliction notes for sine wave with the 16F series chip..http://ww1.microchip.com/downloads/en/AppNotes/00655a.pdf (http://http://ww1.microchip.com/downloads/en/AppNotes/00655a.pdf) together with the examples given in http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT- interrupts (http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts) and http://www.picbasic.co.uk/forum/showthread.php?t=14359.

there are number of things which i've not understand from these readings and i'm asking for help from anyone who can help me to understand.these things are:
1)how to generate a lookup table for the sine waveforms
2)how to include DT_INTS-18.bas file so that when i compile,the compiler will be able to open it
3)what is the purpose of this piece of code from example of http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts

asm
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H
__CONFIG _CONFIG4L, _LVP_OFF_4L
endasm

thank you in advance.

ronsimpson
- 2nd March 2011, 13:55
1) You could use the 32 location array you pointed at in question 3. I used M.S. EXCEL.
3) Get the data sheet for the PIC in PDF format and search for _OSC_HSPLL_1H or some piece of that. In the first of the 3 you can see these bits setup the oscillator and PLL. Most of the PICs have many modes for the oscillator. Internal/ external, divide by 32/ multiply by 4, etc.

1)how to generate a lookup table for the sine waveforms
2)how to include DT_INTS-18.bas file so that when i compile,the compiler will be able to open it
3)what is the purpose of this piece of code from example of http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts

asm
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H
__CONFIG _CONFIG4L, _LVP_OFF_4L
endasm

thank you in advance.[/QUOTE]

pxidr84
- 2nd March 2011, 14:16
to bwaxing:

My advice : read this great post with exemples, the sine is stored in an array :
http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts

bwaxing
- 2nd March 2011, 14:39
thanks for the advice,i read examples from that post and I've not understand how to create the lookup table.From that post sine is stored in the array and i don't understand how the value for a particular step have been determined.for example i want to use 8-bit resolutions (256 steps),how will i determine the value of each step?is there a formula or something?
thanks again.

pxidr84
- 2nd March 2011, 15:34
sine[1]=0
.
.
.
sine[128]=255

Excel can do that. The first number is the angle (1->128, like 0-360°), the second is the result of the sine (0->255, like 0-1).

For each interruption, the command duty=sine[counter] will read the sine value located in the array and the position of this value in the array is determined by the "counter" variable. The result of this command is stored in the "duty" variable.

A little example:


counter=128

loop:

duty=sine[counter]

PWM pin,duty,cycle

counter=counter-1
if counter=0 then counter=128

goto loop

In each loop the counter value is decremented by one, and when the step value equals 0, the counter is reinizialized to 128.

So in this case, to make a complete sine, it will take 128 loops. If you want a 1Hz sine, you have to repeat this loop exactly 128 times per second.

ScaleRobotics
- 2nd March 2011, 16:40
The max I see most people do is a 72 step lookup or array. (36 or 72 steps makes it easier to off set for multiple phases). The resistor capacitor filter smooths out the steps. It is still 8 bit resolution, even with 32 or 36 steps. If you wanted to have each value be more accurate, you could use 10 bits in your values for each step.

bwaxing
- 3rd March 2011, 12:57
Hi,
thanks for the tip,m trying to modify the example you gave in http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts so that i can generate a 50Hz sinusoidal PWM signal to control a single phase inverter using pic16f877.If i understand u correctly,in the sine array you jumped four steps to get 128 steps of 8-bit resolution,but how you got the correspond value for each step is not clear to me,i want to learn how to create a lookup table the way you did as i dont know how to create it using excel.what formula was used to get these values from that example?
; Set sine "table" in an array
sineval var byte[32]
sineval[1] = 128
sineval[2] = 148
sineval[3] = 167
sineval[4] = 185
sineval[5] = 200 etc.

Also for 50Hz,PR2 will be loaded with 78 for 20MHz oscillator frequency of 16f877,but i dont how to arrive in determination of the value loaded for variable'' timerone''.

When i copied the example and try to compile i got the warning 'unable to open include file DT_INTS-18.bas'..what should i do about this?

Finally,is there any other modification i should do in that program that it could work better in pic16f877?

pxidr84
- 3rd March 2011, 15:04
You have to download Darrel Taylor's interrupts system : http://darreltaylor.com/DT_INTS-14/intro.html

And put the "DT_INTS-14.bas", etc. into the folder of your source files.

bwaxing
- 3rd March 2011, 15:28
Hi,
i have download DT_INTS-14.bas" and DT_INTS-18.bas files and put them in the folder of my source files,when i try to compile the program again the same warning appeared again "unable to open INCLUDE file DT_INTS-18.bas"!

ScaleRobotics
- 3rd March 2011, 18:38
Hi,
i have download DT_INTS-14.bas" and DT_INTS-18.bas files and put them in the folder of my source files,when i try to compile the program again the same warning appeared again "unable to open INCLUDE file DT_INTS-18.bas"!

You would need to change the include statement, so that it is using DT_INTS-14 instead of DTS_INTS-18. 18 is for PIC18's, DT_INTS-14 is for lower chips, like PIC17,PIC16 and PIC12's.

Then there are probably different registers that will give you errors, etc. You should be able to change it, (and also the configs), but it will be a little work.

bwaxing
- 3rd March 2011, 19:41
hi everybody,

i'm here again with the sinusoidal PWM, please bear with me,

It seems there were some problems with my compiler but after re-installing it,things work pretty well,i've included the file DT_INTS-14.bas in the folder containing the source code and although there some errors,its a good start to me.
there are few things which are not clear to me from the example ofhttp://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts
How to obtain the correspond value for each step is not clear to me,i want to learn how to create a lookup table the way it is done in the example as i dont know how to create it using excel.what formula was used to get these values from that example?
; Set sine "table" in an array
sineval var byte[32]
sineval[1] = 128
sineval[2] = 148
sineval[3] = 167
sineval[4] = 185
sineval[5] = 200 etc.

Also for 50Hz,PR2 will be loaded with 78 for 20MHz oscillator frequency of 16f877,but i dont how to arrive in determination of the value loaded for variable'' timerone''.

Should i include DT_INTS-18.bas file or DT_INTS-14.bas file?it seems to me they perform different functions!which link will i get DT_INTS-18.bas file?

Finally,is there any other modification i should do in that program that it could work better in pic16f877?

Thank you in advance.

ScaleRobotics
- 4th March 2011, 00:05
hi everybody,

i'm here again with the sinusoidal PWM, please bear with me,

It seems there were some problems with my compiler but after re-installing it,things work pretty well,i've included the file DT_INTS-14.bas in the folder containing the source code and although there some errors,its a good start to me.
there are few things which are not clear to me from the example ofhttp://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT-interrupts
How to obtain the correspond value for each step is not clear to me,i want to learn how to create a lookup table the way it is done in the example as i dont know how to create it using excel.what formula was used to get these values from that example?
; Set sine "table" in an array
sineval var byte[32]
sineval[1] = 128
sineval[2] = 148
sineval[3] = 167
sineval[4] = 185
sineval[5] = 200 etc.

To be quite honest, I copied them from the application note I reference in the example I gave. It shows you a little more about it in the notes in the assembly code. If you wanted to make your own, you just need to figure out how many steps you are going to make. If you were doing 36 steps, each step would be 10 degrees. Sin(10 degrees) * 102 + 128 = number. In the Microchip example, they had the max = 90 percent. So 90 percent * 255 = 230. 230 - 128 (the midpoint) = 102. So it will swing + or - 102 from the midpoint (128).

Then we can make a spreadsheet for our steps. I put the Microchip steps in on the left, then degrees for each step, then the formulated value on the right. As you can see, these pretty much match the Microchip values. You would have to do something similar for your 72 steps.

5251


Also for 50Hz,PR2 will be loaded with 78 for 20MHz oscillator frequency of 16f877,but i dont how to arrive in determination of the value loaded for variable'' timerone''.

You will have to experiment with a scope to see what it comes out at. At least, that is how I did it. There are a lot of coming in and out of interrupts and such.


Should i include DT_INTS-18.bas file or DT_INTS-14.bas file?it seems to me they perform different functions!which link will i get DT_INTS-18.bas file?

Read my previous reply, I think I answered this already.


Finally,is there any other modification i should do in that program that it could work better in pic16f877?

Only change what won't work on a PIC16877 to what will work on a Pic16f877;)

I have not checked to see all that is incompatible. You will have to do a little homework, checking the data sheets, and seeing if you get errors for registers that are incompatible. Seeing if the PWM is compatible, or if the way you address it needs to be changed. It's definately doable, as you can see from the Microchip application note which was written for a 16F device.

ronsimpson
- 4th March 2011, 00:20
Do you know Excel?
Here is 5 minutes work. Left side is 0 to 255. Right side is 0 to +127 to 0 to -127 to 0.
Graph right side!
0 0.0 0.0000 0.0000 0
1 1.4 0.0246 0.0246 3
2 2.8 0.0493 0.0493 6
3 4.2 0.0739 0.0739 9
4 5.6 0.0986 0.0984 12
5 7.1 0.1232 0.1229 16
6 8.5 0.1478 0.1473 19
7 9.9 0.1725 0.1716 22
8 11.3 0.1971 0.1958 25
9 12.7 0.2218 0.2199 28
10 14.1 0.2464 0.2439 31
11 15.5 0.2710 0.2677 34
12 16.9 0.2957 0.2914 37
13 18.4 0.3203 0.3149 40
14 19.8 0.3450 0.3382 43
15 21.2 0.3696 0.3612 46
16 22.6 0.3942 0.3841 49
17 24.0 0.4189 0.4067 52
18 25.4 0.4435 0.4291 54
19 26.8 0.4682 0.4512 57
20 28.2 0.4928 0.4731 60
21 29.6 0.5174 0.4947 63
22 31.1 0.5421 0.5159 66
23 32.5 0.5667 0.5369 68
24 33.9 0.5914 0.5575 71
25 35.3 0.6160 0.5778 73
26 36.7 0.6406 0.5977 76
27 38.1 0.6653 0.6173 78
28 39.5 0.6899 0.6365 81
29 40.9 0.7146 0.6553 83
30 42.4 0.7392 0.6737 86
31 43.8 0.7638 0.6917 88
32 45.2 0.7885 0.7093 90
33 46.6 0.8131 0.7264 92
34 48.0 0.8378 0.7431 94
35 49.4 0.8624 0.7594 96
36 50.8 0.8870 0.7752 98
37 52.2 0.9117 0.7905 100
38 53.6 0.9363 0.8054 102
39 55.1 0.9610 0.8197 104
40 56.5 0.9856 0.8336 106
41 57.9 1.0102 0.8470 108
42 59.3 1.0349 0.8598 109
43 60.7 1.0595 0.8721 111
44 62.1 1.0842 0.8839 112
45 63.5 1.1088 0.8952 114
46 64.9 1.1334 0.9059 115
47 66.4 1.1581 0.9160 116
48 67.8 1.1827 0.9256 118
49 69.2 1.2074 0.9347 119
50 70.6 1.2320 0.9432 120
51 72.0 1.2566 0.9511 121
52 73.4 1.2813 0.9584 122
53 74.8 1.3059 0.9651 123
54 76.2 1.3306 0.9713 123
55 77.6 1.3552 0.9768 124
56 79.1 1.3798 0.9818 125
57 80.5 1.4045 0.9862 125
58 81.9 1.4291 0.9900 126
59 83.3 1.4538 0.9932 126
60 84.7 1.4784 0.9957 126
61 86.1 1.5030 0.9977 127
62 87.5 1.5277 0.9991 127
63 88.9 1.5523 0.9998 127
64 90.4 1.5770 1.0000 127
65 91.8 1.6016 0.9995 127
66 93.2 1.6262 0.9985 127
67 94.6 1.6509 0.9968 127
68 96.0 1.6755 0.9945 126
69 97.4 1.7002 0.9916 126
70 98.8 1.7248 0.9882 125
71 100.2 1.7494 0.9841 125
72 101.6 1.7741 0.9794 124
73 103.1 1.7987 0.9741 124
74 104.5 1.8234 0.9683 123
75 105.9 1.8480 0.9618 122
76 107.3 1.8726 0.9548 121
77 108.7 1.8973 0.9472 120
78 110.1 1.9219 0.9390 119
79 111.5 1.9466 0.9302 118
80 112.9 1.9712 0.9209 117
81 114.4 1.9958 0.9110 116
82 115.8 2.0205 0.9006 114
83 117.2 2.0451 0.8896 113
84 118.6 2.0698 0.8781 112
85 120.0 2.0944 0.8660 110
86 121.4 2.1190 0.8534 108
87 122.8 2.1437 0.8403 107
88 124.2 2.1683 0.8267 105
89 125.6 2.1930 0.8126 103
90 127.1 2.2176 0.7980 101
91 128.5 2.2422 0.7829 99
92 129.9 2.2669 0.7674 97
93 131.3 2.2915 0.7513 95
94 132.7 2.3162 0.7348 93
95 134.1 2.3408 0.7179 91
96 135.5 2.3654 0.7005 89
97 136.9 2.3901 0.6827 87
98 138.4 2.4147 0.6645 84
99 139.8 2.4394 0.6459 82
100 141.2 2.4640 0.6269 80
101 142.6 2.4886 0.6075 77
102 144.0 2.5133 0.5878 75
103 145.4 2.5379 0.5677 72
104 146.8 2.5626 0.5472 69
105 148.2 2.5872 0.5264 67
106 149.6 2.6118 0.5053 64
107 151.1 2.6365 0.4839 61
108 152.5 2.6611 0.4622 59
109 153.9 2.6858 0.4402 56
110 155.3 2.7104 0.4180 53
111 156.7 2.7350 0.3955 50
112 158.1 2.7597 0.3727 47
113 159.5 2.7843 0.3497 44
114 160.9 2.8090 0.3265 41
115 162.4 2.8336 0.3032 39
116 163.8 2.8582 0.2796 36
117 165.2 2.8829 0.2558 32
118 166.6 2.9075 0.2319 29
119 168.0 2.9322 0.2079 26
120 169.4 2.9568 0.1837 23
121 170.8 2.9814 0.1595 20
122 172.2 3.0061 0.1351 17
123 173.6 3.0307 0.1107 14
124 175.1 3.0554 0.0861 11
125 176.5 3.0800 0.0616 8
126 177.9 3.1046 0.0370 5
127 179.3 3.1293 0.0123 2
128 180.7 3.1539 -0.0123 -2
129 182.1 3.1786 -0.0370 -5
130 183.5 3.2032 -0.0616 -8
131 184.9 3.2278 -0.0861 -11
132 186.4 3.2525 -0.1107 -14
133 187.8 3.2771 -0.1351 -17
134 189.2 3.3018 -0.1595 -20
135 190.6 3.3264 -0.1837 -23
136 192.0 3.3510 -0.2079 -26
137 193.4 3.3757 -0.2319 -29
138 194.8 3.4003 -0.2558 -32
139 196.2 3.4250 -0.2796 -36
140 197.6 3.4496 -0.3032 -39
141 199.1 3.4742 -0.3265 -41
142 200.5 3.4989 -0.3497 -44
143 201.9 3.5235 -0.3727 -47
144 203.3 3.5482 -0.3955 -50
145 204.7 3.5728 -0.4180 -53
146 206.1 3.5974 -0.4402 -56
147 207.5 3.6221 -0.4622 -59
148 208.9 3.6467 -0.4839 -61
149 210.4 3.6714 -0.5053 -64
150 211.8 3.6960 -0.5264 -67
151 213.2 3.7206 -0.5472 -69
152 214.6 3.7453 -0.5677 -72
153 216.0 3.7699 -0.5878 -75
154 217.4 3.7946 -0.6075 -77
155 218.8 3.8192 -0.6269 -80
156 220.2 3.8438 -0.6459 -82
157 221.6 3.8685 -0.6645 -84
158 223.1 3.8931 -0.6827 -87
159 224.5 3.9178 -0.7005 -89
160 225.9 3.9424 -0.7179 -91
161 227.3 3.9670 -0.7348 -93
162 228.7 3.9917 -0.7513 -95
163 230.1 4.0163 -0.7674 -97
164 231.5 4.0410 -0.7829 -99
165 232.9 4.0656 -0.7980 -101
166 234.4 4.0902 -0.8126 -103
167 235.8 4.1149 -0.8267 -105
168 237.2 4.1395 -0.8403 -107
169 238.6 4.1642 -0.8534 -108
170 240.0 4.1888 -0.8660 -110
171 241.4 4.2134 -0.8781 -112
172 242.8 4.2381 -0.8896 -113
173 244.2 4.2627 -0.9006 -114
174 245.6 4.2873 -0.9110 -116
175 247.1 4.3120 -0.9209 -117
176 248.5 4.3366 -0.9302 -118
177 249.9 4.3613 -0.9390 -119
178 251.3 4.3859 -0.9472 -120
179 252.7 4.4105 -0.9548 -121
180 254.1 4.4352 -0.9618 -122
181 255.5 4.4598 -0.9683 -123
182 256.9 4.4845 -0.9741 -124
183 258.4 4.5091 -0.9794 -124
184 259.8 4.5337 -0.9841 -125
185 261.2 4.5584 -0.9882 -125
186 262.6 4.5830 -0.9916 -126
187 264.0 4.6077 -0.9945 -126
188 265.4 4.6323 -0.9968 -127
189 266.8 4.6569 -0.9985 -127
190 268.2 4.6816 -0.9995 -127
191 269.6 4.7062 -1.0000 -127
192 271.1 4.7309 -0.9998 -127
193 272.5 4.7555 -0.9991 -127
194 273.9 4.7801 -0.9977 -127
195 275.3 4.8048 -0.9957 -126
196 276.7 4.8294 -0.9932 -126
197 278.1 4.8541 -0.9900 -126
198 279.5 4.8787 -0.9862 -125
199 280.9 4.9033 -0.9818 -125
200 282.4 4.9280 -0.9768 -124
201 283.8 4.9526 -0.9713 -123
202 285.2 4.9773 -0.9651 -123
203 286.6 5.0019 -0.9584 -122
204 288.0 5.0265 -0.9511 -121
205 289.4 5.0512 -0.9432 -120
206 290.8 5.0758 -0.9347 -119
207 292.2 5.1005 -0.9256 -118
208 293.6 5.1251 -0.9160 -116
209 295.1 5.1497 -0.9059 -115
210 296.5 5.1744 -0.8952 -114
211 297.9 5.1990 -0.8839 -112
212 299.3 5.2237 -0.8721 -111
213 300.7 5.2483 -0.8598 -109
214 302.1 5.2729 -0.8470 -108
215 303.5 5.2976 -0.8336 -106
216 304.9 5.3222 -0.8197 -104
217 306.4 5.3469 -0.8054 -102
218 307.8 5.3715 -0.7905 -100
219 309.2 5.3961 -0.7752 -98
220 310.6 5.4208 -0.7594 -96
221 312.0 5.4454 -0.7431 -94
222 313.4 5.4701 -0.7264 -92
223 314.8 5.4947 -0.7093 -90
224 316.2 5.5193 -0.6917 -88
225 317.6 5.5440 -0.6737 -86
226 319.1 5.5686 -0.6553 -83
227 320.5 5.5933 -0.6365 -81
228 321.9 5.6179 -0.6173 -78
229 323.3 5.6425 -0.5977 -76
230 324.7 5.6672 -0.5778 -73
231 326.1 5.6918 -0.5575 -71
232 327.5 5.7165 -0.5369 -68
233 328.9 5.7411 -0.5159 -66
234 330.4 5.7657 -0.4947 -63
235 331.8 5.7904 -0.4731 -60
236 333.2 5.8150 -0.4512 -57
237 334.6 5.8397 -0.4291 -54
238 336.0 5.8643 -0.4067 -52
239 337.4 5.8889 -0.3841 -49
240 338.8 5.9136 -0.3612 -46
241 340.2 5.9382 -0.3382 -43
242 341.6 5.9629 -0.3149 -40
243 343.1 5.9875 -0.2914 -37
244 344.5 6.0121 -0.2677 -34
245 345.9 6.0368 -0.2439 -31
246 347.3 6.0614 -0.2199 -28
247 348.7 6.0861 -0.1958 -25
248 350.1 6.1107 -0.1716 -22
249 351.5 6.1353 -0.1473 -19
250 352.9 6.1600 -0.1229 -16
251 354.4 6.1846 -0.0984 -12
252 355.8 6.2093 -0.0739 -9
253 357.2 6.2339 -0.0493 -6
254 358.6 6.2585 -0.0246 -3
255 360.0 6.2832 0.0000 0

bwaxing
- 4th March 2011, 14:59
Hi everyone.....

First of all thanks to all of you who have been kind to assist me in this journey of learning PIC programming,this is important for me for my final project in my bachelor degree in electrical engineering...
Back to business,i've been working on the suggestions and examples offered to me and things seems to go a little bit forward...however this code is not compiling successfully..


define OSC 20
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3

asm
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H
__CONFIG _CONFIG4L, _LVP_OFF_4L
endasm

ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 16
PR2 = 34 ;set for 36Khz HPWM(=72 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000110 ;enable timer2 and set timer2 prescaler value of 1:4

STEPCOUNT var byte
stepcount = 256

; Set sine "table" in an array
sineval var byte[72]
sineval[1] = 128 ;0 degree
sineval[2] = 137 ;5 degree
sineval[3] = 146
sineval[4] = 154
sineval[5] = 163
sineval[6] = 171
sineval[7] = 179
sineval[8] = 187
sineval[9] = 194
sineval[10] = 200
sineval[11] = 206
sineval[12] = 212
sineval[13] = 216
sineval[14] = 220
sineval[15] = 224
sineval[16] = 227
sineval[17] = 228
sineval[18] = 229
sineval[19] = 230 ;90 degree
sineval[20] = 229
sineval[21] = 228
sineval[22] = 227
sineval[23] = 224
sineval[24] = 220
sineval[25] = 216
sineval[26] = 212
sineval[27] = 206
sineval[28] = 200
sineval[29] = 194
sineval[30] = 187
sineval[31] = 179
sineval[32] = 171
sineval[33] = 163
sineval[34] = 154
sineval[35] = 146
sineval[36] = 137
sineval[37] = 128 ;180 degree
sineval[38] = 119
sineval[39] = 110
sineval[40] = 102
sineval[41] = 93
sineval[42] = 85
sineval[43] = 77
sineval[44] = 69
sineval[45] = 62
sineval[46] = 56
sineval[47] = 50
sineval[48] = 44
sineval[49] = 40
sineval[50] = 36
sineval[51] = 32
sineval[52] = 29
sineval[53] = 28
sineval[54] = 26
sineval[55] = 26
sineval[56] = 26
sineval[57] = 28
sineval[58] = 29
sineval[59] = 32
sineval[60] = 36
sineval[61] = 40
sineval[62] = 44
sineval[63] = 50
sineval[64] = 56
sineval[65] = 62
sineval[66] = 69
sineval[67] = 77
sineval[68] = 85
sineval[69] = 93
sineval[70] = 102
sineval[71] = 110
sineval[72] =119

timerone var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = $31
TMR1L = 255 ; Prescaler = 8, TMR1ON
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = $FD00 ;gives about 50 hz sine
Main:
pause 5
if timerone = $F9FF then timerone = $FF00

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 72

@ INT_RETURN

one of the thing i'm messing up is this part of my code
asm
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H
__CONFIG _CONFIG4L, _LVP_OFF_4L
endasm

To be honest i've been working on this code for the whole day looking on the data sheets but cant find a way out to make it work...:confused: of course there are other errors..

Thank you in advance.

ScaleRobotics
- 4th March 2011, 15:44
I don't think your chip has a PLL. So its always best to go with the default configs when you try to change chips. So if you just erase this from the code:


asm
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H
__CONFIG _CONFIG4L, _LVP_OFF_4L
endasm


It will use the defaults located in PBP under your chipname.inc

Then you will get less errors :)

bwaxing
- 4th March 2011, 18:17
I don't think your chip has a PLL. So its always best to go with the default configs when you try to change chips. So if you just erase this from the code:


asm
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2H, _WDTEN_OFF_2H & _WDPS_512_2H
__CONFIG _CONFIG4L, _LVP_OFF_4L
endasm


It will use the defaults located in PBP under your chipname.inc


Then you will get less errors :)

I've removed that part of the code together with other modifications but these two errors kip on coming,i dont how to make it work....

m getting these two assembler errors.
ERROR:("INT_Handler"-Interrupt flag(PIR1,TMR1IF) not found.)
ERROR:("INT_ENABLE"-Interrupt flag(PIR1,TMR1IF) not found.)

code.

; i'm using pic16f877
;
define OSC 20
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3

ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 16
PR2 = 34 ;set for 36Khz HPWM(=72 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000110 ;enable timer2 and set timer2 prescaler value of 1:4

STEPCOUNT var byte
stepcount = 256

; Set sine "table" in an array
sineval var byte[72]
sineval[1] = 128 ;0 degree
sineval[2] = 137 ;5 degree
sineval[3] = 146
sineval[4] = 154
sineval[5] = 163
sineval[6] = 171
sineval[7] = 179
sineval[8] = 187
sineval[9] = 194
sineval[10] = 200
sineval[11] = 206
sineval[12] = 212
sineval[13] = 216
sineval[14] = 220
sineval[15] = 224
sineval[16] = 227
sineval[17] = 228
sineval[18] = 229
sineval[19] = 230 ;90 degree
sineval[20] = 229
sineval[21] = 228
sineval[22] = 227
sineval[23] = 224
sineval[24] = 220
sineval[25] = 216
sineval[26] = 212
sineval[27] = 206
sineval[28] = 200
sineval[29] = 194
sineval[30] = 187
sineval[31] = 179
sineval[32] = 171
sineval[33] = 163
sineval[34] = 154
sineval[35] = 146
sineval[36] = 137
sineval[37] = 128 ;180 degree
sineval[38] = 119
sineval[39] = 110
sineval[40] = 102
sineval[41] = 93
sineval[42] = 85
sineval[43] = 77
sineval[44] = 69
sineval[45] = 62
sineval[46] = 56
sineval[47] = 50
sineval[48] = 44
sineval[49] = 40
sineval[50] = 36
sineval[51] = 32
sineval[52] = 29
sineval[53] = 28
sineval[54] = 26
sineval[55] = 26
sineval[56] = 26
sineval[57] = 28
sineval[58] = 29
sineval[59] = 32
sineval[60] = 36
sineval[61] = 40
sineval[62] = 44
sineval[63] = 50
sineval[64] = 56
sineval[65] = 62
sineval[66] = 69
sineval[67] = 77
sineval[68] = 85
sineval[69] = 93
sineval[70] = 102
sineval[71] = 110
sineval[72] =119

timerone var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = $31
TMR1L = 255 ; Prescaler = 8, TMR1ON
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = $FD00 ;gives about 50 hz sine
Main:
pause 5
if timerone = $F9FF then timerone = $FF00

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 72
@ INT_RETURN

ScaleRobotics
- 4th March 2011, 19:23
Something is not right. Are you compiling for the right chip, the PIC16F877? Because it does have those registers and bits. Are you using MPASM as your assembler, because the include file requires this. Can you send me your myprogram.lst file? That might tell me more....

ScaleRobotics
- 5th March 2011, 04:47
In fact, your code compiles well over here.

bwaxing
- 5th March 2011, 05:51
Hi, I've been trying to send you the .LST file,but it's bigger than 500000 characters,so i could not upload it on the forum,how should i send it?:confused:

bwaxing
- 5th March 2011, 05:57
Something is not right. Are you compiling for the right chip, the PIC16F877? Because it does have those registers and bits. Are you using MPASM as your assembler, because the include file requires this. Can you send me your myprogram.lst file? That might tell me more....

Yes i'm compiling for the PIC16F877 using MPSAM as my assembler :)

bwaxing
- 5th March 2011, 07:10
I've converted the .lst file into pdf format so that i will be able to attach it,hope it will still serve the purpose.....:)

ScaleRobotics
- 5th March 2011, 09:19
Hmmm. The thing that jumps out at me a bit is that you are using Mpasm v2.30. I think that came out in 1999. Really! I think it is time to upgrade. See if that helps you. You can get the latest one by downloading MPLAB IDE here: http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002

bwaxing
- 5th March 2011, 11:52
Thanks for the tip....yup,it's it working well now....:)
i'm reading the pic16f877 data sheet page 63 about how to change the duty cycle of th pwm,it says the duty cycle is specified by writing to CCPR1L:CCPCON<5:4>. So in our case does this code below specify the duty cycle?if not where the duty cycle of pwm has been specified in the program?i want to know so that i may modify the duty cycle to make it equal to 90%.
code:


sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 72

ScaleRobotics
- 5th March 2011, 15:43
Great!

Yes, that is the duty cycle. Why not modify your array for the 90% instead of doing math here? We want to keep multiplication out of our assembly interrupt handler, otherwise, we will need to change it to a PBP type interrupt. And that would take a lot of time for each interrupt, as it needs to save and restore 70 registers each time it interrupts. If you need it to change dynamically, the beauty of an array rather than a lookup, is that you can change it on the fly (doing math in your main).

bwaxing
- 5th March 2011, 16:45
Thanks, i think i got it...let me experiment with the code i have and see what i got.....
thank again..:)

bwaxing
- 2nd May 2011, 15:52
hellow everyone,

I'm simulating this code on proteus Isis but m not getting the expected waveform(sinusoidal wave form)....the code compiles successful...but the waveform i'm getting getting on the scope is not the one...i need help please..



;
define OSC 20

;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
STEPCOUNT var byte 'Define stepcount as byte type variable
stepcount = 256

;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION*************
ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 16
PR2 = 34 ;set for 36Khz HPWM(=72 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000110 ;enable timer2 and set timer2 prescaler value of 1:4

;****************A sine lookup table in an array********************************
sineval var byte[72]
sineval[1] = 128 ;0 degree
sineval[2] = 137 ;5 degree
sineval[3] = 146
sineval[4] = 154
sineval[5] = 163
sineval[6] = 171
sineval[7] = 179
sineval[8] = 187
sineval[9] = 194
sineval[10] = 200
sineval[11] = 206
sineval[12] = 212
sineval[13] = 216
sineval[14] = 220
sineval[15] = 224
sineval[16] = 227
sineval[17] = 228
sineval[18] = 229
sineval[19] = 230 ;90 degree
sineval[20] = 229
sineval[21] = 228
sineval[22] = 227
sineval[23] = 224
sineval[24] = 220
sineval[25] = 216
sineval[26] = 212
sineval[27] = 206
sineval[28] = 200
sineval[29] = 194
sineval[30] = 187
sineval[31] = 179
sineval[32] = 171
sineval[33] = 163
sineval[34] = 154
sineval[35] = 146
sineval[36] = 137
sineval[37] = 128 ;180 degree
sineval[38] = 119
sineval[39] = 110
sineval[40] = 102
sineval[41] = 93
sineval[42] = 85
sineval[43] = 77
sineval[44] = 69
sineval[45] = 62
sineval[46] = 56
sineval[47] = 50
sineval[48] = 44
sineval[49] = 40
sineval[50] = 36
sineval[51] = 32
sineval[52] = 29
sineval[53] = 28
sineval[54] = 26
sineval[55] = 26
sineval[56] = 26
sineval[57] = 28
sineval[58] = 29
sineval[59] = 32
sineval[60] = 36
sineval[61] = 40
sineval[62] = 44
sineval[63] = 50
sineval[64] = 56
sineval[65] = 62
sineval[66] = 69
sineval[67] = 77
sineval[68] = 85
sineval[69] = 93
sineval[70] = 102
sineval[71] = 110
sineval[72] =119

timerone var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

;********Define INT_Handler as ISR**********************************************
ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = $31 ; Prescaler = 8, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = $EE16 ;gives about 50 hz sine
Main:
pause 5
'if timerone = $F9FF then timerone = $FF00

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 72
@ INT_RETURN


simulation results attached

ScaleRobotics
- 2nd May 2011, 16:19
I don't see any kind of wave form on the scope???

bwaxing
- 2nd May 2011, 16:52
sure,it is just a line and not a sine wave form as expected....the simulation log say there are attempts to read unimplemented memory locations being ignored..i dont know what does that mean and if it may be one of the cause...i need help.

walter
- 2nd May 2011, 17:06
Maybe it is complaining that you have set your array to:
sineval var byte[72]

and then you go from 1 to 72.

You either need to change it to 0 to 71, or change your array size to 73

bwaxing
- 2nd May 2011, 17:50
i have changed the number of array size together with other modifications but there is no change in the simulation result,it is still a line....


define OSC 20

;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
STEPCOUNT var byte 'Define stepcount as byte type variable
stepcount = 256

;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION*************
ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 16
PR2 = 34 ;set for 36Khz HPWM(=72 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000110 ;enable timer2 and set timer2 prescaler value of 1:4

;****************A sine lookup table in an array********************************
sineval var byte[73]
sineval[1] = 128 ;0 degree
sineval[2] = 137 ;5 degree
sineval[3] = 146
sineval[4] = 154
sineval[5] = 163
sineval[6] = 171
sineval[7] = 179
sineval[8] = 187
sineval[9] = 194
sineval[10] = 200
sineval[11] = 206
sineval[12] = 212
sineval[13] = 216
sineval[14] = 220
sineval[15] = 224
sineval[16] = 227
sineval[17] = 228
sineval[18] = 229
sineval[19] = 230 ;90 degree
sineval[20] = 229
sineval[21] = 228
sineval[22] = 227
sineval[23] = 224
sineval[24] = 220
sineval[25] = 216
sineval[26] = 212
sineval[27] = 206
sineval[28] = 200
sineval[29] = 194
sineval[30] = 187
sineval[31] = 179
sineval[32] = 171
sineval[33] = 163
sineval[34] = 154
sineval[35] = 146
sineval[36] = 137
sineval[37] = 128 ;180 degree
sineval[38] = 119
sineval[39] = 110
sineval[40] = 102
sineval[41] = 93
sineval[42] = 85
sineval[43] = 77
sineval[44] = 69
sineval[45] = 62
sineval[46] = 56
sineval[47] = 50
sineval[48] = 44
sineval[49] = 40
sineval[50] = 36
sineval[51] = 32
sineval[52] = 29
sineval[53] = 28
sineval[54] = 26
sineval[55] = 26
sineval[56] = 26
sineval[57] = 28
sineval[58] = 29
sineval[59] = 32
sineval[60] = 36
sineval[61] = 40
sineval[62] = 44
sineval[63] = 50
sineval[64] = 56
sineval[65] = 62
sineval[66] = 69
sineval[67] = 77
sineval[68] = 85
sineval[69] = 93
sineval[70] = 102
sineval[71] = 110
sineval[72] =119

timerone var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

;********Define INT_Handler as ISR**********************************************
ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = $31 ; Prescaler = 8, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = $EE16 ;gives about 50 hz sine
Main:
pause 5
'if timerone = $F9FF then timerone = $FF00

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 1 then stepcount = 73
@ INT_RETURN

cncmachineguy
- 2nd May 2011, 22:04
First thing I would do is make sure the ISR is working. Make an unused pin an output, then toggle it in the ISR. hook a scope to that and make sure it toggles. Also you can do the same in your main with another pin.

This way you will know some basic info like is my pic running, is my interrupt firing. do that and report back

bwaxing
- 6th May 2011, 12:06
hi,
i've managed to get the sinusoidal output sine wave although i'm getting frequency of 202Hz instead of 50Hz and peak voltage of 4.58v instead of 4.5v.Also the waveform is not smooth.5461What should i do to acheave this parameters?
code:

define OSC 4
;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
ADCON0 = %00000000
ADCON1 = %00000000
trisb = %11111111
trisc = %11111011
trisa = %11111111
TMR2 = 16
PR2 = 15 ;set for 16Khz HPWM
CCP1CON.3 = 1 ' set to pwm mode
CCP1CON.2 = 1
T2CON.2=1
T2CON.0=1
STEPCOUNT var byte
stepcount = 32
; Set sine "table" in an array
sineval var byte[32]
sineval[1] = 128
sineval[2] = 148
sineval[3] = 167
sineval[4] = 185
sineval[5] = 200
sineval[6] = 213
sineval[7] = 222
sineval[8] = 228
sineval[9] = 230
sineval[10] = 228
sineval[11] = 222
sineval[12] = 213
sineval[13] = 200
sineval[14] = 185
sineval[15] = 167
sineval[16] = 148
sineval[17] = 128
sineval[18] = 108
sineval[19] = 89
sineval[20] = 71
sineval[21] = 56
sineval[22] = 43
sineval[23] = 34
sineval[24] = 28
sineval[25] = 26
sineval[26] = 28
sineval[27] = 34
sineval[28] = 43
sineval[29] = 56
sineval[30] = 71
sineval[31] = 89
sineval[32] = 108


timerone var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
;include "ReEnterPBP-18.bas" ;not needed for ASM type interrupt service routines

ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = $31 ; Prescaler = 8, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = 65504 ;gives about 50 htz sine
Main:
pause 5
'timerone = timerone - 1 'uncomment to vary 60hz sine
if timerone = $F9FF then timerone = $FF00

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 32

@ INT_RETURN

HenrikOlsson
- 6th May 2011, 15:45
Hi,
You're still off on the array.

Sinval VAR BYTE[32]
This creates an array of 32 elements numbered 0-31 but you assign values to it starting at 1 and ending at 32 - not very good. There is no SineVal[32], when you read/write to that variable you're actually accessing the "next" RAM location, something I'm sure you don't want to do here.

You can adjust the peak value by "scaling" the value in your sine-table but really, you're not even 2% off target.

Are you using a 4MHz x-tal like the code says or are you using something else?

If I'm not mistaken a reload value of 65505 with a prescaler of 1:8 running at 4Mhz gives an interrupt frequency of 4032Hz, you have 32 "steps" to your cycle so you "should" get around 126Hz....

For accuracy it's usually better to stop the timer and then ADD the preload value to the timers current value since this will take into account the interrupt latency etc. Stop it, copy it to a WORD, add the reload value, copy it back and restart the timer.

Any specific reason you're using a TMR1 prescaler of 8? Using a lower prescaler ratio will give you better "resolution" on the interrupt frequency.

/Henrik.

bwaxing
- 7th May 2011, 11:31
hellow Henrik,
thanx for the tips, i've re-worked my sine table,also i've include the code for accuracy although i'm not sure if i've place it in a right place!
For a 4MHz xtal and TMR1 prescaler of 1 i reload the T1 with the value 64980 to get 50Hz and it's what m getting on the scope.
Also TMR2 with prescaler of 4 is loaded with 117 for the interrupt to be generated every 556us(256-(556/(4*0.25*4))
But the problem is that the waveform i'm getting on the scope is not smooth at all....5467

code:

define OSC 4

;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
STEPCOUNT var byte 'Define stepcount as byte type variable
stepcount = 36

;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION*************
ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 117
PR2 = 13 ;set for 18Khz HPWM(=36 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000110 ;enable timer2 and set timer2 prescaler value of 1:4

;****************A sine lookup table in an array********************************
sineval var byte[36]
sineval[0] = 128
sineval[1] = 148
sineval[2] = 167
sineval[3] = 185
sineval[4] = 201
sineval[5] = 215
sineval[6] = 227
sineval[7] = 235
sineval[8] = 240
sineval[9] = 242
sineval[10] = 240
sineval[11] = 235
sineval[12] = 227
sineval[13] = 215
sineval[14] = 201
sineval[15] = 185
sineval[16] = 167
sineval[17] = 148
sineval[18] = 128
sineval[19] = 108
sineval[20] = 89
sineval[21] = 71
sineval[22] = 55
sineval[23] = 41
sineval[24] = 29
sineval[25] = 21
sineval[26] = 16
sineval[27] = 14
sineval[28] = 16
sineval[29] = 21
sineval[30] = 29
sineval[31] = 41
sineval[32] = 55
sineval[33] = 71
sineval[34] = 89
sineval[35] = 108

timerone var word

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

;********Define INT_Handler as ISR**********************************************
ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = %000001 ; Prescaler = 1, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = 64980 ;gives about 50 hz sine
Main:
pause 5

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

'accuracy thing
TimerShadow VAR WORD
T1CON.0 = 0 'Stop TMR1
TimerShadow.HighByte = TMR1H
TimerShadow.LowByte = TMR1L
TimerShadow = TimerShadow + Timerone
TMR1H = TimerShadow.HighByte
TMR1L = TimerShadow.LowByte
T1CON.0 = 1 'Restart TMR1
sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 36
@ INT_RETURN


where i'm wrong in the code? are the calculations above correct?

ScaleRobotics
- 7th May 2011, 15:52
What are you using for a filter? You should have at least half of the below example to smooth out the signal. Also, it will never look too good on simulation. Might look better on actual hardware. Might be some issues with running it at 4 mhz. Is there a reason you don't want 20 mhz? Even AN655 's example showed 20 mhz.



; Filter Diagram
;
; 2.7k 2.7k
; RC2 ___/\ /\ /\______/\ /\ /\________ Analog Output
; \/ \/ | \/ \/ |
; | |
; ----- 0.1uF ----- 0.1uF
; ----- -----
; | |
; GND GND
;
;

bwaxing
- 7th May 2011, 16:15
the 877 pic on the board i'm using have 4Mhz clock, and i'm using the same filter as above.are the calculations above correct?

HenrikOlsson
- 7th May 2011, 16:16
Hi,
Several things.....
TMR2 is the timer used for the PWM generation. The fact that you initially load it with 117 doesn't matter for either the PWM frequency or your interrupt frequency since you're using TMR1 to generate the interrupts.

You have the prescaler for TMR2 set to 1:4 and PR2 set to 13 which indeed gives you ~18kHz PWM frequency but it'll only give you a give you 56 discrete dutycycles. Ie. the maximum value you can put in the dutycycle register is 56. The highest value in your sine table is 242 which you then shift right one time bofore putting in the CCP1L, so you're trying to put 121 in there when 56 is max.

Changing the prescaler to 1:1 and putting 55 in PR2 gives you the same PWM frequency but allows dutycycle values of 0-222.

TMR1 is now setup with a prescaler of 1:1 and you reload it with 64980 making it interrupt every 65536-64980=556us or at a frequency of 1798Hz, there's now 36 steps to your "cycle" so 1798/36=49.96Hz so it seems to be correct. I don't think you should expect to be able to run much faster than that at 4Mhz, the DT-ints takes quite afew cycles to save and restore all the system variables on each interrupt so you won't have much time left.

The "accuracy thing" needs to be performed on each reload or it won't have much effect. It should be in your ISR instead of the reload code you have there now.

/Henrik.

ScaleRobotics
- 7th May 2011, 16:42
Hi Henrik! As always, great post!
I've done some work with DT_INTS, and in ASM mode, they are fairly fast, as they only copy a few registers, vs the PBP type, which copies then restores about 70 registers with each interrupt. So I don't understand your warning about going above 4 Mhz? I've run it at 40 Mhz on a different chip and it worked pretty well using ASM type DT_INTS.

HenrikOlsson
- 7th May 2011, 16:56
Hi,
I missed the fact that the interrupt was declared as ASM. In that case, as you say, there's not that much overhead but it's also risky business since the actual handler IS written in PBP - if you don't know what you're doing here you're likely to run into trouble.

And, with the above in mind, perhaps adding the "extra" reload code for accuracy isn't a good idea (and not needed since there's much less overhead) since it might use some PBP system variables and then the whole thing is a mess.

I wasn't trying to say that it couldn't run at a higher oscillator speed than 4Mhz. I was trying to say that I don't think it'll be able to interrupt much faster when running AT 4Mhz, in fact that IS what I said ;-) But that was before you enlightned me of the fact that he has the ISR declared as ASM.

bwaxing,
You do realise the difference of declaring the interrupt as type ASM as oppesed to type PBP and what impact it might have on your code if you declare it as ASM but write the handler in PBP?

/Henrik.

bwaxing
- 7th May 2011, 17:15
Hi,
Several things.....
TMR2 is the timer used for the PWM generation. The fact that you initially load it with 117 doesn't matter for either the PWM frequency or your interrupt frequency since you're using TMR1 to generate the interrupts.

You have the prescaler for TMR2 set to 1:4 and PR2 set to 13 which indeed gives you ~18kHz PWM frequency but it'll only give you a give you 56 discrete dutycycles. Ie. the maximum value you can put in the dutycycle register is 56. The highest value in your sine table is 242 which you then shift right one time bofore putting in the CCP1L, so you're trying to put 121 in there when 56 is max.

Changing the prescaler to 1:1 and putting 55 in PR2 gives you the same PWM frequency but allows dutycycle values of 0-222.

TMR1 is now setup with a prescaler of 1:1 and you reload it with 64980 making it interrupt every 65536-64980=556us or at a frequency of 1798Hz, there's now 36 steps to your "cycle" so 1798/36=49.96Hz so it seems to be correct. I don't think you should expect to be able to run much faster than that at 4Mhz, the DT-ints takes quite afew cycles to save and restore all the system variables on each interrupt so you won't have much time left.

The "accuracy thing" needs to be performed on each reload or it won't have much effect. It should be in your ISR instead of the reload code you have there now.

/Henrik.
i've the changes in the code as you suggested above,but the waveform is still not smooth....5469



define OSC 4

;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
STEPCOUNT var byte 'Define stepcount as byte type variable
stepcount = 36

;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION*************
ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 117
PR2 = 55 ;set for 18Khz HPWM(=36 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000100 ;enable timer2 and set timer2 prescaler value of 1:1

;****************A sine lookup table in an array********************************
sineval var byte[36]
sineval[0] = 128
sineval[1] = 148
sineval[2] = 167
sineval[3] = 185
sineval[4] = 201
sineval[5] = 215
sineval[6] = 227
sineval[7] = 235
sineval[8] = 240
sineval[9] = 242
sineval[10] = 240
sineval[11] = 235
sineval[12] = 227
sineval[13] = 215
sineval[14] = 201
sineval[15] = 185
sineval[16] = 167
sineval[17] = 148
sineval[18] = 128
sineval[19] = 108
sineval[20] = 89
sineval[21] = 71
sineval[22] = 55
sineval[23] = 41
sineval[24] = 29
sineval[25] = 21
sineval[26] = 16
sineval[27] = 14
sineval[28] = 16
sineval[29] = 21
sineval[30] = 29
sineval[31] = 41
sineval[32] = 55
sineval[33] = 71
sineval[34] = 89
sineval[35] = 108

timerone var word
TimerShadow VAR WORD
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

;********Define INT_Handler as ISR**********************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = %000001 ; Prescaler = 1, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = 64980 ;gives about 50 hz sine
Main:
pause 5

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------


sine:
'accuracy thing
T1CON.0 = 0 'Stop TMR1
TimerShadow.HighByte = TMR1H
TimerShadow.LowByte = TMR1L
TimerShadow = TimerShadow + Timerone
TMR1H = TimerShadow.HighByte
TMR1L = TimerShadow.LowByte
T1CON.0 = 1 'Restart TMR1

TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 36

@ INT_RETURN

ScaleRobotics
- 7th May 2011, 18:02
One small thing I notice is that your:



TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
stepcount = stepcount -1
if stepcount = 0 then stepcount = 36


will read the value of stepcount 36 (doesn't exist), and never get to read stepcount 0.

I don't think this is the dramatic fix you are looking for, but maybe it's one small step forward.



TMR1L = timerone.byte0
TMR1H = timerone.byte1
CCPR1L = sineval[STEPCOUNT]>>1
if stepcount = 0 then stepcount = 36
stepcount = stepcount -1

HenrikOlsson
- 7th May 2011, 18:30
Hi,
You still don't have the reload thing correct. The way you currently have it you are first reloading the timer with the calculated value (for accuracy) then you reload it again with the default value overwriting the "correct", calculated value. However, since the overhead is much less then I initially thought you might not need this "accuracy thing". And because it might also mess up the interrupt system due the ASM/PBP type interrupt I suggest you remove it and go back to the way you had it intitially. It's also not the cause of the distroted waveform.

Something that's more likely the cause of that is the fact that you load the dutycycle value into the top 8 bits of the dutycycle register when you really should load it to the low 8 bits. CCP1L are the 8 high bits and CCP1CON.5 and CCP1CON.4 are the two least significant bits. You are currently putting the (highest) value 121 into CCP1L which, in reallity, looks as 484 to the PWM module. But with the current PWM frequency the PWM module can't "resolve" to that kind of resolution.

As a test, scale down you'r sinetable so that the highest value is around 200. Then use this in the interrupt:

Temp = SineVal[StepCount] 'Don't forget to declare Temp as BYTE.
CCP1CON.4 = Temp.0 'Bit 0
CCP1CON.5 = Temp.1 'Bit 1
CCP1L = Temp >> 2 'Bit 2-7

/Henrik.

PS. Please don't quote the previous message all the time. There's no need to have a copy of it right after the original. If you're responding to specific questions or comment in the message quote those line only.

Ioannis
- 8th May 2011, 15:42
I have made a little house keeping on the thead and deleted all the un-necessary quotes and left only the necessary. The replies were following the answers so it it was really obvious.

As Henrik stated quote only when absolute necessary. It makes reading the thread more comfortable and easy to follow. Saves resources too!

Ioannis

bwaxing
- 9th May 2011, 15:32
hellow,

thanx for the useful comments and suggestions,i learn a lot from them...

Henrik and Scalerobotics,
i've changed the code and include this Code:



Temp = SineVal[StepCount]
CCP1CON.4 = Temp.0 'Bit 0
CCP1CON.5 = Temp.1 'Bit 1
CCPR1L = Temp >> 2 'Bit 2-7
and i'm getting a smooth signal for 20Mhz Osc but not for 4MHz,tried to scale the sine table but it didnt work...but for 20Mhz Osc things looks fine...5473
i'm not sure if it is possible to get a smooth spwm signal with a 4Mhz osc as i've tried to modified my code as suggested above but the waveform is still not smooth.....:confused:

ScaleRobotics
- 9th May 2011, 15:57
Not sure, but you might try the code on real hardware with a scope and see how it looks. I have noticed that simulations of this type don't work out too well. General wave form maybe, but I wouldn't trust it much more than that for this application. Looks like good improvement though!

bwaxing
- 10th May 2011, 13:52
hi,
i've noted that my code produce inverted sine waveform and it is not the one i intend to produce,here is my complete code:


define OSC 20

;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
STEPCOUNT var byte 'Define stepcount as byte type variable
stepcount = 0

;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION*************
ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 16
PR2 = 78 ;set for 16Khz HPWM(=32 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000100 ;enable timer2 and set timer2 prescaler value of 1:1

;****************A sine lookup table in an array********************************
sineval var byte[32]
sineval[0] = 148
sineval[1] = 167
sineval[2] = 185
sineval[3] = 200
sineval[4] = 210
sineval[5] = 222
sineval[6] = 228
sineval[7] = 230
sineval[8] = 228
sineval[9] = 222
sineval[10] = 212
sineval[11] = 200
sineval[12] = 185
sineval[13] = 167
sineval[14] = 148
sineval[15] = 128
sineval[16] = 108
sineval[17] = 89
sineval[18] = 71
sineval[19] = 56
sineval[20] = 43
sineval[21] = 34
sineval[22] = 28
sineval[23] = 26
sineval[24] = 28
sineval[25] = 34
sineval[26] = 43
sineval[27] = 56
sineval[28] = 71
sineval[29] = 89
sineval[30] = 108
sineval[31] = 128


timerone var word
Temp VAR byte
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

;********Define INT_Handler as ISR**********************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = %000001 ; Prescaler = 1, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = 62411 ;gives about 50 hz sine
Main:
pause 5

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------


sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
Temp = SineVal[StepCount]
CCP1CON.4 = Temp.0 'Bit 0
CCP1CON.5 = Temp.1 'Bit
CCPR1L = Temp >> 2 'Bit 2-7
stepcount = stepcount +1
if stepcount = 32 then stepcount = 0
@ INT_RETURN
any idea on how to invert the wave form...?thanx in advance

HenrikOlsson
- 10th May 2011, 15:36
Previously you started at the "end" of table and decremented the "pointer" but now you've apparently changed that so it starts at 0 and increments the pointer instead.

If you want it phase shifted 180° ("inverted") then simply "reverse" your sin-table. 128, 108, 89, 71.... instead of 148, 167, 185....

bwaxing
- 9th June 2011, 11:33
hellow,

i've managed to generate SPWM signal using 4MHz xtal :),thanx to Henrik for the tip of modifying the lookup table values,this is the screen shoot taken from the actual scope.....5654

however,there are things i'm not happy with this signal...
1)i expected to see at least one complete cycle on the screen for a single screen shoot,but this is not the case,it is either positive or negative cycle!what should i do?

2)in theory,SPWM signal is obtained by comparing the triangular wave having a certain switching frequency with a sine wave of certain modulating frequency (50Hz for my case),now the HPWM frequency is 18KHz,is this the switching frequency?if not how do i know the switching frequency for this kind of generation?i want a switching frequency around 2KHz. i want to use this signal to control a single phase inverter.

here is my code:

define OSC 4

;*****************VARIABLE DECLARATION*************************************** ***
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
STEPCOUNT var byte 'Define stepcount as byte type variable
stepcount = 36

;**************SETTING THE REGISTERS WITH APPROPIATE BIT DEFINITION*************
ADCON0 = %00000000
ADCON1 = %00000000 ;all anolog output
trisb = %11111111 ;define porta as input
trisc = %11111011 ;make ccp1/portc.2 an output pin
trisa = %11111111 ;define porta as input
TMR2 = 117
PR2 = 55 ;set for 18Khz HPWM(=36 steps*10 times*50hz)
CCP1CON = %000001100 ;set to pwm mode
T2CON=%00000100 ;enable timer2 and set timer2 prescaler value of 1:1

;****************A sine lookup table in an array********************************
sineval var byte[36]
sineval[0] = 115
sineval[1] = 102
sineval[2] = 90
sineval[3] = 79
sineval[4] = 70
sineval[5] = 62
sineval[6] = 57
sineval[7] = 53
sineval[8] = 52
sineval[9] = 53
sineval[10] = 57
sineval[11] = 62
sineval[12] = 70
sineval[13] = 74
sineval[14] = 90
sineval[15] = 102
sineval[16] = 115
sineval[17] = 128
sineval[18] = 141
sineval[19] = 154
sineval[20] = 166
sineval[21] = 177
sineval[22] = 186
sineval[23] = 194
sineval[24] = 199
sineval[25] = 203
sineval[26] = 204
sineval[27] = 203
sineval[28] = 199
sineval[29] = 194
sineval[30] = 186
sineval[31] = 177
sineval[32] = 166
sineval[33] = 154
sineval[34] = 141
sineval[35] = 128

timerone var word
Temp VAR byte
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System

;********Define INT_Handler as ISR**********************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = %000001 ; Prescaler = 1, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts
timerone = 64980 ;gives about 50 hz sine
Main:
pause 5

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------


sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1
Temp = SineVal[StepCount]
CCP1CON.4 = Temp.0 'Bit 0
CCP1CON.5 = Temp.1 'Bit 1
CCPR1L = Temp >> 2 'Bit 2-7
if stepcount = 0 then stepcount = 36
stepcount = stepcount -1


@ INT_RETURN

HenrikOlsson
- 9th June 2011, 17:10
Hi,

1)i expected to see at least one complete cycle on the screen for a single screen shoot,but this is not the case,it is either positive or negative cycle!what should i do?
I haven't checked your code but going by the comments you expect a 50Hz "sinewave", a full period at 50Hz is 20ms but your scope is set to 200us/div, there's 10 divisions so you're only displaying 2ms on the screen. I see a 10:1 note there but does that apply to the horizontal sweep?

I don't understand the part with the triangular wave being compared with a sine etc but the switching frewuency IS the PWM frequency, or 18kHz in this case. If you want 2kHz you need to reconfigure the PWM module to output 2kHz which might also require adjusting the sine-table depending on how the numbers play out.

sangaboy
- 29th December 2011, 18:37
I see you help bwax to susscced his project, can you help me an idea of how to create sinelookuptable thankx

HenrikOlsson
- 29th December 2011, 20:21
That has been discussed in this very thread... Easiest is probably to use a spreadsheet program like Excel.

sangaboy
- 30th December 2011, 00:48
Thankx HenrikOlsson but I 'm still have I problem which formular should I use to get the value ,cause I want to generate three phase SPWM

Russ Kincaid
- 30th December 2011, 03:42
Check into Don Lancaster's Magic Sinewaves here: http://www.tinaja.com/
I did it with a basic stamp BS1 several years ago when I was a newby, it is quite simple and works great.

HenrikOlsson
- 30th December 2011, 09:22
Hi,
Attached is an Excel spreadsheet showing an examle of a 72 steps/cycle SIN table with an 8bit dutycycle. You can modify it for any number of steps and resolution you see fit or you may want to create one half cycle and then have your code invert it for the second half and so on - it's up to you.

To get three phases there's no need to have three tables, you use three pointers 120° appart indexing the same table. So, with the table in the attached .xls you start at steps 0, 24 and 48 respectively.

/Henrik.

EDIT: Crap, can't attach the .xls here. Send me a PM with your email adress and I'll send it to you.

mackrackit
- 30th December 2011, 09:54
EDIT: Crap, can't attach the .xls here. Send me a PM with your email adress and I'll send it to you.
Add ".txt" to the extension...

HenrikOlsson
- 30th December 2011, 11:05
Ahh, OK, should've thought about that.
So, here it is - remove the .txt extenstion and open with Excel or compatible.

/Henrik.

sangaboy
- 8th January 2012, 06:02
Hi ! demon
I want to generator 3 Phase spwm signal for my final year project but I, m started by understanding single phase SPWM by reading the example from
Microchip appliction notes for sine wave with the 16F series chip..http://ww1.microchip.com/downloads/en/AppNotes/00655a.pdf together with the examples given in http://www.picbasic.co.uk/forum/content.php?r=229-Sine-wave-using-DT- interrupts and http://www.picbasic.co.uk/forum/showthread.php?t=14359.

there are number of things which i've not understand from these readings and i'm asking for help from anyone who can help me to understand.these things are:
1)which formular used to generate a lookup table for the sine waveforms
3)what is the purpose of this piece of code and how to get this values from example of http://www.picbasic.co.uk/forum/cont...-DT-interru and
TMR2 = 117
PR2 = 63

TMR1L = 255
TMR1H = 254

sangaboy
- 11th January 2012, 14:42
Thankx again HenrikOlsson here are some things which I dont understand I ask for the help from any one
(1) ask for the help again which formula should I use to generate this sine look up table I need some detail on it thankx.

(2) and how this portion of code work , what is function, and how to get values of TMR1L AND TMR1H
ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = 000001 ; Prescaler = 8, TMR1ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts

sangaboy
- 11th January 2012, 14:51
Ahh, OK, should've thought about that.
So, here it is - remove the .txt extenstion and open with Excel or compatible.

/Henrik.

thankx HenrikOlsson when I download your Excel fileI didn't able to open it please can you help me how to take it so I can open it. thankx

HenrikOlsson
- 11th January 2012, 15:48
Hello sangaboy,
1) Download the file then rename it SIN-table.xls (or whatever ending with .xls) then open it with EXCEL 2003 - or compatible software. I just tried that here and it works fine. If you don't have Excel 2003 perhaps you can find a free viewer or converter online.

2) The first code snippet you posted is a setup section of DT-Ints which are a set of files making interrupts with PBP a whole lot easier. The second code snippet sets up TMR1 to operate in a specific way and then preloads it with 65534 (which seems a bit strange) but that's what you get when you just copy code. You really need to start a bit further back here. Before taking on a project a like a 3-phase inverter you need to understand the basics of PIC and PBP - at least. How the timers work, how interrupts work and so on.


Read up on the DT-Ints routines, there are several threads on this forum. Read up on how TMR1 operates, there's a lot of info in the datasheet and a bit of searching here will give a lot, I mean a LOT, of usefull information and examples. Start small otherwise you'll never learn how it works.

If you get stuck ask specific questions regarding the particular task at hand and tell us what the actual problem is and what you've tried, post the code and so on.

I really don't want to sound like a smart-ass but if you can't figure out the formula to create a SIN-lookup table then designing and programming a 3-phase inverter drive is going to quite a challange.

sangaboy
- 14th January 2012, 05:30
Hii! to all
I read DT-Ints routines from ttp://darreltaylor.com/DT_INTS-14/order.html here are some problems I faced any one can help me.
(1)the difference between PBP AND ASM interrupt handler is not clear to me.
(2) what the effects of ResetFlag on this code definition.

INT_LIST macro ; IntSource, Label, Type, ResetFlag?

Thankx

HenrikOlsson
- 14th January 2012, 07:52
Hi,

1) Internally PBP works with a bunch of system variables in RAM. These are used to store intermediate results when doinf calculations and comparisons, loop counters etc etc. When you define the type of handler as PBP in the interrupt declaration DT-Ints saves all the PBP system variables on entry of the interrupt service routine and restores them on exit. This allows the code the in interrupt handler to be written in PBP just like any normal PBP program and execute without destroying the content of the system variables for the code that was executing when the intterupt occurs. When the execution returns from the interrupt handler the system variables looks exactly as they did when the interrupt occured and the "normal" program can continue to execute.

If you define the type of handler as ASM DT-Ints does not save and restore the PBP system variables. This means that if you have code in the interrupt handler which happens to use any system variables it's very likely that you'll run into trouble. So, type PBP write the handler in PBP. Type ASM, write the handler in ASM.

The difference is that it takes time for the system to save and restor all the PBP system variables (and the take up space i RAM). No you should not declare the type as ASM and still write the handler in PBP if you don't konw and understand exactly what's happening and what system variables your code uses.


2) When an interrupt occurs the hardware in the PIC sets the interrupt flag for the particular interrupt. The ResetFlag option tells the interrupt system if IT should reset the flag after it's handled the interrupt or if it should leave it alone. Generally you set this to YES but for USART interrupt, for example, the flag is automatically cleared by the hardware when the RCReg is read so there's no need for the code to clear it as well.

sangaboy
- 17th January 2012, 00:04
Thankx HenrikOlsson
for your help .

sangaboy
- 18th January 2012, 01:51
Hi HenrikOlsson
I now I understand to gerate sine lookup table using excel sheet , thi is after working on the sheet you upload to me, The sheet contain the formular
(SIN(Ai*PI()/180)+1)/2 from what I know the portion (Ai*PI())/180)change degrees into radians. but there to thing I need to understand so that I can generate my 32 steps sine look up table for 3 SPWM.
(1) why (sine results+1)
(2) why (sine results+1) is diveded by the factor of 2
(3) why the (sine results+1)/2 are multiplied by 255 to get the scale value.

THANKX

HenrikOlsson
- 18th January 2012, 06:21
Hi,
Yes, convert from degrees which is the number in column A to radians which is what Excel wants.

1) The SIN of an angle of 0-360° varies from -1 to +1 since we're going to use the values to set a PWM dutycycle we can't have negative numbers, we can't have a dutycycle of LESS than 0. So we add 1 to get a value ranging from 0 to 2 instead of +/-1.

2) Then we divide that by 2 to get the value ranging from 0 to 1 to make the next step more logical...

3) Again, since we're going to use the final value to set the dutycycle produced by the PWM generator we can't have the value ranging from 0 to 1, we need to scale the value up to match the number of bits of resolution we have in the PWM generator. If it's 8 bits multiply by 255 to get a value ranging from 0 to 255 (0 is 0% dutycycle, 255 is 100% dutycycle). If you have 9 bits resolution multiply by 512 and so on.

/Henrik.

sougata
- 18th January 2012, 08:15
Hi,
The Standard Hardware PWM modules on the PICs are generally 10 bits CCPRxL (8 bits) plus the 2 LSBs being in the CCPxCON<5:4>. How many bits you can obtain from the PWM module is dependent on the frequency. Sometimes updating the registers could be a bit troublesome and not within a single instruction cycle. What I do personally is select a 10 bit resolution and use only the higher 8 bits. A straight loading of the CCPRxL does the job with the benefit of not hitting 100% duty cycle which is required for the bootstrap gate drivers.
For the PICs with the PowerControl PWM module (sometimes also referred to as a motor control PWM) you can get upto 14 bits of resolution with a dedicated register pairs. And generally they at least have 3 PWM units with complementary outputs / dead time / Fault Input which simplifies the design and control of 3 phase systems greatly.

My choices are the PIC18F1330 and PIC18F4431(has 4 channel sequential sampling capability like the 16bit PIC24/dsPICs).

sangaboy
- 19th January 2012, 15:41
Hi !

Thankx sougata and HenrikOlsson for your helpwhich take me into good stages

there some challenges have any one can help me
(1) My PIC is16cF877 having CCP1 and CCP2 can it able to generate three phase SPWM?. for my little knowledge I know that for single phase the duty cycle is stored into CCP1 to generate SPWM. for three phase should I have a pic of three CCP modules?.

(2) how can I improves these my small number of steps(10) cause I read page 63/281 of PIC 16F87X data sheet and microchip application note AN655 page 1/16 I saw the formular for resolution and number of steps respectively.

The maximum PWM resolution (bits) for a given PWM frequensy is given by the formular below


Resolution = log(FOSC/FWPM)/log(2) bits

I want to set my PWM frequency = 5kHZ
my FOSC = 4MHZ
which gives resolution of 10 it's ok and scale factor of 1023

but
from microchip application note AN655
PWM_Freq = (Sine_freq) • (# of steps) • 10

my sine frequency is 50Hz
PWM_Freq =5kHZ

gives me 10 steps which I think is very small to give clear SPWM.

thankx

sangaboy
- 23rd January 2012, 23:05
Hi !

Thankx sougata and HenrikOlsson for your helpwhich take me into good stages

there some challenges I have any one can help me:

(1) My PIC is16cF877 have CCP1 and CCP2 can it able to generate three phase SPWM?. for my little knowledge I know that for single phase the duty cycle is stored into CCP1 to generate SPWM. for three phase should I have a pic with three CCP modules?.

(2) how can I improves these small number of steps(10) cause I read page 63/281 of PIC 16F87X data sheet and microchip application note AN655 page 1/16 I .http://ww1.microchip.com/downloads/e...tes/00655a.pdf I read the formular for bits resolution and number of steps respectively.

The maximum PWM resolution (bits) for a given PWM frequensy is given by the formular below


Resolution = log(FOSC/FWPM)/log(2) bits

I want to set my PWM frequency = 5kHZ
my FOSC = 4MHZ
which gives resolution of 10 it's ok and scale factor of 1023

but
from microchip application note AN655
PWM_Freq = (Sine_freq) • (# of steps) • 10

my sine frequency is 50Hz
PWM_Freq =5kHZ

gives me 10 steps which I think is very small to give clear SPWM .

thankx

HenrikOlsson
- 24th January 2012, 16:21
Hi,
What exactly do you mean with SPWM? What does the S mean?

If you're generating the PWM signal with CCP-module you'll need 3 CCP-modules to generate three individual PWM signals. As have already been suggested ditch the '877 and take a look at the 18F2431/4431 which is designed for motor control providing deadtime control and dedicated hardware fault inputs to disable the PWM signals - and more.

If you need to stick to a 16 series PIC then use the parametric search tool at Microchips website to look up a PIC with three CCP-modules, perhaps the 16F777.

I just looked briefly at the app-note you reference and they seem to be using a low-pass filter to get a "true" sine-wave output, to do that they calculated/estimated that at least 10PWM cycles is needed to bring the output voltage to the desired value.

How many "steps" do you want, per period? Let's say you have a lookup table of 32 'steps'. Ie it takes 32 "updates" to create one full cycle of the sinewave, so at 50Hz you need to change the PWM dutycycle 50*32=1600 times per second, which means that you'll get atleast three full PWM cycles for each "step" with a 5kHz PWM frequency, I think that'll work.

/Henrik.

sangaboy
- 25th January 2012, 06:13
Hi !


SPWM stands for Sinusoidal Pulse With Modulation.These signals will be used to control Three phase inverter.

thankx

Dave
- 25th January 2012, 11:50
I'm afraid the letter sequence SPWM actually was derived by Darrel for his contribution of Software Pulse Width Modulation.

HenrikOlsson
- 25th January 2012, 15:25
That's what I thought but figured it couldn't be since we're talking about CCP-modules etc. Doesn't matter, now I know what the OP means although I've never heard the term before.

/Henrik.

spcw1234
- 25th January 2012, 16:06
Perhaps this thread will be of use to you.

http://www.picbasic.co.uk/forum/showthread.php?t=1846

sangaboy
- 27th January 2012, 08:06
Hi
I download the pic16f777 datasheet from microchip website I go through it I found it does not much differ from that of pic16f7877 so it easy for me to shift from the PIC16877 to 16F777 which has three ccp modules for SPWM generation.

thanx

Sorry for delay in reply, now I 'm in seventh semister exam of my BSc in electrical eng.

sangaboy
- 10th February 2012, 18:23
hi to all
I try to simulator my code on IMPLAB simulator but I have not yet sussceed til now so I decide to simulator with pic 16F877 which is found in ISIS but when it comes to real environment(actual implementation) I 'm going to use pic16f777 , which I 'm waiting for it to come.

Then
can any one help me !
how to take my waveform from digital oscilloscope in ISIS cauz I want to uploaad in this forum ,I try to print but the file does not contain any waveform. I have some problem on my ouputs.
thankx.

sangaboy
- 12th February 2012, 12:42
Hi!

I manage to compile and modify the example from that link www.picbasic.co.uk/forum/cont...-DT-interrupts, for pic 16877. Because the pic I want to use for three phase spwm signal is (16f777) which has 3 CCP module and I' m waiting for it to come the problem it is not includeded in ISIS simulator that is why I used pic 168777 having 2 CCP module for simulation and is present in ISIS and my college lab. I belive if I manage to generate two phase spwm it became eaasy for 3 phase spmw.

here is the code and attachement of my output from ISIS and mysinelooktable and
define OSC 4

STEPCOUNT var byte
STEPCOUNT1 var byte
STEPCOUNT = 0 'pointer for phase one in sinearray
STEPCOUNT1 = 0 'pointer for phase two in sine array
ADCON0 = %00000000
ADCON1 = %00000000

TRISB = %11111111
TRISC = %11111001 'PMW output for CCP1 AND CCP2
TRISA = %11111111
TMR2 = 117
PR2 = 55 'set for 18Khz HPWM
CCP1CON = %00001100 'set CCP1 for PWM OPERATION
CCP2CON = %00001100 'set CCP2 for PWM OPERATION
T2CON = %00000100 'TIMER2ON and prescale of 1:1

sineval var byte[36]
sineval[0] = 128
sineval[1] = 150
sineval[2] = 171
sineval[3] = 191
sineval[4] = 209
sineval[5] = 225
sineval[6] = 238
sineval[7] = 247
sineval[8] = 253
sineval[9] = 255
sineval[10] = 253
sineval[11] = 247
sineval[12] = 238
sineval[13] = 225
sineval[14] = 209
sineval[15] = 191
sineval[16] = 171
sineval[17] = 150
sineval[18] = 128
sineval[19] = 105
sineval[20] = 84
sineval[21] = 64
sineval[22] = 46
sineval[23] = 30
sineval[24] = 17
sineval[25] = 8
sineval[26] = 2
sineval[27] = 0
sineval[28] = 2
sineval[29] = 8
sineval[30] = 17
sineval[31] = 30
sineval[32] = 46
sineval[33] = 64
sineval[34] = 84
sineval[35] = 105

timerone var word
Temp var byte
Temp1 var byte

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System emp


ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = 000001 ; Prescaler = 1;1, TMR1 ON
TMR1L = 255
TMR1H = 254
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts

timerone = 64980 ;gives about 50 htz sine
Main:
PAUSE 5

GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
TMR1L = timerone.byte0
TMR1H = timerone.byte1

TeMP = sineval[STEPCOUNT]
CCP1CON.4 = Temp.0 ' bit 0
CCP1CON.5 = Temp.1 ' bit 1
CCPR1L = Temp >>2 'Bit 2-7

TeMP1 = sineval[STEPCOUNT1]
CCP2CON.4 = Temp.0 ' bit 0
CCP2CON.5 = Temp.1 ' bit 1
CCPR2L = Temp >>2 'Bit 2-7
if stepcount = 36 then stepcount =0
if stepcount1 = 24 then stepcount1 =0
stepcount = stepcount +1
stepcount = stepcount1 +1

@ INT_RETURN



any one can help me

HenrikOlsson
- 12th February 2012, 13:04
Hi,

First of all, please don't post the same question in several threads. It makes it really hard for people to help you then when someone answers in one thread and someone else in the other. It gets impossible to get the whole picture then.

Second, when posting code put it in between code-tags so it shows up in a scrollable window instead of just cut and paste it.

Right, your code then...
1)

TMR1L = 255
TMR1H = 254

This doesn't make much sense, all it does is cause an interrupt after a single cycle. The timer reloading is done in the ISR so just remove those two lines.

2) It's best to stop the timer before reloading it as it can otherwise overflow between writing to the low and high byte. Even better is to stop it and then ADD the calculated reload value to the timer register as this will account for the otherwsie lost time that occurs when entering the ISR.

3) You have two index variables pointing into the the array (StepCount and StepCount1). To get the phase shift you need to start at different places in the SIN-table, if you don't the phases will be "in sync".

4)

if stepcount = 36 then stepcount =0
if stepcount1 = 24 then stepcount1 =0
stepcount = stepcount +1
stepcount = stepcount1 +1


Here you have three problems.
4.1) There are 36 entries the table, numbered 0-35. Because you are incrementing your pointers AFTER you check if it's 36 you're actually trying to ACCESS sinval[36] which isn't that good since it doesn't exist. Swap that around so that you increment the pointer FIRST then check if its beyond the boundry of the array.

4.2) You reset stepcount1 to 0 when it reach 24 so you won't get a full cycle out of it. It needs to get to 36 and then be reset but again, you need to "start" it at 12 instead of 0.

4.3) If you look at the last two lines of your code above you never actually increment StepCount1.

Start by fixing that and see what happens. May I also suggest you toggle an output or something in the ISR to verify that you've got the correct interrupt frequency.

/Henrik.

sangaboy
- 15th February 2012, 12:47
Hi HenrikOlsson
thankx for your coments and Idea you gave me on the code I posted last time which make my output to be some how clear. But is not quiet clear. here are some challenges I faced again

(1) The ouput does not apper smoth. I tttach the output as seen from ISIS and code.


STEPCOUNT var byte
STEPCOUNT1 var byte

STEPCOUNT = 0 'pointer for phase one in sinearray
STEPCOUNT1 = 12 'pointer for phase two in sine array
ADCON0 = %00000000
ADCON1 = %00000000

TRISB = %11111001
TRISC = %11111001 'PMW output for CCP1 AND CCP2
TRISA = %11111111
TMR2 = 117
PR2 = 55 'set for 18Khz HPWM
CCP1CON = %00001100 'set CCP1 for PWM OPERATION
CCP2CON = %00001100 'set CCP2 for PWM OPERATION
T2CON = %00000100 'TIMER2ON and prescale of 1:1

sineval var byte[36]
sineval[0] = 128
sineval[1] = 150
sineval[2] = 171
sineval[3] = 191
sineval[4] = 209
sineval[5] = 225
sineval[6] = 238
sineval[7] = 247
sineval[8] = 253
sineval[9] = 255
sineval[10] = 253
sineval[11] = 247
sineval[12] = 238
sineval[13] = 225
sineval[14] = 209
sineval[15] = 191
sineval[16] = 171
sineval[17] = 150
sineval[18] = 128
sineval[19] = 105
sineval[20] = 84
sineval[21] = 64
sineval[22] = 46
sineval[23] = 30
sineval[24] = 17
sineval[25] = 8
sineval[26] = 2
sineval[27] = 0
sineval[28] = 2
sineval[29] = 8
sineval[30] = 17
sineval[31] = 30
sineval[32] = 46
sineval[33] = 64
sineval[34] = 84
sineval[35] = 105

timerone var word
Temp var byte
Temp1 var byte
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System emp


ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = 000001 ; Prescaler = 1;1, TMR1 ON
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts


timerone = 64980 ;gives about 50 htz sine
Main:

PAUSE 5
GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
T1CON = 000000 'stop the timer

TMR1L = timerone.byte0 'reload the timer
TMR1H = timerone.byte1


T1CON = 000001 'start the timer

TeMP = sineval[STEPCOUNT]
CCP1CON.4 = Temp.0 ' bit 0
CCP1CON.5 = Temp.1 ' bit 1
CCPR1L = Temp >>2 'Bit 2-7

TeMP1 = sineval[STEPCOUNT1]
CCP2CON.4 = Temp.0 ' bit 0
CCP2CON.5 = Temp.1 ' bit 1
CCPR2L = Temp >>2 'Bit 2-7
stepcount = stepcount +1
stepcount1 = stepcount1 +1
if stepcount = 36 then stepcount =0
if stepcount1 = 36 then stepcount1 =12

@ INT_RETURN





(2) I try to write a code so that I can measure if the interrupt frequence is 1800hz.
When I start learning timer in the previous days I passed I cross the link http://www.microcontrollerboard.com/pic-timer1-tutorial.html there is formural for calcalating a numeric value(count) to be placed to obtain the desired output frequency.
count=fclk/(4*prescale*(65536-TMR1)*fout

where for me
fout=1800hz, prescale 1, TMRI=64980 and fclk=4MHz

gives count = 1 ohh! here I'm confusing how should I proceed since is very small count I cant use it.

can you help which count should I use so I can measure my interrupt frequecy
thankx

sangaboy
- 17th February 2012, 17:22
Hi to all

I am here again I am still working on the code I posted last 2 days. It try to work on the code but I still get the same output, as I Attach on the two days ago, when I try to put LED on the interrupt service routine and to see if the frequency is clear this became another problem to me. The problem arising are

(1) The ouput does not apper smoth and which condition should I put to show I get the desired frequency . I atttach again the output as seen from ISIS and the code use to generate that output.


DEFINE OSC 4

STEPCOUNT var byte
STEPCOUNT1 var byte

STEPCOUNT = 0 'pointer for phase one in sinearray
STEPCOUNT1 = 12 'pointer for phase two in sine array
ADCON0 = %00000000
ADCON1 = %00000000

TRISB = %11111001
TRISC = %11111001 'PMW output for CCP1 AND CCP2
TRISA = %11111111
TMR2 = 117
PR2 = 55 'set for 18Khz HPWM
CCP1CON = %00001100 'set CCP1 for PWM OPERATION
CCP2CON = %00001100 'set CCP2 for PWM OPERATION
T2CON = %00000100 'TIMER2ON and prescale of 1:1

sineval var byte[36]
sineval[0] = 128
sineval[1] = 150
sineval[2] = 171
sineval[3] = 191
sineval[4] = 209
sineval[5] = 225
sineval[6] = 238
sineval[7] = 247
sineval[8] = 253
sineval[9] = 255
sineval[10] = 253
sineval[11] = 247
sineval[12] = 238
sineval[13] = 225
sineval[14] = 209
sineval[15] = 191
sineval[16] = 171
sineval[17] = 150
sineval[18] = 128
sineval[19] = 105
sineval[20] = 84
sineval[21] = 64
sineval[22] = 46
sineval[23] = 30
sineval[24] = 17
sineval[25] = 8
sineval[26] = 2
sineval[27] = 0
sineval[28] = 2
sineval[29] = 8
sineval[30] = 17
sineval[31] = 30
sineval[32] = 46
sineval[33] = 64
sineval[34] = 84
sineval[35] = 105

timerone var word
Temp var byte
Temp1 var byte
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System emp


ASM

INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _sine, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

T1CON = 000001 ; Prescaler = 1;1, TMR1 ON
@ INT_ENABLE TMR1_INT ; Enable Timer 1 Interrupts


timerone = 64980 ; vakue loaded to TMR1 to gives about 50 htz sine
Main:

PAUSE 5
GOTO Main

'---[TMR1_INT - interrupt handler]------------------------------------------

sine:
T1CON = 000000 'stop the timer

TMR1L = timerone.byte0 'reload the timer
TMR1H = timerone.byte1


T1CON = 000001 'start the timer

TeMP = sineval[STEPCOUNT]
CCP1CON.4 = Temp.0 ' bit 0
CCP1CON.5 = Temp.1 ' bit 1
CCPR1L = Temp >>2 'Bit 2-7

TeMP1 = sineval[STEPCOUNT1]
CCP2CON.4 = Temp.0 ' bit 0
CCP2CON.5 = Temp.1 ' bit 1
CCPR2L = Temp >>2 'Bit 2-7
stepcount = stepcount +1
stepcount1 = stepcount1 +1
if stepcount = 36 then stepcount =0
if stepcount1 = 36 then stepcount1 =12

@ INT_RETURN


When I start learning timer in the days ago I passed across the link http://www.microcontrollerboard.com/...-tutorial.html there is formural for calcalating a numeric value(count) to be placed to obtain the desired output frequency.

count=fclk/(4*prescale*(65536-TMR1)*fout this formular gives me a small count which I can not use to test the frequency condition.

thanks

sangaboy
- 21st February 2012, 12:00
Hi to all
can any one help me how to write 10 bit resolution to PWM MODULE because I read pic datasheets and Ds33023 refference manual I see 10bit resolution is applicable for low frequencies.
thankx.

sangaboy
- 25th February 2012, 18:33
Hi to every one
I have worked and modify the code posted by ScaleRobotics and I manage to compile it for the PIC 16F877 and get 2 phase although my output was not very good. my aim is to generate 5kHZ SPWM so that when filtered will give sine waves(50hz). I havebeen reading different application manual and PIC16877 datashet for almost two days but I 'm still in darkness the problem comes for that frequency my duty cycle will have 10bit resolution. here are the questions.

(1) I Try to write the code to FOR 10 bit resolution to PWM module I dont think if is correct.


TeMP = sineval[STEPCOUNT]
CCP1CON.4 = Temp.0 ' bit 0
CCP1CON.5 = Temp.1 ' bit 1
CCPR1L = Temp.Byte0 >>2 '


(2)when I do my calculation
from microchip application note pwm_frequency=50hz*step*10
which gives me very low step about 10step which is very low when I try to use it my output become very distorted and only CCP1 gives output while ccp2 dont gives any output.

any one can help me how to get 5KHZ 36 step and is it nessary to modify my lookup table for 10bit resolution thankx