View previous topic :: View next topic |
Author |
Message |
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Fri Jul 27, 2012 10:11 pm Post subject: Sine wave Variable amplitude |
|
|
Hi To all forum members.
I have back in this forum after a very long time. I have the following code for generating sine wave on the mega8 every thing runs fine in Proteus but now I want to vary the amplitude from say 0-5v which will in turn vary the final amplitude from 0-220v I don't know how to dynamically change the table values to do that. The code is self explanatory.
Thanks and regards
' Program : PWM Sine Wave 50Hz inverter.bas
' Date : 05-06-12
' Processor : ATMEGA8
' Input: Internal sine wave value table
' Process : Pulse width modulation
$regfile = "m8def.dat" ' specify the used micro
$crystal = 8000000 '8000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 128 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack
$framesize = 64
' variable
Dim Half_cycle As Byte
Dim Sine_table(32) As Byte ' sine_table
Dim Index As Byte ' Positive or Negativ Half_cycle
' Config Pin
Config PINB.1= Output 'Pin OC1A - PWM1a
Config PINB.2 = Output 'Pin OC1B - PWM1b
'*************************************************
'* Halfperiod = 10 ms.
'* There are 32 pwm values in a half period 10ms/32
'* We need to change the OCR value every 10000/32 =312.5 microsec
'* Let Timer0 overflow after 312.5 us.
'* Set prescaler to 64 *
'* 1 timer step = 64/16MHz = 4 us ; 312.5/4 = 78.12
'* Preload value = 256 - 78.
'*************************************************
Config Timer0 = Timer , Prescale = 64 '64/8MHz = 8us
Enable Ovf0
On Ovf0 Timer0_ovf
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
' PWM Freq 31.25 kHz for PWM = 8 bit or PWM Freg 15.625 kHz for PWM = 9 bit
'restore Sine_dat
For Index = 0 To 31
Sine_table(index + 1) = Lookup(index , Sine_dat) ' read sine_dat
Next Index
Index = 0
Half_cycle = 0 ' positiv sine cycle
'Pwm_count = 0
Enable Timer0 ' PWM Counter
Enable Interrupts
Do
Loop ' Loop forever
End ' end program
'************************ Interrupt0 ****************************************
Timer0_ovf:
Timer0 = 255 - 39 ' preload
If Half_cycle = 0 Then ' select half cycle positiv
Pwm1a = Sine_table(index + 1) ' positive half cycle
Pwm1b = 0
Elseif Half_cycle = 1 Then
Pwm1b = Sine_table(index + 1) ' negativ sine cycle
Pwm1a = 0
End If
Incr Index ' increments Index for 1
If Index => 32 Then
Index = 0 ' reset Index to 0
If Half_cycle = 0 Then
Half_cycle = 1 ' select negativ Half Cycle
Elseif Half_cycle = 1 Then
Half_cycle = 0 ' select positiv Half Cycle
End If
End If
Return
'**************** SINE WAVE DATA baase on PWM PERIOD 255 **********************
Sine_dat:
Data 25 , 50 , 74 , 98 , 120 , 142 , 162 , 180 , 197 , 212 , 225 , 235 , 244 , 250 , 254 , 255 , 254 , 250 , 244 , 235 , 225 , 212 , 197 , 180 , 162 , 142 , 120 , 98 , 74 , 50 , 25 , 0 |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Sat Jul 28, 2012 2:46 am Post subject: |
|
|
To get a variable amplitude, just divide the value read from the lookup table by a variable you provide, before storing it:
Code: |
dim bAmplitude as byte 'define a variable
dim btemp as byte 'a temporary
For Index = 0 To 31
btemp = Lookup(index , Sine_dat) ' read sine_dat
btemp = btemp / bAmplitude 'reduce amplitude
Sine_table(index + 1) = btemp 'save value for PWM
Next Index
|
Vary the value of bAmplitude by some external means in your program. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Sat Jul 28, 2012 7:51 pm Post subject: |
|
|
Hi
Hmmm that's seems to be the right solution Thanks Adrian J but may I ask a naughty question here Now that it seems possible to vary the Amplitude but what about the feedback from the output to adjust the amplitude as I can implement it through the PI algo but is the avr have the enough guts to do that dynamically.
For now I will use an ADC and change the value by means of a pot and latter build my PI controller.
This forum has helped me a lot and has completed very serious project with the help of you people I am very much indebted to this forum and you guys.
Thanks and regards |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Sat Jul 28, 2012 11:05 pm Post subject: |
|
|
Hi
I have modified my code according to the AdrianJ advice but now I am getting only plain square waves from both the outputs. scratching my head for finding out the problem. below is my code.
Regards
' Program : PWM Sine Wave 50Hz inverter.bas
' Date : 05-06-12
' Processor : ATMEGA 8 at 8 MHz
' Input: Internal sine wave value table
' Process : Pulse width modulation
$regfile = "m8def.dat" ' specify the used micro
$crystal = 8000000 '8000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 128 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack
$framesize = 64
' variable
Dim Half_cycle As Byte
Dim Sine_table(32) As Byte ' sine_table
Dim Index As Byte
dim bAmplitude as byte 'define a variable
dim btemp as byte 'a temporary ' Positive or Negativ Half_cycle
' Config Pin
Config Pinb.1 = Output 'Pin OC1A - PWM1a
Config Pinb.2 = Output 'Pin OC1B - PWM1b
'*************************************************
'* Halfperiod = 10 ms.
'* There are 32 pwm values in a half period 10ms/32
'* We need to change the OCR value every 10000/32 =312.5 microsec
'* Let Timer0 overflow after 312.5 us.
'* Set prescaler to 64 *
'* 1 timer step = 64/8MHz = 8 us ; 312.5/8 = 39
'* Preload value = 256 - 78.
'*************************************************
Config Timer0 = Timer , Prescale = 64 '64/8MHz = 8us
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Enable Ovf0
On Ovf0 Timer0_ovf
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
' PWM Freq 31.25 kHz for PWM = 8 bit or PWM Freg 15.625 kHz for PWM = 9 bit
'restore Sine_dat
For Index = 0 To 31
btemp = Lookup(index , Sine_dat) ' read sine_dat
Btemp = Btemp / Bamplitude 'reduce amplitude
Sine_table(index + 1) = btemp 'save value for PWM
Next Index
Index = 0
Half_cycle = 0 ' positiv sine cycle
'Pwm_count = 0
Enable Timer0 ' PWM Counter
Enable Interrupts
Do
Bamplitude = Getadc(0)
Loop ' Loop forever
End ' end program
'************************ Interrupt0 ****************************************
Timer0_ovf:
Timer0 = 255 - 39 ' preload
If Half_cycle = 0 Then ' select half cycle positiv
Pwm1a = Sine_table(index + 1) ' positive half cycle
Pwm1b = 0
Elseif Half_cycle = 1 Then
Pwm1b = Sine_table(index + 1) ' negativ sine cycle
Pwm1a = 0
End If
Incr Index ' increments Index for 1
If Index => 32 Then
Index = 0 ' reset Index to 0
If Half_cycle = 0 Then
Half_cycle = 1 ' select negativ Half Cycle
Elseif Half_cycle = 1 Then
Half_cycle = 0 ' select positiv Half Cycle
End If
End If
Return
'**************** SINE WAVE DATA baase on PWM PERIOD 255 **********************
Sine_dat:
Data 25 , 50 , 74 , 98 , 120 , 142 , 162 , 180 , 197 , 212 , 225 , 235 , 244 , 250 , 254 , 255 , 254 , 250 , 244 , 235 , 225 , 212 , 197 , 180 , 162 , 142 , 120 , 98 , 74 , 50 , 25 , 0 |
|
Back to top |
|
|
jenalcom
Joined: 10 Apr 2004 Posts: 365 Location: Perth, Western Australia
|
Posted: Sun Jul 29, 2012 4:39 am Post subject: |
|
|
If you wanted to vary the output from 1% to 100% of the full scale value then I would do the following
1) read table value
2) multiply by percentage required (for example 15 = 15% of full scale output)
3) divide answer by 100
4) answer is now the number to use for bAmplitude
So, for example, step 2 of the sine table at 15% would be 50 * 15/100 = 7.5. Maximum output would be 255 * 15/100 = 38.25 and, of course, minimum output will still be 0 (0 * 15/100 = 0).
Rounding up can be done by adding 0.5 to bAmplitude and then using INT. Otherwise just use INT to round down.
Or, to simplify things, use words and do the following:
1) read value
2) wAmplitude = bAmplitude
3) multiply by percentage required (for example 15 = 15% of full scale output)
4) add 50
5) divide answer by 100
6) answer is now the number to use for bAmplitude (and is in the bottom byte of the word)
This automatically rounds the answer up. If you want to round down then leave out step 4). You can probably speed things up a bit by overlaying bAmplitude as the lower byte of wAmplitude instead of using step 2) (the upper byte should always be 0 at the beginning and end of each calculation)
I'll leave the converting to code up to you, |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Sun Jul 29, 2012 7:32 pm Post subject: |
|
|
Hi
Your calculations seems to be right but where to place my ADC routine. |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Mon Jul 30, 2012 1:00 am Post subject: |
|
|
You need to re-read and recompute the sine table each time you change the amplitude, more like:
Code: |
Enable Timer0 ' PWM Counter
Enable Interrupts
do
Bamplitude = Getadc(0) 'read new amplitude inside loop
restore Sine_dat 'get sine table
For Index = 0 To 31
btemp = Lookup(index , Sine_dat) ' read sine_dat
Btemp = Btemp / Bamplitude 'reduce amplitude
Sine_table(index + 1) = btemp 'save value for PWM
Next Index
Index = 0
Half_cycle = 0 ' positiv sine cycle
'Pwm_count = 0
Loop ' Loop forever
End ' end program
|
You still have more to do there, since you need to cope with each half-cycle. There are other, better ways to do this too, including storing the original sine table in ram once only, and modifying it by the set amplitude each time a new value is wanted. Exactly how you implement this is up to you.
Regarding jenalcoms method. That will work too, but you dont need so many multiplies and divides. There are many methods of actually computing the new amplitude. A less obvious one, but which executes a lot faster, is to use a word:
Code: |
dim wtemp as word
wtemp = lookup(index, sine_dat)
wtemp = wtemp * bamplitude 'multiply, not divide !
'that puts the result in the high byte of wtemp
Sine_table(index+1) = high(wtemp)
|
Since a multiply is done in hardware on most AVR chips, its very much faster than a divide.
For instance that would allow you to do the calculation inside the ISR, and so you could do it 'on the fly', without having to read and modify every value in the sine table every time through the loop.
Many other methods are possible.
Regarding your comments about using a control loop. I dont see how that is relevant. You know what amplitude you want, and you have direct control over that. You do not need a control loop to do that. If perhaps you were measuring the resultant amplitude in a room, and you wanted your signal to be x dB above room ambient, then you might need a control loop, but not as you have set up the problem you proposed. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Mon Jul 30, 2012 7:01 pm Post subject: |
|
|
Hi
All these solutions can be implemented but now think this way and first see the sine wave table.
Sine_dat:
Data 25 , 50 , 74 , 98 , 120 , 142 , 162 , 180 , 197 , 212 , 225 , 235 , 244 , 250 , 254 , 255 , 254 , 250 , 244 , 235 , 225 , 212 , 197 , 180 , 162 , 142 , 120 , 98 , 74 , 50 , 25 , 0
bAmplitude will vary from 0-255, what about this sitiuation when lets say the first value in the table 25 will become 25/255 = 0.098039215686274509803921568627451 will the pwm register accept this value. have you consider this situation and for every value of the table except 255/255 = 1 the middle value in the table.
regards. |
|
Back to top |
|
|
jenalcom
Joined: 10 Apr 2004 Posts: 365 Location: Perth, Western Australia
|
Posted: Tue Jul 31, 2012 4:11 am Post subject: |
|
|
You don't divide by 255 at any point - you only use what is in the high byte of wtemp.
Consider when bAmplitude is 0 or 1 then the high byte of wtemp will always be 0.
When bAmplitude is 2 then the high byte of wtemp will be 0 for approx half the table and 1 for approx half the table. In othe words wtemp varies 0 ... 50 .... 100 .... 148 .... up to .... 510 - the high byte of wtemp holds either 0 or 1
When bAmplitude is 3 then the high byte of wtemp varies 0 ... 75 .... 150 .... 222 .... up to .... 765 - the high byte of wtemp holds either 0, 1 or 2.
When bAmplitude is 255 then the high byte of wtemp varies 0 ... 6375 .... 12750 .... 18870 .... up to .... 65025 - the high byte of wtemp holds either 0 or a range of numbers from 24 to 254 (= almost the same as the original table!)
The above holds true only if you want tu use a control variable of 0 to 255. If you wanted to use a control variable of 0 to 100 (that is percentages) then there are other things you can do such as:
1) save table data to a long
2) mutiply by 5
3) multiply by bAmplitude
3) shift right 1 place (that is divide by 2)
4) read second least significant byte to get required value.
This will give a range of outputs from 0 to 249 corresponding to the sine table multiplied by the percentage required. |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Tue Jul 31, 2012 6:19 pm Post subject: |
|
|
Thanks jenalcom
I will try this and will come back with the results
Cheers
regards |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Wed Aug 01, 2012 12:06 am Post subject: |
|
|
My apologies.
I was intent on showing the method of scaling the amplitude at each point in the table, and not on the actual values produced. You need to either scale up by a constant, and then scale down by a variable, to maintain the required number in a byte, or do it the other way, as I suggested in my last post, scale up by a variable, and then scale down by a constant. Either way works.
You should note that we are only using integers here, no decimal fractions exist when you use bytes or words. You suffer a small loss in accuracy, which is usually negligible in this application, but a great gain in execution speed.
The number 25/255 = 0.098039215686274509803921568627451 would of course be truncated to 0 when used as a byte. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Wed Aug 01, 2012 9:52 pm Post subject: |
|
|
Hi
Now I have done like this bot with no promising results and getting only ecg like waveform on the output of the filter.
' Program : PWM Sine Wave 50Hz inverter.bas
' Date : 05-06-12
' Processor : ATMEGA8
' Input: Internal sine wave value table
' Process : Pulse width modulation
$regfile = "m8def.dat" ' specify the used micro
$crystal = 8000000 '8000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 128 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack
$framesize = 64
' variable
Dim Half_cycle As Byte
Dim Sine_table(32) As Byte ' sine_table
Dim Index As Byte ' Positive or Negativ Half_cycle
Dim Bamplitude As Byte 'define a variable
Dim Btemp As Byte
dim wtemp as word 'a temporary
' Config Pin
Config Pinb.1 = Output 'Pin OC1A - PWM1a
Config Pinb.2 = Output 'Pin OC1B - PWM1b
'*************************************************
'* Halfperiod = 10 ms.
'* There are 32 pwm values in a half period 10ms/32
'* We need to change the OCR value every 10000/32 =312.5 microsec
'* Let Timer0 overflow after 312.5 us.
'* Set prescaler to 64 *
'* 1 timer step = 64/16MHz = 4 us ; 312.5/4 = 78.12
'* Preload value = 256 - 78.
'*************************************************
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Config Timer0 = Timer , Prescale = 64 '64/8MHz = 8us
Enable Ovf0
On Ovf0 Timer0_ovf
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
' PWM Freq 31.25 kHz for PWM = 8 bit or PWM Freg 15.625 kHz for PWM = 9 bit
'restore Sine_dat
For Index = 0 To 31
Sine_table(index + 1) = Lookup(index , Sine_dat) ' read sine_dat
Next Index
Index = 0
Half_cycle = 0 ' positiv sine cycle
'Pwm_count = 0
Enable Timer0 ' PWM Counter
Enable Interrupts
Do
Bamplitude = Getadc(0)
wtemp = lookup(index, sine_dat)
wtemp = wtemp * bamplitude 'multiply, not divide !
'that puts the result in the high byte of wtemp
Sine_table(index + 1) = High(wtemp)
'Print "BTEMP" ; Btemp
Print "sinetable" ; Sine_table(index + 1)
Loop ' Loop forever
End ' end program
'************************ Interrupt0 ****************************************
Timer0_ovf:
Timer0 = 255 - 39 ' preload
If Half_cycle = 0 Then ' select half cycle positiv
Pwm1a = Sine_table(index + 1) ' positive half cycle
Pwm1b = 0
Elseif Half_cycle = 1 Then
Pwm1b = Sine_table(index + 1) ' negativ sine cycle
Pwm1a = 0
End If
Incr Index ' increments Index for 1
If Index => 32 Then
Index = 0 ' reset Index to 0
If Half_cycle = 0 Then
Half_cycle = 1 ' select negativ Half Cycle
Elseif Half_cycle = 1 Then
Half_cycle = 0 ' select positiv Half Cycle
End If
End If
Return
'**************** SINE WAVE DATA baase on PWM PERIOD 255 **********************
Sine_dat:
Data 25 , 50 , 74 , 98 , 120 , 142 , 162 , 180 , 197 , 212 , 225 , 235 , 244 , 250 , 254 , 255 , 254 , 250 , 244 , 235 , 225 , 212 , 197 , 180 , 162 , 142 , 120 , 98 , 74 , 50 , 25 , 0 |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Wed Aug 01, 2012 11:56 pm Post subject: |
|
|
You need to do a RESTORE each time you do a new lookup, so the index into the table is reset to the start address of sine_dat:
Code: |
Do
Bamplitude = Getadc(0)
restore 'reset lookup address
wtemp = lookup(index, sine_dat)
...
|
I would also probably set a flag in the IRQ, so that you only read the ADC and change the amplitude at the end of every cycle, or even slower.
This may not be strictly necessary, but it does avoid jitter in the ADC readings causing amplitude changes during a cycle.
Code: |
dim bADCdelay as byte 'incremented in IRQ, cleared in main loop
Do
if bADCDelay > 1 'select bigger to set more delay cycles
bADCDelay = 0 'reset delay flag
Bamplitude = Getadc(0)
restore
wtemp = lookup(index, sine_dat)
wtemp = wtemp * bamplitude 'multiply, not divide !
'that puts the result in the high byte of wtemp
Sine_table(index + 1) = High(wtemp)
'Print "BTEMP" ; Btemp
Print "sinetable" ; Sine_table(index + 1)
end if
Loop ' Loop forever
end
'************************ Interrupt0 ****************************************
Timer0_ovf:
Timer0 = 255 - 39 ' preload
If Half_cycle = 0 Then ' select half cycle positiv
Pwm1a = Sine_table(index + 1) ' positive half cycle
Pwm1b = 0
Elseif Half_cycle = 1 Then
Pwm1b = Sine_table(index + 1) ' negativ sine cycle
Pwm1a = 0
End If
Incr Index ' increments Index for 1
If Index => 32 Then
Index = 0 ' reset Index to 0
If Half_cycle = 0 Then
Half_cycle = 1 ' select negativ Half Cycle
Elseif Half_cycle = 1 Then
Half_cycle = 0 ' select positiv Half Cycle
incr bADCDelay 'increment delay at end of 1 cycle
End If
End If
Return
|
While testing to make sure the actual PWM generation works, disable the ADC, just insert:
bAmplitude = 255 immediately before the RESTORE
Then when you are sure the PWM is generating correct sinewaves, take that line out.
You can even manually set bAmplitude to other numbers, just to ensure it works.
The Bascom simulator is good for doing this sort of testing _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
naseerak
Joined: 08 Nov 2008 Posts: 138
|
Posted: Thu Aug 02, 2012 7:21 pm Post subject: |
|
|
Hi
Thanks for the Time but I am getting the same results on the output though the pwm pulses are stretching wide and narrow. below my new code as suggested by you.
regards
' Program : PWM Sine Wave 50Hz inverter.bas
' Date : 05-06-12
' Processor : ATMEGA8
' Input: Internal sine wave value table
' Process : Pulse width modulation
$regfile = "m8def.dat" ' specify the used micro
$crystal = 8000000 '8000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 128 ' default use 32 for the hardware stack
$swstack = 64 ' default use 10 for the SW stack
$framesize = 64
' variable
Dim Half_cycle As Byte
Dim Sine_table(32) As Byte ' sine_table
Dim Index As Byte ' Positive or Negativ Half_cycle
Dim Bamplitude As Byte 'define a variable
Dim Btemp As Byte
Dim Wtemp As Word
Dim Badcdelay As Byte 'incremented in IRQ, cleared in main loop 'a temporary
' Config Pin
Config Pinb.1 = Output 'Pin OC1A - PWM1a
Config Pinb.2 = Output 'Pin OC1B - PWM1b
'*************************************************
'* Halfperiod = 10 ms.
'* There are 32 pwm values in a half period 10ms/32
'* We need to change the OCR value every 10000/32 =312.5 microsec
'* Let Timer0 overflow after 312.5 us.
'* Set prescaler to 64 *
'* 1 timer step = 64/16MHz = 4 us ; 312.5/4 = 78.12
'* Preload value = 256 - 78.
'*************************************************
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Config Timer0 = Timer , Prescale = 64 '64/8MHz = 8us
Enable Ovf0
On Ovf0 Timer0_ovf
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
' PWM Freq 31.25 kHz for PWM = 8 bit or PWM Freg 15.625 kHz for PWM = 9 bit
'restore Sine_dat
For Index = 0 To 31
Sine_table(index + 1) = Lookup(index , Sine_dat) ' read sine_dat
Next Index
Index = 0
Half_cycle = 0 ' positiv sine cycle
'Pwm_count = 0
Enable Timer0 ' PWM Counter
Enable Interrupts
Do
If Badcdelay > 1 Then 'select bigger to set more delay cycles
bADCDelay = 0 'reset delay flag
End If
Bamplitude = Getadc(0)
Restore Sine_dat
wtemp = lookup(index, sine_dat)
wtemp = wtemp * bamplitude 'multiply, not divide !
'that puts the result in the high byte of wtemp
Sine_table(index + 1) = High(wtemp)
'Print "BTEMP" ; Btemp
Print "sinetable" ; Sine_table(index + 1)
Loop ' Loop forever
' Loop forever
End ' end program
'************************ Interrupt0 ****************************************
Timer0_ovf:
Timer0 = 255 - 39 ' preload
If Half_cycle = 0 Then ' select half cycle positiv
Pwm1a = Sine_table(index + 1) ' positive half cycle
Pwm1b = 0
Elseif Half_cycle = 1 Then
Pwm1b = Sine_table(index + 1) ' negativ sine cycle
Pwm1a = 0
End If
Incr Index ' increments Index for 1
If Index => 32 Then
Index = 0 ' reset Index to 0
If Half_cycle = 0 Then
Half_cycle = 1 ' select negativ Half Cycle
Elseif Half_cycle = 1 Then
Half_cycle = 0 ' select positiv Half Cycle
incr bADCDelay 'increment delay at end of 1 cycle
End If
End If
Return
'**************** SINE WAVE DATA based on PWM PERIOD 255 **********************
Sine_dat:
Data 25 , 50 , 74 , 98 , 120 , 142 , 162 , 180 , 197 , 212 , 225 , 235 , 244 , 250 , 254 , 255 , 254 , 250 , 244 , 235 , 225 , 212 , 197 , 180 , 162 , 142 , 120 , 98 , 74 , 50 , 25 , 0 |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Fri Aug 03, 2012 12:49 am Post subject: |
|
|
In the main loop:
Code: |
Do
If Badcdelay > 1 Then 'select bigger to set more delay cycles
bADCDelay = 0 'reset delay flag
End If 'NO, you want to read the entire array, modify its amplitude, and then save it,
'all within the one delay operation.
Bamplitude = Getadc(0)
Restore Sine_dat
wtemp = lookup(index, sine_dat)
wtemp = wtemp * bamplitude 'multiply, not divide !
'that puts the result in the high byte of wtemp
Sine_table(index + 1) = High(wtemp)
'Print "BTEMP" ; Btemp
Print "sinetable" ; Sine_table(index + 1)
Loop ' Loop forever
|
You dont have anywhere a way to read through the sine_dat table and read it into the Sine_table
The value of the variable 'index' is incremented in the IRQ, but you never run through it in the main loop.
And you should not modify that variable 'index' in both places.
Maybe this would work:
Code: |
dim bRead as byte
Do
If Badcdelay > 1 Then 'select bigger to set more delay cycles
bADCDelay = 0 'reset delay flag
Bamplitude = Getadc(0)
'Restore Sine_dat
'I know it was my suggestion, but I was thinking of READ to get the data, not LOOKUP.
'RESTORE is not necessary when using LOOKUP
for bRead = 0 to 31 'make a loop to read and modify all the data values
wtemp = lookup(bRead, sine_dat)
wtemp = wtemp * bamplitude 'multiply, not divide !
'that puts the result in the high byte of wtemp
Sine_table(bRead + 1) = High(wtemp)
'Print "BTEMP" ; Btemp
Print "sinetable" ; Sine_table(bRead + 1)
next bRead
end if
Loop ' Loop forever
end
|
Even then, you may get unacceptable glitches in the output due to reading and resetting values while the IRQ is active, particularly with the PRINT in there. This needs careful thought to handle, and depends a lot on how you want to implement the design.
I really would rather test this on hardware, but that involves a lot of setting up, which I dont really want to do. While I am happy to make suggestions, you need to think also about how the logic of your program works, and how to make it achieve what you want. Writing little bits of code without proper debugging is not a good way to do this.
Regarding the output, I presume you have some sort of hardware low pass filter on the final output. A PWM signal will always just be a square wave, with variable width pulses. Its up to you to filter these to get a sinewave-looking signal, if that is what you want to see. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|