Fix a slow DS18B20 reading in CODESYS

7 min read · Published November 5, 2026

Three DS18B20 sensors on one GPIO pin that need 12 to 16 s per reading in CODESYS are paying kernel CRC retries. Each failed read costs another conversion, 750 ms at the 12-bit default. Time the shell read with the runtime stopped, fix pull-up and wiring until the CRC count is clean, then move every 1-Wire access into its own low-priority task that publishes values with valid flags and timestamps.

Three DS18B20 sensors on GPIO 4 that need 12 to 16 s per reading in CODESYS are paying kernel-level CRC retries. Every failed read costs another full conversion wait on top of the time the sensor already owes. One sensor on a short lead reads clean. Three sensors plus their cable length push the bus over the edge. The order that finds it fastest: stop the runtime and time the same read from the shell, count the CRC failures, fix the wiring until the count is clean, then move every 1-Wire access into its own low-priority task that publishes values with a valid flag and a timestamp. Reading one sensor the straightforward way is in Read a DS18B20 temperature in CODESYS ladder; this article is the three-sensor, slow-bus version.

Why do three DS18B20 sensors take 12 to 16 seconds per reading?

Each failed CRC check costs another full conversion. The DS18B20 needs up to 750 ms per conversion at its 12-bit default, so five retries stretch a 0.75 s read to about 4.5 s, and three sensors in sequence land in the 12 to 16 s you measure.

The driver bit-bangs the 1-Wire timing on the pin under a non-realtime OS. A marginal edge or a scheduling hiccup corrupts a bit, the CRC fails, and the driver retries the read. Each retry re-issues the convert command and waits the full conversion time again. A single sensor with a short lead tolerates an imperfect bus. Three sensors add stub capacitance and cable length until reads start failing. That is why the delay grows with sensor count while the datasheet conversion time stays fixed.

How do I tell whether the delay is the bus or my CODESYS task?

Stop the CODESYS runtime and time the same read from the shell. If cat /sys/bus/w1/devices/28-<id>/w1_slave returns in under a second per sensor, the task layout is your problem. If it takes several seconds, the kernel driver is retrying CRC failures.

SSH in and stop the runtime so nothing else holds the bus. List it with ls /sys/bus/w1/devices/: one folder per sensor plus the master, and each DS18B20 folder starts with the family code 28-. Time each sensor in turn:

time cat /sys/bus/w1/devices/28-<id>/w1_slave

The first line must end in YES, and the wall time should sit near the conversion time for the set resolution. Write the three wall times down; the worked example below uses them.

Which symptom points to which cause?

Read the symptoms against the layer that produces them. CRC lines marked NO point at the bus wiring, slow shell reads with YES point at driver retries, and fast shell reads with a slow PLC point at the task that holds the read call.

  • NO on the first line: that read failed its CRC. Wiring and edge quality; the next two sections fix it.
  • Shell read takes seconds but ends YES: retries succeed late. The bus is marginal, and the same two sections apply.
  • Shell reads fast but the PLC stays slow: the bus is fine and a blocking read sits in the control task. The one-wire task section fixes it.
  • A device folder disappears between reads: the sensor is dropping off the bus. Check the supply pin wiring and the pull-up before anything else.

Work the list top down; each item names the section that fixes it.

How do I count CRC failures from the shell?

Read each sensor 20 times and count the YES and NO lines. A healthy bus reports 60 YES and zero NO across three sensors, and every NO marks one read the driver will pay another conversion wait for.

Run this with the runtime stopped:

for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
do
  grep -hoE "YES|NO" /sys/bus/w1/devices/28-*/w1_slave
done | sort | uniq -c

A clean bus prints 60 YES and no NO lines. Every NO is one read the driver pays a full conversion wait for. Do the wiring work first and re-run the count until it is clean. The count, not the PLC program, decides when the bus is ready.

What wiring makes a three-sensor 1-Wire bus read clean?

Wire one 4.7 kΩ pull-up from the data line to 3.3 V. Connect every sensor's VDD pin to the 3.3 V rail, not parasite mode. Keep the runs short with no long star legs; weak edges on GPIO 4 under added cable capacitance are what force the retries.

The 4.7 kΩ value is the datasheet's standard pull-up for a 3.3 V bus, and it is worth keeping exact. Too weak and edges slump with cable length; too strong and the sensors struggle to pull the line low. Confirm the boot configuration enables the 1-Wire master on the pin, the w1-gpio overlay set to GPIO 4 here. After a reboot the master folder appears under /sys/bus/w1/devices/. Then re-run the count from the previous section; it has to come back clean before you touch the program.

Worked example: how long should a three-sensor scan take?

Take the middle of your range, 15 s for the whole three-sensor scan. That is 5 s per sensor, about 6.7 conversion waits of 750 ms each, meaning roughly five retries for every good read.

A clean bus owes you the conversion time alone. The DS18B20 datasheet sets the maximum conversion time by resolution, 750 ms / 2^(12 − resolution):

Resolution setting Max conversion per sensor Three sensors, sequential
12-bit (power-up default) 750 ms 3 × 750 ms = 2.25 s
11-bit 375 ms 1.125 s
10-bit 187.5 ms 0.5625 s
9-bit 93.75 ms 0.28125 s

Read the table against your measured wall times. A 5 s per-sensor read at the 12-bit default means the driver paid for about six conversions where the datasheet allows one. After the wiring fix, expect each shell read at the table value plus a small driver overhead, and expect relay decisions to lag by at most a scan period or two.

Recommendation: keep the 12-bit default, fix the bus until 20 reads per sensor come back all YES, and run the reads in their own cyclic task at a 3 s interval with a 10 s stale-data limit. Drop the resolution to 9-bit only if you need the scan under 0.5 s and every load tolerates 0.5 °C steps.

What goes inside the one-wire task in CODESYS?

Put every bus access in one cyclic task of its own, at a lower priority than the relay logic. The task holds the scan-once device list, one read per scanned sensor, and the write of each result to globals with a BOOL valid flag and a timestamp.

A blocking read parked in the relay task stretches that task's cycle to the whole scan, and a retry storm stretches it by seconds more. A task held that long is also the kind of overrun that trips task watchdogs, which Stop a CODESYS status task spin watchdog exception covers separately. Split the work: one POU and one cyclic task own every bus access, and the relay logic only reads published globals.

Globals:

VAR_GLOBAL
    grTemp   : ARRAY[1..3] OF REAL;   // last read value per sensor
    gxValid  : ARRAY[1..3] OF BOOL;   // last read passed CRC
    gdtStamp : ARRAY[1..3] OF DT;     // time of last good read
END_VAR

POU skeleton, with the scan-once block and the device-table identifiers the CODESYS 1-Wire example ships:

PROGRAM OW_Read
VAR
    astrID : ARRAY[1..20] OF STRING;
    ui     : UINT;
    x      : BOOL;
END_VAR
IF NOT x THEN
    x := TRUE; // fill the device table once at startup
    FOR ui := 1 TO MIN(Onewire_master.uiScannedDevices, 20) DO
        astrID[ui] := Onewire_master.pasScannedDevices^[ui-1].StringRepresentation;
    END_FOR
END_IF
// per cycle: call the same read block your single-sensor program uses,
// once per scanned ID; on CRC YES write grTemp[ui], set gxValid[ui],
// stamp gdtStamp[ui] with the current time; on NO clear gxValid[ui]

Create the task as cyclic, 3 s interval, priority below the relay task. The 3 s interval sits comfortably above the 2.25 s worst-case 12-bit scan from the table. Check in the online task monitor: the relay task keeps its normal cycle time, and only the one-wire task shows the long execution time.

How do I keep the relays safe when a reading goes stale?

Check the age of every reading before a relay acts on it. If now minus the last-good timestamp exceeds a limit set above one full scan plus retry margin, or the valid flag is false, drive that relay to its defined safe state.

A one-wire task can stall with the last values frozen in the globals, and the relay logic would act on them indefinitely. In the relay POU, compute the age as current time minus gdtStamp[ui] and require gxValid[ui] AND age below the limit before using the value. With the 3 s interval above, 10 s is a workable starting limit. It rides out one missed scan plus a couple of retries, and it fails fast enough for temperature loads with thermal mass.

Safety note: decide the safe state per output before commissioning. For a heater that means off. For a load that must keep running on loss of measurement, define that state explicitly and alarm it.

How do I verify the fix end to end?

Restart the runtime with all three sensors connected and watch two numbers for ten minutes. The one-wire task completes one full scan per cycle with no gap longer than the interval, and the relay task's cycle time sits where it was before the reads moved in.

Then run the checks:

  • Onewire_master.uiScannedDevices reads 3, and the three IDs match the 28- folders you saw in the shell.
  • Unplug one sensor: its gxValid clears within the 10 s limit and its relay goes to the safe state; the other two channels keep updating.
  • Read the same sensor from the shell at the same moment: PLC and shell agree within the set resolution step.
  • Cross a setpoint with a warm and a cool source: the relay switches on the first valid reading past the hysteresis band, with no multi-second lag.

If you want the headroom number after adding the task, Find a soft PLC runtime cycle time limit with a load sweep gives the sweep method.

Questions

Does lowering the DS18B20 resolution hurt relay control?

The 9-bit setting converts in 93.75 ms and reports in 0.5 °C steps. The 12-bit default takes up to 750 ms and reports 0.0625 °C steps. A relay with a hysteresis band wider than 0.5 °C never sees the difference, so simple on-off control tolerates 9 or 10 bit. Keep 12-bit when you log or trend the values, since the finer step is what the trend needs.

Can DS18B20 sensors with different family codes share one bus?

Yes. Every device on the line carries a unique 64-bit address, so they share one data pin and one pull-up. The kernel names each device folder after its family code. A DS18B20 enumerates as 28-, and other families enumerate with their own prefixes. If a folder shows a prefix you did not buy, the wrong sensor type is wired on the bus; sort that out before tuning any timing.

How many DS18B20 sensors can the example program handle?

The scan-once example stores up to 20 device IDs in astrID : ARRAY[1..20] OF STRING, so 20 is the table's limit. The electrical limit arrives sooner and depends on pull-up strength and total cable capacitance. Add sensors one at a time and repeat the CRC count from the shell after each. As long as the NO lines stay at zero, the bus carries the load.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote