News:

;) This forum is the property of Proton software developers

Main Menu

Quadrature encoder using interrupts

Started by RGV250, Today at 07:28 PM

Previous topic - Next topic

RGV250

Hi,
I am having a bit of grief trying to convert some working code to use interrupts.
This is the working example from Les which I have converted to PIC24.
Device = 24HJ128GP502
Declare Xtal = 79.23
TRISA = 00000000000000
TRISB = 00000000000000
' Configure for internal 7.37MHz oscillator with PLL
' OSC pins are general purpose I/O
'
    Config FBS = BWRP_WRPROTECT_OFF, BSS_NO_FLASH, BSS_NO_BOOT_CODE
    Config FSS = SWRP_WRPROTECT_OFF, SSS_NO_FLASH, RSS_NO_SEC_RAM
    Config FGS = GWRP_OFF, GCP_OFF
    Config FOSCSEL = FNOSC_FRCPLL, IESO_OFF
    Config FOSC = POSCMD_NONE, OSCIOFNC_ON, IOL1WAY_OFF, FCKSM_CSDCMD
    Config FWDT = WDTPOST_PS256, WINDIS_OFF, FWDTEN_OFF
    Config FPOR = FPWRT_PWR128, ALTI2C_OFF
    Config FICD = ICS_PGD1, JTAGEN_OFF
   
PLL_Setup(43, 2, 2, $0300)                          ' Configure the Oscillator to operate the device at 79.23MHz

'------------------------------------------------
' USART1 declares
' Defult settings for Microstick Plus board
    Declare Hserial_Baud = 19200     
         
    Declare HRSOut1_Pin = PORTB.10           ' Select which pin is to be used for TX with USART1   
    PPS_Output(cOut_Pin_RP10, cOut_Fn_U1TX)  ' Make Pin RB10 U1TX

    Declare HRSIn1_Pin = PORTB.11            ' Select which pin is to be used for RX with USART1   
    PPS_Input(cIn_Pin_RP11, cIn_Fn_U1RX)     ' Make Pin RB11 U1RX
'------------------------------------------------   

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Rotary encoder reader using a bit-table decode mechanism
'
' Written by Les Johnson for the Positron8 BASIC compiler
'
 '   Device = 18F25K22                           ' Choose the device to compiler for
 '   Declare Xtal = 16                           ' Tell the compiler, the device will be running at 16MHz
'
' Setup USART1
'
 '   Declare Hserial_Baud = 9600
 '   Declare HRSOut_Pin = PORTC.6

    Symbol Enc_Pin1 = PORTB.6                   ' Connects to a pin on the rotary encoder
    Symbol Enc_Pin2 = PORTB.7                   ' Connects to the other pin on the rotary encoder
'
' Create some global variables for the rotary encoder read procedure
'
    Dim Enc_bValidValue As Byte                 ' Holds the previous valid reading from the rotary encoder
    Dim Enc_bStore As Byte                      ' Stores the previous manipulated value from the rotary encoder
    Dim Enc_wTable As Word = %0110100110010110  ' Holds the bit table for valid moves of the rotary encoder
'
' Create some variables for the demo
'
    Dim wCounter As SWord = 0
    Dim bEncValue As SByte

'---------------------------------------------------
' The main program starts here
' Read a rotary encoder and increment or decrement a variable depending on the direction of the rotation
' The value and the direction are transmitted to a serial terminal
'
Main:
    Enc_Setup()                                 ' Setup the program and the pins for the rotary encoder reading

    Do                                          ' Create a loop
        bEncValue = Enc_Read()                  ' Read the rotary encoder
        If bEncValue <> 0 Then                  ' Is the value read from it 0?
            wCounter = wCounter + bEncValue     ' No. So add the value to wCounter
            If bEncValue < 0 Then               ' Was the value read -1?
                HRSOut "CCW: "                  ' Yes. So display that is was counter-clockwise
            Else                                ' Otherwise... The value read was 1. So...
                HRSOut "CW:  "                  ' Display that is was clockwise
            EndIf
            HRSOutLn SDec wCounter              ' Display the count value on the serial terminal
        EndIf
    Loop                                        ' Do it forever

'---------------------------------------------------
' Read a rotary encoder
' Input     : Enc_Pin1 and Enc_Pin2 hold the pins used for the encoder
' Output    : A valid Clockwise or Anti-Clockwise move returns 1 or -1, an invalid move returns 0
' Notes     : None
'
Proc Enc_Read(), SByte   
    Result = 0                                      ' Default to a 0 return value
    Enc_bValidValue = Enc_bValidValue << 2          ' \
    Enc_bValidValue.0 = Enc_Pin1                    ' |
    Enc_bValidValue.1 = Enc_Pin2                    ' | Find the position of the encoder's pins
    Enc_bValidValue = Enc_bValidValue & %00001111   ' /

    If GetBit Enc_wTable, Enc_bValidValue <> 0 Then ' Is the move possibly valid?
        Enc_bStore = Enc_bStore << 4                ' Yes. So shift up by 4-bits
        Enc_bStore = Enc_bStore | Enc_bValidValue   ' Or in the pin positions
        If Enc_bStore = %00101011 Then              ' Is the encoder moving Anti-Clockwise?
            Result = -1                             ' Yes. So return a value of -1
        ElseIf Enc_bStore = %00010111 Then          ' Is the encoder moving Clockwise?
            Result = 1                              ' Yes. So return a value of 1
        EndIf
    EndIf
EndProc

'---------------------------------------------------
' Setup the pins and variables to read a rotary encoder
' Input     : None
' Output    : None
' Notes     : None
'
Proc Enc_Setup()
    Input Enc_Pin1                  ' \ Make sure the encoder pins are inputs
    Input Enc_Pin2                  ' /
' Pull ups not needed on the Microstick Plus board.   
'   PinPullup Enc_Pin1              ' \ Enable the internal pullup resistors on the encoder pins
'   PinPullup Enc_Pin2              ' /
    Enc_bValidValue = 0             ' Reset the valid value for the encoder pins
    Enc_bStore = 0                  ' Reset the stored value for the encoder pins
EndProc

I wanted to use it with some other code and decided it needed interrupts and have come unstuck.
I have used PPS to set the pins to external interrupts but I may have got that wrong.
I have added the interrupts but am virtually new to PIC24 so may have them wrong as well.
I could not find if I needed to unlock for PPS but tried both ways and still nothing.
With this code it does not appear to even go to the interrupts.
' ____/\\\\\\\\\_________/\\\\\\\\\\\\__/\\\________/\\\____/\\\\\\\\\_______/\\\\\\\\\\\\\\\______/\\\\\\\____       
'  __/\\\///////\\\_____/\\\//////////__\/\\\_______\/\\\__/\\\///////\\\____\/\\\///////////_____/\\\/////\\\__       
'   _\/\\\_____\/\\\____/\\\_____________\//\\\______/\\\__\///______\//\\\___\/\\\_______________/\\\____\//\\\_     
'    _\/\\\\\\\\\\\/____\/\\\____/\\\\\\\__\//\\\____/\\\_____________/\\\/____\/\\\\\\\\\\\\_____\/\\\_____\/\\\_     
'     _\/\\\//////\\\____\/\\\___\/////\\\___\//\\\__/\\\___________/\\\//______\////////////\\\___\/\\\_____\/\\\_   
'      _\/\\\____\//\\\___\/\\\_______\/\\\____\//\\\/\\\_________/\\\//____________________\//\\\__\/\\\_____\/\\\_   
'       _\/\\\_____\//\\\__\/\\\_______\/\\\_____\//\\\\\________/\\\/____________/\\\________\/\\\__\//\\\____/\\\__ 
'        _\/\\\______\//\\\_\//\\\\\\\\\\\\/_______\//\\\________/\\\\\\\\\\\\\\\_\//\\\\\\\\\\\\\/____\///\\\\\\\/___
'         _\///________\///___\////////////__________\///________\///////////////___\/////////////________\///////_____

Device = 24HJ128GP502
Declare Xtal = 79.23
TRISA = 00000000000000
TRISB = 00000000000000
' Configure for internal 7.37MHz oscillator with PLL
' OSC pins are general purpose I/O
'
    Config FBS = BWRP_WRPROTECT_OFF, BSS_NO_FLASH, BSS_NO_BOOT_CODE
    Config FSS = SWRP_WRPROTECT_OFF, SSS_NO_FLASH, RSS_NO_SEC_RAM
    Config FGS = GWRP_OFF, GCP_OFF
    Config FOSCSEL = FNOSC_FRCPLL, IESO_OFF
    Config FOSC = POSCMD_NONE, OSCIOFNC_ON, IOL1WAY_OFF, FCKSM_CSDCMD
    Config FWDT = WDTPOST_PS256, WINDIS_OFF, FWDTEN_OFF
    Config FPOR = FPWRT_PWR128, ALTI2C_OFF
    Config FICD = ICS_PGD1, JTAGEN_OFF
   
PLL_Setup(43, 2, 2, $0300)                          ' Configure the Oscillator to operate the device at 79.23MHz

'------------------------------------------------
' USART1 declares
' Defult settings for Microstick Plus board
    Declare Hserial_Baud = 19200     
         
    Declare HRSOut1_Pin = PORTB.10           ' Select which pin is to be used for TX with USART1   
    PPS_Output(cOut_Pin_RP10, cOut_Fn_U1TX)  ' Make Pin RB10 U1TX

    Declare HRSIn1_Pin = PORTB.11            ' Select which pin is to be used for RX with USART1   
    PPS_Input(cIn_Pin_RP11, cIn_Fn_U1RX)     ' Make Pin RB11 U1RX
   
   
' Set the encoder pins to external interrupts
    PPS_UnLock()   
    PPS_Input(cIn_Pin_RP6, cIn_Fn_INT1)     ' Make Pin RB6 Ext Interrupt 1
    PPS_Input(cIn_Pin_RP7, cIn_Fn_INT2)     ' Make Pin RB7 Ext Interrupt 2
    PPS_Lock()

' Rotary encoder reader using a bit-table decode mechanism
'
' Written by Les Johnson for the Positron8 BASIC compiler
'
 
    Symbol Enc_Pin1 = PORTB.6                   ' Connects to a pin on the rotary encoder
    Symbol Enc_Pin2 = PORTB.7                   ' Connects to the other pin on the rotary encoder
'
' Create some global variables for the rotary encoder read procedure
'
    Dim Enc_bValidValue As Byte                 ' Holds the previous valid reading from the rotary encoder
    Dim Enc_bStore As Byte                      ' Stores the previous manipulated value from the rotary encoder
    Dim Enc_wTable As Word = %0110100110010110  ' Holds the bit table for valid moves of the rotary encoder
'
' Create some variables for the demo
'
    Dim wCounter As SWord = 0
    Dim bEncValue As SByte

    Dim PosChanged As Byte                  ' For debugging

ISR_Start INT1Interrupt
    bEncValue = Enc_Read()                  ' Read the rotary encoder
        HRSOut "Int 1  "
    PosChanged = 1
    INTCON2bits_INT1EP = 0
ISR_End

ISR_Start INT2Interrupt
    bEncValue = Enc_Read()                  ' Read the rotary encoder
        HRSOut "Int 2  "
    PosChanged = 1
        INTCON2bits_INT2EP = 0
ISR_End

'---------------------------------------------------
' The main program starts here
' Read a rotary encoder and increment or decrement a variable depending on the direction of the rotation
' The value and the direction are transmitted to a serial terminal
'
Main:
    Enc_Setup()                                 ' Setup the program and the pins for the rotary encoder reading

    Do                                          ' Create a loop
   
    If PosChanged = 1 Then
    HRSOut "Pos changed  "                      ' For debugging
   
'        bEncValue = Enc_Read()                  ' Read the rotary encoder
        If bEncValue <> 0 Then                  ' Is the value read from it 0?
            wCounter = wCounter + bEncValue     ' No. So add the value to wCounter
            If bEncValue < 0 Then               ' Was the value read -1?
                HRSOut "CCW: "                  ' Yes. So display that is was counter-clockwise
            Else                                ' Otherwise... The value read was 1. So...
                HRSOut "CW:  "                  ' Display that is was clockwise
            EndIf
            HRSOutLn SDec wCounter              ' Display the count value on the serial terminal
        EndIf
       
        PosChanged = 0
        EndIf
    Loop                                        ' Do it forever

'---------------------------------------------------
' Read a rotary encoder
' Input     : Enc_Pin1 and Enc_Pin2 hold the pins used for the encoder
' Output    : A valid Clockwise or Anti-Clockwise move returns 1 or -1, an invalid move returns 0
' Notes     : None
'
Proc Enc_Read(), SByte   
    Result = 0                                      ' Default to a 0 return value
    Enc_bValidValue = Enc_bValidValue << 2          ' \
    Enc_bValidValue.0 = Enc_Pin1                    ' |
    Enc_bValidValue.1 = Enc_Pin2                    ' | Find the position of the encoder's pins
    Enc_bValidValue = Enc_bValidValue & %00001111   ' /

    If GetBit Enc_wTable, Enc_bValidValue <> 0 Then ' Is the move possibly valid?
        Enc_bStore = Enc_bStore << 4                ' Yes. So shift up by 4-bits
        Enc_bStore = Enc_bStore | Enc_bValidValue   ' Or in the pin positions
        If Enc_bStore = %00101011 Then              ' Is the encoder moving Anti-Clockwise?
            Result = -1                             ' Yes. So return a value of -1
        ElseIf Enc_bStore = %00010111 Then          ' Is the encoder moving Clockwise?
            Result = 1                              ' Yes. So return a value of 1
        EndIf
    EndIf
EndProc

'---------------------------------------------------
' Setup the pins and variables to read a rotary encoder
' Input     : None
' Output    : None
' Notes     : None
'
Proc Enc_Setup()
    Input Enc_Pin1                  ' \ Make sure the encoder pins are inputs
    Input Enc_Pin2                  ' /
' Pull ups not needed on the Microstick Plus board.   
'   PinPullup Enc_Pin1              ' \ Enable the internal pullup resistors on the encoder pins
'   PinPullup Enc_Pin2              ' /
    Enc_bValidValue = 0             ' Reset the valid value for the encoder pins
    Enc_bStore = 0                  ' Reset the stored value for the encoder pins
EndProc

Hopefully it is something pretty basic.

Regards,
Bob