Innholdsfortegnelse:
2025 Forfatter: John Day | [email protected]. Sist endret: 2025-01-13 06:58
God jul! Vil du ha et juletre som kan samhandle med deg?
Trinn 1: Ting som brukes i dette prosjektet
Maskinvarekomponenter
- Seeeduino V4.2
- Base Shield V2
- Grove - Justerbar PIR bevegelsessensor
- Grove - Loudness Sensor
- Grove - WS2813 RGB LED Strip Vanntett - 60 LED/m - 1m
Programvare -apper og online -tjenester
Arduino IDE
Trinn 2: Maskinvaretilkobling
Koble PIR -sensor, lydstyrkesensor og LED -stripe til Base Shields port D2, A0 og D6 separat. Plugg Base Shield til Seeduino, alt ferdig.
Trinn 3: Programvareprogrammering
Bibliotekene som følger ned må installeres før du programmerer. Last ned og importer dem til Arduino IDE manuelt:
- Led_Strip
- MsTimer2
- Arduino_Vector
For å gjøre koden mer konsis, har vi pakket den. CheerLight -klassen er applikasjonsklassen for dette prosjektet.
klasse søknad:: CheerLight
: offentlig applikasjon:: grensesnitt:: IApplication {public: void setup (void); void loop (void); void setPIRSensorPin (uint8_t pin); void setLoudnessSensorPin (uint8_t pin); void measureSensors (void); void changeAnimation (void * args); void changeSpeed (void * args); void changeColor (void * args); statisk applikasjon:: CheerLight * getInstance (void); protected: driver:: LEDStrip _ledStrip; driver:: PIRSensor _pirSensor; driver:: LoudnessSensor _loudnessSensor; uint8_t _animasjon; mellomvare:: Delegate _detectedDelegate; mellomvare:: Delegate _absoluteLoudnessDelegate; mellomvare:: Delegate _relativeLoudnessDelegate; CheerLight (ugyldig); statisk applikasjon:: CheerLight _instance; };
CheerLight -klassen ble designet av Singleton Patterns, noe som betyr at det bare er én forekomst for den, du kan kalle CheerLight:: getInstance () til den forekomsten. Hvis sensorenes tilkobling er forskjellig fra maskinvaretilkobling, kan du endre dem ved å ringe til setPIRSensorPin () og setLoudnessSensorPin () -metoder.
Vi anbefaler å kalle MeasureSensors () -metoden i timeravbrudd for å gjøre sensorer målt rettidig, men det er ikke nødvendig å kalle changeAnimation (), changeSpeed () eller changeColor () -metoder manuelt. De vil bli ringt opp via delegater når sensorer måles.
Hva er en delegat?
Som vi alle vet, kan vi deklarere en funksjonspeker og få den til å peke på en funksjon i C:
void func1 (void);
void (*pFunc) (void) = func1;
og bruk den til å kalle funksjonen den pekte på
pFunc ();
Men det er forskjeller i C ++, hvis du prøver å kompilere koden nedenfor:
klasse A {
offentlig: void func1 (void); }; void (*pFunc) (void) = & A:: func1;
kompilatoren vil rapportere en type konverteringsfeil, her er det riktige eksemplet:
void (A::*pFunc) (void) = & A:: func1;
Når vi prøver å bruke den til å kalle den metoden, feil igjen. Årsaken til den feilen er at en objektmetode må kalles av et objekt. Så vi lager et objekt for å kalle det:
A a;
a.*pFunc ();
Denne gangen ikke noe problem. Så det er Delegate -klasse i Delegate.h.
mal
klasse mellomvare:: Delegat: offentlig mellomvare:: grensesnitt:: IDelegate {public: Delegate (T *object, void (T:: *method) (void *)); void påkalle (void * args); beskyttet: T * _object; void (T:: *_ metode) (void *); }; template inline middleware:: Delegate:: Delegate (T *object, void (T:: *method) (void *)): _object (object), _method (method) {} template inline void middleware:: Delegate:: invoke (void * args) {(_object-> * _ method) (args); }
Fordi delegatklassen er en malklasse, noe som betyr at delegat er forskjell fra delegat, hvordan kan du få dem til å peke med pekeren av samme type? Svaret er grensesnitt, så det er IDelegate grensesnitt i IDelegate.h.
klasse mellomvare:: grensesnitt:: IDelegate {
public: virtual void invoke (void * args) = 0; };
I klassen PIR Sensor og Loudness Sensor har det en variabel som heter _delegates som brukes til å lagre pekeren til delegater, og det har en metode som heter invokeAllDelegates () som brukes til å påkalle alle delegater i _delegates, den vil bli kalt i mål () -metoden.
MERK: Delegerte metoder, for eksempel changeAnimation (), changeSpeed () og changeColor () vil bli kalt inn timer2 interrupt, så IKKE bruk forsinkelse () eller annen interrupt-basert funksjon i den.