Lätt Arduino menyer för rotationsencoder (2 / 3 steg)
Steg 2: kod
Detta är koden. Genom att titta på strukturen och kommentarerna hoppas jag du hittar det lätt att anpassa för dina specifika behov!
/ *** Avbrott-baserade Rotary Encoder menyn skiss ***
* av Simon Merrett, baserat på insikt från Oleg Mazurov, Nick Gammon, rt och Steve Spence, och koden från Nick Gammon
* 3,638 byte med felsökning på UNO, 1,604 byte utan felsökning
*/
Rotationsencoder deklarationer
statisk int pinA = 2; Vår första hårdvara avbryta stift är digital stift 2
statisk int pinB = 3; Vår andra hårdvara avbryta stift är digital stift 3
flyktiga byte aFlag = 0; låter veta oss när vi väntar en stigande kanten på pinA att signalera att kodaren har kommit på en spärr
flyktiga byte bFlag = 0; låter oss veta när vi väntar en stigande kanten på pinB att signalera att kodaren har kommit på en spärr (motsatt riktning till när aFlag är inställd)
flyktiga byte encoderPos = 0; Denna variabel lagrar våra nuvarande värde av kodaren position. Ändra till int eller uin16_t i stället för byte om du vill spela in ett större utbud än 0-255
flyktiga byte oldEncPos = 0; innehåller senaste encoder position så vi kan jämföra med den aktuella behandlingen och se om det har ändrats (så vi vet när du ska skriva ut till den seriella bildskärmen)
flyktiga byte läsning = 0; någonstans att lagra direkt värden vi läser från våra avbrott pins innan kontroll för att se om vi har flyttat en hel spärr
Knappen läsning, inklusive debounce utan dröjsmål funktion deklarationer
CONST byte buttonPin = 4; Detta är den Arduino pin vi ansluter knappen för att
byte oldButtonState = hög; antar att växeln öppen på grund av pull-up resistor
CONST osignerade långa debounceTime = 10; millisekunder
osignerade långa buttonPressTime; när växeln senast ändrad staten
booleska buttonPressed = 0; en flagga variabel
Menyn och undermenyn/inställning deklarationer
byte läge = 0; Detta är vilket menyn läge vi är i vid varje given tidpunkt (översta nivån eller en av undermenyerna)
CONST byte modeMax = 3; Detta är antalet undermenyer/inställningar
byte setting1 = 0; en variabel som innehåller det värde vi sätter
byte setting2 = 0; en variabel som innehåller det värde vi sätter
byte setting3 = 0; en variabel som innehåller det värde vi sätter
/ * Obs: du kanske vill ändra settingN etc till int, float eller boolean som passar din ansökan.
Kom ihåg att ändra "void setAdmin (byte namn, * BYTE-inställning)" att matcha och förmodligen lägga några
"modeMax"-Skriv overflow kod i den "om (läge == N & & buttonPressed)" avsnitt * /
void setup() {
Rotationsencoder avsnitt av installationen
pinMode (pinA, INPUT_PULLUP); ställa in pinA som indata, drog hög logik spänningen (5V eller 3.3V för mest fall)
pinMode (pinB, INPUT_PULLUP); ställa in pinB som indata, drog hög logik spänningen (5V eller 3.3V för mest fall)
attachInterrupt(0,PinA,RISING); Ange ett avbrott på PinA, söker en stigande kanten signal och köra den "PinA" avbryta tjänsten rutin (nedan)
attachInterrupt(1,PinB,RISING); Ange ett avbrott på PinB, söker en stigande kanten signal och köra den "PinB" avbryta tjänsten rutin (nedan)
knappen avsnitt av installationen
pinMode (buttonPin, INPUT_PULLUP); Setup knappen pin
FELSÖKNING avsnitt av installationen
Serial.BEGIN(9600); Felsökning: öppnar serieport, anger datahastigheten till 9600 bps
}
void loop() {
rotaryMenu();
utföra andra loop koden här
}
void rotaryMenu() {//This handtag huvuddelen av menyn fungerar utan att behöva installera/omfattar/kompilera ett menyn bibliotek
Felsökning: Rotary encoder uppdatera displayen om vände
om (oldEncPos! = encoderPos) {/ / felsökning
Serial.println(encoderPos); / / felsökning. Seriella bildskärmen kan ibland visa ett värde strax utanför modeMax på grund av denna funktion. Menyn bör inte påverkas.
oldEncPos = encoderPos; / / felsökning
} / / FELSÖKNING
Knappen läsning med non-delay() debounce - tack Nick Gammon!
byte buttonState = digitalRead (buttonPin);
om (buttonState! = oldButtonState) {
om (millis () - buttonPressTime > = debounceTime) {/ / Dämpningstid
buttonPressTime = millis (); När vi stängt växeln
oldButtonState = buttonState; kom ihåg till nästa gång
om (buttonState == låg) {
Serial.println ("knapp stängd"); Felsökning: skriva ut som knappen har stängts
buttonPressed = 1;
}
annat {
Serial.println ("knappen öppnas"); Felsökning: skriva ut som knappen har öppnats
buttonPressed = 0;
}
} / / end om Dämpningstid tid upp
} / / slutet av staten ändra
Huvudmenyn avsnitt
om (läge == 0) {
om (encoderPos > (modeMax + 10)) encoderPos = modeMax; Kontrollera att vi inte har gått utanför gränserna under 0 och korrigera om vi har
annars om (encoderPos > modeMax) encoderPos = 0; Kontrollera att vi inte har gått utanför gränserna ovan modeMax och korrigera om vi har
om (buttonPressed) {
Läge = encoderPos; ange läget till det aktuella värdet för input om knappen har tryckts
Serial.Print ("läge markerat:"); Felsökning: skriva ut vilket läge har valts
Serial.println(mode); Felsökning: skriva ut vilket läge har valts
buttonPressed = 0; reset knappen status så en trycka resultat i en handling
om (läge == 1) {
Serial.println ("läge 1"); Felsökning: skriva ut vilket läge har valts
encoderPos = setting1; börja justera Vout från senaste börvärde
}
om (läge == 2) {
Serial.println ("läge 2"); Felsökning: skriva ut vilket läge har valts
encoderPos = setting2; börja justera Imax från senaste börvärde
}
om (läge == 3) {
Serial.println ("läge 3"); Felsökning: skriva ut vilket läge har valts
encoderPos = setting3; börja justera Vmin från senaste börvärde
}
}
}
om (läge == 1 & & buttonPressed) {
setting1 = encoderPos; spela in vad värde din kodare har förvandlats till, till inställning 3
setAdmin(1,setting1);
kod för att göra andra saker med setting1 här, kanske uppdaterar displayen
}
om (läge == 2 & & buttonPressed) {
setting2 = encoderPos; spela in vad värde din kodare har förvandlats till, till inställning 2
setAdmin(2,setting2);
kod för att göra andra saker med setting2 här, kanske uppdaterar displayen
}
om (läge == 3 & & buttonPressed) {
setting3 = encoderPos; spela in vad värde din kodare har förvandlats till, till inställning 3
setAdmin(3,setting3);
kod för att göra andra saker med setting3 här, kanske uppdaterar displayen
}
}
Genomföra gemensamma aktiviteter varje gång en inställning ändras
void setAdmin (byte namn, byte inställning) {
Serial.Print ("Inställningar"); FELSÖKNING
Serial.Print(Name); FELSÖKNING
Serial.Print ("="); FELSÖKNING
Serial.println (inställning); //DEBUGGING
encoderPos = 0; nyorientera menyindex - frivilligt eftersom vi måste overflow kontrollera koden någon annanstans
buttonPressed = 0; reset knappen status så en trycka resultat i en handling
Läge = 0; gå tillbaka till översta nivån i menyn nu när vi har angett värden
Serial.println ("huvudmenyn"); FELSÖKNING
}
Rotationsencoder avbrottstjänstens rutin för en kodare pin
void PinA() {
CLI(); STOP avbryter händer innan vi läser pin värden
läsning = PIND & 0xC; Läs alla åtta pin värden sedan skala bort alla men pinA och Pinb's värden
om (läser == B00001100 & & aFlag) {//check att vi har båda stiften på spärr (hög) och att vi förväntar oss spärr på detta stift stigande kanten
encoderPos--; stegvis minskning av kodaren läge count
bFlag = 0; återställa flaggor för nästa sväng
aFlag = 0; återställa flaggor för nästa sväng
}
annars om (läser == B00000100) bFlag = 1; signalera att vi väntar pinB att signalera övergången till spärr från fri rotation
SEI(); starta om avbrott
}
Rotationsencoder avbrottstjänstens rutin för andra kodare stift
void PinB() {
CLI(); STOP avbryter händer innan vi läser pin värden
läsning = PIND & 0xC; Läs alla åtta pin värden sedan skala bort alla men pinA och Pinb's värden
om (läser == B00001100 & & bFlag) {//check att vi har båda stiften på spärr (hög) och att vi förväntar oss spärr på detta stift stigande kanten
encoderPos ++; ökar värdet av kodaren läge count
bFlag = 0; återställa flaggor för nästa sväng
aFlag = 0; återställa flaggor för nästa sväng
}
annars om (läser == B00001000) aFlag = 1; signalera att vi väntar pinA att signalera övergången till spärr från fri rotation
SEI(); starta om avbrott
}
slutet av skiss!
Jag har använt "Felsökning" i början av varje kommentar på vilken linje som inte är kritiska att göra sin grej-menyn. Om du är nöjd med den menyfunktion, kanske du vill kommentera ut eller ta bort dessa rader för mindre kompilerade skiss storlek.
Vara medveten om att en viktig del av menynavigering feedback till användaren medan de rullar igenom inställningar och alternativ. Därför om du väljer att inte inkludera felsökning raderna, bör du antagligen använda en annan visuell indikator (e.g. LCD textvisning, lysdioder) att kodaren ingångar är navigera i menyn och ändra inställningar.
Om jag kommentera ut raderna felsökning (att notera att vissa visuell feedback fortfarande behövs för menynavigering) är den kompilerade koden runt 1.650 byte för Arduino Uno, förhoppningsvis lämnar gott om utrymme på din ATMEGA328P för mer spännande delar av din skiss!
Gå till steg 3 ta reda på hur menysystemet fungerar.