Using the DFR0154 LCD with I2C interface

I am looking for the I2C interface specifications (list of command, timing, etc.) for the DFR0154 LCD.

I have the following documents related to the DFR0154:

  1. HD44780 Datasheet.
  2. PCA8574 Datasheet

In a previous project, I used the I2C-based 1602 LCD (DFR0556) whose I2C interface is described in the document “AiP31068 40 SEG / 16 COM Driver & Controller for Dot Matrix LCD/2 or 3 Line Serial Data Interface Product Specification”. The instruction set for the 1602 is shown in Table 3 (page 18) of this document. This table is almost identical to Table 6 on page 24 of the HD44780 datasheet.

So, could you confirm that the I2C command set for the DFR0154 is the data part (D7…D0) of each command in Table 6 of the HD44780 datasheet (ignoring RS and R/W)? That is, pretty much the same as 1602 I2C command set?

Also, do the execution times shown in Table 6 still apply to the I2C interface?

Hi Stephen,

I’m assuming that these were the two datasheets that you were referring to?

If possible can you please link the AiP31068 40 SEG / 16 COM Driver & Controller for Dot Matrix LCD/2 or 3 Line Serial Data Interface Product Specification that you’re referring to? I had a look for it online and couldn’t see any datasheet with the instruction set that you’re referring to on it, although from the HD44780 datasheet I’m quite sure I know the set you’re describing.

I’d expect that’d be correct, the clock speed of the PCA8574/74A used by the DFR0154 sits at 400kHz which for that protocol should allow for a fairly high transmission speed, although I couldn’t see it listed on any of the datasheets to confirm this.

Thank you for your help with this.
Yes, the PCA8574 and LCD2004 (HD44780) documents are correct.
Re the AiP31068 document, I hope this works. I’m 70 years old. The word “link” has no meaning!
AiP31068 Datasheet - LCD1602 Display Engine.pdf (1.5 MB).
Yes, the instruction set for a large range of 44780 LCDs has been fixed for some time (like decades). It’s a shame the specs haven’t been written to deal with someone as limited as me.
I’m going to run my project @ 100KHz, so the 400Khz thing is irrelevant at this time.

I think it might be useful to restate my problem.

I am looking for device-level specifications on the I2C interface to the DFR0154 LCD.

I do not use any Arduino technology. I wish to interface the LCD to a Microchip controller.

I would like to know the device-level message protocol that allows the DFR1054 to distinguish between commands (move cursor, clear display, etc) and data to be displayed.

To explain, I also have a DFR0556 (1602 LCD in green). Its message protocol is specified in the AiP31068 LCD Driver Specification (version 2013-03-A3). To distinguish between sending a command and sending display data, the AiP31068 requires a “control byte” to be inserted in the I2C message between the device address and any data being sent. Bit 6 of the Control Byte mimics the RS (Register Select) signal of the ubiquitous HD44780 LCD chip. For commands, RS = 0; for display data, RS = 1.

I have been unable to find a similar protocol definition for the DFR0154. The DF Robot website gives the datasheets for the HD44780 and the PCA8574 Expander chip. From my reading, these do not explain what has to be sent over the I2C interface to distinguish between transmission of commands and data. I have read (many!) Arduino code samples, but these are always written at the function level, not the device level.

I have tried a number of alternate message formats and so far the LCD does not display anything. The LCD acknowledges all I2C messages properly, but there is no indication that the LCD is processing the messages sent to it. Interestingly, I can send the DDRAM Set Command to the LCD followed by a read of the device. The DDRAM address returned by the LCD appears to be correct.

So, could someone tell me the contents and order of bytes (the actual 1s and 0s – not a function call) that have to be sent to the DFR0154 to accomplish the following tasks:

  • Move the cursor one place to the right, ie. a command message.
  • Display “Mary had a big lamb” on the display, ie. a data display message.

CRO waveforms showing SDA and SCL would be equally useful.

From this, I should be able to reverse engineer the DFR1054 I2C message protocol.

Any help is gratefully received.

You might be looking at the examples instead of the library. For instance the DFRobot referenced library for this device at
includes all the command codes in LiquidCrystalI2c.h, and the communication protocols in LiquidCrystal_I2c.cpp under the heading “/************ low level data pushing commands **********/”.

1 Like

Thanks so much for your help.
I have used a number of I2C devices apart from the DFR0154 (eg. sensors, other LCDs, DAC, etc) and all of them have been “automatic” in processing I2C comms. This is the first time I have encountered an I2C device where you have to “wiggle your own bits”.
I spent today converting the Arduino and other code so that the LCD is initialised according to Figure 24 (p46) of the HD44780 spec. As expected, the PCA8574 acknowledges all I2C messages correctly, but so far the LCD remains blank.
I hope that I have interpreted the signal interface between the HD44780 and the PCA8574 properly. I think the port pins P7…P0 on the PCA8574 are connected in order to the HD44780 as D7 D6 D5 D4 X E RW RS (where X is a don’t care).
I shall keep trying.

1 Like

I now have the DFR0154 working properly.
Firstly, the bit labelled “don’t care” in my previous post is anything but “don’t care”. It is the backlight control bit. To keep the LCD glowing, this bit has to be set in every message sent to the LCD.
I seem to have interpreted Figure 24 (p46) of the HD44780 spec incorrectly. I thought the first four messages to the LCD were 4-bit writes. Reading how others have done the initialisation, these messages are 8-bit writes. For example, the first write in Figure 26 is the bit pattern 0011 with RW=RS=0. So, I sent a nibble with value 3 which didn’t work. The correct answer apparently is the the first write (and the next 2 after it) are the 8-bit writes of the value 0x03. The PCA8574 interface to the HD44780 is 4-bit, so value 0x03 is sent in two operations; the first sends the MS nibble “0”, the second sends the LS nibble “3”. The signal connections between the PCA8574 and the HD44780 are D7 D6 D5 D4 BL E RW RS. So, the first message to the LCD is 0b00001000 (sends the “0” nibble), and the second is 0b00111000 (sends the “3” nibble). BL is set to 1 to keep the backlight on. To load each of these messages, the E signal has to be pulsed, so each nibble requires 3 writes to the PCA8574 (E low, E high, E low). Reading Figure 24 again, I guess that is what the words “Interface is 8 bits long” are all about.
After sending the fourth initialisation message (0x02), the LCD can be written in 4-bit mode to set the other functions (Entry Mode, DDRAM Address Set, etc).
Thank you all for your help. It is much appreciated.


Hi Stephen,

Good dive into the workings of the display!
I’m sure this will help another maker in the future, thanks heaps for updating the topic!



Congrats you fixed your problem. You seem to have dived into the works of things and did your own massaging.
I had a similar problem some time ago where I had a “standard” 1602 display with backlight and I fitted a I2C LCD backpack Core SKU 018-LCD1602-I2C. I downloaded the linked demo but needless to say I could not get anything to work.

Now I am a believer in doing my own research as far as possible as I feel you learn more this way. And I know I don’t have the digital knowledge to disect things as you did. Well done.

The pertinent bits were:
#include <Wire.h>. This bit OK.
#include <LiquidCrystal_I2C.h>. This seemed straight forward.
LiquidCrystal_I2C lcd(0x27,16,2); 0x27 being the default address of the I2C backpack.
Then in the setup section:
lcd. init()
lcd. backlight().

None of this worked.

When I searched PCF8574 I came across some interesting information. There existed another library namely “LiquidCrystal_PCF8574.h”. You mention PCA8574 now I don’t know what the differences are but maybe they are much the same.

I finished up with:
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27); Note the “16,2” missing. This would not work properly with these 2 parameters here. They are included below.
Then in the setup section:
lcd.begin(16, 2);
lcd. setBacklight(10); I found the backlight would not come on without a number in the parentheses, it did not seem to matter which number.
lcd. clear();

The whole thing worked perfectly. The display works with simple commands like lcd. print(variable or string in quotes), lcd. setCursor(x, x), lcd. clear() etc.

I thought I would speak up here as this may help others who are not sufficiently up on the digital nitty gritty to rip things apart as you did. I think I have mentioned this particular Arduino library previously.
Cheers Bob


Thank you all, gentlemen. The Core community is a good thing.