[SOLVED] Help with OOP needed (DS18B20)

Hello,

I'd like to have two DS18B20 sensors and use classes to work with them.
I can't figure out how to call "sensors.getTempCByIndex" declared in the main program from my class, I get "sensors was not declared in this scope" error.

How can I call sensors' method from within my new object?

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "talking_sensor.h"
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

TalkingSensor OuterSensor(0); // OuterSensor is on index 0
TalkingSensor InnerrSensor(1); // InnerSensor is on index 1

void setup() {
 sensors.begin();
}

void loop() {
 sensors.requestTemperatures();   // called only once, time-consuming call
 OuterSensor.Update();
 InnerSensor.Update();
}

talking_sensor.h looks like this:

class TalkingSensor {
   int sensor_id;
   public:
   float current_temp;
   TalkingSensor(int _sensor_id){
        sensor_id = _sensor_id;
   }

  void Update(){
 current_temp=sensors.getTempCByIndex(sensor_id); 
        // do other stuff
   }
};

What does your sensors class look like?

I don't understand why you have to another class called TalkingSensor.

TalkingSensor will be used to upload to a webpage, write to serial console etc. Only one instance of the sensors class is necessary to read data from all DS18B20 sensors on one wire, but I need multiple classes to process those data.
I can of course call InnerSensor.Update(sensors.getTempCByIndex(0)) and OuterSensor.Update(sensors.getTempCByIndex(1)) but this is not the point of the program. I'd like TalkingSensor instances to read temperatures from sensors object themselves.
I want to run their Update() function all the time in the main loop() but want the objects decide themselves when to let the sensors objects tell them temperatures (e.g. only once a second) - the chip itself does conversions and this is time consuming.

hudis602:
Only one instance of the sensors class is necessary to read data from all DS18B20 sensors on one wire,

I think you need to rethink this idea.

No need for a separate sensors class.

Move the declaration of 'sensors' to TalkingSensors.cpp. Initialize it in TalkingSensor.begin() which you would call from setup().

Having a class called sensors does not make sense.

Making current_temp public is a bad idea.

You create an array of senor objects.
You call sensor[0].begin()
You call sensor[0].update() which would get a new temperature and place that value in current_temp.
You call sensor[0].getTemp() to get the new temperature

According to this sensors are not very fast so I'd like to let them do their work asynchronously and independently. The whole point is to have to deal with sensors only once and use results multiple times. If it is not possible to call sensors methods from other objects, I guess I will create a bunch of global variables and let the other objects use them.

hudis602:
If it is not possible to call sensors methods from other objects

Your talking_sensor.h is written wrong.

I know it's wrong, that's why I'm asking here how to write it right :slight_smile:

Do you see how the sensors object is passed a reference to the onewire object when it is instantiated? You could do the same with your objects and the sensors object. Your class would need to hold on to that reference to the sensors object that it is given at instantiation, along with the sensor index number. Then it could invoke the sensors object to take reading when required.

I'm not familiar with pointers and references and I tried to put the ampersant sign at various places and hot various error messages. If tou are familiar with this, could you please send an example or point me to one? Thank you

hudis602:
I know it's wrong, that's why I'm asking here how to write it right :slight_smile:

You are obviously trying to follow that example in the link you provided.

Why did you feel the need to create another class called talking sensor? That answer didn't say to do that.

Seems this is what I was looking for

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "talking_sensor.h"

#define ONE_WIRE_BUS D3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

TalkingSensor OuterSensor(&sensors,0); 
TalkingSensor InnerSensor(&sensors,1); 

void setup() {
  Serial.begin(9600);
  delay(100);
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures();   
  OuterSensor.Update();
  InnerSensor.Update();
  delay(3000);
}

takling_sensor.h :

class TalkingSensor {
   DallasTemperature* sensors_object;
   int sensor_id;
   public:
   float current_temp;
   TalkingSensor(DallasTemperature* _sensors_object, int _sensor_id)
   {
        sensors_object = _sensors_object;
        sensor_id = _sensor_id;
   }

  void Update(){
    current_temp=sensors_object->getTempCByIndex(sensor_id); 
    Serial.print("Sensor ");
    Serial.print(sensor_id);
    Serial.print(" temp: ");
    Serial.println(current_temp);
  }
};

Yes, that's exactly what I meant. Well done figuring out the code. So it works ok?

It does exactly what it should do, except the DallasTemperature library returns data from first sensor (index=0) and second sensor if asked for any other index>=1.

hudis602:
It does exactly what it should do, except the DallasTemperature library returns data from first sensor (index=0) and second sensor if asked for any other index>=1.

you may want to just define an array of known addresses and then get the temperatures by address instead

As I recall you are not guaranteed to get the same array of sensors every time you poll it anyways.

BulldogLowell:
As I recall you are not guaranteed to get the same array of sensors every time you poll it anyways.

I think you are guaranteed to get the same sequence. That's been my experience, anyway.

On this page it states

To find the devices, the master broadcasts an enumeration command, and then an address, "listening" after each bit of an address. If a slave has all the address bits so far, it returns a 0. The master uses this simple behavior to search systematically for valid sequences of address bits. The process is much faster than a brute force search of all possible 64-bit numbers because as soon as an invalid bit is detected, all subsequent address bits are known to be invalid. An enumeration of 10 to 15 devices finishes very quickly.

I interpret this to mean that the sequence is determined by the 64 bit address of each sensor. As long as you don't add/remove/replace a sensor, the sequence won't change.

Of course, you cant tell the addresses of the sensors just by looking at them, and it has nothing to do with the physical sequence they are connected in along a cable.