olkal/HX711_ADC

Initialization issue?

zufus opened this issue · 2 comments

zufus commented

Hi,

I am working on a project where I have 4 load cells. I started by the examples provided in the library with 2 cells, and I expanded it to 4 cells. It worked nicely. However, by following that approach, I ended up by filling the entire global variable memory space (about 95%).

Therefore, I adopted a workaround: I declared as global a array of pointers, and defined the variables in the the setup function. In this way, I only keep the pointer array as global, but can still access the cell objects from everywhere.

The memory is now almost empty, and everything works. The only issue that I have is that the data read from the cells are completely wrong, until I do the tare again. Then everything start to work properly. It seems that by creating the cell objects through the "new" command, the constructor is not properly addressed...

I also gave a look to the library source code, but I don't find a reason for this issue. As said, If I declare the object in the standard way, everything is OK before I do the tare....

Here it follows the script.

Thanks!

Marco


#include <HX711_ADC.h>
#include <EEPROM.h>

#define N 4 // Numero delle celle di carico

// Assegnazione PIN
// PIN CELLE DI CARICO
#define HX711_dout_1 2 //mcu > HX711 no 1 dout pin
#define HX711_sck_1 3 //mcu > HX711 no 1 sck pin
#define HX711_dout_2 4 //mcu > HX711 no 2 dout pin
#define HX711_sck_2 5 //mcu > HX711 no 2 sck pin
#define HX711_dout_3 6 //mcu > HX711 no 3 dout pin
#define HX711_sck_3 7 //mcu > HX711 no 3 sck pin
#define HX711_dout_4 8 //mcu > HX711 no 4 dout pin
#define HX711_sck_4 9 //mcu > HX711 no 4 sck pin

HX711_ADC *cella[N];

const float TELAIO = 1795.0;
//HX711_ADC cella[N] = {c1, c2};

void setup() {
unsigned long stab_time = 2000; // tare precision can be improved by adding a few seconds of stabilizing time
boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
byte cella_ok [4] = {0, 0, 0, 0};
float cal[4] = {442.35, 488.52, 515.87, 423.43};
int i = 0;

// create load cell objects
cella[0] = new HX711_ADC(HX711_dout_1, HX711_sck_1);
cella[1] = new HX711_ADC(HX711_dout_2, HX711_sck_2);
cella[2] = new HX711_ADC(HX711_dout_3, HX711_sck_3);
cella[3] = new HX711_ADC(HX711_dout_4, HX711_sck_4);

Serial.print("Begin Celle");

for (i = 0; i < N; i++) {
Serial.print(".");
cella[i]->begin();
}
Serial.println("OK");

Serial.print("Start Celle");
while ( _somma(cella_ok, N) < N) {
delay(100);
Serial.print(".");
for (i = 0; i < N; i++) {
if (!cella_ok[i]) cella_ok[i] = cella[i]->startMultiple (2000, true);
}
}
Serial.println("OK");

// Tara iniziale
Serial.println("Do tare");
for (i = 0; i < N; i++) {
Serial.print("Cella ");
Serial.print(i + 1);
if (cella[i]->getTareTimeoutFlag()) {
Serial.println(": Timeout");
} else {
Serial.println(": OK");
}
cella[i]->setCalFactor(cal[i]);
}

Serial.println("Press any key to continue");
while (!Serial.available()) {}
}

void loop() {
unsigned long t = 0;
static boolean newDataReady = 0;
static int byteCounter;
static float cal[4] = {};

boolean _resume = false;
int i;
const int serialPrintInterval = 0; //increase value to slow down serial print activity
float p_tot;
float data[4];

// check for new data/start next conversion:
if (cella[0]->update()) newDataReady = true;
for (i = 1; i < N; i++) {
cella[i]->update();
}

//get smoothed value from data set
if ((newDataReady)) {
p_tot = 0;
if (millis() > t + serialPrintInterval) {
for (i = 0; i < N; i++) {
data[i] = cella[i]->getData();
p_tot += data[i];
}
newDataReady = 0;
t = millis();
}
}

for (i = 0; i < N; i++) {
Serial.print("C");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(data[i]);
Serial.print(" gr.\t");
}

Serial.print("Total weight: ");
Serial.print(p_tot);

if (Serial.available()) {
Serial.println("qui");
char cmd = Serial.read();
Serial.println(cmd);
switch (cmd) {
case 't':
// Do Tare
_resume = false;

    Serial.println("When ready, press t again to do tare");

    while (_resume == false) {
      for (i = 0; i < N; i++) {
        cella[i]->update();
      }
      int nb = Serial.available();
     
      while (nb > 0) {
        byteCounter = byteCounter + 1;
        char inByte = Serial.read();
        --nb;

        if (inByte == 't') {
          Serial.println("Evvai con la tara!");
          delay(100);
          for (i = 0; i < N; i++) {
            cella[i]->tareNoDelay();
          }
        }
      }
      for (i = 0; i < N; i++) {
        if (cella[i]->getTareStatus() == true) {
          _resume = true;
        }
      }
    }

    break;


  case 'c':
    // Calibration

    while (_resume == false) {
      for (i = 0; i < N; i++) {
        cella[i]->update();
      }
      int nb = Serial.available();
      if (nb > 0) {
      }
      while (nb > 0) {
        byteCounter = byteCounter + 1;
        char inByte = Serial.read();
        --nb;

        if (inByte == 'c') {
          _resume = true;
          Serial.println("Evvai con la calibrazione!");
          delay(100);
          for (i = 0; i < N; i++) {
            Serial.print("Calibra cella ");
            Serial.print(i + 1);
            cella[i]->refreshDataSet();
            cal[i] = cella[i]->getNewCalibration(TELAIO / 4);
            Serial.print(" ");
            Serial.println(cal[i]);
          }
        }
      }
    }
    break;

  default:
    Serial.println("Uknown Command");

}

}

for (i = 0; i < N; i++) {
if (cella[i]->getTareStatus() == true) {
Serial.print ("Tara cella ");
Serial.print (i);
Serial.println (" OK");
}
}
}

int _somma(byte *rdy, int k) {
int i;
int r = 0;
for (i = 0; i < k; i++) {
r = r + rdy[i];
}
return r;
}

olkal commented

Hi Marco!
Unforunatley, this will not work. You are alocating memory in the Heap for the class objects in setup(). Then, when setup() is complete this memory is released. So even if your pointers are global, the memory they point to is now free, and can/will be used by the Stack for other functions.

If you run out of dynamic memory you have two options:

  • Reduce number of samples in each dataset (edit SAMPLES in config.h)
  • Use a different microcontroller with more memory
zufus commented

Hi, you are absolutely right! Thanks for the tip. I now read the memory scheme of Arduino and understood. I solved by moving all the output strings I have to the FLASH memory.. this created more available space!

Very nice library, btw!

Ciao

Marco