LED Counter in Alarmanlage funktioniert nicht

wie meinst du das?

@andreasnano
Auch wenn Du das blink() jetzt rausgenommen hast:
Damit ist gemeint, dass Du die Variable Speicher immer wieder auf 0 setzt.
Gemeint hast Du höchstwahrscheinlich einen Vergleich auf "ist der Inhalt der Variablen Null":

  if (Speicher == 0)

Großschreibung bei Variablennamen ist übrigens wenig verbreitet; Klassen werden üblicherweise groß, Objekte und Variablen klein geschrieben.

Danke dir. Hab es jetzt mal angepasst und es hinbekommen, dass zumindest der erste Alarm gespeichert wird, jedoch funktionieren die anderen beiden Speicher-LEDs noch immer nicht….

 
int Eingang = 8;
int buzzerPin = 10;
int Licht = A6;
int L1 = A3;
int L2 = A2;
int L3 = A1;
int L4 = A0;
 
const int rs = 11, en = 12, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
 
int A;
int VWert = HIGH;
int VSchranke = 0;
int(Speicher) = 0;
 
void setup() {
  pinMode(Eingang, INPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(Licht, INPUT);
  pinMode(L1, OUTPUT);
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT);
  pinMode(L4, OUTPUT);
  digitalWrite(L1, LOW);
  digitalWrite(L2, LOW);
  digitalWrite(L3, LOW);
  digitalWrite(L4, LOW);
 
  Serial.begin(9600);
 
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Booting up...");
  lcd.blink();
  delay(2000);
  lcd.noBlink();
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("*System bereit*");
  tone(buzzerPin, 700, 100);
  delay(1500);
  lcd.clear();
}
 
void loop() {
  int Wert = digitalRead(Eingang);
  int Schranke = analogRead(Licht);
  Serial.println(Schranke);
  if (Wert == LOW && VWert != LOW) {
    // Alarm ausgelöst
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("!!!ALARM!!!");
    lcd.setCursor(0, 1);
    lcd.print("Bedrohungslage");
    siren();
    Speicher = Speicher + 1;
 
  } else if (Wert == HIGH && VWert != HIGH) {
    // Alarm deaktiviert
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Bereich sicher");
    noTone(buzzerPin);
  }
 
  if (Schranke < 1 && VSchranke >= 1) {
    // Alarm ausgelöst
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("!!!ALARM!!!");
    lcd.setCursor(0, 1);
    lcd.print("Bedrohungslage");
    siren();
    Speicher = Speicher + 1;
 
  } else if (Schranke >= 1 && VSchranke < 1) {
    // Alarm deaktiviert
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Bereich sicher");
    noTone(buzzerPin);
  }
 
  VWert = Wert;
  VSchranke = Schranke;
 
  //if (Speicher == 0)
    //blink();
 

  if (Speicher == 1)
    digitalWrite(L2, HIGH);
    digitalWrite(L1, LOW);
    digitalWrite(L3, LOW);
    digitalWrite(L4, LOW);
 
  if (Speicher == 2)
    digitalWrite(L2, HIGH);
    digitalWrite(L3, HIGH);
    digitalWrite(L1, LOW);
    digitalWrite(L4, LOW);
 
  if (Speicher == 3)
    digitalWrite(L2, HIGH);
    digitalWrite(L3, HIGH);
    digitalWrite(L4, HIGH);
    digitalWrite(L1, LOW);
 
//if (Speicher >= 4)
  //digitalWrite(L1, HIGH);
  //digitalWrite(L2, HIGH);
  //digitalWrite(L3, HIGH);
  //digitalWrite(L4, HIGH);
}
void siren() {
  for (int i = 10; i < 800; i += 90) {
    tone(buzzerPin, i);
    delay(130);
  }
}
 

//void blink() {
//if (Speicher = 0)
//digitalWrite(L1, HIGH);
//delay(1000);
//digitalWrite(L1, LOW);
//delay(1000);
 

 

Nur dass du Klarheit hast, was der Unterschied ist.
"if (Speicher = 0)"
Damit ist Speicher immer "0", weil du Speicher damit auf "0" änderst
"if (Speicher == 0)"
damit testest du ob Speicher "0" ist, ohne ihn zu verändern.
Mit 4 LED´s kannst du übrigens bis zu 16 Zustände anzeigen.
0000 = 0
1000 = 1 - die erste 1 steht für 1
0100 = 2 - die zweite 1 steht für 2
1100 = 3
0010 = 4 - die dritte 1 steht für 4
1010 = 5
0110 = 6
1110 = 7
0001 = 8 - die vierte 1 steht für 8
1001 = 9
0101 = 10
1101 = 11
0011 = 12
1011 = 13
0111 = 14
1111 = 15 = 1+2+4+8=15
Nennt sich "Binärcode"

Franz

Ich schenke Dir ein paar Klammern {{{ }}} - richtig verteilt könnten die helfen :wink: .

nicht spicken, bitte!
  if (Speicher == 1) {
    digitalWrite(L2, HIGH);
    digitalWrite(L1, LOW);
    digitalWrite(L3, LOW);
    digitalWrite(L4, LOW);
  }
 
  if (Speicher == 2) {
    digitalWrite(L2, HIGH);
    digitalWrite(L3, HIGH);
    digitalWrite(L1, LOW);
    digitalWrite(L4, LOW);
  }
 
  if (Speicher == 3) {
    digitalWrite(L2, HIGH);
    digitalWrite(L3, HIGH);
    digitalWrite(L4, HIGH);
    digitalWrite(L1, LOW);
  }

Ich verstehe nicht? :joy:

Hmm.
Dann schau mal hier weiter unten bei Compound statements und klickst danach auf das kleine schwarze Dreieck ► in Post #27. Dann wird daraus ein ▼ und was ich meine wird sichtbar.

Ich hab Dir mal was gebaut, ganz ohne Display.
Nur einen PIN.
Der löst aus, wenn der PIN LOW gezogen wird.

constexpr byte Eingang {8};
constexpr byte buzzerPin {10};
// constexpr byte Licht = A6;
constexpr byte almLed[] {A3, A2, A1, A0};

bool lastPinState;
byte status = 0;
constexpr uint32_t buzzerTime {1500};

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start..."));
  pinMode(Eingang, INPUT);
  pinMode(buzzerPin, OUTPUT);
  for (byte b = 0; b < sizeof(almLed); b++)
  {
    pinMode(almLed[b], OUTPUT);
    digitalWrite(almLed[b], LOW);
  }
}

void loop()
{
  almPinCheck();
  checkOut();
}
//
void checkOut()
{
  switch (status)
  {
    case 0:
      blinken(500);
      break;
    case 1 ... 3:
      if (lastPinState)
      { siren(); }
      else
      { noTone(buzzerPin); }
      digitalWrite(almLed[status], HIGH);
      break;
  }
}

void blinken(const uint32_t blinkTime)
{
  static uint32_t lastBlinkTime = 0;
  if (millis() - lastBlinkTime > blinkTime)
  {
    digitalWrite(almLed[0], !digitalRead(almLed[0]));
    lastBlinkTime = millis();
  }
}
//
void almPinCheck()
{
  static uint32_t lastPinChange = 0;
  if (!digitalRead(Eingang))
  {
    if (!lastPinState)
    {
      lastPinState = HIGH;
      lastPinChange = millis();
      status++;
    }
  }
  else if (millis() - lastPinChange > buzzerTime)
  {
    lastPinState = LOW;
  }
}
//
void siren()
{
  for (byte b = 0; b < 10; b++)
  {
    tone(buzzerPin, b * 90);
    delay(100);
  }
}

Sinn der Übung soll sein, das Du den Alarm mehrfach auslösen kannst, aber nur die drei alarmLeds angehen. (geht hier aufgrund der Beschränkung jetzt 254 Mal)

Die erste LED blinkt, solange kein Alarm ausgelöst wurde.
Wird der Alarm ausgelöst, bleibt sie dauerhaft an oder aus.

Die Sirene ist auch nciht schick, aber vielleicht gibt die ja nen Ton von sich :wink:
Und wenn das geht, bauen wir weiter.

Kompiliert - ob der geht, musst Du probieren.

Vielen Dank und sorry für die späte Antwort. Das Programm funktioniert tatsächlich und genauso war auch meine Vorstellung... muss mir den Code aber noch bisschen genauer ansehen, damit ich ihn verstehe

Schick.
Hab ich ja richtig gelegen. :wink:

Nu musst mir nur noch erklären, was Du mit dem analogpin machen willst und dann baue ich Dir das Display wieder ein.
Willst Du die Anzahl der Auslösungen merken / auf dem Display / auf dem serMon sehen?

