AttachInterrupt in een bibliotheek

Ik heb problemen met het toevoegen van attachInterrupt in een bibliotheek die ik aan het maken ben. Ik heb veel onderzoek gedaan en ik heb gemerkt dat dit een veelvoorkomende fout, maar begrijp de antwoorden die ik heb gevonden niet helemaal.

De fout in kwestie is deze:

sketch_nov04a.ino: In function "void setup()": sketch_nov04a:10: error: argument of type "void (Teste::)()" does not match "void (*)()" 

Mijn bibliotheek is als volgt :

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++; } } 

mijn implementatie

#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 : de fout bijgewerkt en het probleem gecorrigeerd dat door Ignacio wordt genoemd

Antwoord

Het probleem is dat wspeedIRQ() een lidfunctie is (dwz dat het deel uitmaakt van de Teste klasse) , maar attachInterrupt() expe cts een niet-lidfunctie (d.w.z. een functie die statisch is en / of helemaal geen deel uitmaakt van een klasse).

Dit is een heel belangrijk onderscheid in C ++ omdat het beïnvloedt hoe de compiler de functie achter de schermen aanroept. Er is helaas geen manier om een ledenfunctie rechtstreeks te gebruiken met attachInterrupt().

Er zijn echter verschillende oplossingen mogelijk. De eenvoudigste is om een wrapper-functie te schrijven die de lidfunctie aanroept. Bijvoorbeeld:

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 een kanttekening: uw implementatie van wspeedIRQ() zal op dit moment toch niet compileren . De reden is dat this. ongeldig is. Het is een pointer, dus de juiste syntaxis is this->.

( In de praktijk hoeft u this meestal niet te gebruiken om toegang te krijgen tot de gegevens van leden. C ++ berekent dit automatisch, tenzij er een naamconflict is.)

Answer

Normaal gesproken moet u digitalPinToInterrupt (pin) gebruiken om de feitelijke digitale pin te vertalen naar het specifieke interruptnummer, niet de vergelijking van de pin-schakelaar attachInturrupt (,,) dat wil zeggen beperkt tot pin 2,3 op een arduino uno … of als je meer geld uitgeeft … hier “een lijst.

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 () werkt niet, omdat waarden niet terugkeren van millis () (vraag niet waarom) https://www.arduino.cc/en/Reference/AttachInterrupt legt uit hoe je inturrupts kunt gebruiken, zoals laat me de begginin reciteren g

Interrupts zijn handig om dingen automatisch te laten gebeuren in microcontrollerprogrammas en kunnen timingproblemen helpen oplossen. Goede taken voor het gebruik van een interrupt kunnen het lezen van een roterende encoder zijn, of het monitoren van gebruikersinvoer … blah blah

wat Peter niet noemde, is wat Interrupt Service Routines waren … en hoe deze speciale functies hebben unieke beperkingen, andere functies zoals in c ++ niet …. van c-strings tot structs tot overbelasting tot f-structs tot t-sjablonen. ISRs zijn zo kort mogelijk en mogen niets teruggeven! als je goedkoop bent en niet meer dan $ 5 voor een arduino wilt uitgeven, kun je sketch gebruiken om meerdere isrs te gebruiken, je kunt ze instellen als prioriteit

maar je niet-lidfuncties moeten vluchtig en globaal zijn … en millis () is afhankelijk van het tellen van interrupts, dus het zal nooit binnen een ISR toenemen. Aangezien delay () interrupts vereist om te werken, zal het niet werken als het wordt aangeroepen binnen een ISR. micros () werkt aanvankelijk, maar zal zich onregelmatig gaan gedragen na 1-2 ms. delayMicroseconds () gebruikt geen teller, dus het zal normaal werken. en …. globale variabelen worden gebruikt om gegevens tussen een ISR en het hoofdprogramma door te geven. Om ervoor te zorgen dat variabelen die worden gedeeld tussen een ISR en het hoofdprogramma correct worden bijgewerkt, declareert u ze als vluchtig.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *