Stap 9: Input via een knop
Natuurlijk kunt u de I/O pinnen van de Arduino als input ook. In deze stap, we zullen alleen drukknoppen als invoerapparaten gebruiken, maar natuurlijk, u kunt een schakeloptie gebruiken.
Pull-up en pull-down
De Arduino werkt met logische ingangen: 1 = 5v, 0 = 0v. Om onze knop uitgang van deze spanningen, gebruiken we een pull-up of een pull-down-weerstand. (afbeelding 1 & 2)
In het geval van een weerstand van het pull-down (afbeelding 1), we verbinden met een been van de schakelaar 5v, en het andere been door een weerstand (10kΩ in dit geval) op grond (0v). Het been met de aangesloten weerstand gaat naar de invoer pin op de Arduino.
Op deze manier, wanneer de knop niet is ingedrukt (en de 2 benen niet verbinden), de ingang is op 0v, omdat het verbonden met de grond door de weerstand. Wanneer u op de knop drukt, is de ingang op 5v, omdat het rechtstreeks met 5v door de switch verbonden is. De weerstand maakt niet uit wanneer u op de knop drukt, het enkel zorgt ervoor dat de input op 0v wanneer de knop is niet ingedrukt.
Een pull-up weerstand (afbeelding 2) werkt op precies dezelfde manier, maar alles is verwisseld: de eerste etappe is aangesloten op de grond, in plaats van 5v, de tweede is aangesloten op de 5v, via een weerstand (vandaar de naam pull-up weerstand, omdat het trekt het tot 5v). De invoer pin nog steeds verbonden met de kant met de weerstand, maar nu, het is hoog wanneer de knop niet is ingedrukt, en laag gaat wanneer de schakelaar is gesloten.
Knop | Logische staat pull-up | Logisch staat pull-down |
uitgebracht | 1 | 0 |
ingedrukt | 0 | 1 |
Sluit nu een drukknop met een pull-down resister aan 3 pin van de Arduino en een drukknop met een pull-up weerstand op pin 5. Sluit twee LEDs (met hun juiste resistor) aan op pin 10 en 12. (afbeelding 3 & 4)
Nu open voorbeeld button2 en open het. Dit programma alleen leest van de twee ingangen, en de uitgangen ingesteld in dezelfde staat.
Er zijn slechts twee nieuwe dingen, en ze zijn echt duidelijk: in plaats van de constante OUTPUT, wij INPUT kunt instellen van de pennen van onze knoppen als input, en de digitalRead(pin) functie alleen resulteert in de status van de bepaalde invoer pin.
Opmerking: het gebruik van pinMode (pin, ingang) is eigenlijk overbodig, aangezien alle pinnen op de Arduino ingangen standaard, maar het wordt vaak gedaan hoe dan ook, om de code leesbaarder maken.
Wanneer u uploaden van de schets, druk op de knoppen, en je ziet dat de bovenstaande tabel inderdaad juist is: de LED op pin 12 is altijd ingeschakeld, totdat u op de knop op pin 5 drukt, dit is omdat er een pull-up weerstand.
Als u wilt dat de LEDs aan het licht van het alleen wanneer u op de knop, kunt u de Booleaanse operator not: dit verandert slechts een 'echte' in een 'false' (of een 1 in een 0) en vice versa. Deze operator is in C++ (in de Arduino IDE), een uitroepteken (!)
digitalWrite(12, !digitalRead(5));
Interne pull-up weerstanden
Het zou echt lastig zijn als we gebruik maken van een extra weerstand en een extra stuk draad moesten, elke keer als we willen een normale schakeloptie gebruiken. Dat is waarom de chip op de Arduino heeft een ingebouwde pull-up weerstand op elke pin.
Er zijn twee manieren om hen in staat stellen:
pinMode(pin,INPUT); digitalWrite(pin, HIGH);
pinMode(pin,INPUT_PULLUP);
Beide hebben hetzelfde effect, maar deze laatste heeft de voorkeur, want het is beter leesbaar.
Opmerking: als u vergeet te gebruiken pinMode (pin, OUTPUT), en u daarna digitalWrite (pin, hoge), u zult gewoon inschakelen, de pull-up weerstand, aangezien alle pinnen als ingangen standaard zijn ingesteld.
Sluit nu de drukknoppen zonder de weerstanden, alleen de verbinding met de grond (zoals weergegeven in afbeelding 5)
U ziet dat we hoeven niet meer gebruiken van de 5 v-pin van de Arduino, en mochten we dit op grote schaal te produceren, die twee weerstanden die we gered zou een significant verschil in productiekosten.
Open de voorbeeld button2-b. Zoals u zien kunt, gebruikte ik de twee manieren om de pull-up weerstanden. Merk ook op dat ik de operator 'niet', gebruikt zodat de LED's op wanneer op de knop wordt gedrukt.
Sumary
- Voor het gebruik van knoppen en schakelaars met je Arduino, hebt u een pull-up of pull-down weerstand wilt gebruiken.
- pinMode (pin, INPUT_PULLUP); Hiermee kunt de interne pull-up weerstanden van de Arduino.
digitalWrite (pin, hoge); op een invoer pin heeft hetzelfde resultaat. - digitalRead(pin) resulteert in de status van de invoer pin 1 = 5v, 0 = 0v.
Als u een knop gebruikt met een pull-up weerstand (bijvoorbeeld de interne een), betekent 1 dat de knop niet is ingedrukt, 0 betekent dat deze wordt ingedrukt. - Hier kunt u de niet-operator (!) uit te wisselen van 1 en 0. BV ! digitalRead(pin) geeft als resultaat 0 wanneer de knop is niet ingedrukt en 1 wanneer de knop wordt gedrukt.
Extra: Directe haven manipulatie (Geavanceerd)
DigitalRead, digitalWrite en pinMode zijn groot en eenvoudig functies, maar ze zijn relatief traag. Ook u niet 2 pinnen in- of uitschakelen inschakelen op precies hetzelfde moment, en schrijven van 8 bits tegelijk voor parallelle mededeling is niet mogelijk beide. Soms, wanneer u korte op geheugen, kunnen deze 3 functies veel van de beschikbare ruimte, ook gebruiken.
De oplossing voor deze problemen is directe haven manipulatie. De Atmel chip heeft enkele (3 op de meeste Arduinos) registreert voor de I/O pinnen, dit zijn gewoon bytes dat slaan de info over de vraag of een pin een invoer of een uitvoer, of het nu gaat om set hoog of laag, enz. Elke bit van deze bytes komt overeen met een I/O pin op de Arduino.
Op de Arduino Uno bevat poort D 0 tot en met 7 pins, poort B-pinnen 8 tot en met 13 en poort C A0 A5.
Er zijn 3 registers waarmee de I/O (waarbij x staat voor de poort-letter):
- DDRx: Data richting Register: Hiermee wordt ingesteld of de pennen van de poort inputs(1) of uitgangen (0). (pinMode)
- PORTx: poort gegevens registreren: dit is ingesteld uitgangen hoog of laag, en de input pull-up weerstanden inschakelen of uitschakelen. (digitalWrite)
- PINx: poort Input registreren: deze byte bevat de status van de digitale ingangen. Als de PIN-code een output is, krijgt het gewoon u de staat van uitvoer.
In de afbeelding hierboven, kunt u de gehele pin toewijzing voor de Arduino Uno, de poortnummers in de velden van de gele naast de pinnen. (afbeelding krediet)
Aangezien elke bit van de byte één pin vertegenwoordigt, is het makkelijker te schrijven van de waarden in binaire notatie. U kunt dit doen door toevoeging van een hoofdletter B voor het nummer, bijvoorbeeld B111 is 7 in decimale notatie (22 + 21 + 20).
Ook kunt u een leidende 0 te gebruiken van de octale notatie, of 0 x voor de hexadecimale notatie, maar in dit geval met behulp van deze twee notaties niet echt zinvol.
Wanneer tellen bits, de meest rechtse (minst significante, LSB) bit is beetje 0, zodat het overeenkomt met de eerste pin van de poort, terwijl de MSB (meest significante bit) komt met de achtste pin van de poort overeen.
Enkele voorbeelden:
Instelling pin 7 naar een output, en 0-6 pinnen als ingangen:
DDRD = B10000000;
Instelling (output) pin 7 hoog:
PORTD = B10000000;
De interne pull-up weerstand op (input) pin 6 inschakelen:
PORTD = B01000000;
Het lezen van de staat van 0 tot en met 7 pins:
byte state = PIND;
Echter gebruiken als dit kan problemen veroorzaken: bijvoorbeeld in het tweede voorbeeld wordt pin 7 hoog is ingesteld, maar alle andere pinnen in de poort worden ingesteld op nul, ongeacht hun vorige staat. Als u wilt slecht één pin wijzigen op een moment, kunnen we sommige bitsgewijze operatoren gebruiken.
Als u wilt instellen een beetje hoog, zonder de andere bits, kunnen we de bitsgewijze of-operator ( | ) gebruiken. Nota: dit is slechts één |, terwijl de Booleaanse of-operator is ||. Bitsgewijs betekent dat het wordt toegepast op elke bit afzonderlijk. We gebruiken een masker in te stellen van de juiste bit hoog: de bit die we willen hoog is 1, en alle andere bits gelijk zijn aan 0.
byte previousPORTD = PORTD; // read the data register, and store it in a variable PORTD = previousPORTD | B10000000; // set bit seven high
Als een bit in het masker één is, deze bits ingesteld op 1 in het PORTD register, als deze nul, het zal gewoon houden de waarde in previousPORTD. U kunt controleren de waarheid tabellen en enkele voorbeelden in de bovenstaande foto's.
Als u wilt instellen een beetje laag, zonder dat de andere bits, kunnen we de bitsgewijze en-operator ( & ) gebruiken. Nota: dit is slechts één &, overwegende dat de Booleaanse en-operator & &. Nu moeten we onze masker omkeren: de bit die we willen laag ingesteld is nul, en alle andere bits zijn een.
byte previousPORTD = PORTD; // read the data register, and store it in a variable PORTD = previousPORTD & B01111111; // set bit seven low
Deze notatie werkt prima, maar kunnen we het een beetje meer leesbaar. In plaats van het schrijven van een hele binair getal voor onze masker, we kunnen het gebruiken van de exploitant van de linker bitshift (<<). het verschuift enkel alle cijfers naar links voor een gegeven aantal plaatsen. Bijvoorbeeld: 1 << 2 = B100, B101 << 1 = B1010, enzovoort. Dit is ook een gemakkelijke manier voor het berekenen van de bevoegdheden van twee: 1 << 7 = B10000000 = 128 = 27
Maar we gaan om het te gebruiken om onze masker te maken: bijvoorbeeld het masker B10000000 kan worden geschreven als 1 << 7, nu u gemakkelijk zien kunt dat er de achtste pin in het register, zonder te tellen de nullen.
Voor het maken van de inverse masker, voor de en notatie, kunnen we de bitsgewijze operator not ( ~ ) gebruiken om elke bit omkeren: B01111111 kan worden geschreven als ~ (1 << 7). (zie afbeelding)
Als je gewoon spiegelen een of meer bits wilt, kunt u de exclusieve of-operator. (xor, ^ ). Dit resultaat is 1 als één van de input bits is een, en 0 als beide ingangen hetzelfde zijn.
byte previousPORTD = PORTD; // read the data register, and store it in a variable PORTD = previousPORTD ^ B10000000; // flip bit seven
We kunnen samengestelde operatoren gebruiken om het krimpen van de code: x = x + 1; kan worden geschreven als x += 1; bijvoorbeeld. Hetzelfde geldt voor bitsgewijze operatoren. Wij zullen niet de tijdelijke variabele die niet meer nodig.
PORTD |= 1<<7; // set bit 7 high
PORTD &= ~(1<<7); // set bit 7 low
PORTD ^= 1<<7; // flip bit 7
Om specifieke beet van het input register, bijvoorbeeld, kunt u de functie bitRead (byte, bits) :
boolean state = bitRead(PIND, 6); // read the state of the 6th pin of port D
u kunt enkele elementaire wiskunde te bereiken hetzelfde resultaat:
boolean state = (PIND>>6)%2; // read the state of the 6th pin of port D
Deze maakt gebruik van een juiste bitshift (>>) en een modulo operator (%): >> doet hetzelfde als <<, maar in de andere richting. Als PIND B10101010, bijvoorbeeld, PIND is >> 6 = B10, kortom, het karbonades uit de laatste 6 (binaire) cijfers. De bit die wij wilden controleren is nu de meest rechtse bit. Modulo geeft u de rest van een deling, bijvoorbeeld 10 %3 = 1, omdat 3 * 3 + 1 = 10, 5 %6 = 5, omdat 0 * 6 + 5 = 5, 23 %8 = 7, omdat 2 * 8 + 7 = 23. x %2 krijgt u een 0 als x zelfs, en 1 als x oneven is. In de binaire notatie het laatste cijfer (meest rechtse bit) voor een even getal is 0 en het laatste cijfer van een oneven getal is 1. Dus als we gewoon weten het laatste cijfer van een binair getal willen, kunnen we gewoon gebruiken x %2.
Een andere manier om alleen een beetje van een getal is met behulp van de voorwaardelijke operator ( ?: ):
boolean state = (PIND & (1<<6)) == 0 ? 0 : 1; // read the state of the 6th pin of port D
PIND & (1 << 6) zal alleen houden de 6de bit van PIND, alle andere cijfers 0 zal zijn. Als PIND B10101010, bijvoorbeeld, PIND is & (1 << 6) = B00000000, en als PIND B01010101, PIND & (1 << 6) = B01000000. Uit deze voorbeelden, kunt u zien dat het resultaat nul is als bit 6 0 was. Dus als we testen of dit resultaat == 0, wij de staat van bit 6 kent. We gebruiken de voorwaardelijke operator: voorwaarde? resultIfTrue: resultIfFalse. Als de voorwaarde waar is, de exploitant geeft de resultIfTrue, als het onwaar is, wordt geretourneerd resultIfFalse.
Opmerking over compatibiliteit: de poort-to-pin toewijzing hangt af van de chip. Dit betekent dat u uw programma wijzigen als u wilt gebruiken een andere Arduino. Voor persoonlijk gebruik, dit is niet zo veel van een probleem, maar als je het schrijven programma's of bibliotheken voor de Gemeenschap of delen online, u moet hiermee rekening houden.
Arduino Referentie: Integer-constanten zijn
Hij doodde mijn draad: directe haven manipulatie tutorial
Arduino Referentie: poort manipulatie
De Atmel ATmega 328 p gegevensblad p.91 14.4