Sine wave generation

Hi all ,

I want to generate a sine wave using PWM signal fed to a switches on a H-Bridge circuit. I have researched and found that the best way is to sine modulate the PWM signal using a look up table holding sine values ( which can be done by using a timer counter unit to generate a high frequency triangle wave , and counter to compare at a value taken form the LUT).

My question is what is the best way generate the data for the LUT and how do I store the sine values in hex on a 8 bit macro ,to be loaded in the compare register of the comparator ?

BR Niladri

Reply to
ratemonotonic
Loading thread data ...

Hard way - use sine tables and write them out, transcribe them into constant definitions. Easy way - write a program to generate constant definitions.

HTH

Deep.

Reply to
Deep Reset

You only need the values in the first quadrant so it doesnt take very long with a calculator to work them out manually.

Reply to
cbarn24050

Download this Freeware Calc :

formatting link

paste in any of these three lines

mode deg; x=-90/128;;x=x+90/64; ans=255*sin(x)+0.5

display bin; mode deg; x=-90/128;;x=x+90/64; ans=255*sin(x)+0.5

display hex; mode deg; x=-90/128;;x=x+90/64; ans=255*sin(x)+0.5

Press enter 64 times per quadrant. paste the results into your Source code, in a CONST Array declaration, ( along with the Eqn line, as a comment for revision purposes.)

Typically you store one quadrant and reverse scan direction, and reverse sign to build the 4 quadrants.

Comments: CCalc uses ;; as an Eqn block delimiter, and repeated enters repeat the lack Eqn block on the stack. Above sets 64 steps per quadrant, and 255 as Full scale. The +0.5 takes care of rounding

To improve your Sine precision, you should match the highest slopes to a natural slope in the timebase - that drops the errors on that portion of the sine, and drops the distortion.

-jg

Reply to
Jim Granville

Or use any spreadsheet program to do this.

You could also at the same time easily analyse how much the rounded 8 bit value differs from the ideal value and possibly select slightly different points to reduce the average error.

Paul

Reply to
Paul Keinanen

Manual coding of consts. Generation of consts using your own code.

Karthik Balaguru

Reply to
karthikbalaguru

On Sun, 14 Oct 2007 19:36:43 -0000, ratemonotonic wrote:

I use Excel to generate and normalize the sine values, then Word to format them for inclusion into the program using a series of find and replace operations.

I'm including a little routine below with a pre-calculated sine table that might be of use to you.

Tom

;-------------------------------------------------------- ; ; VF_Controller.asm ; ; Voltage-Frequency Converter ; ; PIC 12F683 firmware ; to drive my VF Controller Mk II circuit ; ; V1.00: tested OK with scope on breadboard. ; did not test it with the switching ; hardware yet. ; ; tjl Sep 20,2007 ; ;-------------------------------------------------------- ; ; This program implements a half-bridge voltage-frequency ; speed controller for small single phase shaded pole ; induction motors. ; ; Speed range is from approx 60 Hz to 20 Hz, with the ; voltage reduced by the following formula: ; ; motor V = design V * motor freq / design freq ; ; The wiper of a pot connected between +5v and ground ; is connected to physical pin 3. The pot setting ; determines the motor speed. ; ; Active low -> open outputs on physical pins 7 and 6 ; drive the high side and low side half-H switches, ; respectively. ; ; A half-cycle sinewave is synthesized via PWM, and ; appears as an active high PWM signal on physical ; pin 5. ; ; Connect pins 7 and 6 to the cathodes of optoisolator ; LEDs, and the PWM pin paralleled to the anodes through ; a 330 ohm series resistor. ; ; Use the optoisolator transistors to drive a high side ; P-channel MOSFET and a low side N-channel MOSFET. ; ; Connect the motor between the junction of the two ; MOSFETs and neutral. ; ;-------------------------------------------------------- ; ; Physical pin 3 (AN3) - Speed pot ; Physical pin 5 (CCP1) - PWM output ; Physical pin 6 (GP1) - Neg Switch (active low) ; Physical pin 7 (GP0) - Pos Switch (active low) ; ;-------------------------------------------------------- ; ; 12F683 RAM: ; 96 bytes in bank0, 0x20-0x7f ; 32 bytes in bank1, 0xa0-0xbf ; ; Program memory: ; 2k 14-bit words, 0x000-0x7ff ; ; Data EEPROM: ; 256 bytes, accessed through DE decls or ; the four EExxx registers ;

;-------------------------------------------------------- ; ; Config section ; ;--------------------------------------------------------

list p=12F683 #include

__CONFIG _FCMEN_ON & _IESO_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTOSCIO

;-------------------------------------------------------- ; ; Radix, Defines, and Constants ; ;--------------------------------------------------------

radix dec errorlevel -302 ; I/O #define PosSw 0 #define NegSw 1 #define PWMpin 2 #define Pot 4 ; constants #define Tmrbase 60 ; tune this for 60 Hz at max speed setting #define PWM_val 254 ; 7.8 kHz w/ 8 MHz clock and no prescaling

;-------------------------------------------------------- ; ; Macro definitions ; ;--------------------------------------------------------

bank0 macro bcf STATUS,RP0 endm

bank1 macro bsf STATUS,RP0 endm

;-------------------------------------------------------- ; ; Storage ; ;--------------------------------------------------------

; EEPROM table data

org 0x2100 SineTbl de 0,13,25,37,50,62,74,86 de 98,109,120,131,142,152,162,171 de 180,189,197,205,212,219,225,231 de 236,240,244,247,250,252,254,255 de 255,255,254,252,250,247,244,240 de 236,231,225,219,212,205,197,189 de 180,171,162,152,142,131,120,109 de 98,86,74,62,50,37,25,13

VoltTbl de 255,247,240,233,227,221,215,210 de 205,200,195,191,186,182,178,174 de 171,168,164,161,158,155,152,149 de 147,144,142,139,137,135,133,131 de 129,126,125,123,121,119,118,116 de 114,113,111,110,108,107,106,104 de 103,102,101,99,98,97,96,95 de 94,92,92,90,90,89,88,87

; Un-init RAM

cblock 0x20 w_bup ; save W and STATUS from ISR stat_bup semaphore ; semaphore set by ISR when TMR0 times out rawspeed ; raw ADC speed pot measurement value speedval ; speed value to load into TMR0 sineptr ; SineTbl pointer sineval ; from SineTbl voltval ; from VoltTbl pwmvalhi ; high byte of sine x volt mult pwmvallo ; low byte of sine x volt mult running temp0 temp1 temp2 temp3 endc

;-------------------------------------------------------- ; ; Program code begins here ; ;--------------------------------------------------------

org 0 ; processor reset vector

goto main org 0x04 ; interrupt vector goto Int_Svc_Rtn ;-------------------------------------------------------- ; ; Interrupt service routine ; ;--------------------------------------------------------

Int_Svc_Rtn movwf w_bup ; save the W and STATUS regs movf STATUS,W movwf stat_bup btfss INTCON,T0IF ; TMR0 overflow? goto enableints ; no, just enable ints and return bcf INTCON,T0IF movf speedval,W ; reload the TMR0 preset movwf TMR0 movlw 1 movwf semaphore ; tell SendCycle that an int has occurred enableints movf stat_bup,W ; restore the W and STATUS regs movwf STATUS movf w_bup,W bsf INTCON,GIE ; enable system interrupts retfie

;-------------------------------------------------------- ; ; Main program routine begins here ; ;-------------------------------------------------------- main

; Disable system interrupts

bcf INTCON,GIE ; set the internal oscillator to 8 MHz

bank1 movlw 0x71 movwf OSCCON bank0 ; init I/O & ADC movlw 0x07 movwf CMCON0 ; 0,1,2 are digital I/O bank1 movlw b'01011000' ; AN3 analog, others digital I/O, Fosc/16 movwf ANSEL movlw b'00010011' ; Preset PosSw and NegSw as inputs movwf TRISIO bank0 movlw b'00001101' ; AN3, left-justified,ADON movwf ADCON0 bcf GPIO,PWMpin ; set PWM output low ; set up PWM

call StartPWM ; begin clrf running ; force parm init at first GetSpeed call call Dly1Sec ; 1 sec pause to let HV pwr supply settle mainloop

call GetSpeed call SetPosPhase call SendCycle call SetNegPhase call SendCycle goto mainloop

;-------------------------------------------------------- ; ; Subroutines ; ;--------------------------------------------------------

