Arduino interfacing of Four DS18B20 with 10m long probe interfacing

I am using waterproof DS18B20 probes that are 1meters long. Should I cut the cable to reduce distance of sensor head from stub joints ?

Suggest you try the lengths you have before cutting stuff.

Maybe also try 1k to 4.7k before cutting too.

If you had access to an oscilloscope, you could observe the waveforms.

1 Like

My system would be like this.
Arduino kept on table near my PC, a long cable running through an industrial fluid warmer system with stub joints in between and different sensors places in different placed on the warming system connected via the stubs. So all sensors will be away from my Arduino board. Last sensor shall be at other end of the cable.

Page 7 on that AD guide - add a resistor 150ohm on data line at the branch.
From my personal experience, adding a resistor 68-100ohm on data pin close to sensor can dramatically decrease error readings.

Since I am using this sealed probe, I may use the 150 ohms near to stub as suggested in the application note.

If I use less than 1m length of probe from stub joints , would I still need series resistors ?

I will check the mount points tomorrow and then decide having short length of stub or not.

Like @LarryD already mentioned, try it before cutting off.

1 Like

Would above cabling design will be valid for MAX31850 IC based 1-wire thermocouple amplifiers as well ?

Why would not? 1-Wire is for general use.

1 Like

onewire is onewire
any onewire-device that realises to work obeying the onewire-specifications has the same behaviour

you mentioned

is this a low-cost personal hobby-project or is this for a commercial use?

best regards Stefan

1 Like

I did a project last year using a 18m bus length. I found the below info on the forum most helpful. I'm disappointed that I didn't save a link to the source.

Using the capacitors was key. The only change I made was to use 2k2Ω pullups as I was using 3.3v.
Also the cheap knock off sensors did not work on more than a couple meter bus. I had to source genuine sensors( from Adafruit in my case)

//  My tips for reliable DS18B20 bus:
//
//    Don't use parasite power if possible, its much less robust.
//
//    Use the standard multidrop connection, not a star network, 4k7 pullup at each end of the bus (Second pullup helps with long bus) 
//    add a 100nF decoupling capacitor between Vcc and ground at each sensor and a 100 ohm series resistor between Arduino pin and the bus.
//
//    Do not connect the bus ground to anything except the Arduino, sensors and decoupling caps
//
//  That should maximum the chance of good signaling. Ideally use twin-core shielded cable, or two twisted pairs (signal+ground, 5V+ground). 
//  Ribbon cable can work if the signal wire is sandwiched between two ground wires
//  to shield it.
1 Like

It is a commercial plant where my friend needs an immediate makeshift solution for temperature monitoring and logging.

Meanwhile we are also procuring thermocouple temperature transmitters to wire it with the main PLC. But as you know that procurement takes some time.

Aha. Depending on the budget and how much time you can work on it another approach might be to use four ESP32 nodeMCU-boards that send temperature values as UDP-messages to the PC or a Raspberry Pi

Each DS18B20 sensor is connected to its own ESP32 to keep the onewire short.

The ESP32 would connect to the local WiFi and then send UDP-messages to the PC
while the PC is running a small python-script that stores the received values into a CVS-style textfile

I have such a system up and running for more than a year now.
An Raspberry Pi receives the UDP-messages and stores the value into textfiles.

best regards Stefan

Great idea. Although I have never worked on ESP32 before. But now it seems I need to learn it too.
If you have any setup schematic/wiring, pls feel free to share.

Random nerd tutorials has a tutorial on how to install ESP32 board support

and here is a demo-code that demonstrates sending UDP-messages
The Arduino-Sketch includes a comment with a python demo-code to receive the udp-messages and store them into a textfile
In the python-code For longterm running I removed the lines that print to the python-console. Over weeks running this on a raspberry pi the python-code with the printing stopped to work. So I removed the printing to the python-console and this is running for a lot of months now

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

// I wrote some basic documentation about receiving the UDP-messages with python at the end of the file
#include <WiFi.h>
#include <SafeString.h>
#include <time.h>                   // time() ctime()
time_t now;                         // this is the epoch
tm myTimeInfo;                      // the structure tm holds time information in a more convient way

#define MaxMsgLength 1024
createSafeString(UDP_Msg_SS,MaxMsgLength); 
uint8_t UDP_Msg_uint8_Buffer[MaxMsgLength + 1]; // for some strange reasons on ESP32 the udp.write-function needs an uint8_t-array

#define MaxHeaderLength 32 
createSafeString(Header_SS,MaxHeaderLength);

