Shop OBEX P1 Docs P2 Docs Learn Events
Use I2C/TWI LCD1602 Module with the propeller. — Parallax Forums

Use I2C/TWI LCD1602 Module with the propeller.

jtilghmanjtilghman Posts: 67
edited 2012-09-18 14:38 in Propeller 1
I have the I2C/TWI LCD1602 Module from DFRobots. http://www.dfrobot.com/wiki/index.php?title=I2C/TWI_LCD1602_Module_(SKU:_DFR0063)

Sample code and the libraries are also at that link.

Its an 16x2 LCD with a I2C backpack on it. It works with the Arduino and it has libraries and they work in the arduino IDE.

I would like to make this with the propeller, but I think I am out of my depth here.

I am trying to learn SPIN and that's fun, but I am trying recode the libs for the LCD and trying to understand the I2C for the LCD. :depressed:

It's seems to be a little much.

If any one has some insight into making this work or would like to point me in the right direction, that would be great.

I thought I could just throw the correct codes down the I2C and that it might work. :lol:

Just a little help to get the LCD addressed and flash the backlight would be a great start.

Thanks,
John

Comments

  • SRLMSRLM Posts: 5,045
    edited 2012-09-16 23:16
    You can try this Spin I2C library: http://obex.parallax.com/objects/528/

    There are also several other versions out there, such as the very good one by Mike green: http://obex.parallax.com/objects/672/

    What you really need to interface to that module is a datasheet. When doing I2C it's very important to have the register map: the series of addresses and functionality that define the operation of the module. After a quick inspection of the product page I couldn't find one. If you provide a link to the datasheet I could help more. If you can't find the data sheet, you'll have to go through the sample code provided and make your own register table. For example, using completely random values:
    Address     | read/write  |  Function
    ------------+-------------+-------------------------------------
    0x01        | read/write  | control register. Write 0x30 to it.
    ------------+-------------+-------------------------------------
    0x20        |      write  | add character to display buffer.
    ------------+-------------+-------------------------------------
    

    If you post your code we can provide more specific help.

    One gotcha to be careful of is the I2C address: some drivers expect the address to be in the lower 7 bits, others expect it in the upper 7 bits. Some also expect you to provide the R/W lower bit.
  • jtilghmanjtilghman Posts: 67
    edited 2012-09-17 05:34
    Hey SRLM,

    Thanks for the reply. I have asked DFRobots for a datasheet or any more information that might be usable.

    I also have access to the .h and the .cpp files for the arduino driver.

    They can be seen here: https://dl.dropbox.com/u/12935294/I2CLCD/LiquidCrystal_I2C.h and https://dl.dropbox.com/u/12935294/I2CLCD/LiquidCrystal_I2C.cpp

    In looking at the .h file, this part would make me think these are the device mappings you spoke about:
    #define LCD_CLEARDISPLAY 0x01
    #define LCD_RETURNHOME 0x02
    #define LCD_ENTRYMODESET 0x04
    #define LCD_DISPLAYCONTROL 0x08
    #define LCD_CURSORSHIFT 0x10
    #define LCD_FUNCTIONSET 0x20
    #define LCD_SETCGRAMADDR 0x40
    #define LCD_SETDDRAMADDR 0x80
    
    // flags for display entry mode
    #define LCD_ENTRYRIGHT 0x00
    #define LCD_ENTRYLEFT 0x02
    #define LCD_ENTRYSHIFTINCREMENT 0x01
    #define LCD_ENTRYSHIFTDECREMENT 0x00
    
    // flags for display on/off control
    #define LCD_DISPLAYON 0x04
    #define LCD_DISPLAYOFF 0x00
    #define LCD_CURSORON 0x02
    #define LCD_CURSOROFF 0x00
    #define LCD_BLINKON 0x01
    #define LCD_BLINKOFF 0x00
    
    // flags for display/cursor shift
    #define LCD_DISPLAYMOVE 0x08
    #define LCD_CURSORMOVE 0x00
    #define LCD_MOVERIGHT 0x04
    #define LCD_MOVELEFT 0x00
    
    // flags for function set
    #define LCD_8BITMODE 0x10
    #define LCD_4BITMODE 0x00
    #define LCD_2LINE 0x08
    #define LCD_1LINE 0x00
    #define LCD_5x10DOTS 0x04
    #define LCD_5x8DOTS 0x00
    
    // flags for backlight control
    #define LCD_BACKLIGHT 0x08
    #define LCD_NOBACKLIGHT 0x00
    
    #define En B00000100  // Enable bit
    #define Rw B00000010  // Read/Write bit
    #define Rs B00000001  // Register select bit
    

    And maybe this is how its written down the I2C:
    private:
      void init_priv();
      void send(uint8_t, uint8_t);
      void write4bits(uint8_t);
      void expanderWrite(uint8_t);
      void pulseEnable(uint8_t);
      uint8_t _Addr;
      uint8_t _displayfunction;
      uint8_t _displaycontrol;
      uint8_t _displaymode;
      uint8_t _numlines;
      uint8_t _cols;
      uint8_t _rows;
      uint8_t _backlightval;
    };
    

    Anyway if this helps, let me know. I will keep digging to see what I can find.

    As for code, my code isn't much more than some I2C objects and such but I can post it if you want to see.

    I know I shouldn't be embarrassed about what my code looks like. :lol:

    Thanks,
    John
  • JonnyMacJonnyMac Posts: 9,194
    edited 2012-09-17 09:16
    One gotcha to be careful of is the I2C address: some drivers expect the address to be in the lower 7 bits, others expect it in the upper 7 bits. Some also expect you to provide the R/W lower bit.

    This is very likely the problem -- I ran into this while porting some I2C stuff from an Arduino project.
  • jtilghmanjtilghman Posts: 67
    edited 2012-09-18 14:38
    Ok,

    I think I am making some head way. I have taken code that JonnyMac wrote and have 'adapted' it. Its not complete and doesn't work. But its a start.

    '' =================================================================================================
    ''
    ''   File....... LCD1602_demo.spin
    ''   Purpose.... 
    ''   Author..... John Tilghman
    ''               Copyright (c) 2012 John Tilghman
    ''               -- see below for terms of use
    ''   E-mail..... [EMAIL="john.tilghman@gmail.com"]john.tilghman@gmail.com[/EMAIL]
    ''   Started.... 18 SEP 2012
    ''   Updated.... 
    ''
    '' =================================================================================================
    
    con
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000                                          ' use 5MHz crystal
    ' _xinfreq = 6_250_000                                          ' use 6.25MHz crystal
    
      CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq
      MS_001   = CLK_FREQ / 1_000
      US_001   = CLK_FREQ / 1_000_000
    
    
    con
    
      RX1 = 31                                                      ' programming / terminal
      TX1 = 30
      
      SDL = 12                                                      ' i2c / i2c
      SCA = 13
    
    
    con
    
      LCD = $27 | (0 << 1)                                       ' device address
    
    '' commands
    LCD_CLEARDISPLAY = $01
    LCD_RETURNHOME = $02
    LCD_ENTRYMODESET = $04
    LCD_DISPLAYCONTROL = $08
    LCD_CURSORSHIFT = $10
    LCD_FUNCTIONSET = $20
    LCD_SETCGRAMADDR = $40
    LCD_SETDDRAMADDR = $80
    
    '' flags for display entry mode
    LCD_ENTRYRIGHT = $00
    LCD_ENTRYLEFT = $02
    LCD_ENTRYSHIFTINCREMENT = $01
    LCD_ENTRYSHIFTDECREMENT = $00
    
    '' flags for display on/off control
    LCD_DISPLAYON = $04
    LCD_DISPLAYOFF = $00
    LCD_CURSORON = $02
    LCD_CURSOROFF = $00
    LCD_BLINKON = $01
    LCD_BLINKOFF = $00
    
    '' flags for display/cursor shift
    LCD_DISPLAYMOVE = $08
    LCD_CURSORMOVE = $00
    LCD_MOVERIGHT = $04
    LCD_MOVELEFT = $00
    
    '' flags for function set
    LCD_8BITMODE = $10
    LCD_4BITMODE = $00
    LCD_2LINE = $08
    LCD_1LINE = $00
    LCD_5x10DOTS = $04
    LCD_5x8DOTS = $00
    
    '' flags for backlight control
    LCD_BACKLIGHT = $08
    LCD_NOBACKLIGHT = $00
    
    En = 000100  '' Enable bit
    Rw = 000010  '' Read/Write bit
    Rs = 000001  '' Register select bit
        
    con
    
       #1, HOME, GOTOXY, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR       ' PST formmatting control
      #14, GOTOX, GOTOY, CLS 
    
     
    obj
    
      term   : "fullduplexserial64"                                 ' for terminal
      i2c    : "jm_i2c"                                             ' i2c access
    
    
    var
    
      byte  buffer[80]
    
    
    dat
    
    Menu            byte    "=======================", CR
                    byte    "  i2c Demo             ", CR
                    byte    "=======================", CR  
                    byte    CR
                    byte    "[1] Backlight ON       ", CR
                    byte    "[2] Backlight OFF      ", CR
                    byte    0
    
    
    pub main | c 
    
      term.start(RX1, TX1, 00, 115_200)                          ' start terminal I/O
      i2c.setup                                                     ' setup I2C buss (boot pins)
    
      repeat
        term.tx(CLS)
        term.str(@Menu)
        term.rxflush
        c := term.rx
        case c
          "1" : backlight_on
          "2" : backlight_off
    
    pub backlight_on
    
      term.tx(CLS)
      
      term.str(string("Turning Backlight ON !"))
      term.tx(CR)
    
      i2c.wr_strx(LCD, LCD_BACKLIGHT)
    
      press_key
    
    pub backlight_off
    
      term.tx(CLS)
      
      term.str(string("Turning Backlight ON !"))
      term.tx(CR)
    
      i2c.wr_strx(LCD, ADDR_LO, @TestStr1)                        ' write string
    
      press_key
    
    pub press_key
    
      term.str(string(CR, "Please press a key..."))
      term.rxflush
      term.rx
    
    pub pause(ms) | t
    
    '' Delay program in milliseconds
    
      if (ms < 1)                                                   ' delay must be > 0
        return
      else
        t := cnt - 1792                                             ' sync with system counter
        repeat ms                                                   ' run delay
          waitcnt(t += MS_001)
    
    dat
    
    {{
    
      Terms of Use: MIT License
    
      Permission is hereby granted, free of charge, to any person obtaining a copy of this
      software and associated documentation files (the "Software"), to deal in the Software
      without restriction, including without limitation the rights to use, copy, modify,
      merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
      permit persons to whom the Software is furnished to do so, subject to the following
      conditions:
    
      The above copyright notice and this permission notice shall be included in all copies
      or substantial portions of the Software.
    
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
      INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
      PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
      CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
      OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    
    }}               
    

    The problem I think is that I don't understand completey whats going on. I have looked at the I2C specs and it says: send address, then data, but in the spin code it wants: id, address, value.

    The C++ code I have from the arduino lib seems to only send address, data. I still have not figured out if its 7 or 8 bit but the arduino libs talk about 4 bit address. Also this device is a HD44780U with an I2C backpack on it.

    Don't know if any of this helps.

    Just trying to learn as I go and get something working.. :lol:

    Thanks,
    JT
Sign In or Register to comment.