Go Down

Topic: Increment und Decrement Variable! (Read 1 time) previous topic - next topic

7ower3efender

Hallo liebe Community!
Ich habe ein kleines Problem und finde es nicht heraus wie ich diesen Code umschreiben müsste um die Variable "Gewicht" genau bei 0,2g zu stoppen doch er hüpft immer beim Dekrementieren auf 0,19g und sobald ich wieder Inkrementieren auf 0,21g und nicht auf 0,2g  :smiley-confuse:

Ich hoffe irgendwer kann mir dabei weiterhelfen.

Code: [Select]
const int  buttonPin = 2;
const int  buttonPin1 = 3;
const double Milli = 1000.0;
double Gewicht = 0.0002; 
int buttonState5 = 0;
int buttonState6 = 0;
int lastButtonState = 0;

void setup() { 
   pinMode(buttonPin, INPUT);
   pinMode(buttonPin1, INPUT);
   Serial.begin(115200);
}


void loop() {
   buttonState5 = digitalRead(buttonPin);
   if (buttonState5 != lastButtonState) {
     if (buttonState5 == HIGH){
      Gewicht = Gewicht + 0.00001;
      Serial.println(String("Gewicht: ")+Gewicht*Milli+String("g"));
     }
     delay(100);
   }
   lastButtonState = buttonState5;
   
   buttonState6 = digitalRead(buttonPin1);
   if (buttonState6 != lastButtonState) {
     if (buttonState6 == HIGH){
      Gewicht = Gewicht - 0.00001;
      Serial.println(String("Gewicht: ")+Gewicht*Milli+String("g"));
     }
     delay(100);
     if (Gewicht < 0.00019){
      Gewicht = 0.0002;   
     }
   }
   lastButtonState = buttonState6;
}

Serenifly

#1
May 21, 2019, 04:55 pm Last Edit: May 21, 2019, 04:56 pm by Serenifly
Gleitkommazahlen haben systembedingt Rundungsfehler:
https://www.h-schmidt.net/FloatConverter/IEEE754de.html

0.0002 ist z.B. nicht genau darstellbar sondern wird zu 0.00019999...

Doc_Arduino

#2
May 21, 2019, 05:11 pm Last Edit: May 21, 2019, 05:12 pm by Doc_Arduino
Hallo,

das mit float dachte ich auch erst, dass klappt hier jedoch. Das Problem liegt in der Reihenfolge der Abfrage, der Wertzuweisung auf 0.2 und der Anzeige. Die Anzeige kommt vor der Wertänderung. Intern ist alles korrekt nur man sieht es nicht. Beim nächsten + kommt 0.01 zu 0.2 dazu. Der Sketch arbeit so wie er aufgebaut ist 100% korrekt. Nimm das *Milli raus, dann siehste das besser.

Ich würde dennoch wie schon von Serenifly angesprochen alles soweit es geht in Ganzzahlen rechnen und erst für die Anzeige in Kommastellen darstellen/umrechnen. Bei Ganzzahlen gibts keine Rundungsfehler. Es ist ja kein Problem intern mit Zahlen von 2000 für Gramm zu hantieren für eine Anzeige von 2kg.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

uwefed

Es gibt nicht nur Rundungsfehler sondern auch , wenn 2 verschieden große Gleitkommazahlen zusammengezählt werden einen Punkt wo das Dazuaddieren die größere Zahl nicht mehr verändert.
Ok, das ist auch ein Rundungsfehler aber daran denkt man nicht.
Grüße Uwe

Doc_Arduino

#4
May 21, 2019, 05:52 pm Last Edit: May 21, 2019, 05:58 pm by Doc_Arduino
Hallo,

habe mir mal erlaubt das umzubauen mit Tendenz zum aufräumen. Kann als Basis zum weiteren Ausbau dienen.

Code: [Select]
unsigned long Gewicht = 20;

struct Taster
{
  byte pin;
  bool zustand = false;
};

Taster taster2;
Taster taster3;

void setup() {

  taster2.pin = 2;
  taster3.pin = 3;
  
  pinMode(taster2.pin, INPUT);
  pinMode(taster3.pin, INPUT);
  Serial.begin(115200);
}


void loop() {

  update_Taster();
  
  if (taster2.zustand) {
    Gewicht++;
    taster2.zustand = false;
  }

  if (taster3.zustand) {
    Gewicht--;
    if (Gewicht < 20) {
      Gewicht = 20;
    }
    taster3.zustand = false;
  }

  anzeige(Gewicht);
}



void update_Taster ()
{
  static unsigned long last_ms = 0;
  unsigned long ms = millis();

  if (ms - last_ms >= 40) {
    last_ms = ms;

    taster2.zustand = digitalRead(taster2.pin);
    taster3.zustand = digitalRead(taster3.pin);
  }
}


void anzeige (unsigned long gewicht)
{
  static unsigned long altesGewicht = 0;

  if (gewicht != altesGewicht)
  {
    Serial.print(F("Gewicht: "));
    Serial.print(gewicht);
    Serial.print("g");
    Serial.print("\t\t");
    Serial.print((gewicht/1000.0),3);
    Serial.println("kg");
    altesGewicht = gewicht;
  }
}

Edit: Anzeige verfeinert
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

7ower3efender

Okay Danke für die Hilfe werde es gleich mal ausprobieren und halt wie ihr gesagt habt den Code etwas Umschreiben

Vielen Dank für die Hilfe derweil!

7ower3efender

Hallo,

habe mir mal erlaubt das umzubauen mit Tendenz zum aufräumen. Kann als Basis zum weiteren Ausbau dienen.

Code: [Select]
unsigned long Gewicht = 20;

struct Taster
{
  byte pin;
  bool zustand = false;
};

Taster taster2;
Taster taster3;

void setup() {

  taster2.pin = 2;
  taster3.pin = 3;
 
  pinMode(taster2.pin, INPUT);
  pinMode(taster3.pin, INPUT);
  Serial.begin(115200);
}


void loop() {

  update_Taster();
 
  if (taster2.zustand) {
    Gewicht++;
    taster2.zustand = false;
  }

  if (taster3.zustand) {
    Gewicht--;
    if (Gewicht < 20) {
      Gewicht = 20;
    }
    taster3.zustand = false;
  }

  anzeige(Gewicht);
}



void update_Taster ()
{
  static unsigned long last_ms = 0;
  unsigned long ms = millis();

  if (ms - last_ms >= 40) {
    last_ms = ms;

    taster2.zustand = digitalRead(taster2.pin);
    taster3.zustand = digitalRead(taster3.pin);
  }
}


void anzeige (unsigned long gewicht)
{
  static unsigned long altesGewicht = 0;

  if (gewicht != altesGewicht)
  {
    Serial.print(F("Gewicht: "));
    Serial.print(gewicht);
    Serial.print("g");
    Serial.print("\t\t");
    Serial.print((gewicht/1000.0),3);
    Serial.println("kg");
    altesGewicht = gewicht;
  }
}

Edit: Anzeige verfeinert
Funktioniert Eins A nur mir etwas zu schnell um von 1Gramm auf 2 Gramm umschalten zu können es sollte Machbar sein es mit einem Taster zu um eins zu erhöhen und verringern.
Muss ich dazu einfach ein Delay im Code setzen oder??

7ower3efender

Habe gerade herausgefunden das ich einfach die Zahl die du vergleichst in "update_Taster" einfach erhöhen muss um die Reaktionszeit zu verringern.
Habe ich dabei Recht oder ist meine Vermutung dabei Falsch??

Doc_Arduino

#8
May 21, 2019, 06:33 pm Last Edit: May 21, 2019, 06:39 pm by Doc_Arduino
Hallo,

genau das hatte ich mir auch soeben gedacht das es stören könnte.
Delay? Um Himmelswillen, bloss nicht.  Dann wäre der Aufwand mit millis für die Katz.
Das bekommste hier nebenbei frei Haus geliefert.

Zum Verständnis warum, weshalb und wie:
Theseus erklärt millis()
http://forum.arduino.cc/index.php?topic=400102.msg2752141#msg2752141

GuntherB - BlinkwithoutDelay - Die Nachtwächtererklärung
http://forum.arduino.cc/index.php?topic=423688.0

Hier der geänderte Code. Ich verwende Pullup und muss dann immer nochmal vorm posten umarbeiten. Müssen deine Taster auf High reagieren? Ich hoffe ich habe nichts vergessen. Es reagiert nur auf erneuten Tastendruck. Rasselt also nicht mehr durch.

Code: [Select]

unsigned long Gewicht = 20;

struct Taster
{
  byte pin;
  bool read = false;
  bool oldRead = false;
  bool state = false;
};

Taster taster2;
Taster taster3;

void setup() {

  taster2.pin = 2;
  taster3.pin = 3;

  pinMode(taster2.pin, INPUT);
  pinMode(taster3.pin, INPUT);
  Serial.begin(115200);
}


void loop() {

  update_Taster();

  if (taster2.state) {
    Gewicht++;
    taster2.state = false;
  }

  if (taster3.state) {
    Gewicht--;
    if (Gewicht < 20) {
      Gewicht = 20;
    }
    taster3.state = false;
  }

  anzeige(Gewicht);
}



void update_Taster ()
{
  static unsigned long last_ms = 0;
  unsigned long ms = millis();

  taster2.state = false;
  taster3.state = false;

  if (ms - last_ms >= 40) {
    last_ms = ms;

    taster2.read = digitalRead(taster2.pin);
    taster3.read = digitalRead(taster3.pin);

    if (taster2.read && (!taster2.oldRead) ) {
      taster2.state = true;
    }
    
    if (taster3.read && (!taster3.oldRead) ) {
      taster3.state = true;
    }

    taster2.oldRead = taster2.read;
    taster3.oldRead = taster3.read;
  }
}


void anzeige (unsigned long gewicht)
{
  static unsigned long altesGewicht = 0;

  if (gewicht != altesGewicht)
  {
    Serial.print(F("Gewicht: "));
    Serial.print(gewicht);
    Serial.print("g");
    Serial.print("\t\t");
    Serial.print((gewicht/1000.0), 3);
    Serial.println("kg");
    altesGewicht = gewicht;
  }
}


Wenn es läuft, mach das Beste daraus. Verstehe den Ablauf.   ;)

Edit:
wegen "der Erhöhung", probiere es aus, spiele rum, damit lernt man auch, teste auch größere Werte und merke was sich in der Bedienung verändert. Danach kannste den neuen Code testen.

Edit 2:
mal wieder was "vergessen", die Zeilen 31 und 39 können raus, dass rücksetzen auf false macht die update_Taster Funktion schon
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

7ower3efender

#9
May 21, 2019, 06:45 pm Last Edit: May 21, 2019, 06:46 pm by 7ower3efender
Also ich muss sagen das Verständnis hätte ich ja wenn ich mir so den Code anschaue und nebenbei es praktisch Überprüfe aber so alleine ist es für mich etwas schwierig vor allem so einen Code wie diesen zu schreiben :D

So nun habe ich noch eine kurze Frage.
Ich habe noch einen Code und ich möchte nun den Code den @Doc_Arduino mit diesen hier verbinden um das Gewicht (Varibale) per Tasten druck zu erhöhen oder verringern. Um anschließend bei der Auslösung der beiden Sensoren (Zeitmessung) die richtige Berechnung zu erhalten.

Code: [Select]
#define Button1  2
#define Button2  3
long int elapsedtime, starttime;
const double Milli = 1000.0;
const double Micro = 1000000.0;
const double Gewicht = 0.0002;            // Gewicht in Kilogramm
const double Multiplikator = 0.5;
const double Abstand = 50.0;              // Abstand in Meter
const double fps = 3.2808399;            // Umrechnungsfaktor (so genau wie möglich)
double Time;
double Speed;
double Energie;
double FPS;
 
void setup() {
 pinMode(Button1, INPUT);
 pinMode(Button2, INPUT);
 Serial.begin(115200);
}
 
