funtion ausfürhung Fehler

ChrisSand:
Das geht aber nur bis 49,2 (,2?) Tage denn dann ist die Variable voll und er beginnt immer wieder von vorne, mit den unsignet long "Millisletzteausführung" streibe ich denn dann wieder auf null... bei meinen ein zwei sec. Sketch sollte das kein Problem sein.

Wenn die Kontrolle der verstrichenen Zeit richtig gemacht wird dann ist die Differenz der beiden Zeiten (Beginnzeit und Jetztzeit) auch über einen Überlauf auch richtig berechnet und somit funktioniert die Zeitkontrolle mit millis() richtig. Die einzige Begrenzung ist daß der Intervall nicht größer als ca 49,5 Tage (2^32-1 Millisekunden))sein kann.

Grüße Uwe

combie:
If Schleife

:slight_smile:

so eine LED schaffe ich schon mal...

   byte blinkenPin = 4;                  // LED liegt am (digitalen) Pin 3
    byte buzzPin = 6; //Digital pin an dem der buzer angeschlossen ist
    boolean value = LOW;                  // Startwert der LED
    boolean valuebuzz = HIGH; //start der buzzers
    unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
    unsigned long previousMillisbuzz = 0; //speichert wie viele Sekunden seit derletzten Änderung vergangen sind
    unsigned long interval = 1000;    // Interval zwischen zwei Änderungen
    
     
    void setup()
    {
      pinMode(blinkenPin, OUTPUT);      // Setzt den ledPin (Pin 3) als Ausgang
    Serial.begin(9600);
 
Serial.println("Gestartet");
    }
     
    void loop()
    {
      //LED Blinken
        if (millis() - previousMillis > interval) { //wenn millis() Minus das Letztemalmillies größer als das Interval ist schleife durchlaufen
        previousMillis = millis();   // aktuelle Zeit abspeichern für die nächste abfrage 
        
        value = !value; //der Wert wird gedreht damit bei jeder Loop anders ist

          digitalWrite(blinkenPin, value); // das low oder High auf den Ausgang schreiben
       

 
        }}

jetzt würde ich gerne auch den buzzer jedesmal an und aus schalten lassen

dazu möchte ich "value" noch mal mit if abfragen (@combie nicht schleifen :slight_smile: ) und dann ob LOW oder HIGH den buzzer an oder ausschalten

if (value = LOW){
tone(buzzerPin,500);
}elseo{
notone(buzzerPin);
}

das macht er aber nicht weil der Wert von "value" nach dem schreiben auf den pin dann immer 1 ist...

wo ist der Fehler?

Das sollte auch heißen:

if (value == LOW)

Und bei else ist ein o zuviel.

HotSystems:
Das sollte auch heißen:

if (value == LOW)

Und bei else ist ein o zuviel.

danke bein VBA ist man das einfache = gewohnt....

ChrisSand:
danke bein VBA ist man das einfache = gewohnt....

Ok, da muss man jetzt umdenken.

if (value == LOW)

Ich möchte mich da (ein weiteres Mal) als Pingel outen!

Für mich gilt:
if (value == LOW)
tut man nicht!

Besser:
if (!value)
Wo kein = oder == da kann man sie auch nicht verwechseln

Alternativ:
Anders rum schreiben (die Konstante immer nach links setzen)
if (LOW == value)
Dann schreit der Kompiler, wenn man doch mal aus Versehen
if (LOW = value)
schreibt

guten Morgen zusammen,

ich schon wieder mit meiner Funtion, ich habe jetzt einen Sketch geschrieben der mit aufruf einer Funktion den Arlam ausführt.

//### Variablen Global ###    
    boolean value = LOW;                  // Buzzer an aus schalter
    boolean value2 = HIGH;                // buzzer hoch tief schalter
    unsigned long previousMillis = 0;     // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
    long frq = 500;                       // frequenz des buzze Start 500
//### Starte Setup ###
void setup() {
}
//### Starte Loop ###
void loop() {
  BuzzAlert(8,500); //func wird aufgerufen
}

//### Starte function ###
void BuzzAlert(byte BuzzPin,unsigned long interval) // function #BuzzPin = Ausgabe ping für lautsprecher #Interval Zeit zwischen den wecheln
{     
if (millis() - previousMillis > interval) { //wenn millis() Minus das Letztemalmillies größer als das Interval ist schleife durchlaufen
previousMillis = millis();        // aktuelle Zeit abspeichern für die nächste abfrage 
if (LOW == value){          // wenn value Low dann ton ein
    if (LOW == value2){     // Abfrage für den frequenz wechsel 500/700
      frq = 500;
    }else{
      frq = 700; 
    }
    value2 = !value2;       // dreht den schalter für frequenz wechsel
  tone(BuzzPin,frq);        // buzz on
}else{
  noTone(BuzzPin);          // buzz of
}   
  value = !value;           //der Wert wird gedreht damit bei jeder Loop anders ist
}
}

Das Funktioniert so weit auch, ich habe aber noch fragen zu der Variablen declaration

  • so wie ich das jetzt gemacht habe sind die Global richtig und über all verfügbar. ?
  • Im setup haben die nix zu suchen
  • wenn ich die in den Loop() schreiben und vorbelege (bsp: byte value = LOW;) dann werden die in jedem durchlauf auch neu vorbelegt richtig?
  • das gild auch für die Function ? Denn dann läuft das script nicht m :slight_smile:
  • gibt es eine möglichlkeit die variablen auch in der Func zu belgen? byte hat ja immer eine vorbelegung dann kann ich ja nix machen... oder muss ich dann eine libray schriben ?

so das reicht für einen Sonntag Morgen !

Geltungsbereich von Variablen
Es gibt noch viele weitere C++ Tutorials....

combie:
Geltungsbereich von Variablen
Es gibt noch viele weitere C++ Tutorials....

danke und wieder was gelern...

so jetzt habe ich beide LedBlinen und BuzzAlert als funktionen fertig. puhh aber.... wenn ich beide im LOOP aufrufe Blinkt die LED schon mein Buzzer macht aber keinen wechsel... wo habe ich den denkfehler? einzeln angesprochen gehen beide....

//### Starte Setup ###
void setup() {
  Serial.begin(9600); //kann man immer brauchen!
  }
//### Starte Loop ###
void loop() {
  BuzzAlert(8,200); //func wird aufgerufen
  LedBlinken(4,10,200);
}

void LedBlinken (byte LedPin, long anzahl, long intervalLB){    //function diese lässt an #LedPin pin der LED #anzhal der blinkens #interval lange der Pause
//Variablem deklaration   
static unsigned long previousMillisLB = 0;                      // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
static byte valueLB = HIGH;                                     // schalter für an aus. 
pinMode(LedPin, OUTPUT);                                        // LED Pin zum Ausgang machen
//Strat code
for (int i=0; i <= ((anzahl*2)+1);){                            //die led muss immer an und aus deswegen *2 und +1 damit immer auf low steht (start ist HIGH)
if (millis() - previousMillisLB > intervalLB) {                 //wenn millis() Minus das Letztemalmillies größer als das Interval ist schleife durchlaufen
    previousMillisLB = millis();                                // aktuelle Zeit abspeichern für die nächste abfrage 
    digitalWrite(LedPin, valueLB);                              // pin mit LOW/HIGH belegen
    valueLB = !valueLB;                                         // wechsel von valueLB für die nächste runde
    i++;                                                        // schleife eines höher zählen
}
}
}


//### Starte function ###
void BuzzAlert(byte BuzzPin,unsigned long interval) // function #BuzzPin = Ausgabe ping für lautsprecher #Interval Zeit zwischen den wecheln
{    
    // Variablen statisch nur in der func   
   static  boolean value = LOW;                  // Buzzer an aus schalter
   static  boolean value2 = HIGH;                // buzzer hoch tief schalter
   static  unsigned long previousMillis = 0;     // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
   static  long frq = 500;                       // frequenz des buzze Start 500
if (millis() - previousMillis > interval) { //wenn millis() Minus das Letztemalmillies größer als das Interval ist schleife durchlaufen
previousMillis = millis();        // aktuelle Zeit abspeichern für die nächste abfrage 
value = !value; //der Wert wird gedreht damit bei jeder Loop anders ist
Serial.println(value);
if (LOW == value){          // wenn value Low dann ton ein

    if (LOW == value2){     // Abfrage für den frequenz wechsel 500/700
      frq = 500;
    }else{
      frq = 700; 
    }
    value2 = !value2;       // dreht den schalter für frequenz wechsel
  tone(BuzzPin,frq);        // buzz on
}else{
  noTone(BuzzPin);          // buzz of
}   

}
}

