I also found this code written by norohs difficult to work out and eventually I decided that it works more by accident than design and that there has to be a better way of doing this. This is what I worked out.

The LCD works in four bit mode which makes every byte sent a four bit control nibble plus a nibble of data. To send a byte of data two bytes have to be sent consisting of a control nibble plus high data nibble then control nibble plus low data nibble.

To send "H" which is $48

requires two LCDWRITE instructions

LCD_CMD = $44
GOSUB LCDWRITE
LCD_CMD = $48
GOSUB LCDWRITE

In each instruction the first 4 after the $ sets the R/W bit to write and $48 is made up from the 4 and 8 in red.

and "D" would be

LCD_CMD = $44
GOSUB LCDWRITE
LCD_CMD = $44
GOSUB LCDWRITE

and to print "DHD" would be

LCD_CMD = $44
GOSUB LCDWRITE
LCD_CMD = $44
GOSUB LCDWRITE
LCD_CMD = $44
GOSUB LCDWRITE
LCD_CMD = $48
GOSUB LCDWRITE
LCD_CMD = $44
GOSUB LCDWRITE
LCD_CMD = $44
GOSUB LCDWRITE

Looking at the LCDWRITE

LCDWRITE:
I2CWRITE D,C,ADDR,[LCD_CMD]
E=1
I2CWRITE D,C,ADDR,[LCD_CMD]
E=0
I2CWRITE D,C,ADDR,[LCD_CMD]
RETURN

each command is sent three times with E=0 then E=1 then E=0 which I think is an error, the first line is not needed.

LCDWRITE:
E=1
I2CWRITE D,C,ADDR,[LCD_CMD]
E=0
I2CWRITE D,C,ADDR,[LCD_CMD]
RETURN

but you can test this.

Why send it twice? On the LCD with the E bit set to 1 the data is loaded into a buffer and E has to change from 1 to 0 for the data to be transferred to the screen which is why the second instruction is required.

I decided to look for a better solution as I was not totally confident that the above was correct.

Darrel Taylor came to the rescue here

http://support.melabs.com/threads/98...F8574-20x4-LCD

As you can see from this not all Arduino LCDs are wired the same. The control and data nibbles can be either data/control or control/data.

johncouture worked this out for us in the thread above.