#define MaxTimeStampLength 64 
createSafeString(TimeStamp_SS,MaxTimeStampLength);

char HeaderDelimiter = '$'; // must match the delimiter defined in the python-code 

const char *ssid     = ""; 

const char *password = "";

IPAddress    remoteIP     (192, 168, 178, 160); // receiver-IP
unsigned int remotePort = 4210;                 // receiver port to listen on must match the portnumber the receiver is listening to

WiFiUDP Udp;

const char* ntpServer = "fritz.box";
const long  gmtOffset_sec = 0;
const int   daylightOffset_sec = 7200;


boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - expireTime >= TimePeriod )
  {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  }
  else return false;            // not expired
}

const byte OnBoard_LED = 2;
int BlinkTime = 500;

void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

unsigned long TestTimer;
unsigned long UDP_SendTimer;

int myCounter = 0;
int HeaderNr  = 0;


void PrintFileNameDateTime() {
  Serial.print("Code running comes from file ");
  Serial.println(__FILE__);
  Serial.print(" compiled ");
  Serial.print(__DATE__);
  Serial.println(__TIME__);
}

void showTime() {
  time(&now);                       // read the current time
  localtime_r(&now, &myTimeInfo);           // update the structure tm with the current time
  Serial.print("year:");
  Serial.print(myTimeInfo.tm_year + 1900);  // years since 1900
  Serial.print("\tmonth:");
  Serial.print(myTimeInfo.tm_mon + 1);      // January = 0 (!)
  Serial.print("\tday:");
  Serial.print(myTimeInfo.tm_mday);         // day of month
  Serial.print("\thour:");
  Serial.print(myTimeInfo.tm_hour);         // hours since midnight  0-23
  Serial.print("\tmin:");
  Serial.print(myTimeInfo.tm_min);          // minutes after the hour  0-59
  Serial.print("\tsec:");
  Serial.print(myTimeInfo.tm_sec);          // seconds after the minute  0-61*
  Serial.print("\twday");
  Serial.print(myTimeInfo.tm_wday);         // days since Sunday 0-6
  if (myTimeInfo.tm_isdst == 1)             // Daylight Saving Time flag
    Serial.print("\tDST");
  else
    Serial.print("\tstandard");
    
  Serial.println();
}


void StoreTimeStampIntoSS(SafeString& p_RefToSS, tm p_myTimeInfo) {

  time(&now);                               // read the current time
  localtime_r(&now, &myTimeInfo);           // update the structure tm with the current time

  //p_RefToSS = " ";
  p_RefToSS  = myTimeInfo.tm_year + 1900;
  p_RefToSS += ".";

  // month
  if (p_myTimeInfo.tm_mon + 1 < 10) {
    p_RefToSS += "0";
  }  
  p_RefToSS += myTimeInfo.tm_mon + 1;

  p_RefToSS += ".";

  // day
  if (p_myTimeInfo.tm_mday + 1 < 10) {
    p_RefToSS += "0";
  }    
  p_RefToSS += myTimeInfo.tm_mday;

  p_RefToSS += "; ";

  // hour
  if (p_myTimeInfo.tm_hour < 10) {
    p_RefToSS += "0";
  }    
  p_RefToSS += myTimeInfo.tm_hour;
  p_RefToSS += ":";

  // minute
  if (p_myTimeInfo.tm_min < 10) {
    p_RefToSS += "0";
  }    
  p_RefToSS += myTimeInfo.tm_min;
  
  p_RefToSS += ":";

  // second
  if (p_myTimeInfo.tm_sec < 10) {
    p_RefToSS += "0";
  }    
  p_RefToSS += myTimeInfo.tm_sec;
  //p_RefToSS += ",";  
}


void connectToWifi() {
  Serial.print("Connecting to "); 
  Serial.println(ssid);

  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    BlinkHeartBeatLED(OnBoard_LED, 333);
    delay(332);
    Serial.print(".");
  }
  Serial.print("\n connected.");
  Serial.println(WiFi.localIP() );

}

void synchroniseWith_NTP_Time() {
  Serial.print("configTime uses ntpServer ");
  Serial.println(ntpServer);
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  Serial.print("synchronising time");
  
  while (myTimeInfo.tm_year + 1900 < 2000 ) {
    time(&now);                       // read the current time
    localtime_r(&now, &myTimeInfo);
    BlinkHeartBeatLED(OnBoard_LED, 100);
    delay(100);
    Serial.print(".");
  }
  Serial.print("\n time synchronsized \n");
  showTime();    
}

