Announcement

Collapse
No announcement yet.

I2C PCF8574 20x4 LCD

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • I2C PCF8574 20x4 LCD

    Hey all,

    PBP3 has wonderful LCD routines but I need to utilize the I2C protocol to save pins.

    I am trying to send data to a 20x4 LCD using the I2C protocol and a PCF8574 module (schematic attached). These are neat little modules that sell for under $2 and turn an LCD into an I2C LCD. My project is going to eventually have a keypad, leds a piezo etc and pins are at a premium.

    I can successfully turn on and off the backlight which means that I am able to talk to the module successfully. I just can't seem to initialize the LCD nor send data to it. The PCF module utilizes the 4bit mode on the LCD which further complicates things.

    Here is what I already know:

    The LCD panel works because I can write to it successfully using your normal LCD routines with 7 wires.

    I can successfully turn on and off the backlight using the PCF8574 which means that I am able to talk to the module (i.e. I have the right I2C address which is $4E).

    I2C lines are pulled up with 4k7 resistors. Contrast has been varied to verify I am not missing the text.

    I have connected the PCF8574 to simple LEDs (cathode connection to PCF, other side to 220 resistors thence to +5V. I seem to be sending the right pattern of commands. Now whether or not I am sending a zero when I should be sending a one is a point of confusion.

    Config: PIC16F886, pickit2, winxp, pbp 3.0.5.1, 20x4 LCD module, PCF8574

    Here is what I think is the problem:

    I am not using the I2C Write command properly. I am confused about the optional address parameter and I am probably getting the command vs data mode messed up when talking to the LCD Panel.

    In 4-bit mode, let's say I want to sent the letter "A" which is $41. Should I send the %0100 first or the %0001 first? In other words:

    LCDData = $41

    LCDNibble = LCDData << 4
    i2cwrite SDA,SCL,LCDAddr,LCDNibble ' enable is 0
    i2cwrite SDA,SCL,LCDAddr,LCDNibble + LCDE ' toggle enable to 1?

    ' Now do the same for the high side

    LCDNibble = LCDData & $0F
    i2cwrite SDA,SCL,LCDAddr,LCDNibble ' enable is 0
    i2cwrite SDA,SCL,LCDAddr,LCDNibble + LCDE ' toggle enable to 1?

    Thanks all.
    John.
    Attached Files

  • #2
    the seq is
    r/w =0 e = 0 rs= 1 data nibble= high 4 bits (rs=1/0 data/cmd)
    then i2c that to lcd
    then set e bit=1
    then i2c that to lcd
    then set ebit =0 data nibble=low 4 bits
    then i2c that to lcd
    then set e bit=1
    then i2c that to lcd
    then set ebit =0
    then i2c that to lcd

    check your lcdinit routine
    it only seems to sent the low nibbles
    I think 4 bit mode is $20
    Last edited by richard; 02-23-2014, 07:21 PM.

    Comment


    • #3
      Geez, those Arduino people think the world revolves around them.
      It's a circuit that can be used with any microcontroller, there's nothing specific to that language.

      But to use the circuit, you need to have the proper sequence.

      With the schematic you supplied, the slave address (control byte) is $40.
      It will only be $4E if you have connected the PCF8574's A0,A1 and A2 to VDD.
      There is no optional address for the PCF8574.

      The E line goes HIGH when sending the nibble the first time.
      The E line then goes low the second time, nothing else changes the second time.
      The HD44780 clocks in the data on the Falling edge of the E clk.

      The HIGH nibble always goes first.
      Except during the initialization, where only one nibble is used at a time until the mode is set to 4-bit.

      Sending one byte at a time can be difficult, if not extremely annoying.
      So the test program below (Test_LCD_PCF8574.pbp) shows how to use the ARRAYWRITE command to compose data derived from a combination of text and any of the DEC, HEX, BIN etc. modifiers.
      There's also an example of using Custom Characters (stick man doing jumping jacks).

      The heart of the program is contained in the include file "LCD_PCF8574.pbp" (attached below).
      Put the include file in your PBP3 folder (the one with PBPX.exe in it).

      Click image for larger version

Name:	LCD_PCF8574.jpg
Views:	2
Size:	84.9 KB
ID:	5235

      I actually didn't notice you posted your code before I wrote mine today.
      The include is not processor specific, so all you need to change is the test program for a different chip.

      Code:
      ; Filename    : Test_LCD_PCF8574.pbp
      ; Author      : Darrel Taylor
      ; Created     : Mon Feb 24 2014
      ; Processor   : PIC12F1822
      ; Compiler    : PicBasic Pro 3.0.6.x or higher
      ; Description : Uses PCF8574 Port expander to interface with HD44780 LCD
      ;
      
      ;----[12F1822 Hardware Configuration]-------------------------------------------
      #CONFIG
        __config  _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
        __config  _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
      #ENDCONFIG
      
      
      ;----[Oscillator Setup]---------------------------------------------------------
      DEFINE OSC 32 
      OSCCON = %11110000
      
      ;----[Aliases]------------------------------------------------------------------
      SDA         VAR PORTA.2       ; I2C Data pin
      SCL         VAR PORTA.1       ; I2C Clock Pin
      
      ;----[Initialize Hardware]------------------------------------------------------
      ANSELA = 0    ; All Digital
      
      ;----[Setup LCD using PCF8574 Port Expander]------------------------------------
      LCD_Addr    CON $40           ; A0, A1, A2 tied to ground
      INCLUDE "LCD_PCF8574.pbp"     ; Include LCD module for PCF8574
      
      ;----[Variables]----------------------------------------------------------------
      LoopCount       VAR BYTE
      CustChar        VAR BYTE
      
      ;----[Program Start]------------------------------------------------------------
      Backlight = 0                 ; Turn on LCD Backlight
      ARRAYWRITE LCD_Buff,["   LCD PCF8574"] : LCD_WriteBuff
      LoopCount= 0
      
      ;----[Custom Characters]-(Jumping Jacks)----------------------------------------
      ARRAYWRITE LCD_Buff,[$FE,$40,$00,$04,$0A,$04,$0E,$15,$0A,$11]:LCD_WriteBuff ' #0  
      ARRAYWRITE LCD_Buff,[$FE,$48,$00,$04,$0A,$04,$1F,$04,$0A,$0A]:LCD_WriteBuff ' #1  
      ARRAYWRITE LCD_Buff,[$FE,$50,$04,$0A,$15,$0E,$04,$0A,$0A,$00]:LCD_WriteBuff ' #2 
      
      ;----[Main Program Loop]--------------------------------------------------------
      Main:
          ARRAYWRITE LCD_Buff,[$FE,$C0,"Count = ",DEC LoopCount,"   "] : LCD_WriteBuff
          PAUSE 200
          LoopCount = LoopCount + 1
      
          CustChar = LoopCount//3   ; Jumping Jacks Sequence
          ARRAYWRITE LCD_Buff,[$FE,$9D,CustChar] : LCD_WriteBuff
      GOTO Main
      Oh, and you mentioned that you are using PBP 3.0.5.1.
      You should update to PBP 3.0.7.x from http://pbp3.com/download.html
      Attached Files
      PBP3 Manual : Microchip Datasheets - 10F, 12F, 16F, 18F
      Never download a PIC datasheet from anywhere but microchip.com

      Comment


      • #4
        Thank you Richard and Darrel, I'll tackle this tomorrow when I have a time slot open up.

        Richard, yea, I need to get back to the basic bit twiddling to init that panel. Thank you for the guide.

        Darrel, LCD_Buff and LCD_WriteBuff are undefined. Is that contained in your LCD_PCF8574.pbp file? Do you have some nifty utilities in there too???

        I agree it is going to be a pain. Like I said PBP3 has some GREAT LCD routines and I wish I could use them.

        Just wanted to say thank you .... off to work! Thanks again! I'll let you know how it works!

        John.

        Comment


        • #5
          Originally posted by johncouture View Post
          Darrel, LCD_Buff and LCD_WriteBuff are undefined. Is that contained in your LCD_PCF8574.pbp file? Do you have some nifty utilities in there too???
          Yes, and YES!

          I agree it is going to be a pain. Like I said PBP3 has some GREAT LCD routines and I wish I could use them.
          All of the functions of the LCDOUT command are also available in the ARRAYWRITE command.
          You won't be missing anything.

          I'll let you know how it works!
          Appreciated.
          PBP3 Manual : Microchip Datasheets - 10F, 12F, 16F, 18F
          Never download a PIC datasheet from anywhere but microchip.com

          Comment


          • #6
            Darrel,

            Overall, WOW! Some very kool techniques in there that I haven't tried yet
            (i.e. User Command). I'm impressed! Nice clean design. Thank you for
            taking the time to show me how to do this.

            I haven't been ignoring you all, it actually took me this long to get
            the darn thing to work. Because Darrel's code is so well documented, it
            was handy to be able to test certain portions, and delete others. Here is what
            I found:

            1. The schematic shows the A0,A1,A2 lines being tied to ground. They are not
            on the actual module and thus the I2C address is indeed $4E.

            2. Darrel had some GREAT techniques but he must have been distracted because the
            DATA portion of the 4 bits is on the UPPER side of the nibble and the COMMAND
            lines (RS,RW,E,BL) are on the LOWER side of the nibble. Thus I had to reverse
            that part of the code. At first I though I had to INVERT the bits and tried
            several other things in the past week that I have since forgotten. Overall, this
            actually turned out to be a blessing in disguise because it enabled me to
            understand his code and do a lot of experimenting.

            3. I still don't understand the "R5" in the LCD_WriteBuff function and "R5" is a
            reserved word that is not explained in the PBP documentation. The datasheet
            refers to a "EEAR5" under the special function registers (Datasheet, pg 28) but
            I'm still a little fuzzy as to how to use it. Maybe someone can enlighten us.

            4. Darrel is using a PIC12F1822 and I was using a PIC16F886. His used one of the
            newer series and thus it runs a little faster and has different configuration
            settings. Again, this was a good learning experience for me because I double
            checked my config settings and found that some of mine were incorrect. The
            changes I had to make for the PIC16F886:

            a. Occillator changed to 20
            b. Deleted OSCCON. Darrel was using the internal oscillator, I was using
            an external 20mHz resonator.
            c. ANSELA is not supported on the 16F886. I used ANSEL and ANSELH.

            5. In the process of debugging this I connected LEDs up to the I2C Module and
            put 500ms pauses between I2CWrites (I'm a slow reader :-). By observing the
            pulses, I was able to debug the issue of the Upper and Lower nibbles indicated
            above and it helped me to see that I was only sending the lower nibble to the
            panel.

            6. In retrospect it is silly but I realised that each of these modules can be
            individually addressed. During testing I would type in some code, burn it to the
            MCU and connect the MCU up to the LED platform. Then to see if it worked with
            the LCD panel, I would burn it into a second platform with an LCD panel. Lots of
            time and basically a pain. This morning I realized that I could simply hook up
            both the LED platform and the LCD panel to individual I2C modules with different
            addresses and I could test them simoultaneously. Funny, how a little sleep gives
            you some insight. Duh!

            7. Well, is controlling an LCD over I2C worth it? Yes, definately. Darell has
            made it easy and these little modules only cost me about $1.70 US each. (Search
            EBay for "I2C Interface LCD") From China these took less than 2 weeks and
            shipping was free.

            8. One lesson I learned while soldering these to the LCD. On the remaining I2C
            modules I am going to solder FEMALE sockets (and put MALE pins on the LCD) so
            that I can use the LCD in either a parallel or I2C configuration. In other
            words, by soldering the I2C module directly to the LCD panel, that panel can
            only be used with the I2C protocol.

            9. ATTACHMENTS:
            a. 633_I2C_LCD.PBP - Darrel's program that I modified
            b. LCD_PCF8574a.PBP - Darrel's very kool utility modified
            c. Picture of the I2C LCD Module. I got my I2C panels from EBay vendor
            "alice1101983" and their service was great. There are lots of vendors
            that carry these so shop around and watch out for shipping costs.
            Attached Files

            Comment


            • #7
              Hi,
              Agreed, this UserCommand stuff is really cool. I need to really get into it some day but it's still a bit too "low level" for me. Darrel has made a couple of posts explaining the low level stuff, how it works etc but seeing real world examples, like this one, is great!

              3. I still don't understand the "R5" in the LCD_WriteBuff function and "R5" is a
              reserved word that is not explained in the PBP documentation. The datasheet
              refers to a "EEAR5" under the special function registers (Datasheet, pg 28) but
              I'm still a little fuzzy as to how to use it. Maybe someone can enlighten us.
              R5 is a PBP system variable used "behind the scenes". Here's how I believe it works in this particular case (I'm sure Darrel will correct me if I get it wrong): After an ARRAYWRITE operation the system variable R5 contains a pointer to the last location of the array + 1. Ie where to put "the next" byte.

              So, LCD_BuffLen = R5 - LCD_BuffAddr -1 calculates how many bytes there actually is in the buffer by subtracting the adress of where the buffer starts from that pointer (+1 since the pointer points one byte "past" the last byte actually written to the buffer).

              An important thing to remember is that R5 is used by several PBP commands (not only ARRAYWRITE) so it may or may not work reliably if you decide to do "something else" between filling the array with ARRAYWRITEe and calling LCD_WriteBuf.

              /Henrik.

              Comment


              • #8
                Henrik,

                Thank you. That does make sense! I guess the moral of the story is to immediately save R5 off to another variable if you are going to be gone very long after setting up the buffer.

                Thanks again.

                John.

                Comment


                • #9
                  John,
                  2. Darrel had some GREAT techniques but he must have been distracted because the
                  DATA portion of the 4 bits is on the UPPER side of the nibble and the COMMAND
                  lines (RS,RW,E,BL) are on the LOWER side of the nibble. Thus I had to reverse
                  that part of the code.
                  I wired it pin for pin exactly like the schematic in Post #1.
                  If you had to change things ... the schematic you posted was not for the module in question.
                  And the changes you made will not work with that schematic.

                  And no, you don't save R5 for later. You just use the LCD_WriteBuff immediately after the ARRAYWRITE.

                  Henrik,
                  You've got it all figured out.
                  I never get to correct you anymore.

                  And I'd love to show more USERCOMMAND stuff to somebody.
                  I think you're the only one that might understand it.
                  PBP3 Manual : Microchip Datasheets - 10F, 12F, 16F, 18F
                  Never download a PIC datasheet from anywhere but microchip.com

                  Comment


                  • #10
                    Darrel,

                    You are, of course, correct.

                    So much for relying on schematics from vendors. Apparently the ones I received are flipped around which may explain one of the reasons that things were so difficult when I first tried to send a command to the module.

                    Thank you again Darrel for your help. Now the next step is to use an I2C to monitor a keypad. Once that is done I can start designing the software for the driveway gate monitor as planned. :-)

                    Comment


                    • #11
                      PCF8574 not responding to I2C codes from 16F886

                      In the middle of a project and the goal posts have changed so I need more I/O - the best way to cope (so I thought) was to move the 4 line LCD panel onto I2C. I built the circuit as per Darrel's diagram above and connected it to RB7 and RB6 initially. The screen is an OLED type which worked happilly with the existing PBP commands. Using Darrel's test code, no characters appeared when I looked with the scope, nothing was appearing at those pins on the PIC. Reconnected to RC5 & RC6 and now I get a data stream on both pins but none of the outputs on the PCF8574 change state. (I only have a single channel scope so I cant check the timing of both signals - tempted to just write some code that outputs a standard stream).

                      I spotted the updated version of the code which had pins swapped etc. but this still didnt initialise the display or produce any output at the PCF8574. It's not so easy to try any other I/O pins as the prototype board uses all POrtA for analogue inputs and most pins are connected to something.

                      I have searched for clues and tried different flavours of the code. I have attached the files I am using in the hope that someone will say - aha - that shouldn't be like that ....

                      BTW we use the PWM to drive a power supply and I left that signal running to check chip operation.

                      Thanks - Bob

                      P.S. Have attached some scope images of the data and the clock in the next post - the data seems to be remarkable consistent considering how much information is meant to be sent.
                      Attached Files
                      Last edited by BobMan; 10-01-2015, 04:28 PM. Reason: Update

                      Comment


                      • #12
                        Scope traces fro SDA and SCL

                        While I would expect to see a nice clock signal repeating, I am surprised to see that the data being sent is consistently in the same pattern - very fishy. Am going to set some Outputs waggling so I can see if the program is actually running ....

                        Well I know the main program is running OK as I can see the output signal lines I set for the jumping jacks and loop count change each time through so no crashes etc. Is there an issue with the I2Cwrite command?
                        Attached Files
                        Last edited by BobMan; 10-01-2015, 04:58 PM. Reason: Update

                        Comment


                        • #13
                          It may be that the I2C address is incorrect. I've had problems in the past where the ones were zeroes and zeroes were ones in the address. The way I solved it was to run an I2C scanner.

                          Although it is on an Arduino site here is some code for how to scan your I2C line for all available devices. Again it is Arduino code but it is clear enough to adapt to PBP.

                          http://playground.arduino.cc/Main/I2cScanner

                          Comment


                          • #14
                            Yes, Check the address, as there are 2 different versions of the PCF8574. There is an "A" version and an non "A" version. This allows up to 16 of the devices to be used on the same bus.
                            Dave Purola,
                            N8NTA
                            EN82fn

                            Comment


                            • #15
                              PCF8574AN - Address

                              Thanks both. After the first email and a long walk in the mountains I decided to go back to the datasheets as I had no idea on what the datagrams should be - That was when I discovered there were two flavours of the chip and I had the AN which has a base address of $70 instead of $40

                              Now I have changed that, all the handshaking and data now seems to be going through to the display however it generally produces junk on the screen. I went back through the code adding comments and trying different combinations but I still either get a blank display or my one line message scrolling and scrambled across the whole display. the display I am using is a WEH002004ALPP5N00000 which works perfectly in 4 bit mode when connected directly to the PIC using the normal PBP LCDwrite comands. I have attached the latest version of my files and I have renamed the extension of LCD_PCF8574 back to pbp to allow upload.

                              Any pointers welcome!
                              Attached Files

                              Comment

                              Working...
                              X