0

I am far from being an Arduino specialist, so please bear with me if some of my code below is far from correct.

I am writing a sketch in which I need to use 3 instances of the HX711 library, as I am using 3 different weight sensors.

In order to try to clean up the code, I want to put basically all the code using HX711 in my own class.

Here is what my ScaleMeasure.h looks like:

// ScaleMeasure.h
#ifndef _SCALEMEASURE_h
#define _SCALEMEASURE_h

#if defined(ARDUINO) && ARDUINO >= 100
    #include "arduino.h"
#else
    #include "WProgram.h"
#endif

#include <CmdMessenger.h>
#include "HX711.h"

class ScaleMeasure
{
 public:
    ScaleMeasure(int Dout, int Clk, float CalibF, int ScaleID); 
    void Setup();   
    float Measure();    

private:
    int _dout_pin;
    int _clk_pin;
    float _calibration_factor;
    byte _scaleID;
    HX711 _scale = HX711(_dout_pin, _clk_pin);  
};

and .cpp

#include "ScaleMeasure.h"

ScaleMeasure::ScaleMeasure(int Dout, int Clk, float CalibF, int ScaleID)
{
    _clk_pin = Clk;
    _dout_pin = Dout;   
    _calibration_factor = CalibF;
    _scaleID = ScaleID;     
}

void ScaleMeasure::Setup()
{       
    _scale.power_up();
    _scale.set_scale();
    _scale.set_scale(_calibration_factor);
    _scale.tare();
    _scale.read();
}

float ScaleMeasure::Measure()
{   
    return _scale.get_units(5);
}

but there is obviously something wrong, as a call to the constructor lock the rest of the program. I believe that my instantiation, of HX711 in ScaleMeasure.h HX711 _scale = HX711(_dout_pin, _clk_pin); is not correct, or not in the right place. The code compile fine, though.

Thanks for your help.

3 Answers 3

1

The right way, in C++, to properly construct a field member b (of type class B) inside a class A is to do it as follows in A's constructor:

A::A() : b(...) {
    // Other init code here
}

In your situation that would mean:

class ScaleMeasure
{
 public:
    ScaleMeasure(int Dout, int Clk, float CalibF, int ScaleID); 
    void Setup();   
    float Measure();    

private:
    int _dout_pin;
    int _clk_pin;
    float _calibration_factor;
    byte _scaleID;
    HX711 _scale;  
};

Note that I have removed the init part for _scale.

ScaleMeasure::ScaleMeasure(int Dout, int Clk, float CalibF, int ScaleID)
: _scale(Dout, CLk)
{
    _clk_pin = Clk;
    _dout_pin = Dout;   
    _calibration_factor = CalibF;
    _scaleID = ScaleID;     
}
1
  • Ha! I tried "something like" this BEFORE asking here, but I may have made an error I did not saw. Thanks, I may get back to this, as it would allow to keep HX711 as is<. Thanks!
    – BernardG
    Aug 7, 2016 at 16:08
1

Unfortunatly HX711 has no default constructor. So the easiest way would be to add one in the header:

HX711() {} // default constructor, empty

Add member function to do the init job (done by original constructor), also in the header file

    void Init(byte dout, byte pd_sck, byte gain = 128) {
    PD_SCK  = pd_sck;
    DOUT    = dout;

    pinMode(PD_SCK, OUTPUT);
    pinMode(DOUT, INPUT);

    set_gain(gain);
}

Now your ScaleMeasure class will be like (header):

class ScaleMeasure
{
 public:
    ScaleMeasure(int Dout, int Clk, float CalibF, int ScaleID); 
    void Setup();   
    float Measure();    

private:
    int _dout_pin;
    int _clk_pin;
    float _calibration_factor;
    byte _scaleID;
    HX711 _scale;  
};

and cpp

ScaleMeasure::ScaleMeasure(int Dout, int Clk, float CalibF, int ScaleID)
{
    _clk_pin = Clk;
    _dout_pin = Dout;

    _scale.Init(_dout_pin, _clk_pin);  

    _calibration_factor = CalibF;
    _scaleID = ScaleID;     
}
3
  • Thanks for this different approach. I'll test and let you know how this goes.
    – BernardG
    Aug 6, 2016 at 18:51
  • Modifying the code of a library that you use is probably not the best way to solve this problem as it will prevent easy upgrades later on if the library in improved.
    – jfpoilpret
    Aug 7, 2016 at 8:42
  • It's the solution I choosed, as it's simpler and safe, IMHO. If the need .arise, version control will easily allow to implement eventual modifications
    – BernardG
    Aug 7, 2016 at 16:01
0

The line

HX711 _scale = HX711(_dout_pin, _clk_pin);  

would be executed at construction time, which is the wrong time for it to run since _dout_pin and _clk_pin won't be set. Instead (much as it pains me to recommend it) you will have to use dynamic allocation:

HX711 *_scale;

Then you can, in your constructor:

_scale = new HX711(_dout_pin, _clk_pin);

Since you now have a pointer all your accesses to it need to change to -> instead of .:

_scale->power_up();
... etc ...

Also you should add a destructor to your class that deletes the object pointed to by _scale if it has been created.

3
  • I would refrain (at any cost) to introduce dynamic allocation (with new) just to solve a problem related to proper use of the C++ language itself.
    – jfpoilpret
    Aug 7, 2016 at 8:43
  • There are many ways to skin a cat, all of them perfectly valid and correct. Dynamic allocation is absolutely fine in a memory constrained system as long as it is used "statically" - that is, allocated at init time and not deallocated. Heap fragmentation occurs only when objects are deleted, so if deletion is never needed or used then fragmentation never happens. There still more ways of solving the problem including passing a pointer (or reference) to an HX711 object to the custom class which alleviates the need to pass pins to said class. Like I said - skinning a cat.
    – Majenko
    Aug 7, 2016 at 9:53
  • I finally decided to add a default constructor to the library. Thanks anyway.
    – BernardG
    Aug 7, 2016 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.