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.
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 ) 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...
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
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
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 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
}
}
}
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.
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?
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 ) 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?
@MicroBahner
mehr eingerückt dafür keine kommentare 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
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 ?
ich möchte wiessen wie ich im Loop etwas nur dreimal ausführen lasse ...
... mit if und einer static int variablen ?
die ablauf des beep in eine funct packen damit ich das immer mal bei einem problem aufrufen kann
...lösung ?