Converting 16x2 LCD to I2C (SOLVED)


For the solution to the thread, please navigate to:
http://forum.arduino.cc/index.php?topic=170817.msg1271707#msg1271707

please note this solution will work for a Micro, PCF8475p and 16x2 display (similar to AMD1602K by Sparkfun)


Morning again!

I have a Sparkfun ADM1602k 16x2 display. My project (using the Arduino Micro) has been getting more and more complex and I need to save digital pins. A quick google revealed that I can use an IO expander to use 2 analog connections. So I bought a PFC8574P. There seems to be 3 ways to hook the LCD up to the chip. Some use a transistor some dont... I've tried all three...

Anyway, I downloaded the Liquidcrystal_I2C Library, and set my board up like the Schematic attached. What am I missing... I'm using the "Hello World" I2C sketch.

See attachments. Thanks again for your help.

ArduinoMicro_Pinout.png

0.jpeg

I'm sure some of the real experts here will have a better answer than mine.

In my experience, I was also trying to do what you did was it very frustrating for and I couldn't get it to work.

I purchased a serial back pack and that worked for me... just uses one pin for RX and one for TX.

Another direction is to buy a MEGA. Have seen them under $20 on eBay...

CarlW:
I'm sure some of the real experts here will have a better answer than mine.

In my experience, I was also trying to do what you did was it very frustrating for and I couldn't get it to work.

I purchased a serial back pack and that worked for me... just uses one pin for RX and one for TX.

Another direction is to buy a MEGA. Have seen them under $20 on eBay...

Thanks! I'm going to see what a few others have to say, but if not, I'm going to have to buy the back pack. which one did you get? did it work right off the bat? Do you think it will work with the Micro?

Thanks again.
Keith

I got one from inmojo.com

Here is the link:
http://www.inmojo.com/store/liudr-arduino-and-physics-gadgets/item/serial-lcd-back-pack---phi-panel/
The one I got is called "kit" for $11.95 (+ more for shipping)

It worked for me on two different displays...

Yes, it would work with the micro.

I don't see any pull-up resistors on your 'schematic'.

Don

floresta:
I don't see any pull-up resistors on your 'schematic'.

Don

There are none... Where would they go? whats the size? thanks!

CarlW:
I got one from inmojo.com

Here is the link:
http://www.inmojo.com/store/liudr-arduino-and-physics-gadgets/item/serial-lcd-back-pack---phi-panel/
The one I got is called "kit" for $11.95 (+ more for shipping)

It worked for me on two different displays...

Thanks for the links

There are none... Where would they go? whats the size? thanks!

You need two of them. One between SCL (A5) and +5v and the other between SDA (A4) and +5v. The value isn't critical, 4.7K +/- 100% or so should be OK.

Don

I put 10k resisters between 5v and a4 and a5(see picture). and used this sketch:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>



#define BACKLIGHT_PIN     13

LiquidCrystal_I2C lcd(0x38);  // Set the LCD I2C address

//LiquidCrystal_I2C lcd(0x38, BACKLIGHT_PIN, POSITIVE);  // Set the LCD I2C address


// Creat a set of new characters
const uint8_t charBitmap[][8] = {
   { 0xc, 0x12, 0x12, 0xc, 0, 0, 0, 0 },
   { 0x6, 0x9, 0x9, 0x6, 0, 0, 0, 0 },
   { 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0, 0x0 },
   { 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0, 0x0 },
   { 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0x0 },
   { 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0x0 },
   { 0x0, 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0x0 },
   { 0x0, 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0x0 }
   
};

void setup()
{
   int charBitmapSize = (sizeof(charBitmap ) / sizeof (charBitmap[0]));

  // Switch on the backlight
  pinMode ( BACKLIGHT_PIN, OUTPUT );
  digitalWrite ( BACKLIGHT_PIN, HIGH );
  
  lcd.begin(16,2);               // initialize the lcd 

   for ( int i = 0; i < charBitmapSize; i++ )
   {
      lcd.createChar ( i, (uint8_t *)charBitmap[i] );
   }

  lcd.home ();                   // go home
  lcd.print("Hello, ARDUINO ");  
  lcd.setCursor ( 0, 1 );        // go to the next line
  lcd.print (" FORUM - fm   ");
  delay ( 1000 );
}

void loop()
{
   lcd.home ();
   // Do a little animation by writing to the same location
   for ( int i = 0; i < 2; i++ )
   {
      for ( int j = 0; j < 16; j++ )
      {
         lcd.print (char(random(7)));
      }
      lcd.setCursor ( 0, 1 );
   }
   delay (200);
}

There are several different libraries called "LiquidCrystal_I2C" which one are you using
and where did you get it?

I recommend fm's LiquidCrystal library replacement as it has a few fixes
that most of the other i2c to hd44780 libraries don't have and it is also much faster.

The first question I have is i2c address.
Are you sure you have the correct address?

I don't see a schematic. I do see a fritzing type picture
however, it doesn't match your wiring. In your wiring I also see what looks like a transistor
which I assume is for the backlight - but it's definitely not hooked up correctly.

