thermal printers/The first thing you print/07. A label is not a receipt
The first thing you print · 07 of 11

A label is not a receipt

A receipt is a stream. A label is a page: the printer finds the gap, you declare a size, you place things inside it, and only then does it print. Skip the first step and the text lands across the join.

Four steps instead of one

A printed label curling out of the top of the label printer: a white label on a pale blue backing strip carrying the words Label test, ESP32-S3 Text OK and a barcode, with a close-up inset showing the serrated tear bar the label is pulled across.
The labels come off a backing strip, and the tear bar is the straight edge you pull against.
A label is a page, and the page prints last
idle
Everything before the last step is preparation. The printer is holding a page in memory and the paper has not moved — which is why a label job that crashes half way through leaves you with a blank label rather than half a printed one.

Everything before the last step is preparation. The printer holds the page in memory and the paper does not move — which is why a label job that fails half way leaves you with a blank label rather than half a printed one.

The gap is the whole difference

Labels are die-cut, with a few millimetres of bare backing between them, and a sensor looks through that bare strip. The calibration pass feeds paper until it sees one, and from that moment the printer knows where a label starts.

Skipping it does not produce an error. It produces a label printed across the join between two labels, which is the single most common complaint about label printers and is almost never the printer's fault.

Dots, not millimetres

Sizes go in as millimetres; positions go in as dots. At 8 dots per millimetre, a 55 × 30 mm label is a page 440 × 240 dots — except that the head is only 384 dots wide, so the usable width is 48 mm whatever size label you load.

The library keeps a small margin of its own inside the page — 1 mm on the left, 2 mm top and bottom — so a drawing placed at 0,0 is not quite against the edge. That is deliberate: label stock wanders by a fraction of a millimetre as it feeds, and printing right to the cut line is how you get text with its top sliced off.

The code

label_first_label.ino

One 55 × 30 mm label with a heading, a line of text and a barcode on it, using the LonelyBinaryLabelPrinter library from the kit's GitHub repository. The library sends the calibration pass and the page frame for you; what is left is where things go.

// Label printer wiring for this sketch.
//
//   USB-C PD charger (9 V capable) -> base board PD TYPE-C
//   base board PRINTER POWER -> printer POWER socket
//   base board PRINTER DATA TTL -> printer TTL socket
//
//   base board 3V3 MCU header -> ESP32-S3:
//     TX  -> GPIO16   (this board's RX)
//     RX  -> GPIO17   (this board's TX)
//     3V3 -> 3V3
//     GND -> GND
//
// Arduino IDE: Tools > Board "ESP32S3 Dev Module", Tools > USB CDC On Boot
// "Enabled". Library: LonelyBinaryLabelPrinter, installed from the ZIP in
// github.com/Lonely-Binary/Receipt-Label-Printer.

#include <LonelyBinaryLabelPrinter.h>

#define PRN_RX 16
#define PRN_TX 17
#define PRN_BAUD 115200   // printed on the printer: TTL 115200 N-8-1 9V

LabelSerialESP32 printerSerial(2, PRN_RX, PRN_TX, PRN_BAUD);
LabelPrinter printer(printerSerial);

void setup() {
  Serial.begin(115200);
  delay(500);

  // The size of one label, in millimetres. This also runs the gap
  // calibration pass, which takes about two seconds.
  if (!printer.labelSize(55, 30)) {
    Serial.println("label size rejected - margins larger than the label");
    return;
  }

  printer.newLabel();

  // Positions are in dots, and there are 8 dots to the millimetre.
  printer.setFont(FONT_2X);
  printer.setPos(0, 0);
  printer.println("Lonely Binary");

  printer.setFont(FONT_1X);
  printer.println("Shelf B3 - qty 12");

  // Height in millimetres, unit width in dots. 2 is the sensible floor:
  // at 8 dots/mm a single-dot bar is an eighth of a millimetre.
  printer.barCode(10, 2, "LB1234567");

  // Nothing has printed yet. This is the step that commits the page.
  printer.endLabel();

  Serial.println("sent");
}

void loop() {
  // Ask about paper once a second. Read the three-byte reply, not one byte.
  delay(1000);
}

Install the library first — Sketch > Include Library > Add .ZIP Library, and pick LonelyBinaryLabelPrinter.zip from the repository. Nothing here compiles without it. If the text lands half on one label and half on the next, the calibration pass did not happen: check that labelSize ran before newLabel.

When it does not work

The text straddles two labels

The printer never found the gap, so it does not know where a label begins. Calibration is the 1F 63 pass the library runs inside labelSize — call that before newLabel, and give it the two seconds it needs before sending anything else.

Nothing compiles and the include is underlined

The LonelyBinaryLabelPrinter library is not installed. It is not in the Arduino library manager: download the ZIP from the kit's GitHub repository and use Sketch > Include Library > Add .ZIP Library, then restart the IDE.

The label prints but everything is squeezed into the top left

Positions are in dots, not millimetres, and there are 8 of them per millimetre. setPos(10, 10) is just over a millimetre in from the corner. Multiply the millimetres you want by 8, or use the library's mmToDots helper.

Half the label is blank on the right

The head is 384 dots wide, which is 48 mm, and a label wider than that simply does not get printed on past the edge. A 55 mm label has 48 mm of printable width and about 7 mm that no amount of positioning will reach.

Where this goes next

The printer draws both from a string, and the arithmetic that decides whether they fit.

Barcodes and QR codes

Edit this page — content/books/thermal-printer/a-label-is-not-a-receipt.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

This page covers several products. Choose yours to see the right discussions.

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum