HX711 basierte Waage

Über den Beitrag

Mit einem HX711 Modul und einer Wägezelle ist es kinderleicht, eine erstaunlich exakte Waage zu bauen. In diesem Beitrag möchte ich zeigen wie das prinzipiell funktioniert.  

Mein Ziel war es, die gleiche Funktionalität wie die meiner digitalen Küchenwaage zu erreichen: 

  • Ausgabe des Gewichtes auf einem Display
  • Nur ein Knopf zum Anschalten und für Tara
  • Automatisches Ausschalten nach einer bestimmten Zeit

Der Beitrag ist folgendermaßen gegliedert:

Was ihr braucht

Typisches Set aus Wägezelle und HX711 Modul
Typisches Set aus Wägezelle und HX711 Modul

Zum Bau der Waage benötigt ihr eine Wägezelle und ein HX711 Modul. Beides könnt ihr im Set kaufen. Wenn ihr z.B. bei Amazon oder eBay nach „HX711 Wägezelle“ sucht, bekommt ihr Dutzende von Angeboten für wenige Euro. Wählt eine Wägezelle mit dem für euch passenden Gewichtsbereich. Ich habe mir eine 2 kg Zelle besorgt. 

Was ihr sonst benötigt, kann ich euch nicht in einer konkreten Einkaufsliste vorgeben, da es zu sehr davon abhängt, wie ihr eure Waage gestalten wollt. Lest am besten erstmal weiter und entscheidet dann selbst.

Das Messprinzip

Die Wägezelle wird durch das Gewicht der zu wiegenden Last leicht gebogen. Unter dem weißen Kleber sitzen vier als Wheatstone Brücke angeordnete Dehnungsmessstreifen, deren Widerstand sich mit dem Dehnungsgrad, also mit dem Gewicht, ändert. Der Widerstand wird über den Spannungsabfall bestimmt und der wiederum mit einem A/D-Wandler ausgewertet. Wie das genau funktioniert, steht in meinem Beitrag über Dehnungsmessstreifen.

Die Änderung des Spannungsabfalls mit steigendem Gewicht ist recht gering. Ich habe wenige Millivolt pro Kilogramm gemessen. Der A/D-Wandler eines Arduino UNO bzw. eines ATmega328P ist dafür nicht geeignet. Der HX711 hingegen besitzt eine beeindruckende Auflösung von 24 Bit (= 16.777.216 Stufen).

Der HX711 selbst ist dabei eigentlich nur der sechzehnbeinige Chip auf dem Modul. Da er noch ein paar Elemente zur Beschaltung benötigt, bietet es sich an, zum Modul zu greifen. Wenn ihr euch trotzdem auch für die technischen Details des HX711 interessiert, dann findet ihr hier ein Datenblatt.

Verbauen der Wägezelle

Um ein bisschen Heimwerkern kommt ihr nicht herum. Die Wägezelle muss so eingebaut werden, dass sie sich unter Gewicht auch biegen kann. Ich habe dazu einfach ein Brett genommen und zwei gleich große Stücke abgesägt. Zwischen die Bretter kam die Wägezelle mit Abstandshaltern.

Die Wägezelle mit Abstandhaltern zwischen zwei Brettstücken
Die Wägezelle mit Abstandhaltern zwischen zwei Brettstücken

Durch das untere Brett habe ich zwei Löcher gebohrt und die Wägezelle mit zwei M5 Schrauben fixiert. Damit die Waage nicht direkt mit dem Brett aufliegt, habe ich ihr noch ein paar Füße spendiert: 

Unterseite der HX711 Waage
Unterseite der Waage

Für die andere Seite sind eigentlich M4 Schrauben vorgesehen. Um eine glatte Auflagefläche für das Wägegut zu behalten, wollte ich das obere Brett aber nicht durchbohren. Deswegen habe ich einfach ein paar Holzschrauben genommen.  

Von mir gewählte Schrauben
Von mir gewählte Schrauben

Die Kabel der Wägezelle werden folgendermaßen mit dem Modul verbunden:

  • Rot an E+
  • Schwarz an E-
  • Weiß an A-
  • Grün an E+
Anschluss der Wägezelle an das HX711 Modul
Anschluss der Wägezelle an das HX711 Modul

So sieht dann der Zwischenstand aus:

Die HX711 basierte Waage im Rohzustand
Die Waage im Rohzustand

Verwendung der HX711 ADC Bibliothek

Zur Ansteuerung des Moduls habe ich die HX711 ADC Bibliothek von Olav Kallhovd verwendet. Ihr könnt sie hier direkt von Github herunterladen oder ihr installiert sie über die Bibliotheksverwaltung der Arduino IDE. 

HX711 Grundschaltung

Minimumbeschaltung des HX711 am Arduino UNO
Minimumbeschaltung des HX711 am Arduino UNO

Das Modul kann mit Spannungen zwischen 2.6 und 5.5 Volt betrieben werden. Das Modul ist mit < 1.5 mA Stromverbrauch recht sparsam. Der DT-Pin wird mit dem Arduino Pin 4 verbunden, SCK kommt an Pin 5. Die Pins können auch geändert werden. 

Kalibrierung der Waage

Zur Kalibrierung braucht ihr einen Gegenstand mit bekanntem Gewicht. Das Gewicht sollte auf das Gramm genau bekannt und nicht zu klein sein. Am besten nehmt ihr eine zweite Waage zur Hilfe. 

Das Schöne an der hier verwendeten Bibliothek ist, dass sie euch das Leben – oder zumindest die Waagenkalibrierung – sehr einfach macht. Wählt aus den Beispielen der Bibliothek den Sketch „Calibration.ino“. Ich habe ihn hier unverändert abgedruckt:

//-------------------------------------------------------------------------------------
// HX711_ADC.h
// Arduino master library for HX711 24-Bit Analog-to-Digital Converter for Weigh Scales
// Olav Kallhovd sept2017
// Tested with      : HX711 asian module on channel A and YZC-133 3kg load cell
// Tested with MCU  : Arduino Nano, ESP8266
//-------------------------------------------------------------------------------------
// This is an example sketch on how to use this library
// Settling time (number of samples) and data filtering can be adjusted in the config.h file

// This example shows how to calibrate the load cell and optionally save the calibration  
// value to EEPROM, and also how to change the value.
// The value can later be fetched from EEPROM in your project sketch.

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

//HX711 constructor (dout pin, sck pin):
HX711_ADC LoadCell(4, 5);

int eepromAdress = 0;

unsigned long t = 0;

void calibrate() {
  Serial.println("***");
  Serial.println("Start calibration:");
  Serial.println("It is assumed that the mcu was started with no load applied to the load cell.");
  Serial.println("Now, place your known mass on the loadcell,");
  Serial.println("then send the weight of this mass (i.e. 100.0) from serial monitor.");
  float m = 0;
  boolean f = 0;
  while (f == 0) {
    LoadCell.update();
    if (Serial.available() > 0) {
      m = Serial.parseFloat();
      if (m != 0) {
        Serial.print("Known mass is: ");
        Serial.println(m);
        f = 1;
      }
      else {
        Serial.println("Invalid value");
      }
    }
  }
  float c = LoadCell.getData() / m;
  LoadCell.setCalFactor(c);
  Serial.print("Calculated calibration value is: ");
  Serial.print(c);
  Serial.println(", use this in your project sketch");
  f = 0;
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(eepromAdress);
  Serial.println("? y/n");
  while (f == 0) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
        #if defined(ESP8266) 
        EEPROM.begin(512);
        #endif
        EEPROM.put(eepromAdress, c);
        #if defined(ESP8266)
        EEPROM.commit();
        #endif
        EEPROM.get(eepromAdress, c);
        Serial.print("Value ");
        Serial.print(c);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(eepromAdress);
        f = 1;

      }
      else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        f = 1;
      }
    }
  }
  Serial.println("End calibration");
  Serial.println("For manual edit, send 'c' from serial monitor");
  Serial.println("***");
}

void changeSavedCalFactor() {
  float c = LoadCell.getCalFactor();
  boolean f = 0;
  Serial.println("***");
  Serial.print("Current value is: ");
  Serial.println(c);
  Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
  while (f == 0) {
    if (Serial.available() > 0) {
      c = Serial.parseFloat();
      if (c != 0) {
        Serial.print("New calibration value is: ");
        Serial.println(c);
        LoadCell.setCalFactor(c);
        f = 1;
      }
      else {
        Serial.println("Invalid value, exit");
        return;
      }
    }
  }
  f = 0;
  Serial.print("Save this value to EEPROM adress ");
  Serial.print(eepromAdress);
  Serial.println("? y/n");
  while (f == 0) {
    if (Serial.available() > 0) {
      char inByte = Serial.read();
      if (inByte == 'y') {
        #if defined(ESP8266)
        EEPROM.begin(512);
        #endif
        EEPROM.put(eepromAdress, c);
        #if defined(ESP8266)
        EEPROM.commit();
        #endif
        EEPROM.get(eepromAdress, c);
        Serial.print("Value ");
        Serial.print(c);
        Serial.print(" saved to EEPROM address: ");
        Serial.println(eepromAdress);
        f = 1;
      }
      else if (inByte == 'n') {
        Serial.println("Value not saved to EEPROM");
        f = 1;
      }
    }
  }
  Serial.println("End change calibration value");
  Serial.println("***");
}

void setup() {
  Serial.begin(9600); delay(10);
  Serial.println();
  Serial.println("Starting...");
  LoadCell.begin();
  long stabilisingtime = 2000; // tare preciscion can be improved by adding a few seconds of stabilising time
  LoadCell.start(stabilisingtime);
  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Tare timeout, check MCU>HX711 wiring and pin designations");
  }
  else {
    LoadCell.setCalFactor(1.0); // user set calibration value (float)
    Serial.println("Startup + tare is complete");
  }
  while (!LoadCell.update());
  calibrate();
}
void loop() {
  //update() should be called at least as often as HX711 sample rate; >10Hz@10SPS, >80Hz@80SPS
  //longer delay in sketch will reduce effective sample rate (be carefull with delay() in the loop)
  LoadCell.update();

  //get smoothed value from the data set
  if (millis() > t + 250) {
    float i = LoadCell.getData();
    Serial.print("Load_cell output val: ");
    Serial.println(i);
    t = millis();
  }

  //receive from serial terminal
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();
    else if (inByte == 'c') changeSavedCalFactor();
  }

  //check if last tare operation is complete
  if (LoadCell.getTareStatus() == true) {
    Serial.println("Tare complete");
  }

}

 

 

Startet den Sketch und öffnet den seriellen Monitor. Wartet bis folgende Meldung kommt:

Wagenkalibrierung am seriellen Monitor
Wagenkalibrierung am seriellen Monitor, Eingabe des bekannten Gewichtes

Dann nehmt euer Gewicht, legt es auf die Waage, gebt das Gewicht in Gramm ein und drückt Enter oder auf Senden. Notiert euch den „calibration value“ oder lasst ihn ins EEPROM des Arduino UNO schreiben. Dann wird munter das Gewicht ausgespuckt:

Die Waage im "Regelbetrieb"
Ergebnis der Waagenkalibrierung

Wenn das Gewicht ein wenig driftet, dann wiederholt die Kalibrierung und versucht mal eine längere „stabilisingtime“ (Zeile 145).  

Regelbetrieb am PC
Mein „Eichmaß“

Regelbetrieb der HX711 Waage

Nachdem ihr die Waage kalibriert habt, könnt ihr nun in den Regelbetrieb gehen. Dafür bietet sich der Sketch „Read_1x_load_cell.ino“ an, zumindest als Grundlage. Ihr müsst lediglich in Zeile 41 euren Kalibrierfaktor eintragen oder – falls ihr ihn im EEPROM habt – Zeile 45 entkommentieren. Ansonsten funktioniert der Sketch „out of the box“. Wenn ihr einen ESP8266 verwendet, müsst ihr zusätzlich noch Zeile 43 entkommentieren.

Für die Tara gebt ihr ein „t“ im seriellen Monitor ein.

/*
   -------------------------------------------------------------------------------------
   HX711_ADC
   Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
   Olav Kallhovd sept2017
   -------------------------------------------------------------------------------------
*/

/*
   Settling time (number of samples) and data filtering can be adjusted in the config.h file
   For calibration and storing the calibration value in eeprom, see example file "Calibration.ino"

   The update() function checks for new data and starts the next conversion. In order to acheive maximum effective
   sample rate, update() should be called at least as often as the HX711 sample rate; >10Hz@10SPS, >80Hz@80SPS.
   If you have other time consuming code running (i.e. a graphical LCD), consider calling update() from an interrupt routine,
   see example file "Read_1x_load_cell_interrupt_driven.ino".

   This is an example sketch on how to use this library
*/

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

//pins:
const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 5; //mcu > HX711 sck pin

//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);

const int calVal_eepromAdress = 0;
long t;

void setup() {
  Serial.begin(57600); delay(10);
  Serial.println();
  Serial.println("Starting...");

  LoadCell.begin();
  float calibrationValue; // calibration value (see example file "Calibration.ino")
  calibrationValue = 696.0; // uncomment this if you want to set the calibration value in the sketch
#if defined(ESP8266)|| defined(ESP32)
  //EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom
#endif
  //EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom

  long stabilizingtime = 2000; // preciscion right after power-up 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
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  }
  else {
    LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
    Serial.println("Startup is complete");
  }
}

void loop() {
  static boolean newDataReady = 0;
  const int serialPrintInterval = 0; //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();
      Serial.print("Load_cell output val: ");
      Serial.println(i);
      newDataReady = 0;
      t = millis();
    }
  }

  // receive command from serial terminal, send 't' to initiate tare operation:
  if (Serial.available() > 0) {
    float i;
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();
  }

  // check if last tare operation is complete:
  if (LoadCell.getTareStatus() == true) {
    Serial.println("Tare complete");
  }

}

 

Vielleicht wollt ihr beim Einschalten nicht tarieren? Dann ändert in Zeile 48 den Wert für _tare auf false. Ihr bekommt dann einen „Fantasiewert“ als Messergebnis. Schreibt euch diesen Wert auf und zieht ihn von zukünftigen Messergebnissen ab. Damit habt ihr die Tara sozusagen eingefroren. 

Ich habe die HX711 basierte Waage dann gegen meine Küchenwaage getestet… 

Es treten an: meine Küchenwaage...
Es treten an: meine Küchenwaage…
... gegen den HX711 Eigenbau.
… gegen den HX711 Eigenbau.

… und die Ergebnisse stimmten aufs Gramm!

Ausgabe über ein OLED-Display

Um die Waage vom PC unabhängig zu machen, braucht ihr ein Ausgabemedium. Ich habe dazu ein kleines OLED-Display ausgewählt, das nur wenige Milliampere Strom benötigt. Es wird über I2C mit Hilfe der Bibliotheken Adafruit GFX und Adafruit SSD1306 angesteuert. Falls ihr das auch tun wollt könnt ihr die Bibliotheken von Github über die Links herunterladen oder über die Bibliotheksverwaltung installieren. Auf die Details gehe ich hier nicht ein, denn das würde den Rahmen sprengen. Außerdem wollt ihr ja vielleicht auch ganz andere Displays einsetzen oder Sieben-Segmentanzeigen.

Ausgabe über ein TFT-Display
Ausgabe über ein TFT-Display

Nun noch paar Anmerkungen zum folgenden Sketch. Ein bisschen Aufwand habe ich betrieben um das Gewicht rechtsbündig anzuzeigen. Das wird in der Funktion floatToDisplayString bewerkstelligt. Die Funktion ermittelt zunächst die Zahl der freien Stellen (blanks) und hängt dann das Gewicht als String dran. 

Taramessungen werden über Interrupts an Pin 2 angefordert. Ausgelöst wird der Interrupt über einen Taster. Auf Tasterdruck wird die Variable taraRequest true und dadurch in der loop Schleife eine Taramessung initiiert. Während der Taramessung gibt die Waage ein „Wait“ auf dem Display aus. 

Der Rest des Sketches sollte halbwegs selbsterklärend sein (das behauptet natürlich jeder…). Wenn ihr fragen habt, fragt!

#include <Wire.h>
#include <HX711_ADC.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 7 // we don't have a reset, but the constructor expects it 

Adafruit_SSD1306 display(OLED_RESET);
HX711_ADC LoadCell(4, 5);

byte interruptPin=2;
volatile bool taraRequest = false;

void setup()   {                
  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), taraEvent, RISING);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  display.clearDisplay();
  display.setTextSize(4);
  display.setTextColor(WHITE);
  display.setCursor(10,4);
  display.println("Wait");
  display.display();
  LoadCell.begin();
  LoadCell.start(2000); 
  LoadCell.setCalFactor(883.73); 
}


void loop() {
  float weightAsFloat = 0.0;
  unsigned long t = 0;
  
  LoadCell.update();
  
  if (millis() > t + 250) {
    weightAsFloat = LoadCell.getData();
    displayWeight(weightAsFloat);
    t = millis();  
  }
  if(taraRequest){
    doTara();
    taraRequest = false;
  }
}

void displayWeight(float weight){
  String weightAsString = "";
  weightAsString = floatToDisplayString(weight);
  display.clearDisplay();
  display.setCursor(0,4);
  display.println(weightAsString);
  display.display();
}

void doTara(){
  LoadCell.tareNoDelay();
  display.clearDisplay();
  display.setCursor(10,4);
  display.println("Wait");
  display.display();
  while(LoadCell.getTareStatus()== false){
    LoadCell.update();
    delay(50);
  }
}

void taraEvent(){
  taraRequest = true;
}

String floatToDisplayString(float floatValue){
  String stringValue=" ";
  int intValue = (int)(round(floatValue));
  if(intValue<0){
    stringValue="";
  }
  uint8_t blanks = 3 - int(log10(abs(intValue)));
  for(int i=0; i<blanks; i++){
    stringValue+=" ";
  }
  stringValue+=(String)intValue;
  return stringValue; 
}

 

Und so sieht es dann aus:

HX711 Waage OLED Display und Tara - Taster
OLED Display und Tara – Taster

Der nächste Evolutionsschritt: Die Waage geht schlafen

Dann wollte ich, dass die Waage bzw. ihre Komponenten in einen Standby Modus gehen, wenn über einige Zeit weder eine Gewichtsänderung stattfindet, noch eine neue Taramessung angefordert wird. Da der Arduino UNO im Schlafmodus immer noch viel Strom verbraucht (siehe mein vorletzter Beitrag über Sleep Modes), habe ich hier den „nackten“ ATmega328P verwendet. Wie man mit den ATmega328P mit der Arduino IDE programmiert, habe ich hier beschrieben. Die Schaltung dazu sieht folgendermaßen aus: 

Vollständige Schaltung für die Waage mit Display und Taraknopf
Vollständige Schaltung für die Waage mit Display und Taraknopf

Im Sketch zu dieser Variante habe ich die Variable lastWeightAsFloat eingeführt, die den Wert der jeweils letzten Messung speichert. Dieser Wert wird mit dem aktuellen Messwert verglichen. Solange sich das letzte und das aktuelle Gewicht unterscheiden (Differenz < 1 g), ist die Waage offensichtlich in Benutzung. Und so lange wird die Variable tLastChange immer wieder auf millis aktualisiert. Das gleiche passiert bei einer Taramessung. Einmal pro Hauptschleife wird tLastChange mit millis verglichen. Überschreitet die Differenz 120.000 (= 2 min), wird die Waage in den Schlaf geschickt. Zunächst wird dazu das Display ausgeschaltet, dann das HX711 Modul und schließlich wird der ATmega328P in den Tiefschlafmodus versetzt.

Ein Interrupt weckt den ATmega328P wieder. Da der Taster für die Taramessung einen Interrupt auslöst, übernimmt er auch die Weckfunktion.

#include <Wire.h>
#include <HX711_ADC.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <avr/sleep.h>
#define OLED_RESET 9 // we don't have a reset, but the constructor expects it 

Adafruit_SSD1306 display(OLED_RESET);
HX711_ADC LoadCell(4, 5);

int interruptPin = 2;   // tara and wake-up pin 
int powerOnPin = 6;
volatile bool taraRequest = false;
float weightAsFloat = 0.0; // current weight (as float)
float lastWeightAsFloat = 9999.0;  // former weight
unsigned long t = 0;    // system time of last weight measurement 
unsigned long tLastChange = 0;  // system time of last change of weight

void setup()   {  
  pinMode(interruptPin, INPUT);
  pinMode(powerOnPin, OUTPUT);
  digitalWrite(powerOnPin, HIGH);
  initBalance();
  attachInterrupt(digitalPinToInterrupt(interruptPin), taraEvent, RISING);
}

void loop() {
  LoadCell.update();
  /* In one loop a) measurement is done or b) a tara or c) the balance will be send to sleep
  or d) nothing happens */
  if (millis() > (t + 250)) {
    weightAsFloat = LoadCell.getData();
    displayWeight(weightAsFloat);
    if(abs(weightAsFloat-lastWeightAsFloat) >=1){
      tLastChange = millis();
      lastWeightAsFloat = weightAsFloat;  
    }
    t = millis();
  }
  
  if(taraRequest){
    doTara();
    taraRequest = false;
  }
  
  if(millis() > (tLastChange + 120000)){ // after 2 min of no weight change or tara the balance shall fall asleep
    sleepAndWakeUp();
  }
}

void initBalance(){
  taraRequest = false;
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  display.clearDisplay();
  display.setTextSize(4);
  display.setTextColor(WHITE);
  display.setCursor(10,4);
  display.println("Wait");
  display.display();
  LoadCell.begin();
  LoadCell.start(2000); 
  LoadCell.setCalFactor(883.73); 
  weightAsFloat = 0.0;
  lastWeightAsFloat = 9999.0;
  t = 0;
}

void displayWeight(float weight){
  String weightAsString = "";
  weightAsString = floatToDisplayString(weight);
  display.clearDisplay();
  display.setCursor(0,4);
  display.println(weightAsString);
  display.display();
}

/* The following function displays the weight. The weight is therefore
 * changed into a string. The weight shall be displaey on the right side,
 * therefore the string begins with blanks.  
 */
String floatToDisplayString(float floatValue){
  String stringValue=" ";
  int intValue = (int)(round(floatValue));
  if(intValue<0){
    stringValue="";
  }
  uint8_t blanks = 3 - int(log10(abs(intValue)));
  for(int i=0; i<blanks; i++){
    stringValue+=" ";
  }
  stringValue+=(String)intValue;
  return stringValue; 
}

void doTara(){    // tara
  LoadCell.tareNoDelay();
  display.clearDisplay();
  display.setCursor(10,4);
  display.println("Wait");
  display.display();
  while(LoadCell.getTareStatus()== false){
    LoadCell.update();
    delay(50);
  }
  tLastChange = millis();
}

void taraEvent(){
  taraRequest = true;
}

void sleepAndWakeUp(){
  LoadCell.powerDown();            // switch off HX711
  display.ssd1306_command(SSD1306_DISPLAYOFF);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // deep sleep mode
  cli();
  sleep_enable();
  sleep_bod_disable(); // disable brown-out detector
  sei();
  sleep_cpu();
  /* ATmega328P sleeps */
  sleep_disable();
  LoadCell.powerUp();            // switch on HX711
  display.ssd1306_command(SSD1306_DISPLAYON);
  initBalance();
}

 

Mit diesem Aufbau habe ich im Schlafmodus einen Stromverbrauch von 139 Mikroampere ermittelt. Das sind 3.3 Milliamperestunden pro Tag. Ein Akku sollte also einige Zeit halten.

Die Waage ganz ausschalten

Dann habe ich mir überlegt, wie man die Waage ganz ausschalten kann, ohne einen zusätzlichen Schalter einzubauen (denn das kann ja jeder!). Genau genommen lautet die Frage, wie sich die Waage selbst ausschalten kann.

Ich habe die Aufgabenstellung mit einem Thyristor gelöst. Ein Thyristor hat eine gewisse Verwandtschaft mit einem Transistor. Er besitzt drei Anschlüsse, nämlich die Kathode, die Anode und das Gate. Ein kleiner Stromimpuls am Gate macht den Übergang von Anode zu Kathode leitend. Im Gegensatz zum Transistor bleibt der Thyristor leitend, solange der sogenannte Haltestrom überschritten wird. Bei dem von mir verwendeten MCR100-6 liegt der Haltestrom typischerweise bei 0.5 Milliampere. Da der Stromverbrauch im Sleep Modus wesentlich geringer ist, schließt der Thyristor. „Gezündet“ wird der Thyristor mit Hilfe des Taraknopfes. So sieht die Schaltung dazu aus:

Die sich selbst abschaltende HX711 Waagenschaltung
Die sich selbst abschaltende Waagenschaltung

Dabei gab es noch ein Problem: Solange der Thyristor leitet, bleibt auch die Spannung am Gate hoch. Da wir hier nun eine Verbindung zur Tarafunktion haben, bleibt auch die Spannung am Interruptpin hoch (orangefarbene Leitung). Damit funktioniert die Tara Anforderung nicht mehr. Deshalb habe ich noch eine Diode eingebaut, die den Weg in diese Richtung versperrt.

Ihr könnt den vorherigen Sketch verwenden. Zeile 122 bis 125, also die Aktionen nach dem Wake-Up, werden natürlich nie ausgeführt und können entsprechend gelöscht werden. 

Bei der Auslegung der Stromversorgung ist zu beachten, dass am Thyristor ca. 0.8 Volt abfallen. Entsprechend weniger steht den Bauteilen zur Verfügung. Bei 5 Volt Stromversorgung ist das für die hier verwendeten Bauteile kein Problem. 

Danksagung

Bei Olav Kallhovd möchte ich mich für seine schöne Bibliothek bedanken. Die Bibliotheken von Adafruit haben mir bei der Ansteuerung des Displays geholfen. 

Die Waage auf dem Beitragsbild habe ich Gerhard Gellinger auf Pixabay zu verdanken. Den Arduino im Hintergrund habe ich schon mehrfach verwendet. Er stammt von Seven_au auf Pixabay

114 thoughts on “HX711 basierte Waage

  1. Reinhard
    Danke. Es ist ein sehr guter Beitrag.
    Einen Teil (Kalibrierung, Messung, OLED display) habe ich umgesetzt.
    Nun kommen Tara Taster und Thyristor. Einen Vorschlag zur Stromversorgung haben Sie nicht gemacht.

    Können Sie einen beispielhaften Vorschlag machen?

  2. Hallo Wolfgang,

    vielen Dank für deine super Anleitung und deinen Block.
    Ich habe aber irgendwie ein Problem bei deinem Sketch.
    Mit dem Kalibrierungs-Sketch misst der HX711 einwandfrei aber wenn ich deinen Sketch hochlade
    fährt er zwar ganz normal hoch aber bleibt auf 0 stehen, egal was für ein Gewicht ich drauflege.
    Ich finde einfach den Fehler nicht, weil es mit anderen Sketchen funktioniert.
    Ich habe deinen 1:1 übernommen.
    Vielleicht hast du eine Idee was bei mir der Denkfehler ist, weil wenn die Verkabelung nicht stimmen würde, dann dürfte ja auch nichts anderes funktionieren.

    Gruß
    Stefan

    1. Hallo Stefan,

      du schreibst, dass der Kalibrierungssketch einwandfrei funktioniert. D.h. am Ende liefert er auch richtige Messwerte? Dann schreibst du, dass du den Sketch 1:1 übernommen hast – du meinst den Read_1x_load_cell.ino? Oder einen der folgenden Sketche? Ganz einfach 1:1 übernehmen kannst du ihn ja nicht. Mindestens den Kalibrierwert aus dem Kalibriersketch musst du eintragen. Hast du das gemacht? VG, Wolfgang

      1. Vielen Dank für deine rasche Antwort.
        Kalibrierwert aus dem Kalibriersketch habe ich nicht übernommen.
        Ich habe diesen Sketch “ balance_with_tft_display.ino “
        übernommen.
        Der Kalibrierungssketch hat das richtige Ergebnis angezeigt.
        Dein Sketch funktioniert auch jetzt.
        Ich hatte die Pins für den Wägebalken im Sketch getauscht, weil es es bei mir anders angeschlossen ist.
        Als ich auf (4, 5) zurückgewechselt habe lief es dann :).
        Jetzt habe ich nur ein anderes Problem, was ich noch am Versuchen bin zu beheben.
        Da ich das nicht gelernt habe muss ich mich da etwas durchfuchsen.
        Ich möchte die Waage als Motorprüfstand für Modellmotoren einsetzten und dafür noch eine Servofunktion einbetten, um per Knopfdruck den Motorregler immer um 10% zu erhöhen.
        Einzeln habe ich das schon hinbekommen aber, wenn ich es in deinen Sketch übernehme, dann funktioniert die Waage nicht mehr .
        Ich teste noch ein wenig rum, weil ich dich nicht unnötig damit beschäftigen möchte, da du bestimmt genug zu tun hast.
        Gruß
        Stefan

        1. So der Prüfstand läuft.
          Wäre nur schön, wenn er anstatt den Winkel des Servos den Prozentwert ausgeben würde.
          Mit 0-100% kann ich mehr anfangen als mit 60-114°.
          Ich weiß nicht wie ich das mit map hinbekomme.
          Falls du mir da eine kleine Hilfe geben könntest, wäre ich dir sehr dankbar.

          VG
          Stefan

          1. Hallo Stefan,
            map(gemessenerWinkel, unteresWinkelLimit, oberesWinkellimit,unteresProzentlimit, oberesProzentlimit). Als wenn deine Winkel zwischen 60 und 114° variieren und du 60° als 0% und 114° als 100% ansehen willst dann wäre das:
            WinkelInProzent = map(WinkelInGrad, 60, 114, 0, 100);
            Zu beachten ist, dass map() einen Integerwert liefert.
            VG, Wolfgang

  3. Hallo Wolfgang,
    danke für den Beitrag, alles sehr verständlich und nachvollziehbar. Meine Frage bezieht sich auf eine Anwendung im Langzeitbetrieb. Wenn ich alles verstanden habe, ist jedes Aufwecken mit einem Reset oder Tara-Abgleich verbunden. Jetzt beginnt wieder die Grillsaison und mein unvollendetes Projekt vom vorigen Sommer kommt wieder hoch. Ich möchte den Inhalt der Gasflasche vom Grill als Füllstandsanzeige wiegen. Das Leergewicht kenne ich (5,6kg), so dass ich kein Tara zur Nullstellung benötige. Wie kann ich den alten Wert von voriger Woche als neuen Startwert verwenden? Hast Du Erfahrungen mit so langen Messzyklen, dass ich wie in Deinem Beispiel den Wert vor Einschlafen in den Speicher schreibe, dieser auch als Startwert ein- zwei Wochen später verwenden kann? Viele Grüße von Rolf

    1. Hallo Rolf,
      schau mal in den Sketch Read_1x_Load_Cell.ino, Zeile 48. Wenn du dort _tare=false setzt, dann wird keine Tara gemessen. Die Waage arbeitet linear, d.h. die Messwerte sind dann alle um diesen Wert verschoben. Wenn du einen AVR Arduino (z.B. Uno, Nano, Pro Mini, Mega) hast, dann könntest du diesen Wert in den EEPROM schreiben. Unter Umständen verschiebt sich der Nullpunkt auf Dauer. Das passiert, wenn sich die Waage unter dem Gewicht auf Dauer verformt. Das muss man ausprobieren, aber das ist ja einfach.
      VG, Wolfgang

  4. Hallo ersteinmal und vielen Dank für die super Anleitung hat mir sehr geholfen.
    Jedoch habe ich ein Problem, die Waage misst aufbauend (was ich damit meine man stellt ein Gewicht mit 100g ab und im ersten update schreibt es 10.00g dann 33.00g, 56.00g, 87.00g und dann erst 100g).
    Ich möchte sie so Programiren das sei Hausnummer 5 Sekunden misst und dann mir das Endgewicht anzeigt.
    Ich brauche es um zwei Abläufe zu Triggern, der eine soll zwischen 0g und 50g getriggert werden, der andere zwischen 50g und 100g. Hätte diesbezüglich schon ein funktionierendes Programm, doch durch das aufbauende Messen, triggert es zuerst den ersten Messbereich und dann den zweiten.
    Kann mir jemand helfen?

    Herzliche Grüße,
    Markus

    1. Hi Markus,

      du könntest bei einer Veränderung des Gewichts prüfen, ob sich dieses noch weiter verändert oder nicht. Und erst wenn zwischen der letzten und der aktuellen Messung der Unterschied kleiner x ist, dann verwendest du den Messwert. Du speicherst also den aktuellen Wert in einer Variable „lastWeight“ und nach der nächsten Messung rechnest du Differenz = Aktuelle Wert – lastWeight. Das ganze machst du bis Differenz < x.

      VG, Wolfgang

      1. Hi Wolfgang,

        danke für die schnelle Rückmeldung. Ich habe es probiert aber leider geht es immer noch nicht, vielleicht findest du kurz Zeit mein Programm auf Fehler zu Prüfen.
        (Bin noch Anfänger)

        Hier der Code:

        …..

        1. Hi Markus,

          schicke mir den Code bitte mal per mail. Das Problem ist – und ich muss mal schauen, ob ich das irgendwie ändern kann – dass > und < hier im Kommentar als HTML Steuerzeichen interpretiert werden.
          Ich habe den Code erstmal ganz entfernt.
          Mail Adresse ist: wolfgang.ewald@wolles-elektronikkiste.de

          VG, Wolfgang

  5. Hallo Wolfgang,

    vielen Dank für die ausführliche Dokumentation, Schalpläne und Bilder! Ich muss/ darf für die Uni einen ähnlichen Aufbrau mit einem Raspberry Pi machen. Das Ziel ist hierbei eine möglichst feine Waage bzw. einen Aufbau für sehr geringe Masseänderungen von wenigen Gramm zu konstruieren. (Auf die Wägezelle soll eine kleine Kondensatorplatte und damit die Kraft F zwischen geladenen Platten in Abhängigkeit von der Spannung U bei konstantem Plattenabstand d gemessen werden.. also Elektrostatik-Versuche).
    Hast du da eine Idee wie man es auch für geringe Massen nutzen kann? Ich habe bei meinen (billigen) Wägezellen (500g und 1kg) stets das Problem mit der Nullpunktkalibrierung.. und bekomme weiterhin schwankende Spannungen raus..

    Eventuell hast du oder ein interessierter MitleserIn ja einen guten Gedankengang.

    Vielen Dank und liebe Grüße
    Raphael

    1. Hi Raphael,

      für meine in dem Beitrag beschriebene Waage habe ich auch eine dieser Wägezellen genommen, die es für ein paar Euro im Paket zusammen mit dem HX711 gibt. Wir reden über dieselben Teile, richtig? Du kannst dir das Foto oben ja noch mal anschauen. Und du steuerst die Wägezelle auch über den HX711 an, richtig? Im Gegensatz zu dir bin ich sehr begeistert von der Leistungsfähigkeit. Mit zwei einfachen Brettern konnte ich reproduzierbar auf das Gramm genau wiegen. Oder nutzt du etwas anderes, um die Wägezelle zu lesen? Beim HX711 gibt es ein paar Dinge zu beachten, zum Beispiel dass man mit 10 Hz und nicht mit 80 Hz messen sollte und dass man die Werte mittelt.
      Also bevor du die Wägezelle abschreibst, sage mir und den anderen Lesern erst einmal genau, wie du die Wägezelle ansteuerst und ausliest. Wenn du Schaltpläne, Programme, Fotos o.ä. hast kannst du mir das auch per mail zusenden (wolfgang.ewald@wolles-elektronikkiste.de).
      Die Wägezellen arbeiten ja mit Dehnungsmessstreifen (DMS), die als Wheatstone Brücke angeordnet sind. Ich habe in einem separaten Beitrag auch etwas über DMS gemacht, das könnte dir auch weiterhelfen.
      https://wolles-elektronikkiste.de/dehnungsmessstreifen
      Ist zwar alles Arduino / C++ aber vom Prinzip lässt sich das auf Python übertragen. Ich gehe zumindest davon aus, dass du Python benutzt, wegen des Raspberry Pi, richtig?
      Wir kriegen das hin. Milligramm wäre eine Herausforderung, Gramm ist kein Thema!
      VG, Wolfgang

  6. Hallo Wolfang!

    Zuerst möcht ich mich für den tollen Beitrag bedanken, der ist sehr hilfreich.

    Zu meinem Problem – bin noch Anfänger was dies angeht, ich versuche den gemessenen Wert an einem LCD-TFT Display auzugeben. Die Verkabelung sollte stimmen, aber wie gebe ich nun den Wert am Display aus?

    Ich wär mehr als glücklich wenn du mir weiterhelfen könntest.

    BG Olaf

    1. Hallo Olaf,

      ich kann in einem Kommentar kein Tutorial für LCDs unterbringen. Ich kann dir den Weg nur skizzieren. Wenn ich etwas neues angehe dann teile ich dass Problem erst einmal. Kannst du mit dem TFT Display umgehen, d.h. mit dem Arduino etwas ausgeben? Falls nein, dann arbeite eines der vielen Tutorials durch, die es dazu gibt, z.B.:

      https://www.makerguides.com/character-lcd-arduino-tutorial/
      https://docs.arduino.cc/learn/electronics/lcd-displays

      Und wenn du dann weißt wie es geht, dann musst du im Sketch „balance_with_tft_display.ino“ lediglich alles rausschmeißen, was zum TFT Display gehört und durch den LCD Code ersetzen, d.h. die LiquidCrystal Bibliothek einsetzen, ein LiquidCrystal Objekt anstelle eines TFT Objektes erzeugen und dann schließlich die das Gewicht mit der lcd.print() Funktion ausgeben.

      Mehr ins Detail kann ich hier nicht gehen.

      VG, Wolfgang

  7. Hallo Wolfgang,

    Super Hilfe dein Beitrag. Läuft alles gut. Ich würde die Wägezelle für einen Prüfstand für Modellturbinen nehmen. Da bräuchte ich eine etwas schnellere Aktualisierung der Werte. Ist das möglich?

    Gruß Michael

    1. Hallo Michael,

      es gibt im Wesentlichen zwei Schrauben an denen du drehen kannst: Standardmäßig sind die HX711 Module auf eine Messfrequenz von 10 Hz. Man kann sie auf 80 Hz erhöhen, sofern das auf dem Modul vorgesehen ist. Hier ist ein Beispiel, bei dem es geht:
      https://wolles-elektronikkiste.de/wp-content/uploads/2021/10/HX711_module_balance-1024×350.jpg
      Einfach den 0 Ohm Widerstand bei 10 Hz entfernen und die beiden Kontakte bei 80 Hz überbrücken. Probiert habe ich es nicht, aber es wird mehr Rauschen geben. Ein Hochsetzen der Frequenz per Software geht nicht.

      Die zweite Schraube lässt sich per Software drehen. Und zwar ist das die Anzahl der zu mittelnden Messungen. Der Autor der Bibliothek hat 16 voreingestellt. In den Bibliotheksdateien gibt es eine Datei namens config.h, da kannst du die Einstellung vornehmen. Da steht auch schön beschrieben, wie man die maximale Messfrequenz errechnet.

      Mit beiden Maßnahmen ist es möglich, von 1.8 Sekunden auf 1/80 Sekunden herunterzugehen. Aber wie gesagt, das Rauschen wird zunehmen.

      VG, Wolfgang

      1. Hallo Wolfgang,

        Danke für die schnelle Antwort. Habe es in der config.h Datei bearbeitet und es ist jetzt deutlich schneller. Ich werde es mal so testen. Jetzt muss ich nur noch ein nettes Startbild beim einschalten hinbekommen 🙂

        Noch eine kurze Frage. Die Messung geht je nach Turbine bis 20 kg. Da ist die Anzeige in Gramm etwas doof 🙂 Wenn ich die Anzeige anstatt in Gramm mit kg kalibriere, zeigt es mir nur ganze kg Werte an. Kann man sich auch Komma Werte anzeigen lassen?

        Gruß Michael

        1. Wenn du das Gewicht in Kilogramm als Float hast, dann kannst du es in einen String umwandeln:
          String weightAsString = String(weightAsFloat , 2);
          Die 2 bedeutet dabei die Nachkommastellen.
          Dann muss man nur schauen, wie man es rechtsbündig auf das Display bekommt. Über weightAsString.length() weiß man, wie lang der String ist und lässt links entsprechend viel Platz. Vielleicht gibt es auch fertige Funktionen dafür in irgendwelchen Display Bibliotheken.

          1. Danke schaue ich mir mal an. Habe es jetzt auf die schnelle nicht hinbekommen.
            Kann man den Höchstwert auch anzeigen lassen? Habe die Schriftart kleiner gemacht und habe so noch eine Zeile unter dem aktuellen Wert frei 🙂 Dann wäre mein Code für mein Projekt perfekt 🙂

            1. Was meinst du mit Höchstwert? Den höchst möglichen Messwert? Vielleicht verstehe ich dich gerade falsch.

              1. Sorry habe mich auch etwas doof ausgedrückt. Den höchsten Wert der gemessen wurde. Möchte damit messen, wie viel Schub die Turbine hatte ohne dabei immer auf das Display schauen zu müssen. Sobald ich die Turbine abschalte, könnte ich so zu dem Display gehen und sehen was sie in dem Testlauf hatte. Beim erneuten einschalten von der Waage wäre dieser wieder bei Null. Zusätzlich sollte aber weiterhin den aktuellen Wert auch dran stehen.

                1. Du führst eine Variable ein und die heißt z.B. maxValue. maxValue bekommt den Startwert 0.0. Und dann vergleichst du das jeweils aktuelle Gewicht mit dem maxValue:
                  if (weightAsFloat > maxValue){maxValue = weightAsFloat;}

                  Das führt jetzt aber schon ziemlich weit vom Blogthema weg…

  8. Ich weiß, ich frage jetzt ein klein wenig off Topic. Das Projekt ist aber eine Inspiration für mich.
    Wenn man jetzt beschließen würde, statt eines Thyristors einen Transistor zu verwenden und diesen über einen PIN zu schalten der ab Start auf High geschaltet ist. Und wenn statt eines Arduino ein ESP8266 die Arbeit macht. Und das mit 4 AA Batterien die über einen Festspannungsregler der 3,3V bei max 800mA für den ESP liefert. Welchen Transistor und welchen Widerstand für die Basis würden Sie empfehlen? Ich blicke einfach nicht durch bei der Berechnung und ich kenne auch die Unterschiede bei den Transistoren nicht.
    Mit den 5v am PIN eines Arduinos und einem BC337-40 mit 270 Ohm an der Basis gelingt mir die Sache problemlos.
    Bei 3,3v weiß ich einfach nicht welcher Transistor geeignet ist…. Ich frage für einen Freund 😀

    Herzliche Grüße und Danke, egal ob mit oder ohne Hilfe

  9. Hallo Wolfgang
    Danke für die vielen tollen Imformationenin den Beiträgen von Dir !
    Ich bin 63 Jahre alt und habe mich seit einem Jahr mit dem Arduino beschäftigt.Als erstes hab ich mir das Starterkit von Elegoo gekauft .Die Projekte hab ich auch nachgebaut .Einiges in Programierung habe ich verstanden aber auch so manches noch nicht.Da bin ich auf deinen Kanal gestoßen.
    Das Projekt „Waage“ interesiert mich ganz besonders. Ich bin Hobbyhühnerhalter und wollte mir schon immer etwas zur automatischen Fütterung bauen wen ich mal paar Tage in Urlaub bin .Meine Frage : Kann man den Sketsch so abwandeln,das wenn eine mechanische Schnecke z.B.1kg Körner gefördert hat, über einen Impuls
    der Antrieb abschaltet wird ? Über ein Antwort würde ich mich freuen.Viele Grüße aus Sachsen Andreas.N.

    1. Hallo Andreas,

      ja, natürlich. Vom Prinzip her kein Problem. Das Gewicht kann man ja regelmäßig messen und wenn es gleich oder größer als 1 kg ist, dann folgt das Abschalten. Zum An-/Abschalten gibt verschiedene Möglichkeiten: z.B. Relais, Schaltsteckdose, Mosfet. Das kommt auf dein Gerät an.

      VG, Wolfgang

      1. Hallo Wolfgang,
        erst eimal vielen herzlichen Dank für die schnelle Antwort. Wenn das also nicht das Problem ist den Sketch anders zu schreiben mus ich mich erst einmal damit auseinandersetzen. Darf ich dich wenn ich nicht klar komme konsultieren ? Ich denke ich muss da noch viel lese und lernen.
        Danke noch mal und viele Grüße A.N.

        1. Hallo Andreas,

          ich helfe gerne. Limitierender Faktor ist nur manchmal die Zeit. Melde dich einfach.

          VG, Wolfgang

  10. Danke für diesen Beitrag und danke für die vielen Antworten auf die gestellten Fragen. Ich arbeite gerade an 4 Vollbrücken an 4 HX711 mit einem ESP8266 – genauer an einem entkernten Wii Balance Board, dass mit die Gewichtsverteilung von Patienten nach Beinverletzungen als JSON bereitstellen soll. Zwar bin ich noch nicht am Ziel, jedoch hat mir dieser Beitrag hier sehr weitergeholfen.
    DANKE!

  11. Hallo,
    dies ist mein erstes Projekt mit einem Arduino, weswegen ich bei ein paar Sachen nicht weiterkomme.
    1: Wie verbinde ich die verschiedenen Sketche miteinander? Z.B. die Kalibrierung und den für die LED?
    2: Ich habe anstatt von einer OLED eine lcd1602, muss ich den Sketch dafür anpassen, und wenn ja, wie ungefähr?

    Danke im voraus,
    Freundliche Grüße

    1. Hallo,

      der Sketch für die Kalibrierung ist nur dazu da, den Kalibrierwert zu ermitteln, den man dann im endgültigen Sketch verwendet. Man verbindet die Sketche also nicht wirklich, sondern lässt erst den Kalibriersketch nur einmalig laufen und muss ihn nicht wiederholen, solange man nichts baulich an der Waage ändert.
      Zur anderen Frage: es gibt für die lcd1602 Display eine Bibliothek namens LiquidCrystal. Ein Dokumentation mit Beispielen gibt es hier:
      https://www.arduino.cc/en/Reference/LiquidCrystal
      und dann muss man das, was der Waagensketch mittels LoadCell.getData(); „ausspuckt“ (ich habe es weightAsFloat genannt mithilfe der Funktionen der LiquidCrystal Bibliothek auf das LCD Display bringen.
      Mehr ins Detail kann ich im Rahmen eines Kommentars nicht gehen.
      Viel Erfolg & viele Grüße, Wolfgang Ewald

  12. Ich habe ein Problem und zwar habe ich schon mehrere Codes ausprobiert für einen Tara Button aber jeder Code hat Fehler die ich nicht verstehe. Ich hoffe das jemand von euch mir helfen kann, da ich das schon seit 5 Stunden versuche und es einfach nicht hinbekomme. Ich muss dazu noch erwähnen das ich alles für den Seriellen Monitor brauche und nicht auf einem Display

    Hier der Code:
    #include
    #include
    #define OLED_RESET 7

    //we don’t have a reset, but the constructor expects it

    HX711_ADC LoadCell(4, 5);
    byte interruptPin=2;
    volatile bool taraRequest = false;
    void setup() {
    pinMode(interruptPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(interruptPin), taraEvent, RISING);
    Serial.begin ; // initialize with the I2C addr 0x3C (for the 128×64)
    Serial.clear();
    Serial.setTextSize(4);
    Serial.setTextColor(BLACK);
    Serial.setCursor(10,4);
    Serial.println(„Wait“);

    LoadCell.begin();
    LoadCell.start(2000);
    LoadCell.setCalFactor(883.73);
    }
    void loop() {
    float weightAsFloat = 0.0;
    unsigned long t = 0;

    LoadCell.update();

    if (millis() > t + 250) {
    weightAsFloat = LoadCell.getData();
    SerialWeight(weightAsFloat);
    t = millis();
    }
    if(taraRequest){
    doTara();
    taraRequest = false;
    }
    }
    void SerialWeight(float weight){
    String weightAsString = „“;
    weightAsString = floatToDisplayString(weight);
    Serial.clear();
    Serial.setCursor(0,4);
    Serial.println(weightAsString);

    }
    void doTara(){
    LoadCell.tareNoDelay();
    Serial.clear();
    Serial.setCursor(10,4);
    Serial.println(„Wait“);

    while(LoadCell.getTareStatus()== false){
    LoadCell.update();
    delay(50);
    }
    }
    void taraEvent(){
    taraRequest = true;
    }
    String floatToSerialString(float floatValue){
    String stringValue=“ „;
    int intValue = (int)(round(floatValue));
    if(intValue<0){
    stringValue="";
    }
    uint8_t blanks = 3 – int(log10(abs(intValue)));
    for(int i=0; i<blanks; i++){
    stringValue+=" ";
    }
    stringValue+=(String)intValue;
    return stringValue;
    }

    1. Hallo Alexander, die Funktionen „setTextSize“, „setTextColor“, usw. gehören zur Adafruit_SSD1306.h Bibliothek. Das heißt, du musst ein Objekt erzeugen, z.B. „display“:
      Adafruit_SSD1306 display(OLED_RESET);
      Und dann kannst du die Funktionen für das Objekt verwenden, also z.B. display.setTextSize(….);. Serial versteht diese Funktionen nicht. Den Funktionsumfang von Serial findest du hier:
      https://www.arduino.cc/reference/en/language/functions/communication/serial/
      Für deine Zwecke reichen print und println.
      Ich würde den Sketch Read_1x_load_cell.ino sketch nehmen und diesen um den Tara Button erweitern.

      1. Danke für die schnelle Antwort und den code den sie mir per email gesendet haben. Der Code hat funktioniert nur die Zahlen die rausgekommen sind waren ganz andere und es ist ein bisschen zu schnell

        1. Das mit dem „zu schnell“ lässt sich ja über ein ein delay steuern. Wenn andere Zahlen herauskommen, dann liegt das wahrscheinlich am Kalibrierwert. Eine HX711 basierte Waage muss auf jeden Fall kalibriert werden. Dafür gibt es den Sketch Calibration.ino.

          1. Hallo Wolfgang
            erst mal danke für die schnelle Antwort. Bei mir funktioniert alles immer besser nur habe ich das Problem das wenn ich die Waage kalibriere und dann den anderen Code hochlade, die Waage nicht mehr kalibriert ist.

            1. Hast du denn den Kalibrierwert übertragen? Die Wägezelle liefert ein Signal, das sich linear mit dem Gewicht ändert. Die Steigung der Gerade (calibrationValue) ist für jede Waage unterschiedlich. Du musst ihn einmal bestimmen, den Wert aber in jeden neuen Sketch übertragen. Die Taramessumg setzt den Nullpunkt.

  13. Hallo,
    erstmal danke für den Beitrag.
    Wir stellen aktuell das Projekt nach und es läuft soweit auch alles gut, wir kriegen die richtigen Werte auf dem Seriellen Monitor und die Tara Funktion über den Taster macht eben auch das was sie soll.

    Nun der Haken an der Sache: versuchen wir nun diesen Wert über unser Display auszugeben ( ein Adafruit SSD1306 ) so friert unser Programm ein und nichts geht mehr voran. Warum auch immer können wir immer nur mit dem HX711 kommunizieren oder mit dem Display, niemals mit beiden gleichzeitig bzw. nacheinander. Sobald mit der Funktion ‚display.display();‘ der Buffer für den Text übertragen werden soll bleibt das Programm stehen und nichts geht mehr voran. Der einzige unterschied sonst noch ist das wir keinen Arduino UNO sondern NANO verwenden, doch daran dürfte es doch nicht scheitern? Sonst ist alles angeschlossen so wie auch hier im Projekt beschrieben. Haben Sie evtl. eine Idee was genau das Problem sein könnte?

    MfG

    1. Hallo,
      ich kann sagen, dass es nicht am Arduino Nano liegt oder dass das zumindest sehr unwahrscheinlich ist.

      Woher wisst ihr denn, dass ihr mit dem HX711 kommunizieren könnt, wenn das Display nicht funktioniert?

      Und verwendet ihr den unveränderten balance_with_tft_display.ino sketch? Sonst schaue ich mir euren Sketch mal an (an wolfgang.ewald@wolles-elektronikkiste.de). Hat euer TFT Display andere Abmessungen? Ist vielleicht einfach nur der Cursor an einer falschen Stelle (display.setCursor())? Habt ihr die richtige I2C Adresse (0x3C für 128×32 / 0x3D für 128×64).

      VG, Wolfgang

      Mehr fällt mir aus der Ferne nicht ein.

  14. Hallo Wolfgang

    Zuerst einmal ein dickes Lob für Dein Blog, das ist für mich als Anfänger sehr informativ und gut verständlich. Nun habe ich eine Waage mit 4 x 50Kg Zellen nachgebaut mit Taster und TFT. Das funktioniert alles auch, jedoch nur bis 9999 Gramm, danach schaltet das Display ab, eine kleinere Schrift bringt auch nicht mehr Stellen. Wo und wie könnte ich zu mehr Stellen im Display kommen oder noch besser von Gramm auf Kilo mit 1-2 Dezimalstellen nach dem Komma in der Anzeige zu wechseln. Habe im Sketch „balance_with_tft_display.ino“ nichts gefunden das darauf hindeutet. Könntest Du mir erklären wie ich mein Projekt fertigstellen kann? Herzlichen Dank Markus

    1. Hallo Markus,

      vielleicht schreibe ich das nochmal um, damit der Code etwas unabhängiger Stellenanzahl und Display wird.

      Es müsste reichen, wenn du in Zeile 77 die Zahl der Blanks auf 4 setzt. Wenn der Platz nicht ausreicht, musst du die Textgröße kleiner machen (Zeile 18). Und dann evtl. noch den Cursor an eine andere Stelle setzen (Zeile 50). Probier einfach mal ein bisschen. VG , Wolfgang

      1. Hallo Wolfgang

        Vielen lieben Dank für die prompte Antwort! Mit den Blanks und Textgrösse passt es nun. Bis ca 30Kg funktioniert die Waage, danach kommt ein Negativwert und nach diesem unsinnige Werte. Der Sketch „Regelbetrieb“ zeigt im Seriellenmontior die richtigen Messwerte. Ich versuche es weiter.

        1. Das liegt am Wertebereich von integer, der hört nämlich bei 2^15 -1 = 32767 auf. Wenn du auf long wechselst (Zeile 73), dann sollte es gehen.

          long intValue = (long)(round(floatValue))

          Wenn man den Fehler schon mal hatte, dann fällt einem das auf, ansonsten kann man recht lange danach suchen.

          1. Wolfang Du bist ein Genie! Nun habe ich es geschafft. Die Waage zeigt nun alles korrekt an so wie ich es mir gewünscht habe und mich schon lange damit beschäftigt habe. Die Darstellung von Kilo werde ich später mal angehen, jetzt bin ich einfach nur glücklich.
            1000 Dank für Deine Hilfe Markus

  15. Super Anleitung, die mir sehr gut weitergeholfen hat.
    Ich würde gerne das gemessene Gewicht an ein Victron Tanksensor weitergeben, dieses Teil kann Sensorsignale mit 4-20mA oder 0-10V an ein Anzeigegerät mit TouchScreen weitergeben. An dem Victron Venus OS Gerät kann dann definiert werden, welcher Wert für 0% (Leer) und 100% (Voll) verwendet werden soll. Z.B. Leer ist 7mA oder 1,2V und Voll ist 17mA oder 3,2V.

    Wie kann ich das Sketch erweitern, dass das gemessene Gewicht als Stromwert oder Spannungswert ausgegeben wird?
    Das maximale Gesamtgewicht ist bekannt und ist 20Kg.

    Danke!

    1. Ist das nicht einfach nur ein (erweiteter) Dreisatz? Du willst einen Wert auf einer Gewichtsskala in einen Wert auf einer Spannungs- oder Stromskala umrechnen.
      Wenn einerseits das Gewicht in Gramm weightAsFloat ist, und das maximale Gesamtgewicht maxWeight ist 20000g und anderseits „Leer“ 7mA ist und 17mA ist „Voll“, dann ist der gesuchte Strom I = 7.0 + weightAsFloat * (17.0 -7.0) / maxWeight

      Oder mit der map() Funktion. Die „schluckt“ allerdings nur Ganzzahlen, deswegen muss man ein wenig tricksen:
      I * 1000 = map(weightAsInt, 0, 20000, 7000, 170000)

      Oder sehe ich das zu einfach?

      1. Vielen Dank für diesen Lösungsansatz! So könnte ich das recht einfach umsetzen.
        Leider bin ich Arduino Neuling.
        Ich wäre sehr dankbar für Hinweise, wie ich mit dem Arduino Strom- oder Spannungswerte ausgeben kann?
        Wäre das auch für 2 Waagen mit einem Arduino gleichzeitig möglich?
        Es handelt sich dabei um 2 Gasflaschenwaagen im Wohnmobil.

        Nochmals vielen Dank!

        1. Ich weiß nicht, ob ich die Frage richtig verstehe. Soll der Arduino einen Strom- oder eine Spannung ausgeben, der/die proportional zum Gewicht ist? Einstellen kann man nur eine Spannung (mit analogWrite()). Der Arduino hat aber keinen echten analogen Ausgang, analogWrite() gibt PWM Signale aus. D.h. die Spannung schwankt sehr schnell zwischen 0 und 5 Volt und über das Verhältnis der 0 Volt Zeit zur 5 Volt Zeit wird die mittlere Spannung gesteuert. Man könnte dann das Signal mit einem RC Glied glätten, wenn notwendig. Das ist aber alles nicht so wirklich gut, weil nicht besonders genau.

  16. Mache gerade ein Projekt für die Schule…
    Beim kalibrieren kommt immer der Wert 0.
    Woran könnte liegen?
    Habe eine 1kg wähezelle, gewichte 300g
    Würde mich über eine schnelle Rückmeldung freuen

    1. Hallo,
      also du hast den Sketch Calibration.ino (unverändert?) auf den Arduino (?) geladen und versuchst mit einem bekannten 300g Gewicht zu kalibrieren, richtig? Und der Sketch liefert bei „Calculated calibration value is: “ eine 0? Ich würde ja zunächst sagen, dass es ein Fehler in der Verkabelung ist, aber dann solltest du eine Fehlermeldung bekommen: „Tare timeout, check MCU>HX711 wiring and pin designations“. Oder hast du das Gewicht vielleicht einfach zu früh aufgelegt? Es muss ja der Messwert ohne und mit Gewicht verglichen werden.

    2. Hallo Hannes,
      habe das Selbe Problem, hast du den Fehler gefunden? Verkabelung habe ich geprüft, dennoch kommt im Kalibirierungssketch immer der Kalibrierungsfaktor 0 heraus (der Testsketch liefert auch dauerhaft eine 0). Bin etwas ratlos..

      1. Merkwürdig. Hast du den Calibration Sketch aus meinem Beitrag genommen oder direkt aus der Bibliothek? Vielleicht hat der Autor der Bibliothek inzwischen etwas geändert. Das kann ich nicht permanent anpassen. Probiere mal den Sketch direkt aus der Bibliothek. Ich kann es selbst gerade nicht testen.

  17. Hallo Wolfgang,

    ist ein sehr interessanter Beitrag.
    Ich würde gerne mehrere HX711 seriell abfragen und die Werte in die Datenbank schreiben.
    Leider habe ich nicht gefunden welches Protokoll HX711 verwendet.
    Im Prinzip sollen es 10 Wagen geben die permanent den Wert ermitteln.
    Ändert sich das Gewicht hat sich Lagerbestand geändert.
    Dann wird Lagerbestand in der Datenbank aktualisiert.

    1. Hallo Eduard, der Autor der Bibliothek hat einen Beispielsketch für den Betrieb mehrerer HX711 mitgeliefert. Du findest ihn in Arduino IDE unter den Beispielen oder du suchst im Bibliotheksordner oder gehst direkt auf github:

      https://github.com/olkal/HX711_ADC/blob/master/examples/Read_2x_load_cell/Read_2x_load_cell.ino

      Bei 10 Waagen wird es mit den Pins eng. Ich würde dann einen MEGA2560 einsetzen. Und anders als in dem Beispielsketch würde ich die Waagen als Array anlegen, dann kannst du viel Schreibarbeit sparen.

  18. Hallo Wolfgang,
    natürlich auch von mir erstmal großes Lob zu diesem Projekt. Ich spiele mit dem Gedanken die Wiegezelle mit einem Schrittmotor zu kombinieren, damit ich Gewicht/Strecke abbilden kann. Wieviel Messwerte liefert den Dein Projekt den dafür und ließe sich das so umsetzen?

    1. Hallo Raik, wenn du mit „wieviel Messwerte“ die Messfrequenz meinst, dann ist die einstellbar. Laut Datenblattblatt lassen sich 10 oder 80 Messungen pro Sekunde (SPS) einstellen. Der Autor der Bibliothek hat 10 SPS eingestellt, um das Rauschen gering zu halten. Zusätzlich wird eine gewisse Anzahl von Messungen gemittelt. Dadurch werden die Messzeiten höher. Einstellen lässt sich das über die Datei Config.h (darin wird das auch erklärt). Voreingestellt ist ein Wert von 16. Die „Settling Time“ beträgt dadurch etwas mehr als 1.6 Sekunden. Durch Reduktion des Wertes bekommt man eine höhere Datenrate, aber auch mehr Rauschen. Müsstest du mit Rumspielen. Wenn man mit einer bewegten Messzelle vernünftige Werte ermitteln möchte, muss man nach Möglichkeit Vibrationen verhindern, da diese den Messwert schwanken lassen. Oder man mittelt genügend Messwerte, was dann aber wieder auf die Messfrequenz geht. Es gibt also keine ganz einfache Antwort!

      1. Moin Wolfgang, ich habe eine ähnliche Frage bezüglich des Themas.
        Ich habe vor einen Cocktailmixer mittels dieser Wiegezelle zu realisieren (Orangensaft einfüllen bis 200 Gramm dann Vodka einfüllen bis 250 Gramm usw…).
        Jetzt stehe ich allerdings vor dem Problem, dass dieses Programm je recht träge ist und das ganze so recht ungenau ist.
        würdest du mir noch etwas genauer beschreiben, wie ich das Ganze etwas schneller bekomme.

        1. Hallo Florian,

          die Antwort ist dieselbe wie oben. Die Einstellungen (Messrate und Anzahl der zu mittelnden Messwerte), die die Geschwindigkeit beeinflussen, kannst du in der Datei Config.h vornehmen. Das ist dort auch ganz gut kommentiert. Schnellere Messungen bedeuten mehr Rauschen. Wieviel mehr Rauschen auftritt und was für deine Anwendung akzeptabel ist, das musst du schlicht ausprobieren. Ich selbst habe mit diesen Parametern bisher nicht herum experimentiert. VG, Wolfgang

  19. Hallo Wolle,
    erst einmal mein dickes Kompliment für deine tollen Beiträge hier!
    Ich habe schon eine Menge gelernt!
    Vielleicht kann ich im Gegenzug auch ein wenig hilfreich sein:
    Du tatest dich mit der rechtsbündigen Ausgabe etwas schwer.
    Ich habe da eine, wie ich meine recht einfache Idee.
    Angenommen, du möchtest n Zeichen rechtsbündig ausgeben,
    dann beginne mit einem String mit n Leerzeichen und hänge das an, was du ausgeben möchtest.
    Dann nutze die Funktion substring ab length() – n.
    Dann stehen Deine Zeichen ganz rechts und der String hat die gewünschte Länge.
    Geht natürlich auch mit führenden Nullen oder anderen Zeichen Deiner Wahl.
    Viele Grüße
    Wolfram

  20. Hi Wolle,
    danke für die schnelle Antwort.
    Die Sensoren arbeiten jetzt genau, ich hatte keine Halterungen installiert, sodass die Sensoren nicht vernünftig arbeiten konnten. Mein Fehler 🙁
    den Schalter werde ich mal überdenken, wie und wo ich den im Sketch unterbringe.
    Habe heute recherchiert und bin auf eine AZ Delivery Lösung gestossen:#include

    Preferences preferences;

    void setup() {
    Serial.begin(115200);
    Serial.println();

    preferences.begin(„az“, false); //Ordner az anlegen/verwenden

    //preferences.clear(); //Alle „Dateien“ unter dem Ordner az löschen

    //preferences.remove(„Start“); //“Datei“ Start löschen

    unsigned int counter = preferences.getUInt(„Start“, 0); //“Datei“ Start auslesen und in Variable counter schreiben
    //“, 0″ bedeutet, falls Start nicht existiert standardwert 0 übergeben

    counter++; //Variable counter um 1 erhöhen

    Serial.printf(„Anzahl Starts: %u\n“, counter); //Variable counter Seriell ausgeben

    preferences.putUInt(„Start“, counter); //Variable counter unter „Datei“ Start speichern

    preferences.end(); //Preferences beenden

    Serial.println(„Neustart in 10 Sekunden…“);
    delay(10000); //Wartezeit 10000ms = 10s

    ESP.restart();
    }

    void loop() {}

    das werde ich mal verfolgen und möglicherweise, wenn das funktioniert mit einem MQTT Client einen Wert für den WägeSketch „PUSHEN“, sodass die Variable fürs Gewicht stimmt, ??hm. Vielleicht klappt das. Was meinst du?

    vg

    Gerd

  21. Hallo Wolle,

    bin durch Zufall auf deine Seite gestoßen und finde die sehr gut gelungen, danke fürs teilen.

    Meine Suche führte mich über den HX711 mit Wägesensor auf deine Homepage, sehr interessant auch für weitere Projekte.
    Mein Projekt, das mir schon lange im Kopf geistert ist folgendes:

    In unserem Wohnmobil habe ich EINE Propanflasche, bei der ich nie weiß, wie voll die ist. Immer ausbauen und auf die Personenwaage stellen ?, nee …
    Also 4 Fach ( jeweils 25Kg) Wägesensor über HX711 und ESP32 Mini D1 auswerten über MQQT auf einen Broker übertragen und dann mittels WebServer (der 2. Nodemcu) und altem ausrangierten Iphone5 anzeigen. Auf dem Iphone habe ich den geführten Betrieb eingestellt, dann läuft er nur noch der Webbrowser und stellt auch andere Sensorwerte zur Verfügung (Temp, Luftdruck, Luftfeuchte) dazukommen sollen noch Stromverbrauch, RestKapazität der Bordbatterien und mein Lieblingsprojekt Wasserstand für Frischwasser.

    Habe gestern Abend den WägeSensor verlötet, angeschlossen und in Betrieb genommen, abgesehen von vielen unterschiedlichen Werten !!??, läuft der Mechanismus aber erst mal provisorisch.

    Hab jetzt allerdings folgende Probleme bzw. Fragen, hoffe du kannst da weiterhelfen?
    1. Die Genauigkeit ist nach bisherigem Augenschein äußerst schlecht, permanent unterschiedliche Werte. Arbeite noch mit dem Calibrierungstool von Olav Kallhovd.
    2. Falls das mal irgendwann laufen sollte, stellt sich die Frage
    a. Wenn das Fahrzeug stromlos ist und wieder Plusspannung an den ESP kommt, wie kann ich erreichen, das der letzte Wert gehalten wurde, ohne das ich neu Kalibrieren muss, bzw. die Gasflasche neu aufsetzen muss? um einen Messwert zu erhalten?
    3. Wie kann ich erreichen, das nach Flaschenwechsel das Tara geändert werden kann, ohne Arduino usw. die Propanflaschen haben teilweise unterschiedliche Eigengewichte, die abgezogen werden müssen?

    Viel Grüsse und danke schon mal vorab für deine Mühe.

    VG

    Gerd

    1. Hi Gerd, also was sie Genauigkeit angeht, bin ich von diesen Wägezellen eigentlich absolut begeistert. I habe allerdings immer nur mit einer Zelle gearbeitet.

      Wenn du verhindern möchtest, dass eine Taramessung stattfindet, dann musst du nur im Beispielsketch boolean _tare = true durch boolean _tare = false ersetzen. Dann ermittelst du einmal das Leergewicht (was absurd hoch sein wird) und ziehst diesen Wert bei zukünftigen Messungen ab. Du hast dann sozusagen eine eingefrorene Tara.

      Wenn die Propanflaschen alle unterschiedliche Gewichte haben, wird es ein kleines bisschen schwieriger. Vom Prinzip her müsstest du jedes mal die oben beschriebene Prozedur mit der vollen Flasche wiederholen. Du bekommst dann halt negative Werte. Nun möchtest du wahrscheinlich nicht jedes mal wieder im Sketch den Startwert ändern und alles neu uploaden. Du könntest dafür einen extra Taster installieren und das Programm so ändern, dass beim Drücken des Tasters der Startwert gemessen und ins EEPROM geschrieben wird. Hoffe das hilft – viel Erfolg & Spaß.

      VG, Wolfgang

  22. Danke für die coole Doku!
    Ich verwende vier Loadcells + einen HX711. Das ganze Setup funktioniert einwandfrei. Fällt dir eine Möglichkeit ein auf den Taraknopf als Interrupt zu verzichten?
    Eine Änderung des Gewichts ist auch immer eine Änderung der anliegenden Spannung. Ließe sich das – irgendwie – als Interruptsignal nutzen?
    Mir selbst fällt um ehrlich zu sein nix ein, außer ein externen Input wie der Knopf oder ein weiterer Sensor (ich habe an einen Beschleunigungssensor gedacht – wobei ich mir nicht sicher bin, ob die Gewichtsänderung ausreichend ist).

    1. Hallo Daniel, ein ungewöhnlicher Wunsch. Die Spannungsänderung zu nutzen ist schwierig, da sie sehr klein ist. Deswegen benutzt man auch den HX711 mit seinen gigantischen 24 Bit Auflösung. Du kannst ja einfach die Gewicht regelmäßig abfragen. Und bei einer gewissen Ab- oder Zunahme in einer gewissen Zeit soll er eine Tara durchführen. Da muss man sich aber die Bedingungen genau überlegen. Wenn du etwas auflegst und durch die Gewichtsänderung eine Tara auslöst, dann nimmt er ja die Tara mit dem Gewicht drauf, das du messen willst – auch blöd. Ein Näherungssensor mit Interruptfunktion wäre vielleicht etwas: https://wolles-elektronikkiste.de/apds-9960-das-multitalent.

  23. Hallo Wolfgang
    Vielen Dank für Deine ausführliche Antwort. es war tatsächlich so dass ich den cal Factor durch Probieren ermitteln musste dann flutschte es. Leider Leider klappt es mit „dem Piepsen nicht Habe
    if (weightAsFloat>1000.0)
    { digitalWrite(13, HIGH)
    else
    digitalWrite(13, LOW)}
    eingefügt.
    Dann kommt „weightAsFloat‘ was not declared in this scope“
    ????? Hast Du noch ne Idee ? Das wäre toll Vielen Dank

    1. Hallo Hannes, jede Wägezelle hat ihren individuellen Kalibrierfaktor. Um die Kalibrierprozedur kommst du also nicht herum. Allerdings kann man sich die händische Übertragung der Kalibrierwerte sparen, wenn man sie ins EEPROM schreiben lässt. Dazu muss man nur die entsprechenden Programmzeilen entkommentieren.

      Wenn der Compiler weightAsFloat nicht erkennt, dann hast du entweder die Variable für das Gewicht anders benannt als ich oder du hat die Zeile an einer Stelle zugefügt an der sie nicht gültig ist. Und bei deinem eingefügten Code fehlen zwei Klammern: } else {

      Wenn du nicht klar kommst dann schick mir deinen Sketch per mail.

  24. Hallo Wolfgang, danke erstmal für diese sehr ausführliche und wirklich tolle Erklärung! Ich habe alles wunderbar umsetzen können mit meinem ESP-32 Adafruit Huzzah. Alles funktioniert einwandfrei.
    Allerdings brauche ich für mein Projekt ein WLAN fähiges Board und ich verwende hier das ESP8266 Feather Huzzah. Ich habe die Änderungen angenommen, die du ebenfalls erwähnt hast. Allerdings zeigt es mir nur komische Codes und am Ende „Starting…“ im Seriellen Fenster an und das wiederholt sich nach ein paar Sekunden. Ich habe die Baudrate angepasst und den richtigen Kalibrierungswert angegeben. Hättest du eine Idee für die Lösung meines Problems? Ich wäre sehr dankbar! Viele Grüße Sarah

    1. Hallo Sarah, wie es aussieht, schlägt hier der Watchdog Timer zu. Am Ende meines Beitrages über Watchdog Timer schreibe ich auch etwas über den ESP8266:

      https://wolles-elektronikkiste.de/watchdog-timer

      Due Kurzversion lautet: der ESP8266 hat einen Watchdog Timer, der eigentlich dazu dient abgestürzte Sketche durch ein Reset wieder zum Laufen zu bringen. Nur leider reagiert dieser Timer auch manchmal, wenn man es nicht möchte. Vor allem ist das bei while Schleifen, in denen nur gewartet wird, dass eine bestimmte Bedingung eintritt, der Fall. Der sogenannte Software Watchdog „beißt“ nach drei Sekunden. Wenn du in das setup die Zeile ESP.wdtDisable(); einfügst, stellst du den Software Watchdog ab. Leider gibt es dann noch den Hardware Watchdog, der ca. alle acht Sekunden zuschlägt. Probiere es mal. Wenn sich das Reset Interval auf acht Sekunden erhöht, dann weißt du zumindest schon mal, dass es genau dieses Problem ist. In den kryptischen Meldungen taucht dann auch irgendwo „wdt reset“ auf.

      Und dann musst du im Code nach Stellen suchen, wo der ESP8266 nichts macht außer warten und Bedingungen prüfen, also wie gesagt vor allem while Schleifen. Dort kannst du – wie man so schön sagt – den Watchdog füttern, indem du ein ESP.wdtFeed(); einfügst. Ggf. muss du auch ein ESP.wdtFeed(); in die Hauptschleife (loop()) einfügen. Melde dich nochmal, wenn es dann immer noch nicht geht. Und wenn es, geht wäre eine Rückmeldung auch nett! VG, Wolfgang

      1. Vielen Dank für die schnelle Rückmeldung! Ich werde es gleich ausprobieren und mich dann melden, ob es geklappt hat! Danke Wolfgang!

      2. Hallo Wolfgang,

        ich habe die Commands eingefügt, wie du es vorgeschlagen hast. Leider kommt immer noch die Meldung:
        ets Jan 8 2013,rst cause:4, boot mode:(3,6)

        wdt reset
        load 0x4010f000, len 3584, room 16
        tail 0
        chksum 0xb0
        csum 0xb0
        v2843a5ac
        ~ld

        Starting…

        Das wiederholt sich dann.
        Ich habe es mit 115200 probiert.
        Vielleicht hast du ja noch eine Idee, wie ich das ändern könnte? Danke und Viele Grüße Sarah

        1. Kannst du mir mal deinen ganzen Sketch schicken (wolfgang.ewald@wolles-elektronikkiste.de)? Vielleicht fällt mir ja etwas auf. Und dann könntest du auch mal schauen, wo das Programm aussteigt. Ich mache so etwas für gewöhnlich ganz pragmatisch, indem ich einfach systematisch „Serial.println(„Hallo hier ist Zeile X“); einfüge. So lässt sich eingrenzen, wie weit das Programm kommt.

  25. Hallo Wolfgang!
    Danke für die exacte Darstellung dieses tollen Projektes….
    Bei mir hat alles geklappt .Nach dem Tarieren g genaue Angabe des Gewichtes. Nur nach dem ich auch das Display angeschlossen habe stimmt irgendwas nicht mehr. Nach Drücken des TARA schalters kommt wait . Das Display zeigt dann 0 an. Lege ich aber ein Gewicht auf die Waade wird immer nur ca 1/4 des tatsächlichen Gewichts angezeigt. In der Wiederholung dann aber immer das gleiche exakte Gewicht. Mein Display unterscheidet sich von dem Deinigen bei der Pin belegung dass SDA ganz aussen ist und zwischen VCC und SDA ein PIN namens SCK statt SCL (bei Dir) ist. Die Belegung bei A4 und A5 habe ich dementsprechend geändert. Hast Du ne Idee? Und wenn ich schon beim Schreiben bin. Sicher kann man doch eine Funktion einfügen dass bei einem Gewicht von z.B. 1000g und mehr ein Signal ertönt. Vielen Dank für eine Antwort. Gruß Hannes

    1. Hallo Hannes, das ist ja sehr merkwürdig. Das Display kann ja nicht die Werte verändern. Wenn du die Daten gleichzeitig auf dem seriellen Monitor ausgibst, sind sie dann dort richtig? Mein Sketch ist hinsichtlich der Ausgabe auf dem Display recht spezifisch. Wird vielleicht einfach nur etwas abgeschnitten? Oder ist es wirklich immer ein Viertel? Das könntest du prüfen, indem du die Textgröße mit setTextSize mal änderst. Dass die Pins anders belegt sind bei deinem Display, kann eigentlich auch keinen Einfluss haben. Ich würde dann eher erwarten, dass es gar nicht geht. Vielleicht wiederholst du auch noch mal die Kalibrierung?
      Die Funktion mit der Gewichtswarnung ist kein Problem (if(weightAsFloat>1000.0) {…..}). Nur wie das Piepen ertönen soll, hängt natürlich davon ab, was du für einen Tongeber dran hängen hast. VG, Wolfgang

  26. Hallo Wolfgang,

    die Erklärung ist echt super!
    Aufgrund der Größe meiner Stockwaage und weil ich mehr Pins brauche, bin auch auf einen ESP32 umgestiegen.
    Hier habe ich ein Problem und evtl. hast du mir eine Idee oder einen Tipp. Der ESP32 bietet einen Deep Sleep an. Dieser Startet das ganze System neu und somit auch die Waage immer bei Null. Auf der Wage stehen aber die Bienenkästen und wenn das System bei Null startet, messe ich kein Gewicht. Ich zerbreche mir seit Tagen den Kopf, wie ich die Wage beim Reset richtig starte, aber das System nicht Null ausgibt.
    Hast du evtl eine Idee oder mir einen Tip. Das Prblem hatte ich auch beim Wemos D1.

    Gruß

    Kay

    1. Hallo Kay, du möchtest also keine Tara beim Start. Die kannst du verhindern, indem du _tare auf false setzt.

      boolean _tare = false;
      LoadCell.start(stabilizingtime, _tare);

      Den Wert, den du damit bei deiner ersten Messung ermittelst (der dürfte sehr groß sein) musst du dann später von deinen Messwerten abziehen. Eine fixe Tara, sozusagen.

      Hoffe das hilft!

  27. Hallo,
    ich habe eine Frage.
    Ich möchte gerne 2 Wägezellen benutzen. Eine Anzeige habe ich, ihr kann ich sagen das bei einem bestimmten Ohmwert 0kg und bei einem höheren Ohmwert zb 10kg sind. Die Werte dazwischen werden dann selbst erzeugt. Brauche ich dafür überhaupt den HX711?

    Gruß Peter

    1. Hallo Peter, die Wägezelle ändert ihren Widerstand mit dem Gewicht. Das funktioniert über Dehnungsmessstreifen. Der Effekt, also die Widerstandsänderung ist allerdings äußerst gering. Der Widerstand wird über die abfallende Spannung gemessen. Die Spannungsänderung ist entsprechend auch sehr gering. Da kommt der HX711 ins Spiel, der eine gigantische Auflösung von 24 bit (= 16.777.216) hat. Da ist zum Beispiel der A/D-Wandler des Arduino mit seinen 10 bit ( = 1.023) sehr grob dagegen. Das reicht schlicht nicht aus. Wenn man einen Widerstandsmesser mit ausreichender Empfindlichkeit hat, kann man sich den Umweg über den HX711 im Prinzip sparen. VG, Wolfgang

  28. Hallo zusammen,
    Ich möchte mir eine Waage bauen für meine Bienen Völker um die Futter Vorrat zu ermitteln.
    Die Bienen stehen ca.5 bis 10 Entfernung von meinem Haus entfernt,
    Mene Frage ;
    Könnte mir jemand helfen eine Waage zu bauen und die daten per SMS übermittelt?
    Danke im voraus
    Micha

    1. Hallo Micha,

      ich kann dir keine Fertiglösung anbieten, aber zumindest vom Prinzip her ist das nicht schwer. Du brauchst außer den im Beitrag beschriebenen Teilen lediglich ein SMS-fähiges Modul wie z.B. das SIM800L und eine SIM Karte. Ich wollte immer mal einen Beitrag über solche Module machen, bin aber noch nicht dazu gekommen. Nachteil ist, dass man erst mal die SIM Karte braucht mit der ganzen Registrierung und Identifikation und dann laufende Kosten für die SMS hat. Ich würde deshalb andere Möglichkeiten in Betracht ziehen. Reicht dein W-Lan vielleicht bis zu den Bienen? Dann könntest du die Daten auf den Browser übermitteln, z.B. mit einem WEMOS Board. Das habe ich hier beschrieben. Oder du könntest die Daten über IFTTT (if this then that) als Benachrichtigung (also nicht SMS) auf das Handy schicken. Das habe ich hier beschrieben. Oder Übermittlung per 433 MHz Funk, dann hast du die Daten allerdings nicht auf dem Handy, sondern auf einem zweiten Arduino, aber könntest sie z.B. auf einem Display anzeigen.

  29. Hallo Wolfgang,
    das ist ein tolles Projekt und ich möchte mich bei Dir für die klasse Dokumentation bedanken.
    Ich möchte mehrere Waagen gleichzeitig über längere Zeiträume betreiben um Gewichtsveränderungen zu protokollieren und dann grafisch darzustellen. Hast Du eventuell einen Tip für mich wie ich den Wert regelmässig an eine LANAdresse:Port senden kann um ihn dann dort mit vorhandenenTools abzugreifen und in eine DB zu schreiben bzw. grafisch aufzubereiten?
    Danke für jede Hilfestellung.
    Liebe Grüsse,
    Rudi

    1. Hallo Rudi,

      vielen Dank für’s Feedback. In meinem Beitrag über ESP-01 Boards habe ich beschrieben, wie man Daten per W-LAN an einen Browser sendet. Allerdings würde ich als Board nicht den ESP-01 nehmen, da er nicht genügend Pins hat. Nimm ein ESP-12 Board wie z.B. das WEMOS Board. Alternativ kannst du auch einen Arduino mit W-LAN oder LAN Modul einsetzen.

      Damit hast du allerdings die Daten erst im Browser, aber noch nicht in einer Datei oder Datenbank. Mit HTML kommt man da nicht weit, sondern müsste php oder Java Script Lösungen einsetzen. Damit müsste ich mich selbst auch erstmal beschäftigen. Aber dazu gibt es bestimmt einiges im Netz.

      VG, Wolfgang

  30. Hallo, ich habe die Waage bereits zum Laufen gebracht, verzweifle aber gerade an einer „Kleinigkeit?“.
    Ich möchte, dass sich die Waage nach dem Einschalten nicht automatisch tariert. Hab schon mit der calibrationValue experimentiert, kam aber zu keiner Lösung. Können Sie mir da Weiterhelfen?

    MfG
    Simon Wagner

    1. Hallo Simon, das haben wohl auch andere vermisst. Und die gute Nachricht ist, dass der Autor der Bibliothek da etwas implementiert hat. Installiere – falls nicht schon geschehen – die aktuellste Version der Bibliothek und schau dort in den Read_1x_load_cell.ino Beispielsketch. Anscheinend ist die LoadCell.start() Funktion erweitert worden. Ändere einfach _tare von true in false und schon wird nicht mehr tariert:

      boolean _tare = true; //set this to false if you don’t want tare to be performed in the next step
      LoadCell.start(stabilizingtime, _tare);

      Ich muss das gelegentlich mal in meinem Beitrag ergänzen.

  31. Hallo,
    danke für den Artikel. Ich habe da eine Frage zum Anschluss von mehreren Wägezellen an einer Waage (Gewicht soll über 3-4 Wägezelle gemessen werden). Kann man das über ein HX711 machen oder pro Wägezelle ein HX711? Ich habe zwar Schaltungen gefunden, wo 4 Wägezelle an einen HX711 angeschlossen wurden, diese Wägezellen haben aber nur 3 Kabel. Ist auch möglich, diese Art von Wägezellen (mit 4 Adern) an einem HX711 anzuschließen?
    Schonmal Danke und Grüße,
    Stefan

    1. Hallo Stefan,

      interessante Frage. Eigentlich hat der HX711 nur zwei Kanäle und die Bibliothek benutzt nur den Kanal A. Kanal B soll eine zu geringe Verstärkung haben um gut messen zu können. In der Bibliothek findet man einen Beispielsketch, der zeigt, wie man zwei (oder mehr) HX711 Module ausliest. Das würde bedeuten, dass man nur eine Wägezelle pro HX711 Modul auslesen kann. Kann es seine, dass dort wo mehrere Zellen verwendet werden, diese zusammengeschlossen sind? So etwas kann man machen, wenn man z.B. eine 200 kg Waage bauen will und die auf 4 x 50 kg Zellen aufgebaut ist. Dann liest du einen Gesamtwert aus. Ein individuelles Auslesen ginge nicht nach meinem Verständnis. Vielleicht kannst du mir mal den Link zusenden für das Beispiel, dass du gefunden hast.

      VG, Wolfgang

      1. Hallo Wolfgang,
        genau sowas ähnliches wie dein Beispiel (4x50kg > 200kg Waage) hatte ich vor.
        Ein Beispiel habe ich hier:
        https://youtu.be/LIuf2egMioA?t=40 (Schaltbild bei Sekunde 40)
        und bei der ct 2/2018 (leider hinter einer Paywall):
        https://www.heise.de/select/ct/2018/2/1515450954216728
        Bei beiden werden vier (dreiadrige) Wägezelle an ein HX711 angeschlossen und ausgelesen. Ein Beispiel mit vieradrigen habe ich leider nicht gefunden. Das Beispielsketch mit mit zwei HX711 Module habe ich auch gesehen. Ich hatte nur gehofft, dass es eine elegantere Lösung als vier HX711 gibt, weil dann das Kalibrieren etwas aufwändiger ist.

        Grüße, Stefan

  32. Hallo Wolfgang
    Dank Deinem Blog habe ich es geschafft 2 Waagen zu bauen, als Basis nutzte ich jedoch einen Wemos D1 mini. Eine Waage mit einer 20Kg Zelle und die Zweite mit 4 x 20Kg Zellen, das läuft mit dem CalibSketch und dem Sketch aus dem Abschnitt Regelbetrieb, tiptop.
    Ich schaffe es jedoch nicht dem Sketch mit TFT und Tara Button zum laufen zu bringen. Der D1Mini blinkt ununterbrochen nach dem Upload, das Display bleibt dunkel und im seriellen Monitor sehe ich nur wirre Zeichen.
    Hast Du mir ein Tipp woran das liegen könnte, respektive wie ich Deinen „TFT Tara Button Sketch“ auf einem D1 Mini zum laufen bringe? Als TFT habe ich übrigens SSD1306 und SH1105 zur Verfügung.
    Mit den Besten Grüssen
    Fredi

    1. Hallo Fredi,

      Fehlersuche aus der Ferne ist noch schwieriger als so schon. Ich würde jetzt so vorgehen:
      1) Prüfen, ob der Pull-Down Widerstand am Taster richtig verbunden ist
      2) wegen der wirren Zeichen: ist die Baudrate richtig eingestellt
      3) Generell alle Kabel überprüfen und evtl. mal austauschen (ich hatte mal ein kaputtes Steckbrückenkabel und habe mir einen Wolf gesucht)
      4) Das TFT Display mal entfernen – geht es jetzt mit dem seriellen Monitor?
      5) Das TFT Display separat versuchen „zum Laufen“ zu bringen.
      6) Ist die Displaygröße bei der Initialisierung richtig gewählt? display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

      Mehr fällt mir erstmal nicht ein. Wenn du das Problem identifizieren kannst, wäre es schön, wenn du das teilen könntest. Viel Erfolg!

      VG, Wolfgang

      1. Hallo Wolfgang
        Besten Dank für Deinen Input, werde mich der Sache annehmen und hier berichten. Vielen Dank für Deine Unterstützung.
        Fredi

  33. Hallo Wolfgang!
    Herzlichen Dank für die Zusammenstellung und das Bereitstellen der Informationen und Sketches zum HX711, dies hier hat erheblich zu meinem Verständnis der elektronischen Waage geholfen!

    Ich habe das ganze mit einem Arduino Nano ausprobiert, wenn ich Deinen Sketch mit Display und Tarafunktion verwende, sind Messungen zwar möglich, aber werden dauernd durch „Wait“ und einer (ungewollten) Tarierung der Waage unterbrochen, irgendeine Fehlerschleife muss vorliegen. Zuerst hatte ich einen defekten Taster in Verdacht, aber dieser ist in Ordnung,auch so erkenne ich jetzt keinen offensichtlichen Fehler in meiner Schaltung. Habe ich da vielleicht etwas übersehen?

    Herzliche Grüße,
    Marcel

    1. Wenn die Waage immer wieder tariert, wird anscheinend immer wieder ungewollt ein Interrupt ausgelöst. Da hätte ich auch als erstes den Taster im Verdacht gehabt. Da er es nicht ist, würde ich als nächstes den Pull-Down Widerstand überprüfen. Ist der richtig an GND angeschlossen? Wenn es das auch nicht ist, wird es schwieriger. Irgendwo her muss das High Signal ja kommen, das den Interrupt auslöst.

      Oder du drehst die Logik dann mal um – Interrupt wird bei „LOW“ ausgelöst:
      pinMode(interruptPin, INPUT) –> pinMode(interruptPin, INPUT_PULLUP) und
      attachInterrupt(digitalPinToInterrupt(interruptPin), taraEvent, RISING); –> attachInterrupt(digitalPinToInterrupt(interruptPin), taraEvent, FALLING);
      und natürlich den Pull-Down Widerstand entfernen und den Taster an GND anstelle VCC.

      1. Danke für den Tipp!
        Da lag dann auch der Fehler, der Pull-down-Widerstand lief ins Leere… Jetzt geht alles wie gedacht! Vielen Dank!

  34. Hallo und danke für den tollen Beitrag.

    Auf der Suche nach einer Möglichkeit Meßdaten, hier Gewicht zu erfassen, kam ich auf deine Seite.

    Eine Frage hierzu:
    Ich möchte Milligramm bis max. 200 Gramm zu erfassen, ist dieses hiermit möglich?

    Lieben Gruß

    1. Hallo, ich selbst habe nicht im Milligramm Bereich getestet, aber ich habe bei den Kundenfragen bei Amazon einen Hinweis für die 1kg Version gefunden:

      Welche empfindlichkeit hat dieser 1kg sensor? ab welchem gewicht misst er und wie genau? max. 1kg, richtig?
      Antwort:Ich habe damit el. Bauteile gewogen welche unter 1g Gewicht hatten. Referenzgewichte von 0.5g bis 50g zeigten bei 10 Versuchen immer denn richtigen, gleichen Wert.
      Von W. R. am 10. September 2019
      Der Sensor hat eine Empfindlichkeit von 1mV/V. Habe damit ein Wägesystem mit einer Auflösung von 10 mg aufgebaut. Die Linearität ist sehr gut.
      Von 10mg bis 1 kg keine Abweichung.
      Von Wolfgang… am 11. September 2019

      Zumindest 10 mg Auflösung scheinen zu funktionieren. Aber nochmal, ich habe es selbst nicht ausprobiert (das war ein anderer Wolfgang!).

      1. Hallo ersteinmal und vielen Dank für die super Anleitung 🙂 hat mir sehr geholfen. Für so genaue Messungen sollte man eh mehrere Wägezellen nutzen oder?
        Bei einer Wägezelle würden die Werte schon varieren, weil je nach Position des Gewichts auf der Platte sich der Hebel und sich damit die Biegung der Wägezelle ändert, ist das richtig?
        Das würde sich bei z.B. vier Wägezellen dann ausgleichen.
        VG Mirko

        1. Ich habe nicht ausprobiert was passiert, wenn man das Wägegut mal am Rand und mal in der Mitte. positioniert. Ich habe mir bei Wiederholungsmessungen aber auch keine besondere Mühe gegeben, das Wägegut exakt in der Mitte zu positionieren. Trotzdem habe ich immer wieder auf das Gramm genau denselben Wert gemessen (bei Gewichten von mehreren hundert bis eintausend Gramm).

  35. Danke für den tollen Beitrag!
    Das wollte ich schon lange mal ausprobieren. Die Teile liegen schon ewig bei mir rum.
    Bin über den stabilen Wert (ohne Schirmung) erstaunt.
    Viele Grüße aus dem Süden

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.