APLawrence.com -  Resources for Unix and Linux Systems, Bloggers and the self-employed

Serial Printers

© July 2013 Tony Lawrence

The secret to success with printers on serial ports is understanding that the computer and the printer must agree on baud rate and flow control, and that you must have serial ports and wiring capable of supporting the parameters you have chosen.

It is often not important that your serial baud rate be particularly high. Although it is somewhat simplified, 9600 baud can be thought of as 9,600 bits per second. Given some overhead, we can roughly say that dividing that number by 10 gives characters per second. As very few low end printers can even come close to 960 characters per second, you can see that there is usually no need to go any faster. In fact, very few dot matrix printers can keep up with even 2400 baud. That's what flow control is needed for- the printer needs to be able to say "Hey, hold up a second- let me digest what you've already sent me".

There are two choices for flow control: software or hardware. Software flow control is often referred to as XON or XON/XOFF, and you may see hardware flow control referred to as "ctsflow" or sometimes "dtrflow". Under high speed conditions, hardware flow control is preferred, but you do need to know HOW the printer should be wired to set this up, so software flow control is simpler.

The purpose of flow control is so that the printer can tell the computer that it is momentarily overwhelmed, cannot handle any more input right now, and the computer should suspend sending data until the printer notifies it that it is once again ready to receive data. If the computer and the printer do not agree on flow control, you will lose data. Whether or not the printer notifies you that this has happened is entirely up to the designer of the printer, so HP laser printers, for example. will display an error message on their front panel, but many other printers simply throw away data.

Most printers don't rely entirely on flow control. They usually also have a buffer that fills up with incoming data and gets emptied as it prints. If the buffer is larger than the print job, no flow control is necessarily needed. That's why small jobs print OK, but larger jobs may not- when the buffer fills, the printer needs to yell "Stop".

As the computer sending the data might not respond instantly to that request, the printer has a "high water mark" for the buffer. It might, for example, send the "Stop" signal when the buffer is 90% full. Some printers let you control that high-water mark. If yours does, setting it lower could help.

But by default, the Operating System provides NO flow control on a serial port. If nothing else has been done, a serial port will default to 9600 baud, 8 bit, no parity, and NO flow control. That means it will pay absolutely no attention to the printer telling it not to send any more. That's when garbled junk starts spitting out of the printer. You need to set flow control.

How you set this depends on what you have for serial ports. The very first thing you want to do is DISABLE the serial port (example: "disable tty1a"). This may be confusing because you ENABLE a printer attached to a port, but you never, never want a printer port itself enabled for login. To be safe, check the upper case version of the port also ("disable tty1A").

Many intelligent serial ports (Digiboard, Equinox, Computone, Maxpeed) have ways to set and keep serial parameters on their ports. For example, if you have a Digiboard, you can type

"ditty /dev/ttyb02 9600 ixon printer"

to force the port to stay at 9600 with software flow control.

If you are going to put these in a startup script, it may be necessary to delay their execution a few seconds to give the multiport drivers time to get their boards all set up. What I usually do if have a "setprint" script that gets called (/usr/local/bin/setprint &) from /etc/rc2.d/S99printers. That script starts of with a 15 second sleep and then does the "ditty's" and whatever else is needed. In many environments, I also explicitly disable the affected ports so that no accidental getty's are running, and may issue appropriate chmod commands if the ports are used for direct access.

However, for the standard com ports (tty1a, tty2a), it's not as easy, and you need what's called a "hold-open" script.

The problem is that while intelligent serial boards have special commands to set flow control and keep it set, the standard Unix stty command doesn't work that way. To set any option, you have to "open" the port, which is simply done by combining the stty command with a redirection symbol:

stty ixon < /dev/tty1a

Technically, this command actually works, but the problem is that the port will be reset to defaults -ixon the instant that the port is "closed", and that happens just microseconds after you press return! So, effectively, it does nothing.

SCO technical articles suggest the following command:

( stty 9600 ixon -ixany ; while : ; do sleep 3600; done ) < /dev/tty1a &

The 9600 is the baud rate, and could be different, and of course your printer might be on a different port.

This command forces the port to be held open; therefore the stty command actually stays in effect.

You can't just type this at the command line. Well, you can, but unless you preface it with 'nohup' it will stop working the moment you log out, and if you reboot your machine you'll have to type it again. So the better idea is to create a file containing this command and place it somewhere where it will be executed at startup. The directory /etc/rc.d/8 is a good place on most SCO systems. Call it anything you like; I often use "setprinter". Don't forget to chmod 755 it.

Actually, nowadays there is no reason at all not to leave out the while and do:

(stty 9600 ixon ixoff -ixany; sleep 2000000000)  < /dev/tty1a &

That's over 60 years of "sleep". There is an advantage to the "while" version: if the sleep gets killed, the other version will restart it.

It's also possible to control multiple printers with one shell; see Bela Lubkin's newsgroup post stty hold open scripts

For third-party devices such as Digiboard, etc. you have to be sure that the device is ready to accept commands when you issue them. Although Digi (for example) claims this is completely unnecessary, my experience is that it sometimes is, so my rc script calls "/usr/bin/setprint &", and that script looks something like:

sleep 15
ditty ixon printer ttya15


Bill Vermillion made a really neat suggestion for these scripts:

If you set multiple printers in /etc/rc.d/8, if you use differing sleep times, it will be easy to kill the processes of any particular job by noting the sleep value in ps.

I also typically run a sleep of 300 - 5 minutes - instead of an hour - in case somethings goes awry it comes to life in 5 minutes.

