HACKING A THERMAL TILL PRINTER TO WORK WITH THE RASPBERRY PI

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.

The Sinclair ZX Printer

A Sinclair ZX81 and the ZX Printer
Source: Carlos Pérez Ruiz

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.

Pi Printer. Image © 2025, Tony Smith (@smittytone). All rights reserved

ZX Printer de nos jours: SparkFun's thermal printer and Pi

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.

SparkFun thermal printer

The underside of the printer is home to the power connector—use the bundled red and black cable—and the data line, which takes the yellow, green and black cable, also bundled. No easy USB connection here

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.

Pi printer power wiring. Image © 2025, Tony Smith (@smittytone). All rights reserved

DC barrel. Image © 2025, Tony Smith (@smittytone). All rights reserved

The solder-less DC barrel handily holds the USB cable and printer power wires together

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).

Pi printer data wiring. Image © 2025, Tony Smith (@smittytone). All rights reserved

Pi printer connection. Image © 2025, Tony Smith (@smittytone). All rights reserved

The ground (black) and UART Rx (yellow) wires from the printer's data line go into the Pi's GPIO pins 6 and 8, respectively. Remember, DO NOT connect the green cable

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:

1
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.

Next edit /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:

1
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:

1
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

1
unzip py-thermal-printer-master.zip

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:

1
chmod 777 printer.py

This makes the script executable from the command line, and you can test this—and the printer—byentering and running:

1
./printer.py

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:

1
sudo apt-get install python-imaging-tk

Sample printout. Image © 2025, Tony Smith (@smittytone). All rights reserved

The SparkFun printer does a test print if you hold the linefeed button when powering it up

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:

1
2
3
4
5
6
7
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:

1
2
3
4
5
6
7
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:

1
2
3
4
5
6
7
8
9
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

Printed listing. Image © 2025, Tony Smith (@smittytone). All rights reserved

A printed listed, just like the old days. Well, kind of...

smittytonesmittytone
Site and software copyright © 2026, Tony Smith