Using a Thermal Printer

 

Let me walk you through how to use a serial receipt printer with Python 3.  To the right is an video demo I made where I recreated the text scroll from Star Wars: A New Hope.  This skill will allow you to have a physical output from your scripts.  There are all kinds of uses for this type of skill.

Okay first we need to import the PySerial library.

To install it from command line run the following:

pip install pyserial

import serial

Starting the Connection

Now we need to set the variables for the script.  You can easily change these values to what you need.

‘com’ is for the serial com port you are using.
‘baud’ is the baud rate of your printer.
‘width’ is the character width of your printer.
‘cutfeed’ is how many lines to feed before cutting.

#Set Variables
com = 'COM1'
baud = 38400
width = 42
cutfeed = 6

This starts the printer communications.  Remember as you go you will need to run ‘ser.close()’ to end the connection.  If you don’t close it and the script crashes you may have issues restarting the script because the com port is left open.

ser = serial.Serial(com, baud, timeout=0,
                    parity=serial.PARITY_NONE)
if ser.isOpen():
    ser.close()

Closing the Connection

This makes closing the connection easier as you go.  If you try closing the connection while it is already closed it will cause issues.  This method will check if it is open before closing it.

#closes the serial connection
#you must end any print process with this command.
def close():
    if ser.isOpen():
        ser.close()

Cutting the Paper

This is the cut paper command.  It is dependent on a command (linefeed) we haven’t added yet.  Basically it will feed a count of lines and the cut the paper.  The line ‘ser.write(b”\x1D\x56\x00″)’ is the serial command to trigger the cutter.

#cuts the paper
def cutpaper():
    if not ser.isOpen():
        ser.open()
    line = range(cutfeed)
    for i in line:
        linefeed()
    ser.write(b'\x1D\x56\x00')

Cut and Close

This command is a shortcut to cut paper and end the connection.

#shortcut to cutpaper and close the connection
def end():
    cutpaper()
    close()

Resets ESC/POS Defaults

The ‘init’ command resets different settings we can send to the printer.  Later we can change the text size, direction, etc.  This resets it back to the defaults.

#resets all commands sent to printer
def init():
     if not ser.isOpen():
          ser.open()
     ser.write(b'\x1B\x40')

Force a Line Feed

This will feed a single line.  This is a dependency for the ‘cutpaper’ command.

#Feeds a single line.
def linefeed():
    if not ser.isOpen():
        ser.open()
    ser.write(b'\x0a')

Printing a String

Finally we get to a print command.  This takes an argument (a string) and prints it on the paper and then it runs the ‘linefeed’ command.  The text will be default justified.

#prints a string
def prt(item):
    if not ser.isOpen():
        ser.open()
    ser.write(item.encode())
    linefeed()

Printing a Centered Single String

The ‘prtcent’ command takes a string and centers it before printing it.  For this to work properly it is important that your ‘width’ variable is correct.  If you have many strings to print centered I would use ‘setjust(2)’ and ‘prt()’.

#prints a centered string
def prtcent(item):
    if not ser.isOpen():
        ser.open()
    ser.write((item.center(width)).encode())
    ser.write('\n'.encode())

Printing a List of Strings

This command will take a list object.  It goes through each string in the list and prints it.  Use the ‘setjust(2)’ command to make it centered.  I really like this one and it makes things a lot easier when doing a large body of text.

#prints a list.
def prtlst(item):
    for i in item:
        prt(i)

Rotating the Text

This command will rotate the text clockwise.  It takes an argument.  Using ‘1’ will rotate the text and using ‘0’ will set it back to normal.

#rotates characters clockwise
def rotatecw(item):
    if not ser.isOpen():
        ser.open()
    if item == 0:#cancels
        ser.write(b'\x1B\x56\x48')
    elif item == 1:#rotates
        ser.write(b'\x1B\x56\x49')

Justification

This command can justify the text for use with the ‘prt’ command.
‘0’ will left justify
‘1’ will right justify
‘2’ will center justify

#sets justification
def setjust(item):
    if not ser.isOpen():
        ser.open()
    if item == 0:#left
        ser.write(b'\x1B\x61\x00')
    elif item == 1:#right
        ser.write(b'\x1B\x61\x02')
    elif item == 2:#center
        ser.write(b'\x1B\x61\x01')
    else:
        print('Invalid Entry') 

Changing the Text Size

This will change the size of the text.  This comes in real handy.
‘0’ is normal size
‘1’ is double size
‘2’ is triple size

The key to it is in the last set in the command sent:

b'\x1D\x21\x00'

Changing the ’00’ to ’11’ will double the size.  You can make the characters wider or taller by changing those individually.  The first character is the width and the second is the height.

def setsize(item):
    if not ser.isOpen():
        ser.open()
    if item == 0:#Size Normal
        ser.write(b'\x1D\x21\x00')
    elif item == 1:#Size Double
        ser.write(b'\x1D\x21\x11')
    elif item == 2:#Size Triple
        ser.write(b'\x1D\x21\x22')

Printing Upside Down

This will make your text upside down.  Passing a ‘1’ will make roll it upside down and ‘0’ will make it normal again.  This can come in handy if your printer is mounted on the wall or something.

#print text upside down
def upsidedown(item):
    if not ser.isOpen():
        ser.open()
    if item == 0:#right side up
        ser.write(b'\x1B\x7B\x02')
    elif item == 1:#upside down
        ser.write(b'\x1B\x7B\x01')

As I am working on this project I will add more items to this page.  If you have any feedback or if you know of any commands I can add please send them my way to Contact@DREAM-Enterprise.com.  Thank you.