0% found this document useful (0 votes)
120 views34 pages

Control Electrical Appliances Using PC

This document describes how to control electrical appliances using a PC's parallel port. It provides a circuit diagram for an interface that connects to the parallel port and allows controlling up to 8 devices. The interface uses opto-couplers for isolation between the PC and relay driver circuitry. Background information is given on parallel ports, their pinouts, registers and programming. The document provides code examples for controlling outputs on the parallel port to turn devices on and off.

Uploaded by

ZeeshanKhalid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
120 views34 pages

Control Electrical Appliances Using PC

This document describes how to control electrical appliances using a PC's parallel port. It provides a circuit diagram for an interface that connects to the parallel port and allows controlling up to 8 devices. The interface uses opto-couplers for isolation between the PC and relay driver circuitry. Background information is given on parallel ports, their pinouts, registers and programming. The document provides code examples for controlling outputs on the parallel port to turn devices on and off.

Uploaded by

ZeeshanKhalid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 34

Control Electrical Appliances using PC

Introduction
Hi there, I was searching the web for a way to allow me to control electrical
appliances using PC and I found it here. Here is a circuit (figure 1) for using the
printer port of a PC, for control application using software and some interface
hardware. The interface circuit along with the given software can be used with the
printer port of any PC for controlling up to eight equipments.
The interface circuit shown in figure 1 is drawn for only one device, being controlled
by D0 bit at pin 2 of the 25-pin parallel port. Identical circuits for the remaining data
bits D1 through D7 (available at pins 3 through 9) have to be similarly wired. The
use of opto-coupler ensures complete isolation of the PC from the relay driver
circuitry.

Background
Parallel port is a simple and inexpensive tool for building computer controlled devices
and projects. The simplicity and ease of programming makes parallel port popular in
electronics hobbyist world. The parallel port is often used in computer controlled
robots, Atmel/PIC programmers, home automation, ...etc... Here is a simple tutorial
on parallel port interfacing and programming, with some examples.
Everybody knows what is parallel port, where it can be found, and for what it is being
used. The primary use of parallel port is to connect printers to the computer and is
specifically designed for this purpose. Thus it is often called as printer Port or

Centronics port (this name came from a popular printer manufacturing company
'Centronics' which devised some standards for parallel port). You can see the parallel
port connector in the rear panel of your PC. It is a 25 pin female (DB25) connector
(to which printer is connected). On almost all the PCs only one parallel port is
present, but you can add more by buying and inserting ISA/PCI parallel port cards.
Parallel port modes
The IEEE 1284 Standard which has been published in 1994 defines five modes of
data transfer for parallel port. They are:
1.
2.
3.
4.
5.

Compatibility Mode
Nibble Mode
Byte Mode
EPP
ECP

The programs, circuits, and other information found in this tutorial are compatible to
almost all types of parallel ports and can be used without any problems (Not tested,
just because of confidence!).
Hardware
The pin outs of DB25 connector is shown in the picture below:

The lines in DB25 connector are divided into three groups, they are:
1. Data lines (data bus)
2. Control lines
3. Status lines
As the name refers, data is transferred over data lines. Control lines are used to
control the peripheral, and of course, the peripheral returns status signals back to
the computer through Status lines. These lines are connected to Data, Control And
Status registers internally. The details of parallel port signal lines are given below:

Pin No Signal
(DB25) name

Direction

Register
Inverted
- bit

nStrobe

Out

Control-0

Yes

Data0

In/Out

Data-0

No

Data1

In/Out

Data-1

No

Data2

In/Out

Data-2

No

Data3

In/Out

Data-3

No

Data4

In/Out

Data-4

No

Data5

In/Out

Data-5

No

Data6

In/Out

Data-6

No

Data7

In/Out

Data-7

No

10

nAck

In

Status-6

No

11

Busy

In

Status-7

Yes

12

Paper-Out

In

Status-5

No

13

Select

In

Status-4

No

14

Linefeed

Out

Control-1

Yes

15

nError

In

Status-3

No

16

nInitialize

Out

Control-2

No

17

nSelectPrinter

Out

Control-3

Yes

18-25

Ground

Parallel port registers


As you know, the Data, Control and Status lines are connected to there
corresponding registers inside the computer. So, by manipulating these registers in
program, one can easily read or write to parallel port with programming languages
like 'C' and BASIC.
The registers found in a standard parallel port are:
1. Data register
2. Status register
3. Control register
As their names specify, Data register is connected to Data lines, Control register is
connected to Control lines and Status register is connected to Status lines. (Here the
word connection does not mean that there is some physical connection between
data/control/status lines. The registers are virtually connected to the corresponding
lines.) So, whatever you write to these registers will appear in the corresponding
lines as voltages. Of course, you can measure it with a multimeter. And whatever you
give to Parallel port as voltages can be read from these registers (with some
restrictions). For example, if we write '1' to Data register, the line Data0 will be
driven to +5v. Just like this, we can programmatically turn on and off any of the Data
lines and Control lines.

