Menu LCD1602

C,C++,C#

Moderátori: psichac, Moderátori

hmmmmos
Okoloidúci
Okoloidúci
Príspevky: 4
Dátum registrácie: 04 Aug 2014, 16:02

Menu LCD1602

Príspevok od používateľa hmmmmos » 04 Aug 2014, 16:17

Dobré odpoledne. :)

Už delší dobu doma mám svůj vlastní vývojový KIT s ATmegou8. Vše šlape. Podařilo se mi rozblikat diodu i zobrazit text na LCD,..... a stále pokračuji dál.

Nyní řeším problém, jak si jednoduše udělat MENU.

Ale nějak se nedaří.

Takt ATmegy8 je 16MHz. Jako ovládací prvek je použit rotační enkodér.

Pomocí internetu, bádání,.... jsem napsal rutinu pro ovládání menu. Ale nefunguje.

zde jsou deklarace potrebne k chodu.

Kód: Vybrať všetko

#define MAX_OPTIONS		6
char menu_buf[MAX_OPTIONS][16] = {	
"1.MENU          ", 
"2.MENU          ",
"3.MENU          ",
"4.MENU          ",
"5.MENU          ",
"6.MENU          "
};

unsigned char item = 0, item_old=0;
Zde funkce pro menu

Kód: Vybrať všetko

void disp_menu(unsigned char item){
	if(item>item_old){
		lcd_gotoxy(2,0);
		lcd_puts(&menu_buf[item-1][0]);
		lcd_gotoxy(0,1);
		lcd_putc('>');
		lcd_putc(' ');
		lcd_puts(&menu_buf[item][0]);
	}
	else if(item<item_old) {
		lcd_gotoxy(0,0);
		lcd_putc('>');
		lcd_putc(' ');
		lcd_puts(&menu_buf[item][0]);
		lcd_gotoxy(2,1);
		lcd_puts(&menu_buf[item+1][0]);	
	}
}
void chk_encoder(void){
		if (encoder > 6) {encoder = 0;}
		if (encoder < 0) {encoder = 6;}
		item = encoder;
		item    -= item<1 ? 0 : 1;	//podmínka
		disp_menu(item);
}

V nekonečné smyčce stále dokola volám:

Kód: Vybrať všetko

chk_encoder()
A teď k problému. Když program nahraju do MCU, tak se lze pohybovat v menu. Ale krajní polohy mi nějak drhnou.

Třeba, když chci po "1. MENU" poslední "6.MENU", tak se mi pod sebou zobrazi 2x "6.MENU". Obdobně i když jedu naopak. Když po "6.MENU" chci "1.MENU".

Hodnota

Kód: Vybrať všetko

encoder
, je hodnota na rotačním enkoderu. Toto mi funguje dobře.
Proto bych se chtěl zeptat, jestli někdo neporadí.

Díky moc za vaši pomoc.
0

Používateľov profilový obrázok
dxr
Ultimate člen
Ultimate člen
Príspevky: 3968
Dátum registrácie: 05 Aug 2013, 20:21
Bydlisko: V strede nicoho
Kontaktovať používateľa:

Re: Menu LCD1602

Príspevok od používateľa dxr » 04 Aug 2014, 17:15

Kukam na to ako bager na tvrdu hlinu.....

Skus napriklad chk_encoder prepisat tak aby ti vratil UP DOWN
(ci to bude nula jednicka alebo -1 +1 je uplne jedno)
potom si napis funkciu menu_rotate() ktora sa rozhodne podla co vratil chk_encoder() ako posunie premmenu MENU_ITEM
potom zavolas to prekreslenie menu s polozkou disp_menu(MENU_ITEM)

asi nejako takto

Kód: Vybrať všetko

chk_encoder();
MENU_ITEM = menu_rotate(item);
// vo funkcii  menu_rotate sa rozhodnes ci bola zmena a zavolas  disp_menu(MENU_ITEM);

len tak letmo tipujem ze problem je ta 0 a 1 z chk_encoder()
0
Naposledy upravil/-a dxr v 04 Aug 2014, 18:13, upravené celkom 1 krát.
Mahátma Ghándí: „Nejdřív tě budou ignorovat. Pak se ti budou smát. Pak proti tobě budou bojovat. Potom zvítězíš.“
čo viac dodať som taký a možeš to skúsiť vyhrať aj tak to vzdáš.. Obrázok
Arduino is popular becouse allow complex task with minimum investment

hmmmmos
Okoloidúci
Okoloidúci
Príspevky: 4
Dátum registrácie: 04 Aug 2014, 16:02

Re: Menu LCD1602

Príspevok od používateľa hmmmmos » 04 Aug 2014, 17:32

Tak se přeci jen povedlo. Sice ještě to není úplně dobré, ale posunul jsem se o kus dál.

Rutina s enkodérem, byla upravena tak, že rozlišuji směr pohybu ( smer = 1 >; smer = -1 <)

promenne

Kód: Vybrať všetko

	//PROMENNE
volatile int8_t encoder=0, smer = 1;		//hodnota enkoderu default smer, jinak nefunguje
char buffer[17];				//promenna nutna pro chod LCD displeje (sprintf)

// MENU Options
#define MAX_OPTIONS		6
char menu_buf[MAX_OPTIONS][16] = {	
"1.MENU          ",
"2.MENU          ",
"3.MENU          ",
"4.MENU          ",
"5.MENU          ",
"6.MENU          "
};

unsigned char item = 0, item_old=0;
funkce pro ovladani enkoderem

Kód: Vybrať všetko

void chk_encoder(void){
	if (flag == 0){
		if (smer == -1){
			item_old = item;
			item    -= item<1 ? 0 : 1;
			disp_menu(item);
			smer = 0;
		}
		if (smer == 1){
			item_old = item;
			item    += item>(MAX_OPTIONS-2) ? 0 : 1;
			disp_menu(item);
			smer = 0;
		}
	}
}

//zobrazeni menu

Kód: Vybrať všetko

void disp_menu(unsigned char item){
	if(item>item_old){
		lcd_gotoxy(0,0);	//pozice sipky, ktera ma byt smazana
		lcd_putc(' ');	//smazani sipky
		lcd_gotoxy(2,0);
		lcd_puts(&menu_buf[item-1][0]);
		lcd_gotoxy(0,1);
		lcd_putc('>');
		lcd_putc(' ');
		lcd_puts(&menu_buf[item][0]);
	}
	else if(item<item_old) {
		lcd_gotoxy(0,0);
		lcd_putc('>');
		lcd_putc(' ');
		lcd_puts(&menu_buf[item][0]);
		lcd_gotoxy(0,1);	//pozice sipky, ktera ma byt smazana
		lcd_putc(' ');	//smazani sipky
		lcd_gotoxy(2,1);
		lcd_puts(&menu_buf[item+1][0]);	
	}
}
Ale ještě mám jeden dotaz. Nyní když zapnu program, tak jako výchozí hodnotu v menu mám č. 2. Ale ať koukám jak koukám, tak to ne a ne najít.

Ale určitě bude chyba v tomto:

Kód: Vybrať všetko

void chk_encoder(void){
	if (flag == 0){
		if (smer == -1){
			item_old = item;
			item    -= item<1 ? 0 : 1;
			disp_menu(item);
			smer = 0;
		}
		if (smer == 1){
			item_old = item;
			item    += item>(MAX_OPTIONS-2) ? 0 : 1;
			disp_menu(item);
			smer = 0;
		}
	}
}
,
protože zde není pro to podmínka. Ale nenapadá mě, jak to upravit, aby jako výchozí byl hned první řádek (1.MENU)

-- Spojený príspevok 04 Aug 2014, 18:15 --

Tak už i tohle jsem vyřešil. ;-)

A je to jednoduché. Stačilo trošku jinak inicializovat proměnné.

Kód: Vybrať všetko

	//PROMENNE
volatile int8_t encoder=0, smer = -1;		//hodnota enkoderu
char buffer[17];				//promenna nutna pro chod LCD displeje (sprintf)

// MENU Options
#define MAX_OPTIONS		6
char menu_buf[MAX_OPTIONS][16] = {	
"1.MENU          ",
"2.MENU          ",
"3.MENU          ",
"4.MENU          ",
"5.MENU          ",
"6.MENU          "
	};

unsigned char item = 1, item_old = 0;
0

Používateľov profilový obrázok
dxr
Ultimate člen
Ultimate člen
Príspevky: 3968
Dátum registrácie: 05 Aug 2013, 20:21
Bydlisko: V strede nicoho
Kontaktovať používateľa:

Re: Menu LCD1602

Príspevok od používateľa dxr » 04 Aug 2014, 18:16

pole je pocitane od indexu 0 to je prvy prvok a ked mas item = 1 je to "2.MENU "
0
Mahátma Ghándí: „Nejdřív tě budou ignorovat. Pak se ti budou smát. Pak proti tobě budou bojovat. Potom zvítězíš.“
čo viac dodať som taký a možeš to skúsiť vyhrať aj tak to vzdáš.. Obrázok
Arduino is popular becouse allow complex task with minimum investment

Hinsi

Re: Menu LCD1602

Príspevok od používateľa Hinsi » 04 Aug 2014, 20:01

Jak by to taky mohlo chodit, když máš blbě definovanou dýlku stringu?
Je sice fajn, že máš 16byte rezervovaných pro 16 znaků na displej, a kam dáš ten ukončovací nulový znak? Bo mi vysvětli, jak teda funguje to tvý pole stringů.

hmmmmos
Okoloidúci
Okoloidúci
Príspevky: 4
Dátum registrácie: 04 Aug 2014, 16:02

Re: Menu LCD1602

Príspevok od používateľa hmmmmos » 04 Aug 2014, 23:09

Takže kdybych to chtěl mít dobře, tak by mělo stačit ubrat jeden prvke z každého řádku ne?
0

Hinsi

Re: Menu LCD1602

Príspevok od používateľa Hinsi » 04 Aug 2014, 23:15

A jak bys pak vypisoval 16. znak na řádek? :axe:

Snad místo 16byte nadefinuješ prostě 17 byte prostor.

Pokud tvůj program nepracuje s těmi textovými popisky jako se stringy a kopíruje natvrdo vždy 16 znaků, fungovat to může, ale je to škoda - jak plýtvání místem, tak programátorsky špatné či nevhodné řešení. Program se pak velice obtížně modifikuje pro třeba jiný displej s jiným počtem znaků na řádek - muselo by se toho upravit hodně, nestačilo by jen změnit textové popisky.

A poslední věc, co bych ti rád sdělil : Přesuň si tu tabulku do FLASH programové paměti. Zasíráš si takhle nedostatkovou RAM paměť. Jen těmi 6ti volbami jsi zasvinil 6x16byte = 96 byte. Až se ti menu rozroste, nevejdeš se ani za chvíli do RAMky.

Nastuduj si použití knihovny pgmspace.h.

Používateľov profilový obrázok
dxr
Ultimate člen
Ultimate člen
Príspevky: 3968
Dátum registrácie: 05 Aug 2013, 20:21
Bydlisko: V strede nicoho
Kontaktovať používateľa:

Re: Menu LCD1602

Príspevok od používateľa dxr » 04 Aug 2014, 23:18

tak tak PROGMEM inak ti to natiahne do SRAMky ktorej nieje nikdy dost.
0
Mahátma Ghándí: „Nejdřív tě budou ignorovat. Pak se ti budou smát. Pak proti tobě budou bojovat. Potom zvítězíš.“
čo viac dodať som taký a možeš to skúsiť vyhrať aj tak to vzdáš.. Obrázok
Arduino is popular becouse allow complex task with minimum investment

hmmmmos
Okoloidúci
Okoloidúci
Príspevky: 4
Dátum registrácie: 04 Aug 2014, 16:02

Re: Menu LCD1602

Príspevok od používateľa hmmmmos » 04 Aug 2014, 23:22

Takže teď co bude lepší?? :D
0

Hinsi

Re: Menu LCD1602

Príspevok od používateľa Hinsi » 05 Aug 2014, 00:54

1) nastuduj si, co to je STRING a jak se v Cčku používá
2) oprav chybnou definici počtu byte v paměti. Máš jich tam 17, ne 16, div, že to vůbec funguje. Nenadává compiler tak trochu?
3) nastuduj pgmspace.h a jak se používá.
4) přesuň všechny texty do flash pomocí PROGMEM makra
5) napiš si funkci, která texty z flashe bude číst, třeba pomocí pgm_read_byte_near()

6) pokud z bodů 3-5 nejsi moc moudrý, tak zakoupit vhodnou učebnici jazyka C a nastudovat si pointery (ukazatele). Bez toho se nedá prakticky ani uprdnout.

Napísať odpoveď