Najpierw krótki wstęp:
Zasadniczo każda porządna biblioteka jest po prostu zbiorem kilku plików, gdzie zdefiniowano tzw. klasę, w której zamknięto jak w czarnej skrzynce wszystkie zmienne i funkcje obsługujące ją właśnie. Sama klasa jest niejako szablonem do tworzenia obiektów posiadających właściwości i metody owej klasy.
Biblioteka MenuBackend składa się z 2 klas: MenuBackend i MenuItem , ta druga jest klasą zaprzyjaźnioną z pierwszą czyli w dużym uproszczeniu może korzystać ze zmiennych i funkcji klasy MenuBackend.
Obie klasy służą do zaprojektowania MENU, określenia wszystkich opcji MENU, poziomów zagnieżdżenia oraz co najważniejsze do obsługi samego MENU, czyli do przechodzenia przez wszystkie opcje i reakcji na wybranie danej opcji MENU. W prostych żołnierskich słowach masz jakieś własne menu, masz różne opcje a program musi wiedzieć jaka opcja jest aktywna i co wcisnąłeś aby zareagować na Twój wybór. Program musi także wiedzieć gdzie w drzewie menu aktualnie się znajdujesz, jaka opcja była poprzednio, co jest za nią, powyżej , poniżej, z lewej, z prawej. Pisanie takiego menu za pomocą funkcji wyboru if czy switch w głównej pętli programu jest mało wydajne i mało estetyczne. Biblioteka MenuBackend może być nam przy tym bardzo pomocna.
Aby korzystać z dobrodziejstwa biblioteki warto zaznajomić się z jej zawartością. Kopalnią wiedzy jest katalog examples gdzie w każdej porządnej bibliotece znajdziemy chociaż jeden przykład użycia biblioteki. Polecam także lekturę pliczku keywords.txt Pliczek ten składa się z opisu wszystkich nazw funkcji (metod) danej biblioteki. Słowa KEYWORD1 i KEYWORD2 są potrzebne IDE Arduino, gdyż dzięki nim masz właściwie kolorowaną składnię w edytorze. Teraz funkcja klasy jest zaznaczona tym samym kolorem jakby była funkcją wbudowaną w język C++.
Dla nas ważne są te dane:
MenuBackend KEYWORD1 - nazwa konstruktora klasy MenuBackEnd
MenuItem KEYWORD1 - nazwa konstruktora klasy MenuItem
MenuChangeEvent KEYWORD1 - funkcja obsługująca zmianę akt .pozycji w MENU
MenuUseEvent KEYWORD1 - funkcja obsługująca wybranie akt. pozycji (np. klawiszem OK)
oraz funkcje :
getRoot KEYWORD2 - pobiera nazwę korzenia drzewa ( jak w Awatarze drzewa rosną korzeniem do góry :-)
getCurrent KEYWORD2 - pobiera aktualną pozycję menu
use KEYWORD2 - przejmuje kontrolę nad akt. pozycją menu - czyli obsługuje Twój wybór
getName KEYWORD2 - pobiera nazwę pozycji menu
hasShortkey KEYWORD2 - sprawdza czy dana pozycja ma tzw. shortkey - o tym potem
getShortkey KEYWORD2 - pobiera wartość owego shortkeya
moveBack KEYWORD2 - przenosi "kursor" menu do tyły
moveUp KEYWORD2 - do góry
moveDown KEYWORD2 - w dół
moveLeft KEYWORD2 - w lewo
moveRight KEYWORD2 - w prawo
jak również funkcje służące do tworzenia "mapy" Menu:
add KEYWORD2 - dodaje pozycję w pionie
addBefore KEYWORD2 - dodaje przed
addRight KEYWORD2 - dodaje z prawej
addAfter KEYWORD2 - dodaje po
addLeft KEYWORD2 - z lewej
from KEYWORD2 - określa skąd skoczył kursor
to KEYWORD2 - określa gdzie skoczył kursor
item KEYWORD2 - określa bieżącą pozycje
Jak widać już sama nazwa funkcji podpowiada jej działanie :-)
Do dzieła - czas na nasze przykładowe Menu:
Zaprojektowałem układ Menu nieco podobny do menu jakie jest wykorzystywane w IDE Arduino:
Kod: Zaznacz cały
PLIK
Nowy
Otworz
Szkicownik
Przyklady
Zapisz
Zapisz jako
Zaladuj
Exit
EDYCJA
Wytnij
Kopiuj
Wklej
Zaznacz
Znajdz
SZKIC
Weryfikuj
Kompiluj
Importuj
EEPROM
GSM
SD
MenuBackend
NARZEDZIA
Plytka
Arduino Uno
Leonardo
Decimila
Nano
LilyPad
Odczyt
Temperatura
COM 2
COM 15
Programator
USBasp
AVR ISP
AVR ISP MK II
POMOC
Jak zaczac
Srodowisko
Dokumentacja
O Arduino
Poziom 1: PLIK, EDYCJA, SZKIC, NARZEDZIA, POMOC
Każdy z poziomów (rodzic) ma swoje dzieci (podpoziomy)
Dzieci :Importuj w poziomie SZKIC, Plytka, Odczyt i Programator w poziomie NARZEDZIA mają własne dzieci, czyli 3 poziom zagnieżdżenia menu.
Tak zbudowane menu musimy zdefiniować w programie. To oznacza iż musimy utworzyć obiekt klasy MenuBackend:
Kod: Zaznacz cały
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent); // konstruktor
Utworzyliśmy obiekt klasy MenuBackend o nazwie menu i przekazaliśmy sterowanie nim do dwóch funkcji menuUseEvent i menuChangeEvent. Pierwsza obsługuje wybór opcji z menu a druga nawigację po nim.
Następnie powołujemy do życia wszystkie opcje:(czyli obiekty klasy MenuItem).
Tutaj definiujemy każdy element menu. Możemy robić to na 2 sposoby:
- bez używania tzw. shortkey, czyli np. MenuItem P1 = MenuItem("PLIK");
- lub z shortkey, czyli MenuItem P1 = MenuItem("PLIK",1);
Shortkey to dodatkowy parametr i dzieki niemu będziemy mogli decydować co ma się
wyświetlać na wyświetlaczu. W tym przykładzie parametr shortkey identyfikuje
nam poziom zagnieżdżenia menu. Potem w dość prosty sposób za pomocą strzałek
bedziemy pomagać użytkownikowi w nawigacji po menu.
Kod: Zaznacz cały
MenuItem P1 = MenuItem(" PLIK",1);
MenuItem P11 = MenuItem(" Nowy",2);
MenuItem P12 = MenuItem(" Otworz",2);
MenuItem P13 = MenuItem(" Szkicownik",2);
MenuItem P14 = MenuItem(" Przyklady",2);
MenuItem P15 = MenuItem(" Zapisz",2);
MenuItem P16 = MenuItem(" Zapisz jako..",2);
MenuItem P17 = MenuItem(" Zaladuj",2);
MenuItem P18 = MenuItem(" Exit",2);
MenuItem P2 = MenuItem(" EDYCJA",1);
MenuItem P21 = MenuItem(" Wytnij",2);
MenuItem P22 = MenuItem(" Kopiuj",2);
MenuItem P23 = MenuItem(" Wklej",2);
MenuItem P24 = MenuItem(" Zaznacz",2);
MenuItem P25 = MenuItem(" Znajdz",2);
MenuItem P3 = MenuItem(" SZKIC",1);
MenuItem P31 = MenuItem(" Weryfikuj",2);
MenuItem P32 = MenuItem(" Kompiluj",2);
MenuItem P33 = MenuItem(" Importuj",3);
MenuItem P331 = MenuItem(" Menu Backend",4);
MenuItem P332 = MenuItem(" EEPROM",4);
MenuItem P333 = MenuItem(" KeyBoard",4);
MenuItem P334 = MenuItem(" GSM",4);
MenuItem P4 = MenuItem(" NARZEDZIA",1);
MenuItem P41 = MenuItem(" Plytka",3);
MenuItem P411 = MenuItem(" Arduino Uno",4);
MenuItem P412 = MenuItem(" Leonardo",4);
MenuItem P413 = MenuItem(" Decimila",4);
MenuItem P414 = MenuItem(" LilyPad",4);
MenuItem P415 = MenuItem(" Nano",4);
MenuItem P42 = MenuItem(" Odczyt",3);
MenuItem P421 = MenuItem(" Temperatura",4);
MenuItem P422 = MenuItem(" COM 2",4);
MenuItem P423 = MenuItem(" COM 13",4);
MenuItem P43 = MenuItem(" Programator",3);
MenuItem P431 = MenuItem(" USBasp",4);
MenuItem P432 = MenuItem(" AVR ISP",4);
MenuItem P433 = MenuItem(" AVR ISP MK II",4);
MenuItem P5 = MenuItem(" POMOC",1);
MenuItem P51 = MenuItem(" Jak zaczac",2);
MenuItem P52 = MenuItem(" Srodowisko",2);
MenuItem P53 = MenuItem(" Dokumentacja",2);
MenuItem P54 = MenuItem(" O Arduino",2);
Skoro mamy już zdefiniowane wszystkie opcje czas "nauczyć" program ich położeń na tzw mapie MENU.
Korzystamy z funkcji add addLeft i addRight. Add - dodaje w pionie, addRight - dodaje w poziomie z prawej , addLeft dodaje z lewej :
Aby zachować jakiś porządek robimy to w funkcji void menuSetup():
Kod: Zaznacz cały
void menuSetup() // funkcja klasy MenuBackend
{
menu.getRoot().add(P1); // ustawiamy korzeń Menu, czyli pierwszą opcję
P1.add(P11); // rodzic PLIK ma dziecko Nowy więc dodaje je w pionie
P11.add(P12);P11.addLeft(P1); // poniżej Nowy jest Otworz więc także w pionie
// a addLeft(P1) pozwoli nam wrócić klawiszem w lewo do PLIK
P12.add(P13);P12.addLeft(P1); // analogicznie robimy ze wszystkimi podopcjami dla PLIK
P13.add(P14);P13.addLeft(P1);
P14.add(P15);P14.addLeft(P1);
P15.add(P16);P15.addLeft(P1);
P16.add(P17);P16.addLeft(P1);
P17.add(P18);P17.addLeft(P1);
P18.addLeft(P1);P18.add(P11); // tutaj zamykamy pętlę i wracamy do pierwszej podopcji
// dzieki temu nie musimy wracać na górę przez uciążliwe
// klikanie klawisza Up
P1.addRight(P2); // po prawej dla PLIK jest EDYCJA
P2.add(P21); // rodzic EDYCJA ma dziecko Wytnij
P21.add(P22);P21.addLeft(P2); // poniżej Wytnij jest Kopiuj
P22.add(P23);P22.addLeft(P2); // analogicznie dla wszystkich podopcji
P23.add(P24);P23.addLeft(P2);
P24.add(P25);P24.addLeft(P2);
P25.addLeft(P2);P25.add(P21); // i zamknięcie pętli oraz ew. powrót do pierwszej opcji
P2.addRight(P3); // na prawo od EDYCJA jest SZKIC
P3.add(P31); // rodzic SZKIC ma dziecko Weryfikuj
P31.add(P32);P31.addLeft(P3); // poniżej Weryfikuj jest Kompiluj
P32.add(P33);P32.addLeft(P3); // poniżej kompiluj jest Importuj
P33.addRight(P331); // a tu dziecko Importuj ma już własne dziecko MenuBackend
// dodajemy z prawej, ponieważ gdybyśmy dali poniżej to zrobilibyśmy
// kolejne dziecko dla SZKIC, a w projekcie jest inaczej
P331.add(P332);P331.addLeft(P33); // poniżej MenuBackend jest EEPROM
P332.add(P333);P332.addLeft(P33); // postepujemy analogicznie
P333.add(P334);P333.addLeft(P33);
P334.addLeft(P33);P334.add(P331);
P33.addLeft(P3);P33.add(P31); // zamknięcie pętli i ew. powrót do pierwszej opcji
P3.addRight(P4); // dalej podobnie ....
P4.add(P41);
P41.addRight(P411); // kolejne dziecko, ktore ma dziecko :-)
P411.add(P412);P411.addLeft(P41);
P412.add(P413);P412.addLeft(P41);
P413.add(P414);P413.addLeft(P41);
P414.add(P415);P414.addLeft(P41);
P415.addLeft(P41);P415.add(P411); // zamknięcie pętli itd...
P41.addLeft(P4);
P41.add(P42);
P42.addRight(P421);
P421.add(P422);P421.addLeft(P42);
P422.add(P423);P422.addLeft(P42);
P423.addLeft(P42);P423.add(P421); // zamkniecie pętli itd...
P42.addLeft(P4);
P42.add(P43);
P43.addRight(P431);
P431.add(P432);P431.addLeft(P43);
P432.add(P433);P432.addLeft(P43);
P433.addLeft(P43);P433.add(P431); // zamkniecie pętli itd...
P43.addLeft(P4);P43.add(P41);
P4.addRight(P5);
P5.add(P51);
P51.add(P52);P51.addLeft(P5);
P52.add(P53);P52.addLeft(P5);
P53.add(P54);P53.addLeft(P5);
P54.addLeft(P5);P54.add(P51); // zamkniecie pętli
P5.addRight(P1); // zamkniecie pętli głównej, czyli poziomej - po POMOC jest PLIK
}
Następnie potrzebujemy jeszcze tylko 3 rzeczy:
1) Funkcji obsługi zmiany położenia "kursora" w Menu. (tutaj funkcja wskazana w konstruktorze -menuChangeEvent)
2) Funkcji obsługi wyboru danej opcji (de facto wciśnięcia klawisza OK - funkcja menuUseEvent)
3) Samej klawiatury i funkcji jej obsługi. (tutaj funkcja czytaj_1, lub czytaj_2 lub czytaj_3 )
Ponieważ w "rozmowach" w kolegami na forum spotykam się zasadniczo z 3 rodzajami używanych "klawiatur" postanowiłem przygotować 3 różne wersje funkcji czytaj, w zależności od tego który typ klawiatury używasz w swoim projekcie. I tak:
1) Funkcja int czytaj_1(int analog) obsługuje popularną klawiaturę wykorzystującą jedno wejście analogowe. Budowa takiej klawiatury oparta jest na drabince rezystorowej. Wejście analogowe odczytuje napięcie z dzielnika z i zależności od tego który klawisz wciśnięto wystawia wartość z innego przedziału. Wystarczy teraz odpowiednio zinterpretować ten stan i przełożyć na określoną wartość zwracaną przez funkcję.Parametrem funkcji jest numer wejścia analogowego.
2) Funkcja int czytaj_2(int analog1, int analog2, int pinD) obsługuje popularny moduł joysticka, gdzie pion obsługuje jedno wejście analogowe, poziom - drugie wejście analogowe a klawisz OK pin cyfrowy). funkcja zwraca wartość odpowiadającą danej akcji joysticka.
3) Funkcja int czytaj_3(int p1,int p2,int p3,int p4, int p5) wykorzystuje po prostu 5 przycisków przypiętych do wejść cyfrowych. Jeśli zamierzasz korzystać z takiej klawiaturki właśnie to pamiętaj o odpowiednim skonfigurowaniu w setupie pinMode(pin,INPUT) i digitalWrite(pin,HIGH).
Uważny czytelnik w mig zauważy, że można było przecież użyć jednej nazwy funkcji dla wszystkich trzech, dzięki mechanizmowi przeciążania funkcji. Tak byłoby lepiej i czytelniej. Cóż każdy może potem sobie to zrobić, służę pomocą w razie co :-)
Kod: Zaznacz cały
// --- wersja dla klawiatury 5-cio przyciskowej DFRobot --------------------------------------
int czytaj_1(int analog)
{
int stan_Analog = analogRead(analog);delay(30);//Serial.println(stan_Analog);
if (stan_Analog > 1000) return -1; // dla wartosci poza zakresem
if (stan_Analog < 50) return 0; // w prawo
if (stan_Analog < 150) return 1; // do gĂłry
if (stan_Analog < 300) return 2; // w dół
if (stan_Analog < 500) return 3; // w lewo
if (stan_Analog < 700) return 4; // OK
return -1; // nic nie wcisnieto
}
// --- wersja dla joysticka (2 wejscia analogowe + pin cyfrowy -------------------------------
int czytaj_2(int poziom, int pion, int pinD)
{
// poziom - nr wejścia analogowego do którego podłączona jest manetka joysticka dla ruchu lewo-prawo
// pion - nr wejścia analogowego do którego podłączona jest manetka joysticka dla ruchu góra-dół
// pinD - nr pinu cyfrowego do którego podłączony jest przycisk OK w joysticku
int stan1= analogRead(pion); {delay(60);if(stan1>0)stan1=(stan1+50)/1024+1;}
int stan2= analogRead(poziom); {delay(60);if(stan2>0)stan2=(stan2+50)/1024+1;}
int stanD=digitalRead(pinD);
if(stanD==LOW) return 4; // OK
if(stan1==0) return 2; // w dół
if(stan1==2) return 1; // do gĂłry
if(stan2==0) return 3; // w lewo
if(stan2==2) return 0; // w prawo
return -1; // nic nie wcisnieto
}
// --- wersja dla 5-ciu przycisków cyfrowych --------------------------------------------------
// dla przykładu jeśli wykorzystujesz piny: 1,2,3,11 i 12 to wołasz : czytaj_2(1,2,3,11,12)
int czytaj_3(int gora, int lewo, int ok, int prawo,int dol)
// gora - nr pinu cyfrowego do którego podłączony jest przyciski góra
// lewo - nr pinu cyfrowego do którego podłączony jest przyciski lewo
// ok - nr pinu cyfrowego do którego podłączony jest przyciski OK
// prawo - nr pinu cyfrowego do którego podłączony jest przyciski prawo
// dol - nr pinu cyfrowego do którego podłączony jest przyciski dół
{
if(digitalRead(gora)==LOW) return 1;
if(digitalRead(lewo)==LOW) return 3;
if(digitalRead(ok)==LOW) return 4;
if(digitalRead(prawo)==LOW) return 0;
if(digitalRead(dol)==LOW) return 2;
return -1;
}
Dobra, zostały jeszcze 2 funkcje:
Pierwsza obsługuje nawigację po menu. Dla przykładu wykorzystano wyświetlacz LCD 16x2. Klawisze strzałek informują użytkownika o możliwych ruchach kursora.
Kod: Zaznacz cały
void menuChangeEvent(MenuChangeEvent changed) // funkcja klasy MenuBackend
{
/* tak naprawdę to tylko tutaj przydaje się ów shortkey i służy przede wszystkim do wzbogacenia menu
o symbole strzałek w zależności co wybrano. Wszystko co tutaj się wyprawia jest pokazywane na LCD.
*/
int c=changed.to.getShortkey(); // pobieramy shortkey (1,2,3, lub4)
lcd.clear(); // bez komentarza
lcd.setCursor(0,0);
if(c==1) // jeśli to menu głowne (shortkey=1) to:
{
lcd.write(3); // strzałka w lewo
strcpy(linia1,changed.to.getName()); // tworzymy napis w pierwszej linii
lcd.print(linia1); // wyświetlamy ją
lcd.setCursor(15,0);lcd.write(4); // strzałka w prawo
lcd.setCursor(0,1);lcd.write(5); // strzałka w dół
lcd.setCursor(15,1);lcd.write(5); // strzałka w dół
}
if(c==2) // jeśli to podmenu dla dziecka - (shortkey=2) to:
{
lcd.print("*"); // rysujemy gwiazdkę
strcpy(linia2,changed.to.getName()); // tworzymy napis w pierwszej linii
lcd.print(linia1); // wyświetlamy ją
lcd.setCursor(15,0);lcd.print("*"); // gwiazdka
lcd.setCursor(0,1);lcd.write(6); // druga linia i strzałka powrotu (arrowBack)
lcd.print(changed.to.getName()); // wyświetlamy nazwe "dziecka"
lcd.setCursor(15,1);lcd.write(7); // strzałka góra-dół
}
if(c==3) // jeśli dziecko ma dziecko - (shortkey =3) to:
{
lcd.print("*"); // gwiazdka
strcpy(linia2,changed.to.getName()); // kopiujemy akt. nazwe opcji menu do zmiennej linia2
lcd.print(linia1); // i wyświetlamy pierwszą linię
lcd.setCursor(15,0);lcd.print("*"); // gwiazdka
lcd.setCursor(0,1);lcd.write(6); // druga linia i strzałka arrowBack
lcd.print(changed.to.getName()); // wyświetlamy wnuka w drugiej linii
lcd.setCursor(15,1);lcd.write(4); // strzałka w prawo bo są wnuki
}
if(c==4) // jeśli to wnuk (shortkey =4) to:
{
lcd.print("*"); // gwaizdka
lcd.print(linia2); // w pierwszej linii wyświetlamy dziecko ( czyli rodzica wnuka)
lcd.setCursor(15,0);lcd.print("*"); // gwaizdka
lcd.setCursor(0,1);lcd.write(6); // druga linia i strzałka arrowBack
lcd.print(changed.to.getName()); // wyświetlamy wnuka
lcd.setCursor(15,1);lcd.write(7); // strzałka góra-dół
}
}
Kod: Zaznacz cały
void menuUseEvent(MenuUseEvent used) // funkcja klasy MenuBackend - reakcja na wciśnięcie OK
// tutaj właśnie oddajemy menu na rzecz akcji obsługi klawisza OK
{
Serial.print("wybrano: "); Serial.println(used.item.getName()); // do testów, potem niepotrzebne
// --- ponizej kilka przykładów obsługi opcji -----------
// przykładowa reakcja na wcisnięcie klawisza OK w opcji Otworz :
if (used.item.getName() == " Otworz") // Uwaga - dokładnie taki sam ciąg " Otworz" jak w menu !!!
// bo przecież getName() pobiera nazwę
{
lcd.setCursor(1,0);lcd.print("Otwieram drzwi"); // info
digitalWrite(0,HIGH);delay(2000);digitalWrite(0,LOW); // na 2 sekundy pin 0 otrzymał stan wysoki
// czyli np. otworzyły się drzwi
lcd.setCursor(1,0);lcd.print(" ");lcd.setCursor(1,0);lcd.print(linia1); //poprzedni stan LCD
}
// A teraz coś ambitniejszego :-), bo przekazujemy sterowanie klawiaturką do innej procedury,
// w tym przykładzie programik czeka aż ustawisz jakąś temperaturę i po wciśnięciu OK wraca do pętli głównej
if (used.item.getName() == " Temperatura") // dokładnie taki sam ciąg " Temperatura"
{
int temp=21; // przykładowo 21 st. C
lcd.setCursor(0,0);lcd.write(7); // wyswietlamy nasz symbol strzałki góra-dół
lcd.print(" ");lcd.setCursor(1,0);lcd.print("Ust.temp. = "); // tekst dla użytkownika
lcd.setCursor(13,0);lcd.print(temp); // wyświetlamy akt. temperaturę
int akcja=-1;delay(1000); // zmienna pomocnicza, sterująca dla petli while
// jesli nie puścisz klawisza OK w ciągu 1 sek. to powrót do menu
while(akcja!=4) // ta pętla trwa tak długo aż wciśniesz klawisz OK
{
zm=-1;
akcja=czytaj_1(0);//delay(300); // odczyt stanu klawiatury - funkcja czytaj_1 lub czytaj_2 lub czytaj_3
// opis poniżej przy 3 różnych definicjach funkcji czytaj
if(zm!=akcja) // ruszamy do pracy tylko wtedy gdy zmienił sie stan klawiatury
{
if (akcja==1) {temp++;if(temp>99)temp=99;lcd.setCursor(13,0);lcd.print(temp);delay(300);}
// jesli akcja=1 (czyli wciśnieto klawisz w górę to zwiększono temperaturę
// ustawiono max próg i wyświetlono obecną temperaturę
if(akcja==2) {temp--;if(temp<10)temp=10;lcd.setCursor(13,0);lcd.print(temp);delay(300);}
// jesli akcja=2 (czyli wciśnięto klawisz w dół to mniejszono temperaturę
// ustawiono min próg i wyświetlono obecną temperaturę
if(akcja==4) // jeśli wciśnieto OK
{
lcd.setCursor(0,0);lcd.print("*Temperatura OK");delay(2000); // pokazujemy OK przez 2 sek.
lcd.setCursor(1,0);lcd.print(" "); // czyścimy linię
lcd.setCursor(1,0);lcd.print(linia1); // odtwarzamy poprzedni stan na LCD
}
}
} zm=akcja; // aktualizacja zmiennej zm, po to aby reagować tylko na zmiany stanu klawiatury
// tu WAŻNY MOMENT - kończy się pętla while i zwracamy sterowanie do głównej pętli loop()
}
// a tutaj obsługa pozostałych opcji :-)
// ...
// ...
}
Kod: Zaznacz cały
void setup()
{
linia1=new char[16]; // zainicjowanie dynamicznego wskaźnika do tekstu
linia2=new char[16]; // to BARDZO WAŻNE, bo wskażnik dynamiczny musi wskazywać na
// z góry określone miejsce w pamieci. Gdybyśmy tego nie zrobili
// to wcześniej czy później programik mógłby wskoczyć w nieokreślony
// bliżej obszar pamięci, co może skutkować nieodwracalnymi konsekwencjami
// łącznie z przestawieniem Fuse Bitów !!!
// Proszę uważać na wszystkie dynamiczne wskaźniki, TAKA DOBRA RADA :-)
Serial.begin(9600); // inicjacja Seriala, głównie do testów
lcd.begin(16, 2); // inicjacja LCD
lcd.createChar(3,arrowLeft); // tworzymy w pamięci LCD 5 własnych znaków dla strzałek
lcd.createChar(4,arrowRight);
lcd.createChar(5,arrowDown);
lcd.createChar(6,arrowBack);
lcd.createChar(7,arrowUpDown);
/* tu przykładowe piny cyfrowe dla 3 wersji funkcji czytaj_3(1,2,3,11,12)
pinMode(1,INPUT);digitalWrite(1,HIGH);
pinMode(2,INPUT);digitalWrite(2,HIGH);
pinMode(3,INPUT);digitalWrite(3,HIGH);
pinMode(11,INPUT);digitalWrite(11,HIGH);
pinMode(12,INPUT);digitalWrite(12,HIGH);
*/
pinMode(0,OUTPUT);digitalWrite(0,LOW); // do testów
menuSetup(); // funkcja klasy MenuBackend - tu tak naprawdę tworzymy nasze menu
menu.moveDown(); // idziemy do pierwszej opcji - PLIK, moveDown bo pierwotnie byliśmy w root
// to tak jak w Awatarze drzewa rosną korzeniami do góry :-)
}
// --- I nadszedł czas na neverending story :-) --------------------------------------------
void loop()
{
x=czytaj_1(0);delay(30); // odczytujemy stan klawiatury:
/*
Ja używam funkcji czytaj_1() bo mam akurat klawiaturkę podpiętą pod A0
Jeśli masz inna klawiaturkę to użyj funkcji czytaj_2 lub czytaj_3 - patrz opis
Ponadto musisz pamiętać że w funkcji obsługa klawisza OK - menuUseEvent(MenuUseEvent used)
także musisz użyć odpowiedniej wersji funkcji czytaj !!!
*/
if(zm!=x) // jeśli była zmiana stanu to :
{
switch(x) // sprawdzamy co naciśnięto
{
case 0: menu.moveRight();break; // jeśli naciśnięto klawisz w Prawo to przesuń menu w prawo
case 1: menu.moveUp();break; // menu do góry
case 2: menu.moveDown();break; // menu w dół
case 3: menu.moveLeft();break; // menu w lewo
case 4: menu.use();break; // wciśnięto OK więc skok do funkcji menuUseEvent(MenuUseEvend used)
// to w tej funkcji właśnie obsługujemy nasze Menu, tu sprawdzamy
// jaką opcję wybrano i tutaj tworzymy kod do obsługi zdarzenia.
}
} zm=x; // przypisanie zmiennej zm wartości x po to, aby dłuższe wciskanie tego
// samego klawisza nie powodowało ponownej generacji zdarzenia.
// program reaguje na zmianę stanu klawiatury.
}
// === KONIEC ===========================================================
Pozdrawiam