Where these registers are?


In an IBM PC, these registers are IO mapped and will have an unique address. We
have to find these addresses to work with the parallel port. For a typical PC, the base
address of LPT1 is 0x378 and of LPT2 is 0x278. The Data register resides at this base
address, Status register at base address + 1 and the control register is at base
address + 2. So, once we have the base address, we can calculate the address of
each register in this manner. The table below shows the register addresses of LPT1
and LPT2.
Register
Data register (baseaddress + 0)

LPT1 LPT2
0x378 0x278

Status register (baseaddress + 1) 0x379 0x279


Control register (baseaddress + 2) 0x37a 0x27a

Using the code


I will use Inpout32.dll (or
has the following features:

hwinterface.ocx) for Win 98/NT/2000/XP. This DLL

1.
2.
3.
4.

Works seamless with all versions of Windows (Win 98, NT, 2000 and XP)
Using a kernel mode driver embedded in the DLL
No special software or driver installation required
Driver will be automatically installed and configured automatically when the
DLL is loaded
5. No special APIs required, only two functions Inp32 and Out32.
6. Can be easily used with VC++ and VB or C#.
Collapse

val=axHwinterface1.InPort(888);
axHwinterface1.OutPort(888,(short)(val|2));

The above code reads the value from port 0x378 (888 decimal) and then OR with
value 2. This code will send value 1 to D1.

Hint
For a value=0, all the outputs (D0-D7) are off. For value=1, D0 is ON, value=2 D1 is
ON, value=4 D2 is ON, and so on. E.g., if value=29 (decimal) = 00011101 (binary)
-> D0, D2, D3, D4 are ON and the rest are OFF.

Points of Interest
You can use voice recognition (or DTMF) to control your house by this method (Smart
House).

I/O Ports Uncensored - 1 - Controlling LEDs


(Light Emiting Diodes) with Parallel Port

Introduction
This article is on reaching ports, controlling external devices and electronics. Perhaps
you are asking "why?" The idea is simple: It is to achieve something that is real,
physical and emotional. As a freelancer I have been coding for about 4 years for my
own interest. At first I started with C but now for the GUI, I use mostly C# .
Therefore a lot of people participating in the codeproject can declare and assign a
variable in more than one language:

C:

PHP:

VB: //I don't know VB so I


looked at MSDN

int variable
= 5;

$variable
= 5;

Dim variable As
Integer = 5

We can do things, however we do same things using different methods. By working


in different ways we improve our skills, but everyday something new comes and we
need to look for the references. For eg: there are differences in .NET Framework 1.0
and 1.1, MSDN says "we have improved" blah blah blah... Who cares?!... As a result,
you need to make some changes in your old program and this is a pain...
Anyway, a friend of mine said: "You have to pass your electronic knowledge with
everybody..." This is why I am writing this article.

PART 1 - Some basics of a parallel port


What is a port?
A port contains a set of signal lines that the CPU sends or receives data with other
components. We use ports to communicate via modem, printer, keyboard, mouse
etc. In signaling, open signals are "1" and close signals are "0" so it is like binary
system [See Part 3]. A parallel port sends 8 bits and receives 5 bits at a time. The
serial port RS-232 sends only 1 bit at a time but it is multidirectional so it can send 1
bit and receive 1 bit at a time...

Parallel Port - Data Ports:


In my application, I used the data ports which can be seen in the picture from D0 to
D7
Parallel Port - Status Ports:
These ports are made for reading signals. The range is like in data ports which are
S0-S7. But S0, S1, S2 are invisible in the connector (See my picture in the article). I
mentioned these are for reading signals but S0 is different, this bit is for timeout flag
in EPP (Enhanced Parallel Port) compatible ports. The address of this status port is
0x379 . this will always be refer to "DATA+1" and it can send 5 numeric data from
the 10 - 11 - 12 - 13 - 15 th pins. So how can we reach the data ports? It is simple:
every parallel port has an address. In Windows 2000, you can see yours by Settings
> Control Panel > System > Hardware > Device Manager > Ports (COM & LPT) >
Printer Port(LPT1) > Properties = in Resources > Resource Setting and you can see
your address for your parallel port. For Ex: Mine is 0378-037F. This is hexadecimal

