Probleme mit der Firmware zur Justierung der Waage auf ESP8266

arduino/Makefile-Linux.mk at master · hiveeyes/arduino · GitHub scheint mir auf Arduino Boards ausgelegt zu sein. Leider weiß ich nicht, wie ich es auf ESP8266 umbiege.

Das Makefile sollte hier erstmal irrelevant sein und liegt dort nur, um den sketch fürn Arduino zu kneten.
Wenn der ESP grundsätzlich mit den selben libs arbeitet und die Waage so funktioniert, sollte sich das auch übertragen lassen.
( genau kann ich es dir nicht sagen, weil ich mit dem ESP selber noch nicht gearbeitet habe)

The LowPowerLib does not work with ESP but it (and its related functionality) might not be relevant, for the adjustment. So you can comment it (and relevant functions) out.

Wir haben Dir ein Makefile-ESP8266.mk ins Verzeichnis gelegt:
https://github.com/hiveeyes/arduino/commit/c3a42a5f

Das Kompilieren klappt nun bei uns per:

# Announce path to Espressif SDK
export ESP_ROOT=~/dev/hiveeyes/sdk/esp8266-arduino

# Build firmware
make -f Makefile-ESP8266.mk

… so wie es unter Open Hive GSM and WiFi sensor nodes — Hiveeyes Arduino 0.16.0 documentation detaillierter beschrieben ist. Ohne ein Eisen vor Ort zu haben, können wir dafür allerdings keine Gewähr übernehmen :-). Viel Glück!

Der sollte für den ESP gehen, ich wieß allerdings nicht, ob meine ausgespuckten Werte dann zu Alex’ Sketch passen:

[ich finde das blockcode markup hier nicht]

/*
  Open Hive | Scale Adjustment
  ----------------------------
            | Scale ADC HX711

  Copyright (C) 2016 by Clemens Gruber 
            
  2016-07 Clemens Gruber | initial version 


  GNU GPL v3 License 
  ------------------
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  Licence can be viewed at                               
  http://www.gnu.org/licenses/gpl-3.0.txt


  pins hard coded
  ---------------
  D15 D14  Dout, SCK 
*/

// -------------------------+------
// variables you can modify | START
// -------------------------+------

// ** load cell characteristic
// --------------------------- 
// define here individual values for the used load cell
// this is not type specific! even load cells of the same type /
// model have individual characteristics 
//
// - ZeroOffset is the raw sensor value for "0 kg"
//   write down the sensor value of the scale with no load and 
//   adjust it here
// - KgDivider is the raw sensor value for a 1 kg weight load
//   add a load with known weight in kg to the scale, note the 
//   sesor value, calculate the value for a 1 kg load and adjust 
//   it here
long loadCellZeroOffset = 12022;
long loadCellKgDivider  = -21987;

// Testscale 38 cm - Prototyp 1 
// null  12022
// 1 kg  -21987

// Testscale ESP8266 (green cup) 
// null  -28594
// 1 kg  22207


// wait between samples
// 3 sec is a good delay so that load cell did not warm up 
// too much and external random influences like wind has time 
// to go so that the next sample is more valid
const int waitTimeLoadSamples = 3; 

// ** median statistics (for weight)
// ---------------------------------
// number of readings for median samples
// 5 is a good compromise between time cost and stable output
int weightSamplesNumber = 10;  // take at least 10 readings for adjusting 

// -------------------------+----
// variables you can modify | END
// -------------------------+----

// libraries
// load cell
#include <HX711.h>  // https://github.com/bogde/HX711
// load cell / HX711 pin definition: Dout 15, SCK 14
HX711 loadCell(14, 12);    // parameter "gain" is ommited; the default value 128 is used by the library
int adjustScale = true;  // flag for adjust vs. operation mode 
long weightSensorValue;
float weightKg;

// median statistics to eliminate outlier
#include <RunningMedian.h>  // http://playground.arduino.cc/Main/RunningMedian
RunningMedian weightSamples = RunningMedian(weightSamplesNumber);  // create RunningMedian object

// power saving 
// LowPower lib is not available for ESP8266
//#include <LowPower.h>  // https://github.com/rocketscream/Low-Power


void setup() {
  // serial communication
  Serial.begin(9600);
  
  Serial.println("Scale Adjustment for Open Hive / HX711");
  Serial.println("--------------------------------------");
  Serial.println();

  // switch off HX711 / load cell 
  loadCell.power_down();


  // adjust scale 
  // ------------
  
  // Step 1: tare scale 
  Serial.println(">> Step 1: tare scale");
  Serial.println("   ------------------");
  Serial.println("   Remove all weight from the scale!");
  Serial.println("   (If done, input any character to continue ...)");
  Serial.println(); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  Serial.read();  // clear serial input d
  
 
  // get Weight n times and calculate median 
  Serial.println("Get raw values for tare: ");
  getWeight();
  Serial.println(); 
  outputStatistic(0); 
  // set the median as zero offset value 
  loadCellZeroOffset = weightSamples.getMedian(); 

  // Step 2: weight lower limit
  Serial.println(">> Step 2: weight lower limit");
  Serial.println("   --------------------------");
  Serial.println("   Load at least 1 kg to the scale so that the raw values are > 0!");
  Serial.println("   (If done, input any character to continue ...)");
  Serial.println(); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  Serial.read();  // clear serial input 
  
  // get Weight n times and calculate median 
  Serial.println("Get raw values for lower limit: ");
  getWeight();
  Serial.println(); 
  outputStatistic(0); 
  long lowerValue = weightSamples.getMedian(); 
  
  // Step 3: weight upper limit
  Serial.println(">> Step 3: weight upper limit");
  Serial.println("   --------------------------");
  Serial.println("   Put a know load on the scale! ...");
  Serial.println("   ... and input weight in gram ...");
  Serial.println(); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  long kgValue = Serial.parseInt();
  
  // get Weight n times and calculate median 
  Serial.print("Get raw values for upper limit \""); 
  Serial.print(kgValue); 
  Serial.print(" g\":");
  Serial.println();
  getWeight();
  Serial.println(); 
  outputStatistic(0); 
  long upperValue = weightSamples.getMedian(); 
  
  // calculate loadCellKgDivider
  loadCellKgDivider = (upperValue - lowerValue) / (kgValue/1000); 

  // output calculated parameter
  Serial.println(">> Done! Your calculated parameters:");
  Serial.println("   ---------------------------------");
  Serial.println();
  Serial.print("   loadCellZeroOffset: ");
  Serial.print(loadCellZeroOffset);
  Serial.println();
  Serial.print("   loadCellKgDivider:  ");
  Serial.print(loadCellKgDivider);
  Serial.println();
  Serial.println("   ---------------------------------");
  Serial.println();
  
  Serial.println("You can test your calculated settings now!");
  Serial.println("(Input any character to continue ...)"); 
  Serial.flush(); 
  // wait for serial input 
  while(!Serial.available()) ;  // stop until a byte is received notice the ; after the while()
  Serial.read();  // clear serial input 
  Serial.println();
}


void loop() {
  // test settings 
  // ------------
  adjustScale = false; 
  
  // re-set number of weight sample
// does not work 
//  weightSamplesNumber = 5; 
//  RunningMedian weightSamples = RunningMedian(weightSamplesNumber);  // create RunningMedian object

  getWeight();
  Serial.println(); 
  outputStatistic(3); 
}


// functions
// ---------

// read raw data 
void getWeight() {
  // clear running median samples 
  weightSamples.clear();
  
  // read x times weight and take median 
  // do this till running median sample is full  
  do {
    // wait between samples
    Serial.flush();
    for (int i=0; i<waitTimeLoadSamples; i++) {
      // sleep for one second 
// LowPower lib is not available for ESP8266
// use delay instead 
//      LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // delay 60 ms 
      delay(1000);
    }
      
    // power HX711 / load cell 
    loadCell.power_up();
    
    delay(2);  // wait for stabilizing 

    // read raw data input of ADS1231
    weightSensorValue = loadCell.read();
    
    // switch off HX711 / load cell 
    loadCell.power_down();
    
    // calculate weight in kg
    weightKg = ((float)weightSensorValue - (float)loadCellZeroOffset) / (float)loadCellKgDivider;
        
    // add single value to runnig median sample    
    if (adjustScale == true) {
      // use raw values for median statistic
      weightSamples.add(weightSensorValue);
      // debug raw values 
      Serial.println(weightSensorValue);
    }
    else
    {
      // use calculated kg values for median statistic
      weightSamples.add(weightKg);
      Serial.print(".");
    }
  } while (weightSamples.getCount() < weightSamples.getSize());
}