void loop() {
  while (digitalRead(Button1) == false){
  }

    starttime = micros();

  while (digitalRead(Button2) == false){  
  }

    elapsedtime = (micros() - starttime);
    Time = elapsedtime / Micro;
    Speed = Abstand / Time;
    FPS = Speed * fps;
    Energie = Multiplikator * Gewicht * (Speed * Speed);

  Serial.println("");
  Serial.println(String("Gewicht: ")+Gewicht*Milli+String("g"));
  Serial.println("");
  Serial.println(String("Geschwindigkeit: ")+Speed+String("m/s"));
  Serial.println("");
  Serial.println(String("Geschwindigkeit: ")+FPS+String("fps"));
  Serial.println("");
  Serial.println(String("Energie: ")+Energie+String("J"));
  Serial.println("");
}


Edit: Falls hier in diesem Code schon irgendwas euch auffallen sollte bitte verbessert mich :d

7ower3efender

Edit: Es ist eigentlich egal ob es Pullup oder Pulldown wäre ich habe es nur deswegen da ich es in diesem Code so Programmiert habe sonst wäre es egal.

Doc_Arduino

Hallo,

ich hoffe das war nun alles nicht umsonst.

Schau dir den Code an, schau wie die update_Taster Funktion arbeitet.
Warum überhaupt Funktionen? Code ist lesbarer und einfacher wartbar.

Wenn das verstanden ist, ist die Ergänzung der Zeitmessung mit 2 weiteren Taster ein Kinderspiel.
Viel machen musst du eigentlich nicht, nur abgucken und sanft erweitern.

Pullup:
gut, dann die Pullup Variante. Macht vieles leichter, weil das bei den meisten Programmierern die Standardeinstellung ist. Spart den externen Widerstand, Taster zwischen Pin und Masse.
Code: [Select]

// https://forum.arduino.cc/index.php?topic=617098.0

unsigned long Gewicht = 20;

struct Taster
{
  byte pin;
  bool read = true;
  bool oldRead = true;
  bool state = false;
};

Taster taster2;
Taster taster3;

void setup() {

  taster2.pin = 2;
  taster3.pin = 3;

  pinMode(taster2.pin, INPUT_PULLUP);
  pinMode(taster3.pin, INPUT_PULLUP);
  Serial.begin(115200);
}


void loop() {

  update_Taster();

  if (taster2.state) {
    Gewicht++;
  }

  if (taster3.state) {
    Gewicht--;
    if (Gewicht < 20) {
      Gewicht = 20;
    }
  }

  anzeige(Gewicht);
}


void update_Taster ()
{
  static unsigned long last_ms = 0;
  unsigned long ms = millis();

  taster2.state = false;
  taster3.state = false;

  if (ms - last_ms >= 40) {
    last_ms = ms;

    taster2.read = digitalRead(taster2.pin);
    taster3.read = digitalRead(taster3.pin);

    if (!taster2.read && (taster2.oldRead) ) {
      taster2.state = true;
    }
   
    if (!taster3.read && (taster3.oldRead) ) {
      taster3.state = true;
    }

    taster2.oldRead = taster2.read;
    taster3.oldRead = taster3.read;
  }
}


void anzeige (unsigned long gewicht)
{
  static unsigned long altesGewicht = 0;

  if (gewicht != altesGewicht)
  {
    Serial.print(F("Gewicht: "));
    Serial.print(gewicht);
    Serial.print("g");
    Serial.print("\t\t");
    Serial.print((gewicht/1000.0), 3);
    Serial.println("kg");
    altesGewicht = gewicht;
  }
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

7ower3efender

Okay ich werde mich mal damit bis morgen auseinandersetzen. Falls ich noch fragen habe oder ich es nicht Akzeptabel zusammen bringe hoffe ich das ich auf die Hilfe der Community zählen kann?? :D

7ower3efender

Was bedeutet "long int"??
Ist damit gemeint das die erste Variable den Datentyp "Long" besitzt und die zweite dann den Datentype "Int" oder bedeutet das was anderes??

Serenifly

"long int" ist nur eine umständliche Schreibweise für "long". Du kannst auch "signed long int" schreiben um es noch deutlicher zu machen

Go Up