Variable wird nicht aktualisiert

Moin, die variable " c" in der While- Schleife wird nicht aktualisiert. Ich kann leider den Fehler nicht finden. Kann mir evtl. jemand weiterhelfen?
Achso, ich bin Einsteiger und habe nicht soviel Erfahrung.
Danke.

/*
   -------------------------------------------------------------------------------------
   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>
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;


//pins:
const int HX711_dout = 4;  //mcu > HX711 dout pin
const int HX711_sck = 5;   //mcu > HX711 sck pin
const int Relais = 10;
const int Taster = 7;
int Buttonstate = 0;

 

//zeiten
//const int feedinginterval = 30 * 60 * 1000;



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

const int calVal_eepromAdress = 0;
unsigned long t = 0;

void setup() {
  pinMode(Relais, OUTPUT);
  pinMode(Taster, INPUT_PULLUP);
  digitalWrite(Relais, HIGH);
  Serial.begin(57600);
  delay(10);
  Serial.println();
  Serial.println("Starting...");
  Wire.begin();
  if(!rtc.begin()) {
    Serial.println("Kein RTC-Modul gefunden");
   
  // wihle(1); // Stopt das Programm wenn kein RTC-Modul gefunden
  }
     // rtc.adjust(DateTime(2024,5,20,20,40,0));
  //Serial.printIn(RTC-Modul Datum gesetzt);



  LoadCell.begin();
  //LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
  float calibrationValue;      // calibration value (see example file "Calibration.ino")
  calibrationValue = 1095.31;  // 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

  unsigned 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);
  // the following allows for getting a new load value
  //LoadCell.tare();
  //Serial.println("Place");
  //delay(10000);
  //LoadCell.refreshDataSet();
  //float new_value = LoadCell.getNewCalibration(374);
  //Serial.print("new loadv is: ");
  //Serial.println(new_value);
  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() {
 digitalWrite(Relais, HIGH);
  float c = LoadCell.getData();
  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();
    }
  }
 // char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
  DateTime now = rtc.now();
   //Serial.print(now.year(), DEC);
    //Serial.print('/');
    //Serial.print(now.month(), DEC);
   // Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    //Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
   // Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
  
  if     ((now.second() == 5 || now.minute() == 0) && now.second() == 5) { //(millis() % 1000 == 0) {   
      
     // c = LoadCell.getData();
      float f = (c - 50.0);
      
      digitalWrite(Relais, LOW);
      Serial.print("cl: ");
      Serial.println(c);
      //delay(1000);
      Serial.print("fl: ");
      Serial.println(c);
      //delay(5000);
      while (c >= f){
       // c = LoadCell.getData();  
      
      digitalWrite(Relais, HIGH);
      //delay(1000);
      Serial.print("wl: ");
      Serial.println(c);
      }
  


  }
    

    Serial.print("c: ");
    Serial.println(c);
   

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

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

weil die Zuweisung auskommentiert ist?

h̶i̶e̶r̶ ̶i̶s̶t̶ ̶d̶i̶r̶ ̶a̶u̶c̶h̶ ̶n̶o̶c̶h̶ ̶e̶i̶n̶ ̶"̶=̶"̶ ̶g̶e̶f̶l̶ü̶c̶h̶t̶e̶t̶.̶.̶.̶ Dummfug :see_no_evil:

..und natürlich ein herzlich Willkommen hier im Forum :wave: :smiley:

Hallo,
wie sollte sie auch , c sollte innerhalb der Schleife schon eine Zuweisung erhalten,aber die Zeile hast Du ja auskommentiert.

Wozu soll die schleife überhaupt gut sein ? da wird mehrfach das relais eingeschaltete und etwas auf dem Monitor ausgegeben. while schleifen sind sehr oft völlig unnötig und blokieren den Ablauf.

Stimmt.
In der While-Schleife wird nix geschrieben, nur gelesen.

Zur Erklärung: Die While-Schleife wird solange durchlaufen, wie die Bedingung wahr ist. Der Arduino tut in dieser zeit nichts anderes.
Das Programm springt am Ende der While-Schleife wieder an deren Anfang. Alles, was "außen" herum steht, wird nicht durchlaufen. Die While-Schleife blockiert die Ausführung des restlichen Codes. Du müsstest also entweder innerhalb der While-Schleife c aktualisieren oder das Ganze irgendwie nicht blockierend schreiben.

An welchem Punkt erwartest du denn die Aktualisierung der Variable?

Außerhalb der Schleife?

In dieser auskommentierten Zeile?
// c = LoadCell.getData();

auch wenn // c = LoadCell.getData(); innerhalb der Schleife nicht auskommentiert ist geht es nicht.
Prinzipiell soll die while- Schleife c mit f vergleichen. Das Relais steuert ein Motor über den Futter ausgegeben wird. während der Zeit wird das Gewicht c geringer.
Dafür muss c sich aber bei jedem durchlauf aktualisieren. Was aber nicht passiert. c bleibt immer gleich, aber nur wenn die Schleife druchlaufen wird. Ausserhalb der Schleife wird c auch aktualisiert. Die Anweisung für den serialMonitor habe ich nur drin damit ich sehen kann wie c sich verhält.

Du solltest noch auf irgendeine Weise sicherstellen, dass die Schleife wenigstens einmal betreten wird - sonst wird das nie was mit dem
c = LoadCell.getData().

Ich würde dann ein do { ... } while (<Bedingung>); vorschlagen, sofern dieser Haltepunkt erforderlich ist.

Vielleicht innerhalb der Schleife noch ein LoadCell.update() (mit Verzögerung)?

Hallo,
ich denke die Schleife muss weg. Das ist eine Aufgabe für eine Ablaufsteuerung, Schrittkette, Statemashine, wie immer Du es nenne willst.
Es ist ein zeitlicher oder Ereigins gesteuerter Ablauf. Man könnte noch mit if .. arbeiten.

Pseudocode

c= load.Cell.getData();
if ( c > f )  Motor ein 
else if (c< f - hysterese ) Motor aus

Danke an alle die Lösung war LoadCell.update()
Hab das noch in die Schleife eingebunden.
Jetzt läuft es wie gewünscht.
Vielen Dank nochmal

Man sollte Variablen die für die Prüfung in der While-Schleife benötigt werden IMMER vor der Schleife deklarieren. Notfalls mit Werten die eine unbedingte Auslösung der Schleife erfolgen lassen.

Dann ist man auch sicher das keine Fehler auftreten.

Gruß

Pucki

Man sollte immer überlegen, ob man überhaupt eine while-Schleife in loop braucht.
Oder ob das Ganze nicht einfacher wird, wenn man stattdessen ofters loop durchläuft.
Einfache Programme sind immer besser als unnötig komplizierte.

4 Likes

Ich habe mal Ärger HIER bekommen weil ich dafür plädiere sowas wenn nötig in eigene Subroutinen auszulagern.

Ich bin der Ansicht das man die Loop-Schleife so klein und sauber wie nötig halten sollte.

Gruß

Pucki

Eine while-Schleife in eine Funktion zu packen und dadurch zu verstecken, ist überhaupt keine Lösung.

void loop () {
   machDies();
   machDas();
}

Kann man gern so machen, aber ob das blockadefrei programmiert ist, sieht man loop() nicht an.

Und wieder einmal verdrehst du alles, weil du es nicht verstanden hast.

In C++ gibt es keine "Subroutinen", das sind Funktionen.
Und die Kritik bezog sich auf eine "While-Schleife", die blockierend ist und bei einer korrekten Programmierung unter C++ unnötig ist, da man alles in der "loop()" abhandeln kann.
Und das gern auch in den üblichen Funktionen, ohne die While-Schleife.

ich dachte immer, das wären "void"s :slight_smile:

1 Like

:stuck_out_tongue:

Eine Funktion ist etwas, das aus einem oder mehreren Eingabewerten ein Ergebnis errechnet und dieses zurückliefert.
Eine Funktion kann während dieser Berechnung auch Nebeneffekte verursachen, was von Puristen aber nicht so gern gesehen wird.

Eine void-Funktion liefert nichts zurück und hat nur Nebeneffekte.
(schade eigentlich, könnte doch auch was zurückliefern :slight_smile: )

Eine Sub-Routine ist wie der Name schon sagt eine UNTER-Routine .
Diese kann eine Funktion sein, oder auch nur "ausgelagerter" Programmcode.

In diese Fall halt letzteres. Der Vorteil ist nicht das ich die While-Schleife spare. Sondern das ich die x-te. Einrückung spare und dadurch der Code übersichtlicher wird.

Gerade wenn ich da noch if-Abfragen und alles mögliche drin habe muss ich anfangen einrückungen zu zählen. Mich persönlich kotzt es schon an wenn eine Einrückung länger als 2 Bildschirmseiten ist. Oft kommentiere ich dann hinter die "schließende Klammen }" // Ende Abfrage was_auch_immer.

Aber das ist halt mein Stil. Vorteil ist das ich durch meine Codes auch noch nach > 25 Jahren durchblicke. Was ich neulich bei einer Oldtimer-Verwaltung sehr gut gemerkt hatte. Das Problem, war den Uralten VB6.0 Code neu zu kompilieren. :wink:

Gruß

Pucki

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.