PDA

View Full Version : How to write pwm using picbasic pro?



Haydn303
- 28th April 2013, 10:46
How to write pwm using picbasic pro?

longpole001
- 28th April 2013, 10:55
heres an example that may be of value i found that i found usefull , its for the 18f1825 , it does not use all the pic pasic pro command set but if you just do a search on PWM on forum , you will soon find many examples



' PWM_TEST.BAS
'
' WRITTEN BY DAVID PUROLA 04/05/2012
'
' WRITTEN FOR USE W/16F1825 E/P @ 32 Mhz.
'
'
DEFINE OSC 32
DEFINE NO_CLRWDT 1

#CONFIG
;----- CONFIG1 Options --------------------------------------------------
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON

;----- CONFIG2 Options --------------------------------------------------
__config _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG

' ************************************************** ******************
' Declare Port Variables
' ************************************************** ******************
COMOUT VAR PORTA.0 '0-OUTPUT COMMUNICATIONS PORT PIN
COMIN VAR PORTA.1 '1-INPUT COMMUNICATIONS PORT PIN
FEEDBK VAR PORTA.2 '1-ANALOG INPUT FROM POSITION POT
RST VAR PORTA.3 '1-RESET/MCLR
BATTERY VAR PORTA.4 '1-ANALOG INPUT FROM BATTERY VOLTAGE
RS485TX VAR LATA.5 '0-DRIVER ENABLE INPUT TO RS-485

RUNLED VAR LATC.0 '0-RUN LED
ESTOP VAR PORTC.1 '1-ESTOP INPUT FROM BUTTON
CWLIM VAR PORTC.2 '1-CW HARD LIMIT SWITCH
CCWLIM VAR PORTC.3 '1-CCW HARD LIMIT SWITCH
CCW VAR LATC.4 '0-PWM CCW OUTPUT
CW VAR LATC.5 '0-PWM CW OUTPUT

' ************************************************** ******************
' Define Constants
' ************************************************** ******************
NREADS CON 16 'A/D READINGS TO AVERAGE
MAXCHANNELS CON 2 'NUMBER OF A/D CHANNELS
OFF_ CON 0 'DIGITAL 0 NUMONIC
ON_ CON 1 'DIGITAL 1 NUMONIC
SINK CON 0 'MOTOR SINK CURRENT NUMONIC
SOURCE CON 1 'MOTOR SOURCE CURRENT NUMONIC
SPAN CON 2040 'WORKING VALUE SERVO FULL SCALE SPAN

' ************************************************** ******************
' Declare Variables
' ************************************************** ******************
BITSWORD VAR WORD BANK0 'BITS FOR STORAGE
TX_EMPTY VAR BITSWORD.0 'TRANSMIT BUFFER EMPTY FLAG
RX_BUFFULL VAR BITSWORD.1 'RECEIVER BUFFER FULL FLAG
RX_MESSAGE VAR BITSWORD.2 'MESSAGE RECEIVED FLAG
COWS_HOME VAR BITSWORD.3 'LOOP FLAG
MSBIT VAR BITSWORD.4 'SIGN FLAG FOR MATH
MSGSTAT VAR BITSWORD.5 'SIGN FLAG FOR CORRECT MESSAGE
TXPAR VAR BITSWORD.6 'PARITY ENABLE FLAG
PARITYTYPE VAR BITSWORD.7 'PARITY TYPE (1=ODD/0=EVEN)

VOLTS VAR WORD[MAXCHANNELS] 'A/D READINGS (N-CHANNELS)
AV_VOLTS VAR WORD[MAXCHANNELS] 'A/D READINGS (N-CHANNELS)
ADREADS VAR WORD[NREADS * MAXCHANNELS]'A/D READINGS (0-65535) (N-CHANNELS * N-READS)
ADINDEX VAR BYTE[MAXCHANNELS] 'RING INDEX POINTER (N-CHANNELS)
CHANNEL VAR BYTE 'A/D CHANNEL VARIABLE

BITINDEX VAR BYTE 'SCRATCH VARIABLE
SCRATCH VAR WORD 'SCRATCH VARIABLE WORD
JUNK VAR BYTE 'SCRATCH VARIABLE
JUNK1 VAR BYTE 'SCRATCH VARIABLE
SCRATCH1 VAR WORD 'SCRATCH VARIABLE WORD
DIR VAR BYTE 'DIRECTION BIT,BYTE PATERN FOR PWM STEERING LOGIC

FINAL VAR WORD 'FINAL EQUATION OUTPUT
HALFSPAN VAR WORD 'HALF SPAN ERROR LIMITER

' ************************************************** ******************
' SYSTEM INITIALIZATION
' ************************************************** ******************
clear
PORTA = %00000000
PORTC = %00000000
TRISA = %00101110 'INITIALIZE PORT DIRECTIONS
TRISC = %00000000 'INITIALIZE PORT DIRECTIONS

OSCCON = %11110000 'SET SYSTEM CLOCK SWITCH BIT

INTCON = %00000000 'CLEAR GIE,PEIE,TMR0IE,INTE,RBIE,TMR0IF,INTF,RBIF
PIE1 = %00000000 'CLEAR ALL INTERRUPT ENABLE BITS
PIR1 = %00000000 'CLEAR ALL INTERRUPT FLAGS

PIE2 = %00000000 'CLEAR ALL INTERRUPT ENABLE BITS
PIR2 = %00000000 'CLEAR ALL INTERRUPT FLAGS

APFCON0 = %10000100 'ENABLE USART ON PORTA.0:1
APFCON1 = %00000000 'ALL DEFAULT

ANSELA = %00010100 'AN2,AN4 ANALOG,:AN0,AN1 DIGITAL I/O
WPUA = %00000000 'WEAK PULLUP'S OFF

INLVLA = %00111111 'SCHMITT TRIGGER

ANSELC = %00000000 'PORTC, DIGITAL I/O
WPUC = %00000000 'WEAK PULLUP'S OFF

INLVLC = %00111111 'SCHMITT TRIGGER
ADCON0 = %00000000 'CHS2:0,GO/DONE,ADOFF
ADCON1 = %11100000 'RIGHT JUSTIFIED,FOSC/64,VSS,VDD
SRCON0 = %00000000
SRCON1 = %00000000
CM1CON0 = %00000000 'CLEAR/DISABLE COMPARATOR
CM1CON1 = %00000000 'CLEAR/DISABLE COMPARATOR
CM2CON0 = %00000000 'CLEAR/DISABLE COMPARATOR
CM2CON1 = %00000000 'CLEAR/DISABLE COMPARATOR
CMOUT = %00000000 'DISABLE OUTPUT REGISTER
DACCON0 = %00000000 'CLEAR/DISABLE D/A
DACCON1 = %00000000 'CLEAR/DISABLE D/A
FVRCON = %00000000 'DISABLE FIXED VOLTAGE REFERENCE

OPTION_REG = %10000000 'CLEAR ALL PULL-UPS,INTEDG,T0CS,T0SE,PSA,PS
T1CON = %00010101 'PRESCALER 1/2,START TIMER 1
T1GCON = %00000000 'NO GATE CONTROL

T4CON = %00000000 'POSTSCALER 1/1,STOP,PRESCALER 1/1
T6CON = %00000000 'POSTSCALER 1/1,STOP,PRESCALER 1/1

T2CON = %00000110 'POSTSCALER 1/1,START,PRESCALER 16
CCPTMRS = %00000000'SET COMPMPARES 1,2,3 FOR TIMER 2
TMR2 = 0 'CLEAR TMR2 MODULE REGISTER
PR2 = 255 'SET PERIOD ((((1 / 40,000,000)*4)*16 PRESCALE)*(1+255 PR2)) = 2.44 KHZ
CCP1CON = %00001100 'PLACE CCP1 INTO PWM MODE
CCPR1L = $00 'CLEAR CCP1 LOWER 8 BITS
CCPR1H = $00 'CLEAR CCP1 UPPER 2 BITS

CCP2CON = %00000000 'PLACE CCP1 INTO DISABLE MODE
CCP4CON = %00000000 'PLACE CCP1 INTO DISABLE MODE
TMR4 = 0 'CLEAR TMR2 MODULE REGISTER
TMR6 = 0 'CLEAR TMR2 MODULE REGISTER
PR4 = $FF 'SET PERIOD (1/1 PRESCALE * 256 PR2 * 1/20,000,000 * 4 = 19.53 Khz.
PR6 = $FF 'SET PERIOD (1/1 PRESCALE * 256 PR2 * 1/20,000,000 * 4 = 19.53 Khz.
CCPR2L = $00 'CLEAR LOWER 8 BITS
CCPR2H = $00 'CLEAR UPPER 2 BITS
CCPR3L = $00 'CLEAR LOWER 8 BITS
CCPR3H = $00 'CLEAR UPPER 2 BITS
CCPR4L = $00 'CLEAR LOWER 8 BITS
CCPR4H = $00 'CLEAR UPPER 2 BITS

GOTO MAINLOOP

' ************************************************** ******************
' SUBROUTINES
' ************************************************** ******************

