Interfacing Thermal Printer with Raspberry Pi to Print Text, Images, Barcodes and QR Codes

Published  January 24, 2022   0
Interfacing Thermal Printer with Raspberry Pi

Today, in this project, we will learn how to interface a Thermal Printer with Raspberry Pi using hardware serial communication, to print a test receipt that contains various elements like a Logo, a QR Code, or a barcode, along with various other text and graphical characters. Learning how to connect a thermal printer to Raspberry Pi opens up exciting possibilities for DIY projects, from creating a Raspberry Pi receipt printer for your home business to building automated ticketing systems.  As we all know, Raspberry Pi is a portable development board, and we have already built many Raspberry Pi-based projects previously. In this project, we will be interfacing a Thermal Printer with Raspberry Pi, then by using Serial communication and the python-escpos library, we will control the thermal printer from Raspberry Pi and print text and graphical imagesThis comprehensive Raspberry Pi thermal printer project guide will walk you through interfacing a thermal printer with Raspberry Pi using hardware serial communication and Python programming. You should check out our previous articles, where we already interfaced a thermal printer with ESP32, Arduino Uno and PIC16F877A. Whether you're working with a Raspberry Pi 3, Raspberry Pi Zero, or exploring Raspberry Pi Bluetooth thermal printer options, this tutorial covers everything you need to create a fully functional POS printer Raspberry Pi setup. A complete tutorial on building a smart shopping cart using a Raspberry Pi, USB barcode scanner, 20×4 LCD and POS thermal printer—scanning items, fetching prices from a Google Spreadsheet, and printing an invoice automatically.

Before going further, let us have a look at these steps that will be involved,

  1. Enable the Hardware Serial through raspi-config
  2. Connections for the Thermal printer and Pi 3
  3. Figure out how the ESC-POS commands work.
  4. Install the library from GitHub.
  5. We will do some basic coding to print text, image, barcode, QR Code, etc.
  6. We will try to print a sample Receipt
  7. Conclusion

Components Required for Raspberry Pi Thermal Printer Setup

Before starting your Raspberry Pi thermal printer project, gather these essential components:

Component NameQty
Thermal Printer MAXIM PNP-5001
Raspberry Pi 3 or Raspberry Pi 01
Jumper Wires Male to FemaleAs required
9V 1 Amp Adaptor1

The above table shows the list of components I am using as of now; you can have a different set of thermal printers and Raspberry Pi versions. Also, my printer requires at least 6 Volts to operate. (Please check the user manual while selecting the power source).

What is a Thermal Printer and How Does It Work?

A thermal printer is a printer that uses a heating head on thermal paper to produce images. Its quality of print, ease of installation, minimum use of external components, and low power consumption make it more popular among token or ticket counters, grocery stores, tiffin centres, entertainment centres, healthcare, corporate industries, etc. It's both eco-friendly as well as a cost-effective solution for small-scale use, as no ink Cartridge or ribbon, making it ideal for POS printer Raspberry Pi applications, ticket printing, and receipt generation.

Key Advantages of Thermal Printers for Raspberry Pi Projects

∗ Zero Ink Costs: Extensively cutting down on the operation costs due to no need for cartridges or ribbons
∗ Low Power Consumption: Ideal for Raspberry Pi projects that are portable and battery-operated
∗ Silent Operation: Absolutely no noise during printing, thus suitable for quiet places
∗ High Reliability: Very low maintenance due to fewer moving parts, and also using the printer longer (up to 50km of paper)
∗ Fast Printing: Receipt generation at a very quick rate of 250mm/sec
∗ Compact Design: Raspberry Pi systems with embedded applications can use the very little space occupied by the printer

It provides a noise-free operation along with faster monochromatic printing. Make sure to use the printer with an optimised temperature of the print head, as it may get damaged on operating at high temperatures.

Thermal printer connected to Raspberry Pi showing serial TTL connection for receipt printing project

In our case, we are using a thermal printer that can be interfaced using RS232 mode or Serial TTL. I am using a 9V adaptor to power it up. By default, the baud rate of most printers is 9600. We will use the TTL mode of communication in this case. For more technical details of the printer, please download the brochure.

Technical Specifications: MAXIM PNP-500 Thermal Printer

Print Method

Thermal Direct Line Printing

Paper loading method

Easy paper loading

Paper width

57 mm

Print width

48 mm

Print speed

250 mm/sec

Resolution ratio

8 dots/mm (384 dots/line)

Life of printing head

50 km

Printing speed

50 mm/sec

Max. printing speed

80 mm/sec

Character size

9 x 17 • 12 x 24

Chinese character fonts

GB18030

Chinese character size

12 x 24 dots • 24 x 24 dots

Outline dimension

76.8 x 77.4 x 47.6 (WxDxH mm)

Installation

72.8 x 73.4 (WxD mm)

Embedded depth

34.65 mm

Paper roll specification

Width : 58 mm, max. diameter: 40 mm

Interface

Serial (RS232C,TTL) / USB

Input power

DC5-9V • 12V

Operating temperature

0°C~55°C

Storage temperature

25°C~70°C

Operating humidity

10°C~80°C

Storage humidity

10°C~90°C

Understanding ESC/POS Command Protocol

Most of the printers work on ESC Point of Service commands for interfacing with computers, which were designed by EPSON. ESC/POS (Epson Standard Code for Point of Sale) is the industry-standard command language for controlling receipt printers and POS printer Raspberry Pi systems. It was mostly used in some inkjet printers, dot matrix printers and is still widely used in many receipt thermal printers for controlling them. As of 2014, few modern non-Epson printers use ESC/P instead, and most are driven through a standardised page description language, usually PCL or PostScript, or they use proprietary protocols such as Hardware Code Pages. The python-escpos library we'll use abstracts these low-level commands, making thermal printer Raspberry Pi Python programming straightforward even for beginners.

This thermal printer works on ESC/POS commands, for which we will be using the dedicated library.

How to Install a Thermal Printer on Raspberry Pi: Step-by-Step Setup

Step 1: Enable Hardware Serial Communication on Raspberry Pi

To connect thermal printer to Raspberry Pi, you must first enable the hardware serial port. In the terminal, write the following command and then press enter.

sudo raspi-config

You will see the configuration page, then navigate to ‘interfacing option’ through the arrow keys. After pressing enter, go to the ‘serial port enable/disable’ option. Press ‘no’ for enabling the serial login shell and then press ‘yes’ for enabling the ‘Hardware Serial port’. Click ‘ok’ and then click on the ‘finish button’ to reboot your Pi.

Step 2: Install Python Library for Thermal Printer Control

The python-escpos library simplifies thermal printer Raspberry Pi Python programming by providing high-level functions for all ESC/POS commands:

Now by doing so, you have enabled your Hardware Serial, i.e. ‘/dev/serial0’, which is dedicated tottyAMA0’.  This can be determined by entering the following command on Pi-3.

ls -l /dev

You'll see the following screenshot. Serial 1 is being used by the onboard Bluetooth of the Raspberry Pi 3. So, we will only be using the Serial 0 for the Thermal printer that is to be connected to GPIO 14 and GPIO 15 as TX-D0 and RX-D0.

Raspberry Pi terminal showing serial port configuration using raspi-config command for thermal printer setup

Now we will connect the Printer with our Raspberry Pi and provide a 9V Supply to the Printer.

Connection Diagram: Wiring Thermal Printer to Raspberry Pi

Here you can see that the RXD of the Printer is connected to the TXD of the Raspberry Pi, and the TXD of the Thermal printer is connected to the RXD of the Raspberry Pi 3.  Properly connecting your thermal printer to the Raspberry Pi is crucial for reliable communication. 

Detailed wiring diagram showing how to connect thermal printer to Raspberry Pi GPIO pins for serial communication

Also, one can note that TDR and GND are set to GND as of now. My printer was not printing until I put TDR to the ground.

