Cheap LCD Uses USB Serial [Hackaday]

View Article on Hackaday

Browsing the Asian marketplaces online is always an experience. Sometimes, you see things at ridiculously low prices. Other times, you see things and wonder who is buying them and why — a shrimp pillow? But sometimes, you see something that probably could have a more useful purpose than the proposed use case.

That’s the case with the glut of “smart displays” you can find at very low prices. Ostensibly, these are being sold as system monitors. A business-card-sized LCD hooks up via USB and shows your CPU speed, temperature, and so on. Of course, this requires sketchy Windows software. I don’t run Windows, and if I did, I wouldn’t be keen to put some strange service on just so I could see tiny displays of my system information. But a 3.5-inch IPS LCD screen for $15 or less probably has some other uses. But how to drive it? Turns out, it is easier than you think and the hardware looks reasonably hackable, too.

Like a lot of this cheap stuff, these screens are sold under a variety of names, and apparently, there are some subtle differences. Two of the main makers of these screens are Turing and XuanFang, although you rarely see those names in the online listings. As you might expect, though, someone has reverse-engineered the protocol, and there is Python software that will replace the stock Windows software the devices use. Even better, there is an example of using the library for your own purposes.

Inside Hardware

There’s not much behind the metal cover. Taking out the two screws reveals this neat layout.

The hardware is super simple — at least, the variant I have. A cheap CH552T CPU is an 8051 with a USB core. It should be possible to crack into it and reprogram the whole thing, but that seems like a lot of work. There’s a 3.3 V regulator and a handful of small components on the board.

There are two USB-C ports and a connector to hook up to a motherboard’s internal USB port. You can only use one of the ports at a time, though. There’s actually only one port. The different ports are there so you can route the wire based on your mounting preference.

From the software standpoint, the thing looks like… a serial port! I was hoping the USB conversion occurred outside the chip since a logic-level RS232 LCD display would have been very cool, indeed! Alas, no. The CH552 has its own USB controller. On the other hand, the device does have two normal UARTs, so it would be possible assuming you could reflash the controller.

Inside Software

The Python software is pretty simple to use. There are several versions of the display, and you do need to know which one you have: mine is a revision B. The software can find the serial port automatically, which seems to work well, or you can specify a port number. You can use simple calls to clear the screen, draw text, lay down images, and draw “progress bars” that the stock software uses as a meter.

Reading the code, there are several commands available. One provides a handshake with the display. You can also set the LED lighting, the brightness, and the orientation, portrait or landscape. To display text or graphics, you build an image and send that to the display.

The code provided uses the Pillow library for Python. Of course, it would be possible for you to directly interact with the screen in your own applications using the serial port directly. The underlying protocol sends 8 bytes at a time in a 10-byte packet. The code is easy to read, so you could easily work out your own drivers if you wanted to.

A Quick Example

Naturally, I had to try it out for myself. My goal? Show the last Hackaday headline on the diminutive screen. I stuck with Python since the libraries were ready to go, and I prepared a Jolly Wrencher graphic with a little room on the bottom.

The code just opens the display, scrapes the headline, draws it, and then quits. If you want constant updates, you must run the whole thing from a cron job or a systemd timer.

Here’s the code:

#!/usr/bin/env python3

import requests

from bs4 import BeautifulSoup
from library.lcd.lcd_comm_rev_b import LcdCommRevB, Orientation

# init LCD
lcd=LcdCommRevB() # default is AUTO,320,480
lcd.Reset() # Does nothing for Rev B hardware
lcd.InitializeComm()
lcd.SetOrientation(Orientation.LANDSCAPE)
lcd.SetBrightness(10);

# background graphic
back='had.png'
lcd.DisplayBitmap(back)

# scrape
r=requests.get('http://www.hackaday.com')
if (r.ok) :
   soup=BeautifulSoup(r.content, 'html.parser')
   entry=soup.find('div', class_='entry-intro')
   title=entry.findAll('a')[1].text;
# put title on LCD
   print(f"Found {title}n")
   lcd.DisplayText(" " + title, 0, 280, font_size=16, font_color=(0,0,0), background_color=(255,255,255))
   exit(0)
else : # error message
   lcd.DisplayText(" Internet error!", 0, 280, font_size=16, font_color=(0,0,0), background_color=(255,255,255))
exit(1)

The BeautifulSoup library makes it easy to pull the title — at least until we do a site redesign. After that, it is just a matter of calling DisplayText. You can find the code and the graphic you need on GitHub. A good idea to grab it from there since the browser display of the code above is always suspect when you need indentation.

If you need a quick and dirty (and cheap) LCD and you have a USB host port and Python, this could be just the ticket. Even without Python, the protocol would be easy to replicate. We are still tempted to reflash the CH552 to convert it to use a normal serial port. If you decide to give it a go, you’ll need to figure out programming. The header would be a good place to pull up the D+ pin to 3.3V to enter bootloader mode. Let us know how you do!