Hallo,
ich hatte schon mal einen Thread in dieser Sache angefangen, finde ihn
aber nicht mehr (man sollte eine bessere Suchfunktion haben).
Also:
Ich war aufgefordert worden, das fraglich Programm so weit bis auf das
Wesentlich zu kürzen, daß es leichter zu durchschauen ist, was ich getan
habe.
Mein Problem: nach einer if-Abfrage hängt es von der Fragestellung ab,
ob die Daten korrekt oder falsch in ein I2C-EEPROM geschrieben werden.
Die fragliche Stelle befindet sich etwa in der Mitte des Programms (ich
kann leider keine Zeilennummern einfügen).
Und anschließend habe ich ein Stück einer Ausgabe beigefügt, wo man die
fehlerhafte Ausgabe sieht (Spalte 1 ist die Adresse, in Spalte 2 sollte
das highByte stehen (falls gewünscht, kann ich das Ausleseprogramm noch
posten)).
Meine Frage: weshalb beeinflußt die mehr oder weniger brauchbare
if-Schleife die EEPROM-Schreiberei bzw. wie kann man das vermeiden?
VG
Alexander
Das abgemagerte Programm
1
// _2DS18_ganz_leer_Relais_180116 16.1.18
2
#include<Wire.h>
3
#include<LiquidCrystal_I2C.h>
4
LiquidCrystal_I2Clcd(0x20,16,2);// Achtung: auf den neuen I2C-LCD gibt es Adressjumper.
5
constintI2CADRESSE=0x51;// A0 = high,
6
inteepromadresse=0;
7
intadresse=0;
8
inta=10;// zum Testen der lcd-Ausgabe
9
intrelaispin=9;
10
unsignedlongtime;
11
12
voidsetup()/****** SETUP: RUNS ONCE ******/
13
{
14
Serial.begin(9600);// für Ausgabe über Terminal
15
pinMode(relaispin,INPUT);
16
delay(4000);
17
lcd.init();
18
lcd.backlight();
19
lcd.clear();
20
lcd.print(" _2_DS18_ins_EEPROM");
21
lcd.clear();
22
23
24
// start serial port to show results
25
Serial.begin(9600);
26
Serial.println("_2DS18_leer_Relais_180116");
27
Serial.print("Initializing Temperature Control Library Version ");
28
// Serial.println(DALLASTEMPLIBVERSION);
29
delay(2000);
30
31
}//--(end setup )---
32
33
voidloop()/****** LOOP: RUNS CONSTANTLY ******/
34
{
35
36
// Abfrage des Brennerrelais, genauer gesagt, des Relais, das dem eigentlichen Brennerrelais
37
// nachgeschaltet ist.
38
inti;
39
intSummelow=0;
40
intersterRelaiszustand[6];
41
for(i=0;i<7;i++)
42
{
43
ersterRelaiszustand[i]=digitalRead(relaispin);
44
Summelow=Summelow+ersterRelaiszustand[i];
45
delay(100);
46
}
47
48
intSummehigh=0;
49
intzweiterRelaiszustand[6];
50
for(i=0;i<7;i++){
51
zweiterRelaiszustand[i]=digitalRead(relaispin);
52
Summehigh=Summehigh+zweiterRelaiszustand[i];
53
delay(100);
54
}
55
56
if(!Summehigh>Summelow)// hier beginnt das Unerklärliche:
57
{// wenn die Schleife heißt if(Summehigh > Summelow), dann wird
58
zeit_ins_EEPROM();// bei zeit_ins_EEPROM() das highByte(Time) nicht geschrieben s.Anh.
59
// Mit der Schleife if(!(Summehigh > Summelow)) wird highByte(Time) auch nicht geschrieben
60
// aber mit der Schleife if(!Summehigh > Summelow) wird es korrekt geschrieben.
61
62
// wie beeinflußt die if-Schleife die EEPROM-Schreiberei ?
63
64
65
intTempC=1234;// irgendwelche Zahl
66
schreibEEPROM(eepromadresse,highByte(TempC));
67
eepromadresse++;
68
schreibEEPROM(eepromadresse,lowByte(TempC));
69
eepromadresse++;
70
71
TempC=2345;// irgendwelche Zahl
72
schreibEEPROM(eepromadresse,highByte(TempC));
73
eepromadresse++;
74
schreibEEPROM(eepromadresse,lowByte(TempC));
75
eepromadresse++;
76
77
// zeit_ins_EEPROM();
78
79
}// Ende Relaispinabfrage
80
}//--(end main loop )---
81
82
83
voidschreibEEPROM(intadresse,bytedaten)
84
{
85
Wire.beginTransmission(I2CADRESSE);
86
Wire.write((byte)(adresse>>8));
87
Wire.write((byte)(adresse&0xFF));
88
Wire.write(daten);
89
Wire.endTransmission();
90
delay(5);
91
}
92
93
voidzeit_ins_EEPROM()
94
{
95
// Zeit ins EEPROM schreiben
96
unsignedintTime=millis()/1000;// Zeit seit Programmstart in sec
Frank schrieb:> if( ! (Summehigh > Summelow))
Das hatte er schon probiert:
Alexander S. schrieb:> Mit der Schleife if(!(Summehigh > Summelow)) wird highByte(Time) auch> nicht geschrieben
Simon S. schrieb:> Google mal operator prezedenz.> if(!Summehigh > Summelow) Heißt so viel wie:> if((!Summehigh) > Summelow)> Und (!Summehigh) is genau dann 1 wenn summehigh == 0 ist, in allen> anderen Fällen ist es 0.
Er hatte auch das hier schon probiert:
Alexander S. schrieb:
> Mit der Schleife if(!(Summehigh > Summelow)) wird highByte(Time) auch> nicht geschrieben
Edi R. schrieb:> Ich bin mit Arduino-Code nicht so vertraut, aber in C wäre das ein> grober Schnitzer:>>
1
>intersterRelaiszustand[6];
2
>for(i=0;i<7;i++)
3
>{
4
>ersterRelaiszustand[i]=...
5
>
Sehe ich genauso. Damit überschreibst du dir Werte im Stack und es ist
nicht mehr vorhersehbar, was dein Programm macht.
Mach aus der 6 mal eine 7 und teste nochmal. Kleiner Tipp noch: ändere
deine schreibeEEPROM so ab, dass sie zuerst das byte ausliest und nur
schreibt, wenn sich was geändert hat. (EEProms sind nur 100000 mal
beschreibbar)
Gruß Roland
Kräuterli schrieb:> Er hatte auch das hier schon probiert:> Alexander S. schrieb:>> Mit der Schleife if(!(Summehigh > Summelow)) wird highByte(Time) auch>> nicht geschrieben
Richtig. Er hat 3 unterschiedliche Bedingungen ausprobiert. Vielleicht
sollte er sich mal überlegen unter welcher davon er etwas schreiben
will.
Übrigens, Kleinigkeit, aber: ein if ist keine schleife.
Alexander S. schrieb:> for (i=0; i<7; i++)> {> ersterRelaiszustand[i] = digitalRead(relaispin);> Summelow = Summelow + ersterRelaiszustand[i];> delay(100);> }>> int Summehigh= 0;> int zweiterRelaiszustand[6];> for (i=0; i<7; i++){> zweiterRelaiszustand[i] = digitalRead(relaispin);> Summehigh = Summehigh + zweiterRelaiszustand[i];> delay(100);> }>> if(!Summehigh > Summelow) // hier beginnt das Unerklärliche:
Also... erstmal unbeachtet der fehlerhaften Array Definition (Größe
sollte 7 sein)
Wenn sich die Variable "relaispin" in keiner der For Schleifen ändert,
dann ist Summelow immer gleich Summehigh und beide können dann auch nur
die Werte 0 oder 7 bekommen...
Demnach wäre die IF Abfrage eigentlich komplett unsinning, da sich nie
etwas unterscheidet.
Dass doch (wohl eher zufällig) in die IF Abfrage reingesprungen wird,
hängt dann vermutllich damit zusammen, dass wie bereits oben
beschrieben, durch die FOR Schleife ausserhalb des Arrays geschrieben
wird. Wenn der Compiler die Variablen so im Speicher anlegt, wie die im
Code auftreten, dann liegt wohl summehigh direkt hinter dem Array
ersterRelaiszustand und wird somit vermutlich im letzten Durchlauf der
ersten FOR Schleife überschrieben.
Lustigerweise würde die Korrektur der Array Definition dann dazu führen,
dass die IF Bedingung nicht mehr wahr würde ;-)
Alexander S. schrieb:> Die fragliche Stelle befindet sich etwa in der Mitte des Programms (ich> kann leider keine Zeilennummern einfügen).
Genau deshalb postet man ja solchen langen Code als Anhang.
Kräuterli schrieb:> Hörst du die Bart-Wickelmaschine laufen? ;-)
Ja ist echt unerträglich laut :(
Sollte sie vielleicht mal wieder schmieren ...
Trotzdem sollte man es richtig benennen :D
>> die schliessende Klammer der If-Abfrage sein ? oder schon vorher ?>> Wenn ja, rück die Anweisung nochmal bitte einen Tab ein, dann sieht mans> besser.> LG
Du meinst, einrücken ist nicht bloss kosmetisch nützlich sondern sollte
fast obligatorisch sein?
Meine Güte: am Schluss wird noch in Python programmiert...
Programmiersprachentheaterintendant schrieb:> Du meinst, einrücken ist nicht bloss kosmetisch nützlich sondern sollte> fast obligatorisch sein?
Eigentlich schon. Ich rücke selber ein und lass dann die IDE das nochmal
machen. Wenn sich dann etwas stark verändert schau ich mir den Code
nochmal genau an.
MfG Klaus
Stimmt!
Kräuterli schrieb:> Simon S. schrieb:>> Google mal operator prezedenz.>> if(!Summehigh > Summelow) Heißt so viel wie:>> if((!Summehigh) > Summelow)>> Und (!Summehigh) is genau dann 1 wenn summehigh == 0 ist, in allen>> anderen Fällen ist es 0.>> Er hatte auch das hier schon probiert:> Alexander S. schrieb:>> Mit der Schleife if(!(Summehigh > Summelow)) wird highByte(Time) auch>> nicht geschrieben
Es geht mir durchaus nicht um die Logik der if-Schleife. Es gibt eine
einzige brauchbare Version, die anderen habe ich nur probiert, als ich
gesehen hatte, daß die EEPROM-Schreiberei von der if-Schleife abhängt
(mit while geht es besser).
Diese Abhängigkeit verstehe ich nicht! Ich kann das später im richtigen
Programm sicher umschiffen, aber neugierdehalber würde ich gern wissen,
woran es liegt.
Gruß
Alexander
Alexander S. schrieb:> Es geht mir durchaus nicht um die Logik der if-Schleife.
Bitte:
Es gibt keine "if-schleife".
Gewöhn' Dir das einfach sofort und jetzt gleich ab.
Damit ich die Absicht des Codes auch durchschaue: bei jedem Durchlauf
von loop() wird der Zustand von D9 (da ist ein Relais dran) alle 100ms
6* Mal erstmalig erfasst, anschl. zweitmalig wieder D9 alle 100ms 6*
erfasst. Danach soll entschieden werden ob ins EEPROM zu schreiben ist.
Korrekt?
In beiden Schleifen werden die Rückgabewerte von digitalRead() -also
HIGH / LOW- gespeichert und aufsummiert als int gespeichert.
@TO: was bedeutet Dir eine 6er* Summe von HIGH / LOW?
(* 6 oder 7 Mal hängt davon ab ob die Grösse der 2 Arrays oder die
Anzahl For-Durchläufe korrigiert wird)
Der Vergleich (int Summehigh > int Summelow) lässt sich Boolesch
negieren und bewerten.
Aber was soll (! (int Summehigh)) für eine Bedeutung haben?
Ja, in C kann man viel so Mann weiss was man tut.
@TO: was weisst DU, was DU da tust? WILLST DU das so?
Programmiersprachent h eaterintendant schrieb:> Damit ich die Absicht des Codes auch durchschaue: bei jedem Durchlauf> von loop() wird der Zustand von D9 (da ist ein Relais dran) alle 100ms> 6* Mal erstmalig erfasst, anschl. zweitmalig wieder D9 alle 100ms 6*> erfasst. Danach soll entschieden werden ob ins EEPROM zu schreiben ist.> Korrekt?
Korrekt! Allerdings geht es mir derzeit nicht um die Logik hinter der
if-Abfrage, die Variationen dienen nur dazu, daß ich herausfinden
wollte, weshalb highByte(Time) manchmal und manchmal nicht ins EEPROM
geschrieben wird. Was hat das if mit der nachfolgenden Anweisung
zeit_ins_EEPROM() zu tun?
> In beiden Schleifen werden die Rückgabewerte von digitalRead() -also> HIGH / LOW- gespeichert und aufsummiert als int gespeichert.> @TO: was bedeutet Dir eine 6er* Summe von HIGH / LOW?>> (* 6 oder 7 Mal hängt davon ab ob die Grösse der 2 Arrays oder die> Anzahl For-Durchläufe korrigiert wird)
Ich weiß, in den for-Anweisungen sind die Arrays falsch, sollte hier
aber nicht überbewertet werden. da sich wahrscheinlich die Hardware
ändern wird und die Passagen dann verschwinden werden.
>> Der Vergleich (int Summehigh > int Summelow) lässt sich Boolesch> negieren und bewerten.> Aber was soll (! (int Summehigh)) für eine Bedeutung haben?>
Gar keine!
Wie oben erwähnt, ging es mir n u r um den Einfluß der if-Abfrage auf
die EEPROM-Schreiberei
Alexander S. schrieb:> Es geht mir durchaus nicht um die Logik der if-Schleife. Es gibt eine> einzige brauchbare Version, die anderen habe ich nur probiert, als ich> gesehen hatte, daß die EEPROM-Schreiberei von der if-Schleife abhängt> (mit while geht es besser).> Diese Abhängigkeit verstehe ich nicht! Ich kann das später im richtigen> Programm sicher umschiffen, aber neugierdehalber würde ich gern wissen,> woran es liegt.> Gruß> Alexander
das war mir schon klar. die frage ist: warum schreibst du ein programm,
das nicht tut was du willst? schreib doch einfach mal eine if-bedingung
die das überprüft was du wissen willst. Dann korrigierst du die array
grenzen und wenn es immernoch komische sachen macht kannst du noch mal
wieder kommen.
Und dann könntest du uns noch erklären wie deine ausgabe zustande kommt.
im moment sehe ich da nämlich einfach nur irgendwelche zahlen.
Alexander S. schrieb:> Ich weiß, in den for-Anweisungen sind die Arrays falsch, sollte hier> aber nicht überbewertet werden. da sich wahrscheinlich die Hardware> ändern wird und die Passagen dann verschwinden werden.>>>>> Der Vergleich (int Summehigh > int Summelow) lässt sich Boolesch>> negieren und bewerten.>> Aber was soll (! (int Summehigh)) für eine Bedeutung haben?>>>> Gar keine!> Wie oben erwähnt, ging es mir n u r um den Einfluß der if-Abfrage auf> die EEPROM-Schreiberei
Das eine hängt in einer Kausalkette mit dem anderen Zusammen...
Alexander S. schrieb:> Wie oben erwähnt, ging es mir n u r um den Einfluß der if-Abfrage auf> die EEPROM-Schreiberei
vermutlich: die compileroptimierungen verschieben die befehle so, dass
dein kaputtes array geschreibe manchmal was kaputt macht und manchmal
nicht, je nachdem wo der copiler die zugriffe hin optimiert.
Stefan U. schrieb:> Ist es eigentlich eine gute Idee, immer wieder die selben Zellen im> EEPROM zu überschreiben?
Natürlich nicht, aber für die Probephase sind 10000x mehr als
ausreichend, danach werden die 32k einmal pro Woche beschrieben.
Simon S. schrieb:> vermutlich: die compileroptimierungen verschieben die befehle so, dass> dein kaputtes array geschreibe manchmal was kaputt macht und manchmal> nicht, je nachdem wo der copiler die zugriffe hin optimiert.
Ok, ich werde die array-Größen in Ordnung bringen und mich dann wieder
melden (bis dahin muß ich erst mal den ewig benutzten USB-Anschluß, der
plötzlich nicht mehr funktioniert, gangbar machen).
VG
Alexander
> Ich weiß, in den for-Anweisungen sind die Arrays falsch, sollte hier> aber nicht überbewertet werden.
Du korrumpierst damit den Stack. Das sollte man sehr hoch bewerten, denn
ohne intakten Stack verhalten sich Computer praktisch nur noch zufällig.
Sie tun nicht mehr das, was du ihnen befohlen hast.
Array/Buffer Überläufe sind seit ich denken kann die häufigste
Fehlerursache für schwerwiegende Computerprobleme! Auch für Viren sind
sie in den allermeisten Fällen der Angriffspunkt.
Deswegen haben sich die Designer einiger Programmiersprachen darum
bemüht, sie von vorne herein auszuschließen. Das selbe Programm in Java
wäre zum Beispiel prompt abgebrochen worden.