Arduino library 路 Data and time

QRCode: generate a QR code on the board itself

Richard Moore鈥檚 QRCode library builds a QR code on the microcontroller from any text, a URL, a WiFi login or a serial number, so a device can show a code that changes without a phone app or an internet service. It hands you the code as a grid of dark and light squares (modules), and you draw them on a display or print them to Serial.

Built in on Mokxi: #include <qrcode.h> and it builds, with nothing to install. Free, and no account needed.

What QRCode does

Two numbers control the code. The version, from 1 to 40, sets its size: version 1 is 21 by 21 modules and each version adds 4. The error correction level, ECC_LOW to ECC_HIGH, sets how much of the code can be damaged and still read, at the cost of how much text fits. Version 3 with ECC_LOW holds 53 bytes of text, enough for a short URL.

The buffer for the code is yours to provide, sized with qrcode_getBufferSize(version). On a 128x64 OLED, a version 3 code at two pixels a module is 58 pixels square, which fits with room for the quiet zone scanners need around it.

Library Manager nameQRCode
AuthorRichard Moore
Include#include <qrcode.h>
Boardsevery board Mokxi compiles for but ATtiny85
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesOLED display, 128x64

Install it

It builds on every board Mokxi compiles for but ATtiny85.

In Mokxi it is built in: #include <qrcode.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "QRCode" by Richard Moore from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add QRCode to lib_deps in PlatformIO. Mokxi follows the calls of release 0.0.1, so a sketch written here builds there too.

What to know in the simulator: The mask is the lowest penalty under the standard鈥檚 rules; another library may pick another, and either scans.

ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

QRCode qrcode

Holds the code鈥檚 size and a pointer to its modules once it is built.

qrcode_getBufferSize(3)

How many bytes a version 3 code needs. Use it to size a uint8_t array.

uint8_t qrcodeData[qrcode_getBufferSize(3)];

qrcode_initText(&qrcode, qrcodeData, 3, ECC_LOW, "https://mokxi.com")

Builds the code for the text at that version and error correction level. It returns 0 on success and a negative number if the text does not fit.

qrcode_getModule(&qrcode, x, y)

True when the module at x, y is dark. qrcode.size is the number of modules along each side.

for (uint8_t y = 0; y < qrcode.size; y++)
  for (uint8_t x = 0; x < qrcode.size; x++)
    if (qrcode_getModule(&qrcode, x, y))
      display.fillRect(ox + x * 2, oy + y * 2, 2, 2, SSD1306_WHITE);

qrcode_initBytes(&qrcode, qrcodeData, 3, ECC_LOW, data, length)

The same for binary data of a given length, always using byte mode.

Example: A QR code on the Serial Monitor

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino 路 Arduino Uno R3
#include "qrcode.h"

void setup() {
  Serial.begin(115200);
  QRCode qrcode;
  uint8_t qrcodeData[qrcode_getBufferSize(1)];
  qrcode_initText(&qrcode, qrcodeData, 1, ECC_LOW, "HELLO WORLD");
  for (uint8_t y = 0; y < qrcode.size; y++) {
    for (uint8_t x = 0; x < qrcode.size; x++) {
      Serial.print(qrcode_getModule(&qrcode, x, y) ? "##" : "  ");
    }
    Serial.println();
  }
  Serial.print("version 1, mask ");
  Serial.println(qrcode.mask);
}

void loop() {}

Open it in the editor, wired and ready to run

Common errors and how to fix them

The code is blank or qrcode_initText() returns a negative value

The text is too long for the version and error correction chosen. Raise the version by one or two, or drop to ECC_LOW, and size the buffer again with qrcode_getBufferSize().

Phones will not scan the code on the screen

Draw each module at least two pixels wide, leave a blank border of about four modules around the code, and if a scanner struggles with white on black, draw dark modules on a lit background.

The board resets when making a large code

A high version needs a big buffer, and a local array that large overflows an Uno鈥檚 2 KB of RAM. Keep to small versions on AVR boards, or make the buffer a global so the compiler reports its size.

Try QRCode without installing anything

Open the example, change the sketch, and keep your version in a free account.