Zählfunktion bei Arduinoprojekt

Hallo zusammen,

ich habe mich vor Kurzem an mein erstes Projekt mit einem Aruino Uno gewagt. Das Programmieren hab ich mir über Youtube Videos und lesen hier im Forum beigebracht. Das Projekt läuft recht gut, nur an einer Sache, die m.E. sehr einfach sein sollte, hänge ich jetzt.

Das Projekt gestaltet sich so: Wenn ein Fotowiderstand beleuchtet wird, soll ein Transistor eine 12V Last schalten und das für eine bestimmte und unterschiedliche Dauer. Im Beispiel bei der ersten Beleuchtung des Fotowiderstands für 10 Sekunden, bei der zweiten für 5. Das Signal des Fotowiderstandes wird über Serial.beginn (9600) und Pin A0 eingelesen. Der Transistor wird über Pin 4 angesteuert. Gelöst habe ich das Ganze über eine for- und mehrere if-Schleifen. Ich bin mir sicher, der Programmcode lässt sich viel eleganter gestalten. Aber ich bin wie gesagt nicht wirklich vom Fach.

Das Ganze funktioniert auch. Nur die unterschiedlichen Schaltzeiten (10 und 5 Sekunden) klappen nicht. Es wird nur immer für 5 Sekunden geschalten. Weiß jemand rat? Wenn es das Thema so schon im Forum gibt, bitte gerne darauf verweisen. Dann hab ich es leider nicht gefunden.
Danke im Vorraus,
Matthias

Hier der Code:

int licht; // Signal auf A0 vom Fotowiderstand
int zaehler;
void setup() {
Serial.begin(9600); // Öffnet die serielle Schnittstelle für Fotowiderstand
pinMode(4, OUTPUT);
}

void loop() {
 licht = analogRead(0);
 Serial.println(licht);
 for (zaehler = 0; zaehler = zaehler+1; zaehler < 10);
 if (zaehler = 0) // für das erste Signal vom Fotowiderstand
 {
 if (licht < 500) { // Transistor soll geschaltet werden, wenn Sensorwert < 500
   digitalWrite (4, HIGH);
 }
 else {
   digitalWrite(4, LOW);
 }
 if (licht < 500) { // Transistor soll für 10 Sekunden geschalter werden, wenn Sensorwert < 500
   delay(10000);
 }
 else {
   delay(1);
 }
 }
else
{
   delay(1);
}
 if (zaehler = 1) // für das zweite Signal vom Fotowiderstand
 {
 if (licht < 500) { // Transistor soll geschaltet werden, wenn Sensorwert < 
   digitalWrite (4, HIGH);
 }
 else {
   digitalWrite(4, LOW);
 }
 if (licht < 500) {
   delay(5000); // Transistor soll dieses Mal für 5 Sekunden geschalter werden, wenn Sensorwert < 500
 }
 else {
   delay(1);
 }
 }
else
{
   delay(1);
}
}
for (zaehler = 0; zaehler = zaehler + 1; zaehler < 10);

Denk mall drüber nach was hier passiert :wink:
Schau mal wie soll for schleife eingebunden werden

Hallo
ich habe jetzt deinen Sketch nicht verstanden , aber deine for schleife ist falsch, schaue Dir noch mal die for schleife an .

for (zaeler=0; zaehler<10;zaeler++) {

}

Über die {} Klammer wollte später schreiben :wink:

OK das hat sich überschnitten

Gruß Heinz

Mall schauen was der TO draus macht :wink: habe nicht genau geschaut was er Sketsch soll machen

Ok noch kleine Hilfe :wink:

if (licht < 500 && zaehler == 2)  digitalWrite (4, HIGH);
    

Und so Weiter dan sollte es klappen :wink:

if (licht < 500 && zaehler == 2) { // Transistor soll geschaltet werden, wenn Sensorwert < 500
      digitalWrite (4, HIGH);
    }

Kann man auch schreiben.

Das macht garantiert nicht was du glaubst.
Die aktivierten Warnungen würden dir das auch sagen.

Lesestoff: if-Schleife

Ja der Compiler meckert, nur unterbricht nicht.
@matt53
so die IDE Einstellen
image
Danach ist bei deinem Sketch ziemlich rot :wink:

? wie bitte?

constexpr byte outputPin {4};
constexpr uint32_t interval {5000};

unsigned int lichtWert; // Signal auf A0 vom Fotowiderstand
unsigned int lastLichtWert;
unsigned int zaehler;

uint32_t startTime;
uint32_t pauseTime;

void setup()
{
  Serial.begin(9600); // Öffnet die serielle Schnittstelle für Fotowiderstand
  Serial.println(F("Start..."));
  pinMode(outputPin, OUTPUT);
  digitalWrite(outputPin, LOW);
}
//
void getLicht()
{
  lichtWert = analogRead(0);
  if (lastLichtWert != lichtWert)
  {
    Serial.println(lichtWert);
    lastLichtWert = lichtWert;
  }
}
//
void setOutput()
{
  if (lichtWert < 500)   // Transistor soll geschaltet werden, wenn Sensorwert < 500
  {
    if (!digitalRead(outputPin))
    {
      digitalWrite (outputPin, HIGH);
      startTime = millis();
      switch (zaehler)
      {
        case 0:
          pauseTime = interval;
          break;
        case 1:
          pauseTime = interval * 2;
        break;
        case 2 ... 10:
          // hier mach irgendwas anderes
          break;
        default:
          // wenn keine Bedingung passt
          zaehler = 0;
          break;
      }
      zaehler++;
    }
  }
  else
  {
    if (digitalRead(outputPin))
    {
      digitalWrite(outputPin, LOW);
    }
  }
}
//
void loop()
{
  if (millis() - startTime > pauseTime)
  { getLicht(); }
  setOutput();
}

Vielen Dank für eure Antworten. Ich werde versuchen, es damit zum Erfolg zu führen :slight_smile:
@fony: ja tatsächlich. Wenn ich for rauslasse, funktioniert's wie geplant :slight_smile:

Grüße,
Matthias

Na ja, wenn du das sagst, ich sage nur

Kann nicht funktionieren, wurde die IDE so eingestellt wie ich gezeigt habe, wurdest du bei Kompilieren nur Rot sehen. Ein Link für if Abfrage
Sich selber beliegen ist nicht so meine Sache, gerade wenn mir jemand zeigt den Weg wo soll ich hin, muss selber noch sehr sehr viel Lernen.

Gruß Bernhard

Hallo Bernhard,

wie schon geschrieben: das Programm funktioniert, bis auf die unterschiedlichen Schaltzeiten. Damit habe ich gemeint, dass, wenn der Fotowiderstand beleuchtet wird, der Transistor schließt. Mehr nicht. Und der Compiler ist tatsächlich ohne Meckern durchgelaufen. Wenn ich ihn so einstelle, wie von Dir vorgeschlagen, schaut die Welt zugegeben etwas anders aus. :see_no_evil:
Ich habe Dein Tipps jetzt mal eingearbeitet - vielen Dank dafür. Compiler läuft jetzt auch mit der Einstellung alle Compiler-Warnungen durch. Leider funktioniert es noch nicht wie gewünscht.
Transistor schaltet zwar, aber leider jedes Mal durchgehend für 15 Sekunden. Und nicht beim ersten Beleuchten für 10 und beim zweiten für 5.
Hier nochmal der angepasst Code. Weiß jemanden einen Rat?

Danke,
Matthias

int licht; // Signal auf A0 vom Fotowiderstand
int zaehler;
void setup() {
Serial.begin(9600); // 
pinMode(4, OUTPUT);
}

void loop() {
 licht = analogRead(0);
 Serial.println(licht);

 for (zaehler = 0; zaehler < 10; zaehler++) {
 if (zaehler == 0 && licht < 500) // für das erste Signal vom Fotowiderstand
 {
   digitalWrite (4, HIGH);
 }
 else {
   digitalWrite(4, LOW);
 }
 if (zaehler == 0 && licht < 500) { // Transistor soll für 10 Sekunden geschalter werden, wenn Sensorwert < 500
   delay(10000);
 }
 else {
   delay(1);
 }


if (zaehler == 1 && licht < 500) // für das zweite Signal vom Fotowiderstand
 {
   digitalWrite (4, HIGH);
 }
 else {
   digitalWrite(4, LOW);
 }

 if (zaehler == 1 && licht < 500) { // Transistor soll für 5 Sekunden geschalter werden, wenn Sensorwert < 500
   delay(5000);
 }
 else {
   delay(1);
 }
}
}

