Control Electrical Appliances Using PC
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
LPT1 LPT2
0x378 0x278
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).
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:
int variable
= 5;
$variable
= 5;
Dim variable As
Integer = 5
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
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...
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
-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
And also I get different angled pictures of my complete circuit. Click for the bigger
ones.
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...
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.
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);
{
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
}
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.
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
E2
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
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.
3.
4.
5.
6.
7.
16 PCB terminals
8.
A digital multimeter(must
measure few ampers!), a
solder pen with some
soldering iron
9.
10 K potentiometer (Not
required - needed when
you want to adjust the
contrast of your LCD - see
circuit with potentiometer)
If your soldering goes well you get a typical test screen of a character based LCD as
its shown below:
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
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
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
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
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.
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
//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
See the below table for the ascii code binary equivalent for understanding
the button_Write_to_screen_Clickfunction:
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.
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.
[HKEY_LOCAL_MACHINE\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\Parport
]
CPaPiC papi;
The constructor sets the default port LPT1, and selects all the input and output port
pins that are active:
Physically:
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.