control a I2C Display with HD44780 controller

woschx

New Member
Hi, everyone,
I'm currently trying to output texts on an I2C display with HD44780 controller, which unfortunately I can't do.
On the supplier's side, the address is Hex 3F, but if I set this address like this:
"hi2csetup i2cmaster, $3F, i2cslow, i2cbyte"
, then there is an error message that bit 0 must not be set.
"Error: Please use full 8 bit slave address (with bit0 clear)"
It's about this screen https://funduino.de/nr-19-i²c-display
Regards
wolfgang
 

Attachments

lbenson

Senior Member
With bit 0 cleared, the address would be $3E--but search for I2C HD44780 threads. There are a lot of working examples, but it's not straightforward, since the device is set up to use "nibble" mode.
 

woschx

New Member
I found the address with an address scanner for an Arduino with 0x27 but there is also the bit 0 =1
I couldn't find a clear example.
 

AllyCat

Senior Member
Hi,

Arduino and some manufacturers specify only the high 7 bits of the address, but PICaxe requires all 8 bits to be specified (with the LSb = 0), so you often need to multiply the specified address by 2. Thus for "address $3F" you should use $7E , or for "address 0x27" use $4E .

However, you cannot simply send ASCII characters, or even HD44780 commands, directly over the I2C bus, because the display very probably is working in "4-bit (nibble data) mode" (with the other four bits used for control signals). There are some threads on the forum concerning similar I2C displays, but they're not easy to find, so perhaps a better introduction to the 4-bit mode was described by inglewoodpete HERE. Basically, you will need to map his seven "pins": oLCD4, oLCD5, oLCD6, oLCD7, oLCDRS, oLCDEn, oLDCRW (and probably an eighth controlling the backlight) into a byte which is transmitted twice (once for each nibble) for each data/control byte.

Cheers, Alan.
 

woschx

New Member
With an Arduino and the appropriate library, I have now been able to control the display. It's a pity that there doesn't seem to be anything like that for the Picaxe. I actually thought that the PCF8574 would already take over the entire control of the display, but that is probably not the case and so it is much more difficult to address the display via I2C than directly in parallel! A long time ago, I used an 18M2 to program a small controller for a display like the AXE133, but the display with the built-in I2C interface was so cheap that I thought I could control it just as easily. I then finish further work with this display. That makes absolutely no sense!

Wolfgang
 

Goeytex

Senior Member
The PCF8574(A) is simply a "dumb" 12C based I/O expander. It only does what it is told to do. While these can be made to work with a Picaxe to control an LCD display, the effort is not worth the rather dismal performance results (IMO).
 

PhilHornby

Senior Member
All my (LCD) projects have used PCF8574-based displays :)

What is this dismal performance of which you speak? (What are you trying to do to them?)


The only delays in there, are the program timing-out, waiting for button presses and returning to the previous menu
 

Goeytex

Senior Member
Hi Phil

Dismal may not be the right word. How about "less than ideal"? Or maybe even "annoyingly slow"?

With LCD displays, I expect to get a minimum of 5,000-8,000 char per sec so that the program is not bogged down with updating the display and can move on to do other stuff. Can you get that with a Picaxe using an PCF8574? I am guessing not.

Now if all you do is update the temperature value every 5 seconds or so then that's great. Speed not really needed for a simple temperature gauge. But for a newbie to even get that working with a Picaxe/LCD/PCF8574 can be a nightmare. There are reason(s) that Rev-Ed does not provide a standardized "library" for displays using a PCF8574 and reasons(s) that not too many folks use it.

Yes, you can save I/0s with the PCF8574 but at the cost of the added overhead of I2C and having to send 2 bytes instead of 1 for each character or command since 4-bit mode is required.
 
Last edited:

woschx

New Member
Hi Phil

basically, this display is exactly what I could use for a student project because only two lines are needed and because the entire display with driver board only costs 3.2 euros! Since the students have to pay for the display themselves, I have problems with 18 euros for the AXE133 because they also need other things for their projects. The speed does not matter in the projects and that of your video is absolutely sufficient!
Can you leave me an example program that I can then prepare as a module for my students. They would then only have to integrate it into their projects and adapt it to their respective tasks.
Regards
Wolfgang

info@der-schutzhund.de
 

lbenson

Senior Member
A modification of Hippy's PCF8574 I2C LCD code from here: http://www.picaxeforum.co.uk/showthread.php?21872
Code:
#picaxe 20M2
#terminal 4800

' hippy's generic string poking macro:
#Macro PokeString( toLoc, string )
' modified to include zero terminator
  bPtr = toLoc
  lookupAdr = 0
  Do
    Lookup lookupAdr, ( string, 0 ), lookupData
'    If lookupData <> 0 Then
      @bPtrInc = lookupData
      lookupAdr = lookupAdr + 1
'    End If
  Loop Until lookupData = 0
#EndMacro

symbol stringAdrBase = $40 ' location of up to 16 offsets for strings
symbol stringBase    = $50 ' location of strings

' hippy's I2C LCD with PCF8574 code, post 28: 
' http://www.picaxeforum.co.uk/showthread.php?21872
' symbol b2,b3,secondNybble reserved for LCD 
' b3 bits defined below
Symbol bitRS = bit24
Symbol bitWR = bit25
Symbol bitE  = bit26
Symbol bitBKL = bit27
Symbol bitD4 = bit28
Symbol bitD5 = bit29
Symbol bitD6 = bit30
Symbol bitD7 = bit31

symbol secondNybble    = b5 ' for LCD
symbol lookupAdr       = b6 ' for PokeString Macro
symbol lookupData      = b7 ' for PokeString Macro
symbol stringAdrOffset = b8 ' location of nth string address

Initialisation:

  gosub InitializeLCD
  stringAdrOffset = stringAdrBase
  bptr = stringBase
  poke stringAdrOffset, bptr
  pokeString(bptr,"Line 1 8901234567890")
  inc stringAdrOffset
  poke stringAdrOffset, bptr
  pokeString(bptr,"Line 2")
  inc stringAdrOffset
  poke stringAdrOffset, bptr
  pokeString(bptr,"Line 3")
  inc stringAdrOffset
  poke stringAdrOffset, bptr
  pokeString(bptr,"Line 4")
  inc stringAdrOffset
  poke stringAdrOffset, bptr
  pokeString(bptr,"Another longer line")
  inc stringAdrOffset
  pause 2000

MainProgram:

  b2 = $80 : Gosub Sendb2AsCommandByte
  stringAdrOffset = stringAdrBase ' offset of first string
  peek stringAdrOffset, bptr
'  sertxd(#bptr, " ", @bptr," | ")
  gosub sendString

  b2 = $C0 : Gosub SendB2AsCommandByte ' LB 180526 was $A0
  stringAdrOffset = stringAdrBase + 1 ' offset of 2nd string
  peek stringAdrOffset, bptr
  gosub sendString

  b2 = $94 : Gosub Sendb2AsCommandByte ' LB 180526 was $C0
  stringAdrOffset = stringAdrBase + 2 ' offset of 3rd string
  peek stringAdrOffset, bptr
  gosub sendString

  b2 = $D4 : Gosub Sendb2AsCommandByte ' LB 180526 was $E0
  stringAdrOffset = stringAdrBase + 3 ' offset of 4nd string
  peek stringAdrOffset, bptr
  gosub sendString

  pause 5000
  b2 = $C0 : Gosub SendB2AsCommandByte ' LB 180526 was $A0
  stringAdrOffset = stringAdrBase + 4 ' offset of 5th string
  peek stringAdrOffset, bptr
  gosub sendString

  Do : Loop

Sendb2AsInitByte:

  Pause 15

  bitWR = 0         ; Keep WR signal low
  bitBKL = 1        ; keep backlight on
  bitBKL = 0        ; keep backlight off
 
Sendb2AsCommandByte:

  bitRS = 0         ; Send byte as a command

Sendb2AsDataByte:

  bitD4 = bit20      ; Send msb first
  bitD5 = bit21
  bitD6 = bit22
  bitD7 = bit23

  bitE  = 1
  secondNybble = b3        ; secondNybble holds msb with E set
  bitE  = 0         ; b1 holds msb with E clear

  HI2cOut b3, ( secondNybble, b3 )

  bitD4 = bit16      ; Send lsb second
  bitD5 = bit17
  bitD6 = bit18
  bitD7 = bit19

  bitE  = 1
  secondNybble = b3        ; secondNybble holds lsb with E set
  bitE  = 0         ; b1 holds lsb with E clear

  HI2cOut b3, ( secondNybble, b3 )

  bitRS = 1         ; Send data byte next time
  
  Return

InitializeLCD:
  HI2cSetup I2CMASTER, $4E, I2CSLOW, I2CBYTE

  b2 = $33 : Gosub Sendb2AsInitByte
  b2 = $33 : Gosub Sendb2AsInitByte
  b2 = $32 : Gosub Sendb2AsInitByte
  b2 = $28 : Gosub Sendb2AsCommandByte
  b2 = $0C : Gosub Sendb2AsCommandByte
  b2 = $06 : Gosub Sendb2AsCommandByte
  b2 = $01 : Gosub Sendb2AsCommandByte 

  Pause 2
  return

sendString:
  do : b2 = @bptrinc: if b2 <> 0 then: Gosub Sendb2AsDataByte: endif: loop until b2 = 0
  return
 

PhilHornby

Senior Member
An example using 'glyphs' to form large characters, on a 20x4 display (driven by a 14M2 @ 32MHz)

(It's a real-time display of my Solar PV output - such as it is!)

 

woschx

New Member
success.. success!
The 16x2 display can be controlled immediately with Phil's sample program. I just have to slim it down a bit but other than that it's exactly what I was looking for!
Thanks a lot for this!
Regards
wolfgang
 
Top