KurtE
Senior Member+
@bastiaan: I hear you, we have all been there. For example just ask me how to do something in JAVA, and I am lost... (Or busy with google)...
There are many different ways for you structure your code.
Note: I started off as a C only person (although before that: Fortran2, some assembly, PLI1, COBOL, Datapoint, ...), but later branched into C++. Although I am an old timer who is still not comfortable with some of those new fanged things like templates, Lambda...
Sorry I should have avoided adding extra complexities like inline... All that means is the code of that method is put in line. So if you call it 20 places there may be 20 copies of that same code... But plus side if it is something as simple as returning an internal variable than it allows you to protect the access to those data members.
Then there is some other magic glue things like:
public, versus private, versus protected: public implies code outside of this class can access the members and variables that are in the public area.
Those areas in private: can only be accessed by the class itself.
Sort of like private: protected means that in addition to this call can access those data members or methods, classes that are derived from this class can access them as well.
I also took the slightly more complicated route and made this new class be a sublclass of the Adafruit class?
I also took some short cuts with how I defined it... So for example the Adafruit class is defined like:
Again pretty simple, the class is pretty straight forward.
So if I rework my simple class above, and unwind it, it might look like:
First the class definition. Could still be in .ino file or could be split out... For now I would maybe keep in same file...
Now split out the code. Could be in same file or a separate file (.cpp) would need to include appropriate header files.
Again why I like going this way is everything about your sensor and dealing with it are contained here. Your display code simply has to use the methods to retrieve the values.
So you should be able to debug the class on its own... Create 4 of them either loop on them or just add 4 lines that do call update()..
Another completely different way is again to not use an array to return multiple values, is instead create a structure that contains all of the data for the return values:
Something like: Sorry in advance I will complicate slightly be adding typedef as you will see many examples of this in the base code.
Something like:
Then your code could return a structure...
That is you could have it return this structure.
More later.
There are many different ways for you structure your code.
Note: I started off as a C only person (although before that: Fortran2, some assembly, PLI1, COBOL, Datapoint, ...), but later branched into C++. Although I am an old timer who is still not comfortable with some of those new fanged things like templates, Lambda...
Sorry I should have avoided adding extra complexities like inline... All that means is the code of that method is put in line. So if you call it 20 places there may be 20 copies of that same code... But plus side if it is something as simple as returning an internal variable than it allows you to protect the access to those data members.
Then there is some other magic glue things like:
public, versus private, versus protected: public implies code outside of this class can access the members and variables that are in the public area.
Those areas in private: can only be accessed by the class itself.
Sort of like private: protected means that in addition to this call can access those data members or methods, classes that are derived from this class can access them as well.
I also took the slightly more complicated route and made this new class be a sublclass of the Adafruit class?
I also took some short cuts with how I defined it... So for example the Adafruit class is defined like:
Code:
class Adafruit_MAX31855 {
public:
Adafruit_MAX31855(int8_t _sclk, int8_t _cs, int8_t _miso);
Adafruit_MAX31855(int8_t _cs);
bool begin(void);
double readInternal(void);
double readCelsius(void);
double readFahrenheit(void);
uint8_t readError();
// Define the update timeouts
static const uint32_t TC_1b1_Interval = 100; // Choose the time... this is same as #define except it is only in class and has a type
private:
Adafruit_SPIDevice spi_dev = NULL;
boolean initialized;
uint32_t spiread32(void);
};
So if I rework my simple class above, and unwind it, it might look like:
First the class definition. Could still be in .ino file or could be split out... For now I would maybe keep in same file...
Code:
class cached_max31855 : public Adafruit_MAX31855 {
Public:
// constructor
cached_max31855 (int8_t _sclk, int8_t _cs, int8_t _miso);
// We have ability to call directly all of the Adafruit methods.
// cached - computed values
double internal() {return _cached_internal;}
double celsius() {return _cached_celsius;}
double computed() {return _cached_computed; } // again not sure what this is.
bool update(); // called to update the cached values;
bool changed() {return _changed; } // return true if some value changed since last clear.
void clearChanged() {_changed = false; }
private:
bool _changed = false; // something changed;
double _cached_internal = 0.0;
double _cached_celsius = 0.0;
double _cached_computed = 0.0;
elapsedMillis emUpdate = TC_1b1_Interval; // make sure it fires the first time through
}
Now split out the code. Could be in same file or a separate file (.cpp) would need to include appropriate header files.
Code:
// Constructor: First call off to parent class
cached_max31855::cached_max31855 (int8_t _sclk, int8_t _cs, int8_t _miso) : Adafruit_MAX31855 (_sclk, _cs, _miso) {
};
// We have ability to call directly all of the Adafruit methods.
// cached - computed values
double cached_max31855::internal() {
return _cached_internal;
}
double cached_max31855::celsius() {
return _cached_celsius;
}
double cached_max31855::computed() {
return _cached_computed;
} // again not sure what this is.
bool cached_max31855::changed() {
return _changed;
} // return true if some value changed since last clear.
// Now the fun part...
void cached_max31855::clearChanged() {
_changed = false;
}
bool cached_max31855::update() {
; // called to update the cached values;
if (emUpdate >= TC_1b1_Interval) {
emUpdate = 0; // clear timer
// read in your updated stuff maybe update changed.
// changed for double is sort of tricky... for now absolute difference... could be an abs delta > threshold or ???
double new_val = readCelsius(); // Uses base classes call
if (new_val != _cached_celsius ) {
_changed = true;
_cached_celsius = new_val;
new_val = readInternal();
if (new_val != _cached_internal) {
_changed = true;
_cached_internal = new_val;
}
if (_cached_celsius < 0) //if temperature is lower than 0 ////Thermocouple 1
{
// compute the other value here...
...
}//_cached_celsius if statement
else //this is the 0...500°
{
// again compute ...
}
return _changed; // return our cached value of being changed... If useful?
}
So you should be able to debug the class on its own... Create 4 of them either loop on them or just add 4 lines that do call update()..
Another completely different way is again to not use an array to return multiple values, is instead create a structure that contains all of the data for the return values:
Something like: Sorry in advance I will complicate slightly be adding typedef as you will see many examples of this in the base code.
Something like:
Code:
typedef struct {
double celcius;
double internal;
double computed;
} MAX31855_t;
Then your code could return a structure...
That is you could have it return this structure.
Code:
MAX31855_t UpdateFunction() {
MAX31855_t max;
max.celcius = mysensors(i)->readCelsius();
max.internal = mysensors(i)->readInternal();
,,,
return max;
}
...
More later.