like in math (mod 16). 0x378 belongs to 888 in decimal form. In this way you can
look for your com port or game port addresses. Let's enlighten these bits with a
printer example:

S0: This bit becomes higher (1) if a timeout operation occurs in EPP mode.
S1: Not used (Maybe for decoration :))
S2: Mostly not used but sometime this bit shows the cut condition (PIRQ) of
the port
S3: If the printer determines an error it becomes lower (0). Which is called
nError or nFault
S4: It is high (1) when the data inputs are active. Which is called Select
S5: It is high(1) when there is no paper in printer. Which is called PaperEnd,
PaperEmpty or PError
S6: It sends low impact signaling when the printer gets a one byte data.
Which is called nAck or nAcknowledge
S7: This is the only reversed pin on the connector (see my table in the article)
. If the printer is busy and it cannot get any additional data this pin becomes
lower. Which is called Busy

Parallel Port - Control Ports:


This port usually used for outputting but these can be used for inputting. The range
is like in data ports C0-C7 but C4, C5, C6, C7 are invisible in connector. And the
address for this is 0x37A

C0: This pin is reversed. It sends a command to read D0-D7 on the port.
When the computer starts it is high in the connector. Which is called nStrobe
C1: This pin is reversed. It sends a command to the printer to feed the next
line. It is high in the connector after the machine starts. Which is called Auto
LF
C2: This pin is for reset the printer and clear the buffer. Which is called nInit,
nInitialize
C3: This pin is reversed. Sends a high(1) for opening data inputs. It is low
after the machine starts. Which is called nSelectIn
C4: Opens the cut operation for the printer. Not visible in the connector...
C5: Sets the direction control in multidirectional ports. Not visible in the
connector...
C6: Not used and also Not visible in the connector...
C7: Mostly not used but it is used as a C5 in some ports. Not visible in the
connector...

Parallel Port -Ground Pins:


These are (G0 - G7) the pins from 18 to 25 . These are mostly used for completing
the circuit.
After these I used data ports in my application because there are reversed pins in
control and status ports. Here is an explanation for reversed pins: While you are not
sending any signals to the data port it is in closed position like "00000000" so the 8
pins have no voltage on it (0 Volt) .If you send decimal "255" (binary "11111111")
every pin (D0-D7) has a +5 Volt... On the other hand, if I used control ports, there

are reversed pins which are C0, C1 and C3 so while we send nothing to the control
port its behaviour is "0100" in binary (decimal "11")... If I receive e-mails from you I
can make apps using control and status ports...

Signal

BIT PIN Direction

-Strobe

C0 1

Output

+Data Bit 0

D0

Output

+Data Bit 1

D1

Output

+Data Bit 2

D2

Output

+Data Bit 3

D3

Output

+Data Bit 4

D4

Output

+Data Bit 5

D5

Output

+Data Bit 6

D6

Output

+Data Bit 7

D7

Output

10

Input

+Busy

S7 11

Input

+Paper End

S5

12

Input

+Select In

S4

13

Input

-Auto Feed

C1 14

Output

-Error

S3

15

Input

-Initialize

C2

16

Output

-Select

C3 17

Output

Ground

S6
Acknowledge

1825

Ground

PART 2 - Electricity - Lets get some Zzzzzttt zzzzttt...


I made an electrical circuit to show you how our circuit work. It is shown in the
picture...

And also I get different angled pictures of my complete circuit. Click for the bigger
ones.

Ok then let's find out what we have to supply:

1 or 2 meter parallel port cable (3 mt is acceptable but the voltage drops from
5 V to 4.7 V)
9 assembling cables (8 go to resistance and 1 go to ground)
A Breadboard (white one in the picture) or you can solder the cables but with
a breadboard you don't have to...
8 Leds (2,5 V)

8 Resistances (470 ohm) (For not to make the leds garbage because of +5V)
A Multimeter (Not needed but if something happens you can check the wiring
with this...)
My Program to make your circuit live :)

Assemble the circuit as in the picture if it is not clear, e-mail me as [email protected] and
I will send you the bigger pictures of the circuits...

Part 3 - Hexadecimal / Decimal / Binary


People who have knowledge about the subject can easily pass this part...
Binary = 0, 1 --> 2 digit
Decimal = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 --> 10 digit
Hexadecimal = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F --> 16 digit

Ex 1: We
have a six
digit binary
number like
"100111"
and we want
to make it
decimal so
what we
have to do?

Ex 2: We
have a two
digit decimal
number like
"11" and we
want to
convert it to
binary???

Ex 3: We
have a three
digit
hexadecimal
number like
"21F" and
we want it to
convert to
decimal???

The logic is in these three examples but nobody does the conversion like this. They
use Windows operating system's scientific calculator. So if a conversion is needed I
use Start > Programs > Accessories > Calculator . or you can make your own
conversion program. Also you can check my loop (enumerated checkboxes) func in
my app for binary to decimal conversion.

Part 4 - Before coding


Before coding I want to give some info about reaching the ports by using a language
and OS. When I was using Windows 98 I could reach the ports with a function which
is "outportb". When I upgraded to Windows 2000 this failed because of its kernel.
You can not reach the ports directly in NT, 2000 and XP because of their kernel and
their printer drivers. Let me prove this: First make the circuit as in the pic and then
shutdown your computer, start it, if you have multi boot menu select Windows 98,
when it starts there is no light up in the circuit but in Win2000 and XP all the 8 lights
are on so we know that the signal is coming and the pins are registered by their
kernel with the printerdriver.

Part 5 - Lets make the code to do the rest


I used inpout32.dll in my app for interoping. You can check the workflow below
for inpout32.dll and also you can get the source of the dll from here .
Note: I am importing it with the reference of http://www.logix4u.net/ So for further
info about the driver check out the site...

In my PortInterop.cs I used the following:


Collapse

using System;
using System.Runtime.InteropServices;
public class PortAccess
{
[DllImport("inpout32.dll", EntryPoint="Out32")]
public static extern void Output(int adress, int value);
}

So you have to import inpout32.dll to your debug or release directory. By the way,
the main thing in my Form1.cs isPortAccess.Output. It takes two variables
which are address and value. If your data ports are set in "0x378" (see Part 1) you
will have to write "888" because "378" Hexadecimal is equal to "888" in decimal.
(Default LPT1 is set to "378") If you are using LPT2 which is "0x278" you have to
write for the address "632" For ex: for full signaling to pins we have to call
the Output method of PortAccess like:
Collapse

PortAccess.Output(888, 255);

And for null data we have to send "0" to the Output method like:
Collapse

PortAccess.Output(888, 0);

I wrote a func for reseting the LEDs which is:


Collapse

private void Reset_LEDs()

{
PortAccess.Output(adress, 0);
}

I didn't use loops for checkboxes and pictureboxes you can also enumerate these for
quick coding. First, I do like that but after I changed to several if-else statements
because I had to change the GUI. But I left them on the code for performance issues
anyone who want speed can use these.
You can also reach your ports with Turbo C++ like:
Collapse

#include <conio.h>
#include <dos.h> // For _out
#define port 0x378 // Port Address
#define data port+0 // Data Port of the parallel cable
void main (void)
{
_out(data, 255); // For all lights on
_out(data, 0); // For all lights off
}

Last Part - Conclusion


I think you will find this to be the most exciting part of this article... So what can you
do besides powering small LEDs? You can... Search the net about relays for
triggering higher voltages, search some electrical newsgroups and then make circuits
and connect them to your parallel port, light up your room lights or turn on your TV
etc etc... You can do a thousand things it is up to your imagination... I am planning
to write more articles about relays, lcds, oscillators and things like that (of course
with PC connection)... Below is a picture of my next article...

Final Note
English is not my first language, so please excuse any mistakes. This is my first
article for codeproject, so any suggestions and/or feedback will be appreciated.
Thanks for reading till here.

I/O Ports Uncensored Part 2 - Controlling LCDs


(Liquid Crystal Displays) and VFDs (Vacuum
Fluorescent Displays) with Parallel Port

LCD App Source Files - 17.8 Kb

Before You Start


If you want to understand the logic of these I/O ports and want to make a quick start
to LCD you have to check out my first article. If you don't need the logic and only
need a quick live work, do the circuit in part 2 and download my program to make
LCD live.

Part 1 - What is an LCD and what is it for?


Don't be afraid, I won't give a history lesson like every other article out there does
but I want to say why we are using all these LCDs from the time when it was first
invented. At first we used LEDs and then 7SDs appeared now we are using LCDs
because of their capability of showing not only numbers also showing letters and all
kind of symbols. I used a character based LCD see it's datasheet here. It has a
HD44780(Hitachi) compatible KS0066U controller. Samsung made this controller and
if you are interested in the electronic stuff, you can download the controller info from
here These controllers are not much complicated like today's graphic LCDs' (Palms,
New Generation Digital Cameras, Nokia and other cell phones) controllers but they
have been used in commercial and industrial products around the world. Because of
their basic interface they can talk to the old Z80, 6502 and/or the PIC
microcontrollers which are considered as one of the most popular microcontrollers by
the hobbyists. You can find additional info on microcontrollers
at http://www.microchip.com/
Let me explain what VFDs are: VFDs (Vacuum Fluorescent Displays) are also like
LCDs. These are commonly used in microwaves and some pocket calculators. See a
sample picture of a VFD here. The key is controllers so there are HD44780 compliant
VFDs around. I like VFDs more than LCDs because they are brighter than LCDs but
they are also more expensive than LCDs so I used an LCD in my article.
What are the shapes of these LCDs? I used a 2x16 (2 row(line) x 16 column) LCD in
my article as you can see in the above picture. There are lots of LCD types such as
1x8, 2x8, 1x16, 1x20, 2x20, 2x20, 2x10, 1x40 and there are also many different
vendors. And if there are more than 80 characters, mostly they use 2 controllers on
the LCD (Mine has one - This is important). I don't give any lcd structure information
due to codeproject's concept if somebody wants to learn about how these LCD
structures are check these two urls:
1. Samsung's LCD structure and type article
2. Sharp's The Principles of LCD Technology article

Part 2 - LCD Connections, Pinout Descriptions and Circuit


LCD Connections
Mostly an LCD has a 14 pin connection which are D0-D7 (Data Bits), E (Enable), R/W
(Read/Write), RS (Register Select), Vee or Vo (Contrast), Vdd or Vcc (+5V supply),
Vss (Ground/Earth connection) so there are 8 data, 3 power and 3 control lines for a
standard non-backlight LCD. If an LCD has a backlight it has additional two lines for
that which are 15th (VB+) and 16th(VB- or Ground) lines. Below there is a table of
the pin matches and pictures of my LCD's backsides:

Standard LCD Pin Matches (Character number <80)


Pin

Symbol/Alternate
Possibility Function
Symbol

Vss

Power
supply
(GND)

Vdd/Vcc

Power
supply
(+5V)

Vee/Vo

Contrast
adjust

RS

0/1

0=
Instruction
input / 1 =
Data input
0 = Write
to LCD
module / 1
= Read
from LCD
module

R/W

0/1

1, 1-->0

DB0

0/1

Data pin 0

DB1

0/1

Data pin 1

DB2

0/1

Data pin 2

10

DB3

0/1

Data pin 3

11

DB4

0/1

Data pin 4

12

DB5

0/1

Data pin 5

13

DB6

0/1

Data pin 6

14

DB7

0/1

Data pin 7

Enable
signal

If your LCD has more than 80 characters (like 4x40)


15
16

E2

1, 1->0 Enable signal row 2 & 3


Not used mostly

HY1602B (Hyper 1602B) with KS0065 controller (compatible with HD44780) and
backlight. Click for a bigger picture

1602-04 with KS0066U controller (compatible with HD44780) and backlight Click for a
bigger picture

These are 2 different 2x16 LCDs as in the pictures the 15th and 16th pins are for
backlight as I mentioned above.
Pinout Descriptions
Pin 1,2,3

According to the table, I call Pin 1(Vss),2(Vdd/Vcc),3(Vee/Vo) power pins because


they are the gates to power. Pin 1 is for ground so you have to connect to
ground/earth and Pin 2 is for the +5V power supply. 6V or 4,5V is mostly acceptable
in few amperes and also 3V is acceptable on some of the LCD modules (You can also
power these modules with a battery in a very economical way). In my application I
get the voltage from the molex cable of the pc which is inside the case. And pin 3 is
for the LCD's contrast adjustment. I did not but you could use a potentiometer(10K
pot will be ok) for changing the contrast of your LCD. See the schematics below
Pin 4,5,6

I call Pin4(RS),5(R/W),6(E) the control buddies because these pins are the arms of
your controller inside your LCD module. Pin 4(RS) is registration select if this pin is
low the data perceived by the data pins taken as commands by the LCD and if this
pin is high the LCD can receive/send 8 or 4 bit character data. I call Pin 5(R/W) clerk
because when this pin is low you can write character to the LCD, if the pin is high
you can read character data or the status information from the LCD. I didn't make
any read operations in my app so I solder this pin to the ground (with soldering this
to the ground I made this pin low - "0" see the below circuits). Pin 6(E) which I call
the guardian, is used to initiate the actual transfer of commands or character data
between the LCD module and the data pins.
Pin 7,8,9,10,11,12,13,14

The eight pins which are DB0-DB7 are the data pins which I call them the workers.
The data can be transferred or fetched from the LCD by 8 or 4 bits. Which one is
better? This is up to you, by the way if you are using a microcontroller and you have
few pins you can use your module in 4 bit mode(by using DB4-DB7). I used 8 bit
mode in my LCD because I used the parallel port which already have 8 bit data lines
(remember my first article, part 1 D0-D7)
Pin 15,16