PWMcalc ; 8 x 8 unsigned mult of sineval x voltval ; result in pwmvalhi and pwmvallo ; modifies sineval, temp0,temp1,temp3 bank0 clrf pwmvalhi clrf pwmvallo movf voltval,W movwf temp0 ; holds low byte of shifted voltval clrf temp1 ; holds high byte of shifted voltval movlw 8 movwf temp3 ; counter mult1 rrf sineval,F btfss STATUS,C goto mult2 movf temp0,W addwf pwmvallo,F btfss STATUS,C goto mult3 incf pwmvalhi,F mult3 movf temp1,W addwf pwmvalhi,F mult2 bcf STATUS,C rlf temp0,F rlf temp1,F decfsz temp3,F goto mult1 return LoadPWM ; pwmvalhi to CCPR1L, pwmvallo to CCP1CON bank0 bcf CCP1CON,5 bcf CCP1CON,4 btfsc pwmvallo,7 bsf CCP1CON,5 btfsc pwmvallo,6 bsf CCP1CON,4 movf pwmvalhi,W movwf CCPR1L return GetSpeed ; read speed pot setting, set delay, ; then set TMR0 and semaphore bsf ADCON0,1 ; start an ADC measurement btfss PIR1,ADIF ; wait for completion goto $-1 bcf PIR1,ADIF movf ADRESH,W ; get the reading movwf temp0 movf running,F ; running? btfss STATUS,Z goto gslp2 ; if not, force parm initialization movlw 1 movwf running goto gslp1 gslp2 subwf rawspeed,W ; exit if it speed pot setting has not changed btfsc STATUS,Z return gslp1 movf temp0,W ; save the new reading movwf rawspeed comf temp0,F ; subtract speed reading from

255... bcf STATUS,C ; ...and divide it by 4 rrf temp0,F bcf STATUS,C rrf temp0,F ; temp0 contains 0 (max) to 63 (min) movlw VoltTbl ; calc addr of volt table addwf temp0,W call EERead movwf voltval bcf STATUS,C ; double the speed index rlf temp0,F movlw Tmrbase ; add speed factor to timer base value addwf temp0,W movwf speedval comf speedval,F ; subtract from 256 (255), save as TMR0 ; preload value

bcf INTCON,GIE ; disable interrupts movf TMR0,F ; write to TMR0 bcf INTCON,T0IF bsf INTCON,T0IE clrf semaphore ; clear interrupt semaphore bsf INTCON,GIE ; enable interrupts return

SendCycle ; set pwm from sine table and volts tbl, ; wait for interrupt, set next step's vals clrf sineptr sclp1 movf sineptr,W ; get sine value call EERead movwf sineval call PWMcalc ; calc PWM from sine & pre-calc'd volts val call LoadPWM ; set new PWM duty cycle movf semaphore,F ; wait for TMR0 interrupt btfsc STATUS,Z goto $-2 clrf semaphore incf sineptr,F ; loop through the sine table movlw 64 ; (SineTbl size) subwf sineptr,W btfss STATUS,Z goto sclp1 return EERead ; EEPROM read. Enter with addr in W, ; exit with data in W bank1 movwf EEADR bsf EECON1,RD movf EEDAT,W bank0 return SetPosPhase ; Open PWM path to Q1

bank0 bsf GPIO,NegSw bsf GPIO,PosSw bank1 movlw b'0010010' movwf TRISIO bank0 bcf GPIO,PosSw return SetNegPhase ; Open PWM path to Q2

bank0 bsf GPIO,PosSw bsf GPIO,NegSw bank1 movlw b'0010001' movwf TRISIO bank0 bcf GPIO,NegSw return StartPWM ; Set up and start PWM

bank1 bsf TRISIO,PWMpin ; Disable the PWM output pin

movlw PWM_val ; Set the PWM period into TMR2 movwf PR2 bank0

movlw b'00001100' ; Set CCP module for PWM mode movwf CP1CON movlw 0 ; Inital duty cycle = 0% movwf CCPR1L

clrf T2CON ; Set TMR2 scalers for 1:1 bsf T2CON,TMR2ON ; Start TMR2 bcf PIR1,TMR2IF ; Clear TMR2's interrupt flag

btfss PIR1,TMR2IF ; Wait for TMR2 overflow goto $-1 bcf PIR1,TMR2IF bank1 ; Start PWM by setting the PWM pin bcf TRISIO,PWMpin ; as an output bank0 return Dly1Sec ; 1 sec delay at 8 MHz movlw 7 bank1 movwf OPTION_REG ; set for 1:256 prescaling for TMR0 bank0 movlw 31 movwf temp0 dlylp clrf TMR0 ; TMR0: 254 ticks of 256 instr cycles bcf INTCON,T0IF btfss INTCON,T0IF goto $-1 decf temp0,F btfss STATUS,Z goto dlylp movlw 1 bank1 movwf OPTION_REG ; restore 1:4 prescaling for TMR0 bank0 return end

Reply to
Tom2000

Just use your favorite programming language to write a program to spit out the values, which you can write into or redirect into a file (to be pasted or included into the source code). Try it-- you'll use this technique again and again.

Best regards, Spehro Pefhany

--
"it's the network..."                          "The Journey is the reward"
speff@interlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com
Reply to
Spehro Pefhany

Check this out:

formatting link

and this:

formatting link

Al

Reply to
Al

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.