Display values from two PIC16F series controllers with one LCD display


Closed Thread
Results 1 to 10 of 10
  1. #1
    Join Date
    Mar 2017
    Posts
    3

    Default Display values from two PIC16F series controllers with one LCD display

    Has anyone ever attempted to display outputs of two PIC16F series controllers to one LCD display? I'm looking for a way to interface two PIC16F76 controllers that output the position of a Quadrature encoder (two axes values).
    I'm using a 2x16 LCD and would like to display each axes per line. The outputs are simply a 2 decimal place angular value such as 35.25. I though maybe connecting the data and control lines from one controller to another and have the second process to the display. Any ideas how can accomplish this?

    Thanks in advance...

    Chris

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    Assuming you connect the data lines together and the control signals together, you still need a way to arbitrate access to the common resource (the LCD). Therefore one extra handshake line from each cpu to the other should be enough to indicate ownership of the resource and thus be able to arbitrate control effectively. Never done this before, but, this could be a way forward.

  3. #3
    Join Date
    Sep 2009
    Posts
    737


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    For me, that is wrong way forward....
    Just use some serial protocol to transfer data from one to other pic, and then display all data to LCD.
    This will use less resource, hardware and software. If you have interrupts, then use I2C like protocol.

  4. #4
    Join Date
    Mar 2017
    Posts
    3


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    I know this can be done without using I2C protocol. I found a device that uses two PICs with one LCD just don't know how it's done in software.
    Lets call the PIC connected to the LCD the slave and other master

    I see that pins RB0-RB3 are connected from slave PIC to the master(the only interconnections) and RA0-RA3 pins of slave are connected to data lines of LCD. Additionally, the slave PIC uses all three control lines (RW, E, RS). Maybe using enable pin to multiplex data from both PICs? I'm sure there are many cases when using multiple PICs with a single display would be desirable. I really don't want to dedicate two LCD displays for each axes.

    I appreciate the responses so far.

    Chris

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    You could have a simple one-wire bus between the PICs that would "request the bus", which would change the TRIS bits from inputs to outputs and vice-versa for both?

  6. #6
    Join Date
    Sep 2009
    Posts
    737


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    If two pics share RW,E and RS line, then E pin of master pic(master is connected to DATA LCD pins), enables slave with E=0 and disables LCD. So pic could talk with each other using synchronous comm, or async. Eg I2C, or like, half of SPI etc, or Tx and Rx for async. When master want to free comm, just send dome break signal, or on transition from 0 to 1 on E pin slave pic just relist RW and RS pins by setting them to inputs.
    And I don't see why is I2C problem?
    It simple, robust protocol that can be done on that 3 pins. Most LCD have pull up on all pin, so it is very well suited for that task.

  7. #7
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    Having two controllers connected to the LCD sounds horrible in both software and hardware.
    The two controllers would have to be able to talk to each other anyway, to make sure both don’t talk to the LCD at the same time.
    So long as you have to connect pins between the controllers, why not just send information from one controller to the other serially?

    I would go for making both programs identical, both outputting to the LCD pins, but neither assuming the LCD is connected,
    and both programs listening on a serial port for information from another chip.
    Then maybe one flag set at compile time to set which has the LCD.
    That’s if I were in that position, which wouldn’t happen because one chip would be watching both rotary encoders

  8. #8
    Join Date
    Mar 2017
    Posts
    3


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    Art -

    I completely agree with your assessment. Interfacing two channels of quadrature input is what I would prefer to do, however, I had huge issues just getting one to work reliably and fast! The current code interprets the quadrature signal (360 CPR) using ASM coded interrupt within PBP3 and it doesn't miss a beat! I was looking at another manufactures device and they actually do use two separate PICs with one LCD as I described in my original post. I agree this is a poor way to handle two inputs but after struggling for a couple of months with the existing code, I'm looking for whatever works at this point. I have to admit that the limitations I have are no more than my inexperience with PIC coding so far.

    The code I use is similar to this:
    Code:
    'Read Quadrature Encoder and display value on LCD in .25 increments. for pic16f76
    
     '************************ DEFINES HERE *************************************
     DEFINE OSC 20 ' set to 20mhz
     DEFINE LCD_DREG PORTA ' Set Data Registers port
     DEFINE LCD_DBIT 0 ' Set starting data bit
     DEFINE LCD_RSREG PORTB ' Set LCD RS Port
     DEFINE LCD_RSBIT 1 ' Set LCD RS Bit
     DEFINE LCD_EREG PORTB ' Set LCD Enable Port
     DEFINE LCD_EBIT 2 ' Set LCD Enable Bit
     DEFINE LCD_BITS 4 ' Set LCD 4bit Mode
     DEFINE LCD_LINES 2 ' Set number of LCD Lines
     DEFINE LCD_COMMANDUS 2000 ' Set Command Delay time in uS
     DEFINE LCD_DATAUS 60 ' Set Data delay time in uS 
    
     clear 'clear out variables
    
     '*********************** CHIP REGISTER SETUP *******************************
    
     ADCON0 = 7 ' turn off analog porta, set to digital IO
     ADCON1 = 7 '
     CCP1CON = 0
     CCP2CON = 0
     
     TRISA = %00000000 ' output ports
     TRISB = %11000000 ' set input and output ports
     TRISC = %00100000 ' output ports
      
     portB.4 = 0
     portB.5 = 0
     
     '************************ PROGRAM VARIABLES HERE ***************************
    
     symbol   ledUp     = portC.2 ' status led
     symbol   ledDown = portC.3 ' status led2
     symbol   lcdbkl     = portC.4 ' lcd pannel backlight
     symbol   sw1        = portC.5 ' encoder switch
     symbol   ledTest   = portC.6
     
    
     enc_old                VAR BYTE
     enc_new              VAR BYTE
     enc_tmp              VAR byte
     enc_counter         VAR word bank0
     enc_counter_old   VAR word bank0
     enc_scaler            VAR word
     enc_dir                VAR enc_old.bit7
     Counter               VAR word bank0
     enc_SIGN            VAR counter.bit15
     Sign                    VAR BIT
    
    
     '*********************** ASSEMBLY INTERUPT VARIABLES ***********************
     wsave     VAR  byte $20 system
     wsave1   VAR  byte $a0 system ' Necessary for devices with RAM in bank1
     wsave2   VAR  byte $120 system ' Necessary for devices with RAM in bank2
     wsave3   VAR  byte $1a0 system ' Necessary for devices with RAM in bank3
     ssave     VAR  byte bank0 system
     psave     VAR  byte bank0 system 
    
     goto start 'skip over interupt handler
     '*********************** ASSEMBLY INTERUPT HANDLER *************************
    
     define INTHAND myint
     Asm
    
    myint 
     ; Save W, STATUS and PCLATH registers
     movwf wsave
     swapf STATUS, W
     clrf STATUS
     movwf ssave
     movf PCLATH, W
     ;movwf psave 
     CLRF PCLATH
    
    
     ;====== BEGINNING OF THE ROTARY ENCODER CODE ========
     ;The Rotary Encoder is connected to PORTB 
     ;The A signal of the encoder connected to the PIN portB.7
     ;The B signal of the encoder connected to the PIN portB.6
     ;
     ;The 4 variables used are declared in the PicBasic code.
     ;
     ; enc_new VAR BYTE
     ; enc_old VAR BYTE
     ; enc_tmp VAR BYTE
     ; enc_counter VAR WORD
     ;
     ;================================================
    
     ;Read latest input from PORTB & put the value in _enc_new.
     movf PORTB,W
     movwf _enc_new
    
     ;Strip off all but the 2 MSBs in _enc_new.
     movlw 0xc0 ;Create bit mask (bits 7 & 6). b'11000000' ?
     andwf _enc_new,F ;Zero bits 5 thru 0.
    
        ;Check to see if encoder has moved
            movf    _enc_old,W         ;move enc_old to W
            movwf   _enc_tmp           ;put W to enc_tmp
            movf    _enc_new,W         ;move enc_new to W for XOR
            xorwf   _enc_tmp,F         ;XOR enc_tmp to detect encoder movement
            btfsc   STATUS,Z           ;if result is not zero, encoder moved.      
            goto    Continue           ;no movement exit isr
    
     ;Determine the direction of the Rotary encoder. 
     rlf _enc_old,F ;left shift it into _enc_old to align bit 6 of _enc_old with bit 7 of _enc_new.
    
     movf _enc_new,W ;Move the contents of _enc_new to W in order to XOR.
     xorwf _enc_old,F ;XOR previous inputs (in _enc_old) with latest
     ;inputs (in W) to determine CW or CCW.
    
     btfsc _enc_old,7 ;Test bit 7 of result (in _enc_old). Skip next line
     ;if it is 0 (direction is CCW).
     goto Up ;Bit is 1 (direction is CW). Go around Down and increment counter.
    
    Down
     ;Decrements _enc_counter because the rotary encoder moved CCW.
     ;Decrements _enc_counter (16 bit value), sets Z on exit.
    
     decf _enc_counter,F ; Decrement low byte
     incfsz _enc_counter,W ; Check for underflow
     incf _enc_counter+1,F ; Update
     decf _enc_counter+1,F ; Fixup
     movf _enc_counter,W
     iorwf _enc_counter+1,W ; Set Z bit
    
    
     ;Add here code for the CCW LED if needed.
     bsf _ledDown ;turn on led
    
     goto Continue ;Branch around UP.
    
    Up
     ;Increments _enc_counter because the rotary encoder moved CW.
     ;Increments _enc_counter (16 bit value), sets Z on exit.
    
     incfsz _enc_counter,W ; Add one to low byte
     decf _enc_counter+1,F ; No carry (negates next step)
     incf _enc_counter+1,F ; Add one to high byte
     movwf _enc_counter ; Store updated low byte back.
     iorwf _enc_counter+1,W ; Set Z flag
    
    
     ;Add here code for the CW LED if needed.
     bsf _ledUp ;turn on led
    
    Continue 
     ;Assign the latest encoder inputs (in _enc_new) to _enc_old.
     movf _enc_new,W
     movwf _enc_old
    
     ; Restore saved registers
     movf  psave, W
     movwf PCLATH
     swapf ssave, W
     movwf STATUS
     swapf wsave, F
     swapf wsave, W
     bcf INTCON, RBIF ; Clear the Interupt Flag
     RETFIE ; Return from interrupt
     endasm
    
     '************************************************* **************************
     '************************* PROGRAM STARTS HERE *****************************
     '************************************************* **************************
    
     START: ' Main Program starts here
     INTCON = %10001000 ' Enable PortB Change Interupts 
     LCDOUT $FE,1 'Init The LCD
     pause 500 'wait for LCD to start 
    
     lcdout $FE,$80,  "TEST ANGLE DISP " 'display splash screen
     LCDOUT $FE,$C0,  "Initializing... " 
     high lcdbkl ' turn on backlight
    
    
     '************************** SET DEFAULT SETTINGS HERE **********************
     pause 2000 ' just wait a bit to read splash screen
     lcdout $FE,1
     enc_counter = 0 ' set default encoder value
     enc_counter_old = 0 
     Counter = 0
     
     
     lcdout $FE,$80, "Measurement   "
     lcdout $FE,$C0,"TST ANGLE: "
    
    
     '************************** TESTING ROUTINES HERE **************************
     test:
       If portC.5 = 0 then clearall
       
    if enc_counter <> enc_counter_old then 'see if value has changed
        enc_counter_old = enc_counter 'move new value to old
            Counter = enc_counter '(enc_counter */ 250)/2
            Sign = Counter.15   ' Save sign
            Counter = ((ABS Counter) * 25) ' Degrees is now 0 to 900
            
    
    If Sign THEN Counter = -Counter ' Restore sign, value is now -900 to 900
    
    
    If not sign AND (-Counter < 0 or Counter > 0) then
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", "-",sdec Counter /100 , ".", sdec Counter // 100, " " 
    else
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", " ", sdec -Counter /100 , ".", sdec -Counter // 100, " "
    endif 
    
     
     low ledUp 'turn off CCW led
     low ledDown 'turn off CW led
     endif
     
     goto test
    
     ClearAll:
     
        enc_counter = 0
        enc_counter_old = 0 
        Counter = 0
        clear
        lcdout $FE,$80, "Measurement   "
        lcdout $FE,$C0,"TST ANGLE:", " 0.00 "
            high ledtest
                pause 1000
            low ledtest
     goto test
     
    @INT_RETURN
    Last edited by CBRUN17; - 24th March 2017 at 18:05.

  9. #9
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    I’ll put it to you this way, I don’t think you have any choice but to communicate between the two controllers in some fashion
    If any one controller prints the entire display of both values, then one value has to be communicated from one controller to the other.

    If you want both values displayed on the LCD at the same time, the only way to achieve that without one controller knowing what the other is thinking,
    is to print half of the display with one controller, and the other half of the display with the other, but to do that, to some extent,
    one controller still has to know what the other is thinking at the very least so they don’t try to print a the same time.

    To do that you only need to use the shared LCD Enable pin.
    Whenever a controller is not printing, the Enable pin is an input listening for highs on the Enable pin from the other controller.
    Whenever a controller wants to print, so long as the enable has not been held high by the other controller for a duration
    it can go ahead and print it’s line, by setting the Enable pin output, then high, then set the rest of the LCD data/control pins,
    then send Enable low to latch the LCD data, and continue till the line is printed, then set Enable as an input again.

    If one controller wants to print, but notices the other is printing because the Enable pin has been set high by the other controller
    within a duration (the duration being a little longer than it takes to print a line to the LCD), it simply waits until the Enable pin
    has been low for the duration before having a go at printing it’s data. That way neither controller is a master or a slave,
    so long as each leaves a significant delay because there’s an awareness that it’s no the only controller trying to use the LCD.
    At least that’s first way I wouldn’t go about not doing any of that.

    This all assumes that the LCD data latches on the transition of the Enable pin from high to low,
    and it’s the transition from low to high that is ignored (which is the way I remember it),
    but I’m writing for a library currently, and haven’t had to deal with that for some time.

  10. #10
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,585


    Did you find this post helpful? Yes | No

    Default Re: Display values from two PIC16F series controllers with one LCD display

    I'd keep things simple: 1 master to drive the LCD, 2 slaves to process your axis data.

    Easier to develop and debug.

    Robert
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

Similar Threads

  1. Trouble with LCD 2x8 and sequential display of values
    By fratello in forum mel PIC BASIC Pro
    Replies: 30
    Last Post: - 27th February 2012, 15:51
  2. LCD Display
    By lambert in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 16th January 2010, 23:18
  3. Replies: 2
    Last Post: - 5th November 2009, 18:07
  4. glcd display vs lcd display
    By davids in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 3rd July 2009, 19:16
  5. LCD Display - Which One
    By Switch in forum General
    Replies: 1
    Last Post: - 21st January 2009, 23:44

Members who have read this thread : 2

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