These two pins are for the backlight of the LCD module. 15th pin goes to the power
supply(VB+) and 16th pin goes to the ground(VB-). Backlight is very useful in dim
environments but some LCD modules don't have backlights. There are multicolored
LCDs around as well.
Circuit
What we need to supply for our circuit? Below is a list of that:
No:
1.

Description
2x16 Paralell LCD must be
HD44780 compatiable

2.

Normal parallel printer


cable

3.

Normal twin power cable

4.

10 way housing and the


PCB header

5.

6 way housing and the PCB


header

6.

Hard drive type power


connector (Molex)

7.

16 PCB terminals

8.

A digital multimeter(must
measure few ampers!), a
solder pen with some
soldering iron

9.

Some patience, and my


program :)

10 K potentiometer (Not
required - needed when
you want to adjust the
contrast of your LCD - see
circuit with potentiometer)

Make the circuit as its shown in the pictures below.

The circuit with potentiometer

The circuit without potentiometer

If your soldering goes well you get a typical test screen of a character based LCD as
its shown below:

Part 3 - Before Coding

Before coding you have to know some of the basic instructions of a HD44780
controller. Below is a table from the Hitachi's old web site which explains the
instructions for HD44780 compatible LCD. Note: I add some extra info for easy
understanding.

Instruction

Clear display

Code

Description

Execution
time**

Clears
display and
returns
cursor to the
home
position
(address 0).

1.64mS

Returns
cursor to
home
position
(address 0).
Also returns
display being
shifted to
the original
position.
DDRAM
contents
remains
unchanged.

1.64mS

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

Cursor home

Entry mode
set

I/D

Sets cursor
move
direction
(I/D),
specifies to
shift the
display (S).
These
operations
are
performed
during data
read/write.
I/D = 0 -->
cursor is in
decrement
position. I/D
= 1 -->
cursor is in
increment
position. S =
0 --> Shift is
invisible. S =

40uS

1 --> Shift is
visible

Display On/Off
control

Cursor/display
shift

Function set

DL

S/C R/L

Sets On/Off
of all display
(D), cursor
On/Off (C)
and blink of
cursor
position
character
(B). D = 0
--> Display
off. D = 1
--> Displan
on. C = 0
--> Cursor
off. C = 1
--> Cursor
on. B = 0
--> Cursor
blink off. B =
1 --> Cursor
blink on.

40uS

Sets cursormove or
display-shift
(S/C), shift
direction
(R/L).
DDRAM
contents
remains
unchanged.
S/C = 0 -->
Move cursor.
S/C = 1 -->
Shift display.
R/L = 0 -->
Shift left.
R/L = 1 -->
Shift right

40uS

Sets
interface
data length
(DL),
number of
display line
(N) and
character
font(F). DL =
0 --> 4 bit

40uS

interface. DL
= 1 --> 8 bit
interface. N
= 0 --> 1/8
or 1/11 Duty
(1 line). N =
1 --> 1/16
Duty (2
lines). F = 0
--> 5x7
dots. F = 1
--> 5x10
dots.

Set CGRAM
address

Set DDRAM
address

CGRAM address

DDRAM address

Read busy-flag 0
and address
counter

BF

CGRAM / DDRAM address

Sets the
CGRAM
address.
CGRAM data
is sent and
received
after this
setting.

40uS

Sets the
DDRAM
address.
DDRAM data
is sent and
received
after this
setting.

40uS

Reads Busyflag (BF)


indicating
internal
operation is
being
performed
and reads
CGRAM or
DDRAM
address
counter
contents
(depending
on previous
instruction).
I used some
delay
functions in
my code
which are
ThreadSleep

0uS

if you don't
want to use
these you
can check
the Busy
Flag and
make your
LCD speedy.
BF = 0 -->
Can accept
instruction.
BF = 1 -->
Internal
operation in
progress no
additional
operation
can be
accepted.
Write to
CGRAM or
DDRAM

write data

Writes data
to CGRAM or
DDRAM.

40uS

Read from
CGRAM or
DDRAM

read data

Reads data
from CGRAM
or DDRAM.

40uS

* = Not important, Can be "1" or "0"


** = Execution Time is a time needed which the LCD needs for the operation.
CGRAM is character generator RAM, this ram can hold user defined graphic characters. This
capability gains these modules popularity because of this you can make bargraphs and your
own language's special characters(Maybe Chinese, Korean, Turkish, Greek, etc.).
DDRAM is the Display Data RAM for these modules which represents the hexadecimal Display
data adresses. See below:
Char.

1 2 3 4 5 6 7 8 9 10 11 12 13 141516

