Ich habe Probleme beim Hinzufügen von attachInterrupt in einer Bibliothek, die ich erstelle. Ich habe viel recherchiert und festgestellt, dass dies häufig vorkommt Fehler, aber verstehe die Antworten, die ich gefunden habe, nicht ganz.
Der fragliche Fehler lautet:
sketch_nov04a.ino: In function "void setup()": sketch_nov04a:10: error: argument of type "void (Teste::)()" does not match "void (*)()"
Meine Bibliothek lautet wie folgt :
Teste.h
#ifndef TESTE_H #define TESTE_H #include <Arduino.h> class Teste { public: volatile long lastWindIRQ; volatile byte windClicks; void wspeedIRQ(); }; #endif
Teste.cpp
#include "Teste.h" void Teste::wspeedIRQ() { if (millis() - this.lastWindIRQ > 10) { this.lastWindIRQ = millis(); this.windClicks++; } }
meine Implementierung
#include <Teste.h> Teste teste; void setup() { Serial.begin(9600); pinMode(2, INPUT); digitalWrite(2, HIGH); attachInterrupt(0, teste.wspeedIRQ, FALLING); } void loop() { Serial.println(teste.windClicks); delay(3000); }
EDIT : Der Fehler wurde aktualisiert und das von Ignacio
Antwort
Das Problem ist, dass wspeedIRQ()
eine Mitgliedsfunktion ist (dh Teil der Klasse Teste
). , aber attachInterrupt()
expe cts eine Nichtmitgliedsfunktion (d.h. Eine Funktion, die statisch ist und / oder überhaupt nicht Teil einer Klasse ist.
Dies ist eine sehr wichtige Unterscheidung in C ++, da sie sich darauf auswirkt, wie der Compiler die Funktion hinter den Kulissen aufruft. Es gibt leider keine Möglichkeit, eine Mitgliedsfunktion direkt mit attachInterrupt()
zu verwenden.
Es sind jedoch verschiedene Problemumgehungen möglich. Am einfachsten ist es, eine Wrapper-Funktion zu schreiben, die die Member-Funktion aufruft. Beispiel:
Teste teste; // This is a non-member function... void isr() { // ...which calls the member function: teste.wspeedIRQ(); } void setup() { //... // Setup interrupt to use a non-member function attachInterrupt(0, isr, FALLING); }
Als Randnotiz: Ihre Implementierung von wspeedIRQ()
wird derzeit ohnehin nicht kompiliert Der Grund dafür ist, dass this.
ungültig ist. Es ist ein Zeiger, daher lautet die korrekte Syntax this->
.
( In der Praxis müssen Sie normalerweise nicht this
verwenden, um auf Mitgliedsdaten zuzugreifen. C ++ ermittelt dies automatisch, es sei denn, es liegt ein Namenskonflikt vor.)
Antwort
Normalerweise sollten Sie digitalPinToInterrupt (Pin) verwenden, um den tatsächlichen digitalen Pin in die spezifische Interrupt-Nummer zu übersetzen, nicht in den Pin-Switch-Vergleich attachInturrupt (,,) beschränkt auf Pin 2,3 auf einem Arduino uno … oder wenn Sie mehr Geld gut ausgeben … hier „sa list.
Board Digital Pins Usable For Interrupts Uno, Nano, Mini, other 328-based 2, 3 Mega, Mega2560, MegaADK 2, 3, 18, 19, 20, 21 Micro, Leonardo, other 32u4-based 0, 1, 2, 3, 7 Zero all digital pins, except 4 MKR1000 Rev.1 0, 1, 4, 5, 6, 7, 8, 9, A1, A2 Due all digital pins all digital pins (Only pins 2, 5, 7, 8, 10, 11, 12, 13 work with CHANGE
delay () funktioniert nicht b / c-Werte werden nicht von millis () zurückgegeben (fragen Sie nicht warum) https://www.arduino.cc/en/Reference/AttachInterrupt erklärt, wie man Inturrupts verwendet, wie ich das Begginin rezitieren kann g
Interrupts sind nützlich, um Dinge in Mikrocontroller-Programmen automatisch ablaufen zu lassen, und können helfen, Zeitprobleme zu lösen. Gute Aufgaben für die Verwendung eines Interrupts können das Lesen eines Drehgebers oder das Überwachen von Benutzereingaben sein …. bla bla
Was Peter nicht erwähnt hat, ist, was Interrupt-Serviceroutinen waren … und wie diese speziellen Funktionen haben einzigartige Einschränkungen, die andere Funktionen wie in C ++ nicht haben … von C-Strings über Strukturen bis hin zu Überladung zu F-Strukturen zu T-Templates. ISRs sind so kurz wie möglich und sollten nichts zurückgeben! Wenn Sie billig sind und nicht mehr als 5 US-Dollar für ein Arduino ausgeben möchten, können Sie mithilfe der Skizze mehrere isr verwenden. Sie können sie als Priorität
einrichten, aber Ihre Nicht-Mitglieder-Funktionen sollten volatil und global sein … und millis () ist auf Interrupts angewiesen, um zu zählen, sodass es innerhalb eines ISR niemals inkrementiert wird. Da für delay () Interrupts erforderlich sind, funktioniert es nicht, wenn es innerhalb eines ISR aufgerufen wird. micros () funktioniert zunächst, verhält sich jedoch nach 1-2 ms unregelmäßig. delayMicroseconds () verwendet keinen Zähler, daher funktioniert es wie gewohnt. und …. globale Variablen werden verwendet, um Daten zwischen einem ISR und dem Hauptprogramm zu übertragen. Um sicherzustellen, dass die von einem ISR und dem Hauptprogramm gemeinsam genutzten Variablen korrekt aktualisiert werden, deklarieren Sie sie als flüchtig.