Initialization issue?
zufus opened this issue · 2 comments
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;
}
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
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