My sleep times will be 300,301,302,303, ad nauseum.

-- Bill Vermillion bv @ wjv.com

You can check how your port is set by typing "stty -a < /dev/tty1a" You will see something like:

speed 9600 baud;   ispeed 9600 baud;   ospeed 9600 baud; 
line = 0; intr = DEL; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = ^@; 
swtch = ^@;susp = ^Z;start = ^Q;stop = ^S;
-parenb -parodd cs8 -cstopb hupcl cread -clocal -loblk -ortsfl -ctsflow -rtsflow 
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -iuclc 
ixon -ixany -ixoff
isig icanon -xcase echo echoe echok -echonl -noflsh -iexten -tostop -xclude 
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel 

If the line referring to ixon instead says:

-ixon -ixany -ixoff 

then you do not have software flow control set at all.

Generally speaking, you are better off with hardware flow control. Unfortunately, "better" is sometimes harder to attain, simply because there is no absolute standard way of implementing hardware flow control. Fortunately, it's not completely out of hand: serial printers usually either use the rts/cts pins or dtr. Most use cts/rts, or if they use dtr, it's probably wired to cts, so you can use:

stty rtsflow ctsflow -ortsfl -ixon -ixoff -ixany -clocal

See RS232 Diagrams and Pinouts also.

Older versions (Xenix, particularly) didn't do this well. Sometimes it helped to leave out "rtsflow". One some Unix 3.2v4.0 to 4.2, it sometimes was necessary to use "ortsfl" instead. At one point, SCO used "crtsfl" to replace "rtsflow ctsflow". This is no longer true. You can read the gruesome details of this at Jeff Liebermann's site.

Even software flow control can have wiring problems: if the transmit line from the computer to the printer is correct, the printer will receive characters and will print. If the transmit back from the printer to the computer is wrong, or broken, the printer can't signal the computer to stop sending. You can check this sort of thing with a simple led device for serial ports (Radio Shack sells part no. 276-1401) or even with just a continuity test.

Another test is to drag over a dumb terminal and hook it up as though it were the printer. If you are using software (ixon) flow control , hit CTRL-S as you send a print job (the data will be on the terminal's screen). If the data stops, then flow control is working- which means if your printer is still producing junk, there's something wrong with it.

For hardware flow control, leave the printer off-line and then send a print job. If it goes to the printer (disappears from the queue), then hardware flow control is not working. For more on wiring, see Serial Wiring

Note on printers: Okidata serial printers require DSR Invalid when using 3 wire xon/xoff flow control. Set this on the printer, using the front panel menus. The printer will not print with 3 wire (2-3-7) setups without this. If you've wired for hardware flow control, you don't need this, but if you are using xon-xoff you might as well do this anyway.

Baud rate

Let's start with some basics: the SCO box is going to assume 8 data bits, no parity, and one stop bit. We''ll get to the baud rate in a minute, but first:

If you are otherwise set correctly but the SCO is set for EVEN parity, you'll be able to send lower case "a"'s and "b"'s, but not upper case, and upper case "C"'s, but not lower case.

If it's set ODD, it will be the other way around.

Why? Because the characters themselves are 7 bits, and the eighth (paity) bit will be set or unset depending on whether the number of bits set (in 7 bits) is even or odd. So an "a" is decimal 65, which is 2 bits set (64 and 1), while a "b" is decimal 66, which is still 2 bits (64 and 2), while "c" is 3 bits (64, 2 and 1). So if "even" parity is set, the "c" needs a parity bit added.

If the printer is set 7/even/1, you can send just about anything, but nothing happens.

If the baud rate is wrong, you'll get "garbage": wrong characters, no characters, characters with umlauts, etc.

Copyright 1998,1999 Anthony Lawrence. All rights reserved.

Updae 2012 (I'm surprised that people are still using serial printers!):

I ran across a case where (supposedly) the baud rate could not be lowered. I suggested filtering through a "chunking" script like this:

$sleep=10; # adjust as needed
while (<>) {
sleep $sleep if  not $lines % 120;

You'd modify your interface script to pass output through that on its way to the printer.

You could also look into slow-filter.

What you'd ideally want to see is the printer pausing only very briefly now and then.

The characters sent will be arriving at 960 cps (appx., assuming 9600 baud) until we pause. It can't print quite that fast, so its buffer will start to fall behind.

After 120 lines, we'll be pausing for $sleep seconds. The printer will be drawing down its buffer during that time and ideally it hits empty just as we wake up and start sending again.

If we aren't sleeping long enough, the buffer will eventually overflow - not as fast as it would without this, but eventually it will.

If we sleep too long, the printer will pause for less than the $sleep time and then begin printing.

If all else fails, drop the baud rate lower than the printing rate. The buffer may allow you to push that a bit if the jobs aren't very much larger than the buffer.

Got something to add? Send me email.

(OLDER)    <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> Serial Printers

Inexpensive and informative Apple related e-books:

Take Control of iCloud, Fifth Edition

Take Control of Numbers

Photos for Mac: A Take Control Crash Course

Take Control of Apple Mail, Third Edition

Take Control of Automating Your Mac

More Articles by © Tony Lawrence

Printer Friendly Version

Have you tried Searching this site?

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us

Printer Friendly Version

UNIX does not allow path names to be prefixed by a drive name or number; that would be precisely the kind of device dependence that operating systems ought to eliminate. (Andrew S. Tanenbaum)

Linux posts

Troubleshooting posts

This post tagged:



Unix/Linux Consultants

Skills Tests

Unix/Linux Book Reviews

My Unix/Linux Troubleshooting Book

This site runs on Linode