Ho problemi ad aggiungere attachInterrupt in una libreria che sto creando. Ho fatto molte ricerche e ho notato che questo è un comune errore, ma non capisco bene le risposte che ho trovato.
Lerrore in questione è questo:
sketch_nov04a.ino: In function "void setup()": sketch_nov04a:10: error: argument of type "void (Teste::)()" does not match "void (*)()"
La mia libreria è la seguente :
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++; } }
mia implementazione
#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 : aggiornato lerrore e corretto il problema citato da Ignacio
Answer
Il problema è che wspeedIRQ()
è una funzione membro (cioè fa parte della classe Teste
) , ma attachInterrupt()
expe cts una funzione non membro (ad es. una funzione che è statica e / o non fa affatto parte di una classe).
Questa è una distinzione molto importante in C ++ perché influenza il modo in cui il compilatore chiama la funzione dietro le quinte. Sfortunatamente non cè modo di usare una funzione membro direttamente con attachInterrupt()
.
Sono possibili varie soluzioni alternative. Il più semplice è scrivere una funzione wrapper che chiama la funzione membro. Ad esempio:
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); }
Come nota a margine, la tua implementazione di wspeedIRQ()
non verrà comunque compilata al momento . Il motivo è che this.
non è valido. È “un puntatore, quindi la sintassi corretta è this->
.
( In pratica, di solito non è necessario utilizzare this
per accedere ai dati dei membri. C ++ lo capisce automaticamente, a meno che non ci sia un conflitto di denominazione.)
Risposta
Normalmente dovresti usare digitalPinToInterrupt (pin) per tradurre il pin digitale effettivo nel numero di interrupt specifico e non nel confronto del pin switch attachInturrupt (,,) che è limitato al pin 2,3 su un arduino uno … o se spendi più soldi bene … ecco “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 () non funzionerà i valori b / c non verranno restituiti da millis () (non chiedere perché) https://www.arduino.cc/en/Reference/AttachInterrupt spiega come usare inturrupts come let me recite the begginin g
Gli interrupt sono utili per far accadere le cose automaticamente nei programmi del microcontrollore e possono aiutare a risolvere i problemi di temporizzazione. Buoni compiti per lutilizzo di un interrupt possono includere la lettura di un codificatore rotante, o il monitoraggio dellinput dellutente …. blah blah
ciò che pete non ha menzionato è cosa fossero le routine di servizio di interrupt … e come queste funzioni speciali hanno limitazioni uniche, altre funzioni come in c ++ non … dalle stringhe c alle strutture, al sovraccarico, alle strutture f ai modelli T. Gli ISR sono i più brevi possibile e non dovrebbero restituire nulla! se sei economico e non vuoi spendere più di $ 5 per un arduino puoi usare sketch per usare più isr puoi impostarli come priorità
ma le tue funzioni non membri dovrebbero essere volatili e globali … e millis () si basa sugli interrupt per contare, quindi non aumenterà mai allinterno di un ISR. Poiché delay () richiede interrupt per funzionare, non funzionerà se chiamato allinterno di un ISR. micros () funziona inizialmente, ma inizierà a comportarsi in modo irregolare dopo 1-2 ms. delayMicroseconds () non usa alcun contatore, quindi funzionerà normalmente. e …. le variabili globali vengono utilizzate per trasferire i dati tra un ISR e il programma principale. Per assicurarti che le variabili condivise tra un ISR e il programma principale siano aggiornate correttamente, dichiarale come volatili.