- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 28

Thema: Teensy 3.2 +++ Interrupt, Übergabeparameter

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    56
    Beiträge
    2.211
    Mach das nicht.
    Das geht ganz schnell schief.
    Nimm dir irgendeine Variable, die innerhalb der ISR geändert wird- nichts weiter.
    Alles andere (z.B. die Variable auswerten, dass sie erst ab dem 30. Mal zählt (Entprellung für Arme, einfach, reicht aber oft) mach ausserhalb.

    Wenn du sicher gehen wllst, dann mach in der ISR folgendes:

    -Interrupts deaktivieren
    -tun, was zu tun ist
    -Interrupts aktivieren

    So stellst du sicher, dass innerhalb der ISR kein Interrupt ausgelöst wird- das nämlich ist das Problem mit ISR's.
    Wenn dir sowas passiert, wird die ISR aufgerufen, während sie noch läuft...du kannst dir denken, wie _das_ endet.
    Grüssle, Sly
    ..dem Inschenör ist nix zu schwör..

  2. #2
    HaWe
    Gast
    Nimm dir irgendeine Variable, die innerhalb der ISR geändert wird- nichts weiter.
    Alles andere (z.B. die Variable auswerten, dass sie erst ab dem 30. Mal zählt (Entprellung für Arme, einfach, reicht aber oft) mach ausserhalb.
    genau, und Variable, die innerhab einer ISR geändert werden, sollten wieder global deklariert werden und volatile sein.
    Geändert von HaWe (22.11.2019 um 12:05 Uhr)

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Zitat Zitat von Rabenauge Beitrag anzeigen
    -Interrupts deaktivieren
    -tun, was zu tun ist
    -Interrupts aktivieren
    DANKE - toller Hinweis!
    Genau darüber hatte ich mir auch schon Gedanken gemacht.
    noInterrupts(), interrupts() ist die Lösung!
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Rabenauge Beitrag anzeigen
    -Interrupts deaktivieren
    -tun, was zu tun ist
    -Interrupts aktivieren
    Vorsicht, das geht in die Hose.

    Von vorne mal angefangen. Das Deaktivieren des Interrupts am Anfang ist nicht das erste, was im Interrupthandler passiert. Da laufen noch ein Dutzend oder mehr Assemblerbefehle vorher ab, wie Status und Register retten. Wenn dort der Interrupt nicht automatisch gesperrt wäre, würde der Interrupt sofort wieder zuschlagen, da das Interruptflag noch nicht gelöscht ist. Der Interrupt muß also noch vor dem ersten Assemblerbefehl gesperrt werde, und das geht nur, wenn es automatisch passiert. Und so ist es auch. Beim Eintritt in den Interrupthandler ist mindestens dieser interrupt gesperrt. Den Interrupt im Handler zu deaktivieren ist zwar nicht unbedingt schädlich aber überflüssig und käme auch viel zu spät.

    Das Aktivieren ist aber schlecht. Zwischen dem letzten C-Befehl und dem Ende der Funktion wird das, was am Anfang des Handlers gesichert wurde, wiederhergestellt. Das sind nochmal ein Dutzend oder mehr Befehle. Die laufen jetzt mit offenen Interrupts und das ist gefährlich. Erst ganz am Ende, wenn der Prozessor den Interruptkontext verlassen hat, dürfen die Interrupte wieder zugelassen werden. Daher endet ein Interrupthandler auch nicht mit einem Return (from Subroutine) sondern einem Return from Interrupt. Das heißt häufig RETI. Der stellt den Interrupstatus wieder so ein, wie er vor dem Interrupt war.

    MfG Klebwax
    Geändert von Klebwax (23.11.2019 um 19:42 Uhr)
    Strom fließt auch durch krumme Drähte !

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Kann sein, aber wie macht man´s besser?

    Zwischen
    attachInterrupt(Taster01Pin, ISR_Taster1, RISING);
    und
    Code:
    ISR_Taster1() {
      noInterrupts(); // alle Interrupts ausschalten
      Variable = Entprellung();  // volatile, ~30ms
      interrupts();  // alle Interrupts wieder einschalten
    }
    ist nicht mehr viel Platz.
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  6. #6
    HaWe
    Gast
    erst mal evt das hier wieder streichen (ich kann es nicht beurteilen, was nun stimmt, Klebwax vs. Rabenauge):
    noInterrupts(); // alle Interrupts ausschalten
    interrupts(); // alle Interrupts wieder einschalten


    ich vermute, 30ms warten ist auch etwas lang für eine ISR, und wenn das so ist: dann eine Statemachine programmieren:
    erst state1=0,
    beim 1.Tastendruck per Interrupt: state1=1 und timestamp1=millis()
    dann millis()-timestamp1 in loop() kontrollieren und sobald 30ms erreicht ist: Tastendruck verarbeiten und state1 wieder auf 0.

    Ich mache das bisher ganz ohne Interrupts in einer C++ Klasse, auch zum Erkennen und Unterscheiden von kurzem Click, langem Press und Doppelklick.
    Aber ich weiß ntl nicht, ob dich meine Lösung interessiert, sonst zeige ich sie dir gerne...

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Zitat Zitat von HaWe Beitrag anzeigen
    Ich mache das bisher ganz ohne Interrupts in einer C++ Klasse, auch zum Erkennen und Unterscheiden von kurzem Click, langem Press und Doppelklick.
    Aber ich weiß ntl nicht, ob dich meine Lösung interessiert, sonst zeige ich sie dir gerne...
    Natürlich interessiert mich das - kann ja durch andere (erfahrene) Gedanken nicht blöder werden
    Ich finde die ISR-Auslösungen schon super - mit einer state-Mashine kombiniert - und dann als universelle Standart-Funktion mit der ich mich nie wieder beschäftigen muss... !
    Zitat Zitat von HaWe Beitrag anzeigen
    ich vermute, 30ms warten ist auch etwas lang für eine ISR, und wenn das so ist: dann eine Statemachine programmieren:
    Daher war mein Ursprungsgedanke, dass der Interrupt ein Sprungziel in die loop()-Funktion defeniert - mehr nicht.
    Dort wird dann erneut die Tastenabfrage/Entprellung und alles folgende vor genommen.
    Geht das überhaupt?
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  8. #8
    HaWe
    Gast
    ok, hier ist die Klasse:

    Code:
    // Button Press Object
    // (C) 2018 by dsyleixa
    
    // This example code is in the public domain for private use.
    // Use for professional or business purpose only by personal written permission 
    // by the author.
    
    // history
    // 0.0.8 new level 31 & debounce premature 2nd click
    // 0.0.7 PCF + MCP pin-read (outline) 
    // 0.0.6 adjustable long press
    // 0.0.5 adjustable dbl click speed, block press limit
    // 0.0.4 constant long press intervall
    // 0.0.3 long press= 6*short press
    
    // ButtonClass.h
    // ver 0.0.8
    
    
    #ifndef __BTNCLASS__
    #define __BTNCLASS__ 
    
    #include <Arduino.h>
    
    #define PCF_INPUT          8574
    #define PCF_INPUT_PULLUP  -8574
    #define MCP_INPUT         23017
    #define MCP_INPUT_PULLUP -23017
    #define ANALOG_HIGH         900
    #define ANALOG_LOW          100
    #define ANALOG_50            50
    #define ANALOG_100          100
    #define ANALOG_200          200
    #define ANALOG_300          300
    #define ANALOG_400          400
    #define ANALOG_500          500
    #define ANALOG_600          600
    #define ANALOG_700          700
    #define ANALOG_800          800
    #define ANALOG_900          900
    #define ANALOG_1000        1000
    
    
    
    class tButton {
      
       //---------------------------------------------------------- 
       protected:   
        
        int16_t  pin;
        int32_t  mode;
        uint32_t aktMillis, aktMillis2;
        int8_t   level, 
                 dnstate, dnstate2, upstate, 
                 btnstate, oldbtnstate;
        uint32_t MINPRESSms, DBLCLICKms, LONGPRESSms, BLOCKPRESSms, DEBOUNCEms;
    
    
        //------------------------------------- 
        int8_t dtimer() {
          if (millis()-aktMillis >= LONGPRESSms) { // long press 400ms
              return 3;
          }
          else
          if (millis()-aktMillis >= MINPRESSms) {   
              return -1;
          }
          else
          return 0;
        }
    
        
        //-------------------------------------
        int8_t dtimer2() {
          if (millis()-aktMillis2 >= BLOCKPRESSms) { // block press limit
              return 2;
          }
          if (millis()-aktMillis2 >= DBLCLICKms) { // double click limit
              return 1;
          }
          //else
          return 0;
        }
    
    
        //-------------------------------------
        int8_t readButton(int16_t _pin, int32_t _mode) {
          if(_mode==INPUT) return digitalRead(_pin);
          else
          if(_mode==INPUT_PULLUP) return !digitalRead(_pin);
          else
          if(_mode==ANALOG_HIGH) return analogRead(_pin)>900;
          else
          if(_mode==ANALOG_LOW)  return analogRead(_pin)<100;
          else
          if(_mode==ANALOG_50)  return inRange(analogRead(_pin),50);
          else
          if(_mode==ANALOG_100) return inRange(analogRead(_pin),100);
          else
          if(_mode==ANALOG_200) return inRange(analogRead(_pin),200);
          else
          if(_mode==ANALOG_400) return inRange(analogRead(_pin),400);
          else
          if(_mode==ANALOG_800) return inRange(analogRead(_pin),800);
    
    
          
          /*
          else
          if(_mode==PCF_INPUT) return !pcfRead(_pin);
          else
          if(_mode==PCF_INPUT_PULLUP) return !pcfRead(_pin);
          else
          if(_mode==MCP_INPUT) return !mcpRead(_pin);
          else
          if(_mode==MCP_INPUT_PULLUP) return !mcpRead(_pin);
          */
    
        } 
    
    
      //----------------------------------------------------------
      public:       
    
        tButton () : 
          pin(0xFF), aktMillis(0), aktMillis2(0), 
          MINPRESSms(40),     // min duration for either button press
          DBLCLICKms(150),    // max priod between double click actions
          LONGPRESSms(300),   // min duration for long press 
          BLOCKPRESSms(200),  // min wait duration after completed actions
          DEBOUNCEms(20),     // debounce time after btn press (idle, ignore) 
          mode(INPUT_PULLUP),
          level(0), dnstate(0), dnstate2(0), upstate(0), 
          oldbtnstate(0), btnstate(0)  
          { }
       
        ~tButton ()  { }
    
        //-------------------------------------
        void init(int16_t _pin, int32_t _mode, uint32_t _minpressms=40) {      
          pin  = _pin;    
          mode = _mode;  
          MINPRESSms = _minpressms;
          
          if(mode==INPUT || mode==INPUT_PULLUP)         // Button at dig GPIO
          {  
             pinMode(pin, mode);
          }
          else 
          if(mode==PCF_INPUT || mode==PCF_INPUT_PULLUP) // Button at PCF8574
          { 
             // dummy     
          }
          else 
          if(mode==MCP_INPUT || mode==MCP_INPUT_PULLUP) // Button at MCP23017
          { 
             // dummy     
          }
    
        }
    
    
        //-------------------------------------
        bool inRange(int val, int ref, int range=10 ) {
          return( (val>ref-range)&&(val<ref+range) );
        }
    
    
        //-------------------------------------
        void setclickdurations( uint32_t _minpressms,
                                uint32_t _dblclickms,
                                uint32_t _longpressms,
                                uint32_t _blockpressms ) 
        {            
          MINPRESSms =   _minpressms;
          DBLCLICKms =   _dblclickms; 
          LONGPRESSms =  _longpressms;
          BLOCKPRESSms = _blockpressms;
        }
    
    
        //-------------------------------------
        int8_t click() { // returns 1(single), 2(double), 3(long), or 0(no press)
    
          btnstate=readButton(pin, mode); 
    
          if(level==0) {     
             dnstate=0;       
             if(!oldbtnstate && btnstate) { //  1st new btn down:
               aktMillis=millis();          //  restart btn down timer 
               level=1;           
               return 0;
             }  
          }
    
          if(level==1) {                           // either btn stroke happened        
             //Serial.println("level1");    Serial.println(dnstate);
    
             if(millis()-aktMillis <= DEBOUNCEms) { // debounce
                 return 0;
             }
    
             dnstate= dtimer();             // -1=short, 3=long pess 
             
             if(!btnstate){                 // 1st btn up                          
               if(dnstate){                 // -1=short, 3=long pess
    
                 aktMillis2=millis();             
                 if(dnstate==3) {           // long press: finished !!    
                    btnstate=0;
                    oldbtnstate=0;
                    dnstate=0;
                    aktMillis=millis();
                    aktMillis2=millis();
                    upstate=0;
                    level=4;            // extra wait after long press
                    return 3;
                }
                else level=2;               // short press: next level
               }  
             }  
          }
    
          if(level==2) {                           // short press happened         
             //Serial.println("level2");  Serial.println(dnstate);
    
             upstate=dtimer2();             // check btn up pause 
    
             btnstate=readButton(pin, mode);          
             
             //Serial.print("upstate="); Serial.println(upstate);     
                 
             if(btnstate) {           // second btn click during pause: double click! 
                dnstate2=1;
                //Serial.print(" dnstate2="); Serial.println(dnstate2); 
             }
             
             
             if(upstate==0 && dnstate2)   { // if double click: next level
                level=3;
             }
             else         
             if(upstate>=1) {                           // dbl click time passed:             
                //Serial.println(millis()-aktMillis2);   // single press finished !!
                dnstate=0; 
                dnstate2=0;
                //Serial.println(dnstate);
                btnstate=0;
                oldbtnstate=0;
                level=4;
                aktMillis=millis();   
                aktMillis2=millis(); 
                upstate=0;
                level=4;                  // extra wait after single press
                return 1;  
              }
          }
    
          if(level==3) {                       // double click
             if (btnstate) {     
                btnstate=readButton(pin, mode); 
                if (btnstate) level=31;    // non-blocking while still pressed 
                return 0;                                 
             }
             if (!btnstate) {              
                //Serial.println("level3");   
                dnstate=0;                   // double click finished !!
                dnstate2=0;
                upstate=0;
                //Serial.println(dnstate);
                oldbtnstate=0;              
                aktMillis=millis();  
                aktMillis2=millis(); 
                level=4;                // extra wait after double click
                return 2;    
             }         
          }
    
          if(level==4) {                // BlockPress  wait routine
             upstate=dtimer2();
             aktMillis=millis();  
             if(upstate>=2) {
                 level=0;
                 dnstate=0;     
                 upstate=0;
                 aktMillis=millis();   
                 aktMillis2=millis();
                 //Serial.println("level4 extra wait finished");
             }
          }
    
    
          if(level==31) {    // double click, still pressed
             btnstate=readButton(pin, mode);
             if (!btnstate) {            
                level=3;
                return 0; 
             } 
             oldbtnstate=btnstate;
             return 0; 
          } 
    
          oldbtnstate=btnstate;
          return 0;                
        };    
    
        //------------------------------------- 
        int8_t state() { // returns 1(single), 2(double), 3(long), or 0(no press)
             return  click();   // alias       
        }
    
    };
    
    #endif

    hier ist ein example:

    Code:
    // Button Press Lib Testcode
    // (C) 2018 by dsyleixa
    
    // This example code is in the public domain for private use.
    // Use for professional or business purpose only by personal written permission 
    // by the author.
    
    
    
    
    #include <ButtonClass.h>
    
    
    tButton btn1;
    tButton btn2;
    
    
    void setup() {
      Serial.begin(115200);
      delay(2000);
      pinMode(13, OUTPUT); // debug
      
      Serial.println("Serial started\n");
      btn1.init(4, INPUT_PULLUP);  // <<< adjust
      btn2.init(5, INPUT_PULLUP);  // <<< adjust
    }
    
    //------------------------------------------------------------------------
    
    void loop() {
      int8_t  btn;
    
      btn=btn1.click();
      if(btn) {
        Serial.print("btn1.click()=");
        Serial.println(btn);
      }
      btn=btn2.click();
      if(btn) {
        Serial.print("btn2.click()=");
        Serial.println(btn);
      }
      // delay(10);  // debug
    }


    den Teil für Analog-, MCP23017- und PCF8574-Buttonpads kannst du streichen, dazu kommen wir später

    - - - Aktualisiert - - -

    ach ja,
    und hier eine Beschreibung:

    Code:
    # Arduino
    
    
    ButtonClass tButton
    
    Instances: e.g.
    
    
    tButton mybtn;
    
    
    
    // and perhaps more:
    
    
    tButton mybtn1;
    
    
    tButton mybtn2;
    
    
    // etc
    
    
    Init:
    
    mybtn.init(pin_number,  INPUT/INPUT_PULLUP)
    - or -
    mybtn.init(pin_number,  INPUT/INPUT_PULLUP,  min_press_ms)
    (for INPUT_PULLUP mode, the press action is inverted automatically)
    (min_press_ms default: 60ms)
    
    
    
    to retrieve/refresh button click  states: 
    call repeatedly
    
    
    mybtn.click() 
    alias:  mybtn.state() 
    
    
    it returns a int8_t value 0, 1, 2, or 3:
    
    
    0: not pressed
    
    1: 1 short click (default minimum duration = 60ms)
    
    2: double click = 2 quick short clicks (default: within <= 150ms)
    
    3: a long press (minimum duration= 300ms)
    Geändert von HaWe (23.11.2019 um 10:28 Uhr) Grund: c+p Fehler

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    WOUW!

    Eigentlich wollte nur ich eine einfache Tasten/Kontakt-Entprellung von 20-30ms (ohne dalay) nach einer ISR-Auslösung programmieren.
    Deine Lösung scheint mir sehr viel umfangreicher und somit aufwendiger. Auch aufgrund der 6 Status-Abfragen. DIE EierLegendeWollMilchSau
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

Ähnliche Themen

  1. Teensy 3.2 +++ Interrupttimer via RTC ?
    Von frabe im Forum Arduino -Plattform
    Antworten: 1
    Letzter Beitrag: 22.10.2019, 14:56
  2. Teensy 3.2 +++ I/O-Werte, Analog-In
    Von frabe im Forum Arduino -Plattform
    Antworten: 26
    Letzter Beitrag: 18.10.2019, 08:57
  3. Der Teensy 4.0 ist fertig
    Von Mxt im Forum Arduino -Plattform
    Antworten: 44
    Letzter Beitrag: 12.08.2019, 09:24
  4. Platinenlayout Problem mit Platinenlayout - Adapterplatine für den Teensy 3.1
    Von robonooby im Forum Konstruktion/CAD/3D-Druck/Sketchup und Platinenlayout Eagle & Fritzing u.a.
    Antworten: 9
    Letzter Beitrag: 29.06.2014, 15:09
  5. Tabelle als Übergabeparameter von Subroutine?
    Von screwdriver im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 09.01.2009, 15:45

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress