Hallo,
ich habe angefangen eine Alarmanlage zu programmieren habe jetzt aber ein Problem mit meinem millis() weil ich meine Variable nur einmal = millis() setzen kann und danach nur komische werte raus kommen also dann ist millis()=20000 und meine Variable auf einmal =-17000 oder noch komischere Zahlen. Kann mir da einer helfen warum das so ist ?
Verwenden Sie ein unsigned long
(auch bekannt als uint32_t
)
(Wir könnten Ihnen mehr sagen, wenn Sie Ihren Code teilen und welche Plattform Sie verwenden)
int fc = 0;
//LED
int LED = 13;
int ledState = LOW;
int ledState2 = LOW;
//ausgang für das leuchten der LED
//Alarm
int alarm = 11; //ausgang für den Pipser also den Alarm
int bewegungsmelder = 12; //auslesen der bewegung also rückmeldung des Bewegungsmelder
int bewegungsmelderspannung = 10; //nur die Spannungsversorgung für den Bewegungsmelder
int h = 0;
int b = 0;
int alarmaktiviert = 0; //
int myTimer2 = 0;
int myTimeout2 = 10000;
//Anzeige
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//Zahlenpad
#include <Keypad.h>
char P1 = '1'; char P2 = '2'; char P3 = '3'; char P4 = '4';
char C1, C2, C3, C4;
char SP1 = '4'; char SP2 = '3'; char SP3 = '2'; char SP4 = '1';
char SC1, SC2, SC3, SC4;
const byte COLS = 4;
const byte ROWS = 4;
int z1 = 0, z2, z3, z4;
int sz1 = 0, sz2, sz3, sz4;
char hexaKeys[ROWS][COLS] = {
{'1', '4', '7', '*'},
{'2', '5', '8', '0'},
{'3', '6', '9', '#'},
{'A', 'B', 'C', 'D'}
};
byte colPins[COLS] = { 9, 8, 7, 6 };
byte rowPins[ROWS] = { 5, 4, 3, 2 };
char Taste;
char STaste;
Keypad Tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(alarm, OUTPUT);
pinMode(bewegungsmelder, INPUT);
pinMode(LED, OUTPUT);
}
void loop()
{
Anfang:
if (fc <= 2)
{
Taste = Tastenfeld.getKey();
if (Taste)
{
if (Taste == '*')
{
for (int s = 5; s > 0; s--)
{
Serial.print("Alarm aktiviert in: ");
Serial.print( s );
Serial.println( " Sekunden.");
lcd.setCursor(0, 0);
lcd.print("Alarm aktiviert ");
lcd.setCursor(0, 1);
lcd.print("in: ");
lcd.print( s );
lcd.println( " Sekunden.");
delay(1000);
}
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
Serial.println("ALARM AN");
lcd.setCursor(0, 0);
lcd.print("ALARM AN");
digitalWrite(bewegungsmelderspannung, HIGH);
alarmaktiviert = 1;
z1 = 0; z2 = 1; z3 = 1; z4 = 1;
goto Anfang;
}
if (Taste == '#')
{
if (C1 == P1 && C2 == P2 && C3 == P3 && C4 == P4)
{
lcd.setCursor(0, 0);
lcd.print(" ");
Serial.println ("ALARM AUS");
lcd.setCursor(0, 0);
lcd.print ("ALARM AUS");
lcd.setCursor(0, 1);
lcd.print(" ");
digitalWrite(bewegungsmelderspannung, LOW);
delay(3000);
digitalWrite(alarm, LOW);
digitalWrite(LED, LOW);
alarmaktiviert = 0;
h = 0;
b = 0;
// myTimer2 = 0;
fc = 0;
}
else
{
Serial.println ("FALSCHER CODE");
lcd.setCursor(0, 1);
lcd.print ("FALSCHER CODE");
delay(1000);
lcd.setCursor(0, 1);
lcd.print(" ");
z1 = 0; z2 = 1; z3 = 1; z4 = 1;
fc++;
if (fc > 2)
{
lcd.setCursor(0, 0);
lcd.print("SPW erforderlich");
Serial.println("SPW erforderlich");
}
goto Anfang;
}
}
if (z1 == 0)
{
C1 = Taste;
Serial.println(C1);
lcd.setCursor(0, 1);
lcd.print(C1);
z1 = 1; z2 = 0; z3 = 1; z4 = 1;
goto Anfang;
}
if (z2 == 0)
{
C2 = Taste;
Serial.println(C2);
lcd.setCursor(0, 1);
lcd.print("*");
lcd.setCursor(1, 1);
lcd.print(C2);
z1 = 1; z2 = 1; z3 = 0; z4 = 1;
goto Anfang;
}
if (z3 == 0)
{
C3 = Taste;
Serial.println(C3);
lcd.setCursor(1, 1);
lcd.print("*");
lcd.setCursor(2, 1);
lcd.print(C3);
z1 = 1; z2 = 1; z3 = 1; z4 = 0;
goto Anfang;
}
if ( z4 == 0)
{
C4 = Taste;
Serial.println(C4);
lcd.setCursor(2, 1);
lcd.print("*");
lcd.setCursor(3, 1);
lcd.print(C4);
z1 = 1; z2 = 1; z3 = 1; z4 = 1;
}
}
}
spw:
if (fc > 2)
{
STaste = Tastenfeld.getKey();
if (STaste)
{
if (STaste == '#')
{
if (SC1 == SP1 && SC2 == SP2 && SC3 == SP3 && SC4 == SP4)
{
lcd.setCursor(0, 0);
lcd.print(" ");
Serial.println ("ALARM AUS");
lcd.setCursor(0, 0);
lcd.print ("ALARM AUS");
lcd.setCursor(0, 1);
lcd.print(" ");
digitalWrite(bewegungsmelderspannung, LOW);
delay(3000);
digitalWrite(alarm, LOW);
digitalWrite(LED, LOW);
alarmaktiviert = 0;
fc = 0;
h = 0;
b = 0;
myTimer2 = 0;
SC1 = 0, SC2, SC3 = 0, SC4 = 0;
sz1 = 0, sz2 = 0, sz3 = 0, sz4 = 0;
}
else
{
Serial.println ("FALSCHER CODE");
lcd.setCursor(0, 1);
lcd.print ("FALSCHER CODE");
delay(1000);
lcd.setCursor(0, 1);
lcd.print(" ");
sz1 = 0; sz2 = 1; sz3 = 1; sz4 = 1;
goto spw;
}
}
if (sz1 == 0)
{
SC1 = STaste;
Serial.println(SC1);
lcd.setCursor(0, 1);
lcd.print(SC1);
sz1 = 1; sz2 = 0; sz3 = 1; sz4 = 1;
goto spw;
}
if (sz2 == 0)
{
SC2 = STaste;
Serial.println(SC2);
lcd.setCursor(0, 1);
lcd.print("*");
lcd.setCursor(1, 1);
lcd.print(SC2);
sz1 = 1; sz2 = 1; sz3 = 0; sz4 = 1;
goto spw;
}
if (sz3 == 0)
{
SC3 = STaste;
Serial.println(SC3);
lcd.setCursor(1, 1);
lcd.print("*");
lcd.setCursor(2, 1);
lcd.print(SC3);
sz1 = 1; sz2 = 1; sz3 = 1; sz4 = 0;
goto spw;
}
if ( sz4 == 0)
{
SC4 = STaste;
Serial.println(SC4);
lcd.setCursor(2, 1);
lcd.print("*");
lcd.setCursor(3, 1);
lcd.print(SC4);
sz1 = 1; sz2 = 1; sz3 = 1; sz4 = 1;
}
}
}
if (alarmaktiviert == 1) // nur wenn der Alarm durch die "*" Taste aktiviert wurde kann dieser Block ausgeführt werden
{
if (digitalRead(bewegungsmelder) == HIGH && h == 0 )
{
Serial.println("bewegung erkannt");
myTimer2 = millis();
Serial.print("myTimer2 ");
Serial.println(myTimer2);
Serial.print("millis ");
Serial.println(millis());
//Serial.println("Rote LED leuchtet"); // soll für die Übersicht im digitalen monitor sagen das die LED jetzt leuchtet
digitalWrite(LED, HIGH);
h = 1;
b = 1;
}
if (millis() == (myTimeout2 + myTimer2) && b == 1 ) //"digitalRead(bewegungsmelder) == HIGH" ausgetauscht durch *b*
{
//Serial.print("alarm an");
digitalWrite(alarm, HIGH);
}
}
}
Das wäre der Code er ist noch nicht vollständig und es fehlen noch ein paar sachen.
Es geht unten um das MyTimer=millis() das wird nur einmal ausgeführt und danach wie schon beschrieben wird MyTimer2 zu super komischen Zahlen und nichtmehr =millis()
restlos alle variablen die im Zusammenhang mit millis() benutzt werden müssen vom Variablentyp unsigned long sein.
statt
int myTimer2 = 0;
int myTimeout2 = 10000;
unsigned long myTimer2 = 0;
unsigned long myTimeout2 = 10000;
Der Variablentyp int kann nur Zahlen +- 32767 speichern.
Also 32676 Millisekunden = 32,7 Sekunden.
Wenn man eine größere Zahl speichern will kommt da Quark dabei raus.
unsigned long geht bis 4.294.967.295
Das sind dann 49 Tage. Ausserdem gibt die function millis() einen Zahlenwert vom Type unsigend long zurück
16bit 1234567890123456
int myVar = 1111111111111111
32bit 12345678901234561234567890123456
unsigned long myVar = 11111111111111111111111111111111
Wenn du eine 32bit-Zahl in eine 16bit Variable reinstopfst klappt das nicht
da geht was verloren
vgs
Achso ok danke das probiere ich morgen direkt mal aus und melde mich dann nochmal
Die Additionsmethode macht Probleme.
Und der Vergleich auch.
Besser > o.ä.
Bei Binärzahlen ist dieses Problem etwas abstrakt weil Binärzahlen in Dezimalzahlen umgewandelt immer krumm sind.
Warum wird bei int aus 40000 plötzlich 7233?
8 Bit sind Zahlen von 0 bis 255
16 bit sind 0 bis 65535 bzw -32768 bis 32767 mit Vorzeichen
32 bit sind 0 bis 4294967295 bzw -2147483648 bis 2147483647 mit Vorzeichen
float sind -3,4028235E+38 bis 3,4028235E+38 aber nur 6-7 significante Ziffern.
Am ehesten versteht man es wenn man ein Display mit 2 Ziffern hat und dort eine 3 stellige Zahl reinschreiben will. Die Hunderter gehen verloren.
Grüße Uwe
ich habe jetzt oben beim festlegen die Variable als unsigned long gekennzeichnet und jetzt funktioniert alles so wie es soll und ich kann mit den anderen Funktionen die ich noch einbauen möchte weiter machen. Danke für eure Hilfe
Das macht bei mir bisher keine Probleme warum könnte das zu einem Problem führen?
Sie verwenden
int meinTimer2 = 0;
int meinTimeout2 = 10000;
Ein int
auf einem UNO/MEGA kann bis zu 32767 steigen, wenn Sie dann 1 hinzufügen, wird es negativ. Sie überlaufen.
Wenn Sie myTimeout2 + myTimer2
ausführen, können Sie im negativen Bereich landen, und da millis() immer positiv ist, gibt es keine Chance, dass Sie die Bedingung jemals erfüllen werden
if (millis() == (myTimeout2 + myTimer2)
Darf man es sehen?
Er hat die zwei Variablen doch inzwischen als unsigned Long definiert.
Der gut erklärende Thread wurde doch in Post #6 verlinkt. Es gibt Probleme beim Überlauf. Da du nicht die Differenz sondern das Ergebnis der Summe vergleichst.
Hier einmal das Fertige Proramm hat alles funktioniert war auch nur zum Zeitvertreib also benutzen werden ich es für eine Alarmanlage nicht aber es funktioniert so wie ich es mir vorgestellt habe.
int fc = 0;
//LED
const byte LED = 13;
int ledState = LOW;
int ledState2 = LOW;
const unsigned long onZeitLed = 1000; //ms //fürs blinken der LED
const unsigned long offZeitLed = 200; //ms
int Blink = 0;
//ausgang für das leuchten der LED
//Alarm
int alarm = 11; //ausgang für den Pipser also den Alarm
int bewegungsmelder = 12; //auslesen der bewegung also rückmeldung des Bewegungsmelder
int bewegungsmelderspannung = 10; //nur die Spannungsversorgung für den Bewegungsmelder
int h = 0;
int b = 0;
int alarmaktiviert = 0; //
unsigned long myTimer2 = 0;
unsigned long myTimeout2 = 10000; // Die Zeit nach der der Alarm angehenm soll nachdem die Warn LED an gegangen ist
//Anzeige
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//Zahlenpad
#include <Keypad.h>
char P1 = '1'; char P2 = '2'; char P3 = '3'; char P4 = '4';
char C1, C2, C3, C4;
char SP1 = '4'; char SP2 = '3'; char SP3 = '2'; char SP4 = '1';
char SC1, SC2, SC3, SC4;
const byte COLS = 4;
const byte ROWS = 4;
int z1 = 0, z2, z3, z4;
int sz1 = 0, sz2, sz3, sz4;
char hexaKeys[ROWS][COLS] = {
{'1', '4', '7', '*'},
{'2', '5', '8', '0'},
{'3', '6', '9', '#'},
{'A', 'B', 'C', 'D'}
};
byte colPins[COLS] = { 9, 8, 7, 6 };
byte rowPins[ROWS] = { 5, 4, 3, 2 };
char Taste;
char STaste;
Keypad Tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(alarm, OUTPUT);
pinMode(bewegungsmelder, INPUT);
pinMode(LED, OUTPUT);
}
void loop()
{
Anfang:
if (fc <= 2)
{
Taste = Tastenfeld.getKey();
if (Taste)
{
if (Taste == '*')
{
for (int s = 5; s > 0; s--) //hier kann man einstellen nach welcher zeit der Alarm aktiviert werden soll, nachdem die "*" Taste gedrückt wurde, indem man die s = verändert s Startet bei " " und wird bei jedem lauf um 1 runter gezählt durch den delay unten immer nach genau 1 Sek
{
Serial.print("Alarm aktiviert in: ");
Serial.print( s );
Serial.println( " Sekunden.");
lcd.setCursor(0, 0);
lcd.print("Alarm aktiviert ");
lcd.setCursor(0, 1);
lcd.print("in: ");
lcd.print( s );
lcd.println( " Sekunden.");
delay(1000);
}
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
Serial.println("ALARM AN");
lcd.setCursor(0, 0);
lcd.print("ALARM AN");
digitalWrite(bewegungsmelderspannung, HIGH);
alarmaktiviert = 1;
z1 = 0; z2 = 1; z3 = 1; z4 = 1;
goto Anfang;
}
if (Taste == '#')
{
if (C1 == P1 && C2 == P2 && C3 == P3 && C4 == P4)
{
lcd.setCursor(0, 0);
lcd.print(" ");
Serial.println ("ALARM AUS");
lcd.setCursor(0, 0);
lcd.print ("ALARM AUS");
lcd.setCursor(0, 1);
lcd.print(" ");
digitalWrite(bewegungsmelderspannung, LOW);
delay(3000);
digitalWrite(alarm, LOW);
digitalWrite(LED, LOW);
alarmaktiviert = 0;
h = 0;
b = 0;
Blink = 0;
// myTimer2 = 0;
fc = 0;
}
else
{
Serial.println ("FALSCHER CODE");
lcd.setCursor(0, 1);
lcd.print ("FALSCHER CODE");
delay(1000);
lcd.setCursor(0, 1);
lcd.print(" ");
z1 = 0; z2 = 1; z3 = 1; z4 = 1;
fc++; // nach falscher passwort Eingabe wird hier fc einen hoch gesetzt und wenn das 3 mal falsch eingegeben wurde wird man nach einem Sicherheitspassort gefragt
if (fc > 2)
{
lcd.setCursor(0, 0);
lcd.print("SPW erforderlich");
Serial.println("SPW erforderlich");
}
goto Anfang;
}
}
if (z1 == 0)
{
C1 = Taste;
Serial.println(C1);
lcd.setCursor(0, 1);
lcd.print(C1);
z1 = 1; z2 = 0; z3 = 1; z4 = 1;
goto Anfang;
}
if (z2 == 0)
{
C2 = Taste;
Serial.println(C2);
lcd.setCursor(0, 1);
lcd.print("*");
lcd.setCursor(1, 1);
lcd.print(C2);
z1 = 1; z2 = 1; z3 = 0; z4 = 1;
goto Anfang;
}
if (z3 == 0)
{
C3 = Taste;
Serial.println(C3);
lcd.setCursor(1, 1);
lcd.print("*");
lcd.setCursor(2, 1);
lcd.print(C3);
z1 = 1; z2 = 1; z3 = 1; z4 = 0;
goto Anfang;
}
if ( z4 == 0)
{
C4 = Taste;
Serial.println(C4);
lcd.setCursor(2, 1);
lcd.print("*");
lcd.setCursor(3, 1);
lcd.print(C4);
z1 = 1; z2 = 1; z3 = 1; z4 = 1;
}
}
}
spw:
if (fc > 2)
{
STaste = Tastenfeld.getKey();
if (STaste)
{
if (STaste == '#')
{
if (SC1 == SP1 && SC2 == SP2 && SC3 == SP3 && SC4 == SP4)
{
lcd.setCursor(0, 0);
lcd.print(" ");
Serial.println ("ALARM AUS");
lcd.setCursor(0, 0);
lcd.print ("ALARM AUS");
lcd.setCursor(0, 1);
lcd.print(" ");
digitalWrite(bewegungsmelderspannung, LOW);
delay(3000);
digitalWrite(alarm, LOW);
digitalWrite(LED, LOW);
alarmaktiviert = 0;
fc = 0; //Der Zähler für die Eingabe zu vieler Passwort versuche
h = 0;
b = 0;
Blink = 0;
SC1 = 0, SC2, SC3 = 0, SC4 = 0;
sz1 = 0, sz2 = 0, sz3 = 0, sz4 = 0;
}
else
{
Serial.println ("FALSCHER CODE");
lcd.setCursor(0, 1);
lcd.print ("FALSCHER CODE");
delay(1000);
lcd.setCursor(0, 1);
lcd.print(" ");
sz1 = 0; sz2 = 1; sz3 = 1; sz4 = 1;
goto spw;
}
}
if (sz1 == 0)
{
SC1 = STaste;
Serial.println(SC1);
lcd.setCursor(0, 1);
lcd.print(SC1);
sz1 = 1; sz2 = 0; sz3 = 1; sz4 = 1;
goto spw;
}
if (sz2 == 0)
{
SC2 = STaste;
Serial.println(SC2);
lcd.setCursor(0, 1);
lcd.print("*");
lcd.setCursor(1, 1);
lcd.print(SC2);
sz1 = 1; sz2 = 1; sz3 = 0; sz4 = 1;
goto spw;
}
if (sz3 == 0)
{
SC3 = STaste;
Serial.println(SC3);
lcd.setCursor(1, 1);
lcd.print("*");
lcd.setCursor(2, 1);
lcd.print(SC3);
sz1 = 1; sz2 = 1; sz3 = 1; sz4 = 0;
goto spw;
}
if ( sz4 == 0)
{
SC4 = STaste;
Serial.println(SC4);
lcd.setCursor(2, 1);
lcd.print("*");
lcd.setCursor(3, 1);
lcd.print(SC4);
sz1 = 1; sz2 = 1; sz3 = 1; sz4 = 1;
}
}
}
if (alarmaktiviert == 1) // nur wenn der Alarm durch die "*" Taste aktiviert wurde kann dieser Block ausgeführt werden
{
if (digitalRead(bewegungsmelder) == HIGH && h == 0 )
{
Serial.println("bewegung erkannt");
myTimer2 = millis();
Serial.print("myTimer2 ");
Serial.println(myTimer2);
Serial.print("millis ");
Serial.println(millis());
//Serial.println("Rote LED leuchtet"); // soll für die Übersicht im digitalen monitor sagen das die LED jetzt leuchtet
h = 1;
b = 1;
Blink = 1;
}
if (millis() >= (myTimeout2 + myTimer2) && b == 1 ) //"digitalRead(bewegungsmelder) == HIGH" ausgetauscht durch *b*
{
//Serial.print("alarm an");
digitalWrite(alarm, HIGH);
}
if (Blink == 1)
{
digitalWrite(LED, (millis() % (onZeitLed + offZeitLed)) < onZeitLed);
}
}
}
/*
* ..////////////...////..........
* ............//...//...//.......
* ............//...//.....//.....
* ............//...//.......//...
* ............//...//.....//.....
* ............//...//....//......
* ............//...//......//....
* ............//...//.......//...
* //........//.....//.....//.....
* ..//.....//......//...//.......
* ....////.........////..........
*/
Das ist ein Problem
Es ist kein gutes Zeichen, dass du das ignorierst.
Das macht mir Sorgen.
Und dein Goto Einsatz....
(Nicht falsch verstehen, ich habe nix gegen Goto)
Aber dennoch sieht das bei dir aus, als würdest du damit Schleifen nachbauen.
Ein Rat:
Niemals rückwärts springen!
Nur vorwärts.
Tipps zu Verschönerung:
Wenn schon Automaten bauen, dann klar benennen, auch die Zustände.
In Funktionen aufteilen. Keine länger als, Pi mal Daumen, 20 Zeilen.
Weniger IF ineinander schachteln.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.