Tutorial: Arduino and a Thermal Printer
Use inexpensive thermal printers with Arduino in chapter thirty-eight of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – a series of articles on the Arduino universe. The first chapter is here, the complete series is detailed here.
Updated 05/02/2013
In this article we introduce the inexpensive thermal printer that has recently become widely available from Sparkfun and their resellers. The goal of the article is to be as simple as possible so you can get started without any problems or confusion. In the past getting data from our Arduino to a paper form would either have meant logging it to an SD card then using a PC to finish the job, or perhaps viewing said data on an LCD then writing it down. Not any more – with the use of this cheap and simple serial printer. Before we get started, here is a short demonstration video of it in action:
Not bad at all considering the price. Let’s have a look in more detail. Here is the printer and two matching rolls of thermal paper:
… and the inside of the unit:
Loading paper is quite simple, just drop the roll in with the end of the paper facing away from you, pull it out further than the top of the front lip, then close the lid. The paper rolls required need to be 57mm wide and have a diameter of no more than 39mm. For example. There is a piece of white cardboard stuck to the front – this is an economical cover that hides some of the internals. Nothing of interest for us in there. The button next to the LED on the left is for paper advance, and the LED can blink out the printer status.
From a hardware perspective wiring is also very simple. Looking at the base of the printer:
… there are two connections. On the left is DC power, and data on the right. Thankfully the leads are included with the printer and have the plugs already fitted – a great time saver. You may also want to fit your own rubber feet to stop the printer rocking about.
Please note – you need an external power supply with a voltage of between 5 and 9 volts DC that can deliver up to 1.5 amps of current. When idling the printer draws less than 10 milliamps, but when printing it peaks at around 1.47 A. So don’t try and run it from your Arduino board. However the data lines are easy, as the printer has a serial interface we only need to connect printer RX to Arduino digital 3, and printer TX to Arduino digital 2, and GND to … GND! We will use a virtual serial port on pins 2 and 3 as 0 and 1 will be taken for use with the serial monitor window for debugging and possible control purposes.
If you want to quickly test your printer – connect it to the power, drop in some paper, hold down the feed button and turn on the power. It will quickly produce a test print.
Next we need to understand how to control the printer in our sketches. Consider this very simple sketch (download):
/* Example 38.1 - Sparkfun Thermal Printer Test (COM-10438) http://tronixstuff.wordpress.com/tutorials > chapter 38 Based on code by Nathan Seidle of Spark Fun Electronics 2011 */
#include <SoftwareSerial.h> SoftwareSerial Thermal(2, 3);
int heatTime = 80; int heatInterval = 255; char printDensity = 15; char printBreakTime = 15;
void setup()
{
Serial.begin(57600); // for debug info to serial monitor
Thermal.begin(19200); // to write to our new printer
initPrinter();
}
void initPrinter()
{
//Modify the print speed and heat
Thermal.write(27);
Thermal.write(55);
Thermal.write(7); //Default 64 dots = 8*('7'+1)
Thermal.write(heatTime); //Default 80 or 800us
Thermal.write(heatInterval); //Default 2 or 20us
//Modify the print density and timeout
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting); //Combination of printDensity and printBreakTime
Serial.println();
Serial.println("Printer ready");
}
void loop()
{
Thermal.println(" Visit http://tronixstuff.com ");
Thermal.write(10); //Sends the LF to the printer, advances the paper
Thermal.print(" Millis = ");
Thermal.println(millis());
Thermal.write(10);
Thermal.write(10);
do { } while (1>0);
}
After ensuring your printer is connected as described earlier, and has the appropriate power supply and paper – uploading the sketch will result in the following:
Now that the initial burst of printing excitement has passed, let’s look at the sketch and see how it all works. The first part:
#include <SoftwareSerial.h> SoftwareSerial Thermal(2, 3); // printer RX to digital 2, printer TX to digital 3
configures the virtual serial port and creates an instance for us to refer to when writing to the printer. Next, four variables are defined. These hold parameters used for configuring the printer. As the printer works with these settings there is no need to alter them, however if you are feeling experimental nothing is stopping you. Next we have the function initPrinter(). This sets a lot of parameters for the printer to ready itself for work. We call initPrinter() only once – in void setup(); For now we can be satisfied that it ‘just works’.
Now time for action – void loop(). Writing text to the printer is as simple as:
Thermal.print("text");
You can also use .println to advance along to the next line. Generally this is the same as writing to the serial monitor with Serial.println() etc. So nothing new there. Each line of text can be up to thirty-two characters in length.
The next thing to concern ourselves with is sending commands to the printer. You may have noticed the line
Thermal.write(10);
This sends the command to advance to the next line (in the old days we would say ‘carriage return and line feed’). There are many commands available to do various things. At this point you will need to refer to the somewhat amusing user manual.pdf. Open it up and have a look at section 5.2.1 on page ten. Notice how each command has an ASCII, decimal and hexadecimal equivalent? We will use the decimal command values. So to send them, just use:
Thermal.write(value);
Easy. If the command has two or more values (for example, to turn the printer offline [page 11] ) – just send each value in a separate statement. For example:
Thermal.write(27);
Thermal.write(61);
int zero=0; Thermal.write(zero);
… will put the printer into offline mode. Notice how we used the variable “zero” for 0 – you can’t send a zero by itself. So we assign it to the variable and send that instead. Odd.
For out next example, let’s try out a few more commands:
- Underlined text (the printer seemed to have issues with thick underlining, however your experience may vary)
- Bold text
- Double height and width
/* Example 38.2 - Sparkfun Thermal Printer Test II (COM-10438) http://tronixstuff.wordpress.com/tutorials > chapter 38 Based on code by Nathan Seidle of Spark Fun Electronics 2011 */
#include <SoftwareSerial.h> SoftwareSerial Thermal(2, 3);
int zero=0;
int heatTime = 80; int heatInterval = 255; char printDensity = 15; char printBreakTime = 15;
void setup()
{
Serial.begin(57600); // for debug info to serial monitor
Thermal.begin(19200); // to write to our new printer
initPrinter();
}
void initPrinter()
{
//Modify the print speed and heat
Thermal.write(27);
Thermal.write(55);
Thermal.write(7); //Default 64 dots = 8*('7'+1)
Thermal.write(heatTime); //Default 80 or 800us
Thermal.write(heatInterval); //Default 2 or 20us
//Modify the print density and timeout
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting); //Combination of printDensity and printBreakTime
Serial.println();
Serial.println("Printer ready");
}
void loop()
{
// underline - one pixel
Thermal.write(27);
Thermal.write(45);
Thermal.write(1);
Thermal.println("Underline - thin");
Thermal.println("01234567890123456789012345678901");
Thermal.write(10);
// underline - two pixels
Thermal.write(27);
Thermal.write(45);
Thermal.write(2);
Thermal.println("Underline - thick");
Thermal.println("01234567890123456789012345678901");
Thermal.write(10);
// turn off underline Thermal.write(27); Thermal.write(45); Thermal.write(zero); delay(3000); Thermal.write(10);
// bold text on
Thermal.write(27);
Thermal.write(32);
Thermal.write(1);
Thermal.println(" #### Bold text #### ");
Thermal.println("01234567890123456789012345678901");
delay(3000);
// bold text off Thermal.write(27); Thermal.write(32); Thermal.write(zero); Thermal.write(10); //Sends the LF to the printer, advances the paper delay(3000);
// height/width enlarge
Thermal.write(29);
Thermal.write(33);
Thermal.write(255);
Thermal.println("ABCDEF");
Thermal.println("012345");
delay(3000);
// back to normal Thermal.write(29); Thermal.write(33); Thermal.write(zero); delay(3000);
Thermal.write(10);
Thermal.println("Back to normal...");
Thermal.write(10);
Thermal.write(10);
do { } while (1>0); // do nothing
}
And the results:
Frankly bold doesn’t look that bold, so I wouldn’t worry about it too much. However the oversized characters could be very useful, and still print relatively quickly.
Next on our list are barcodes. A normal UPC barcode has 12 digits, and our little printer can generate a variety of barcode types – see page twenty-two of the user manual. For our example we will generate UPC-A type codes and an alphanumeric version. Alphanumeric barcodes need capital letters, the dollar sign, percent sign, or full stop. The data is kept in an array of characters named … barCode[] and barCode[]2. Consider the functions printBarcode(), printBarcodeThick() and printBarcodeAlpha() in the following example sketch (download):
/* Example 38.3 - Sparkfun Thermal Printer Test III (COM-10438) http://tronixstuff.wordpress.com/tutorials > chapter 38 Based on code by Nathan Seidle of Spark Fun Electronics 2011 */
#include <SoftwareSerial.h> SoftwareSerial Thermal(2, 3);
int heatTime = 80;
int heatInterval = 255;
char printDensity = 15;
char printBreakTime = 15;
char barCode[]={ '9','2','3','0','5','6','4','8','9','8','4','4'};
char barCode2[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' };
int zero=0;
void setup()
{
Serial.begin(57600); // for debug info to serial monitor
Thermal.begin(19200); // to write to our new printer
initPrinter();
}
void initPrinter()
{
//Modify the print speed and heat
Thermal.write(27);
Thermal.write(55);
Thermal.write(7); //Default 64 dots = 8*('7'+1)
Thermal.write(heatTime); //Default 80 or 800us
Thermal.write(heatInterval); //Default 2 or 20us
//Modify the print density and timeout
Thermal.write(18);
Thermal.write(35);
int printSetting = (printDensity<<4) | printBreakTime;
Thermal.write(printSetting); // Combination of printDensity and printBreakTime
Serial.println();
Serial.println("Printer ready");
}
void printBarcode(char zz[])
{
Thermal.write(29); //GS
Thermal.write(107); //k
Thermal.write(zero); //m = 0
for (int z=0; z<12; z++)
{
Thermal.write(zz[z]);
}
Thermal.write(zero); // bar code terminator
delay(3000); // necessary delay
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
}
void printBarcodeThick(char zz[])
{
Thermal.write(29); // specified height of barcode
Thermal.write(104);
Thermal.write(200); // 200 pixels high (default is 50)
Thermal.write(29); //GS
Thermal.write(107); //k
Thermal.write(zero); //m = 0
for (int z=0; z<12; z++)
{
Thermal.write(zz[z]);
}
Thermal.print(zero); // bar code terminator
delay(3000); // necessary delay
Thermal.write(29); // specified height of barcode
Thermal.write(104);
Thermal.write(50); // need to set back to 50 pixel height
delay(3000);
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
}
void printBarcodeAlpha(char zz[])
{
Thermal.write(29); //GS
Thermal.write(107); //k
Thermal.write(4); //m = 0
for (int z=0; z<16; z++)
{
Thermal.write(zz[z]);
}
// Thermal.print(zero); // bar code terminator
delay(3000); // necessary delay
Thermal.write(10);
Thermal.write(10);
Thermal.write(10);
}
void loop()
{
printBarcode(barCode);
printBarcodeThick(barCode);
printBarcodeAlpha(barCode2);
do { } while (1>0); // do nothing
}
Notice in printBarcodeThick() we make use of the ability to change the vertical size of the barcode – the height in pixels is the third parameter in the group. And here is the result:
So there you have it – another practical piece of hardware previously considered to be out of our reach – is now under our control. Now you should have an understanding of the basics and can approach the other functions in the user guide with confidence. Please keep in mind that the price of this printer really should play a large part in determining suitability for a particular task. It does have issues printing large blocks of pixels, such as the double-width underlining and inverse text. This printer is great but certainly not for commercial nor high-volume use. That is what professional POS printers from Brother, Star, Epson, etc., are for. However for low-volume, personal or hobby use this printer is certainly a deal. As always, now it is up to you and your imagination to put this to use or get up to other shenanigans.
This article would not have been possible without the example sketches provided by Nathan Seidle, the founder and CEO of Sparkfun. If you meet him, shout him a beer. Please don’t knock off bus tickets or so on. I’m sure there are heavy penalties for doing so if caught.
Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.
July 8, 2011 Posted by John Boxall | arduino, COM-10438, COM-10560, education, microcontrollers, printer, sparkfun, thermal, tutorial | arduino, barcode, bitmap, COM-10438, COM-10560, DIY, duemilanove, how, interface, inverse, learn, lesson, lessons, printer, receipt, serial, sparkfun, thermal, to, tronixstuff, tutorial, tutorials, understand, uno | Leave a Comment
YouTube
Visit tronixstuff on YouTube for our range of videosClock Projects
Zero - blinky the clock
One - DMD clock
Two - Single digit clock
Three - Pillow clock
Four - Scrolling text clockArduino Tutorials
Click for Detailed Chapter Index
Chapters 0 1 2 3 4
Chapters 5 6 6a 7 8
Chapters 9 10 11 12 13
Ch. 14 - XBee
Ch. 15 - RFID - RDM-630
Ch. 15a - RFID - ID-20
Ch. 16 - Ethernet
Ch. 17 - GPS part I
Ch. 18 - RGB matrix
Ch. 19 - GPS part II
Ch. 20 - I2C bus part I
Ch. 21 - I2C bus part II
Ch. 22 - AREF pin
Ch. 23 - Touch screen
Ch. 24 - Monochrome LCD
Ch. 25 - Analog buttons
Ch. 26 - Arduino + GSM - part I
Ch. 27 - Arduino + GSM - part II
Ch. 28 - Colour LCD
Ch. 29 - TFT LCD
Ch. 30 - Arduino + twitter
Ch. 31 - Inbuilt EEPROM
Ch. 32 - Infra-red control
Ch. 33 - Control AC via SMS
Ch. 34 - SPI bus part I
Ch. 35 - Video-out
Ch. 36 - SPI bus part II
Ch. 37 - Timing with millis()
Ch. 38 - Thermal Printer
Ch. 39 - NXP SAA1064
Ch. 40 - Push wheel switches
Ch. 40a - Wheel switches II
Ch. 41 - More digital I/O
Ch. 42 - Numeric keypads
Ch. 42a - Keypads II
Ch. 43 - Port Manipulation
Ch. 44 - ATtiny+Arduino
Ch. 45 - Ultrasonic Sensor
Ch. 46 - Analog + buttons II
Ch. 47 - Internet-controlled relays
Ch. 48 - MSGEQ7 Spectrum Analyzer
Arduino Due - first look
Ch. 49 - KTM-S1201 LCD modules
Ch. 50 - ILI9325 colour TFT LCD modules
Ch. 51 - MC14489 LED display driver IC
Search
RSS Feeds
Categories
Previous posts
Archives
- May 2013
- April 2013
- March 2013
- February 2013
- January 2013
- October 2012
- September 2012
- June 2012
- May 2012
- April 2012
- March 2012
- February 2012
- January 2012
- December 2011
- November 2011
- October 2011
- September 2011
- August 2011
- July 2011
- June 2011
- May 2011
- April 2011
- March 2011
- February 2011
- January 2011
- December 2010
- November 2010
- October 2010
- September 2010
- August 2010
- July 2010
- June 2010
- May 2010
- April 2010
- March 2010
Contact information
email - john at tronixstuff dot com
Google Group
Australian Electronics!
Buy and support Silicon Chip - Australia's only Electronics Magazine.Creative Commons
All the original material in this website, unless noted otherwise, is covered under a Creative Commons Attribution-Non Commercial-Share Alike v3.0 license. Please email me if you see any mis-attributions or would like to use my content in different circumstances.on twitter…
- Arduino IDE v1.0.5 has been released - arduino.cc/en/Main/Softwa… 18 hours ago
- Interesting new website to show and share electronics projects - knickknack.co.nz 1 day ago
- Gorgeous Black-and-White Photos of Vintage NASA Facilities - brainpickings.org/index.php/2013… 1 day ago
- RT @nathanknz Look what arrived today! Teleduino can be found from page 344. #ArduinoWorkshop #Teleduino #IoT http://t.co/u4HdHhwB9W 1 day ago
- RT @nicegear John Boxall writer of loads of fantastic tutorials, wrote a book about Arduino. Go and check it out! nostarch.com/arduino 1 day ago
Flickr Photos



More PhotosFind me on…
Interesting Sites
David L. Jones' eev blog
Freetronics Arduino Geniuses!
Silicon Chip magazine Always a great read!
Amazing Arduino Shield Directory
The Amp Hour podcast
EEWeb Elec Engineering Forum
Superhouse.tv High-tech home renovation
Mr Dick Smith OANuclear weapons = global suicide
In a war with nuclear weapons, everybody loses. Please check these out:
Count Down to Zero
The War Game
Threads