// print statistics for raw values (decimal 0) and kg values (decimal 3)
void outputStatistic(int decimal) {
  // debug
  Serial.println("Low \tAvg \tMed \tHigh \tDiff");
  Serial.print(weightSamples.getLowest(),decimal);
  Serial.print("\t");
  Serial.print(weightSamples.getAverage(),decimal);
  Serial.print("\t");
  Serial.print(weightSamples.getMedian(),decimal);
  Serial.print("\t");
  Serial.print(weightSamples.getHighest(),decimal);
  Serial.print("\t");
  Serial.println(weightSamples.getLowest()-weightSamples.getHighest(),decimal);
  Serial.println(); 
}

mit der Arduino IDE übersetzt stürzt es zur Laufzeit ab, während auf eine Eingabe gewartet wird.

>> Step 1: tare scale
   ------------------
   Remove all weight from the scale!
   (If done, input any character to continue ...)


Soft WDT reset

ctx: cont 
sp: 3ffef550 end: 3ffef760 offset: 01b0

>>>stack>>>
3ffef700:  3ffe8778 00000000 3fff0034 4020190e  
3ffef710:  feefeffe feefeffe 00000000 402025ca  
3ffef720:  3fffdad0 00000000 3ffee708 40201f12  
3ffef730:  feefeffe feefeffe feefeffe 3ffee72c  
3ffef740:  3fffdad0 00000000 3ffee724 40202d00  
3ffef750:  feefeffe feefeffe 3ffee740 40100114  
<<<stack<<<

Die Kompilierung im Terminal endet mit:

make -f Makefile-ESP8266.mk 
make: *** Keine Regel vorhanden, um das Ziel „../libraries/HX711/HX711.cpp“, 
  benötigt von „/tmp/mkESP/scale-adjust-hx711_generic/HX711.cpp.o“, zu erstellen.  Schluss.
  1. Welchen Sketch hast Du denn damit versucht, zu kompilieren? Den im Repository oder den obigen von Clemens?
  2. Hast Du das komplette Repository per git clone --recursive heruntergeladen? Falls ja, dann sollten eigentlich alle Bibliotheken korrekt anliegen: Im Makefile-ESP8266 wird auf die HX711 Bibliothek per ../../libraries/HX711 referenziert. Das sollte klappen (bzw. klappt bei uns), wenn man ins Verzeichnis wechselt und dort das Makefile aufruft:
cd scale-adjust/HX711/
make -f Makefile-ESP8266.mk

Ich habe den Sketch von Github benutzt, die Pins auf 12, 14 angepasst und versuche zu kompilieren, wie du auch vorschlägst. Die node-wifi-mqtt Firmware kompliliert ja auch in der selben Umgebung fehlerfrei.

Bist Du 100%ig sicher, dass Du das neue Makefile benutzt, das dort im Verzeichnis liegt?

Da die Firmwares zur Kalibrierung ein Verzeichnis tiefer liegen (scale-adjust/HX711) als die reguläre Firmware (node-wifi-mqtt), muss dort mit einer weiteren Pfadkomponente ../ auf das Basisverzeichnis zu den Bibliotheken verwiesen werden, also ../../libraries/HX711 vs. ../libraries/HX711. Ich vermute den Fehler in diesem Bereich.

Wenn ich mich recht entsinne, wurde damals der Y2K bug dadurch gefixt, dass in den RechnerUhren die Berücksichtigung der Zeitumstellung ignoriert werden muss. Das verschaffte uns weitere 2000Jahre, es ergab sich jedoch die die Problematik, dass einmal im Jahr eine -1h existierte, also eine Parallelstunde existiert. Normalerweise maskiert das Betriebsystem das mit einer Dummyzeit (zählt dann einfach weiter), aber die Kompiler können das nicht. Um das Problem jedoch nicht in der Nacht der tatsächlichen Zeitumstellung zu haben hat man das statisch auf die Nacht vom 1. April gelegt. Also einfach noch 36min warten und dann sollte das funktionieren.

just my 2 cents :-)

Der ESP läuft einfach in den watchdog, weil das Tastendruck-Warten while(!Serial.available()) ; ein busy wait ist. Das serielle Auslesen sollte in eine Schleife, die ein yield() enthält, um u.a. den Wachhund zu füttern. Den WDT solange auszuschalten, wäre nicht ratsam.

Danke für die Analyse @weef! So in etwa?
https://github.com/hiveeyes/arduino/commit/5ac2d35d

@Thias: Die volle Version findest Du im Branch “scale-adjust-esp8266”: https://github.com/hiveeyes/arduino/blob/scale-adjust-esp8266/scale-adjust/HX711/scale-adjust-hx711.ino

Wie immer ohne Gewähr :-). Sag Bescheid, falls es funktioniert.

Sketch stürzt nicht mehr ab beim Warten auf eine Eingabe. gut! Allerdings wird das Normgewicht bei Schritt 3 nicht eingelesen. kgValue ist immer 0, wodurch dann später eine Division durch 0 einen Crash auslöst. Auch ist aus der Bildschirmausgabe nicht erlesbar, dass nur volle kg eingegeben werden müssen. (kgValue / 1000) schneidet für den Datentyp long vermeintliche Nachkommastellen ab. Oder stimmt da die Logik mit der Dimension noch nicht vollends?

Wunderbar!

Wir haben gerade eine kleine Verbesserung bereitgestellt, die das Problem vermutlich behebt. Da waren wir gestern zu schnell beim Umbau des Lesens von der seriellen Schnittstelle:
https://github.com/hiveeyes/arduino/commit/a3c118f2

Die Meldung sagt “... and input weight in gram ...”…

Stimmt! @clemens, was sagst Du dazu?

hat mich gestern auch noch verwundert.

a/(b/c) ist zwar identisch mit a*c/b , aber bei (long)Int-Division merkt man davon nichts, insbesondere wirkt sich b (kgValue) nicht sonderlich aus, was aber der Fall sein muß. Da ist noch was komisch.


Das könnte daran, liegen, daß @Andreas in der Funktion void wait_for_keypress() ein

// Clear serial input
Serial.read();

hat. Damit geht wohl mind. ein Zeichen bei der Eingabe von kgValue verloren?

Ja, scheint falsch zu sein, ist mir und auch Frank bisher noch gar nicht aufgefallen, da wir immer mit genau 1000 g justieren und das dann nicht relevant ist.

Ist ein neues Problem, das ich mit der 1.8.1er IDE nun auch habe. Mit der 1.6.6er ging der sketch noch.

Ja, das hatten wir vermutet. @clemens und @Thias: Probiert bitte bei Gelegenheit die überholte Version:
https://github.com/hiveeyes/arduino/blob/scale-adjust-esp8266/scale-adjust/HX711/scale-adjust-hx711.ino

Wenn die funktioniert, dann können wir sie in den master branch tun und ich kann einen Haken dran setzen.

Viele Grüße,
Andreas.

…aber doch sicher nur, wenn Du ‘das’ (die alte Version) für einen ESP baust - gewiß nicht bei einem AVR?! Das hatten wir doch oben: der watchdog ist beim ESP für housekeeping-Dienste immer an, und das ‘wait-for-keypressed’ honorierte das nicht - und das ist von Deiner IDE-Version unabhängig.

Ich vermute, dass das Programm vorher bei @clemens seiner Aussage nach lief, weil noch ein älteres Espressif SDK unter der Haube war, das in dem Bereich evtl. gnädiger war. Genau kann ich es mir aber auch nicht vorstellen.

Seis drum: Es wäre spitze, wenn Ihr die neue Variante der Firmware sowohl auf ESP8266 als auch auf AVR überprüfen könntet. Danke!

Ich habe den gelisteten sketch für die Justierung von zwei Waagen genutzt - mit dem ESP8266! Einmal Anfang Januar und nochmal für meine Testwaage mit 4x AA-Zellen, vor ca. 4 Wochen, da ich die 1.8er Version neu installiert habe kann es sein, dass der ESP-core für die Arduino IDE ein anderer war. Aber es lief mal!

----- Reply message -----