Convert Rotary Encoder Code from 16F628A to 16F1825


Closed Thread
Results 1 to 28 of 28

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default Re: Convert Rotary Encoder Code from 16F628A to 16F1825

    No, but it does show PortA pins and according to the quote from the datasheet PortA has IOC.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: Convert Rotary Encoder Code from 16F628A to 16F1825

    Thanks Henrik - I didn't catch the part about PortB on chip 16F1829.

    I've got the code converted to work with a 16F1825 but I had to add the following to the p16F1825.inc file in MPASM:

    Code:
    CCPTMRS          EQU  H'029E'
    CCPTMRS0         EQU  H'029E'
    Can anyone tell me why? All I'm trying to do is use HPWM on CCP3 with the following config/code:

    Code:
    ANSELA   = %00000000
    ANSELC   = %00000000
    TRISA    = %00000011     ' Make PortA pins 0-1 input for rotary encoder
    TRISC    = %00000000     ' Make all pins on PortC output
    
    HPWM 3, 97, 20000
    Until I added the line above in the p16F1825.inc MPASM file, I got this compile error:

    Code:
    Error[113] c:\pbp\pbppi14e.lib 2089 : Symbol not previously defined (CCPTMRS0)

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    In the version history for PBP3 ... http://support.melabs.com/content/29...ersion-History

    One of the bug fixes listed is ... Fixed HPWM compile error for Enhanced Mid-Range parts in which CCPTMRS0 doesn't exist.
    DT

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: Convert Rotary Encoder Code from 16F628A to 16F1825

    Ah! So what you're saying is, use PBP3 already I did purchase the software upgrade but haven't tried converting my existing PBP code yet. Guess I should start sooner than later.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Convert Rotary Encoder Code from 16F628A to 16F1825

    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?

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Convert Rotary Encoder Code from 16F628A to 16F1825

    I'll double check the connections, but can someone please confirm if I need this to enable the interrupt-on-change feature?

    Code:
    INTCON.3 = 1        'IOCIE bit set to 1

  7. #7


    Did you find this post helpful? Yes | No

    Default Re: Convert Rotary Encoder Code from 16F628A to 16F1825

    That doesn't explain why the HPWM doesn't work, though. Is there something that needs to be configured for PWM use of CCP3?

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts