Access denied. You must login to view this page.

Blink without delay modifizieren

vor 49 weeks 4 days von Jumbo

Hallo an alle Arduino Freaks,
bin völlig neu in der Szene, weil sich mein Projekt nur mit Hilfe eines Arduinos realisieren lässt.
Ich möchte über einen digitalen Ausgang eine gezeitete Schaltung, ähnlich des
"Blink without delay" Sketches vornehmen,
Allerdings möchte ich nicht nur die On-Zeit kontrollieren können, sondern auch die Off-Zeit.
Außerdem soll der Loop erst beginnen, wenn ein Hall-Sensor mir einen digitalen Eigang auf HIGH
geschaltet hat.
Weiter möchte ich den Zeitpunkt, zu dem der Loop beginnt auch kontrollieren, sowie die Häufigkeit
des On-Off Vorgangs, während der Hall den Eingang auf High schaltet ( ca 50 Microsec.).
Da der Arduino dieses Spiel mit weiteren Ausgängen treiben soll, geht das nicht über die delay()
Funktion.
Ich habe mir nun schon tagelang die Zähne ausgebissen und bekomme trotz vielem Lesen das Problem
nicht gelöst.
Es gibt doch bestimmt jemanden, der mir hier weiterhelfen kann.
Viele Arduino-Grüße
Jumbo

Ähnliche Posts

13 Antworten auf “Blink without delay modifizieren”


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
  1. Jumbo sagt:

    Sorry, Tippfehler, der Hall hält den Ausgang nicht für 50 Microsec., sonder für 50 Millisec. auf HIGH.

    Login or register to post comments

  1. chrimbo sagt:

    Zeig mal was du bisher hast

    Login or register to post comments

  1. Jumbo sagt:

    Danke für das Interesse,

    folgender Sketch funktioniert mit dem delay() Befehl:

    int k;
    boolean Hall_an;

    void setup()
    {
    pinMode( 2 , INPUT);
    Hall_an = false;
    pinMode( 12 , OUTPUT);
    pinMode( 13 , OUTPUT);
    }

    void loop()
    {
    Hall_an = digitalRead( 2) ;
    if (Hall_an)
    {
    digitalWrite( 13 , HIGH );
    for (k=0; k< ( 10 ); ++k )
    {
    delayMicroseconds( 5000 );
    digitalWrite( 12 , HIGH );
    delayMicroseconds( 1500 );
    digitalWrite( 12 , LOW );
    delayMicroseconds( 10000 );
    }

    }
    else
    {
    digitalWrite( 13 , LOW );
    }
    }

    nun möchte ich das Ganze statt delay() mit micros() schreiben.

    Jumbo

    Login or register to post comments

  1. chrimbo sagt:

    und das kennst du?
    http://arduino.cc/en/Tutorial/BlinkWithoutDelay

    loop(){
    hallan=digread...
    if(!hallan)
      cmil = millis();
    else
    {
      counter += millis()-cmil;
      if(counter>5000&&counter<6000)
        ledan;
      else if (counter>6000&&counter<7000)
        ledaus;
      else if (counter>=7000)
        counter = 0;
    }
    }

    kp ob das klappt. Aber müsste zumindest eine LED nach 5sekunden einschalten, nach einer weiteren aus und dann von vorne beginnen.
    Aber alles ohne Gewähr. Ist nur ein Ansatz. Vllt reicht es als Denkanstoß

    Login or register to post comments

  1. Jumbo sagt:

    Super, vielen Dank!
    Ich werde das gleich mal probieren.
    Als Denkanstoß taugt das auf jeden Fall!
    Jumbo

    Login or register to post comments

  1. Jumbo sagt:

    So,habe probiert und den Denkanstoß weiter ausgebaut.
    Funzt schon mal ganz gut.
    Hier meine Version:

    boolean Hall_an; // definiert die Variable "Hall_an"
    long cmil = 0; // definiert die Variable "cmil"
    long counter = 0; // definiert die Variable "counter und setzt sie auf den Anfangswert "0"
    const int Puls = 12; // definiert die Varialble "Puls"
    int PulsState = LOW; // definiert die Variable "PulsState" und setzt deren Eigenschaft und somit den Pin12 anfangs auf LOW

    void setup()
    {
    pinMode( 2 , INPUT); // setzt Pin2 auf Input vom Hall
    Hall_an = false; // setzt "Hall_an" anfangs auf "aus"
    pinMode(Puls, OUTPUT);
    pinMode(13, OUTPUT);
    }

    void loop()
    {
    Hall_an = digitalRead( 2) ; // liest den Zustand am Pin2
    digitalWrite(Puls, PulsState); // übergibt den Zustand von "PulsState" der Variablen "puls"

    if(Hall_an)

    cmil = micros(); // startet das Hochzählen der Variablen "cmil"
    else

    counter = micros(); // startet das Hochzählen der Variablen "counter"
    //digitalWrite(13, HIGH);
    counter += micros()-cmil; //??????????????????????????????????????????????????
    if(counter>0&&counter<2550) // setzt das Zeitfenster für Pin12 HIGH
    PulsState = HIGH;
    //digitalWrite(13, HIGH);
    else if (counter>2500&&counter<2850) // setzt das Zeitfenster für Pin12 LOW
    PulsState = LOW;
    else if (counter>=2850) //läßt den Ein- Ausschaltvorgang von vorne beginnen
    counter = 0;
    //digitalWrite(13, LOW);

    if(!Hall_an)
    PulsState = LOW; // unterbricht den Prozess, bis der Hall den Pin2 wieder auf HIGH schaltet
    }

    Ich habe mal meine Kommentare hinzugefügt, so wie ich die Sache verstehe.
    Vielleicht kannst du mir die Zeile mit den ??????????? mal genau erklären.

    Allerdings verstehe ich auch Folgendes nicht:
    Wenn, wie in o.g. Beispiel der Pin12 für 2550 micros auf HIGH gesetzt wird, warum zeigt
    mir mein Oszilloscop dann 50 Millisekunden an?
    Bei der delay() Variante decken sich die Werte mit dem Oszi.

    Außerdem bleibt der Prozess nach ca. 45Min stehen, offensichtlich wegen Overflow.
    Wie bekommt man den im Sketch resettet?

    Danke noch mal, hat mich erheblich weitergebracht!
    Jumbo

    Login or register to post comments

  1. chrimbo sagt:

    Hi

    counter = micros(); // startet das Hochzählen der Variablen "counter"

    das darf da nicht stehen.
    und in Setup könnte ein counter = 0 helfen

    wenn das läuft können wir an das 45Min Problem gehen

    Login or register to post comments

  1. Jumbo sagt:

    Tja,
    sobald ich counter = micros(); entferne, läuft die Schleife nicht mehr.
    Dieser Befehl scheint absolut nötig zu sein, aber warum?
    Hätte dir grundsätzlich zugestimmt.

    Jumbo

    Login or register to post comments

  1. Jumbo sagt:

    So, ein Problem gelöst, und das Nächste eingefangen:
    mein letzter Kommentar hat sich erübrigt und du hattest Recht, wenn das Programm wie folgt
    geändert wird:

    ------------------------------------------------------------------------------

    boolean Hall_an; // definiert die Variable "Hall_an"
    long cmil = 0; // definiert die Variable "cmil"
    long cmic = 0; // definiert die Variable "cmic"
    long counter = 0; // definiert die Variable "counter" und setzt sie auf den Anfangswert "0"
    long counter_a = 0; // definiert die Variable "counter_a" und setzt sie auf den Anfangswert "0"
    const int Puls = 12; // definiert die Varialble "Puls"
    const int Trig = 11; // definiert die Variable "Trig"
    int PulsState = LOW; // definiert die Variable "PulsState" und setzt deren Eigenschaft und somit den Pin12 anfangs auf LOW

    int TrigState = HIGH; // definiert die Variable "TrigState" und setzt deren Eigenschaft und somit den Pin11 anfangs auf HIGH

    void setup()
    {
    pinMode( 2 , INPUT); // setzt Pin2 auf Input vom Hall
    Hall_an = false; // setzt "Hall_an" anfangs auf "aus"
    pinMode(Puls, OUTPUT);
    pinMode(13, OUTPUT); // schaltet die Kontroll LED auf dem Board
    pinMode(Trig, OUTPUT);
    counter = 0;
    counter_a = 0;
    }

    void loop()
    {
    Hall_an = digitalRead( 2) ; // liest den Zustand am Pin2
    digitalWrite(Puls, PulsState); // übergibt den Zustand von "PulsState" der Variablen "puls"
    digitalWrite(Trig, TrigState); // übergibt den Zustand von "TrigState" der Variablen "Trig"

    if(Hall_an) {
    cmil = micros(); // startet das Hochzählen der Variablen "cmil"

    //digitalWrite(13, HIGH); // Option, um anhand der Board LED zu sehen, ob der Hall an oder aus ist
    counter += micros()-cmil; //setzt den Counter auf die Zeit, die vergangen ist seit Programmstart Minus der des Startens von "cmil"
    }

    if(counter>0&&counter<3100) { // setzt das Zeitfenster für Pin12 HIGH
    PulsState = HIGH;
    }
    else if (counter>3100&&counter<3300) { // setzt das Zeitfenster für Pin12 LOW
    PulsState = LOW;
    }
    else if (counter>=3300) { //läßt den Ein- Ausschaltvorgang von vorne beginnen
    counter = 0;
    //digitalWrite(13, LOW);
    }
    if(!Hall_an) {
    PulsState = LOW; // unterbricht den Prozess, bis der Hall den Pin2 wieder auf HIGH schaltet
    //digitalWrite(13, LOW);
    }

    if (Hall_an||!Hall_an) { // Bedingung für zweiten Timer der unaghängig von "Hall_an" arbeitet, aber den Zeitzähler vom ersten "Hall_an) verwendet
    TrigState = HIGH;
    cmic = micros();

    counter_a += micros()-cmic;
    }

    if (counter_a>4000&&counter_a<4400) {
    TrigState = LOW;
    }
    else if (counter_a>=4400&&counter_a<4800) {
    TrigState = HIGH;
    }
    else if (counter_a>=4800);{
    counter_a = 0;
    }

    }
    ------------------------------------------------------------------------------------

    nun möchte ich einen zweiten Timer laufen lassen z,B. über Ausgang Pin11, wie oben ersichtich,
    aber egal welchen Pin ich ansteuern möchte, keiner reagiert auf den Befehl.
    Da dies nun absolutes Basiswissen ist, bin ich um so mehr verwundert.
    Brauche dringend weitere Hilfe.

    nochmal danke, ich habe viel gelernt!
    Jumbo

    Login or register to post comments

  1. chrimbo sagt:

    Hey du :)
    Ich hab immer recht :) spaß

    if(Hall_an||!Hall_an)

    das ist wie if(True), gibt also keinen Sinn. Schmeiß das If weg.

    TrigState = HIGH;

    innerhalb deiner unnötigen if Abfrage macht dir die Sache kaputt. Schätze ich.

    übrigens

    if(Hall_an) {
    cmil = micros(); // startet das Hochzählen der Variablen "cmil" 
    counter += micros()-cmil;

    bist du dir da sicher, dass counter überhaupt erhöht wird? Für ziemlich kleine Zeiten sieht mir das nach counter += 0 aus
    probier das mal anders herum:)
    counter += micros()-cmil;
    cmil = micros();

    oben übrigens genauso. bloß solltest du dann in setup cmil und cmic auf micros() initialisieren

    Login or register to post comments

  1. Jumbo sagt:

    Hi,
    erstmal vielen Dank für deine Mühe.
    Aber diesmal liegst du wohl doch falsch:
    Der Fehler lag genau dort,wo du vorschlägst cmil und cmic auf micros() zu initialisieren.
    Der Aufruf micros() lässt sich nämlich nur einer Variablen zuordnen.
    Als ich cmic gelöscht habe und counter_a ebenfalls über cmil definiert habe, lief das Prgramm und
    Pin11 ließ sich ansteuern.
    Macht, wenn ich bislang alles richtig verstanden habe,ja auch Sinn. Denn der Arduino fängt genau dann an die Zeit von Null bis Anschlag(overfow) hochzuzählen, wenn im Programm erstmalig der Aufruf micros() erfolgt. Wenn man nun damit arbeiten möchte, muss dessen aktueller Wert einer Varialblen gleichgesetzt werden und das kann logischer Weise nur eine einzige sein.
    Sollte ich hier falsch liegen, dann muss ich wohl wieder ganz von vorne anfangen, weil ich mir ja auf Dauer nicht alles vorbeten lassen möchte, sondern selbst verstehen will.
    Ich denke schon, dass der counter hochzählt, denn sonst würde der Programmablauf ja nicht genau
    auf die gewollten Zeiten reagieren, ob micros oder millis ist doch völlig egal, solange die Taktfrequenz des Prozessors noch mitkommt.
    Aber ich frage mich nun, warum die counter-Schleife nicht unendlich in die Runde läuft, bevor wieder eine Hall_an Abfrage kommt.
    Ich muss nämlich, um mehrere Pulse während der Hall_an Phase zu bekommen, mit zusätzlichen Timerzeilen arbeiten.
    Muss hier evtl. eine "for Schleife" programmiert werden?
    Ich habe noch viel zu lernen, aber es stellen sich schon kleine Erfolge ein, auch wenn
    sie durch Probieren und viel Zeitaufwand erreicht werden müssen.
    Aber nochmal, du hast mir zweifelsfrei weiter geholfen und kannst mir vielleicht auch noch mehr Tips geben.
    Da es sich bei meinem Projekt um die Steuerung eines großen Brushless Motors handelt, wäre es in
    in einem weiteren Schritt nötig, die Drehzahl zu erfassen, oder die Frequenz des Hall_an Impulses, um dann widerum mittels einer Variablen und einer Formel die nun manuell eingestellten Zeiten automatisch anzupassen, da diese sich ja bei unterschiedlichen Drehzahlen ändern.

    Vielleicht hast du ja Lust, mir auch dabei zu helfen?

    Also bis dann und Danke
    Jumbo

    Login or register to post comments

  1. chrimbo sagt:

    Hi,

    nein, micros() und millis() zählen schon vorher. Und man kann sie auch verschiedenen Variablen zuweisen. Das ist eigentlich kein Problem. Ich wollte dich auch nur zum selbstdenken anregen. Die meiner Meinung nach optimale Lösung (zumindest mit Verwendung von micros oder millis) sieht in etwa wie folgt aus:

    unsigned int dt;    // Wichtig: Muss unsigned sein, sonst gibt es nach 45minuten (?) ein Problem :)
    unsigned long cmic;
    unsigned (jenachtyp) mytime1, mytime2;
     
    void setup()
    {
    	/*
    	 *  Variablen initialisieren
    	 */
    	cmic = micros();
    	...
     
    }
     
    void loop()
    {
    	/*
    	 *  Vergangene zeit updaten
    	 */
    	dt = micros() - cmic;
    	cmic = micros();
     
    	/*
    	 *  Action 1
    	 */
    	if(Hall...)
    	{
    	  mytime1 += dt;
    	  if(mytime1>xxx&&mytime1<yyy)
    	  {
    	    do_something;
    	  }
    	  else if (...)
    	  {
    	    undo_something;
    	  }
    	}
     
    	/*
    	 *  Action 2
    	 */
    	mytime2 += dt; // das ist das Selbe dt, daran wird nichtsmehr gemacht!
    	if(mytime2>uuu&&mytime2<vvv)
    	{
    	  do_anything;
    	}
    	else...
     
    }

    Das müsste ganz brauchbar funktionieren, solange die Zeitscheiben (uuu-vvv und xxx-yyy) nicht zu klein sind.

    Login or register to post comments

  1. Jumbo sagt:

    Super, danke,
    werde ich testen und dann berichten. Kann dieses Mal aber ein paar Tage dauern.
    Jumbo

    Login or register to post comments