10 knoppen met 1 onderbreking
Componenten en benodigdheden
| × | 1 | ||||
| × | 1 | ||||
| × | 21 | ||||
| × | 10 |
Apps en online services
|
Over dit project
Inleiding
Interrupts zijn handig. Ze maken code soms eenvoudiger, maar kunnen ook worden gebruikt voor nauwkeurige timing of om de Arduino uit de slaapstand te halen.
Stel dat je een gebruikersinterface hebt, bijvoorbeeld een afstandsbediening die op batterijen werkt. Misschien wilt u de Arduino (of stand-alone ATmega) in de uitschakelmodus zetten om stroom te besparen. Wanneer een Arduino in de power-down-modus gaat, kan deze alleen worden gewekt door een externe interrupt. De ATmega328P-chip die in een Arduino Uno wordt gebruikt, heeft slechts twee externe pin-interrupts. (INT0
en INT1
op pinnen 2 en 3) Aangezien een gebruikersinterface waarschijnlijk meer dan twee knoppen heeft, is dat een probleem.
De standaard manier om op te lossen
dit zou zijn om alle knoppen normaal aan te sluiten, maar ook om ze aan te sluiten op een interruptpin met een diode. Dit bemoeilijkt het circuit echter aanzienlijk.
Naast standaard externe interrupts heeft de ATmega328P ook pin change interrupts. Er zijn bibliotheken om ermee om te gaan en ze zijn een goede oplossing voor dit probleem.
Tijdens een programmeerwedstrijd ontdekte ik echter hoe ik dit kon doen met behulp van standaard externe interrupts zonder extra elektrische componenten.
Het circuit
We hebben een paar knoppen. Ik gebruikte er tien, die mooi op mijn breadboard pasten. (Meer heb ik ook niet.) Je kunt één knop per pin hebben, dat wil zeggen tot 20 op een Uno en tot 70 op een Mega! (Als je echt 70 knoppen nodig hebt, raad ik je aan multiplexen te gebruiken, daar heb je geen hele Mega voor nodig.)
Elke knop heeft een zijde die is verbonden met een willekeurige pin. (4-13 in mijn geval) De andere zijden van alle knoppen zijn met elkaar verbonden tot een enkele pin die kan worden onderbroken. (2 in mijn geval)
De code
De code is hieronder bijgevoegd. Om dit voorbeeld te laten werken, upload het naar je bord. Open uw seriële monitor. Als u op een knop drukt, verschijnt het nummer ervan. Zoals je kunt zien, wordt de loop-functie helemaal niet gebruikt.
Hoe werkt het?
Er is duidelijk een onderbreking. In mijn geval is het bevestigd aan pin 2. Het is geconfigureerd als FALLING
.
Om het gebruik van diodes te vermijden, herbedraden de Arduino het circuit on-the-fly. Er zijn twee mogelijke configuraties:Algemene modus en Afzonderlijke modus .
Algemene modus
Meestal bevindt het circuit zich in de gewone modus. De interrupt-pin wordt geconfigureerd als INPUT_PULLUP
en de rest is OUTPUT
en LAAG
.
void configureCommon() { pinMode(commonPin, INPUT_PULLUP); for (int i =0; i
In de gewone modus zal het indrukken van een willekeurige knop onze interrupt-pin naar beneden trekken en onze interrupt afvuren. Zodra dat gebeurt, zal onze interrupt-serviceroutine de pinnen opnieuw configureren voor de afzonderlijke modus.
Aparte modus
Zodra onze interrupt wordt geactiveerd, schakelen we snel over naar de afzonderlijke modus.
De verschillende modus is het tegenovergestelde van de gewone modus. De interrupt-pin is OUTPUT
en LAAG
en de rest is INPUT_PULLUP
.
void configureDistinct() { pinMode(commonPin, OUTPUT); digitalWrite (commonPin, LAAG); for (int i =0; i
In de afzonderlijke modus worden alleen pinnen die overeenkomen met de knoppen die daadwerkelijk zijn ingedrukt, naar beneden getrokken. We kunnen gemakkelijk alle pinnen doornemen om erachter te komen welke de interrupt heeft geactiveerd.
Nadat dat is gebeurd, kan de Arduino terugschakelen naar de gewone modus en wachten op een nieuwe onderbreking. Of, afhankelijk van uw toepassing, kan het in de aparte modus blijven en gebruikersinvoer verwerken zoals het normaal zou doen, en terugschakelen naar de gewone modus voordat de Arduino in slaap valt.
Een complexer voorbeeld
Laten we iets ingewikkelders proberen. We zullen een servo bevestigen en elke knop in een andere hoek plaatsen. (1=0°, 2=20°... 10=120°) We zullen onze Arduino ook van stroom voorzien met een paar batterijen.
In dit voorbeeld zetten we de Arduino in de power-down-modus na vijf seconden van inactiviteit om energie te besparen. U kunt online enkele tutorials over de slaapmodus vinden. Daarnaast voeden we de servo via een transistor om hem uit te schakelen wanneer hij niet in gebruik is.
De code voor dit voorbeeld is ook hieronder bijgevoegd.
Code
- Seriële logger
- Servo met slaapstand
Seriële loggerArduino
const int commonPin =2;const int buttonPins[] ={4,5,6,7,8,9,10,11,12,13};unsigned long lastFire =0;void setup() { configureCommon( ); // Stel pinnen in voor interrupt attachInterrupt (digitalPinToInterrupt (commonPin), pressInterrupt, FALLING); Serial.begin(9600);}void loop() {// Leeg!}void pressInterrupt() { // ISR if (millis() - lastFire <200) { // Debounce return; } lastFire =millis(); configureDistinct(); // Stel pinnen in voor het testen van individuele knoppen voor (int i =0; iServo met slaapstandArduino
#include#include #include const int commonPin =2;const int buttonPins[] ={4,5,6,7,8 ,9,10,11,12,13};const int servoEnablePin =A1;const int servoPin =A0;Servo servo;unsigned long lastFire =0;int status =0;void setup() { pinMode(commonPin, INPUT_PULLUP); configureCommon(); attachInterrupt(digitalPinToInterrupt(commonPin), pressInterrupt, FALLING); servo.attach (servoPin); pinMode(servoEnablePin, OUTPUT);}void loop() {if (millis()-lastFire> 5000) {digitalWrite(servoEnablePin, LOW); set_sleep_mode (SLEEP_MODE_PWR_DOWN); sleep_enable(); slaapstand(); } delay(10);}void pressInterrupt() { sleep_disable(); power_all_enable(); if (millis()-lastFire <200) { return; } lastFire =millis(); configureDistinct(); for (int i=0;i Schema's
multiinterrupt_hoF76Oc4T5.fzz servo_with_sleep_u9ZqxF0jhY.fzz
Productieproces
- DTMF-decoder met alleen Arduino
- Maak Monitor Ambilight met Arduino
- ULTRASONE LEVITATION-machine die ARDUINO gebruikt
- DIY voltmeter met Arduino en smartphone
- Hartslagmeter met IoT
- WebServerBlink met Arduino Uno WiFi
- Autoteller met Arduino + Processing + PHP
- Geautomatiseerd Dino-spel met arduino
- FM-radio met Arduino en RDA8057M
- BLUE_P:Wireless Arduino Programming Shield
- Digital Watch op Arduino met behulp van een Finite State Machine