Schleife nach zeitlicher Bedingung ablaufen lassen

Hello,

ich bin gerade an einem kleinen Programm bei, und das soll ein Geschenk werden.
Bin auch fast fertig aber ich will noch eine Funktion implementieren.
Durch ein Ultraschallsensor wird die Entfernung gemessen, so weit funktioniert es auch.

Ich möchte jetzt aber das eine Schleife wo z.B. LED´s nacheinander angesteuert werden, wenn der Ultraschallsensor für 10 Sekunden eine Entfernung von z.B. über 100 cm misst.

Wie gesagt: Entfernungsmessung klappt soweit, ich will nur wissen wie man das am besten schreibt, dass eine Schleife erst losrattert wenn die Entfernung über 10 Sekunden über 100 cm war.

Vielen Dank für eure Hilfe!

Flutschfinger:
Hello,

ich bin gerade an einem kleinen Programm bei, und das soll ein Geschenk werden.
Bin auch fast fertig aber ich will noch eine Funktion implementieren.
Durch ein Ultraschallsensor wird die Entfernung gemessen, so weit funktioniert es auch.

Ich möchte jetzt aber das eine Schleife wo z.B. LED´s nacheinander angesteuert werden, wenn der Ultraschallsensor für 10 Sekunden eine Entfernung von z.B. über 100 cm misst.

Wie gesagt: Entfernungsmessung klappt soweit, ich will nur wissen wie man das am besten schreibt, dass eine Schleife erst losrattert wenn die Entfernung über 10 Sekunden über 100 cm war.

Das solltest du noch einmal besser erklären, damit wir das auch verstehen.

Hi,

das hört sich für mich so an, daß Du ein retriggerbares Monoflop programmieren musst, und jedesmal wenn die 100cm überschritten werden Du die aktuelle Zeit mit millis() nimmst, und falls die 10s erreicht werden (mit gespeicherter Zeit vergleichen), dann ist die Bedingung erfüllt. Falls es nur 9s werden, dann von vorne anfangen.

Gruß André

SpaghettiCode:
Hi,

das hört sich für mich so an, daß Du ein retriggerbares Monoflop programmieren musst, und jedesmal wenn die 100cm überschritten werden Du die aktuelle Zeit mit millis() nimmst, und falls die 10s erreicht werden (mit gespeicherter Zeit vergleichen), dann ist die Bedingung erfüllt. Falls es nur 9s werden, dann von vorne anfangen.

Gruß André

so wollte ich es haben :wink:

kannst du mir auch bitte kurz erläutern wie man ein retriggerbares Monoflop programmiert? :smiley:

Du hast mit loop() schon eine Schleife. Mehr braucht also die braucht man nicht

vieleicht so verständlich?

direkt im loop():

WENN 
  Ultraschallsensor > 10cm UND ist_unter_10cm_flag == false
DANN 
  previousMillis = millis();
  ist_unter_10cm_flag = true;
SONST
  ist_unter_10cm_flag = false;


WENN 
  Ultraschallsensor unter 10cm UND ist_unter_10cm_flag == true
DANN
  WENN 
    millis()-previousMillis>10*1000
  DANN
    //tu deine Schleife ...

wenn du das in c++ umsetzt, solltest du in "//tu deine Schleife" fallen, sobald dein Sensor mindestens 10 Sekunden unter 10cm ist.

sinds nur 9, resettet sich das flag und er würde wieder von vorne zu warten beginnen.

Hallo,

meine Version wäre ... zum testen Poti an A3.

Bei "erfolgreich" bzw. bei case READY musste dann deine Wunschaktion ausführen lassen bzw. aufrufen.

/* 
 *  Doc_Arduino - german Arduino Forum
 *  IDE 1.8.5
 *  Arduino Mega2560
 *  24.04.2017
 */

typedef enum {TRIGGER, ZEIT, READY} state;    // Steuerzustände
state sens_MODE = TRIGGER;

unsigned int entfernung;  // ohne Debugging besser lokal machen

void setup() {
  Serial.begin(9600);
}  

 
void loop() {

  retrigger_Monoflop(700, 10000);     // Limit, Zeit[ms]              
  
  serieller_Monitor();
}


// *** Funktionen *** ----------------------------------------------

void retrigger_Monoflop (unsigned int abstand, unsigned int zeit)
{
  static unsigned long retrigger_time = 0;
  
  entfernung = analogRead(A3);  // ohne Debugging hier lokal machen

  switch (sens_MODE) {
    case TRIGGER:
                if (entfernung > abstand) {
                  sens_MODE = ZEIT;
                  retrigger_time = millis();
                  Serial.println(F("retrigger"));
                }
                break;
                
    case ZEIT:
                if (entfernung < abstand) {
                  sens_MODE = TRIGGER;
                  Serial.println(F("abbruch"));
                }  
                
                if (millis()-retrigger_time>zeit) {
                  sens_MODE = READY;
                }
                break;
                
    case READY:
                Serial.println(F("erfolgreich"));
                sens_MODE = TRIGGER;
                break;
                                    
    default:    sens_MODE = TRIGGER;
                break;
  }
  
}
  

void serieller_Monitor ()
{
  static unsigned int intervall = 500;
  static unsigned long last_millis = 0;

  if ( millis() - last_millis > intervall )  {    // aller x [ms] frische Daten
    last_millis = millis(); 
    Ueberschriftszeile();
    Serial.print(sens_MODE); Serial.print('\t');
    Serial.print(entfernung); Serial.print('\t');
    Serial.print(millis()/1000); Serial.print('\t');
    Serial.println();
  }  
}


void Ueberschriftszeile ()
{
  static int counter = 30;  // Initial Überhöhung

  counter++;
  
  if (counter<25) return;   // Zeilen noch nicht erreicht, Funktion abbrechen
  
  counter = 0; 
  Serial.print(F("MODE")); Serial.print('\t');
  Serial.print(F("Entf")); Serial.print('\t');
  Serial.print(F("Sek")); Serial.print('\t');
  
  Serial.println();
}

viel Spass beim testen

Hallo,

so noch besser, dann muss man nicht in der fertigen Monoflopfunktion rumfummeln.

/* 
 *  Doc_Arduino - german Arduino Forum
 *  IDE 1.8.5
 *  Arduino Mega2560
 *  24.04.2017
 */

typedef enum {TRIGGER, ZEIT, READY} state;    // Steuerzustände
state sens_MODE = TRIGGER;

unsigned int entfernung;  // ohne Debugging besser lokal machen

void setup() {
  Serial.begin(9600);
}  

 
void loop() {

  if (retrigger_Monoflop(700, 10000) == true) {     // Limit, Zeit[ms]  
    Serial.println(F("erfolgreich")); 
    // ... hier die Wunschaktion ausführen bzw. aufrufen
    // oder andere sinnvolle Dinge           
  }
  
  serieller_Monitor();                              // Debug
}


// *** Funktionen *** ----------------------------------------------

bool retrigger_Monoflop (unsigned int abstand, unsigned int zeit)
{
  bool state = false;
  static unsigned long retrigger_time = 0;
  
  entfernung = analogRead(A3);  // ohne Debugging hier lokal machen

  switch (sens_MODE) {
    case TRIGGER:
                if (entfernung > abstand) {
                  sens_MODE = ZEIT;
                  retrigger_time = millis();
                  Serial.println(F("retrigger"));   // Debug
                }
                break;
                
    case ZEIT:
                if (entfernung < abstand) {
                  sens_MODE = TRIGGER;
                  Serial.println(F("abbruch"));   // Debug
                }  
                
                if (millis()-retrigger_time>zeit) {
                  sens_MODE = READY;
                }
                break;
                
    case READY:
                sens_MODE = TRIGGER;
                state = true;
                break;
                                    
    default:    sens_MODE = TRIGGER;
                break;
  }

  return state;
}
  

void serieller_Monitor ()
{
  static unsigned int intervall = 500;
  static unsigned long last_millis = 0;

  if ( millis() - last_millis > intervall )  {    // aller x [ms] frische Daten
    last_millis = millis(); 
    Ueberschriftszeile();
    Serial.print(sens_MODE); Serial.print('\t');
    Serial.print(entfernung); Serial.print('\t');
    Serial.print(millis()/1000); Serial.print('\t');
    Serial.println();
  }  
}


void Ueberschriftszeile ()
{
  static int counter = 30;  // Initial Überhöhung

  counter++;
  
  if (counter<25) return;   // Zeilen noch nicht erreicht, Funktion abbrechen
  
  counter = 0; 
  Serial.print(F("MODE")); Serial.print('\t');
  Serial.print(F("Entf")); Serial.print('\t');
  Serial.print(F("Sek")); Serial.print('\t');
  
  Serial.println();
}

Hallo,

setze deinen Sketch bitte in die Code Tags. Nach Preview in der Leiste ganz links der </> Button.
Geht auch nachträglich mit Modify. Ggf. als neuer User nach einer kleinen Wartezeit.

int LED_M_LEFT=2;
int LED_M_MIDDLE=3;
int LED_M_RIGHT=4;

int LED_I_DOWN=13;
int LED_I_TOP=14;

int LED_A_1=7;
int LED_A_2=8;
int LED_A_3=9;
int LED_A_4=10;

int echo=11;
int trigger=12;

long zeit;

long dauer=0; //Das Wort daur ist jetzt eine Variable unter der die Zeit gespeichert wird, die eine Schallwelle bis zur Reflektion
              // und qzurück benötigt. Startwert ist hier 0.
long entfernung=0; //Das Wort entfernung ist jetzt die variable unter die die berechnete Entfernung gespeicher wird. 
                   // Info: Anstelle von "int" steht hier vor den beiden variablen "long". Das hat den Vorteil, dass eine größere Zahl
                   // gespeichert werden kann



void setup() {
  // put your setup code here, to run once:
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);
pinMode(LED_M_LEFT,OUTPUT);
pinMode(LED_M_MIDDLE,OUTPUT);
pinMode(LED_M_RIGHT,OUTPUT);

pinMode(LED_I_DOWN,OUTPUT);
pinMode(LED_I_TOP,OUTPUT);

pinMode(LED_A_1,OUTPUT);
pinMode(LED_A_2,OUTPUT);
pinMode(LED_A_3,OUTPUT);
pinMode(LED_A_4,OUTPUT);

millis();

zeit=10000;

}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(trigger,LOW); //Hier nimmt man die Spannung für kurze Zeut vom Trigger-Pin, damit man später beim senden des Trigger-Signale
                           // ein rauschfreies Signal hat
delay(5); //Dauer 5 ms
digitalWrite(trigger,HIGH); //jetzt sendet man ein Ultraschallwelle los
delay(10); //Dieser "TON" erklingt für 10 ms
digitalWrite(trigger,LOW); //Dann wird der "Ton" abgeschaltet
dauer = pulseIn(echo,HIGH); // mit dem Befehl "pulseIn" zählt der Mikrokontroller die Zeit in ms, bis der Schall zum Ultraschall zurückkehrt
entfernung = (dauer/2) * 0.03432; //Berechnung der Entfernung in cm (durch 2 wegen nur einem Weg und mal Schall in cm)


if (entfernung<=99)
{
digitalWrite(LED_M_LEFT,HIGH);
}
else
{
  digitalWrite(LED_M_LEFT,LOW);
}

if (entfernung<=90)
{
  digitalWrite(LED_M_MIDDLE,HIGH);
 }
 else
 {
  digitalWrite(LED_M_MIDDLE,LOW);
 }
if (entfernung<=80)
{
  digitalWrite(LED_M_RIGHT,HIGH);
}
else
{
  digitalWrite(LED_M_RIGHT,LOW);
}
if (entfernung<=70)
{
  digitalWrite(LED_I_DOWN,HIGH);
}
else 
{
  digitalWrite(LED_I_DOWN,LOW);
}
if (entfernung<=60)
{
  digitalWrite(LED_I_TOP,HIGH);
}
else
{
  digitalWrite(LED_I_TOP,LOW);
}
if (entfernung<=50)
{
  digitalWrite(LED_A_1,HIGH);
}
else
{
  digitalWrite(LED_A_1,LOW);
}
if (entfernung<=40)
{
  digitalWrite(LED_A_2,HIGH);
}
else
{
  digitalWrite(LED_A_2,LOW);
}
if (entfernung<=30)
{
  digitalWrite(LED_A_3,HIGH);
}
else
{
  digitalWrite(LED_A_3,LOW);
}
if (entfernung<=20)
{
  digitalWrite(LED_A_4,HIGH);
}
else
{
  digitalWrite(LED_A_4,LOW);
}


if(entfernung>=99)
{
  digitalWrite(LED_M_LEFT,HIGH);
  delay(1000);
  digitalWrite(LED_M_LEFT,LOW);
  digitalWrite(LED_M_MIDDLE,HIGH);
  delay(1000);
  digitalWrite(LED_M_MIDDLE,LOW);
  digitalWrite(LED_M_RIGHT,HIGH);
  delay(1000);
  digitalWrite(LED_M_RIGHT,LOW);
  digitalWrite(LED_I_DOWN,HIGH);
  delay(1000);
  digitalWrite(LED_I_DOWN,LOW);
  digitalWrite(LED_I_TOP,HIGH);
  delay(1000);
  digitalWrite(LED_I_TOP,LOW);
  digitalWrite(LED_A_1,HIGH);
  delay(1000);
  digitalWrite(LED_A_1,LOW);
  digitalWrite(LED_A_2,HIGH);
  delay(1000);
  digitalWrite(LED_A_2,LOW);
  digitalWrite(LED_A_3,HIGH);
  delay(1000);
  digitalWrite(LED_A_3,LOW);
  digitalWrite(LED_A_4,HIGH);
  delay(1000);
  digitalWrite(LED_A_4,LOW);

}
}

Hallo,

deine vielen Tausenden Entfernungsabfragen machste besser mit switch case. Sollte theoretisch nicht flackern.

alle Leds ausschalten;
switch (entfernung) {
    case     0 ...  9: Led schalten; break;
    case    10 ... 19: Led schalten; break;
    case    20 ... 29: Led schalten; break;
    case    30 ... 39: Led schalten; break;
    default:           break;
  }

zum restlichen Code, der ist wirklich nicht schön, tausende delays drin, so wird das nie was.
Beschäftige dich bitte erstmal mit millis() um die blockierenden delays los zu werden.
Dann schreibste die LED Spielerei für größer 99 in eine Funktion.

Theseus erklärt millis()
http://forum.arduino.cc/index.php?topic=400102.msg2752141#msg2752141

GuntherB - BlinkwithoutDelay - Die Nachtwächtererklärung
http://forum.arduino.cc/index.php?topic=423688.0

Danke dir!

Ich bin noch ein ziemlicher Anfänger und muss da noch einiges zulernen :wink:

Hallo,

das ist mir bzw. uns schon klar ;), deswegen meine Empfehlung, dass Vorhaben in Teilprobleme zerlegen, testen und verstehen lernen und am Ende alles zusammenfügen. Irgendwann wirst du dann mein Monoflop Bsp. verstehen oder schreibst dein eigenes oder ...
Um millis() zu spielen vielleicht ein Blinklicht oder Lauflicht programmieren oder ...
In der IDE gibts auch Bsp.

Flutschfinger:
so wollte ich es haben :wink:

kannst du mir auch bitte kurz erläutern....

Ach und danke auch, dass du es für alle noch besser verständlich erklärt hast.

Hallo,

wegen der Entfernungsanzeige per Einzel-LED, weil es gerade Spass macht.
Bsp. mit Poti am analogen Eingang.
Mehr mach ich nun nicht. :slight_smile:
Wenn du das getestet und nachvollziehen kannst, kannste das für deine Zwecke leicht übernehmen und anpassen.

/*
  Doc_Arduino - german Arduino Forum
  IDE 1.8.5
  Arduino Mega2560
  25.04.2018

  Je nach Wertebereich eine bestimmte LED einschalten und alle anderen ausschalten.
  Ein wandernder Punkt oder wie man das nennen möchte.
*/

const byte pinLED[] = {30,31,32,33,34};       
byte sum_led;


void setup()
{ 
  sum_led = sizeof(pinLED)/sizeof(pinLED[0]);
    
  for (byte i=0; i<sum_led; i++) {
    digitalWrite(pinLED[i], LOW);
    pinMode (pinLED[i], OUTPUT);
  }
}


void loop()

{
  Einzel_LED( analogRead(A2) );
}


//  einzelne LEDs schalten
void Einzel_LED (unsigned int entfernung)
{  
  byte Led_Nr = 0;
  
  /*
  switch (entfernung) {
    case    0 ...  199: Led_Nr=0; break;
    case  200 ...  399: Led_Nr=1; break;
    case  400 ...  599: Led_Nr=2; break;
    case  600 ...  799: Led_Nr=3; break;
    case  800 ... 1023: Led_Nr=4; break;
    default:                      break;
  }
  */
  
  Led_Nr = map(entfernung, 0, 1024, 0, sum_led);  // beide eigentlichen MAX Werte um eins erhöhen
    
  for (byte i=0; i<sum_led; i++) {
    if (Led_Nr != i) {
      digitalWrite(pinLED[i], LOW);
    }  
    else {
      digitalWrite(pinLED[i], HIGH);
    }
  }
}