Reading incremental encoder


Closed Thread
Results 1 to 8 of 8
  1. #1
    Join Date
    Apr 2016
    Posts
    1

    Default Reading incremental encoder

    Hi all,
    For a university project I have written a PICBASIC code to read digital signals from the encoder on my MCU and send them to both another MCU (to graphically plot the result on PC via Python) and to an LCD screen (for debugging). Now, since i'm completely new to picbasic i have no idea whether my code will work. Since we have limited time to actually work with the hardware, we have to make sure the software is carefully prepared beforehand. That's why i would kindly ask some of you guys, with a lot more experience, to look through my code and make me aware of certain mistakes.
    The MCU i'm using is PIC12F683 (datasheet: http://akizukidenshi.com/download/ds/microchip/pic12f683.pdf). It's an 8 pin MCU.
    The encoder output (which is the MCU input) exists out of 2 square waves, which are the same but shifted 90° in phase (to check which way the encoder is turning).
    What i want to get as output is a 3 digit number, because that is what to next MCU requires as input. So i wanted to take number 0 to 499 for clockwise turning and 501 to 999 for counterclockwise turning.
    I'm pretty convinced the idea behind my method is correct, but i have no idea whether i have written it all in a correct way, without too many syntax errors.
    Here's what i've written so far, i hope i did a decent job of explaining what i want to achieve, if not you can always ask me.
    It would be great if some people with actual PICBASIC knowledge could help me
    Thanks!

    '************************************************* ***************
    '* Name : RotaryEncoder.BAS *
    '* Author : Robbe Degezelle *
    '* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
    '* : All Rights Reserved *
    '* Date : 12/04/2016 *
    '* Version : 1.0 *
    '* Notes : *
    '* : *
    '************************************************* ***************


    'initialisation------
    NewVal = (GPIO & 000) >> 3
    OldVal = NewVal
    ANSEL = 00000 ' all pins digital
    TRISIO = 1111 'set all ports to inputs
    'Enc_1 VAR GPIO.5 ' first encoder input
    'Enc_2 var GPIO.4 ' second encoder input
    LCD_pin var GPIO.1




    'variables-----------
    NewVal VAR BYTE
    OldVal VAR BYTE
    Counter VAR BYTE
    CounterCC var byte
    Counter = 000
    CounterCC = 500
    word1 var word 'C
    word1=000
    word2 var word 'CC
    word2=000
    P4800 CON 188 '4800 baud true
    N9600 con $4054 '9600 baud rate inverted




    'Program----------------
    Main
    NewVal = (GPIO & 000) >> 3 ; zou 0,1,2 of 3 moeten geven
    If NewVal <> OldVal Then
    Branch CurVal, [S0,S1,S2,S3] ; indien waarde veranderd, vergelijken met oud
    EndIF
    AfterBranch
    Goto Main


    S0
    If OldVal = 2 Then
    GoSub Clockwise
    ELSE
    GoSub CounterClockwise
    EndIF
    Goto AfterBranch

    S1
    if OldVal = 0 Then
    GoSub Clockwise
    ELSE
    GoSub CounterClockwise
    EndIF
    Goto AfterBranch

    S2
    if OldVal = 3 Then
    GoSub Clockwise
    Else
    GoSub CounterClockwise
    EndIf
    Goto AfterBranch

    S3
    if OldVal = 1 Then
    GoSub Clockwise
    Else
    GoSUb CounterClockwise
    Endif
    Goto AfterBranch



    Clockwise
    OldVal = CurVal
    Counter = Counter + 1
    word1 = Counter
    serout2 GPIO.0,p4800, ["B1", DEC3 word1]
    gosub disp_lcd
    Return

    CounterClockwise
    OldVal = CurVal
    CounterCC = CounterCC + 1
    word2 = CounterCC
    serout2 GPIO.0,p4800, ["B1", DEC3 word2]
    gosub disp_lcd
    return


    'LCD
    disp_lcd
    serout2 LCD_pin, N9600, [$FE, 1$] 'clear display
    pause 1
    serout2 LCD_pin, N9600, [$FE, 2$] 'cursor returns home
    pause 1
    serout LCD_pin, N9600, ["TellerC= ", DEC Counter]
    pause 1
    SEROUT2 LCD_pin,N9600, [$FE, $C0] 'cursor to 2nd line
    pause 1
    SEROUT2 LCD,N9600, ["TellerCC= ", dec CounterCC]
    return


    end

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    You have limited time to work with the hardware and you don't have time to even compile the code to see if there are any syntax errors and you want us to check for it you. Is that it? OK, here are a couple of things I noticed:

    CounterCC is declared as a BYTE but you're trying to squeeze a value of 500 into it.
    There are no colons after LABELS.
    There are no % signs where your expressing your numbers in binary.
    You're reading the state of the IO pins into NewVAL but you're using CurVal in the BRANCH statement.
    Provided the decoding logic is correct (which I haven't checked) it's not going to keep up with a turning encoder since all the SEROUT statements will take tens or even hundreds of ms each time - that may not matter, I don't know - just pointing it out.

    When posting code in the forum, please use code-tags.

    /Henrik.

  3. #3
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    Well it fails to compile, and I presume that you are using PBP2.6x rather than 3.x



    To be honest, you will learn a lot more, and gain a better understanding by actually downloading the relevant software such as micro code studio, mplab etc and debug the code until it compiles without errors. You don't need the physical hardware as at this stage all you want to do is to know if the code has no errors. But, having said that, the only real way you will know if the project functions correctly is to either use an expensive simulator that runs the hex code, or get a solderless breadboard and build the circuit and debug both hardware and software at the same time

  4. #4
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    Quote Originally Posted by HenrikOlsson View Post
    You have limited time to work with the hardware and you don't have time to even compile the code to see if there are any syntax errors

    /Henrik.
    You beat me to it...

  5. #5
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    Code:
    'LCD
    disp_lcd
    serout2 LCD_pin, N9600, [$FE, 1$] 'clear display
    pause 1
    serout2 LCD_pin, N9600, [$FE, 2$] 'cursor returns home
    pause 1
    serout LCD_pin, N9600, ["TellerC= ", DEC Counter]
    pause 1
    SEROUT2 LCD_pin,N9600, [$FE, $C0] 'cursor to 2nd line
    pause 1
    SEROUT2 LCD,N9600, ["TellerCC= ", dec CounterCC]
    return
    OK you may of got some syntax wrong, but at least check for obvious omissions first !

  6. #6
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    You also need to set the PIC registers and to get reliable 9600 baud rate you need to ensure the PIC is running at 4Mhz as serial out assumes a 4mhz timing base

    From the BPB manual

    SEROUT2 assumes a 4MHz oscillator when generating its bit timing. To maintain the proper baud rate timing rate with other oscillator values, be sure to DEFINE the OSC setting to the new Oscillator value. An oscillator speed faster than 4MHz may be required for reliable operation at 9600 baud and above
    You need to read section 3.5.2 of the datasheet on how to configure the internal oscillator HFINTOSC which is factory calibrated to 8Mhz, The frequency of the HFINTOSC can be altered via software using the OSCTUNE register (see the Register section 3-2).

    The point of mentioning this is that you really need to spend time developing the hardware as well as the software... the two go hand in hand.

    It may seem that we've come down hard on you, but then you must appreciate that the guys here see 100's of posts from new members who ask for help, but don't want to put the effort in from the start. The guys here (Henrik, Tabsoft and Richard to name a few) are very helpful and have lots of coding experience, and it's only fair to have done the ground work first, and then they are only too pleased to help (and I'm talking from experience here)

  7. #7
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    Ok this compiles... but it won't work as there are lots missing from the code, such as the "afterbranch" subroutine hasn't been included (I just gave it a label and return) I've also added some config settings, and a few missing variables...

    Code:
    '************************************************* ***************
    '* Name : RotaryEncoder.BAS *
    '* Author : Robbe Degezelle *
    '* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
    '* : All Rights Reserved *
    '* Date : 12/04/2016 *
    '* Version : 1.0 *
    '* Notes : *
    '* : *
    '************************************************* ***************
    
    
    'initialisation------
    
    
    @ __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BOD_ON 
              ' Internal Oscillator
              ' Enable watch dog timer
              ' Enable power up timer
              ' Disable MCLR pin
              ' Enable brown out detect
    
    
    ANSEL = 0      ' Set all digital
    CMCON0 = 7     ' Analog comparators off
    
    LCD_pin var GPIO.1 
    
    'variables-----------
    NewVal VAR word 
    OldVal VAR word
    Counter VAR word
    CounterCC var word
    word1 var word 'C
    word2 var word 'CC
    
    CurVal var word '  This seemed to be missing from your original code... again I presume it should be a word variable as you have statements like OldVal = CurVal
    
    P4800 CON 188 '4800 baud true
    N9600 con $4054 '9600 baud rate inverted
    
    word2=000
    NewVal = (GPIO & 000) >> 3
    OldVal = NewVal
    Counter = 000
    CounterCC = 500 
    word1=000
    
    'Program----------------
    Main:
    NewVal = (GPIO & 000) >> 3 ; zou 0,1,2 of 3 moeten geven
    If NewVal <> OldVal Then
    Branch CurVal, [S0,S1,S2,S3] ; indien waarde veranderd, vergelijken met oud
    EndIF
    goto AfterBranch
    Goto Main
    
    
    S0:
    If OldVal = 2 Then
    GoSub Clockwise
    ELSE
    GoSub CounterClockwise
    EndIF
    Goto AfterBranch
    
    S1:
    if OldVal = 0 Then
    GoSub Clockwise
    ELSE
    GoSub CounterClockwise
    EndIF
    Goto AfterBranch
    
    S2:
    if OldVal = 3 Then
    GoSub Clockwise
    Else
    GoSub CounterClockwise
    EndIf
    Goto AfterBranch
    
    S3:
    if OldVal = 1 Then
    GoSub Clockwise
    Else
    GoSUb CounterClockwise
    Endif
    Goto AfterBranch
    
    
    
    Clockwise:
    OldVal = CurVal
    Counter = Counter + 1 
    word1 = Counter
    serout2 GPIO.0,p4800, ["B1", DEC3 word1]
    gosub disp_lcd 
    Return 
    
    CounterClockwise:
    OldVal = CurVal
    CounterCC = CounterCC + 1
    word2 = Countercc
    serout2 GPIO.0,p4800, ["B1", DEC3 word2] 
    gosub disp_lcd
    return
    
    
    'LCD
    disp_lcd:
    serout2 LCD_pin, N9600, [$FE, $1] 'clear display
    pause 1
    serout2 LCD_pin, N9600, [$FE, $2] 'cursor returns home
    pause 1
    serout2 LCD_pin, N9600, ["TellerC= ", DEC Counter]
    pause 1
    SEROUT2 LCD_pin,N9600, [$FE, $C0] 'cursor to 2nd line
    pause 1
    SEROUT2 LCD_pin,N9600, ["TellerCC= ", dec CounterCC] ' corrected this line
    return
    
    
    AfterBranch:             ' no idea what afterbranch is meant to do, as you have several goto's afterbranch but there is no such subroutine
    Return
    There may be other coding errors, but the syntax seems OK and like I said this now compiles, but until you add the missing subroutines, and take on board some of the comments Henrik has mentioned it won't work. Also, your post seemed to have good command of the English language, but some of the comments (hi-lighted in green) are in a different language, which makes me wonder if the code is your own work ?

  8. #8


    Did you find this post helpful? Yes | No

    Default Re: Reading incremental encoder

    The most efficient method for an encoder that I've encountered is a "current state/next state" combination of 4 bits that you can use for a lookup function. The result of the lookup defines the action, where a result of 1 could be "increment", 2 could be "decrement", 0 could be "do nothing/not valid". Super slick, minimal code space. Don't forget to allow for debouncing.
    Last edited by picster; - 4th May 2016 at 14:50. Reason: additional note

Similar Threads

  1. Reading incremental encoder interupt
    By RFsolution in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 1st March 2017, 12:50
  2. Using an incremental rotary encoder?
    By keithv in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 12th January 2016, 22:23
  3. Encoder velocity....
    By thasatelliteguy in forum mel PIC BASIC Pro
    Replies: 11
    Last Post: - 21st April 2014, 00:33
  4. Rentron Encoder
    By lerameur in forum mel PIC BASIC Pro
    Replies: 14
    Last Post: - 27th June 2013, 07:28
  5. encoder wowes
    By wallaby in forum mel PIC BASIC Pro
    Replies: 16
    Last Post: - 6th December 2005, 21:56

Members who have read this thread : 1

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