'************************************************* ********************
READAD: 'READ SYSTEM A/D VOLTAGES (AVERAGE 64 READINGS) 16F1825
'************************************************* ********************
ADCON0 = $01 | ((CHANNEL + 2) << 2) ' Set A/D to Channel X, On
PAUSEUS 40
VOLTS(CHANNEL) = 0 'CLEAR A/D READINGS
SCRATCH = 0
WHILE SCRATCH < 64 'SUM 64 READINGS
ADCON0.1 = 1 ' START CONVERSION
WHILE ADCON0.1 = 1 'WAIT FOR A/D TO FINISH
WEND
VOLTS(CHANNEL) = VOLTS(CHANNEL) + (((ADRESH & $3) << 8) + ADRESL) 'BUILD SENSOR WORD
SCRATCH = SCRATCH + 1
WEND
VOLTS(CHANNEL) = VOLTS(CHANNEL) >> 5 'TURN INTO 11 BIT RESULT
ADINDEX(CHANNEL) = (ADINDEX(CHANNEL) + 1) & (NREADS - 1) 'INCREMENT INDEX POINTER
ADREADS((CHANNEL * (NREADS)) + ADINDEX(CHANNEL)) = VOLTS(CHANNEL) 'STORE IN RING BUFFER
RETURN

'************************************************* ********************
AVERAGE_AD: 'AVERAGE N X 16 BIT VALUES WO/LONG OR 32 BIT MATH
'************************************************* ********************
SCRATCH = 0 ' Zero to Start
SCRATCH1 = 0
JUNK = 0
WHILE JUNK < NREADS
SCRATCH = SCRATCH + ADREADS((CHANNEL * NREADS) + JUNK)
If SCRATCH < ADREADS((CHANNEL * NREADS) + JUNK) then
SCRATCH1 = SCRATCH1 + 1 ' Detect overflow and carry...
endif
JUNK = JUNK + 1
WEND

JUNK = ((NCD NREADS) - 1)
SCRATCH = SCRATCH >> JUNK
JUNK = JUNK - 1
BITINDEX = 15
WHILE JUNK < 255
SCRATCH.0(BITINDEX) = SCRATCH1.0(JUNK)
JUNK = JUNK - 1
BITINDEX = BITINDEX - 1
WEND
AV_VOLTS(CHANNEL) = SCRATCH
RETURN

' ************************************************** ******************
OUTPWM: 'OUTPUT NEW PWN VALUE
' ************************************************** ******************
LATC.4 = SINK 'PRESET PORT PIN LOW
LATC.5 = SINK 'PRESET PORT PIN LOW
PSTR1CON = %00010000 | DIR '1=CW (PWM P1A/STATIC STATE P1B, 2=CCW (PWM P1B/STATIC STATE P1A
CCPR1L = FINAL >> 2 'UPDATE PWM1 UPPER 8 BITS
CCP1CON = $0C | ((FINAL & $3) << 4) 'UPDATE PWM1 LOWER 2 BITS
RETURN

' ************************************************** ******************
MAINLOOP:' PROGRAM LOOP
' ************************************************** ******************
HALFSPAN = SPAN / 2
REPEAT
CHANNEL = 0 'FEEDBACK POT
GOSUB READAD 'READ SYSTEM A/D VOLTAGES (AVERAGE 64 READINGS)
GOSUB AVERAGE_AD 'AVERAGE N X 16 BIT VALUES WO/LONG OR 32 BIT MATH
FINAL = VOLTS(0) - HALFSPAN
DIR = FINAL.15
DIR = 1 << DIR
IF FINAL.15 = 1 THEN FINAL = ABS(FINAL)
FINAL = FINAL MIN HALFSPAN
GOSUB OUTPWM 'OUTPUT NEW PWN VALUE

UNTIL COWS_HOME
' ************************************************** ******************
END 'SHOULD NEVER GET HERE.........
STOP

electroken
- 5th May 2013, 14:23
You didn't mention which type of PWM you wanted, HWPM for continous PWM, or regular. Here is a quickie program that flashes a LED from full bright to dimly lit. It's good for an indication of some kind.
Install a LED on portb.0



T var byte' set-up the loop variable
For t=1 to 20' amount of bright/dim flashes
portb.0=1:pause 90:portb.0=0' full bright ON time then turn OFF---experiment with the ON time.
PWM portb.0,20,80' the 20 is LED brightness, the 80 is it's ON time--Again experiment with the numbers, try changing the 20 to 50.
TRISb=0' Once PWM is used on a pin, then that pin only wants PWM to be used. The TRISb resets the pin back to normal output.
next t' end of loop


If you had inputs on portb, like portb.1, and portb.2, then use TRISb=%00000110
.
While PWM is operating, nothing else is being done. Same way with SOUND. When using a servo, when PWM stops, the servo no longer gets data causing it to lose it's position if it was under a load. To correct this you would need to use the HWPM.
Hope this helped.
Electroken