-- Inverter Controll Firmware -- Chester Lowrey -- this program outputs a 19.53khz carrier frequency modulated with a 60hz sine wave. -- Pin RB3 outputs the signal -- There are 328 steps per full wave -- limited by the carrier frequency -- Short Explanation -- -- For the sine wave generation there are a range of duty cycles from 0 - 255 -- The lookup table only goes to a max of 128 -- And only has enough values for half of the sine wave -- The number of values was calculated to match the number of 19.53khz oscillations in one half cycle of 60hz -- 19.53khz / .06 khz(60hz) = 325.5 -- -- So for one 60hz full wave (~) there are 325.5 19khz full waves. -- We want half wave so divide that by two and its 162.75 -- The lookup table actually has 164 values... its close enough to work, not perfect. -- But now the lookup table only gives us the values for half the full wave, and only goes to 128. -- I get around this by using a polarity variable that is toggled on and off every runthrough of the lookup table. -- if polarity = true then pwm output = lookup table value + 128 -- If polarity = false then pwm output = 128 - lookup table value pragma target chip 16F628 -- PIC16F628 pragma target clock 20_000_000 -- 20mhz crystal pragma target osc hs pragma target watchdog off pragma target powerup on pragma target protection off -- HS, -BOD, -CP pragma target fuses 0x3F0A -- pic 16F62x -- RA2 / AN2 / Vref 1 === 18 RA1 / AN1 -- RA3 / AN3 / CMP1 2 === 17 RA0 / AN0 -- RA4 / TOCK1 / CMP2 3 === 16 RA7 / OSC1 / CLKIN -- RA5 / -MCLR / THV 4 === 15 RA6 / OSC2 / CLKOUT -- Vss 5 === 14 VDD -- RB0 / INT 6 === 13 RB7 / T1OSI -- RB1 / RX / DT 7 === 12 RB6 / T1OSO / T1CK1 -- RB2 / TX / CK 8 === 11 RB5 -- RB3 / CCP1 / PWM 9 === 10 RB4 / PGM -- -- REMARK RA4 has no pullup FET !! include jpic628 include delay_simple CMCON = 7 -- set portA to normal digital IO var byte duty_h = 0 port_a_direction = 0b0000_0000 -- all output port_b_direction = 0b0000_0000 port_a = 0b0000_0000 -- startup value = 0 port_b = 0b0000_0000 -- These outputs are just for testing how the code was working var volatile bit pwm_select is pin_b0 -- high or low side of sine wave var volatile bit interrupt is pin_b1 var volatile bit pwm_select2 is pin_b2 while intcon_gie loop -- make sure general interrupts are disabled intcon_gie = false end loop intcon_t0ie = true -- enable TMR0 interrupt var byte opt at 0x01 -- option register assembler -- andlw 0b_1101_0000 -- clrwdt -- clrf tmr0 movlw 0b1101_1111 -- set the timer0 prescaler to divide by 256 bsf status, 5 -- change to bank 1 clrwdt movwf opt -- move to option register bcf status, 5 -- back to bank 0 end assembler intcon_gie = true -- enable general interrupts intcon_t0if = false -- clear TMR0 interrupt flag var byte pwm var byte pwmt var byte indx = 1 var bit interrupt_temp = true -- var byte pwm_counter = 1 var bit polarity = true -- first or second half of wave -- var bit change = true var bit get_pwm = true procedure pwm_sine_table is pragma jump_table assembler addwf PCL,f retlw 0 retlw 2 retlw 5 retlw 7 retlw 10 retlw 12 retlw 15 retlw 17 retlw 20 retlw 22 retlw 25 retlw 27 retlw 29 retlw 32 retlw 34 retlw 36 retlw 39 retlw 41 retlw 44 retlw 46 retlw 48 retlw 50 retlw 53 retlw 55 retlw 57 retlw 59 retlw 61 retlw 64 retlw 66 retlw 68 retlw 70 retlw 72 retlw 74 retlw 76 retlw 78 retlw 80 retlw 82 retlw 84 retlw 86 retlw 87 retlw 89 retlw 91 retlw 93 retlw 94 retlw 96 retlw 98 retlw 99 retlw 101 retlw 102 retlw 104 retlw 105 retlw 107 retlw 108 retlw 109 retlw 110 retlw 112 retlw 113 retlw 114 retlw 115 retlw 116 retlw 117 retlw 118 retlw 119 retlw 120 retlw 121 retlw 122 retlw 122 retlw 123 retlw 124 retlw 124 retlw 125 retlw 125 retlw 126 retlw 126 retlw 127 retlw 127 retlw 127 retlw 128 retlw 128 retlw 128 retlw 128 retlw 128 retlw 128 retlw 128 retlw 128 retlw 128 retlw 128 retlw 127 retlw 127 retlw 127 retlw 126 retlw 126 retlw 125 retlw 125 retlw 124 retlw 124 retlw 123 retlw 122 retlw 122 retlw 121 retlw 120 retlw 119 retlw 118 retlw 117 retlw 116 retlw 115 retlw 114 retlw 113 retlw 112 retlw 110 retlw 109 retlw 108 retlw 107 retlw 105 retlw 104 retlw 102 retlw 101 retlw 99 retlw 98 retlw 96 retlw 94 retlw 93 retlw 91 retlw 89 retlw 87 retlw 86 retlw 84 retlw 82 retlw 80 retlw 78 retlw 76 retlw 74 retlw 72 retlw 70 retlw 68 retlw 66 retlw 64 retlw 61 retlw 59 retlw 57 retlw 55 retlw 53 retlw 50 retlw 48 retlw 46 retlw 44 retlw 41 retlw 39 retlw 36 retlw 34 retlw 32 retlw 29 retlw 27 retlw 25 retlw 22 retlw 20 retlw 17 retlw 15 retlw 12 retlw 10 retlw 7 retlw 5 retlw 2 retlw 0 -- 164 TOTAL ENTRIES end assembler end procedure procedure pwm_ccp ( byte in period, byte in duty_l ) is asm movf period, w bank_1 asm movwf pr2 bank_0 ccpr1l = duty_l -- set duty cycle ccpr1h = duty_h pin_b3_direction = output -- t2con = 0b_0000_0110 -- tmr2 on, prescale=16 -- t2con = 0b_0000_0101 -- tmr2 on, prescale=4 t2con = 0b_0000_0100 -- tmr2 on, prescale=1 ccp1con = 0b_0000_1100 -- pwm mode on end procedure pwm_ccp (255,128) -- start up the pwm module -- after initialized you only need to change the ccpr11 variable to change the duty cycle procedure TMR0_interrupt is pragma interrupt -- everything that needs to be done on time is done in this interrupt ccpr1l = pwm -- set the PWM register to the new PWM value pwm_select2 = on -- just for testing if indx == 164 then -- index will come from master PIC in final version-- maybe? indx = 1 polarity = ! polarity -- This switches the polarity of the sine wave end if assembler -- lets find the PWM value for next time bank movfw indx page call pwm_sine_table bank movwf pwm -- put the lookup value in the pwm variable end assembler indx = indx + 1 if polarity then -- Positive side of half waveform pwm = pwm + 127 -- pwm_select = on -- just for testing else -- Negative side of half waveform pwmt = pwm pwm = 128 - pwmt pwm_select = off -- just for testing end if pwm_select2 = off -- testing intcon_t0if = false -- clear TMR0 interrupt flag end procedure forever loop -- needs some form of communication with other pics -- serial input the pwm value??? -- one bit input to reset index value and polarity?????? -- one slave controller.. at 1/3rd of phase1 start phase2, at 2/3rd start phase3.. -- if get_pwm == true then -- end if end loop