AVR assembler: Menysystem
Postat: 17 juni 2009, 20:56:59
Jag har byggt ett enkelt menysystem för AVR Atmega48 med 2x16-teckens LCD och tre knappar. Jag hittade inget liknande någonstans, så det var bara att börja programmera. Tänkte att den är såpass allmän att den kan vara intressant här. Kom gärna med feedback och frågor.

klicka på bilden för att se en kort film...
Jag utvecklade det först för mitt kyl/frys då jag ville kunna bläddra mellan menyer, läsa av max/min temp och kunna nollställa dessa, samt ändra "önskad temperatur" för både kyl och frys.
Tyvärr hade jag lite bråttom och slarvade ihop koden fort och jag fick med ett par buggar som jag inte orkat fixa. Det mesta fungerar dock. Mitt projekt nu är att dokumentera menysystemet, göra om koden så den blir lite mer flexibel och lättläst så det går lätt att anpassa den till andra byggen i framtiden med kanske lite mer avancerade menyer. Den ska även fungera med upp till 8 knappar hade jag tänkt (vad man nu ska ned så mycket till).
Beskrivning av funktionen:
Man kan ha visning av data i olika "mode" på displayen vilka kan bläddras mellan med hjälp av "meny" knappen. Vissa av dessa moden presenterar enbart uppgifter på LCD:n medans andra också kan mata in eller modifiera presenterad data.
Detta ska vara så flexibelt som möjligt, så att data som modifieras kan vara vad som helst, t.ex. toggla mellan "ON/OFF/AUTO" eller höja/sänka ett numeriskt värde med +/- knapparna.
Uppdatering av bilden sker antingen automatiskt med visst tidsintervall (t.ex. varannan sekund) eller direkt efter att man tryckt ner en knapp.
Att bara visa data på displayen är ganska enkelt:
När displayen ska uppdateras kollar man viken "mode" man befinner sig i för tillfället och man hoppar till motsvarande utskriftsrutin. Flera "mode" kan ju vara mycket likartade - de ska presentera data i samma format fast från olika källor. Andra "mode" kan presentera samma data på annat vis eller bara visa t.ex. programversion etc.
Vissa "mode" som är inmatningsmode sätter också en blinkande markör på lämplig plats.
Hur processorn sedan reagerar på knapptryckningar blir lite mer komplicerat så jag har ritat ett flödesschema för det:

Knappavkänningen har flera funktioner:
1) vid nedtryckning av knapp utförs motsvarande funktion i den mode man befinner sig i. Detta kontrolleras av en array (mode,knapp) som innehåller adresser till funktioner. En knapp har alltså olika funktion beroende på mode.
2) repetitionsfunktion : aktiveras efter viss tid om knapp hålls nedtryckt. Eftersom repetitionsfunktionen ska vara på/av beroende på mode och dessutom kanske ha en annan funktion än när man bara trycker kort tid så fiss en egen array (mode,key) för dessa funktioner.
3) inaktivitetstimer. kan sättas till t.ex. 60 sekunder. Sätts till 60 sek så fort man rör en knapp. räknar sedan ner. Om eller när den når 0 så utförs "inaktivitetsfunktionen". Det kan t.ex. vara att displayen återgår till default visning (mode0) och / eller att ändrade värden sparas i EEPROM.
exempel 1:
trycker man på "meny" så ökar "mode" med 1, dvs man går vidare i menyn, förutom i sista menyn då man återgår till default-mode (0). Men håller man ner mode-knappen länge så kommer man direkt till default (mode0).
exempel 2: I mode0 visas bara aktuell temperatur. knapparna "plus" och "minus" har ingen funktion här. Men i "mode1" ska man ändra ett numeriskt värde. knapparna "plus" och "minus" ökar /miskar värdet. Repetitionsfunktionen är densamma, dvs. man kan öka/minska värdet snabbt geno att hålla in en knapp.
exempel 3: i mode3 visas max / min temperaturer. Här har "minus" knappen ingen funktion vid nedtryckning, men hålls den nedtryckt i 2 sek (repetirionsfunktionen går igång) så nollställs värdet.

aktuell temperatur visas i mode0

"MENY"-knappen trycks ner och jag kommer till mode1 där jag kan ändra inställd temp på första raden. I mode2 blinkar cursorn istället på nedre raden.
Nån gång i framtiden när jag snyggat till koden och hittat buggarna så kommer jag att presentera den här.
---------------------------------------------------------------------------------------------------------
Så här ser knapptabellerna ut med mitt kyl/frys som exempel:


klicka på bilden för att se en kort film...
Jag utvecklade det först för mitt kyl/frys då jag ville kunna bläddra mellan menyer, läsa av max/min temp och kunna nollställa dessa, samt ändra "önskad temperatur" för både kyl och frys.
Tyvärr hade jag lite bråttom och slarvade ihop koden fort och jag fick med ett par buggar som jag inte orkat fixa. Det mesta fungerar dock. Mitt projekt nu är att dokumentera menysystemet, göra om koden så den blir lite mer flexibel och lättläst så det går lätt att anpassa den till andra byggen i framtiden med kanske lite mer avancerade menyer. Den ska även fungera med upp till 8 knappar hade jag tänkt (vad man nu ska ned så mycket till).
Beskrivning av funktionen:
Man kan ha visning av data i olika "mode" på displayen vilka kan bläddras mellan med hjälp av "meny" knappen. Vissa av dessa moden presenterar enbart uppgifter på LCD:n medans andra också kan mata in eller modifiera presenterad data.
Detta ska vara så flexibelt som möjligt, så att data som modifieras kan vara vad som helst, t.ex. toggla mellan "ON/OFF/AUTO" eller höja/sänka ett numeriskt värde med +/- knapparna.
Uppdatering av bilden sker antingen automatiskt med visst tidsintervall (t.ex. varannan sekund) eller direkt efter att man tryckt ner en knapp.
Att bara visa data på displayen är ganska enkelt:
När displayen ska uppdateras kollar man viken "mode" man befinner sig i för tillfället och man hoppar till motsvarande utskriftsrutin. Flera "mode" kan ju vara mycket likartade - de ska presentera data i samma format fast från olika källor. Andra "mode" kan presentera samma data på annat vis eller bara visa t.ex. programversion etc.
Vissa "mode" som är inmatningsmode sätter också en blinkande markör på lämplig plats.
Hur processorn sedan reagerar på knapptryckningar blir lite mer komplicerat så jag har ritat ett flödesschema för det:

Knappavkänningen har flera funktioner:
1) vid nedtryckning av knapp utförs motsvarande funktion i den mode man befinner sig i. Detta kontrolleras av en array (mode,knapp) som innehåller adresser till funktioner. En knapp har alltså olika funktion beroende på mode.
2) repetitionsfunktion : aktiveras efter viss tid om knapp hålls nedtryckt. Eftersom repetitionsfunktionen ska vara på/av beroende på mode och dessutom kanske ha en annan funktion än när man bara trycker kort tid så fiss en egen array (mode,key) för dessa funktioner.
3) inaktivitetstimer. kan sättas till t.ex. 60 sekunder. Sätts till 60 sek så fort man rör en knapp. räknar sedan ner. Om eller när den når 0 så utförs "inaktivitetsfunktionen". Det kan t.ex. vara att displayen återgår till default visning (mode0) och / eller att ändrade värden sparas i EEPROM.
exempel 1:
trycker man på "meny" så ökar "mode" med 1, dvs man går vidare i menyn, förutom i sista menyn då man återgår till default-mode (0). Men håller man ner mode-knappen länge så kommer man direkt till default (mode0).
exempel 2: I mode0 visas bara aktuell temperatur. knapparna "plus" och "minus" har ingen funktion här. Men i "mode1" ska man ändra ett numeriskt värde. knapparna "plus" och "minus" ökar /miskar värdet. Repetitionsfunktionen är densamma, dvs. man kan öka/minska värdet snabbt geno att hålla in en knapp.
exempel 3: i mode3 visas max / min temperaturer. Här har "minus" knappen ingen funktion vid nedtryckning, men hålls den nedtryckt i 2 sek (repetirionsfunktionen går igång) så nollställs värdet.

aktuell temperatur visas i mode0

"MENY"-knappen trycks ner och jag kommer till mode1 där jag kan ändra inställd temp på första raden. I mode2 blinkar cursorn istället på nedre raden.
Nån gång i framtiden när jag snyggat till koden och hittat buggarna så kommer jag att presentera den här.
---------------------------------------------------------------------------------------------------------
Så här ser knapptabellerna ut med mitt kyl/frys som exempel:
