[RESOLVED] DS18B20 Library Modifications

Hi All,

Apologies for the huge code dump…but why won’t this compile? I’ve been modifying the ‘Ds18b20’ library to add support for multiple sensors on different pins. I want to pass an ‘instance’ of each sensor to the getTemp() function. IDK, maybe I’ve been programming Java too much recently and I’m missing something obvious?!

I get the error message
error: variable or field 'getTemp' declared void
however I know this is because I’m trying to pass the type ‘DS18B20’ to getTemp(), what am I doing wrong here?

Thanks

code:

// This #include statement was automatically added by the Particle IDE.
#include "Particle-OneWire.h"

// This #include statement was automatically added by the Particle IDE.
#include "DS18B20.h"

SYSTEM_MODE(SEMI_AUTOMATIC); //comment this in when debugging - prevents Particle connecting to 3G network

int sensorPin = D6;
DS18B20 eBayTemp = DS18B20(sensorPin); //Sets Pin for Water Temp Sensor
int led = D7;
char szInfo[64];
float pubTemp;
double celsius;
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(sensorPin, INPUT);
    Serial.begin(115200);
}

void loop() {

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

}



void getTemp(DS18B20 sensor){
    if(!sensor.search()){
      sensor.resetsearch();
      celsius = sensor.getTemperature();
      while (!sensor.crcCheck() && dsAttempts < 4){
        Serial.println("Caught bad value.");
        dsAttempts++;
        Serial.print("Attempts to Read: ");
        Serial.println(dsAttempts);
        if (dsAttempts == 3){
          delay(1000);
        }
        sensor.resetsearch();
        celsius = sensor.getTemperature();
        continue;
      }
      dsAttempts = 0;
      DS18B20nextSampleTime = millis() + DS18B20_SAMPLE_INTERVAL;
    }
    char buffer [50];
    sprintf(buffer,"Temperature of sensor on pin %d is %f \0",sensorPin, celsius);
    
    Serial.println(buffer);
}

If you want to pass an object, you should either use a reference (void getTemp(DS18B20 & sensor)) or a pointer (void getTemp(DS18B20* sensor)).

But I guess you’ll have got more than just that one line as error message(s). Can you post the full output?

1 Like

Sure, thanks.

Error message:

    ds18b20_test.cpp:6:14: error: variable or field 'getTemp' declared void
 void getTemp(DS18B20 sensor);
              ^

ds18b20_test.cpp:6:14: error: 'DS18B20' was not declared in this scope
ds18b20_test.cpp: In function 'void loop()':
ds18b20_test.cpp:31:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     pinMode(sensorPin, INPUT);
                ^
ds18b20_test.cpp:32:19: error: 'getTemp' was not declared in this scope
     Serial.begin(115200);
                   ^
Error: Could not compile. Please review your code.

The error about the signed and unsigned int goes away when there are no other compilation issues :slight_smile:

BTW, I just recalled that I had a similar discussion a few days ago here

I saw this, read through it for inspiration :wink:

That's the important bit.
You need to find out why it's not declared in this scope.

BTW, the signed/unsigned message is a warning (which doesn't go away but is not displayed) without errors.


Update:

 void getTemp(DS18B20 sensor);

Given this line - quoted in the error message - doesn't exist in your code, it could be that the Wiring preprocessor is tripping you up.

You could add this to your .ino file

#pragma SPARK_NO_PREPROCESSOR
#include "Paritlce.h"
#include "Particle-OneWire.h"
#include "DS18B20.h"

void getTemp(DS18B20 & sensor);

I thought it would be declared in the header file for the library? Could you explain what you mean by

Thanks

See my edit above.

The Wiring preprocessor helps non-C/C++ people (when it works correctly) by adding “forgotten” forward declarations/prototypes of functions that will be implemented after their first use (and it also includes Particle.h).
But sometimes - like here - it doesn’t do its job well.
I guess the output of the preprocessor of your code looks something like this - which would explain the error message

// --------------- this part was added by the Wiring preprocessor ------------------
// some comments (to account for the error occuring on line 6
#include "Particle.h"  

// note: at this point DS18B20.h wasn't included yet
void getTemp(DS18B20 sensor);  
// --------------- this part was added by the Wiring preprocessor ------------------

// This #include statement was automatically added by the Particle IDE.
#include "Particle-OneWire.h"

// This #include statement was automatically added by the Particle IDE.
#include "DS18B20.h"

SYSTEM_MODE(SEMI_AUTOMATIC); //comment this in when debugging - prevents Particle connecting to 3G network

int sensorPin = D6;
DS18B20 eBayTemp = DS18B20(sensorPin); //Sets Pin for Water Temp Sensor
int led = D7;
char szInfo[64];
float pubTemp;
double celsius;
...
1 Like

@ScruffR You’re a genius, thanks for your help! My strengths lie in Java so migrating to C/C++ will happen with hiccups I’m sure!

1 Like

@joearkay, tiny little thing… In setup() you call Particle.syncTime(); but you also have SYSTEM_MODE(SEMI_AUTOMATIC);. The cloud won’t be connected to sync the time!

2 Likes

I just throw SYSTEM_MODE(SEMI_AUTOMATIC);. into the Particle when I’m serially debugging, so I don’t have to wait for the Particle to connect to my patchy 3G GSM signal :slight_smile:

@joearkay, FYI, when you run SYSTEM_MODE(AUTOMATIC); which is the default mode, time is synched automatically when the cloud connection is established. However, it may take a few seconds during which the RTC on the Photon will be incorrect if power has been removed and the RTC is wiped. You can do a simple test to see if the time is valid by checking that Time.year() > 1970. I usually run this code to do the check:

while (Time.year() <= 1970) {
    delay(10);
}

Note that the delay(10) will call Particle.process() in the background.

:wink:

Ah I like that. the reason I was calling Particle.syncTime(); originally was due to the face that my first message would always send with a time stamp that was pre-epoch!

1 Like

Guys…you know when you have been looking at the same piece of code for days and you can’t work out what doesn’t work?

I’m running this modified version of the example again, and for some odd reason, half of the values return “0.00”…

Here is the code:

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

double getTemp(DS18B20 sensor); 

SYSTEM_MODE(SEMI_AUTOMATIC); //comment this in when debugging - prevents Particle connecting to 3G network

int genericPin = D6;
int loxonePin = D5;

DS18B20 generic = DS18B20(genericPin); 
DS18B20 loxone = DS18B20(loxonePin);
char szInfo[64];
int DS18B20nextSampleTime;
int DS18B20_SAMPLE_INTERVAL = 20000; //2500 default


void setup() {
    Time.zone(-5);
    Particle.syncTime();
    
    pinMode(genericPin, INPUT);
    pinMode(loxonePin, INPUT);

    Serial.begin(115200);
}

void loop() {

//if (millis() > DS18B20nextSampleTime){
    
    sprintf(szInfo, "generic: %2.2f", getTemp(generic));
    Serial.println(szInfo); 
    
    
    sprintf(szInfo, "loxone: %2.2f", getTemp(loxone));
    Serial.println(szInfo); 
    delay(10000);

 // }
}


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

And here is a sample from the serial monitor:

    Opening serial monitor for com port: "COM7"
generic: 23.19
loxone: 24.00
generic: 0.00
loxone: 0.00
generic: 23.19
loxone: 24.00
generic: 0.00
loxone: 0.00
generic: 23.19
loxone: 24.00
generic: 0.00
loxone: 0.00
generic: 23.19
loxone: 24.00
generic: 0.00
loxone: 0.00
generic: 23.25
loxone: 24.00
generic: 0.00
loxone: 0.00
generic: 23.25
loxone: 24.00
generic: 0.00
loxone: 0.00
generic: 23.25
loxone: 24.06
generic: 0.00
loxone: 0.00

I’m sure I’ll feel like an idiot when someone tells me what I’m doing wrong, but I’m at the tipping point!!

Cheers :laughing:

You might want to put back the debug prints inside that getTemp() :wink:

@ScruffR I’ve had those uncommented for a bit. All I noticed is the ‘bad attempts’ at the first call to this, as the probes are just stablising after boot up. But I still can’t figure out for the life of me why the ‘celsius’ value isn’t being placed into the ‘celsius’ variable every OTHER call.

I guess this is the reason

  double celsius;
  if(!sensor.search()) {
    ...
  }
  return celsius;

@ScruffR: The original code wrote to a global variable, ‘celsius’, but because I’m creating multiple instances of the DS18B20, I can’t do that, so i had to take this approach. I’ve simply replaced the ‘Serial.print()’ statements with ‘return’ statements, to get the celsius value back, but this is obviously not working…

I guess your sensor.search() can’t find the sensor and hence will not return a valid temperature.
To test this theory, you can just declare double celsius = 123.45; and see if that is coming back now instead of 0.0.

I’d acutally expect random values to come back, since automatic variables aren’t initialzed by default, but maybe a previous call leaves a 0.0 on the stack.

That’s what I thought with regards to the ‘0.0’! Iv’e changed it and still ‘0.0’ back! Crazy times! Perhaps this library isn’t written in such a way that I can do this!