Garbage on the temperature line only, with the clock line clean, is a write fault: the fast line rewrites on nearly every scan. Fix it with strings cut to exactly 16 printable characters and a driver call gated to once per second from one task, and re-initialise the module after any slip. A one-minute value hold alone leaves the fault in place.
Random glyphs and question marks that fill the temperature line of a 16x2 character module, while the clock line above it stays clean, are a display write fault. The temperature line changes on nearly every controller scan, so it rewrites dozens of times a second. On a module with an HD44780-compatible controller running 4-bit mode, which most 16x2 character modules use, every rewrite is a chance for the host and the controller to slip out of step. The fix is two changes made together: format the line as exactly 16 printable characters, and gate the write to about once per second from one task.
Why does the temperature line go garbage while the clock line stays clean?
The clock line changes once per second, so it writes one stable string each second. The temperature line changes on nearly every controller scan, so it rewrites dozens of times a second and exposes every weakness in the write path. A task with a 20 ms cycle time that calls the display driver every scan writes that line about 50 times a second. Each write is a fresh chance for one byte to arrive wrong, which is why the display runs clean for minutes and then collapses. The clock line never loads the bus that hard, so it survives. Nothing in the sensor or the stored values is broken; the fault sits between the runtime string and the module, however you read the temperature, whether that is a DS18B20 read in ladder or a scaled analog input.
What causes garbage characters on an HD44780 module in 4-bit mode?
In 4-bit mode every byte travels to the controller as two nibbles. One lost or doubled nibble shifts every later byte onto a wrong character code until the module is re-initialised. The maintainers of a widely used HD44780 library describe this as 4-bit nibble synchronization: once the host and the module are out of nibble sync, they stay out of sync until the interface is re-initialised. Bytes that land on wrong codes print as odd glyphs or question marks. Two further mechanisms produce the same look:
- Variable-length strings. A line built by concatenating REAL conversions changes length with every reading: a longer string overruns the 16 columns, a shorter one leaves the previous digits on screen.
- Interleaved writes. If the clock line and the temperature line are written from different POUs or tasks, cursor moves and data bytes can interleave, which puts text on the wrong line.
Match your symptom to its cause before you change code:
| Symptom | Points to |
|---|---|
| Garbage only on the fast line, clock line clean | Write rate on that line, or that line's string width |
| Clean for minutes, then the whole display fills with odd glyphs | Nibble slip, growing with total write count |
| Question marks or two odd glyphs where the degree sign should be | A multibyte character in the string literal |
| Old digits left behind after a value gets narrower | Variable-length strings with no padding |
| Text turning up on the wrong line | Two call sites in different tasks |
Which test tells a write-rate fault from a string fault?
Write a constant string of 15 printable characters every scan. If the display stays clean well past the old time-to-failure, the fault is in your string content. If it still corrupts, the fault is in the write rate or in concurrent access. Run the tests in order and record each pass condition.
- Enable one temperature only and note the minutes until the display corrupts. That number is your baseline for the soak test later.
- Replace the temperature variables with a constant 15-character string and keep writing every scan. Clean past the baseline: the fault is string content. Still corrupting: write rate or concurrency.
- Write a counter-driven string that changes every scan but is always 16 characters. Corruption here confirms the write flood with valid strings.
- Watch the string variable in online mode. LEN() must never exceed 16 and every character must be printable.
- Open the task configuration and read the cycle time of the task that calls the driver. Confirm one task and one call site write the display.
- Read the driver block's interface in its library documentation: the input string type, the maximum length it accepts, and whether it writes on every call or only on change.
On a visualization the runtime renders values for you; displaying PLC values in a visualization binds the variable and moves on. On a character module the formatting is your job, which is why tests 2 to 4 exist.
How do I format the temperature line to a fixed 16 characters?
Convert each reading to integer tenths. Build each field to a fixed width of 4 characters, join three fields with single-space separators for 14 characters, then pad and cut the line to exactly 16. Work in integers so the length never moves:
- Multiply by ten into an INT: 23.4 becomes 234.
- Split with division and modulo: 234 / 10 = 23 and 234 MOD 10 = 4, giving "23.4".
- Pad each field to 4 characters with leading spaces, so 8.6 prints as " 8.6".
- Assemble the fields and separators in a work string, pad with trailing spaces, then take LEFT(sLine, 16).
Division truncates toward zero, so a reading of -0.5 prints as 0.5. Handle the sign before splitting the digits if the process runs below zero.
The degree sign must travel as one byte. A typed degree character in a string literal can be stored as two bytes and print as two odd glyphs. The controller's character ROM carries the degree sign at code 0xDF on the standard table. Write that byte explicitly and check your module's ROM table, because the printed symbol depends on which ROM the module carries.
How fast should the task write to the LCD?
Gate the driver call to once per second, because your own clock line already runs clean at that rate on this hardware. Call it from one POU in one task so both lines share one write sequence. Two ways to build the gate:
- A TON timer of 1 s whose elapsed output enables one driver call, reset after the write.
- A write-on-change trigger with a 1 s minimum spacing, so a jittering value cannot reflood the bus.
Keep the clock line and the temperature line in the same POU. Add a re-initialise path now: a manual command, or a slow periodic timer, that sends the module's init sequence after a slip so the display recovers without a controller restart. The sequence to send is the 4-bit initialisation sequence from the controller datasheet, and the nibble order it needs is printed there.
Does holding the values for one minute fix it?
No: a 60-second hold cuts the write rate to one update per minute and the display goes quiet. But the next update still carries the same overlong or variable-width string, so the corruption returns at that update. The hold trades a live reading for a slower failure.
| Approach | What it fixes | What it leaves open |
|---|---|---|
| Fixed 16-character formatting | Overlong strings, leftover digits | Write flood if the driver still runs every scan |
| 1-second write gate | Write flood, interleaving | Strings that overflow or change width |
| Both together | The fault you have | Nothing on this path |
| 60-second value hold | Update rate drops to 1 per minute | The string fault, at every update |
Use the 60-second hold when a one-minute average is an operating requirement of the process, and pair it with the formatting fix.
What does a worked example with three temperatures look like?
Take readings of 23.4, 8.6 and 41.9. As tenths they become 234, 86 and 419. Each field prints in 4 characters as "23.4", " 8.6" and "41.9", and the line becomes "23.4 8.6 41.9" padded to 16. The arithmetic end to end:
- 23.4 × 10 = 234; 234 / 10 = 23; 234 MOD 10 = 4; field = "23.4", 4 characters.
- 8.6 × 10 = 86; 86 / 10 = 8; 86 MOD 10 = 6; field = " 8.6", leading space to 4 characters.
- 41.9 × 10 = 419; 419 / 10 = 41; 419 MOD 10 = 9; field = "41.9", 4 characters.
- Line = "23.4" + " " + " 8.6" + " " + "41.9" = 4 + 1 + 4 + 1 + 4 = 14 characters.
- Pad with 2 trailing spaces and cut: LEFT(sLine, 16) yields 16 characters. Confirm LEN(sLine) = 16 in online mode before enabling the driver call.
One decision this forces: a reading of 105.2 needs 5 characters, and 3 × 5 + 2 separators = 17, one column over. If any value can pass 99.9, show two values per line with 5-character fields, or keep three values on the line and cap the printed range at 99.9. Pick one before writing the formatter. Then force the inputs across the full sensor range, including the widest and narrowest printed values, and confirm no leftover characters from a wider previous value.
How do I recover a corrupted display and soak-test the fix?
Re-initialise the module through the driver's init command. A controller that has slipped out of nibble sync stays corrupted for as long as it holds power. Then run the soak test for at least five times your recorded baseline. The display does not heal on its own. The soak in full:
- Enable all three temperatures with the 1-second gate active.
- Confirm the line shows exactly 16 characters and the printed values match the sensor readings.
- Force the inputs through the full sensor range, including the extremes of the printed width.
- Run for at least five times the baseline from the first test. A display that first corrupted after 10 minutes needs 50 minutes of clean running on both lines.
- Only then tune the gate period, one step at a time, and repeat the soak after each change.
If the same controller also feeds a pixel screen and that screen misbehaves, start from troubleshooting an embedded controller video display; a pixel panel fails for different reasons than a character module.
Recommendation: Apply the 16-character formatting and the 1-second write gate together, from one POU in one task, with a re-initialise command wired to a button or a slow timer. Add the 60-second hold only when the process actually needs a one-minute average, because on its own it leaves the fault in place and hides a live reading.
Questions
My display corrupted after 10 minutes before the fix. How long must it run clean now?
Run at least five times the baseline, so 50 minutes with the gate active and all three temperatures shown. Both lines clean for the full run is a pass. If it corrupts earlier, re-check that one task and one call site still write the display before touching the formatting.
Is the controller too slow for a fast task cycle?
No. An HD44780-compatible controller executes most instructions in about 37 microseconds per the datasheet figure, so even 50 line writes a second from a 20 ms task sits far inside its capability on time alone. The fault is synchronization and string width: one lost nibble in 4-bit mode, or bytes the string should never have carried.
Why does the corruption take minutes to appear?
Because each write carries a small chance of a slip and the bad write has not happened yet. At roughly 50 writes a second the display passes thousands of correct writes first, which is why it looks clean at startup and fails later. A fault present from the first second points at the string content instead.
Do RETAIN or PERSISTENT variables help with the corruption?
They keep values across a power loss and restart. They change nothing in the path between the runtime and the display module, so the line still corrupts. Use them if the process needs its values after a power cut; fix the display with the 16-character formatting and the write gate.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.