Arduino multiplizieren

Hallo Freunde, Arduino Mega+LCD-Keypadshield+12*1Wire-Sensoren. Das ist der Auszug aus dem Sketch zur Pelletverbrauchsberechnung. Folgendes Problem: Der counter0 zählt die Umdehung der Stokerschnecke und counter1 berechnet den Pelletverbrauch, das klappt auch alles prima, aber bei ca. 32 kg Anzeige erscheint vor der Summe ein Minuszeichen und die Verbrauchsanzeige zählt rückwärts gegen 0 und dann wieder hoch bis 32kg. Vielleicht kann mir einer der Experten helfen, bin nicht mehr ganz jung (73) und erst seit 6 Mon. begeisterer Arduinofan, somit etwas unerfahren. Meine Suche zum Problem war bisher erfolglos.
Würde mich über Hilfe freuen.

void irq_Svc0() // Entprellung, Zähler, Verbrauchsberechnung
{
if (inputpin2==HIGH)
if(debounce(inputpin2))
digitalWrite(inputpin2,HIGH);
long unsigned act_IRQ0; // Umdrehungen der Stokerschnecke zählen,
act_IRQ0=millis();
{
counter0++; // Zähler für Stokerschnecke,
counter1=counter0*1/10; // Zähler durch 10 teilen zur LCD Anzeige,
if(counter1>20000)counter1=0; // Zähler: gültiger Zustandswechsel, bei 4140 kg reset,
last_IRQ0 = act_IRQ0;
long unsigned act_counter1;
var=counter1 *207/1000; // Pelletverbrauch berechnen, 1 Umdr.= 20,725 gr. Pellets,
if (Serial.read()== ‚;‘) // Pelletverbrauch an LCD ausgeben,
Serial.println( var);
Serial.print( var);
}
{
val=digitalRead(inputpin2); // LED - Umdrehungsanzeige Stokerschnecke,
if(val==LOW)
digitalWrite(led13,HIGH); // LED Pin 13
delay(2000),
digitalWrite(led13,LOW);
}
}

Hallo elektronik,

die Definition von den Zählern ist aus dem Beispiel nicht ersichtlich, aber ich vermute einen Überlauf einer deiner Zähler. Wenn du nur positive Werte benötigst, solltest du die Zähler als unsigned definieren, damit hast du schonmal ein Bit mehr (also einen doppelt so großen Bereich). Wenn der Zähler-Wert jedoch noch deutlich größer werden soll musst du vermutlich einen größeren Typ verwenden. Ich glaube ein Integer ist auf dem Atmega ein 16Bit-Typ, nicht wie auf modernen PCs ein 32Bit-Typ. Überlauf der Typen bsw.:

int (16Bit) -> 32767 + 1 = -32768
char (8Bit) -> 127 + 1 = -128

unsigned int -> 65535 + 1 = 0
unsigned char -> 255 + 1 = 0

Ich hoffe das bringt dich weiter…

Viele Grüße
Sascha

Hallo elektronik,

wie auch sascha vermute ich einen Buffer-Overflow. Da die Antwort von sascha deine Frage hoffentlich vollkommend ausreichend erklärt (kompetent ist sie alleweil), sehe ich keinerlei Notwendigkeit, noch etwas nachzuschieben, außer einen Link auf den Wikipedia-Artikel bezüglich des Jahr 2038-Problems. Dort ist auf der rechten Seite eine schöne Animation dargestellt, die den Buffer-Overflow einer int-Variable darstellt:

http://de.wikipedia.org/wiki/Jahr-2038-Problem

In diesem Sinne wünsche ich frohes Werkeln,
BlueBlobb

Aber bei ca. 32 kg Anzeige erscheint vor der
Summe ein Minuszeichen und die Verbrauchsanzeige zählt
rückwärts gegen 0 und dann wieder hoch bis 32kg.

Die Arduino Plattform kenne ich leider auch nicht. Der beschriebene Effekt tritt meist auf wenn es einen Überlauf bei den Variablen gibt. Datentypen haben eine bestimmte maximale Zahlengröße die sie speichern können.

Welchen Datentyp haben den counter0 und counter1?

Hallo,

Respekt erst mal, dass Du noch im höheren Alter dich an Programmierung machst. Ich kann Dir aber leider nicht weiterhelfen. Weiterhin viel Erfolg und Spaß
wünscht

Hermann

Hallo ich kenne mich zwar mit dem arduino nicht aus aber dein Problem hört sich nach einem Fehler bei der Deklaration der Variablen an.

Wenn die Variable als int deklariert ist, dann sind alle Werte über 32768, negativ. Bei der Zahl wurde das 8te Bit gesetzt und das ist bei einer ineger Zahl das Vorzeichenflag.

Wenn die Zahl nicht negativ sein soll, dann muss man die Variable als uint deklarieren, also als unsignet int! Dann geht die Zahl bis 65535 ohne negative Zahlen.

Hallo,

auch ich schließe mich den anderen an:
Es sieht nach einem Überlauf aus.

Wenn counter1 einen größeren Wertebereich erhält, sollte es länger funktionieren. Allerdings auch nicht ewig.
counter0 hat gerade mal ca. 1546 Drehungen gezählt, wenn counter1 überläuft.
Also counter1 statt als int als unsigned int definieren und schon kommt das Programm länger klar. Den geplanten Reset 4140 kg erreicht es so aber auch nicht.

Da hilft nur unsigned long für counter0 und counter1.
unsigned long hat einen Wertebereich von 0 bis 4,294,967,295. Das sollte reichen.

Viel Erfolg!

frozen

Hallo an Alle!
Vielen Dank für die schnellen, ausführlichen und kompetenten Antworten. Ich werde mich sofort ans Umschreiben des Sketches machen. Man kommt manchmal nicht auf so einleuchtende Fehler. Aber es gibt ja Freunde im Netz, die einem so schnell helfen.
Ich sage mir dann immer:
„Ermuntre dich, mein schwacher Geist“
Joh.Seb. Bach(1685-1750)

Mit Gruß Elektroniker

Hey elektronik,

dein Problem hört sich stark nach nem Deklarationsfehler an. Deine Variable (counter1) die bei ca. 32kg aufhört ist wahrscheinlich als Integer deklariert (int counter1:wink:. Diese laufen unter Arduino von -32768 bis 32767, heisst wenn deine Variable den Wert 32768 hat und du +=1 rechnes, dann wird sie auf -32768 gesetzt. Am einfachsten wäre es also deine Deklaration zu ändern (zb auf: unsigned long counter1:wink:. Ein unsigned long (unsigned=ohne Vorzeichen ±) nutzt die vollen 32bit aus, bedeutet er kann Werte zwischen 0 und (2^32)-1=4294967295 speichern. In deinem Fall also bis mindestens 4294967kg zählen. Solltest du wieder Erwarten höhere Werte benötigen helf ich gerne weiter.

Viel Erfolg und mach bloß weiter ich finds super in deinem Alter noch sowas zu lernen!!

Hallo!

Arduinno ist mir leider nicht geläufig und auch die Besonderheiten, die ich im Sketch-Auszug entdeckte, halfen meinem Verständnis nicht wirklich auf die Sprünge.

Was ich aber sagen kann: Das berichtete Verhalten spricht für einen signed data type, einen Datentyp, dessen oberstes Bit als Vorzeichen dient. Da sgegenstück ist Vorzeichenfrei bzw. unsigned.
So hat ein Byte unsigned die Reichweite 0 bis 255, während das signed Byte -127 bis +127 aufnimmt.

Vielleicht hilft das ja weiter.
gegrüßt!

Hallo,

Das ist ein Überlauf. Bei irgend einer Rechnung
war der Datentyp zu klein.
Bitte peinlichst genau aufpassen mit den Datentypen.
In c schreibt man etwa
counter1=0.1f * counter0;
Dafür sollte dann counter1 auch wenigstens ein
float sein. counter0 wird in diesem Fall
automatisch gecastet.
Das ganze geht zwar auch ohne floats aber dann
muss man nochmehr aufpassen: Es gibt bei
zu kleinen Datentypen schnell Überläufe in
den Zwischenergebnissen.
Eine genauere Programmanalyse spare ich mir aus Zeitgründen und Verweise auf ein beliebiges
Grundlagenwerk in der Sprache c.