Mam problem z dodaniem attachInterrupt w bibliotece, którą tworzę. Dużo szukałem i zauważyłem, że jest to częste pomyłka, ale nie do końca rozumiem znalezionych odpowiedzi.
Występuje następujący błąd:
sketch_nov04a.ino: In function "void setup()": sketch_nov04a:10: error: argument of type "void (Teste::)()" does not match "void (*)()"
Moja biblioteka wygląda następująco :
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++; } }
moja implementacja
#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); }
EDYTUJ : zaktualizowano błąd i poprawiono problem wymieniony przez Ignacio
Odpowiedź
Problem polega na tym, że wspeedIRQ()
jest funkcją składową (tj. jest częścią klasy Teste
) , ale attachInterrupt()
exp cts funkcja niebędąca członkiem (tj. funkcja, która jest statyczna i / lub w ogóle nie jest częścią klasy).
Jest to bardzo ważna różnica w C ++, ponieważ wpływa na to, jak kompilator wywołuje funkcję w tle. Niestety nie ma możliwości bezpośredniego użycia funkcji składowej z attachInterrupt()
.
Możliwe są jednak różne obejścia. Najprościej jest napisać funkcję opakowującą, która wywołuje funkcję składową. Na przykład:
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); }
Na marginesie, Twoja implementacja wspeedIRQ()
i tak wygrała „t w tej chwili skompilowana . Powodem jest to, że this.
jest nieprawidłowy. Jest to wskaźnik, więc prawidłowa składnia to this->
.
( W praktyce zwykle nie trzeba używać this
, aby uzyskać dostęp do danych członków. C ++ oblicza to automatycznie, chyba że występuje konflikt nazw).
Odpowiedź
Zwykle powinieneś użyć digitalPinToInterrupt (pin), aby przetłumaczyć rzeczywisty cyfrowy pin na konkretny numer przerwania, a nie na porównanie przełącznika pinów attachInturrupt (,,), czyli ograniczone do pinu 2,3 na arduino uno … lub jeśli dobrze wydasz więcej pieniędzy … tutaj „lista sa.
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 () nie działa wartości b / c nie są zwracane z millis () (nie pytaj dlaczego) https://www.arduino.cc/en/Reference/AttachInterrupt wyjaśnia, jak używać przerywników, na przykład pozwól mi wyrecytować początek g
Przerwania są przydatne do automatycznego wywoływania rzeczy w programach mikrokontrolerów i mogą pomóc w rozwiązywaniu problemów z synchronizacją. Dobre zadania związane z używaniem przerwania mogą obejmować czytanie enkodera obrotowego lub monitorowanie danych wejściowych użytkownika … bla bla
Pete nie wspomniał o tym, czym były procedury obsługi przerwań … i jak te specjalne funkcje mają unikalne ograniczenia inne funkcje, takie jak w c ++, nie… od łańcuchów c do struktur do przeciążania do struktur f i szablonów t. ISR są tak krótkie, jak to tylko możliwe i nie powinny niczego zwracać! jeśli jesteś tani i nie chcesz wydawać więcej niż 5 $ na arduino, możesz użyć Sketch, aby użyć wielu ISR, możesz ustawić je jako priorytetowe
ale twoje funkcje niebędące członkami powinny być niestabilne i globalne … a millis () polega na zliczaniu przerwań, więc nigdy nie będzie inkrementować wewnątrz ISR. Ponieważ funkcja delay () wymaga do działania przerwań, nie zadziała, jeśli zostanie wywołana wewnątrz ISR. micros () działa początkowo, ale zacznie zachowywać się nieregularnie po 1-2 ms. delayMicroseconds () nie używa żadnego licznika, więc będzie działać normalnie. i …. zmienne globalne są używane do przekazywania danych między ISR a głównym programem. Aby upewnić się, że zmienne współdzielone między ISR a głównym programem są poprawnie aktualizowane, zadeklaruj je jako zmienne.