A thermal printer on an Arduino: a fortune ticket
Beginner
Or see every lesson.
- 505parts on the bench
- 45boards running now
- 1.00xreal time, on every board
A mini thermal printer is the kind in a shop’s card reader: it prints on heat-sensitive paper with no ink at all, a line at a time, 32 characters across. Wired to an Arduino’s serial pins, it can print receipts, labels, tickets and barcodes.
The circuit above is an Uno, a thermal printer on its own 9 V supply, and a button. Each press prints a fortune ticket: a big bold header, one of eight fortunes, and a lucky number as text and as a barcode. Press Run, then press the button and watch the paper roll out.
What you need
- An Arduino Uno
- A mini TTL thermal printer (58 mm paper)
- A 5 V to 9 V power supply for the printer, 2 A or more
- A pushbutton
- A breadboard and jumper wires
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| Printer VH | Its own 9 V supply | Not from the Uno’s 5 V pin |
| Printer GND | GND | Shared with the Uno and the supply |
| Printer RX | Pin 6 | The Uno sends on 6 (SoftwareSerial TX) |
| Printer TX | Pin 5 | The printer answers on 5; optional |
| Button | Pin 2 and GND | INPUT_PULLUP |
How a thermal printer works
The paper is coated with a chemical that turns black when it is heated. The print head is a row of tiny heaters, 384 across a 58 mm roll. As a motor pulls the paper past, the printer heats the dots that make up each line of text. No ink, no ribbon, very few moving parts.
Heating hundreds of dots at once draws a lot of current, well over an amp at peaks. That is why the printer has its own supply on VH, and why it must never run from an Arduino’s 5 V pin.
The sketch
The printer talks plain serial at 19200 baud. The Uno’s own serial pins, 0 and 1, go to the USB port and the serial monitor, so the sketch uses SoftwareSerial on pins 5 and 6 instead: SoftwareSerial printerSerial(5, 6) (RX, TX), handed to Adafruit_Thermal printer(&printerSerial).
The ticket is built from the library’s style calls: justify('C') to center, boldOn(), setSize('L') for double height and width, then println() for each line. printBarcode(code, CODE39) prints the lucky number as a barcode, with its digits under it. Each ticket is nine lines of paper, and the serial monitor says "Ticket 1, lucky number 47" or whichever number came up.
The button is read with a 20 ms debounce, and the sketch waits for it to be let go, so one press is one ticket.
#include <Adafruit_Thermal.h>
#include <SoftwareSerial.h>
const int BUTTON = 2;
SoftwareSerial printerSerial(5, 6);
Adafruit_Thermal printer(&printerSerial);
void printTicket() {
randomSeed(micros());
int lucky = random(10, 100);
printer.justify('C');
printer.boldOn();
printer.setSize('L');
printer.println("FORTUNE");
printer.setSize('S');
printer.boldOff();
printer.println("--------------------------------");
printer.justify('L');
printer.println(FORTUNES[random(FORTUNE_COUNT)]);
printer.feed(1);
printer.justify('C');
printer.print("Lucky number: ");
printer.println(lucky);
char code[3];
code[0] = (char)('0' + lucky / 10);
code[1] = (char)('0' + lucky % 10);
code[2] = 0;
printer.setBarcodeHeight(40);
printer.printBarcode(code, CODE39);
printer.justify('L');
printer.feed(2);
}
void setup() {
Serial.begin(9600);
pinMode(BUTTON, INPUT_PULLUP);
printerSerial.begin(19200);
printer.begin();
if (!printer.hasPaper()) Serial.println("Out of paper");
Serial.println("Press the button for your fortune");
}Random numbers that change
random() on an Arduino gives the same sequence every time it starts, unless you seed it. The sketch calls randomSeed(micros()) at each press: the exact microsecond a person presses a button is different every time, so the fortunes and lucky numbers differ from run to run. Seeding once in setup() would not work as well, since setup() always runs at the same moment after power-on.
Paper, baud rate and the TX wire
The printer’s TX wire is optional for printing, but it is how the printer answers questions. hasPaper() asks the printer for its status and reads the answer on TX. With TX unwired there is no answer, so the library decides the paper is out: pull the TX wire in the circuit above and the serial monitor says "Out of paper", even though the tickets still print fine.
Note that this sketch only checks the paper at start-up. Take the paper out later (the P button on the printer) and press for a ticket: the serial monitor still says "Ticket 1", but nothing prints. A real kiosk checks hasPaper() before every ticket.
Most of these printers run at 19200 baud, some at 9600. Hold the printer’s feed button while you power it on and it prints a test page with its baud rate on it. If your printer prints garbage, that is the first thing to check.
Common mistakes
Powering the printer from the Uno. The head needs its own 5 V to 9 V supply that can give 2 A or so. Unplug VH in the circuit above and nothing prints at all.
Forgetting to join the grounds. The printer’s supply, the printer and the Uno must share GND, or the serial signal has no reference.
RX and TX swapped. The printer’s RX takes the Uno’s transmit pin, pin 6 here. Swap them and nothing prints, and the sketch says "Out of paper".
The wrong baud rate. Garbage on the paper; print the test page to check.
Using pins 0 and 1. They are shared with USB, so uploading and the serial monitor fight with the printer. Use SoftwareSerial on other pins, as here.
Expecting it to last. Thermal prints fade in sunlight and heat over months. Fine for tickets and receipts, not for keeping.
Open this circuit in the editor. Arduino Uno: a thermal printer fortune ticket, wired as it runs at the top of this page. Change a part or a value and run it again.
Open the circuitQuestions
How do I connect a thermal printer to an Arduino?
The printer’s RX to an Arduino transmit pin (here pin 6 on SoftwareSerial), its TX to a receive pin (pin 5), GND to GND, and VH to its own 5 V to 9 V supply with the grounds joined.
What library do I use for a thermal printer?
The Adafruit Thermal Printer Library: printer.begin(), then println(), justify(), boldOn(), setSize(), printBarcode() and feed().
Can a thermal printer print pictures?
Yes, black and white bitmaps with printBitmap(). In this simulation a bitmap shows as a placeholder box with its size, not the picture itself.
Why does my thermal printer print faint?
Usually the supply cannot give enough current, or the voltage is low. Use a supply of at least 2 A. The library’s heat settings in begin() also make it darker or lighter.
Keep going
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.