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 a hardware serial communication, to print a test receipt that contains various elements like a Logo, a QR Code, or barcode along with various other text and graphical characters. 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 imagesYou should check out our previous articles, where we already interfaced thermal printer with Arduino Uno and PIC16F877A.

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 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 Print a sample Receipt
  7. Conclusion

Components for Interfacing the Thermal Printer with Raspberry Pi

Component Name Qty
Thermal Printer MAXIM PNP-500 1
Raspberry Pi 3 or Raspberry Pi 0 1
Jumper Wires Male to Female As required
9V 1 Amp Adaptor 1

The above table is showing 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?

A thermal printer is a printer that uses heating head-on thermal papers to produce images. Its quality of print, ease of installation, minimum use of external components, and low power consumption, makes it more popular among token or ticket counters, grocery stores, tiffin centers, entertainment centers, 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 is used.

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

Thermal Printer

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 of the printers is 9600. We will use the TTL mode of communication in this case. For more technical details of the printer please download Brochure.

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

Most of the printers work on ESC Point of service commands for interfacing with computers which was designed by EPSON. It was mostly used in some inkjet printers, dot matrix printers and is still widely used in many receipts thermal printers for controlling them. As of 2014, few modern non-Epson printers use ESC/P instead and most are driven through a standardized page description language, usually, PCL or PostScript, or they use proprietary protocols such as Hardware Code Pages.

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

Enabling Serial Port of our Raspberry Pi

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.

Now by doing so, you have enabled your Hardware Serial i.e. ‘/dev/serial0which is dedicated forttyAMA0’.  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.

Enabling Serial Port of our Raspberry Pi

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

Connection Diagram for Interfacing Thermal Printer and Raspberry Pi 3

Here you can see that 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. 

Connection Diagram for Interfacing Thermal Printer and Raspberry Pi 3

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.

Interfacing Thermal Printer on Raspberry Pi

Code for Interfacing Thermal Printer and Raspberry Pi

As we have discussed earlier, the thermal printer can be controlled by passing 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 would 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 would become a piece of cake for you.

Now for 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 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 Thermal Printer

The ‘set()’ function will be used to set the text properties like font style (‘a’ or ‘b’), alignment, or font size.

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 flip like upside or downside.

Printing the Barcodes

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.

Printing Barcodes with Thermal Printer

Printing the QR Code

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”, size of the QR code, and native as TRUE or FALSE.

Printing QR Codes with Thermal Printer

Printing Image using Thermal 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 place 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.

Printing Image using Thermal Printer

Print Sample Receipt using Thermal Printer

So, now it's time to print our first Receipt using 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")

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 does it support, 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 have less maintenance. It can print up to 50Kms of fully dense written paper roles. We will try to print some more tables and aligned text next time, till then stay connected.

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 realated to this Article?

Ask Our Community Members