Warum nutzt du eine for Schleife was zählt bis 10 wenn nur 0 = Start und 1nutzt,
von 2 bis 10 passiert gar nichts, ab 2 bis 10 ist die Schleife so schnell das du gar nicht merkst das die von 0 wider anfängt. Und damit du nicht jedes mall 10Sek warten musst kürze die Zeiten auf 2 und 6 Sek.
Versuche das, wo möglich findest du dein Denkfehler :wink:

int licht; // Signal auf A0 vom Fotowiderstand
int zaehler;
void setup() {
  Serial.begin(9600); //
  pinMode(4, OUTPUT);
}

void loop() {


  for (zaehler = 0; zaehler < 10; zaehler++) {
    licht = analogRead(0);
    Serial.print("Licht ");
    Serial.println(licht);
    if (zaehler == 0 && licht < 500) // für das erste Signal vom Fotowiderstand
    {
      digitalWrite (4, HIGH);
    }
    else {
      digitalWrite(4, LOW);
    }
    Serial.print("Zaehler  ");
    Serial.println(zaehler);
    if (zaehler == 0 && licht < 500) { // Transistor soll für 10 Sekunden geschalter werden, wenn Sensorwert < 500
      delay(10000);
    }
    else {
      delay(1);
    }
    Serial.print("Zaehler  ");
    Serial.println(zaehler);

    if (zaehler == 1 && licht < 500) // für das zweite Signal vom Fotowiderstand
    {
      digitalWrite (4, HIGH);
    }
    else {
      digitalWrite(4, LOW);
    }
    Serial.print("Zaehler  ");
    Serial.println(zaehler);
    if (zaehler == 1 && licht < 500) { // Transistor soll für 5 Sekunden geschalter werden, wenn Sensorwert < 500
      delay(5000);
    }
    else {
      delay(1);
    }
    Serial.print("Zaehler  ");
    Serial.println(zaehler);
  }
}

Noch was nach Delay 10000 und 5000 must du den Pin auf LOW schalten sonst leuchtet 15 Sek. habe mein Rechner schon aus, notfalls Morgen.
_Hasse am Tablet programmieren :wink:

Guten Morgen,
Vielen Dank für deine Hinweise, du bist ja fix. Bin übers Wochenende nicht da, werds mir danach nochmal anschauen.
Den Verdacht, dass es quasi in Rutsch durchrauscht hatte ich auch schon.
Ein Detail habe ich vergessen. Ich zähle bis 10 weil ich die Möglichkeit brauche, dass ich bis zu 10 unterschiedliche Zeiten einstellen kann. Hier hab ich beispielhaft nur zwei (10 Sekunden und 5 Sekunden) gepostet, damits nicht zu lang wird. Sorry vielleicht ein sehr wichtiges Detail.
Grüße
Matthias

Ohne For schleife :wink: jetzt musst du nur die Delays endsorgen :wink:

int licht = A0; // Signal auf A0 vom Fotowiderstand
byte zaehler = 0; // Zähler kann bis 255 sein sonst int
const byte transistor = 4; // 13 Interne LED zum test
void setup() {
  Serial.begin(9600); //
  pinMode(transistor, OUTPUT);

}

void loop() {



  licht = analogRead(0);
  
  Serial.print("Licht ");
  Serial.println(licht);
  if (zaehler == 0 && licht < 500) // für das erste Signal vom Fotowiderstand
  {
    digitalWrite (transistor, HIGH);

  }
  else {
    digitalWrite(transistor, LOW);
  }


  if (zaehler == 0 && licht < 500) { // Transistor soll für 10 Sekunden geschalter werden, wenn Sensorwert < 500
    delay(10000);
    digitalWrite(transistor, LOW);
    zaehler ++;
    Serial.print("Zaehler  ");
    Serial.println(zaehler);
  }
  else {
    digitalWrite(transistor, LOW);
    delay(1);//die 1 milisek wo zu?
  }


  if (zaehler == 1 && licht < 500) { // Transistor soll für 5 Sekunden geschalter werden, wenn Sensorwert < 500
    digitalWrite(transistor, HIGH);
    delay(5000);
    digitalWrite(transistor, LOW);
    zaehler ++;
    Serial.print("Zaehler  ");
    Serial.println(zaehler);
  }
  else {
    digitalWrite(transistor, LOW);
    delay(1);
  }
  if (zaehler == 2 && licht < 500) { // Transistor soll für 5 Sekunden geschalter werden, wenn Sensorwert < 500
    digitalWrite(transistor, HIGH);
    delay(5000);
    digitalWrite(transistor, LOW);
    zaehler ++;
    Serial.print("Zaehler  ");
    Serial.println(zaehler);
  }
  else {
    digitalWrite(transistor, LOW);
    delay(1);
  }

  zaehler = 0;// Hier wird der Zähler zurückgsestzt

}

Was passiert, wenn Du #11 ausprobierst und auf Dich ggfls. anpasst?

Man könnte es ja auch so machen:

#include <Arduino.h>

//////////////////////////////////////////////////
// Object definitions
//////////////////////////////////////////////////
class Timer {
public:
  void start() { timeStamp = millis(); }
  bool operator()(const unsigned long duration) const { return (millis() - timeStamp >= duration) ? true : false; }

private:
  unsigned long timeStamp {0};
};

class SignalCounter {
public:
  template <size_t MAX>
  SignalCounter(const unsigned long (&stArray)[MAX]) : switchingTimes {stArray}, maxIndex {MAX - 1} {}
  byte next() {
    index = (index < maxIndex) ? index + 1 : 0;
    return index;
  }
  unsigned long signalDuration() const { return switchingTimes[index]; }

private:
  const unsigned long *switchingTimes;
  byte maxIndex;
  byte index {0};
};

enum class TransistorSwitchState : uint8_t { off = 0, on, locked };

//////////////////////////////////////////////////
// Global constants
//////////////////////////////////////////////////
constexpr byte ANALOGREAD_PIN {A0};
constexpr byte TRANSISTOR_SWITCH {4};
constexpr int LIGHT_THRESHOLD {500};

//////////////////////////////////////////////////
// Global variables and instances
//////////////////////////////////////////////////
const unsigned long msTimes[] {10000, 5000, 2500, 1250};
//const unsigned long msTimes[] {10000, 5000};
SignalCounter scTransistor(msTimes);
Timer timer;

//////////////////////////////////////////////////
// Main Program
//////////////////////////////////////////////////

bool showMessage(SignalCounter &sct) {
  Serial.print("Nächstes ");
  Serial.print(sct.signalDuration());
  Serial.println(" ms Schaltsignal geblockt weil: ");
  Serial.print("Lichtwert ist nach Schaltsignal");
  Serial.println(" immer noch kleiner als der Grenzwert.\n");
  return false;
}

void setup() {
  Serial.begin(115200);
  pinMode(TRANSISTOR_SWITCH, OUTPUT);
  Serial.println("Schieber nach links  -> \"LDR\" Werte werden kleiner");
  Serial.println("Schieber nach rechts -> \"LDR\" Werte werden größer\n");
}

void loop() {
  static unsigned int light {0};
  static TransistorSwitchState tss {TransistorSwitchState::off};

  if (tss == TransistorSwitchState::off) { light = analogRead(ANALOGREAD_PIN); }

  if (light < LIGHT_THRESHOLD) {
    switch (tss) {
      case TransistorSwitchState::off: 
        timer.start();
        tss = TransistorSwitchState::on;
        digitalWrite(TRANSISTOR_SWITCH, HIGH);
        break;
      case TransistorSwitchState::on:
        if (timer(scTransistor.signalDuration())) {
          scTransistor.next();
          digitalWrite(TRANSISTOR_SWITCH, LOW);
          tss = TransistorSwitchState::locked;
        }
        break;
      case TransistorSwitchState::locked:
        static bool message {true};
        if (analogRead(ANALOGREAD_PIN) >= LIGHT_THRESHOLD) {
          tss = TransistorSwitchState::off;
          message = true;
          break;
        }
        message && (message = showMessage(scTransistor));
        break;
      default: break;
    }
  }
}

Der Lichtwert muss zwischen den zwei Signalen aber min. einmal den Grenzwert von 500 überschreiten. Sonst würden diese ja permanent nacheinander geschaltet.
Die Lichtmessung erfolgt auch nur, wenn gerade kein "Signal" aktiv ist.