Der Analogpin "Licht"? Das war nur ein Experiment mit einer Lichtschranke. Hat auch geklappt, brauch ich aber nicht mehr in dem Code, ist nur einfach dageblieben weil das funktioniert hat. Die Anzahl der Auslösungen wollte ich eigentlich über die LEDs sehen, aber wenn es auch noch auf dem LCD stehen würde, wäre natürlich super.

Auf dem serMon brauch ichs nicht, weil es später nur an nem USB -Stecker im Strom hängen wird

#include <LiquidCrystal.h>

constexpr byte rs {11};
constexpr byte en {12};
constexpr byte d4 {3};
constexpr byte d5 {4};
constexpr byte d6 {5};
constexpr byte d7 {6};
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
uint16_t lastlcdState = 65000; // muss zum Start != 0 sein


constexpr byte Eingang {8};
constexpr byte buzzerPin {10};
// constexpr byte Licht = A6;
constexpr byte almLed[] {A3, A2, A1, A0};

bool alarmState;
uint16_t status = 0; // MAX: 65535
constexpr uint32_t buzzerTime {1500};

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start..."));
  lcd.begin(16, 2);
  lcd.print(F("boot"));
  pinMode(Eingang, INPUT);
  pinMode(buzzerPin, OUTPUT);
  for (byte b = 0; b < sizeof(almLed); b++)
  {
    pinMode(almLed[b], OUTPUT);
    digitalWrite(almLed[b], LOW);
  }
  for (byte b = 0; b < 4; b++)
  {
    lcd.print('.');
    delay(500);
  }
  lcd.noBlink();
}

void loop()
{
  almPinCheck();
  checkOut();
  lcdOut();
}
//
void checkOut()
{
  switch (status)
  {
    case 0:
      blinken(500);
      break;
    case 1 ... 3:
      if (alarmState)
      { siren(); }
      else
      { noTone(buzzerPin); }
      digitalWrite(almLed[0], LOW);
      digitalWrite(almLed[status], HIGH);
      break;
  }
}

void blinken(const uint32_t blinkTime)
{
  static uint32_t lastBlinkTime = 0;
  if (millis() - lastBlinkTime > blinkTime)
  {
    digitalWrite(almLed[0], !digitalRead(almLed[0]));
    lastBlinkTime = millis();
  }
}
//
void almPinCheck()
{
  static uint32_t lastPinChange = 0;
  if (!digitalRead(Eingang))
  {
    if (!alarmState)
    {
      alarmState = HIGH;
      lastPinChange = millis();
      status++;
    }
  }
  else if (millis() - lastPinChange > buzzerTime)
  {
    alarmState = LOW;
  }
}
//
void siren()
{
  for (byte b = 0; b < 10; b++)
  {
    tone(buzzerPin, b * 90);
    delay(100);
  }
}

void lcdOut()
{
  if (lastlcdState == status)
  { return; }
  lcd.clear();
  lcd.print(status ? (F("Alarm")) : (F("*System bereit*")));
  if (status)
  {
    lcd.setCursor(0, 1);
    lcd.print(F("Value: "));
    lcd.print(status);
  }
  lastlcdState = status;
}

// edit: Überarbeitet - Funktionen getrennt

Hab das jetzt mal ausprobiert, er bleibt jetzt leider im Alarm Modus stecken und zählt dauerhaft hoch... kann das daran liegen, dass der Code Funktion für Funktion durchgeht und deshalb, sobald Alarm ausgelöst wird, nicht wieder zurückspringt?

Das Hochzählen mit den LEDs funktioniert aber wunderbar

Hm... Ich hab doch nix weiter dran geändert.

Wie ist denn denn Dein Magnetsensor angeschlossen? Ich hab ja ne böse Ahnung.
Probier mal den hier.

#include <LiquidCrystal.h>

constexpr byte rs {11};
constexpr byte en {12};
constexpr byte d4 {3};
constexpr byte d5 {4};
constexpr byte d6 {5};
constexpr byte d7 {6};
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
uint16_t lastlcdState = 65000; // muss zum Start != 0 sein


constexpr byte Eingang {8};
constexpr byte buzzerPin {10};
// constexpr byte Licht = A6;
constexpr byte almLed[] {A3, A2, A1, A0};

