Linux example code for Sure Electronics LCD




Sure Electronics make really nice LCD displays at a great price. The DE-LD023 is a 20x4 white on blue LCD that has a built in temperature sensor and is controlled by USB.

The DE-LD023 LCD uses the CP2102 USB to UART Bridge Controller for communication to the host computer via the USB port.

One of these Liquid Crystal Displays was purchased to interface to the RMS-200 board to display voltage, io, temperature, and other board functions. The fun came to an abrupt halt when I realized that I could not program the display. The windows software that is included with the LCD kit was able to display text and graphics to the LCD, but I could not make anything appear with my own Linux C code. Over several days I battled with this problem. The manufacturer would only point me to the PDF documentation that is not complete (ie. the initialization sequence is not described). I finally figured out how to control the LCD with my own Linux C program and would like to share my findings with others that may be struggling with the same problem.

First, a BIG thanks to Laurent Latil for making the Sure Electronics driver in LCDproc program that my code is based on.

The comment below is from the LCDproc Sure Electronics driver.
/*
 * It should be noted that the communication protocol, while somewhat
 * documented in the LCD user's manual, is not complete (ie. the
 * initialization sequence is not described), and inacurate on some points.
 * This driver is so based on the spying of serial communication using the
 * officially supported client softwares (LCD Smarties & SureLCD).
 */


How I made it work.


You must have the Linux CP210x driver version 0.09 or newer. I spent countless hours with v0.08 and was getting write() errors.

I ripped the Sure Electronics initialization code out of the LCDproc program and adapted it to my program. Below is a small program that initializes the LCD, and displays some text. The code is not optimized in any way, but is merely an example of how to display text on the DE-LD023 display.

Dan Pattison
EtherTek Circuits

#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <termios.h>
#include <strings.h>

/* Function Declarations */
void lcd_init(void);
void backlight_on(void);
void backlight_off(void);
void clear_screen(void);
void print_banner(void);
void lcd_close(void);

/* Structures */
struct termios saved_tty_parameters;	/* old serial port setting (restored on close) */
struct termios portset; /* new serial port settings */

int main(int argc, char **argv)
{
lcd_init();
clear_screen();
print_banner();
lcd_close();
exit(0);
}

/****************************
*                           *
*   Subroutines go Below    *
*                           *
****************************/



//************************
//* Init LCD             *
//************************

void lcd_init(void)
{
	unsigned char cmd[3] = {'\xFE', '\x56', 0};
	unsigned char init_seq[7] = {'\x54', '\x58', '\x4B', '\x52', '\x44', '\x41', '\x60'};
	int i;
	
	fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
	if (fd == -1) {
		printf("SHAZBOT! Open failed\n");
		exit(1);
	}
	tcgetattr(fd, &portset);
	tcgetattr(fd, &saved_tty_parameters);

	/* Set port parameters */
	portset.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
			     | INLCR | IGNCR | ICRNL | IXON);
	portset.c_oflag &= ~OPOST;
	portset.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	portset.c_cflag &= ~(CSIZE | PARENB | CRTSCTS | CSTOPB);
	portset.c_cflag |= CS8 | CREAD | CLOCAL;
	portset.c_cc[VMIN] = 1;
	portset.c_cc[VTIME] = 10;

	/* Set port speed */
	cfsetospeed(&portset, B9600);
	cfsetispeed(&portset, B9600);

	/* Do it... */
	tcsetattr(fd, TCSANOW, &portset);

	
	/* Send initialization sequence */
	for (i = 1; i <= 8; i++) 
	{
		cmd[2] = i;
		if (write(fd, cmd, sizeof(cmd)) == -1)
			{
			  printf("SHAZBOT init failed\n");
			  close(fd);
			  exit(1);
			}
	}

	for (i = 0; i < sizeof(init_seq); i++) 
	{
		if (write(fd, (const unsigned char *)"\xFE", 1) == -1
		    || write(fd, &(init_seq[i]), 1) == -1)
			{
			  printf("SHAZBOT init failed\n");
			  close(fd);
			  exit(2);
			}
	}
	usleep(100000); //sleep 0.1 of a second <- really important
}

//************************
//* LCD Close            *
//************************
void lcd_close(void)
{
	if (tcsetattr (fd,TCSANOW,&saved_tty_parameters) < 0)
    	{
    		printf("Can't restore terminal parameters!\n");
    	}
	close(fd);
}


//************************
//* Back Light OFF       *
//************************
void backlight_off(void)
{
	unsigned char cmd1[2] = {'\xFE', '\x46'};
	if (write(fd, cmd1, sizeof(cmd1)) == -1) 
	{
		printf("Back Light OFF failed!\n");
		close(fd);
		exit(1);	
	}
	usleep(100000); //sleep 0.1 of a second <- really important
}

//************************
//* Back Light ON        *
//************************
void backlight_on(void)
{
	unsigned char cmd_bl[3] = {'\xFE', '\x42', '\x0'};
	if (write(fd, cmd_bl, sizeof(cmd_bl)) == -1) 
	{
		printf("Back Light ON failed!\n");
		close(fd);
		exit(1);
	}
	usleep(100000); //sleep 0.1 of a second <- really important	
}

//************************
//* Clear LCD Screen     *
//************************
void clear_screen(void)
{
	unsigned char row1[4] = {'\xFE', '\x47', '\x01', '\x01'};
	unsigned char row2[4] = {'\xFE', '\x47', '\x01', '\x02'};
	unsigned char row3[4] = {'\xFE', '\x47', '\x01', '\x03'};
	unsigned char row4[4] = {'\xFE', '\x47', '\x01', '\x04'};
	unsigned char spaces[20] = "                    ";
	write(fd, row1, sizeof(row1));
	write(fd, spaces, sizeof(spaces));
	write(fd, row2, sizeof(row2));
	write(fd, spaces, sizeof(spaces));
	write(fd, row3, sizeof(row3));
	write(fd, spaces, sizeof(spaces));
	write(fd, row4, sizeof(row4));
	write(fd, spaces, sizeof(spaces));
	usleep(100000); //sleep 0.1 of a second <- really important
}

//*************************
//* Print EtherTek Banner *
//*************************
void print_banner(void)
{
	unsigned char row1cmd[4] = {'\xFE', '\x47', '\x01', '\x01'};
	unsigned char row2cmd[4] = {'\xFE', '\x47', '\x01', '\x02'};
	unsigned char row3cmd[4] = {'\xFE', '\x47', '\x01', '\x03'};
	unsigned char row4cmd[4] = {'\xFE', '\x47', '\x01', '\x04'};
	unsigned char row1txt[20] = "   RMS-200 System   ";
	unsigned char row2txt[20] = " EtherTek Circuits  ";
	unsigned char row3txt[20] = "  (C) 2001 - 2011   ";
	unsigned char row4txt[20] = "                    ";
	
	write(fd, row1cmd, sizeof(row1cmd));
	write(fd, row1txt, sizeof(row1txt));
	
	write(fd, row2cmd, sizeof(row2cmd));
	write(fd, row2txt, sizeof(row2txt));
	
	write(fd, row3cmd, sizeof(row3cmd));
	write(fd, row3txt, sizeof(row3txt));
	
	write(fd, row4cmd, sizeof(row4cmd));
	write(fd, row4txt, sizeof(row4txt));
	
	usleep(100000); //sleep 0.1 of a second
}


DE-LD023 USB LCD owned.
DE-LD023 USB LCD owned.