How to read two temp sensors, and publish them? (ds18b20 sensors) [SOLVED]

I would like to read two temp senors on to the particle log. I have the code for one being read, but i’m a noob and don’t know exactly what to add for a second temp sensor set-up.

Also my digital pin space is dwindling, and if there is a good post about how to properly run these (or similar) ds18b20 sensors to analog inputs or how to run push-buttons to analog inputs that would be helpful. In the future I i’ll have more photons to expand with. Thanks.

Code for 1 ds18b20 temp sensor. (I pan on using one of the waterproof probe and one of the standard semi-circle)

#include "DS18B20/Particle-OneWire.h"
#include "DS18B20/DS18B20.h"

DS18B20 ds18b20 = DS18B20(D7); //Sets Pin D2 for Water Temp Sensor
int led = D0;
char szInfo[64];
float pubTemp;
double celsius;
double fahrenheit;
unsigned int Metric_Publish_Rate = 30000;
unsigned int MetricnextPublishTime;
int DS18B20nextSampleTime;
int DS18B20_SAMPLE_INTERVAL = 2500;
int dsAttempts = 0;

void setup() {
    Time.zone(-5);
    Particle.syncTime();
    pinMode(D2, INPUT);
    Particle.variable("temp1", &fahrenheit, DOUBLE);
    Serial.begin(115200);
}

void loop() {

if (millis() > DS18B20nextSampleTime){
  getTemp();
  }

  if (millis() > MetricnextPublishTime){
    Serial.println("Publishing now.");
    publishData();
  }
}


void publishData(){
  if(!ds18b20.crcCheck()){
    return;
  }
  sprintf(szInfo, "%2.2f", fahrenheit);
  Particle.publish("ambient_temp", szInfo, PRIVATE);
  MetricnextPublishTime = millis() + Metric_Publish_Rate;
}

void getTemp(){
    if(!ds18b20.search()){
      ds18b20.resetsearch();
      celsius = ds18b20.getTemperature();
      Serial.println(celsius);
      while (!ds18b20.crcCheck() && dsAttempts < 4){
        Serial.println("Caught bad value.");
        dsAttempts++;
        Serial.print("Attempts to Read: ");
        Serial.println(dsAttempts);
        if (dsAttempts == 3){
          delay(1000);
        }
        ds18b20.resetsearch();
        celsius = ds18b20.getTemperature();
        continue;
      }
      dsAttempts = 0;
      fahrenheit = ds18b20.convertToFahrenheit(celsius);
      DS18B20nextSampleTime = millis() + DS18B20_SAMPLE_INTERVAL;
      Serial.println(fahrenheit);
    }
}

Hi @bvolzmfg,

Here’s a giant “all-in-one-file” demo I keep handy for reading from multiple DS18B20 sensors:

There are probably more modern ways to do this :wink:

The DS18B20’s are also called “OneWire” because you can literally put the second temperature sensor signal wire on the same rail as the first, it looks like this:

Thanks,
David

2 Likes

Thank you so much for the help! As far as the OneWire goes, does that mean I could connect both of my signal wires to the same rail and have 2 different temp sensors publishing on my log (or any other display site/app/ect)?

2 Likes

Hi @bvolzmfg,

Yup! There’s a fairly sophisticated guide to OneWire deployments if you want to start adding lots of sensors to the same wire, but if you’re under a handful, and under long distances you should be fine. :slight_smile:

Thanks,
David

2 Likes

Thanks for helping the needy! I will look through all this and hopefully make something of it. I planned on using 2-3 OneWire sensors at minimal distance, so all should be well there. :grin:

If it is too much to deal with don’t worry, but can you give a general guide to which sections of that “all-in-one-file” I would need to modify with my credentials/pins/numbers/ect…
Being very new to this I’m a little handicapped and appreciate the help very much!

A# pins can be used exactly the same way as any D# pin.
You might just be extra careful with DAC (A6) since it's not 5V tolerant. And if you need interrupts or PWM you need to check if these are available on that pin (but the same goes for D# pins too).

3 Likes

Hi @bvolzmfg,

Sure thing, there’s a define at top to tell it how many sensors to expect, so update that:

Down at the bottom it’ll collect the IDs off the temperature sensors, and include them when it publishes an event, so you can update the event name.

I noticed I’m using a super-old version of the OneWire library in this example and it wasn’t compiling, so here’s an updated version that I’m hoping will work (haven’t tested it yet)

Thanks!
David

1 Like

This compiles and runs! Thank you very much!! I do have a question as to the updating event name. Are the correct individual ID’s the ones that appears after Temperature_ on the particle console? Also do I need to place them in the line Serial.print("Thermometer ID: "); in place of Thermometer ID or elsewhere? Appreciate all the help!

Hi @bvolzmfg,

So the program tries to persist the OneWire device id as a hex string (my memory allocation isn’t quite perfect, but it seems to work :slight_smile: ).

(edit: the link summaries are showing as the whole file every time, but they link to specific lines of code)

That happens around here:

I think you’re talking about these lines:

I’m not sure you need to modify those, unless you want the serial output to be different.

The actual publish happens here:

so you can make the topic anything you want, by changing that line, or you could assign different names to the thermometers in code by looking for specific IDs, etc, etc.

I hope that helps!

Thanks,
David

1 Like

Okay. I guess I could have been more specific in my goals, which are to display the thermometer names as oil_temp and ambient_temp or something similar to that. Would that be a lengthy thing to do as far as getting the ID’s and changing it everywhere just to display a certain name for a thermometer?

Hi @bvolzmfg,

I would recommend using the original program, connecting both thermometers, and then getting one hot / the other cold so you can uniquely identify the thermometers and label them individually.

Then copy-paste into a new program, and do something like…

String sensor_name;
if (strcmp("abcdefgh", sensors[checkIndex].id) == 0) {
  sensor_name= "oil_temp";
}
else if (strcmp("0123456789", sensors[checkIndex].id) == 0) {
  sensor_name = "ambient_temp";
}
else {
  sensor_name = "unknown";
}

etc, etc, and then use those to publish
1 Like

Well as is obvious, I don’t know what i’m doing but want to give this little naming thing one more shot…

I played with this for a little while in hopes that I would be able to do it on my own, but as prevails i’m lost and out of moves. I understand that idea of figuring out which of the sensors goes with what ID, and placing them into the "abcdefgh" and "0123456789" for comparison via the strcmp comand. So I guess the first question would be, I am to place the code you provided in the void loop() section correct? and does it need to replace anything or just be pasted in as additional?

Next
How do I go about adjusting the Particle.publish(String("Temperature_") + sensors[checkIndex].id, tempfStr ); line to work with the code added from above in giving two different titled readouts.

I was able to get it to give me the two names, but each time it published it would give 4 results, aka each name gave both the readings under it. That led me to believe I needed to change the tempfStr in the particle.publish line, but that has been unsuccessful.

I was picturing something like this:

this replaces line 822 - 827

<snip>...

    if ((now - sensors[checkIndex].updated) > 10000)
    {
        sprintf(tempfStr, "%f", sensors[checkIndex].value);

        String sensor_name;
if (strcmp("abcdefgh", sensors[checkIndex].id) == 0) {
  sensor_name= "oil_temp";
}
else if (strcmp("0123456789", sensors[checkIndex].id) == 0) {
  sensor_name = "ambient_temp";
}
else {
  sensor_name = "unknown";
}


        Particle.publish(String("Temperature_") + sensor_name,  tempfStr );
        sensors[checkIndex].updated = now;
    }
2 Likes

Dave, you are the mvp! Such a small change, but so much better. Thank you so much! :point_up: :+1:

1 Like