Line 1 808182838485868788898A8B8C8D8E8F
Line 2 C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF
If you decide to develop your own program after this article, this instruction table will
come in handy. If it comes a bit complicated see Part 4 then you can understand the
logic behind the instructions with coding.

Part 4 - Coding Time

Now we know a lot of things about LCDs so we can write some codes to make our
LCD live. There are three important functions in my app which
are Prepare_LCD | move_to_specific | button_Write_to_screen_Click
The below code(Prepare_LCD) Prepares the LCD after you saw the test screen. I
made the comments as clear as possible so you can examine with the guiding of the
instruction codes above.
Collapse

private void Prepare_LCD(int cursor_status)


{
/* Look at the instruction table to make these comments make sense */
/* Thread.Sleep() function is not needed for some type of LCD instructions
* and also this is changeable from an LCD
* to another so tryout the best for your module */
/* Sends 12(d) = 1100 binary to open the entire display and
* makes a delay that LCD needs for execution */
if(cursor_status == 0)
PortAccess.Output(data, 12); //Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Sends 14(d) = 1110 binary to open the entire display
* and makes the cursor active and also
* makes a delay that LCD needs for execution */
if(cursor_status == 1)
PortAccess.Output(data, 14); //Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Sends 15(d) = 1111 binary to open the entire display, makes
* the cursor active and blink and also
* makes a delay that LCD needs for execution */
if(cursor_status == 2)
PortAccess.Output(data, 15); //Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin high and register pin low */
PortAccess.Output(control, 8); Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin low for LCD to read its
* data pins and also register pin low */
PortAccess.Output(control, 9); Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Clears entire display and sets DDRAM address
* 0 in address counter */
PortAccess.Output(data, 1); //Thread.Sleep(1);

//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin high and register pin low */
PortAccess.Output(control, 8); Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin low for LCD to read its
* data pins and also register pin low */
PortAccess.Output(control, 9); Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* We are setting the interface data length to 8 bits
* with selecting 2-line display and 5 x 7-dot character font.
* Lets turn the display on so we have to send */
PortAccess.Output(data, 56); //Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin high and register pin low */
PortAccess.Output(control, 8); Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
/* Makes the enable pin low for LCD to read its
* data pins and also register pin low */
PortAccess.Output(control, 9); Thread.Sleep(1);
//The delays can be smaller, Check Busy Flag info in the article
}

move_to_specific moves the cursor anywhere on the LCD (anywhere from the 32
option in a 2x16 LCD). See the code below:
Collapse

private void move_to_specific(int line, int column)


{
/* Makes the RS pin low */
PortAccess.Output(control, 8); //Thread.Sleep(1);
if(line == 1)
{
/* Sets RAM address so that the cursor is positioned
* at a specific column of the 1st line. */
PortAccess.Output(data, 127+column); //Thread.Sleep(1);
}
if(line == 2)
{
/* Sets RAM address so that the cursor
* is positioned at a specific column of the 2nd line. */
PortAccess.Output(data, 191+column); //Thread.Sleep(1);
}
}

See the below table for the ascii code binary equivalent for understanding
the button_Write_to_screen_Clickfunction:

Now you can look at the button_Write_to_screen_Click function in the code, I


am not putting it here because I don't want to make the article hard to read but I
commented on it in the app so you can check it out.
Note: You can enable Thread.Sleep functions in the code if your LCD's execution
time is very quick

Part 5 - Before Final Note


Some people say "what will I benefit from an extra LCD?" For those, I made a tiny
thing which grabs codeproject or the msdn rss headlines from the net and displays
them on the LCD screen. Now you can check out the news while you are playing or
watching full screen TV on your computer.

Here you can find the video of that.

As you can see in the video the first line is fixed and the second line scrolls with the
news after a period of time the second news scrols and the third, fourth and goes on.
If you have online site which has some member systems or forums on it, you could
send information using a php or an asp file to a xml or txt file and then fetch the info
from there and send to the screen of your LCD or maybe even your area's forecast.
You can make some periodic e-mail checks and display them on your LCD screen.
You can also interface with your winamp for some spectrum visualization like a plugin
but this will be outer world plugin to your winamp :) so see the motion1 and motion2
buttons for info how to develop these type of solutions:

You can make lots of things with an extra LCD on your desktop and these type of
things are bounded by your imagination so I can say here "Enjoy your
imagination" :)

Final Note
Finally I come to the end of my second article in codeproject. I hope I was able to
put a smile on the faces of those waiting for my second article. After my first article I
get 35-40 e-mails from various people who are interested in these type of things.
People send their works also their circuits about various projects, for ex: some
people sent their year(s) lasting problems on similar projects. So I want to thank you
all for e-mails and also the threads in codeproject. I will be expecting your new
suggestions and comments on this article. Don't abstain to mail at [email protected] if you
have problems.