bool alarmState;
uint16_t status = 0; // MAX: 65535
constexpr uint32_t buzzerTime {1500};

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start..."));
  lcd.begin(16, 2);
  lcd.print(F("boot"));
  pinMode(Eingang, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  for (byte b = 0; b < sizeof(almLed); b++)
  {
    pinMode(almLed[b], OUTPUT);
    digitalWrite(almLed[b], LOW);
  }
  for (byte b = 0; b < 4; b++)
  {
    lcd.print('.');
    delay(500);
  }
  lcd.noBlink();
}

void loop()
{
  almPinCheck();
  checkOut();
  lcdOut();
}
//
void checkOut()
{
  switch (status)
  {
    case 0:
      blinken(500);
      break;
    case 1 ... 3:
      alarmState ? siren() : noTone(buzzerPin);
      digitalWrite(almLed[0], LOW);
      digitalWrite(almLed[status], HIGH);
      break;
  }
}

void blinken(const uint32_t blinkTime)
{
  static uint32_t lastBlinkTime = 0;
  if (millis() - lastBlinkTime > blinkTime)
  {
    digitalWrite(almLed[0], !digitalRead(almLed[0]));
    lastBlinkTime = millis();
  }
}
//
void almPinCheck()
{
  static uint32_t lastPinChange = 0;
  if (!digitalRead(Eingang))
  {
    if (!alarmState)
    {
      Serial.println(F("ausgelöst"));
      alarmState = HIGH;
      lastPinChange = millis();
      status++;
    }
  }
  else if (millis() - lastPinChange > buzzerTime)
  {
    if (alarmState)
    { Serial.println(F("nicht ausgelöst")); }
    alarmState = LOW;
  }
}
//
void siren()
{
  for (byte b = 0; b < 10; b++)
  {
    tone(buzzerPin, b * 90);
    delay(100);
  }
}

void lcdOut()
{
  if (lastlcdState == status)
  { return; }
  lcd.clear();
  lcd.print(status ? (F("Alarm")) : (F("*System bereit*")));
  if (status)
  {
    lcd.setCursor(0, 1);
    lcd.print(F("Value: "));
    lcd.print(status);
  }
  lastlcdState = status;
}

Mit jedem auslösen und mit jedem Ende des auslösens muss eine Meldunga uf dem SerMon kommen.

Hi, ich werde das morgen probieren. Du hast tatsächlich recht, ich hab beim letzen testen dummerweise vergessen, den Magnetsensor anzuschließen :man_facepalming:

Werde das morgen nochmal probieren und mich dann melden. Vielen vielen Dank dir auf jeden Fall schonmal für deine Mühe und Zeit

Es hat vieleicht nur zufällig funktioniert. Der analoge Eingang mißt nicht zuverlässig bei auf Masse geschaltenen Eingang 0. Durch Übergangswiderstände in Kontakten, Störungen und Ausgangselektronik des Sensors (hier Lichtschranke) kann leicht das letzte Bit ( LSB ) mal 1 werden und Du dann bei geschlossener Lichtschranke 1 statt 0 mißt. Wenn Du einen digitalen Sensor schon analog auslesen mußt, weil alle digitalfähigen Pins schon verwendet sind, dann nimmm doch bitte einnen geeigneten Schwellwert um auf HIGH bzw LOW zu prüfen, am besten noch mit einer Hysterese.

Wenn die Messung des Sensors sagen wir mal als Werte 0 und 900 erhalten dann nimm als Schwellwert nicht 1 sondern etwas um 450 mit einer Hysterese von 100. Also Wert > 500 HIGH; Wert < 400 LOW.

Grüße Uwe

Alsooooo.... wenn ich die tür öffne kommt "ausgelöst". Bleibt sie auf, komt "ausgelöst" und "nicht ausgelöst" gleichzeitig, bis ich die tür schließe.

Diesmal ist der Sensor angeschlossen. Was soll ich tun, liegt es daran, wie ich den angeschlossen habe?

Hi, es geht aber nicht um die Lichtschranke, die ist gar nicht vorhanden, sondern um einen Magnetsensor....

AHH!
Ändere mal die Zeile 78 von

  if (!digitalRead(Eingang)) 

in neu:

  if (digitalRead(Eingang)) 

Ist egal was der Sensor wie mißt. Ich sprach vom Ausgang des Sensors und Deiner falschen Annahme wie sich der Digitale Ausgangswert analog darstellt.

Grüße Uwe