The sketch looks like one of fm's example sketches and you are using all the defaults
for the constructor. (I don't recommend this)
Also, if using fm's library, then that commented out constructor that is using pin 13 is wrong.
The parameters in the constructor are not arduino pin numbers but bit position on the pcf8574 output latch.

To get it to work with fms' library is not difficult.
You will need to either wire it up like his LCD i2c i/o expander or
fill in the proper constructor for your wiring.
fm's LCD i/o expander uses this pin mapping from pcf8574 output pins to LCD pins.
p0 D4
p1 D5
p2 D6
p3 D7
p4 RS
p5 RW
p6 EN
p7 (optional backlight)

It is hard to tell the exact wiring in your photo
for the wires going to the lower pins on the lcd
(it almost looks like the red wire is going to lcd pin 5 rather than pin 4
as the fritzing picture shows.)
For now, I'll assuming the fritzing diagram is correct as I can't tell your wiring from the
photograph.
From the fritzing diagram your wiring appears to be:
p0 D4
p1 D5
p2 D6
p3 D7
p4 E
p5 RW
p6 RS
p7 backlight

If you are using fm's library, then I recommend using the full constructor as it defines
all pin mappings as well as backlight control.
(I'm assuming that you eventually want backlight control)

For your wiring it would be
LiquidCrystal_I2C lcd(4, 5, 6, 0, 1, 2, 3, 7, polarity);

(where 'polarity' is either POSITIVE or NEGATIVE depending on your backlight circuit)

This matches the constructor for the mjkdz i2c backpack which you see all over
ebay for about $2-$3 USD but notice that the control lines are different
than the default wiring.

There is a connection from P7 over to what looks like a transistor.
What is that? If it is transistor for backlight control it is not hooked up
to either A or K on the LCD. And the wiring looks pretty funky. (bad)
You have the LCD backlight A and K directly wired to power and ground
(with no current limiting resistor).

Here is my suggestion:
Use fm's library if you are not using that one.
For the time being remove the wire going to pcf8574 p7.
Use this constructor:
LiquidCrystal_I2C lcd(4, 5, 6, 0, 1, 2, 3, 7, POSITIVE);

Get rid of any use the stuff that messes with BACKLIGHT _PIN in the sketch.
That stuff is just plain wrong anyway. This includes any pinMode() and digitalWrite() stuff.
And there is no need for to use the obsolete lcd.setBacklightPin() call as well when you are ready
to use backlight control since you will be using the newer full constructor that also defines backlight control.
For backlight control use lcd.backlight() and lcd.noBacklight()

If you need help with a backlight control circuit either post your schematic or
just ask and I can recommend one if you say which transistor you have.
You will also need to know if you backlight needs any current limiting.
The polarity in the constructor for backlight control will vary depending on your backlight circuit.
The POSITIVE in the one I recommend above is simply a place holder until you finalize your backlight
circuit.

--- bill

i've got to agree with Bill, the only LiquidCrystal_I2C library that seems to work these days is the newLiquidCrystal one, the MarioH and LiquidTWI ones certainly don't work for me. I'm using an I2C backpack though, which is probably easier than wiring up your own PFC8574P.

My code (based on a post here somewhere) is:

// include libs
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

// init vars
const int I2C_ADDR = 0x20;
const int LED = 3;
const int EN = 2;
const int RW = 1;
const int RS = 0;
const int D4 = 4;
const int D5 = 5;
const int D6 = 6;
const int D7 = 7;
int n = 1;

// constructor
LiquidCrystal_I2C lcd(I2C_ADDR,EN,RW,RS,D4,D5,D6,D7);

void setup()
{
    // init 16x2
    lcd.begin(16,2);

    // switch on the backlight
    lcd.setBacklightPin(LED,POSITIVE);
    lcd.setBacklight(HIGH);

    // goto (0,0)
    lcd.home();

    // print start
    lcd.print("Hello, World!");
    lcd.setCursor ( 0, 1 );
    lcd.print("Iteration No: ");
}

void loop()
{
    // goto col 14 of row 2
    lcd.setCursor (14,1);

    // print increment
    lcd.print(n++,DEC);

    // wait 0.5secs
    delay(500);
}

sej7278,
I would recommend updating your sketch a bit.

Change your constructor to:

// constructor
LiquidCrystal_I2C lcd(I2C_ADDR,EN,RW,RS,D4,D5,D6,D7, LED, POSITIVE);

This configures the backlight as well.

Then remove:

    // switch on the backlight
    lcd.setBacklightPin(LED,POSITIVE);
    lcd.setBacklight(HIGH);

The setBacklightPin() is no longer needed since the backlight can be configured
with the constructor and when done so, the begin() call will automatically
turn on the backlight.
Also, using

    lcd.setBacklight(HIGH);

is incorrect because HIGH is currently defined as 1 and the setBacklight(dimvalue) call
is used to set the intensity of the backlight not to turn it full on/off.
Using a value of 1 would be very dim on devices that support dimming.
use:
lcd.backlight() and lcd.noBacklight() to turn the backlight full/on off.
If you still really want to use setBacklight(dimvalue); to turn the backlight
on/off, the proper calls would be:

lcd.setBacklight(BACKLIGHT_ON);
lcd.setBacklight(BACKLIGHT_OFF);

The reasoning behind all this is that the library is designed to allow
sketches to work on any underlying hardware. Some h/w supports dimming
and some doesn't. If the sketches use the full constructor and use
proper backlight(), noBacklight() or setBacklight(dimvalue) calls, then
the sketch will work on any hardware without any code modifications by
simply modifying the constructor.
In the case of code doing something like lcd.setBacklight(HIGH), the code
would create a backlight that is VERY dim (pretty much off) when run on alternate hardware
like an LCD shield that uses 4bit mode and supports dimming.

So I highly recommend using the "best practice" of using the calls above.
This ensures that only the constructor and not the actual sketch code need
be modified when changing to alternate hardware.

--- bill

thanks for the advice bill, i love best practice info like this.

To get it to work with fms' library is not difficult.
You will need to either wire it up like his LCD i2c i/o expander or
fill in the proper constructor for your wiring.
fm's LCD i/o expander uses this pin mapping from pcf8574 output pins to LCD pins.
p0 D4
p1 D5
p2 D6
p3 D7
p4 RS
p5 RW
p6 EN
p7 (optional backlight)

It is hard to tell the exact wiring in your photo
for the wires going to the lower pins on the lcd
(it almost looks like the red wire is going to lcd pin 5 rather than pin 4
as the fritzing picture shows.)
For now, I'll assuming the fritzing diagram is correct as I can't tell your wiring from the
photograph.
From the fritzing diagram your wiring appears to be:
p0 D4
p1 D5
p2 D6
p3 D7
p4 E
p5 RW
p6 RS
p7 backlight

If you are using fm's library, then I recommend using the full constructor as it defines
all pin mappings as well as backlight control.
(I'm assuming that you eventually want backlight control)

For your wiring it would be
LiquidCrystal_I2C lcd(4, 5, 6, 0, 1, 2, 3, 7, polarity);

(where 'polarity' is either POSITIVE or NEGATIVE depending on your backlight circuit)

This matches the constructor for the mjkdz i2c backpack which you see all over
ebay for about $2-$3 USD but notice that the control lines are different
than the default wiring.

There is a connection from P7 over to what looks like a transistor.
What is that? If it is transistor for backlight control it is not hooked up
to either A or K on the LCD. And the wiring looks pretty funky. (bad)
You have the LCD backlight A and K directly wired to power and ground
(with no current limiting resistor).

Here is my suggestion:
Use fm's library if you are not using that one.
For the time being remove the wire going to pcf8574 p7.
Use this constructor:
LiquidCrystal_I2C lcd(4, 5, 6, 0, 1, 2, 3, 7, POSITIVE);

Get rid of any use the stuff that messes with BACKLIGHT _PIN in the sketch.
That stuff is just plain wrong anyway. This includes any pinMode() and digitalWrite() stuff.
And there is no need for to use the obsolete lcd.setBacklightPin() call as well when you are ready
to use backlight control since you will be using the newer full constructor that also defines backlight control.
For backlight control use lcd.backlight() and lcd.noBacklight()

Sorry for the confusing picture above. I did have a transistor in the circuit, but got rid of it; and at the time of my post had my wiring like the fritzing diagram.

What i've done:
I've added 2 10K Ohm resistors to the analog a4 and a5 inputs (from the inputs to 5V)
Based on Bills suggestion and first list of pins I switched p4 and p6 (en and rs values)

(see attachment)

I'm using the constructor from the newLiquidCrystal Library:

LiquidCrystal_I2C lcd(0x38,6, 5, 4, 0, 1, 2, 3, 7, POSITIVE);

i've got to agree with Bill, the only LiquidCrystal_I2C library that seems to work these days is the newLiquidCrystal one, the MarioH and LiquidTWI ones certainly don't work for me.

I guess the real question after all that is if I have the right address? I've tried 0x38, 0x20, 0x27 with no avail.

Lcd_pin0ut.jpg

I guess the real question after all that is if I have the right address? I've tried 0x38, 0x20, 0x27 with no avail.

that's what i2_scanner is for: Arduino Playground - I2cScanner

When it comes to hardware, guessing is not good.
(Some guesses can damage the hardware)
I'd recommend running an i2c scanner to locate the i2c chip so you know
that that the i2c chip is functioning as well as its address.
You could also run my i2clcd guesser sketch. Read the comments for how to use
it and understand that there is some risk involved since it is guessing at the pin
configuration.
http://forum.arduino.cc/index.php?topic=157817.msg1235230#msg1235230

--- bill

I ran the scanner.

according to the google searches i did; 0x38 is the right address.

the canner doesnt come up with anything:

"Scanning...
No I2C devices found"

That's not good.
That means that the Arduino and the PCF8574 are not able to communicate.
You need to resolve that issue first.

Post a picture of your current setup.
A nice large one like the one that was in your original post that is now gone.

Post a picture of your current setup.
A nice large one like the one that was in your original post that is now gone.

Here you go.

PCF8574P.jpg

Lcd_pin0ut.jpg