Convert Rotary Encoder Code from 16F628A to 16F1825


Closed Thread
Results 1 to 28 of 28

Hybrid View

  1. #1


    Did you find this post helpful? Yes | No

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

    It works! I think I had a combination of problems - PBP config and a weird breadboard connection issue (I have 4 banks of +/- and when the chip was connected to the far bank the voltage potential between Vdd and Vss wasn't 4.91 volts (my 7805's 5v) - more like 1.93 v. Once I configured the chip with Darrel's code above and move the power connections to one of the other banks I can see the LED fade in and repeat.

    Thanks heaps Darrel!

  2. #2


    Did you find this post helpful? Yes | No

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

    Now that I've got the HPWM stuff sorted (thanks to Darrel) I'm back to the original problem which is converting RBC interrupts to IOC on the 16F1825 - rotating the rotary encoder knob has no effect on MotorRPM. Here's the code I have so far:

    Code:
    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, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF
    #ENDCONFIG
    
    
    ' ***************************************************************
    ' Initialization
    ' ***************************************************************
    
    
    DEFINE CCP3_REG PORTA
    DEFINE CCP3_BIT 2
    
    
    ;DEFINE CCP4_REG PORTC
    ;DEFINE CCP4_BIT 1
    
    
    
    
    ANSELA.2 = 0             ' Digital only on CCP3 pin
    ;ANSELC.1 = 0             ' Digital only on CCP4 pin
    TRISA    = %00000011     ' Make PortA pins 0-1 input for rotary encoder
    ;TRISC    = %00000000     ' Make all pins on PortC output
    
    
    ;INTCON.3  = 1            ' Enable interrupt-on-change (IOCIE)
    INTCON    = %10001000    ' Global int enabled, IOCI enabled, IOCI flag bit 0 clr
    IOCAP.0   = 1            ' Enable positive (rising edge) change
    IOCAP.1   = 1            ' Enable positive (rising edge) change
    IOCAN.0   = 1            ' Enable negative (falling edge) change
    IOCAN.1   = 1            ' Enable negative (falling edge) change
    IOCAF.0   = 0            ' Clear interupt-on-change flag
    IOCAF.1   = 0            ' Clear interupt-on-change flag
    
    
    
    
    A              VAR PortA.1 ' Variable to store encoder's A pin output (RA1)
    B              VAR PortA.0 ' Variable to store encoder's B pin output (RA0)      
    
    
    RotEncDir      VAR BIT   ' 1=CW, 0=CCW
                             ' Rot Enc pin A connected to PortA.1;
                             ' Rot Enc pin B connected to PortA.0
    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      
    ;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, 100
    
    
    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_RPM = MotorRPM
    
    
    ;LCDOUT $FE, 1
    ;PAUSE 1000
    
    
    ' Spin up motor to saved value of _MotorRPM
    IF MotorRPM > 1 THEN
        FOR I = 0 to MotorRPM
            pause 30
            HPWM 3, I, 20000
    ;        HPWM 4, 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
    ;    HPWM 4, 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:
        RotEncDir = (A ^ B) ^ IOCAF.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
    
    
        IOCAF.0 = 0  ' Clear interrupt flags
        IOCAF.1 = 0
    
    
    @ INT_RETURN
    Any ideas?

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


    Did you find this post helpful? Yes | No

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

    Not bad Ross,

    All you need is to clear ANSELA bits 0 and 1.
    DT

  4. #4


    Did you find this post helpful? Yes | No

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

    That worked! At least as recognizing the IOC, but I think my logic is wrong - turning the knob one way makes the motor go faster and then slower. The idea is that a CW rotation would make it go faster but turning it CCW would slow it down:

    Code:
    ' ***************************************************************
    ' [RBC - interrupt handler]
    ' ***************************************************************
    Rot_Encoder:
        RotEncDir = (A ^ B) ^ IOCAF.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
    
    
        IOCAF.0 = 0  ' Clear interrupt flags
        IOCAF.1 = 0
    
    
    @ INT_RETURN

  5. #5


    Did you find this post helpful? Yes | No

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

    If I revert to the Old_Bits/New_Bits logic it now works:

    Code:
    DEFINE OSC 20            ' Set oscillator 20Mhz
    
    
    ' ***************************************************************
    ' Device Fuses
    ' ***************************************************************
    #CONFIG
       __config _CONFIG1, _FOSC_HS & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
       __config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF
    #ENDCONFIG
    
    
    ' ***************************************************************
    ' Initialization
    ' ***************************************************************
    
    
    DEFINE CCP3_REG PORTA
    DEFINE CCP3_BIT 2
    
    
    ANSELA.0 = 0             ' Digital only on roatary encoder B pin
    ANSELA.1 = 0             ' Digital only on roatary encoder A pin
    ANSELA.2 = 0             ' Digital only on CCP3 pin
    TRISA    = %00000011     ' Make PortA pins 0-1 input for rotary encoder
    
    
    INTCON   = %10001000     ' Global int enabled, IOCI enabled, IOCI flag bit 0 clr
    IOCAP.0  = 1             ' Enable positive (rising edge) change
    IOCAP.1  = 1             ' Enable positive (rising edge) change
    IOCAN.0  = 1             ' Enable negative (falling edge) change
    IOCAN.1  = 1             ' Enable negative (falling edge) change
    IOCAF.0  = 0             ' Clear interupt-on-change flag
    IOCAF.1  = 0             ' Clear interupt-on-change flag
    
    
    Old_Bits       VAR BYTE
    New_Bits       VAR BYTE
    RotEncDir      VAR BIT   ' 1=CW, 0=CCW
                             ' Rot Enc pin A connected to PortA.1;
                             ' Rot Enc pin B connected to PortA.0
    Old_RPM        VAR BYTE
    I              VAR BYTE
    
    
    ' ***************************************************************
    ' 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, 100
    ;PortNacelleDir VAR BYTE  :  @  EE_var  _PortNacelleDir, BYTE, 0   ' 0 = CCW (inwards)
                                                                      ' 1 = CW (outwards)
    
    
    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_RPM = MotorRPM
    Old_Bits = PORTA & (%00000011)
    
    
    ' Spin up motor to saved value of _MotorRPM
    IF MotorRPM > 1 THEN
        FOR I = 0 to MotorRPM
            pause 30
            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   
        
        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
    
    
    ' ***************************************************************
    ' [IOC - 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
        
        IOCAF.0 = 0  ' Clear interrupt flags
        IOCAF.1 = 0
    
    
    @ INT_RETURN

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


    Did you find this post helpful? Yes | No

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

    Yay!

    Well, stick with what works for you then.

    Cheers.
    DT

  7. #7


    Did you find this post helpful? Yes | No

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

    Thanks Darrel. I would have preferred your approach as its the more elegant solution, but oh well ...

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