void setup() {
  Serial.begin(115200);
  Serial.println("\n Setup-Start \n");
  PrintFileNameDateTime();
  Serial.print("InitSensor() done \n");
  
  connectToWifi();
  synchroniseWith_NTP_Time();
  Header_SS = "Header"; 
}

void PrintMsg() {
  Serial.print("UDP_Msg_SS #");
  Serial.print(UDP_Msg_SS);
  Serial.println("#");
}

void loop() {
  BlinkHeartBeatLED(OnBoard_LED, BlinkTime);

  if (TimePeriodIsOver(UDP_SendTimer, 2000) ) {
    Serial.print("Send Message to #");
    Serial.print(remoteIP);
    Serial.print(":");
    Serial.println(remotePort);

    UDP_Msg_SS = "";

    UDP_Msg_SS = Header_SS;
    UDP_Msg_SS += HeaderDelimiter;

    StoreTimeStampIntoSS(TimeStamp_SS,myTimeInfo);
    UDP_Msg_SS += TimeStamp_SS;

    UDP_Msg_SS += ",my Testdata1,";
    UDP_Msg_SS += 123;
    UDP_Msg_SS += ",my Testdata2,";

    UDP_Msg_SS += 789;
    UDP_Msg_SS += ",";
    
    UDP_Msg_SS += myCounter++; 

    dbg("Send UDP_Msg #",UDP_Msg_SS);
    dbg("length:",UDP_Msg_SS.length());
    Udp.beginPacket(remoteIP, remotePort);
    Udp.write((const uint8_t*)UDP_Msg_SS.c_str(), UDP_Msg_SS.length() );  
    Udp.endPacket();
  }    
}

/*

This is a democode that demonstrates how to send TCP/UDP-messages with a timestamp 
The time is synchronized using a NTP-server. Most local routers like Fritz!Box can be used as the NTP-timer-server

The message has a userdefinable header which could be used for identifying the sender on the recieverside
There is a user-definable Header-delimiter that can be used to identify which characters of the
UDP-message belong to the header and which to the userdata

The code makes use of the SafeString-library. SafeStrings don't cause memory-problems like datatype "Strings"
and are easier to use than arrays of char. Example adding an integer to a SafeString-variable is as easy as
MySafeString = myInteger;

The userdata has commas between each data so you can import the textfile 
into table-calculation-software or databases as CSV-file comma separated values

the code has some additional useful functions as there are
- PrintFileNameDateTime() printing the path and filename of sourcecode file this program was generated with

- boolean TimePeriodIsOver  a non-blocking timing-function based on millis which is suitable for 
  timed execution in a regular manner (repeat every n milliseconds)

- BlinkHeartBeatLED() blinks the onboard-LED of ESP32 nodeMCU-boards. Gives visual feedback if the code is running  

The lines of code are grouped by functionality into several functions
The functions name says what the function does

I use this code for easy datalogging on a computer with a python-code that acts as the UDP-listener for 
incoming messages. Inside your ESP32-code you have to adjust the IP-adress to the receiver 
and the portnumber must be the same on sender (ESP32) and receiver-side 

In the python-code The header is used to create a file with the header as filename and extension ".txt" or if file 
is already existant to append the actual received UDP-message at the end of the file.

here is the python-code that does this. I tested it with python 3.9.2 for windows
#Start of python-code
# very simple and short upd-receiver based on python-code I found here
# https://www.studytonight.com/network-programming-in-python/working-with-udp-sockets#

import socket

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)      # For UDP

udp_host = socket.gethostname()            # Host IP
udp_port = 4210                     # specified port to connect

sock.bind((udp_host,udp_port))
print ("Waiting for client...")

HeaderDelimitChar = "$"

while True:
  data,addr = sock.recvfrom(1024)         #receive data from client
  print("data #",data,"#")
  Msg = data.decode('utf-8')
  print ("Received Message: #",Msg,"# from",addr)
  EndOfHeader = Msg.find(HeaderDelimitChar)
  HeaderBytes = Msg[0:EndOfHeader]
  FileName = HeaderBytes + ".txt"
  print("Filename #",FileName,"#")
  myFile = open(FileName, "a+")
  EndOfStr = data.find(0)
  MsgToWrite = Msg[EndOfHeader + 1 :1024] + '\r'
  myFile.write(MsgToWrite);
  myFile.close()
  print ("Data #",MsgToWrite,"#")

#End of python-code

For learning more about python just google with keyword "python" "your keyword of interest"  
 */

Adding reading DS18B20 sensors is the same as for Arduino

best regards Stefan

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.