LCD Display
If you have a Linux PC without a monitor working as a server, but want
to be informed about the current status of the computer, you could use
a Liquid Crystal Display.
LCD & Linux
The connection of a Liquid Crystal Display to a Linux computer has been described
many times and we don't want to repeat old information.
We will describe how you are able to access a LCD via the parallel port with
the program lcd by Nils Fdrber. With four buttons that are
checked by jslaunch you can navigate through your own menu and
execute different commands. Everything without a huge effort in
programming.
The program lcd can be used to communicate with LCDs with
a Hitachi HD44780 chip.
Our article not only discusses the basic access to a LCD but also shows
how an LCD and jslaunch can work together, so you
do not get only a simple status report but also the PC can be
steered interactively.
The Display
You can get this at Conrad-Elektronik (Germany) and it costs about 70,-
DM ($40) for 4 lines and 20 columns without (Best.-Nr. 187267) and about
80,- DM with a back light (Best.-Nr. 187275).
If your computer is placed in a room that is not illuminated very well
you should get a display with a back light.
The display is connected to the parallel port and needs the following connections:
ParPort-cable | Panel | |

In addition, pin 2 of the LCD panel has to be connected to the
+5V power line and the pins 1 and 5 of the display and the pins 18 and 25
of the parallel port to ground.
A nice 5 Volt source inside the PC is the 2-wire floppy power cable
(red cable +5V, black is ground -- test it first!).
The contrast of the display can be changed by a 100 ohm potentiometer. But it should be OK if you connect pin 3 of the display to the ground.
+5V ---+
/
\ <--+
/ |
\ |
GND ---+ +--- VL (Pin 3 - driver input)
The final connection looks like:
25 pin LCD
SUB D Panel Pin
---------------------------
GND 1 --+--- \ Connect to
+5V 2 --|--- / Gameport
R/W 5 --+
1 EN 6 |
2 DB1 7 |
3 DB2 8 |
4 DB3 9 |
5 DB4 10 |
6 DB5 11 |
7 DB6 12 |
8 DB7 13 |
9 DB8 14 |
14 RS 4 |
18-25 GND --+
The connection of pins 18-25 is very important, otherwise you would see flashing signs and boxes on the display.
If you correctly linked everything, you would see two rows with black boxes:

The driver
The latest driver that is used to communicate with the LCD has the
release number 0.152, but we were not able to compile this version. The previous
release 0.151 worked fine for us.
You get this one at the FTP server
ftp://ftp.unix-ag.uni-siegen.de/pub/os/linux/drivers/
(On the server you find a version 0.6.0. That one has the same name
but is a different program.)
First check if you managed to compile the drivers before you go
and buy an LCD. Only after being sure that you can communicate
with the LCD is it worth spending the money!
We only succeeded in compiling the driver on a system with a
2.2.13 and an old 2.0.36 kernel. It failed on the 2.2.16 kernel. LCD-0.151
stopped with an error message. Maybe you will have more luck than us.
Before compiling, you choose your kernel in the file
driver/Makefile (2.0.x or 2.2.x). You have to set the
address of the parallel port in the file
driver/hardware.h:
| driver/hardware.h |
[...]
#define LCD_ADDRESS 0x0378 /* corresponds to lpt1: */
/* #define LCD_ADDRESS 0x0278 */ /* corresponds to lpt2: */
/* #define LCD_ADDRESS 0x3bc */ /* also a possible address for the parallel port */
[...]
|
Delete the comments /* and */ for your address.
If you do not know the address of the parallel port, plug in a
printer, load the printer module:
>> insmod lpand have a look at:
>> cat /proc/ioportsThere you find the address.
If you have a display with a different size than 20x4 you can set this in driver/hardware.h.
| driver/hardware.h |
[...] #define LCD_COLS 20 #define LCD_LINES 4 [...] |
lcd needs the files
/usr/src/linux/include/linux/modversions.h and
/usr/src/linux-2.2.13/include/linux/modsetver.h for compiling
the drivers. But both are missing in our copy of the 2.0.x kernel.
It would work if you copied these files from a 2.2.x kernel into the
proper directory modsetver.h and modversions.h).
If everything was completed you could:
>> makethe program lcd.
Then you'll find the compiled module lcd.o in the subdirectory driver/, which is needed to talk to the LCD.
Finally, you have to create the pseudo file /dev/lcd that will be the device talking to the LCD. This creation is done using the script mkdevice in the subdirectory driver/ (as root).
Next you have to connect the hardware in the right way.
jslaunch
We wrote about Jslaunch in an earlier issue
(Jslaunch -- PC steering via Joystick
).
In combination with an LCD, the usefulnes of the program is extended.
The program jslaunch checks in well-defined time
intervals if the buttons of a joystick connected to the
gameport of the sound card were pressed and would execute
commands depending on the button combination that was pressed.
Jslaunch can be used very comfortably because it does not need any
kernel module to read the joystick port, but gets the
information directly and can be installed easily.
Due to the high stability of the program, it can be used as an
emergency reset. If a few important components of the system
crashed (e.g. keyboard, network and/or Xserver) you would be able to
halt or reboot the system and would not have to use the hard-reset
button.
The easiest way would be if you got a joystick (maybe broken but with the buttons are still working) and separate the cables and buttons from
the stick.
If the display had to have a professional look, you could substitute
the buttons with better looking buttons you would get in any well-stocked
electronics shop.
The program jslaunch does not take much work; you just
have to compile it (>> make).
first test
After everything is connected correctly, you should test the
display.
To do this, you have to load the module of the LCD driver (as root in
the subdirectory driver/):
>> /sbin/insmod lcd.oThen you should see a flashing cursor in the upper left corner. If everything worked well you could copy the module into the directory /lib/modules/2.2.*/misc/ and you do not have to change into the driver/ directory any longer.
To produce an output on the LCD you change into the subdirectory tools/proclcd and compile the program with a
>> makeThe program is started and the output is piped to the /dev/lcd device:
>> ./proclcd > /dev/lcdThen you should see an output on the display like:

By the way, the driver can be removed using:
>> /sbin/rmmod lcdThis would only work if no running process accessed the LCD.
Next you test the joystick.
Start jslaunch with the command:
>> jslaunch -r 1 "echo 1" -r 2 "echo 2" -r 3 "echo 3" -r 4 "echo 4"If you pressed a button, jslaunch would show which button was pressed.
You should write down which number belongs to which button because you will need it later for the LCD steering.
If both (LCD and joystick buttons) worked well, you could place both
into the housing of the PC.
A free slot would be ideal to fix the display and the four buttons. If
the parallel port and/or joystick port was not fixed on a slot card but
was fixed with a cable on the backside of the PC you could remove it
and place it inside of the PC.
The menu
This part describes how you can construct your own menu which can be used via the joystick buttons. This is not a complicate program, just a few simple bash scripts. Even an inexperienced programmer is able to modify these to his desired LCD output.
First, you create a new directory where you collect the scripts for the LCD:
>> mkdir /usr/local/etc/display/There, you create the file own that has to be an executable:
>> touch /usr/local/etc/display/own >> chmod a+x /usr/local/etc/display/ownThe script should look like:
| /usr/local/etc/display/own |
#!/bin/sh
# Just a dumb script copying some nice system information values
# to our LCD device
#
export SLEEP=10
#Button 1,2,4: Menu -- button 3: reboot
echo -n -e "\33c" > /dev/lcd
echo -n -e "\33h" > /dev/lcd
echo -e " " > /dev/lcd
echo -e " Please wait ..." > /dev/lcd
echo -e " ==============" > /dev/lcd
killall jslaunch
sleep 4
/usr/local/jslaunch-2.0/jslaunch -r 1 "killall own && /usr/local/etc/display/menu1"\
-r 3 "killall own && /usr/local/etc/display/reboot"\
-r 4 "killall own && /usr/local/etc/display/menu1"\
-r 2 "killall own && /usr/local/etc/display/menu1"&
#The buttons 1,2 and 4 start the menu
#button 3 reboots the computer
echo -n -e "\33c" > /dev/lcd
while true; do
echo -n -e "\33c"
echo -n -e "\33h"
#The following lines collect information about the PC and show these
#on the LCD step by step
#-- Number of the apache users
export WEB=$(apachectl status | grep reques | cut -d " " -f 4) .
#-- Number of the ftp users
export FTP=$(ftpcount | grep local | cut -d " " -f 22)
#-- Size of the free memory
export MEM=$(cat /proc/meminfo |fgrep "MemFree"|cut -b 13-24)
#-- Uptime of the PC
export UPT=$(uptime | cut -d "," -f 1)
#-- Number of the users logged in
export USER=$(uptime | cut -d "," -f 2)
#-- CPU usage
export LOAD=$(cat /proc/loadavg | cut -d " " -f 1)
#-- The following lines display the information about a
# few mounted devices
# (Zip-drive, cdrom, local-partition...)
export ZIP=$(df | grep "zip" | cut -d "%" -f 2,2)
export LOCAL=$(df | grep "local" | cut -d "%" -f 2,2)
export CDROM=$(df | grep "cdrom" | cut -d "%" -f 2,2)
export ZIP_P=$(df | grep "zip" | cut -b 50-53)
export LOCAL_P=$(df | grep "local" | cut -b 50-53)
export CDROM_P=$(df | grep "cdrom" | cut -b 50-53)
# ***** SCREEN 1 *******
# Here the collected information is shown
# Uptime, Memory, HTTP/FTP-User and Load
echo -e $UPT
echo -e "MEM "$MEM
echo -e "HTTP "$WEB" -- FTP" $FTP" "
echo -e $USER " load:" $LOAD
sleep $SLEEP
# The sleeping time sets how log the info is shown
# ***** SCREEN 2 *******
# List of the mounted devices
echo -n -e "\33c"
echo -n -e "\33h"
echo -e $ZIP_P $ZIP
echo -e $LOCAL_P $LOCAL
echo -e $CDROM_P $CDROM
sleep $SLEEP
# ***** SCREEN 3 *******
# List of all entries in the printer spool
echo -n -e "\33c"
echo -n -e "\33h"
export DRUCK=$(lpq | grep bytes | cut -b 8-18 | tail -n 6)
echo -e "printer queue:"
echo -e $DRUCK
sleep $SLEEP
# ***** SCREEN 4 *******
# Some information about the network device
echo -n -e "\33c"
echo -n -e "\33h"
export ETH_R=$(cat /proc/net/dev | grep eth0 | cut -b 8-14)
export ETH_S=$(cat /proc/net/dev | grep eth0 | cut -b 36-43)
export IPP_R=$(cat /proc/net/dev | grep ippp0 | cut -b 8-14)
export IPP_S=$(cat /proc/net/dev | grep ippp0 | cut -b 36-43)
export IPP_E=$(cat /proc/net/dev | grep ippp0 | cut -b 44-48)
export ETH_E=$(cat /proc/net/dev | grep eth0 | cut -b 44-48)
echo -e " eth0 ippp0"
echo -e "rec " $ETH_R" "$IPP_R
echo -e "sen " $ETH_S" "$IPP_S
echo -e "err " $ETH_E" "$IPP_E
sleep $SLEEP
done > /dev/lcd
|
The scripts are very simple. The required information is shown with
a small command and can be obtained with the tools "grep" and "cut". On
different distributions, this can cause a few problems because the
format of the output of the programs can be different and so the
specified columns in the cut command can be incorrect.
If the specific information did not appear on the display, you should
check the commands by hand and determine the appropriate values.
The information is written in to a variable (e.g. $ETH_E for
the number of all received corrupt packages of the network device) and
then printed via echo.
Instead of this, you could use another program, too:
e.g. procload.
As you can see in line 18, the menu (own) would be killed if you pressed
the buttons 1,2 and 4 and the corresponding menu (here it is menu 1 for all)
would be started.
The following script has to be placed in the directory
/usr/local/etc/display, too, and needs to be an executable.
The file could look like:
| File /usr/local/etc/display/menu1 |
#!/bin/sh
# First you have to stop the old jslaunch because it still owns the
# old configuration
killall jslaunch
# If the previous menu stayed in the sleep modus it has to be
# stopped, too.
killall sleep
# This sleeping time is necessary because the user needs enough
# time to release the button. Otherwise jslaunch does not
# start again.
echo -n -e "\33c" > /dev/lcd
echo -n -e "\33h" > /dev/lcd
echo -e " " > /dev/lcd
echo -e " Please wait..." >/dev/lcd
echo -e " ==============" > /dev/lcd
sleep 4
# Here some information which button has which option
export VERZ=/usr/local/etc/display
echo -n -e "\33c" > /dev/lcd
echo -n -e "\33h" > /dev/lcd
echo " --== Menu ==--" > /dev/lcd
echo " 1 mount zip module" > /dev/lcd
echo " 2 unmount zip module" > /dev/lcd
echo " 3 next" > /dev/lcd
# Now it starts jslaunch with the new options
# 1 == mount Zip
# 2 == unmount Zip
# 3 == e.g. menu, to mount a CD Rom -- the line is
# not active
# 4 == Reboot
/usr/local/jslaunch-2.0/jslaunch\
-r 1 "killall menu1 && /usr/local/etc/display/zip_on"\
-r 3 "killall menu1 && /usr/local/etc/display/reboot"\
# -r 4 "killall menu1 && /usr/local/etc/display/cdrom"\
-r 2 "killall menu1 && /usr/local/etc/display/zip_off" &
# After 15 seconds the menu would go back to the main menu if
# no button was pressed.
sleep 15
/usr/local/etc/display/own
|
The script to reboot looks like the following (also here you could add a security question like "Really reboot?").
| File /usr/local/etc/display/reboot |
#!/bin/sh killall jslaunch killall sleep echo -n -e "\33c" > /dev/lcd echo -n -e "\33h" > /dev/lcd echo -e " " > /dev/lcd echo -e " Reboot now ..." >/dev/lcd echo -e " ==============" > /dev/lcd echo -e " See you soon ;-) "> /dev/lcd sleep 4 reboot |
In menu1 we commented out button 3 because it should now be clear how
you could create your scripts. With button 3, you could got to
an additional menu where you would be able to mount or unmount the CD-ROM
drive, for example.
But any other display could be made, like special status reports.
Every menu has to be placed in a new script file in the directory
/usr/local/etc/display/, that has to be constructed like:
| Basic structure |
#!/bin/sh
killall jslaunch
killall sleep
echo -n -e "\33c" > /dev/lcd
echo -n -e "\33h" > /dev/lcd
echo -e " " > /dev/lcd
echo -e " Please wait ..." >/dev/lcd
echo -e " ==============" > /dev/lcd
sleep 4
# Here a few information about the commands that are executed after
# pressing a button
export VERZ=/usr/local/etc/display
echo -n -e "\33c" > /dev/lcd
echo -n -e "\33h" > /dev/lcd
echo " --== Menu ==--" > /dev/lcd
echo " 1 Button 1 does..." > /dev/lcd
echo " 2 Button 2 does..." > /dev/lcd
echo " 3 next" > /dev/lcd
# Every button gets a command or menu
/usr/local/jslaunch-2.0/jslaunch\
-r 1 "killall this_menu && /usr/local/etc/display/Script1"\
-r 3 "killall this_menu && /usr/local/etc/display/Script2"\
# -r 4 "killall this_menu && /usr/local/etc/display/Script3"\
-r 2 "killall this_menu && /usr/local/etc/display/Script4" &
sleep 15
/usr/local/etc/display/own
|
Using this method you can build your own menu structure without any big effort or great knowledge in any programming language.
start it automatically
The LCD display is ideal for a PC without any monitor or keyboard, but without those the menu has to be started automatically while booting.
Two options exist to accomplish this. Either you add the command that starts the service into the boot.local (placed at /sbin/init.d), or you write a short init script and place this at /sbin/init.d (SuSE) or /etc/rc.d/init.d (RedHat).
The commands that have to be executed start the LCD module and then start the menu script:
/sbin/insmod lcd sleep 2 /usr/local/etc/display/own &If you did not copy the LCD module into a subdirectory of /lib/modules (see above) you would have to specify the full path instead.
So, there it is. The LCD should work and if you wanted to see how it looks in the final state, look at this picture:

| http://www.home.unix-ag.org/nils/lcd.html | Homepage of the program lcd |
| http://www.linux-magazin.de/ausgabe/1999/08/LCD/lcd.html | lcd programmer`s article in the German Linux Magazine |
| ftp://sunsite.org.uk/Mirrors/contrib.redhat.com/libc6/i386/ | Sorry but jslaunch does not have a homepage of its own |
| http://lcdproc.omnipotent.net/ | Drivers for several displays connected to the serial port |
| http://www.mv.com/ipusers/cdwalker/lpt_driver.html | Drivers for several displays connected to the parallel port |
Talkback Area
Enter Own Comment