This code works on a PIC 16F628A:
Code:
'---------Initialization--------
DEFINE OSC 20 ' set oscillator 20Mhz
' ***************************************************************
' Device Fuses
' ***************************************************************
#CONFIG
__config _HS_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BODEN_ON & _LVP_OFF & _CP_OFF & _CPD_OFF
#ENDCONFIG
CMCON = 7 ' Turn off comparators
TRISA = %00000000 ' Make all PortA pins output
TRISB = %00110000 ' Make PortB pins 4-5 input
Old_Bits VAR BYTE
New_Bits VAR BYTE
RotEncDir VAR BIT ' 1=CW, 0=CCW
' Rot Enc pin A connected to PortB.5;
' Rot Enc pin B connected to PortB.4
Old_RPM VAR BYTE
I VAR BYTE
'***************************************************************************
' SETUP YOUR LCD HERE!!!
'***************************************************************************
;Define LCD_DREG PORTA
;Define LCD_DBIT 0
;Define LCD_RSREG PORTA
;define LCD_RSBIT 4
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 7 ' Use PortB.7 as the Enable (E) bit since PortB.3
' on the 16F628A is the one-and-only HPWM output
;define LCD_BITS 4
;define LCD_LINES 2
;define LCD_COMMANDUS 2000
;define LCD_DATAUS 50
'---------Includes----------
INCLUDE "EE_Vars.PBP" ' Requires MPASM assembler
' Go to "View > Compile and Program Options..."
' On "Assembler" tab, check "Use MPASM"
' (no need to change any of the default settings)
' --> copy file to PBP main folder (i.e. c:\pbp)
MotorRPM VAR BYTE : @ EE_var _MotorRPM, BYTE, 50
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
' --> copy both files to PBP main folder
' (i.e. c:\pbp)
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RBC_INT, _Rot_Encoder, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE RBC_INT ;RB Port Change Interrupt
' Set default values
Old_Bits = PORTB & (%00110000)
Old_RPM = MotorRPM
LCDOUT $FE, 1
PAUSE 1000
rpmAdj CON 20 ' PWM cycle seems to be "higher" than HPWM, so need
' to reduce PWM cycle max to be less than HPWM cycle value
' Spin up motor to saved value of _MotorRPM
IF MotorRPM > rpmAdj Then
FOR i = 0 to (MotorRPM - rpmAdj)
PWM PortB.3, I, 100
NEXT I
EndIf
' Begin background HPWM
GOSUB motorhpwm
Main:
IF MotorRPM <> Old_RPM Then
Old_RPM = MotorRPM
GOSUB motorhpwm
@ EE_write_var _MotorRPM ; save the new number to EEPROM
EndIF
LCDOUT $FE, 2, "MotorRPM: ", #MotorRPM, " "
pause 10
GOTO Main
motorhpwm:
HPWM 1, MotorRPM, 20000 ; Tried 245 Hz but it made the motor too loud.
; Supposedly, anything above 20kHz is above
; human hearing
RETURN
end
'---[RBC - interrupt handler]---------------------------------------------------
Rot_Encoder:
New_Bits = PORTB & (%00110000)
IF (New_Bits & %00110000) = (Old_Bits & %00110000) Then DoneRotEnc
RotEncDir = New_Bits.5 ^ Old_Bits.4
IF RotEncDir = 1 Then
; CW rotation - increase speed but only to a max of 255
IF MotorRPM < 255 then MotorRPM = MotorRPM + 1
Else
' CCW rotation - decrease speed to a min of 0
IF MotorRPM > 0 Then MotorRPM = MotorRPM - 1
EndIF
DoneRotEnc:
Old_Bits = New_Bits
@ INT_RETURN
This code does NOT on a PIC 16F1825:
Code:
' ***************************************************************
' Initialization
' ***************************************************************
DEFINE OSC 20 ' Set oscillator 20Mhz
' ***************************************************************
' Device Fuses
' ***************************************************************
' PIC chip data sheets can be found here: C:\Program Files\Microchip\MPASM Suite
#CONFIG
__config _CONFIG1, _FOSC_HS & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
__config _CONFIG2, _LVP_OFF
#ENDCONFIG
ANSELA = %00000000
ANSELC = %00000000
TRISA = %00000011 ' Make PortA pins 0-1 input for rotary encoder
TRISC = %00000000 ' Make all pins on PortC output
Old_Bits VAR BYTE
New_Bits VAR BYTE
RotEncDir VAR BIT ' 1=CW, 0=CCW
' Rot Enc pin A connected to PortB.5;
' Rot Enc pin B connected to PortB.4
Old_RPM VAR BYTE
I VAR BYTE
' ***************************************************************
' SETUP YOUR LCD HERE!!!
' ***************************************************************
;Define LCD_DREG PORTA
;Define LCD_DBIT 0
;Define LCD_RSREG PORTA
;define LCD_RSBIT 4
;DEFINE LCD_EREG PORTB
;DEFINE LCD_EBIT 7 ' Use PortB.7 as the Enable (E) bit since PortB.3
' on the 16F628A is the one-and-only HPWM output
;define LCD_BITS 4
;define LCD_LINES 2
;define LCD_COMMANDUS 2000
;define LCD_DATAUS 50
'---------Includes----------
INCLUDE "EE_Vars.PBP" ' Requires MPASM assembler
' Go to "View > Compile and Program Options..."
' On "Assembler" tab, check "Use MPASM"
' (no need to change any of the default settings)
' --> copy file to PBP main folder (i.e. c:\pbp)
MotorRPM VAR BYTE : @ EE_var _MotorRPM, BYTE, 50
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
' --> copy both files to PBP main folder
' (i.e. c:\pbp)
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler IOC_INT, _Rot_Encoder, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE IOC_INT ; Interrupt-on-Change interrupt
' Set default values
Old_Bits = PORTA & (%00000011)
Old_RPM = MotorRPM
;LCDOUT $FE, 1
;PAUSE 1000
' Spin up motor to saved value of _MotorRPM
IF MotorRPM > 1 THEN
FOR i = 0 to MotorRPM
HPWM 3, I, 20000
NEXT I
EndIf
Main:
IF MotorRPM <> Old_RPM Then
Old_RPM = MotorRPM
GOSUB motorhpwm
@ EE_write_var _MotorRPM ; save the new number to EEPROM
EndIF
; LCDOUT $FE, 2, "MotorRPM: ", #MotorRPM, " "
; pause 10
GOTO Main
motorhpwm:
HPWM 3, MotorRPM, 20000 ; Tried 245 Hz but it made the motor too loud.
; Supposedly, anything above 20kHz is above
; human hearing
RETURN
end
' ***************************************************************
' [RBC - interrupt handler]
' ***************************************************************
Rot_Encoder:
New_Bits = PORTA & (%00000011)
IF (New_Bits & %00000011) = (Old_Bits & %00000011) Then DoneRotEnc
RotEncDir = New_Bits.1 ^ Old_Bits.0
IF RotEncDir = 1 Then
; CW rotation - increase speed but only to a max of 255
IF MotorRPM < 255 then MotorRPM = MotorRPM + 1
Else
' CCW rotation - decrease speed to a min of 0
IF MotorRPM > 0 Then MotorRPM = MotorRPM - 1
EndIF
DoneRotEnc:
Old_Bits = New_Bits
@ INT_RETURN
(The motor spins at full speed and encoder changes are ignored).
I've been at this most of the night - any ideas? Apart from the subtle change to spinning up the motor to the saved _MotorRPM EEPROM variable, I can't see what I'm doing wrong. Am I missing a register setting to tell it to use PWM on CCP3?
Bookmarks