funtion ausfürhung Fehler

Hallo zusammen,

Mein Name ist Christian ich komme aus dem nähe von Düsseldorf und beschäftige mich seit einem Geburtstags Geschenk mit dem Thema Adruino.
Ich bin noch etwas frisch im Arduino Thema, ich habe bis dato nur VBA Programmiert und diverse E-Bausätze verbaut/bastelt.
Ich habe aus dem StarterKid einige Schaltungen nachgebaut die auch allesamt funktioniert haben, jetzt möchte ich mich mit der Programmierung beschäftigen. Ich möchte die Codes so einfach wie möglich halten und deswegen einige dinge wie das blinken und Meldungen in Funktionen packen (die dann auch in eine eigene Libraries (Vielleicht hat noch wer einen link wo da beschrieben ist eine eigene Libraries zu schrieben?)

Ich denke mein Problem ist eher etwas logisches und ich verstehe die Programmierung des Sketch noch nicht richtig ( Das mit dem dauerhaften Loop ist schon gewöhnungbedürftig ist man es von VBA doch gewohnt immer auf eine Usereingabe oder einen Klick zu reagieren), ich habe zwei Funktionen geschrieben die ich gerne verwenden möchte das beepAlert() funktioniert auch schon nur wenn ich blinkenLED() ausführe wird die LED nicht mehr ausgeschaltet sondern bleibt während des beepAlter() an.
was mache ich falsch?

// setupCode
void setup() {
}
// start codeloop
void loop() {
beepAlert(2); //Funktion aufrufen
delay(2000); //2sec wait
LEDblinken(3); //Funktion aufrugen
delay(4000); // 2sec wait
}
// start functioncode
void beepAlert(int buzzPin){ //gibt am übergeben Pin einen Alarm ab
  for(int i=0;i<3;i++){  
tone(buzzPin,500);
delay(1000);
tone(buzzPin,700);
delay(1000);
noTone(buzzPin);}
}
void LEDblinken(int blinkenPin){  // lässt eine LED am übergenen Pin leuchten
  pinMode(blinkenPin, OUTPUT);
  digitalWrite(blinkenPin, HIGH);
  delay(50);
  digitalWrite(blinkenPin, LOW);
  delay(50); 
}

Danke
Christian

Beide Funktionen blockeren den Sketch.

Laß das Blinken im loop() und verwende millis() für die Zeiten.

Grüße Uwe

(die dann auch in eine eigene Libraries (Vielleicht hat noch wer einen link wo da beschrieben ist eine eigene Libraries zu schrieben?)

Klar!

Danke Combi.

danke Uwe... jetzt habe ich millis() gelesen (und hoffentlich verstanden) wenn ich das Blinken jetzt im Loop{} mache und das buzzAlert über eine Funktion aufrufe stoppt er natürlich das Blinken :frowning: Klar den delay() unterbricht ja den Code.
Geht Millis() nicht in Funktionen? habe das jetzt noch nicht ausprobiert wollte zuert das buzzAlert mit Mills() lösen damit der nicht immer unterbricht :slight_smile:

    byte blinkenPin = 3;                  // LED liegt am (digitalen) Pin 13
    boolean value = LOW;                  // Startwert der LED
    unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
    unsigned long interval = 1000;    // Interval zwischen zwei Änderungen
    int anzahlBlink = 10; // Anzahl der Blink vorgänge
    
     
    void setup()
    {
      pinMode(blinkenPin, OUTPUT);      // Setzt den ledPin (Pin 3) als Ausgang
      Serial.begin(9600);
    }
     
    void loop()
    {
        if (millis() - previousMillis > interval) {
        previousMillis = millis();   // aktuelle Zeit abspeichern
        Serial.print(anzahlBlink);
      
        // LED Zustand wecheln.
        value = !value;
        
        digitalWrite(blinkenPin, value); // Wert auf den Ausgang schreiben
          }
          beepAlert(2);
      }

    void beepAlert(int buzzPin){ //gibt am übergeben Pin einen Alarm ab
  for(int i=0;i<3;i++){  
tone(buzzPin,500);
delay(1000);
tone(buzzPin,700);
delay(1000);
noTone(buzzPin);}
}

Geht Millis() nicht in Funktionen?

Natürlich geht das.

Das mit dem dauerhaften Loop ist schon gewöhnungbedürftig

Stimmt! Gilt natürlich auch für Funktionen. Vergiss doch erstmal einfach die Funktion delay(), und loop() sowie die darin aufgerufenen Funktionen wird keine Zeit brauchen und dafür unendlich oft drankommen (fast, jedenfalls)

Gibt noch mehr Sachen, die eine Verzögerung eingebaut haben, und nur verwendet werden sollten, wenn man das weiss und es einem egal ist. (tone() gehört nicht dazu)

Mindestens so wichtig wie die Funktion millis() ist natürlich die zugehörige Vergleichsvariable. Da brauchst du für jede der gleichzeitig laufenden Aktionen eine eigene. Erst wenn dir das klar ist, hast du BlinkWithoutDelay verstanden.

millis() funktioniert auch in Funktionen. Damit Du aber kontrollieren kannst ob die Zeit verstrichen ist und etwas gemacht werden muß mußt Du die Funktion dauernd aufrufen. Da kann der Code auch in der loop() bleiben.

Basic läuft ja auch nur einmal durch und nach Ausführung aller Befehle wird es geschlossen. Da ist C nicht anders. Da im Microcontroller des Arduino (außer dem Bootloader der nur beim Einschalten aktiv ist und Interruptroutinen die über ein Ereignis gestartet werden) nichts anderes als Dein Sketch ist, der abgearbeitet wird kann das progeamm nicht irgendwann mal fertig sein. Es muß eine schleife geben damit der Microkontroller immer was zu arbeiten hat.

Grüße Uwe

michael_x:
Natürlich geht das.
Stimmt! Gilt natürlich auch für Funktionen. Vergiss doch erstmal einfach die Funktion delay(), und loop() sowie die darin aufgerufenen Funktionen wird keine Zeit brauchen und dafür unendlich oft drankommen (fast, jedenfalls)

Gibt noch mehr Sachen, die eine Verzögerung eingebaut haben, und nur verwendet werden sollten, wenn man das weiss und es einem egal ist. (tone() gehört nicht dazu)

Mindestens so wichtig wie die Funktion millis() ist natürlich die zugehörige Vergleichsvariable. Da brauchst du für jede der gleichzeitig laufenden Aktionen eine eigene. Erst wenn dir das klar ist, hast du BlinkWithoutDelay verstanden.

thx. Ich glaube ich werde es erst mal wieder ohne funktion versuchen mit Millis() wenn ich das richtig verstanden habe mit der vergleich variablen speichere ich ihn ihr das letzte mal wenn etwas ausgeführt worden ist und vergleiche das dann immer wenn das größer ist als Millis()-Interval soll er einen Code ausführen. 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.

edit:die logik noch mal geändern mit der if Schleife für millis()

uwefed:
millis() funktioniert auch in Funktionen. Damit Du aber kontrollieren kannst ob die Zeit verstrichen ist und etwas gemacht werden muß mußt Du die Funktion dauernd aufrufen. Da kann der Code auch in der loop() bleiben.

okay in das leuchtet mit ein, also lieber eine gute strucktur mit der ich das visualisiert bekomme

uwefed:
Basic läuft ja auch nur einmal durch und nach Ausführung aller Befehle wird es geschlossen. Da ist C nicht anders. Da im Microcontroller des Arduino (außer dem Bootloader der nur beim Einschalten aktiv ist und Interruptroutinen die über ein Ereignis gestartet werden) nichts anderes als Dein Sketch ist, der abgearbeitet wird kann das progeamm nicht irgendwann mal fertig sein. Es muß eine schleife geben damit der Microkontroller immer was zu arbeiten hat.

Grüße Uwe

So langsam blicke ich das, deswegen sehe ich immer so wenige Funktionen sondern viel im LOOP stehen... da muss ich mich mal drann gewöhnen.
chris

deswegen sehe ich immer so wenige Funktionen sondern viel im LOOP stehen...

Bitte nicht das falsche lernen!

Wurstbildung in loop() ist unübersichtlich
Es muss nicht alles in loop() gepfercht werden.

Man kann in loop() auch Funktionen aufrufen.
Muss dann aber dafür Sorge tragen, dass sie möglichst schnell wieder verlassen werden, sollten also möglichst kein delay() enthalten.

So langsam blicke ich das, deswegen sehe ich immer so wenige Funktionen sondern viel im LOOP stehen... da muss ich mich mal drann gewöhnen.

Das ist eher ein schlechter Programmier Stil wenn es sich um ein längeres Program handelt. Es hindert dich nichts daran Dinge in Funktionen auszulagern und diese in loop() aufzurufen

edit:die logik noch mal geändern mit der if Schleife für millis()

If Schleife

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....