+ Reply to Thread
Results 1 to 9 of 9
  1. #1

    Default LCD displays, rotary encoders, and the WRITE statement

    I'm having trouble using incremental rotary encoders with an LCD display and using the WRITE command together. The first problem was getting the rotary encoders to work well and read out on the LCD. I found that for the LCD screen to display clearly, it needs a small pause each time the screen is cleared and updated. Unfortunately, adding this pause made the encoders not work well. They seem to not want any pause or debounce at all. I found that if I use an interrupt for the LCD display code and have the rotary encoder code in the main code it works great. However, after resolving that and moving on to the next phase, I'm finding that the WRITE statment doesn't work.

    I have added DEFINE WRITE_INT 1 and this did not help.

    I wrote an alternate version of the code that does not use the interrupt and the READ/WRITE statements works fine, so I think I'm using it correctly....it's just that the encoders don't work very well.

    Is there something else I should be doing besides the DEFINE WRITE_INT 1? Is there some trick to getting encoders to work with an LCD without using an interrupt?

  2. #2
    Join Date
    Mar 2003
    Location
    Commerce Michigan USA
    Posts
    1,057

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    You do realize that the WRITE statement is writing to EEPROM and each time it is executed there is a up to 10Ms. delay in the writing process. DEFINE WRITE_INT 1 is to be used when there are active interrupts in your source code. It allows for the command to complete before executing the next statement. I have to ask, why are you writing to eeprom during your rotary encoder decoding?
    Last edited by Dave; - 16th March 2018 at 11:41.
    Dave Purola,
    N8NTA
    EN82fn

  3. #3
    Join Date
    Apr 2014
    Location
    Northeast
    Posts
    180

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    Create a variable to count each time you loop through your Main segment. Only display to the LCD when your counter reaches 50 (or whatever). This way it will just skip the LCD write 49 times, giving it the needed display time for visibility.

  4. #4

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    I used mpgmike's suggestion and added a 200ms counter for the LCD display. The read or write (i'm not sure which one) statement still isn't working correctly. I was wrong before when I said it worked when I removed the interrupt. After fiddling with it some more, I realized it doesn't work correctly. So I'm not sure what I'm doing wrong. Hopefully it's something obvious. Here's what's going on:

    I'm using a PIC16F887. I have an LCD display connected. There are also 3 incremental rotary encoders connected. Each of the rotary encoders also has a pushbutton switch. I want to display each rotary encoder's "position" of 0 - 255 on the LCD. This is part is working.

    I want to be able to save and recall the settings of the rotary encoders. I am using the button on encoder2 as a "save" button. I'm using the button on encoder1 to move backwards through the saved settings and the button on encoder3 to move forward through the saved settings. This is the part that is not working. I'm not sure if it isn't writing correctly or isn't reading correctly...well...I'm sure it's doing what it's supposed to do correctly, I just did something wrong.

    Code:
    CLEAR
    define LOADER_USED 1
    define OSC 4
    define LCD_DREG PORTD
    define LCD_DBIT 0
    define LCD_RSREG PORTE
    define LCD_RSBIT 0
    define LCD_EREG PORTE
    define LCD_EBIT 1
    define LCD_RWREG PORTE
    define LCD_RWBIT 2
    define LCD_BITS 4
    define LCD_LINES 4
    define LCD_COMMANDUS 2000
    define LCD_DATAUS 50
    
    
    
    
    ANSEL = %00000000
    ANSELH = %00000000
    TRISD = %00000000
    TRISE = %00000000
    
    TRISB = %11111111
    TRISC = %10000000
    
    encoder1_counter var byte
    encoder1_LastStateA var bit
    encoder1_StateA var bit
    encoder2_counter var byte
    encoder2_LastStateA var bit
    encoder2_StateA var bit
    encoder3_counter var byte
    encoder3_LastStateA var bit
    encoder3_StateA var bit
    preset_counter var byte
    saved_counter var byte
    display_counter var byte
    encoder1_pinA var PORTB.7
    encoder1_pinB var PORTB.6
    encoder2_pinA var PORTB.5
    encoder2_pinB var PORTB.4
    encoder3_pinA var PORTB.3
    encoder3_pinB var PORTB.2
    button1 var PORTB.1
    button2 var PORTB.0
    button3 var PORTC.7
    
    encoder1_preset var byte
    encoder2_preset var byte
    encoder3_preset var byte
    
    encoder1_counter = 50
    encoder2_counter = 50
    encoder3_counter = 50
    preset_counter = 1
    display_counter = 0
    saved_counter = 0
    encoder1_LastStateA = encoder1_pinA
    encoder2_LastStateA = encoder2_pinA
    encoder3_LastStateA = encoder3_pinA
    
    pause 500
    
    '=====================MAIN LOOP TO READ INCREMENTAL ROTARY ENCODERS========================
    mainloop:   
        
        encoder1_StateA = encoder1_pinA                                 ' read first encoder
        if encoder1_StateA != encoder1_LastStateA then
            if encoder1_pinB != encoder1_StateA then
                encoder1_counter = encoder1_counter + 1
            else 
                encoder1_counter = encoder1_counter - 1               
            endif
            encoder1_LastStateA = encoder1_StateA
       endif
       
       encoder2_StateA = encoder2_pinA                                  ' read second encoder
        if encoder2_StateA != encoder2_LastStateA then
            if encoder2_pinB != encoder2_StateA then
                encoder2_counter = encoder2_counter + 1
            else 
                encoder2_counter = encoder2_counter - 1               
            endif
            encoder2_LastStateA = encoder2_StateA
       endif
       
       encoder3_StateA = encoder3_pinA                                  ' read third encoder
        if encoder3_StateA != encoder3_LastStateA then
            if encoder3_pinB != encoder3_StateA then
                encoder3_counter = encoder3_counter + 1
            else 
                encoder3_counter = encoder3_counter - 1               
            endif
            encoder3_LastStateA = encoder3_StateA
       endif
       
     '=====================MAIN LOOP TO RECOGNIZE BUTTON PRESSES==============================  
       
       if button1 = 0 then                                  'when preset down button on encoder1 is pressed
            preset_counter = preset_counter - 1
            gosub read_preset
            pause 25
            do until button1 = 1                            ' debounce
                pause 25
            loop
            pause 25        
       endif
       
       if button2 = 0 then                                  'when save button on encoder2 is pressed
           gosub save_preset
            pause 25
            do until button1 = 1                            ' debounce
                pause 25
            loop
            pause 25
       endif
       
       if button3 = 0 then                                  'when preset up button on encoder3 is pressed
            preset_counter = preset_counter + 1
            gosub read_preset
            pause 25
            do until button3 = 1                            'debounce
                pause 25
            loop
            pause 25
       endif
       
       display_counter = display_counter + 1                '200ms delay between LCD updates
       pause 1
       if display_counter >= 200 then
            gosub display
            display_counter = 0
       endif
       
    goto mainloop
    end 
    
    read_preset:                                                    ' read presets from EEPROM and change values for encoder positions
    
        read preset_counter, encoder1_preset, encoder2_preset, encoder3_preset
        pause 25
        encoder1_counter = encoder1_preset
        encoder2_counter = encoder2_preset
        encoder3_counter = encoder3_preset
    
    return
    
    save_preset:                                                    'save encoder positions to EEPROM and display "saved" message
        
        lcdout $fe, 1
        lcdout $fe, $c0, "     PRESET ", dec2 preset_counter
        lcdout $fe, $94, "       SAVED"
        write preset_counter, encoder1_counter, encoder2_counter, encoder3_counter
        pause 1500
    
    return 
    
    
    display:                                                           ' LCD display text
            lcdout $fe, 1
            
            lcdout $fe, $80, "*****PRESET ", dec2 preset_counter, "******"
        
            lcdout $fe, $94 + 1, "NCDR1"
            lcdout $fe, $d4 + , dec encoder1_counter
        
            lcdout $fe, $94 + 8, "NCDR2"
            lcdout $fe, $d4 + 9, dec encoder2_counter
        
            lcdout $fe, $94 + 14, "NCDR3"
            lcdout $fe, $d4 + 15, dec encoder3_counter
    return

  5. #5

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    Quote Originally Posted by Dave View Post
    You do realize that the WRITE statement is writing to EEPROM and each time it is executed there is a up to 10Ms. delay in the writing process. DEFINE WRITE_INT 1 is to be used when there are active interrupts in your source code. It allows for the command to complete before executing the next statement. I have to ask, why are you writing to eeprom during your rotary encoder decoding?
    I want to save the settings on the rotary encoders and be able to recall them as presets. I posted the code for the project.

  6. #6

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    write preset_counter, encoder1_counter, encoder2_counter, encoder3_counter
    Each time you write you're writing three bytes of data, but you're only incrementing the address (preset_counter) by one.
    The next time you write you'll be overwriting part of the previously saved data.

    When you go to write/read, multiply preset_counter by 4 and use that as the address so the three bytes are preserved.
    Make sure preset_counter is never more than 255/4 or the address will wrap since it's a byte value.

  7. #7

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    Yes! That fixed it. I didn't realize that each data space had its own address. I thought everything in the statement was stored at the designated address.

    write 4, 1, 2, 3

    So 1 is stored at address 4, 2 is stored at address 5, and 3 is stored at address 6? And then if I want to write something else, it would have to be "write 7, 4, 5, 6" if I didn't want to overwrite the other data? Is that how it works?

  8. #8

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    Basically, yes, as long as you're talking about bytes.

    EEPROM is byte-addressable, and each byte has its own address. Muti-byte variables like words and longs take multiple bytes (addresses) for each value.

  9. #9

    Default Re: LCD displays, rotary encoders, and the WRITE statement

    Thanks so much!

Similar Threads

  1. Replies: 10
    Last Post: - 29th June 2010, 20:58
  2. 2 LCD Displays, one Pic
    By Art in forum General
    Replies: 10
    Last Post: - 10th April 2010, 13:56
  3. Rotary encoders
    By mister_e in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 21st February 2007, 16:57
  4. LCD Displays
    By Roland in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 16th August 2005, 09:43
  5. Melanie's LCD displays
    By BobK in forum Adverts
    Replies: 1
    Last Post: - 24th October 2004, 11:27

Members who have read this thread : 22

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