Skip to main content

4.1 Print Message

Every example so far has reported back through the Serial Monitor, which means the board only has something to say while it is tethered to a computer. This one changes that: the kit's 16x2 LCD gives the board a screen of its own, and a message printed there stays on it whether the computer is watching or not.

The wiring is the easiest in the whole kit. The LCD is a Qwiic module, so one cable does everything.

In this documentation you will learn:

  • How to connect the 16x2 LCD with a single Qwiic cable.
  • What the purple I2C LCD adapter on the back of the display is for.
  • How to initialize a display and turn on its backlight.
  • How to put text where you want it with setCursor(), and why counting from zero matters.
  • Why only 16 characters fit on a row, and what happens to the seventeenth.
  • What to do when the screen glows but stays empty, the one fault that catches everybody.

Hardware required:

  • 1x Soldered NULA MINI board
  • 1x Breadboard
  • 1x 16x2 LCD display with I2C adapter
  • 1x Qwiic cable
  • 1x USB-C cable
ℹ️
No resistors and no jumper wires. Like example 3.1, this is a Qwiic module, so a single cable carries power and data together and it only fits one way round. The breadboard is here purely to hold the board steady.

Putting the components together

1. Insert the NULA MINI board on the breadboard

Push the board into one end of the breadboard so that its two rows of pins sit on either side of the centre channel, with the chip facing down.

NULA MINI board seated on the breadboard
Step 1: the board seated on the breadboard

2. Plug the Qwiic cable into the board

The NULA MINI has one Qwiic connector, on the edge of the board between the USER and RST buttons. It is the white connector marked qwiic on the silkscreen. Push the cable in until it clicks.

Qwiic cable plugged into the NULA MINI board, with the other end still loose
Step 2: the cable in the board's Qwiic connector, other end still free
⚠️
Do not confuse it with the smaller two-contact connector on the opposite edge of the board, marked - and +. That one is the battery connector, and a Qwiic cable will not fit it.

If you would like to see exactly which connector this is on a bare board, it is highlighted here:

The NULA MINI board with its Qwiic connector highlighted
The Qwiic connector on the NULA MINI, highlighted in blue

3. Plug the other end into the display

Turn the display over and you will find a purple board screwed to its back, silkscreened I2C LCD ADAPTER. It carries two Qwiic connectors, one at each end. Plug the free end of the cable into either one. They are wired together, and the spare exists so you can chain another module onwards.

The display turned over to show its purple adapter board, with the Qwiic cable running from it to the NULA MINI on the breadboard
Step 3: the display turned over, cable in one of the adapter's two Qwiic connectors
ℹ️
Along the adapter's edge you can also see holes marked SCL, SDA, 5V and GND. That is the same connection brought out to solder pins, for boards that have no Qwiic socket. You do not need it here. The cable does the same job.

4. Plug in the USB-C cable

Connect the board to your computer. The purple PWR light comes on and the display's backlight lights up blue, but the screen itself stays empty, because you have not uploaded anything to the board yet.

The finished build with USB-C connected: the display's backlight is lit blue but the screen shows no characters
Step 4: powered up, before uploading. Backlight on, screen still blank
ℹ️
This is worth looking at properly, because it is exactly what a fault looks like too. A lit backlight only means the display has power. It says nothing about whether the board is talking to it. Right now the screen is blank for the ordinary reason that there is no sketch. If it still looks like this after you upload, see If the backlight is on but the screen is empty below.

What the adapter board is for

Look closely at the green display board and you will count 16 pins along its top edge, labelled VSS, VDD, V0, RS, RW, E, D0 through D7, A and K. That is the native interface of the HD44780, the controller chip that has driven displays like this since the 1980s. Wiring it directly means fourteen or so connections, and you would spend this whole example pushing jumper wires into a breadboard.

The purple adapter board does that job for you. It sits on those 16 pins permanently and talks to your board over just two wires instead.

The purple I2C LCD adapter board mounted on the back of the display, showing its silkscreen labels
The I2C LCD adapter: 16 display pins on one side, two Qwiic connectors and an I2C address on the other

Those two wires are the I2C bus, the same one the ultrasonic sensor used in example 3.1: SDA carries the data and SCL provides the clock that keeps both ends in step. Several modules can share one pair of wires, each answering to its own address, which is why this board has I2C ADDR 0X20 printed on it. 0x20 is the number this display answers to.

ℹ️
That address is why LCD lcd(16, 2); needs no pin numbers, exactly as Ultrasonic_Sensor hc; needed none in 3.1. On the NULA MINI the I2C lines are permanently wired to IO6 and IO7 and are not even brought out to the pin headers, so there is nothing to choose. The library already knows the address, so begin() takes no arguments either.

You may also spot three small pads marked A0, A1 and A2 near the SOLDERED logo. Bridging them with solder changes the address, up to 0x27. You would only ever do that to put two of these displays on one cable. Leave them alone.


Installing the library

This example needs the Soldered LCD library. If you followed Setting up the Arduino environment you already have it. If not, open Tools → Manage Libraries, search for Soldered LCD, and install the one published by Soldered Electronics.

⚠️
Watch out for the look-alike. The Library Manager also lists a library called 16x2 LCD Library. It drives the same display but uses a different header name and a different constructor, so the code below will not compile against it. If the IDE reports fatal error: LCD-SOLDERED.h: No such file or directory, you have installed the wrong one of the two.

Rows, columns, and counting from zero

The display is a grid: 16 characters across, 2 rows down. lcd.setCursor(column, row) chooses where the next thing you print will land, and both numbers start at zero:

  • lcd.setCursor(0, 0) is the very first character of the top row.
  • lcd.setCursor(0, 1) is the very first character of the bottom row.

So the rows are numbered 0 and 1, not 1 and 2, and the columns run 0 to 15. Asking for row 2 on a two-row display gets you nothing at all rather than an error, which is a confusing way to lose ten minutes.

The 16-character limit is worth taking seriously, because the display does not wrap. Print a nineteen-character string and you get the first sixteen characters and nothing else. The rest is simply thrown away, with no warning. Both messages in this example are twelve characters long, so both fit comfortably:

column: 0123456789012345
row 0: Hello, NULA!
row 1: Let's start!
ℹ️
Count your own messages before printing them. If a string is too long, the usual fix is to shorten the wording rather than to split it across the two rows, since the second row is normally carrying something else.

Everything happens once

One last thing to notice before the code: every instruction in this example sits inside setup(), and loop() is completely empty.

That is deliberate. setup() runs once when the board starts, and loop() then runs forever, but there is nothing here that needs repeating. An LCD holds whatever it was last told to show, without being reminded, so printing the message once is enough. It stays on the screen until you cut the power or press RST, which restarts the sketch and prints it again.


Code

/**
**************************************************
*
* @file 4.1_Print_Message.ino
* @brief Example that shows how to display a message on an LCD screen.
* The LCD is controlled using the Soldered LCD library.
* This example demonstrates the basics of initializing the display and printing text.
* For details, connection diagram and more, check out the example documentation at: <link placeholder>
* @author Soldered
***************************************************
*/

#include "LCD-SOLDERED.h" // Include the Soldered LCD library

/*
Create an LCD object with 16 columns and 2 rows.
These numbers correspond to the width and height of the display.
*/
LCD lcd(16, 2);

void setup() {
/*
Initialize the LCD display and turn on the backlight (if supported by your module).
*/
lcd.begin();
lcd.backlight();

/*
Clear the display to ensure a clean start.
*/
lcd.clear();

/*
Set the cursor to the first column of the first row.
Then print a simple message on the LCD screen.
*/
lcd.setCursor(0, 0);
lcd.print("Hello, NULA!");

/*
Move to the second line and print another message. Keep in mind that this display fits exactly 16 characters per row,
so anything longer is simply cut off at the edge. Count the characters of your own messages before printing them.
*/
lcd.setCursor(0, 1);
lcd.print("Let's start!");
}

void loop() {
/*
Nothing needs to run repeatedly in this example.
The message remains visible until the board is reset or powered off.
*/
}
ℹ️
lcd.clear() wipes anything left over from a previous sketch. Without it you can end up reading a mixture of the old message and the new one, because whatever was on the display stayed there through the upload.

What you should see

Upload the sketch. Within a second of the board restarting, both lines appear, the same build as the photo above, now with something on the screen:

The finished build with the 16x2 LCD showing Hello, NULA! on the top row and Let's start! on the bottom row
`Hello, NULA!` on row 0 and `Let's start!` on row 1, each starting at column 0

There is no Serial Monitor output this time. The sketch never calls Serial.begin(), because the display is the output. Press RST and the two lines blink off and back on as the sketch runs again.

If the backlight is on but the screen is empty

This is the single most common problem with these displays, and it is not a fault in your code.

The characters are being sent correctly, but the display's contrast voltage is set so low that they are invisible against the backlight. The fix is a small trimmer potentiometer on the adapter board, marked CONTRAST:

The I2C LCD adapter board with the CONTRAST trimmer potentiometer highlighted
The CONTRAST trimmer on the adapter board, highlighted in blue

With the board powered and the sketch running, turn that trimmer slowly through its full range with a small flat screwdriver. At one end you get a blank blue screen; at the other, a row of solid dark blocks. Your text is somewhere in between. Stop where the characters look crisp. You only ever need to do this once.

ℹ️
Nothing in the library touches contrast. It is set purely by that trimmer, which is why no amount of changing the code will bring the text back. If your screen is blank, reach for the screwdriver, not the keyboard.
⚠️
If the trimmer does nothing across its whole range, the problem is communication rather than contrast. Check that Tools → Board reads Soldered NULA Mini ESP32C6. The library asks for the board's default I2C pins, and a different board selection sends the data to the wrong pins while still compiling and uploading perfectly happily. After that, reseat both ends of the Qwiic cable until each one clicks.

Try it yourself: change one of the messages to something longer than sixteen characters and upload again. You will see it clipped at exactly the sixteenth character, which is a quicker way to learn the limit than counting.


Full example

Check out the full example code on the link below:

4.1_Print_Message.ino

Example that initializes the Qwiic 16x2 LCD and prints a static two-line message using the Soldered LCD library.