Skip to content

DS18B20 module: doesn't need to handle parasite mode differently if ow_write MODE == 1 #3682

@caiohamamura

Description

@caiohamamura

Expected behavior

CONVERT_T should be broadcast for parasite powered sensors too (use a single delay ~750ms).

Actual behavior

Currently for parasite mode the readings are done one by one in a loop fashion, creating a delay for each sensor. But it turns out that this is not needed, we can broadcast the conversion for all sensors at once, provided that in ow_write the MODE is set to 1 (set a strong pull-up), which it is.

Context

It is known that the one-wire bus will be occupied during parasite power mode for some operations due to the power requirements that make the gpio to send a strong pull-up which is achieved by sending MODE=1 to ow_write.

The strong pull-up is actually a HIGH gpio.OUTPUT, which can provide 12mA in ESP8266. The DS18B20 datasheet states that the CONVERSION_T operation may draw up to 1.5mA, that is, the default ESP8266 gpio can power up to 8 sensors during CONVERSION_T operation in the worst case scenario (all of them are drawing the peak current at the same time which is highly unlike), which will meet most usual applications.

So there is no need for the special handling of parasite powered mode and we could safely broadcast CONVERT_T for all sensors, since we are actually providing ow_write with MODE=1 to every operation. For the sake of perfect correctness for conventional powered sensors the ow_write could actually be set to MODE=0, then it wouldn't block the bus HIGH and the user would be able to issue write/read operations to other devices during the CONVERT_T operations.

Testing

Within module change conversion = function to:

conversion = (function (self)
  local sens = self.sens
  debugPrint("starting conversion: all sensors")
  ow_reset(pin)
  ow_skip(pin)  -- skip ROM selection, talk to all sensors
  ow_write(pin, CONVERT_T, MODE)  -- and start conversion
  for i, _ in ipairs(sens) do status[i] = 1 end
  tmr_create():alarm(750, tmr_ALARM_SINGLE, function() return readout(self) end)
end)

Within lua.init:

local t = require("ds18b20")
local pin = 7
gpio.mode(pin, gpio.INPUT, gpio.PULLUP)

function readout(temp)
  t:read_temp(readout, pin, t.C)
  if t.sens then
    print("Total number of DS18B20 sensors: ".. #t.sens)
    for i, s in ipairs(t.sens) do
      print(string.format("  sensor #%d address: %s%s",  i, ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(s:byte(1,8)), s:byte(9) == 1 and " (parasite)" or ""))
    end
  end
  for addr, temp in pairs(temp) do
    print(string.format("Sensor %s: %s °C", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)), temp))
  end
end


t:read_temp(readout, pin, t.C)

And the sensors will be re-read as soon as the alarm is triggered. Everything works as expected and instead of having delay * n_parasite_sensors, it will print at the fixed ~750ms delay.

NodeMCU startup banner

NodeMCU 3.0.0.0 built with Docker provided by frightanic.com
        branch: release
        commit: 36cbf9f017d356319a6369e299765eedff191154
        release: 
        release DTS: 202402250804
        SSL: false
        build type: float
        LFS: 0x0 bytes total capacity
        modules: adc,bit,dht,file,gpio,gpio_pulse,i2c,mqtt,net,node,ow,rtctime,sntp,spi,tmr,uart,wifi
 build 2025-08-21 23:29 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)

Hardware

Usual NodeMCU ESP8266.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions