HD44780    Reading / Sniffing data - Page 1
Forum section: electronics / projects

author: kyndal
author_rank: Regular Contributor
timestamp: March 10, 2020, 03:45:41 am
content: Hi guys, I'm starting up a project, and was hoping on some input on what direction to takeI have an older alarm system using the standard HD44780 LCD display 4x20 charsthis alarm is pretty "dumb" and I'm hoping to add some IOT type smarts to it.there does not appear to be any way for me to get any serial data from the box directly.the LCD however does display the some / most of the wanted informationAlarm Status Armed / Disarmed, various messages on alarms, zones etc.my plan is to piggyback on the LCD interface and decode the data as the display is updated by the alarm.i have experimented with a few approaches using an arduino + LCD as "alarm simulator" (updating slowly)and various micros as the "tap"initially i was hoping to use an ESP8266, and either read the whole 8 bit in one go (whole port)or using i2c I/O exepanders like PCF8574 (8bit) / MCP23017-E/SP 16bit(these appear to be way to slow to capture the datastream for a 4x20 char display)i tried looking at using a whole port.. but it seems various pins in a complete port are taken for other purposesI'm having some success on my MEGA2560, triggering via interrupt on the "Enable_pin", to capture the complete PortAand based on RS_pin determine if its a command or ASCII databut my code does seem to somewhat work.. but not well. its not greatI'm starting to think that a parallel - serial "shift in" register cd4021? 74hc166? may be the faster way to go?Have any of you guys done this before? know what does / does not work?at the moment i'm not sure of the display update frequency, (text does not change, unless some alarm update has taken place)i do not know if its run in 4 or 8 bit mode yet.I'm just poking around / proof of concept before taking things appartRune

author: james_s
author_rank: Super Contributor
timestamp: March 10, 2020, 04:12:49 am
content: I would probably use a small CPLD but you could try using a parallel-in shift register. If you latch the data when the E line is asserted you should be able to shift it out of there. You might also manage the same thing using a parallel latch. I suspect the data is only valid very briefly at the time the E line is asserted, these displays were often used on the shared data bus of a microprocessor so there's going to be lots of other data flying by when the display is not being written to.

author: kyndal
author_rank: Regular Contributor
timestamp: March 10, 2020, 05:22:12 am
content: yes..I do have it somewhat working using the "port read" ATMEGA 2560 via with interrupt on "E", but its the long way around if i want an ESP8266 to do IOT stuff.so maby a shift in register is the way to go there.maby an ESP32 has got a whole 8bit port available. must look into thatRune

author: james_s
author_rank: Super Contributor
timestamp: March 10, 2020, 05:23:06 am
content: I think I would try a parallel latch first, something like an octal D type flip flop, that will latch the data and then you can read it out of that.

author: greenpossum
author_rank: Frequent Contributor
timestamp: March 10, 2020, 05:43:38 am
content: You realise the HD44780 instruction set is completely documented?https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controllerIf you're lucky it may be in 4-bit mode and then you only need 6 lines (4 data + RS + clock) to see everything the display receives, otherwise 10 lines. These LCDs are relatively slow. It should be no problem using an interrupt triggered by the clock to sample the RS and data lines, and updating a virtual display inside the MCU. Then you can make sense of the info however you want.

author: kyndal
author_rank: Regular Contributor
timestamp: March 10, 2020, 06:26:13 am
content: @greenpossumyes.. i am familiar with the HD44780 and i AM able to intercept and decode the LCD data as its updated by the alarm(simulator)however. I only have it working on an ATMEGA2560 , using a full 8bit port.its a bit cumbersome to get that string from the Atmega, over to an ESP8266, that can THEN do something clever with itit would be handy if the ESP can read the LCD directly.Rune

author: greenpossum
author_rank: Frequent Contributor
timestamp: March 10, 2020, 07:53:53 am
content: If necessary just build up the byte from bits taken from reads of ports using C's shift and masking operations. With a modern MCU, it will still be fast enough.

author: kyndal
author_rank: Regular Contributor
timestamp: March 10, 2020, 08:31:38 am
content: @greenpossumI'm currently reading in the bytes, adding them to an array based on its index.and based on various command bytes, I'm using them as "framing" changing arrays mid read-in to fill (and pad to full) 4x16 char "line" arrays.those i can then compare the ASCII of known Lines under various conditionsif (String(lcd_line3) == known_string2) {Serial.println("** ALARM in the bunker **");}i can probably go down and compare parts of the strings. but its not too many full strings to have as "known"i just need the ESP to grab the data instead of having another damn Arduino stuffed in the boxRune

author: greenpossum
author_rank: Frequent Contributor
timestamp: March 10, 2020, 08:39:51 am
content: Quote from: kyndal on March 10, 2020, 08:31:38 amAnd if you have enough input lines, even if they don't all belong to the same port, you can.

author: kyndal
author_rank: Regular Contributor
timestamp: March 10, 2020, 09:51:54 am
content: @greenpossumi have enough input lines, but i have only had luck with reading a "whole 8bit port""digital read" has been too slow.i suppose i could try reading 4 bits ea off two ports and add them together? (as i would if the display turns out to be driven 4bit)or do you have something else in mind?Rune

author: greenpossum
author_rank: Frequent Contributor
timestamp: March 10, 2020, 09:59:09 am
content: Quote from: kyndal on March 10, 2020, 09:51:54 amSure, that's the general idea.nybble1 = portA & 0x0F;nybble2 = portB & 0x0F;combined = (nybble1 << 4) | nybble2;Toss in more masks and shifts as necessary to build up a byte.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 10, 2020, 10:52:48 am
content: Don't use Arduino digitalWrite or digitalRead for anything you want to do quickly. You can find fast IO libraries or just access the registers yourself.

author: Ian.M
author_rank: Super Contributor
timestamp: March 10, 2020, 12:19:29 pm
content: IMHO a lot of your problems could be solved by a 8 bit PISO shift register then SPI to the Arduino or ESP. If the ESP is busy with WiFi, you'll probably need a FIFO buffer as well in front of the shift register as the worst case interrupt response is likely to miss bytes.Next step: put a logic analyser on the HD44780 interface you want to sniff and get hard worst case timings for the minimum time between bytes.

author: kyndal
author_rank: Regular Contributor
timestamp: March 10, 2020, 09:24:05 pm
content: @Prehistoricman exactly.. that's why i have been using the "port read" approach (LCD_port_Read = PINK;) //Pins on port Kwhich so far has limited my hardware options a bit.. but I'm going to experiment with @greenpossum's idea of doing two separate port reads, each providing two 4bit halfs each.Shift one and add.or probably simpler.. on the ESP if i stop using the hardware serial port. i believe i would have a full port available.@Ian.M Yes.. I'm leaning towards PISO too.. but you are correct. i would want to ensure i dont miss an update, as the display likelygoes from "no alarm" to "alarm" in one update.. and i suspect it does not refresh the LCD in steady state. (no clock / date etc).and missing that one update would defeat the whole purpose of this exercise.rune

author: james_s
author_rank: Super Contributor
timestamp: March 10, 2020, 11:36:42 pm
content: I would expect that the display is updated at a glacial speed compared to what the ESP is doing. If you have the same line that latches data into the display latch data into the shift register then the register should always have the latest data in it. As long as you either dump the shift register regularly or check it when you detect a pin change on the enable line you should be fine. When enable de-asserts that's a good indication that the system has finished writing something to the display. Those LCD displays are really slow, you can easily send data to one with an arduino faster than the display can accept the data.

author: Prehistoricman
author_rank: Regular Contributor
timestamp: March 11, 2020, 02:24:09 am
content: Quote from: kyndal on March 10, 2020, 09:24:05 pmOh yeah. I should have realised you would already know about this.

author: ozcar
author_rank: Frequent Contributor
timestamp: March 11, 2020, 04:44:54 am
content: Quote from: greenpossum on March 10, 2020, 05:43:38 amNot so sure aboutalwaysbeing able to do it entirely in software. The data does not have to be valid when E goes high - it only has to be there at least 195ns before E falls, and for at least 10ns after that.Reality in the alarm might be much more forgiving though.

author: greenpossum
author_rank: Frequent Contributor
timestamp: March 11, 2020, 04:55:23 am
content: Quote from: ozcar on March 11, 2020, 04:44:54 amThat's probably what the display datasheet says but its driver may be more lax. It's worth finding out before throwing hardware at the problem.

author: ozcar
author_rank: Frequent Contributor
timestamp: March 11, 2020, 05:09:28 am
content: Quote from: greenpossum on March 11, 2020, 04:55:23 amSure, I did say that the alarm use of the display might make it much easier to deal with. Whenever I used one of these displays, I made sure the data lines were valid before raising E, and was in no hurry to change them after dropping E - I tended to chuck a few NOPs in just to be sure.

author: james_s
author_rank: Super Contributor
timestamp: March 11, 2020, 05:58:05 am
content: Quote from: ozcar on March 11, 2020, 04:44:54 amSo trigger the latch on the falling edge, you know the data will be valid at that time and at least 10ns afterward, that should be no problem.

author: ozcar
author_rank: Frequent Contributor
timestamp: March 11, 2020, 08:24:39 am
content: Quote from: james_s on March 11, 2020, 05:58:05 amI was responding to the suggestion that these LCDs are so slow, that an interrupt routine triggered by the clock (E) could sample the RS and data lines (thus obviating the need for a latch).If you generate an interrupt from the rising edge of E, you might sample data which is not yet valid. If you generate an interrupt from the falling edge, you better be quick, as you only have 10ns to respond.You could interrupt on rising E, then spin in the interrupt routine reading the data and then checking for E to fall. You'd have to be reasonably quick in the spin loop, and maybe implement a timeout (unless you can afford to hang there indefinitely - there is a minimum time specified for high level E pulse width, but there is no maximum).To be clear, I'm talking about getting it to work according to the HD44780 specification - in other words, something that will always work. If you "know" more about how the LCD is being driven, as may be the case here, it likely becomes much easier.

author: kyndal
author_rank: Regular Contributor
timestamp: March 12, 2020, 05:39:16 am
content: I have it working "fast enough" on a regular Arduino Nano now so I'm probably going to get lazy,... and use the Arduino as "glue logic" here..its a "one off" project.. have the 2$ Adruino take care of the decoding, (and read some status Led's, housekeeping) and just spit out a serial stream to an ESP8266 module.for the connectivityi do have a Shift register is in the mail thoughRune

author: Ian.M
author_rank: Super Contributor
timestamp: March 12, 2020, 10:16:57 am
content: Probably the best way to go. Although it offends you conceptually to have two MCUs, its much easier for a one-off to offload the hard realtime processing to another MCU than to build LSI/MSI logic to do it, then find out you need to add a FIFO, because you cant quite guarantee to meet the worst case timings.The only different choice I would make would be to chose a different MCU for the realtime processing - personally, I'd probably be lazy and see if I can select a Microchip PIC with a PMP with an addressable parallel slave port mode, to get internal latches for the command and data bytes that can be selected by the LCD RS signal, and clocked by E, qualified by R/nW so I can guarantee in hardware to sample the LCD data bus in the worst case minimum validity window specified in the datasheet, then code it with an eye to future reuse,However having successfully developed an AVR based specific solution, attempting the general solution is probably not worth it for you. Also if you had enough familiarity and the right toolchain for a different family of MCUs or even small FPGAs, capable of a 'just the chip' implementation, you probably wouldn't have gone down the Arduino Nano module route.

author: kyndal
author_rank: Regular Contributor
timestamp: March 13, 2020, 07:18:11 am
content: thanks for the input guys.I now have it working "well enough" on an Atmega168, (Arduino nano board) for an "initial attack". in both 4 and 8 bit .at least with my "alarm LCD simulator" as the data source.now i just have to get access to the actual hardware, do some Analysis on the signals..but it "should" conform to the HD44780 timing.. and so i "suppose" my prototype code shouldbe pretty close to working from the get gothe adjustments likely to be required, depends on how the screen is actually updated(full clear screen + new line draws, or cursor moves and single char updates only)Rune

author: Ian.M
author_rank: Super Contributor
timestamp: March 13, 2020, 07:42:19 am
content: You *may* be S.O.L. and find your prototype code isn't efficient enough if the original alarm panel designer cared about fast update rate so used busy bit polling, and they happen to have used a display that has significantly faster than nominal timings.As I said earlier, you *NEED* those timings from a logic analyser on the actual display bus, and force the mode transitions that you *MUST* monitor while on the analyser to be sure there are no nasty timing surprises. If you don't have a logic analyser (no excuse as a Salae Logic 8 clone is dirt cheap and is well supported by the open source Sigrok software), even using a DSO to check just the RS and E signals then check one data bus line against E, will give you a good idea of the timing constraints.

author: kyndal
author_rank: Regular Contributor
timestamp: March 13, 2020, 10:14:33 pm
content: @Ian.M i do have a both logic analyser and a scope.. but no access to the hardware at the momentso for me starting with code that conforms to regular HD44780 timing, and getting the reading and decoding routines working is a good start.i have pictures of the LCD its stock standard as far as i can tell.i see no "technical reason" why the designer of the alarm firmware would need to "push" the update speed.the LCD is static and just goes from stuff like "armed" to "disarmed" when the state changesnot exactly speed criticalhowever... we shall seeRune

author: Jatsoca
author_rank: Newbie
timestamp: May 10, 2022, 09:31:09 pm
content: Quote from: kyndal on March 13, 2020, 07:18:11 amHello, could you please share the arduino code that has worked for you?Thank you.

author: Jatsoca
author_rank: Newbie
timestamp: May 10, 2022, 09:34:47 pm
content: Hello, could you please share the arduino code that has worked for you?Thank you.

author: DavidAlfa
author_rank: Super Contributor
timestamp: May 11, 2022, 07:16:32 am
content: Perhabs you should use Google...https://github.com/fsalomon/HD44780-decoder

author: lukg20
author_rank: Newbie
timestamp: March 09, 2023, 07:38:15 am
content: Hi!Old topic, but I could use some help.I'm a bad programmer, and Arduino and the "C" language is new to me.I have a very unusual 3D printer that I need to extract data from. The only possibility is to listen to the hd44780 display because the printer does not even have a UART. Was it possible to make such a system on the ESP8266 itself (without arduino)?I would just like to display data from the display in a web browser.

author: dgenkov
author_rank: Newbie
timestamp: January 25, 2024, 08:23:27 am
content: Hello,Your code doesn't work with my setup. I use Arduino nano, connected to an LCD display of a coffee maker. It is 4 rows by 20 columns display and uses 8-bit mode.I've changed the following:Code:#define NUM_CHARS 80bool fourBitMode = false;And the divider for the new line to NUM_CHARS/4.The only output I get is the "Ready" message.Can you help me, what could be my mistake?