Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Sine wave Variable amplitude
Goto page 1, 2  Next
 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive
View previous topic :: View next topic  
Author Message
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Fri Jul 27, 2012 10:11 pm    Post subject: Sine wave Variable amplitude Reply with quote

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
View user's profile
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Sat Jul 28, 2012 2:46 am    Post subject: Reply with quote

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
View user's profile Visit poster's website
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Sat Jul 28, 2012 7:51 pm    Post subject: Reply with quote

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
View user's profile
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Sat Jul 28, 2012 11:05 pm    Post subject: Reply with quote

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
View user's profile
jenalcom

Bascom Member



Joined: 10 Apr 2004
Posts: 365
Location: Perth, Western Australia

australia.gif
PostPosted: Sun Jul 29, 2012 4:39 am    Post subject: Reply with quote

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
View user's profile
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Sun Jul 29, 2012 7:32 pm    Post subject: Reply with quote

Hi
Your calculations seems to be right but where to place my ADC routine.
Back to top
View user's profile
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Mon Jul 30, 2012 1:00 am    Post subject: Reply with quote

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
View user's profile Visit poster's website
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Mon Jul 30, 2012 7:01 pm    Post subject: Reply with quote

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
View user's profile
jenalcom

Bascom Member



Joined: 10 Apr 2004
Posts: 365
Location: Perth, Western Australia

australia.gif
PostPosted: Tue Jul 31, 2012 4:11 am    Post subject: Reply with quote

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
View user's profile
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Tue Jul 31, 2012 6:19 pm    Post subject: Reply with quote

Thanks jenalcom
I will try this and will come back with the results
Cheers
regards
Back to top
View user's profile
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Wed Aug 01, 2012 12:06 am    Post subject: Reply with quote

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
View user's profile Visit poster's website
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Wed Aug 01, 2012 9:52 pm    Post subject: Reply with quote

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
View user's profile
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Wed Aug 01, 2012 11:56 pm    Post subject: Reply with quote

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
View user's profile Visit poster's website
naseerak

Bascom Member



Joined: 08 Nov 2008
Posts: 138

pakistan.gif
PostPosted: Thu Aug 02, 2012 7:21 pm    Post subject: Reply with quote

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
View user's profile
AdrianJ

Bascom Expert



Joined: 16 Jan 2006
Posts: 2483
Location: Queensland

australia.gif
PostPosted: Fri Aug 03, 2012 12:49 am    Post subject: Reply with quote

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
View user's profile Visit poster's website
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    www.mcselec.com Forum Index -> BASCOM-AVR Archive All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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