Thermal Printer PinRaspberry Pi GPIO PinPin NumberFunction
RXD (Receive Data)TXD (GPIO 14)Pin 8Transmit data from Pi to Printer
TXD (Transmit Data)RXD (GPIO 15)Pin 10Receive data from Printer to Pi
GND (Ground)GNDPin 6 (or any GND)Common ground reference
VCC (Power)External 9V AdapterN/AMain power supply (DO NOT connect to Pi's 5V)
TDR (Thermal Detection)GNDPin 6 (or any GND)Pull to ground to enable printing

Physical setup photo of thermal printer interfaced with Raspberry Pi showing actual wire connections for POS receipt printing

Programming the Raspberry Pi Receipt Printer with Python

Now that the hardware setup is complete, let's explore thermal printer Raspberry Pi Python programming.  As we have discussed earlier, the thermal printer can be controlled by passing the appropriate ESC POS Command. But for now, we are using a library to interface it, as this library will send the data by using the same commands, and your desired print will become easy. It is quite complex to understand the basic nature of the printers based on ESC Command, but once you learn the basics, it will become a piece of cake for you. If everything is configured correctly, your Raspberry Pi receipt printer should print the test message.

Now, for the installation of the library, write the following command in the terminal.

sudo pip install python-escpos

By doing so, you will be able to use the library. We will be using the serial UART protocol for interfacing.

Printing Text on a Thermal Printer

Here we will be testing our first code on the printer that will print the text “Hello World” followed by a QR code.

from escpos.printer import Serial
""" 9600 Baud, 8N1, Flow Control Enabled """
p = Serial(devfile='/dev/serial0,
           baudrate=9600,
           bytesize=8,
           parity='N',
           stopbits=1,
           timeout=1.00,
           dsrdtr=True)
p.text("Hello World\n")

Now you can have a look at the detailed documentation for learning and exploring the functions and methods of this amazing library.

Setting up the Text Properties on the Thermal Printer

The ‘set()’ function will be used to set the text properties like font style (‘a or ‘b’), alignment, or font size. The set() method provides comprehensive control over text appearance on your thermal printer Raspberry Pi Python project:

p.set(
        underline=1,
        align="left",
        font="a",
        width=2,
        height=2,
        density=3,
        invert=0,
        smooth=False,
        flip=False,
)
p.textln(“Hello World”)

The text can also be bold or normal, inverted to black and white, or flipped upside down or downside.

Printing Barcodes with Raspberry Pi Thermal Printer

Barcodes are essential for inventory management, ticketing, and product identification in POS printer Raspberry Pi applications. The barcode(data, code_type, pos) where the arguments will be as follows,

data= “any data to convert into Barcode”
code_type=”type of barcode for eg. CODE39, CODE128, UPC-1, etc. “
POS=”position of the barcode data for eg. ‘BELOW’, ABOVE, BOTH, OFF“

For further details about this method, please refer to the documentation page. It can be noted that the size of the barcode can also be adjusted by passing the respective arguments.

p.barcode('123456', 'CODE39')

This will print the barcode that will store ‘123456’. Also, this will be of CODE39 type. Moreover, for the alignment of the barcode, you can use the set() function as we discussed earlier.

Barcode TypeUse CaseData Format
CODE39Inventory, logistics, labelsAlphanumeric (0-9, A-Z, special chars)
CODE128Shipping, packagingAll ASCII characters, high density
EAN13Retail products (international)12 digits + check digit
EAN8Small retail products7 digits + check digit
UPC-ARetail products (North America)11 digits + check digit
UPC-ESmall products6-digit compressed UPC

Example of CODE39 barcode printed on thermal paper using Raspberry Pi receipt printer for inventory management

Creating QR Codes for Modern Applications

Now you will be amazed to know that the ESCPOS Library has the facility to convert your data into a QR Code directly by passing the desired string. For printing a QR Code of your desired information, you can use the following Function.

p.qr("Circuit Digest",native=True,size=12)

Here you can pass the “String data in quotes”, the size of the QR code, and native as TRUE or FALSE.

Printing QR Codes with Thermal Printer

Printing Images and Logos

Add professional branding to receipts by printing logos and graphics on your Raspberry Pi receipt printer. Now it’s time for the image printing. Here, you can locate the image and pass the location as the argument of the image() function.

p.image("/home/pi/Raspberry_Pi_logp.png",impl="bitImageColumn")

Here, “the path of the image should be placed here”, followed by the impl as “imageRaster” or “bitImageColumn”, etc. You can have a look at the documentation part for more details. Just keep in mind that the pixels of width should not be more than 360, as the page size has a limited width.

Logo and graphics printed on thermal receipt using Raspberry Pi thermal printer showing image rendering capability

Complete Sample Receipt: Building a Professional POS System

So, now it's time to print our first Receipt using a Thermal Printer, but before going further, please note that we are hard-coding the output for now and will try to make it dynamic next time.

Printing Sample Receipt using Thermal Printer

The code for printing the receipt is as follows:

from escpos.printer import Serial
from time import *
from datetime import date
from datetime import datetime
now = datetime.now()
dt_string = now.strftime("%b/%d/%Y %H:%M:%S")
print("Today's date:", dt_string)
""" 9600 Baud, 8N1, Flow Control Enabled ""'
p = Serial(devfile='/dev/serial0',
           baudrate=9600,
           bytesize=8,
           parity='N',
           stopbits=1,
           timeout=1.00,
           dsrdtr=True
)
p.set(
        underline=0,
        align="left",
        font="a",
        width=2,
        height=2,
        density=3,
        invert=0,
        smooth=False,
        flip=False,
)
p.text("\n")
p.set(
        underline=0,
        align="center",
        font="a",
        width=2,
        height=2,
        density=2,
        invert=0,
        smooth=False,
        flip=False,
)
#Printing the image
# here location can be your image path in “ ”
p.image("/home/pi/proj on pi0/CD_new_Logo_black.png",impl="bitImageColumn")
#printing the initial data
p.set(
        underline=0,
        align="left",
)
p.textln("CIRCUIT DIGEST\n")
p.text("AIRPORT ROAD\n")
p.text("LOCATION : JAIPUR\n")
p.text("TEL : 0141222585\n")
p.text("GSTIN : \n")
p.text("Bill No. : \n\n")
p.set(
        underline=0,
        align="left",
        font="a",
        width=2,
        height=2,
        density=2,
        invert=0,
        smooth=False,
        flip=False,   
)
# print the date and time of printing every time
p.text("DATE : ")
p.text(dt_string)
p.textln("\n")
p.textln("CASHIER : ")
p.textln(" ===========================")
p.textln("      ITEM   QTY  PRICE    GB")
p.textln(" --------------------------")
p.textln("IR SENSOR  2  30   60")
p.textln("ULTRASONIC  2  80   160")
p.textln("RASPBERRY  1  3300   3300")
p.textln("ADOPTOR  2  120   240")
p.textln(" --------------------------")
p.textln("     SUBTOTAL:  3760")
p.textln("     DISCOUNT:  0.8")
p.textln("     VAT @ 18%: 676.8")
p.textln(" ===========================")
p.textln("    BILL TOTAL: 4436.8")
p.textln("     TENDERD:  0.8")
p.textln("     BALANCE: 676.8")
p.textln(" --------------------------")
p.textln("          THANK YOU")
p.textln(" ===========================")
p.set(
        underline=0,
        align="center",
        font="a",
        width=2,
        height=2,
        density=2,
        invert=0,
        smooth=False,
        flip=False,  
)
p.qr("Circuit Digest",native=True,size=12)
p.textln("")
p.barcode('123456', 'CODE39')
#if your printer has paper cuting facility then you can use this function
p.cut()
print("done")

Technical Summary and GitHub Repository

This section outlines the key technical details of the project, covering its design, components, and working principles. The accompanying GitHub repository includes all source files and code for further exploration and development.

Code and Schematics Download Zip

Advanced Features to Add to Your Raspberry Pi POS Printer System

After you have gotten used to the basics of Raspberry Pi Python thermal printer programming, consider adding some additional features:

» Database Integration: Hook up to an SQLite or MySQL source, look up product prices, and check the inventory
» Barcode scanner input: Attach a USB barcode scanner to look up products even more quickly
» Web app: Create a Flask or Django web app for remote printing capability from mobile devices
» Receipt templates: Create multiple receipt layouts for different types of sales
» Cloud Backup: Automatically upload receipt data to the cloud for accounting purposes
» Multilingual: Print receipts in preferred languages based on the customer's preference
» Auto-print on-event: Print when receiving data via GPIO, MQTT, or webhooks

Troubleshooting Common Raspberry Pi Thermal Printer Issues

ProblemPossible CauseSolution
Printer doesn't print anythingTDR pin not grounded, insufficient power, serial port disabledGround TDR pin, use 9V/1A adapter, verify serial enabled with ls -l /dev/serial*
Garbled or random charactersWrong baud rate, incorrect serial settingsVerify baud rate is 9600, check bytesize=8, parity='N', stopbits=1
Permission denied errorUser lacks serial port accessAdd user to dialout group: sudo usermod -a -G dialout pi, then reboot
Print quality is faintLow density setting, old paper, low voltageIncrease density in set() function, check paper quality, verify 9V supply
Images don't print correctlyImage too wide, wrong formatResize to max 384px width, convert to high-contrast B&W PNG
QR codes won't scanSize too small, poor contrastIncrease size parameter (try 8-12), ensure high print density
Serial port conflictAnother process using serial portCheck with lsof /dev/serial0, kill conflicting process

Frequently Asked Questions Raspberry Pi Thermal Printer Project

⇥ Q1: Is it possible to utilise a Raspberry Pi Zero for thermal printer projects?
Yes, both the Raspberry Pi Zero and Zero W are suitable for thermal printer projects because they both have hardware UART (serial) pins you can use to wire to the thermal printers. The Zero W has WiFi on board, which is useful for wireless POS printer Raspberry Pi projects,  because instead of getting print jobs via a dongle, the print jobs come in via the network.

⇥ Q2: Is there a way to attach a thermal printer to a Raspberry Pi without a physical connection? 
For a Raspberry Pi Bluetooth thermal printer setup, you can utilise Bluetooth-enabled thermal printers that have support for SPP (Serial Port Profile), or add a Bluetooth-to-serial adapter to standard serial thermal printers. Another option is to connect the printer via USB, then share it across the network using CUPS (Common Unix Printing System) for wi-fi printing from multiple devices.

⇥ Q3: What is the widest image width I can print on a 57mm thermal printer?
For standard 57mm thermal paper, the printable width is approximately 48mm, which is equivalent to 384 pixels wide at 8 dots/mm (203 DPI) resolution. Any image width greater than 384 pixels will automatically be cropped or resized to fit by the python-escpos library. Therefore, to obtain the best print outcome.

⇥ Q4: Which thermal printer choices can I use with the Raspberry Pi? 
Many popular thermal printers utilise ESC/POS commands that can be used with the Raspberry Pi. Some of the more common models are the MAXIM PNP-500, CSN-A2, Adafruit Mini Thermal Receipt Printer, Goojprt QR203, and Epson TM-T20. Ensure the printer has either an RS-232/TTL serial or USB connection when selecting a thermal printer, and that it utilises the standard ESC/POS command set, allowing for easy connection to the Raspberry Pi.

⇥ Q5: Do I need different paper for thermal printers?
Yes, thermal printers require specific thermal paper coated with heat-sensitive chemicals that darken when heated. Typically, standard paper will not work. You will want to order thermal paper rolls that are the same width as your thermal printer (normally 57mm or 80mm). Be aware that thermal paper receipts degrade over time, depending on the environmental conditions, so it is critical for important documents to use quality thermal paper either received from your Raspberry Pi or placed into your Raspberry Pi receipt printer.

⇥ Q6: Is it possible for multiple Raspberry Pis to print to one thermal printer? 
Yes! It will take a network-based solution, as the thermal printer only has one serial port. The best way I have found to handle this is to have one "print server" Raspberry Pi connected to the thermal printer, and two have CUPS or a custom Flask/FastAPI server that allows for the other Raspberry Pis on the network to send an HTTP POST request to it with the print data. This enables a Raspberry Pi network of thermal printer POS that can easily be expanded.

⇥  Q7: How long will thermal print last before fading? 
The standard thermal paper receipt can last 1-3 years until the print is hardly readable, depending on how you store the receipt. Fading occurs at a faster rate depending on heat, light and humidity. If you have any receipts that you want to keep for a longer period of time for preservation from your Raspberry Pi receipt printer, usually use premium or "long-life," thermal paper (7-10 years rated), store in a cool, dark space and, of course, take a digital backup with a scan or photograph after you print them.
 

Conclusion

We can have multiple ideas of printing text in different fonts and various sizes on the thermal printer. In this article, we have learned some basic functionalities of the thermal printer and what commands it supports, i.e. ESCPOS in our case. Also, we come to know that thermal printers are the handiest in daily usage, have a long life, and require less maintenance. It can print up to 50 km of fully dense written paper rolls. We will try to print some more tables and aligned text next time. Till then, stay connected.

Similar Projects Using Raspberry Pi

Explore more innovative and hands-on projects built using Raspberry Pi. These tutorials demonstrate how to integrate sensors, cameras, and automation features to create smart systems and IoT applications.

 Build a Raspberry Pi-Based SMS Alert System Using Cloud API

Build a Raspberry Pi-Based SMS Alert System Using Cloud API

In this project, I’ll show you how I built a temperature alert system using a Raspberry Pi and a DHT11 sensor. The best part is it uses only Wi-Fi and a free SMS API from Circuit Digest Cloud, no SIM cards, no GSM shields. 

Raspberry Pi Print Server: Setup a Network Server using CUPS

Raspberry Pi Print Server: Setup a Network Server using CUPS

For this Raspberry Pi Print Server tutorial, we will be creating a Network Printer with the aid of the Raspberry Pi 3 and the almighty CUPS which makes it all possible.

QR Code Scanner using Raspberry Pi and OpenCV

QR Code Scanner using Raspberry Pi and OpenCV

In this tutorial, we will build a QR code scanner using Raspberry Pi and OpenCV, and the ZBar library. ZBar is the best library for detecting and decoding the different types of barcodes and QR codes.

Complete Project Code

from escpos.printer import Serial
from time import *
from datetime import date
from datetime import datetime
now = datetime.now()
dt_string = now.strftime("%b/%d/%Y %H:%M:%S")
print("Today's date:", dt_string)
""" 9600 Baud, 8N1, Flow Control Enabled """
p = Serial(devfile='/dev/serial0',
           baudrate=9600,
           bytesize=8,
           parity='N',
           stopbits=1,
           timeout=1.00,
           dsrdtr=True
           )
p.set(
        underline=0,
        align="left",
        font="a",
        width=2,
        height=2,
        density=3,
        invert=0,
        smooth=False,
        flip=False, 
    )
p.text("\n")
p.set(
        underline=0,
        align="center",
        font="a",
        width=2,
        height=2,
        density=2,
        invert=0,
        smooth=False,
        flip=False,       
    )
#Printing the image
p.image("/home/pi/ proj on pi0/CD_new_Logo_black.png",impl="bitImageColumn")
#printing the initial data
p.set(
        underline=0,
        align="left",
     )
p.textln("CIRCUIT DIGEST\n")
p.text("AIRPORT ROAD\n")
p.text("LOCATION : JAIPUR\n")
p.text("TEL : 0141222585\n")
p.text("GSTIN : \n")
p.text("Bill No. : \n\n")
p.set(
        underline=0,
        align="left",
        font="a",
        width=2,
        height=2,
        density=2,
        invert=0,
        smooth=False,
        flip=False,       
    )
p.text("DATE : ")
p.text(dt_string)
p.textln("\n")
p.textln("CASHIER : ")
p.textln(" ===========================")
p.textln("      ITEM   QTY  PRICE    GB")
p.textln(" --------------------------")
p.textln("IR SENSOR  2  30   60")
p.textln("ULTRASONIC  2  80   160")
p.textln("RASPBERRY  1  3300   3300")
p.textln("ADOPTOR  2  120   240")
p.textln(" --------------------------")
p.textln("     SUBTOTAL:  3760")
p.textln("     DISCOUNT:  0.8")
p.textln("     VAT @ 18%: 676.8")
p.textln(" ===========================")
p.textln("    BILL TOTAL: 4436.8")
p.textln("     TENDERD:  0.8")
p.textln("     BALANCE: 676.8")
p.textln(" --------------------------")
p.textln("          THANK YOU")
p.textln(" ===========================")
p.set(
        underline=0,
        align="center",
        font="a",
        width=2,
        height=2,
        density=2,
        invert=0,
        smooth=False,
        flip=False,       
    )
p.qr("Circuit Digest",native=True,size=12)
p.textln("")
p.barcode('123456', 'CODE39')
#if your printer has paper cuting facility then you can use this function
p.cut()
print("done")
Video

Have any question related to this Article?

Add New Comment

Login to Comment Sign in with Google Log in with Facebook Sign in with GitHub