danke euch

Einfach gesagt:
Du denkst noch nicht in Nebenläufigkeiten.

Darum bekommst du dein Programm auch noch nicht nebenläufig.

Hier mal deine vorherige Version, in etwa so wie ich sie für mich schreiben würde...
Die Hupe als eigene Task(nach meinem TaskModell)
Und den AlarmSchlager, so wie es hier im Forum häufig gemacht wird.

Der AlarmSchlager veranlasst alle 10 Sekunden ein kleines Hupkonzert, indem er dem Horn eine Nachricht sendet.

#include <TaskMacro.h>
// https://forum.arduino.cc/index.php?topic=415229



class Horn
{
  protected:
  const unsigned long freqHigh = 750; // Hz
  const unsigned long freqLow  = 500; // Hz
  unsigned long interval;
  byte hornPin;
  unsigned int zyklen;

  public:
  Horn(byte hornPin, unsigned long interval): hornPin(hornPin),interval(interval),zyklen(0) {}
  void update()
  {
    taskBegin();
    while(1)
    {
      // Start
      noTone(hornPin);

      taskWaitFor(zyklen);

      while(zyklen)
      {
          tone(hornPin,freqHigh);
          taskPause(interval);   
               
          tone(hornPin,freqLow);
          taskPause(interval);        

          zyklen--;
      }
    }
    taskEnd();
  }
  
  void addAlarmZyklen(unsigned int zyklen = 1)
  {
      this->zyklen += zyklen;
  }  
};


Horn horn(8,500);


void alarmSchlager()
{
  static unsigned long  previousMillis = 0;

  if (millis() - previousMillis > 10000) // alle 10 Sec
  {
     previousMillis = millis();
     horn.addAlarmZyklen(2); // anzahl Tonfolgen setzen 
  }
}

// -------------------------------------------

void setup() 
{
}


void loop() 
{
  horn.update();
  alarmSchlager();
}

Dein Fehler liegt in der for-Schleife in 'Led-Blinken'. Letzendlich hast Du da wieder ein delay() reinprogrammiert, in dem Du die Schleifenvariable erst hochzählst, wenn die Zeit abgelaufen ist. Dadurch blockierst Du hier wieder den Programmabllauf bis zum Ablauf der Zeiten - wie in delay().
Deine LedBlinken-Funktion kehrt erst nach dem gesamten Blinken wieder zurück. In der Zeit wird also der Buzzer gar nicht aufgerufen.
Es reicht nicht, die delays durch einen millis-Konstrukt zu ersetzten, der letztendlich das gleich macht wie delay. Der ganze Programmablauf muss auf 'blockadefrei' umgestellt werden.
Dazu eigenet sich auch der im Forum schon oft angesprochene 'endlcher Automat' (einfach mal danach suchen - es gibt einige Beiträge dazu )

N.B. Du solltest die angewöhnen, vernünftig einzurücken.

MicroBahner:
Dein Fehler liegt in der for-Schleife in 'Led-Blinken'. Letzendlich hast Du da wieder ein delay() reinprogrammiert, in dem Du die Schleifenvariable erst hochzählst, wenn die Zeit abgelaufen ist. Dadurch blockierst Du hier wieder den Programmabllauf bis zum Ablauf der Zeiten - wie in delay().
Deine LedBlinken-Funktion kehrt erst nach dem gesamten Blinken wieder zurück. In der Zeit wird also der Buzzer gar nicht aufgerufen.
Es reicht nicht, die delays durch einen millis-Konstrukt zu ersetzten, der letztendlich das gleich macht wie delay. Der ganze Programmablauf muss auf 'blockadefrei' umgestellt werden.
Dazu eigenet sich auch der im Forum schon oft angesprochene 'endlcher Automat' (einfach mal danach suchen - es gibt einige Beiträge dazu )

N.B. Du solltest die angewöhnen, vernünftig einzurücken.

gut das habe ich verstanden ohne die for schleife funktioniert der Sketch auch, die "endliche Automation" habe ich aber noch nicht verstand bzw. weiß nicht ob ich es richtig verstanden habe...

Mit einem solchen sketch frage ich immer wieder zustände aber und reagiere darauf dann mit funtionen usw.... beispiel ob ein button gedrück wurde und dann rufe ich die funtion BuzzAlert auf... oder ein sensor liefert einen wert und ich rufe den auf...
die Abfrage kommt in den loop und darin werden dann funktionen aufgerufen?

oder bin ich da auf dem Holzweg?

Christian

oder bin ich da auf dem Holzweg?

Ich verstehe dich nicht ganz...

Zumindest wirfst du 2 Sachen in einen Topf.

  1. Der endliche Automat
  2. Multitasking

Es ist schon wahr, dass beide häufig gemeinsam anzutreffen sind, aber das ist kein Muss.

Zu 1:
Der endliche Automat kommt immer zu seiner Rolle, wenn bestimmte Abläufe eingehalten werden wollen.

Zu 2:
Damit man 2 oder auch mehr Dinge quasi gleichzeitig erledigen kann

Zu 1+2:
In der Regel müssen viele Dinge parallel abgearbeitet werden. Die Kombination tritt also gerne in Rudeln auf.

Goldene Regel:
Jede Funktion sollte möglichst sofort zurückkehren, damit die anderen Funktionen auch ein Chance haben ihr Ding zu erledigen. Und das ist völlig unabhängig davon, ob diese Funktion einen endlichen Automaten abbildet/implementiert.

combie:
Goldene Regel:
Jede Funktion sollte möglichst sofort zurückkehren, damit die anderen Funktionen auch ein Chance haben ihr Ding zu erledigen. Und das ist völlig unabhängig davon, ob diese Funktion einen endlichen Automaten abbildet/implementiert.

Das ist das A&O wie man den Arduino dazu bringt, mehrere Dinge 'quasi gleichzeitig' zu tun.
Und ein endlicher Automat ist eine elegante Möglichkeit dies zu erreichen: Er prüft bei jedem Durchlauf, ob im momentanen Zustand gerade was zu tun ist, und wenn nicht beendet er sich sofort wieder.

In deinem Beispiel könnte man den Beeper und den Led-Blinker jeweils als (sehr einfachen :wink: ) endlichen Automaten realisieren, der bei jedem Durchlauf prüft, ob er nun gerade den Beeper bzw. die Led ein- oder ausschalten soll. Danach lässt er dann gleich wieder den anderen dran.

ich hoffe nichts das ihr die nerven mit mit verliert ich wollte jetzt zurst mal die endliche Maschiene verstehen und habe mich mal an eine eigene nachtwächter Version versucht

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
static unsigned long letzemalMillisLED = 0;
static unsigned long letzemalMillisBEEP = 0;
static int LedStatus = HIGH;
static int beepStatus = HIGH;
const int LedPin = 4;
const int beepPin = 8;
pinMode(LedPin, OUTPUT);
static int frqStatus = HIGH;
int frq = 500;

//###LED anaus
if(millis()-letzemalMillisLED >400){
  letzemalMillisLED = millis();
   // Serial.println("LED");
    //Serial.println(letzemalMillisLED);
      digitalWrite(LedPin, LedStatus);
        LedStatus = !LedStatus;
  }

//beep anaus
if(millis()-letzemalMillisBEEP >2000){
  letzemalMillisBEEP = millis();
    Serial.println("BEEP");
    Serial.println(letzemalMillisBEEP);
    Serial.println(frqStatus);
            if(frqStatus == HIGH){
              frq = 700;
            }else{
              frq = 500;
            }
      if(beepStatus == HIGH){
          Serial.println(frq);
        tone(beepPin,frq);
      }else{
        noTone(beepPin);
      }
     beepStatus = !beepStatus;
     frqStatus = !frqStatus;
}
}

der Sketch führt auch zwei verschiedene dinge auf einmal aus (Led blinken & beep) das einzige das nicht geht ist der wechsel der Frequenz da will er die else{} einfach nicht durchlaufen? Denkfehler?

if(frqStatus == HIGH){
              frq = 700;
            }else{
              frq = 500;
            }

@MicroBahner
mehr eingerückt dafür keine kommentare :slight_smile: beim nächsten mal beider, ich muss mal verstehen wie die IDE von alleine einrück bei schleifen und abfragen...

ChrisSand:
das einzige das nicht geht ist der wechsel der Frequenz da will er die else{} einfach nicht durchlaufen? Denkfehler?

Doch, er durchläuft den else-Zweig schon. Aber Du schaltest beepStatus und frqStatus immer gleichzeitig um. D.h. frq setzt Du immer dann auf 500, wenn Du gar keinen Ton ausgibst ...

Und die Einrückungen sollten schon auch zur Programmlogik passen. Du kannst die IDE deinen Sketch formatieren/einrückenlassen: Menü->Werkzeuge->Automatisch formatieren

Zusätzlich:

  1. Warum ist frqStatus ein int, obwohl du es doch als bool benutzen möchtest?
    Oder habe ich was übersehen?

if(frqStatus == HIGH){
              frq = 700;
            }else{
              frq = 500;
            }

Das ist gültig, aber tut mir in den Augen weh.. :smiling_imp:

Um solche Dinge abzuhandeln wurde der Ternary Operator erfunden.

frq = frqStatus?750:500;

:o Macht das gleiche :o

vielen dank ( schon wieder ::slight_smile: ),

jetzt habe ich es am laufen

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {

  static unsigned long letzemalMillisLED = 0;   //Letzte ausführung LED Bling wird beim überschreiben null und nicht in jedem loop neu gesetzt
  static unsigned long letzemalMillisBEEP = 0;  //Letzte ausführung LED Bling wird beim überschreiben null und nicht in jedem loop neu gesetzt
  static bool LedStatus = HIGH;                 //Led Status an oder aus
  static bool beepStatus = HIGH;                //Beep Status an oder aus
  const int LedPin = 4;                         // Pin der LED
  const int beepPin = 8;                        // Pin des Pioezo 
  pinMode(LedPin, OUTPUT);                      // Led Pin auf outputt
  static bool frqStatus = HIGH;                 // Status des hohen oder niedirgen frquens 
        

  //###LED anaus
  if (millis() - letzemalMillisLED > 200) {    // prüfen nach ober X (400) mSec seit der letzten ausführung um sind dann abfrage durchlaufen
    letzemalMillisLED = millis();              // neue letzte ausfürhung aufschreiben
    digitalWrite(LedPin, LedStatus);           // den Pin auf HIGH oder LOW Setzten (aus LedStatus)
    LedStatus = !LedStatus;                    // Status wechseln 
  }

  //beep anaus
  if (millis() - letzemalMillisBEEP > 200) {   // prüfen nach ober X (400) mSec seit der letzten ausführung um sind dann abfrage durchlaufen
    letzemalMillisBEEP = millis();             // neue letzte ausfürhung aufschreiben
    if (beepStatus == HIGH) {                  // Prüft ob er an oder aus schalten soll HIGH = an LOW = aus (else)
      tone(beepPin, frqStatus ? 950 : 700);    // wenn er anschalten soll dann am beepPin und nach dem frwStatus ( frgStatus ? 950 : 700 )
      frqStatus = !frqStatus;                  // Status Frequens wechseln
    } else {
      noTone(beepPin);                         // beepStatus ist LOW dann ausstelen
    }
    beepStatus = !beepStatus;                  // beepStatus wechseln
  }
}

die var. hab ich in bool geändert thx
super vielen dank für die kurze if abfrage das spart viel tipperei und fehler anfälligkeit mit den {}
Einrücken lassen hab ich diesmal das Programm und auch mal wieder was kommentiert

damit ist das jetzt eine endliche Maschiene? und ich habe dsa mit millis() richtig angewenden ? von verstehen will ich noch nicht sprechen dazu muss ich mal ein paar beispiele scripten.

jetzt noch zwei errausforungen oder doch Lernziele ?

  1. ich möchte wiessen wie ich im Loop etwas nur dreimal ausführen lasse ...
    ... mit if und einer static int variablen ?
  2. die ablauf des beep in eine funct packen damit ich das immer mal bei einem problem aufrufen kann
    ...lösung ?

Chris