I’ve always had a soft spot for Sinclair’s ZX Printer. Yes it was slow and the print was poorly rendered on its special aluminium-coated paper, which picked up greasy fingerprints like they were going out of fashion, but it was cute, compact and cheap.
I never owned one – I didn’t have a Sinclair computer back then – but I’ve always liked the idea of having a small thermal printer for listings and such. I do have a Raspberry Pi, and it struck me that a cheap, compact thermal printer would be ideal for this mini microcomputer too. Being a Pi user, of course, hooking up a printer isn’t about plugging in a USB cable and running CUPS it’s about driving the device directly through code and the Pi’s GPIO ports.
I did a search for a suitably small and low-cost printer and quickly uncovered this little – 111 x 65 x 57cm – fellow from SparkFun, available from various retailers in the UK for around £40, including Hobbytronics and Proto-Pic.
It’s basic and it only takes a narrow cash register paper, but it’s inexpensive. Designed to be integrated into some other hardware, doesn’t come with a convenient USB cable. Instead, there are two cables in the box – ‘collections of wires’ would be a better description – each capped with a block connector for the printer and a block connector for the device you’ll be printing from. I’d say with a bit of wiring they could together support a single USB connector if you want to connect the printer that way.
I was forewarned of the printer’s wires-only approach by a Geek Gurl Diaries blog, which used the printer in a project. My original plan was to cut off one connector, clip the live and ground wires into a solder-less DC barrel connector and hook it up to a new AC adaptor. But to avoid a trip to Maplin, I thought I’d see if I anything at home I could use instead. There was: a spare USB extension cable and a USB AC adaptor with a 5.2V output.
USB cables have a black ground wire and a red power line, so it was the matter of a moment to remove the female connector from the extension cable, cut away the shielding and the green and yellow data wires, and mate the cable’s red and black wires with the red and black power wires that come with the printer. The USB wires were particularly thin, but I used the DC barrel adaptor I’d already bought to connect the two cables securely together.
A botch, to be sure, but it worked. If you plan to put the printer inside another box, you can probably leave the cable as it is, but I think I’ll eventually pick up a pre-made USB-to-DC barrel cable, which will make for a tidier connection.
For now, though, the printer has sufficient power to experiment with. You can start by pressing the printer’s line feed button down as you switch on the power: this forces the printer to churn out a test print.
The printer’s second cable is for data: the Pi uses the yellow (3.3V in) and black (ground) wires, but don’t attempt to connect the green (5V out) wire as it’ll blow your Raspberry. Since you don’t need the printer to talk to the Pi – we just want the Pi to talk to the printer – leaving the green wire disconnected is not a problem.
A pair of male-to-female prototyping wires can be used to hook the printer’s data cable connector to the Pi’s GPIO ports: pin 6 (GND) for the ground (black) connection and pin 8 (UART Tx) for the data (yellow).
To set the Pi to talk to the printer, you need to re-configure the Pi’s serial GPIO ports from the default settings. Edit
/etc/inittab using your preferred text editor – I use Nano, thus:
sudo nano /etc/inittab – and find the following line:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Add a # symbol at the start so the line is ignored when the OS reads the file at start-up – you turn the line from a command to a comment – then save the file.
/boot/cmdline.txt and find the line
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Duplicate this line, and then remove
console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 from the copy. Now add a # to the first line. This way you can easily switch between default and custom version of the line simply by swapping the # from one line to the other.
Now reboot your Pi with the command:
sudo shutdown -r now
To use the printer in your Python programs, you need to install Python’s serial module,
python-serial, using the following command:
sudo apt-get install python-serial
Now head over to Lauri Kainulainen’s page on the Github website: github.com/luopio/py-thermal-printer. Lauri has written a Python module,
printer.py, that takes a lot of the work out of sending control codes and such to the printer. Download the code’s Zip file to your home folder and unpack it with
I made a directory called
Piprint first and put the
printer.py and the file
example-lammas.png into that. Wherever you save it, open up an LXTerminal window and navigate to the location and enter this command:
chmod 777 printer.py
This makes the script executable from the command line, and you can test this – and the printer – byentering and running:
which will print out a test page.
Actually it won’t, at least not entirely, because it requires the
python-imaging-tk module in order to output a sample bitmap image. You can install the module, if you wish, by entering:
sudo apt-get install python-imaging-tk
You don’t need
python-imaging-tk just to print out text and graphical glyphs, only images. Whether you install it or not, you can add
import printer to the start of your own Python programs to print from within them. The printer can only output 32 characters on each line using the standard font, ‘A’ – 40 with the smaller, alternative font, ‘B’ – so it’s useful to import the
textwrap module to make use of its text handing routines. For instance:
import printer, textwrap base_text = "This is a very long line of text which will almost certainly not fit on a single print line." wrapped_text = textwrap.fill(base_text, 32) p = printer.ThermalPrinter(serialport="/dev/ttyAMA0") p.print_text(wrapped_text) p.linefeed()
You can use the
sys to get characters entered by the user at the keyboard:
import printer, textwrap, sys p = printer.ThermalPrinter(serialport="/dev/ttyAMA0") base_text = sys.stdin.read() wrapped_text = textwrap.fill(base_text, 32) p.print_text(wrapped_text) p.linefeed()
Incidentally, if you don’t want to use
printer.py, it’s not hard to control the printer using its own commands, each triggered with an ESC character –
chr(27) in Python. You can download a full list of the printer’s commands here (PDF). However,
Printer.py masks these codes with easy-to-remember command words.
So, if you’ve define a variable
p as per the Python program above,
p.bold_on() turns on bold printing
p.bold_off() turns it off
p.font_b_on() activates the alternative, small font
p.font_b_off() brings back the main, large font
p.justify("R"), p.justify("C") and
p.justify("L") aligns the text, respectively, right, centred and left
p.upsidedown_on() turns on upside down printing
p.upsidedown_off() turns it off
p.underline_on() starts underlining characters
p.underline_off() stops the underline
p.inverse_on() prints characters white on black
p.inverse_off() sets character printing back to black on white
Those are the key text commands. Look through
printer.py and you’ll see commands to format and output barcodes too, along with bitmap image printing. There are also routines to interpret text with markup commands and print it accordingly.
And here is the first draft of a simple Python program to replicate the Basic
LPRINT command, or equivalent, to print out your programs:
import printer, fileinput p = printer.ThermalPrinter(serialport="/dev/ttyAMA0") for line in fileinput.input(): p.print_text(line) p.linefeed() p.linefeed() p.linefeed()
Save it as
lprint.py. Run it with
sudo lprint.py my_app.py