What will be the third?


I don't want to talk about my next article so I didn't put a picture of it like I did in
the end of my first article because it is after all a mystery.

Parallel Port Pin Control Library (PaPiC)

Introduction
This is a wrapper for the inpout32.dll/inpout32.lib class which is available
at Logix4u.net. For a little theory, please visitLogix4u.net.
This class is useful if you wish to control the 12 output pins of your computer's
parallel port under Windows XP/NT (e.g., driving LEDs, motors and all). This means,
the control pins are used as output. The LPT port has 8 data pins, 4 control pins, and
5 status pins (input), but unfortunately, the basic functions (Console and Port I/O
Routines) do not support direct access to the control pins. For this reason, I have
developed this project: to have more freedom and functionality using the LPT port.
Almost all functions have the same interface as PARAPIN functions, so this class is
useful too if you are adapting your linux code included PARAPIN to Windows
enviroment. Hopefully you will find CPaPiC useful.

Background
This C++ class was inspired by PARAPIN, A Parallel Port Pin Programming Library for
Linux, which was developed by Jeremy Elson and Al Hooton.
The realization of this work can never been done without
the inpout32.dll/inpout32.lib from Logix4u.net.

Using the code


Important!
If you are using WinXP, do the following steps:
1. Execute regedit.exe:
2. Find the following registry key:
Collapse

[HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Parport
]

3. Insert a new key named "Parameters" (if it does not exist).


4. Insert a new double word named "DisableWarmPoll" into "Parameters"
with value "1".
5. Restart Windows.
After this. WinXP will not disturb the output if you are switching the status pins.
Before using CPaPiC:
1. Copy the DLL file inpout32.dll and the lib file inpout32.lib to the project folder.
2. From the Project menu, select Settings, go to the tab Link, in Object/ Library
Modules, write inpout32.lib.
You may use CPaPiC in different ways. For example, you can:
1. create a static or dynamic object, or
2. derive your class from CPaPiC.
At first, I will show you how to create a static object and use its member functions
and definitions. In this case, it is possible to use more then one object and control
only the selected pins without the danger of disturbing the others. Let me declare
a CPaPiC object like this:
Collapse

CPaPiC papi;

The constructor sets the default port LPT1, and selects all the input and output port
pins that are active:

Physically:

Two additional definitions that refer to all I/O pins


are LP_INPUT_PINS and LP_OUTPUT_PINS. The LPT port can be changed by
the lpt_init_user() function. For example:
Collapse

papi.lp_init_user(LPT2); // papi will control port LPT2

Furthermore, you may give different memory addresses. (But


only LPT1 and LPT2 are defined.) If you want to select the pins to control, you can
do it this way:
Collapse

papi.pin_input_mode( LP_PIN10 | LP_PIN11 | LP_PIN12 );


// Set input pins 10, 11 and 12 active
papi.pin_output_mode( LP_PIN01 | LP_PIN02 );
// Set output pins 1 and 2 active
// Equivalent code:

papi.pin_mode( LP_PIN10 | LP_PIN11 | LP_PIN12, LP_INPUT );


papi.pin_mode( LP_PIN01 | LP_PIN02, LP_OUTPUT );

Now, only the 10, 11, 12 input pins and the 1, 2 output pins will be available for
the papi object. The port address and active pins are revisable any time. Controlling
the selected pins is very simple. Just have a look at these (PARAPIN-like) functions:

For example:
Collapse

papi.clear_pin(LP_OUTPUT_PINS);
// Set all pins low (if not all have
// been selected, set only selected)
papi.set_pin( LP_PIN01 ); // Set pin 1 high
papi.invert_pin( LP_PIN01 | LP_PIN02 ); // Invert pins 1 and 2
// Loading the values of input pin registers:
lp_pin pins; // Creat a new lp_pin varible
pins = papi.pin_is_set( LP_PIN10 | LP_PIN11 | LP_PIN12 );
// ask the state of the registers of pins 10, 11 and 12
for( int i = 10; i < 13; i++)
if( pins & LP_PIN[i] == 0 )
printf( "pin %d is low\n", i );
// the pin number i is low
else
printf( "pin %d is high\n", i ); // the pin number i is high

In the demo program, you can specify the pin parameters of a function using check
boxes (parameter ofpin_is_set(..) contains all input pins):

I have derived the CPaPiCDlg class from CPaPiC, so my dialog has all the
properties of CPaPiC. So, I can use all its functions instead of creating a
separate CPaPiC object.

You might also like