ATmega16 + LCD PCD8544

C,C++,C#

Moderátori: psichac, Moderátori

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

ATmega16 + LCD PCD8544

Príspevok od používateľa jirka.jirka. » 30 Júl 2014, 00:01

Zdravím kamarádi.

Jelikož jsou prázdniny, tak abych se nenudil, řekl jsem si, že si připojím k AVR-ku (mega16), LCD z nokie 3310 (PCD8544) a DS18B20. Vše funguje, ale dostal jsem se do slepé uličky a nevím jak z ní.

Takže k věci.

Teplotu snímám, vypisuji na displej. Nic složitého. Ale chtěl jsem použít funkci: LcdSingleBar a zobrazit si jednoduchý "rtuťový teploměr".

Ale on ten BAR funguje jenom jednou cestou. A to tak, že při zahřátí čidla se mi zvětšuje ten bar. Ale zpět už ne. Nevím jak docílit toho, aby to fungovalo obousměrně.
Vytvořil jsem si funkci, ve které při změně hodnoty cele by se měl měnit i ten bar.

Celý ten bar by měl fungovat jako nulová výchylka.

Kód: Vybrať všetko

-t ----------- 0 ------------ +t

Kód: Vybrať všetko

void hlavni_display(){
//kresleni car						
		LcdLine(42, 42, 40, 47, 1); 	//vykresli svislou caru
	//vykresleni progress Baru (vodorovna cara)
	//LcdSingleBar (42, 45, 2, delka_cary, 1);		//SingleBar (zacatek x, zacatek y, tloustka, delka, On/Off); rozmery v pixelech
	//	delka_cary = cele;
		
		if (cele > 0 ){		//kresleni progress baru pro teploty vetsi nez 0
			if (cele >= 40 ){
				delka_cary = 40;LcdSingleBar (42, 45, 2, delka_cary, PIXEL_ON);
			}
			else{
				LcdSingleBar (42, 45, 2, cele, PIXEL_ON);
			}
		}
		
		if (cele == 0){LcdSingleBar (42, 45, 2, 0, 1);}	//kresleni progress baru pro teplotu rovnou nule

		if (cele < 0 ){		//kresleni progress baru pro teploty mensi nez 0
			if (cele <= -40){
				delka_cary = -40; LcdSingleBar ((42+delka_cary), 45, 2, 42, PIXEL_ON);
			}
			else{
				delka_cary = cele;
				LcdSingleBar ((42+cele), 45, 2, (delka_cary *= -1), PIXEL_XOR);
			}
		}
		
	
	//kontrola teploty	
		if (cele > 0) {tempDisplay[0] = '+';}	//je-li teplota vwtsi nez 0, zobrazi +
		if (cele < 0) {tempDisplay[0] = '-'; cele *= -1;}	//je-li teplota mensi nez 0, zobrazi -						
			
	//prepocet teploty
		tempDisplay[1] = cele/10;
		tempDisplay[2] = cele%10;
		tempDisplay[3] = '.';
		tempDisplay[4] = decicelsius%10;

	//vypis na LCD
		LcdGotoXYFont(1,5);	
		sprintf(buffer,"-42");	//- krajni rozsah
		LcdStr(FONT_1X,(unsigned char*)buffer);	//zapis znaku desetin
			LcdUpdate();
		LcdGotoXYFont(12,5);
		sprintf(buffer,"+42");	//+ krajni rozsah
		LcdStr(FONT_1X,(unsigned char*)buffer);	//zapis znaku desetin
			LcdUpdate();

	//vypis teploty na displej
		LCD_writeChar_megaFont(tempDisplay[0],  4, 1);	//cislo (jako znak '4', pozice x v pixelech (napr. 25), radek 0 az 3
		LCD_writeChar_megaFont(tempDisplay[1], 20, 1);	//cislo (jako znak '4', pozice x v pixelech (napr. 25), radek 0 az 3
		LCD_writeChar_megaFont(tempDisplay[2], 32, 1);	//cislo (jako znak '4', pozice x v pixelech (napr. 25), radek 0 az 3
		LCD_writeChar_megaFont(tempDisplay[3], 46, 1);	//cislo (jako znak '4', pozice x v pixelech (napr. 25), radek 0 az 3
		LCD_writeChar_megaFont(tempDisplay[4], 50, 1);	//cislo (jako znak '4', pozice x v pixelech (napr. 25), radek 0 az 3
			LcdUpdate();	//aktualizace displeje

	//vypis znaku teploty °C
		sprintf(buffer,"{C");	//znak desetin
		LcdGotoXYFont(12,3);	//pozice znaku stupnu "°C"
		LcdStr(FONT_1X,(unsigned char*)buffer);	//zapis znaku desetin
			LcdUpdate();			//aktualizace displeje
}
No a samotná funkce, vypadá takto:

Kód: Vybrať všetko

byte LcdSingleBar ( byte baseX, byte baseY, byte height, byte width, LcdPixelMode mode )
{
	byte tmpIdxX,tmpIdxY,tmp;

    byte response;

    /* Checking border */
	if ( ( baseX > LCD_X_RES ) || ( baseY > LCD_Y_RES ) ) return OUT_OF_BORDER;

	if ( height > baseY )
		tmp = 0;
	else
		tmp = baseY - height;

    /* Draw lines */
	for ( tmpIdxY = tmp; tmpIdxY < baseY; tmpIdxY++ )
	{
		for ( tmpIdxX = baseX; tmpIdxX < (baseX + width); tmpIdxX++ )
        {
			response = LcdPixel( tmpIdxX, tmpIdxY, mode );
            if(response)
                return response;

        }
	}

    /* Set update flag to be true */
	UpdateLcd = TRUE;
    return OK;
}
Třeba na to někdo koukne a trkne ho něco, co mě ne. :) předem díky
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: ATmega16 + LCD PCD8544

Príspevok od používateľa dxr » 30 Júl 2014, 07:05

Prekreslujes / mazes to poriadne? lebo ak tam mas chybu vtom premazavani pozadia sa javi ze len rastie
ten kod sa v hlave zle debuguje idealne si zobrat 2 hodnoty napr 20`C a -5`C alebo ine prva vyssia druha nizsia
skusit si to odladit ak nemas debuger si pogoogli macro DEBUG_print stym ze to posles seriakom von
a este do neho pridas delay napr 1-1.5sek tym to spomalis a cele to bude v MACRe debug
potom staci len odstranit DEBUG flag a debug_print moze ostat v zdrojaku ale neskompiluje sa vo finalnom kode.

niekde tu by som zacal badat

Kód: Vybrať všetko

else{
            LcdSingleBar (42, 45, 2, cele, PIXEL_ON);
else{
            LcdSingleBar (42, 45, 2, cele, PIXEL_XOR);
inak to ide napisat cistejsie ako relativna odchylka od stredu cize abs() a potom staci len jeden IF
dalsia moznost ako to napisat je ze si das nulu napr -50`C a potom je to odchylka vzdialenost od -50`C
tam potom netreba riesit ci je to pod nulou alebo nad nulou bude to len vzdialenost od pozicie -50`C
tych -50`C je len preto ze unas to nikdy nebude mozes pouzit aj inu hodnotu

cize priklad ak mas interval -50 do +50 to je 100`C+0`C cize je to 101pixelov na teplomeri (mozes mat menej)
poom dlzka ciary pre teplotu +10`C stupnov bude

signed char TEMP_MIN = -50;
signed char TEPLOTA = 0;
// priklad pre 10`C
//cele=abs(-50-(10)) // abs() tam musi byt lebo potrebujes kladne cislo tj absolutnu hodnotu
//
signed char cele = abs ( TEMP_MIN - (TEPLOTA) );
LcdSingleBar (42, 45, 2, cele, PIXEL_OFF);
LcdSingleBar (42, 45, 2, cele, PIXEL_ON);

// nezabudni ze signed char je od nejakych -127 do +127 ci ako ak potrebujes ciac musis ist do signed int.

Poznamka
Dal som to do QUOTE lebo v tagu CODE nejde zvyraznit text farebne
chcel som zdoraznit prekreslenie tej osi a nutnost pouzit signed datove typy
vyskusaj uprav a malo by to chodit.
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

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: ATmega16 + LCD PCD8544

Príspevok od používateľa jirka.jirka. » 30 Júl 2014, 10:17

Tak jsi mě přivedl k nápadu s tím překreslování toho pozadí. Tohle mě opravdu nenapadlo. :oops: Řešení je velice prosté.

Do mého kódu stačilo přidat jeden řádek a to než se začne rozhodovat, jakou velikost má teplota a vykreslovat čáry, tak smazat celý ten bar.

Kód: Vybrať všetko

LcdSingleBar (1, 45, 2, 83, PIXEL_OFF);		//prekresleni BARu, (vyhozi hodnota)
dxr Díky moc za nakopnutí
0

MiloPS3
Stály člen
Stály člen
Príspevky: 480
Dátum registrácie: 20 Apr 2011, 00:00
Bydlisko: Lazne Kynzvart / CZ

Re: ATmega16 + LCD PCD8544

Príspevok od používateľa MiloPS3 » 30 Júl 2014, 17:57

to je sice funkcni ale asi trochu zbytecny, ty ten bar vykreslujes celej 1x a pak jeste 1nou podle aktualni teploty,
placnu: rozsah teploty 0-50° , 1° = 1pixel, pro teplotu t=20° -> t pixelu ON + (50-t)pixelu OFF , takle vy vykreslis jen 1 ,treba...
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: ATmega16 + LCD PCD8544

Príspevok od používateľa dxr » 30 Júl 2014, 18:23

Super, cerpal som zo svojich skusenosti ked som pisal nieco podobne :) hlavne ze to chodi ...
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

Používateľov profilový obrázok
jirka.jirka.
Ultimate člen
Ultimate člen
Príspevky: 1538
Dátum registrácie: 17 Okt 2008, 00:00
Bydlisko: Uherské Hradiště
Kontaktovať používateľa:

Re: ATmega16 + LCD PCD8544

Príspevok od používateľa jirka.jirka. » 07 Aug 2014, 21:45

Dobrý večer pánové a dámy.
V televizi nic není, tak jsem si řekl, že bych mohl pokročit v mém malém projektíku. Takže jsem se rozhod, že se zdokonalím v programování. :)

No a teď řeším jak ušetřit co nejvíce energie.

Takže takt MCU jsem nastavil na interních 4MHz. Jako dalšího jsem využil asynchronního módu čítače/časovače (S krystalem 32.768kHz). Tak a teď by mě zajímalo, jestli můj nastavený sleep mód je dobrý, nebo to mám blbě a šlo by to upravit.

Odběr je teď cca 5mA, pokud se probudí, tak vzroste na cca 14mA.

Mám hlavní smyčku:

Kód: Vybrať všetko

/**********************************************************/
/*				    	Hlavni smycka	    			  */
/**********************************************************/
int main()
{
	inicializace();
	cti_teplotu();	//prvotni zobrazeni teploty
	set_sleep_mode(SLEEP_MODE_PWR_SAVE);
	sleep_enable();

 while(1){	

	cti_teplotu();
	flag = 0;	//vynuluje flag
	
	set_sleep_mode(SLEEP_MODE_PWR_SAVE);
	sleep_enable();
	sleep_cpu();
    sleep_mode();

 } return 0;

}
A v přerušení nastavuji toto:

Kód: Vybrať všetko

/**********************************************************/
/*				    	PRERUSENI    	    			  */
/**********************************************************/
volatile uint8_t flag = 0;
ISR(TIMER2_OVF_vect){     TCNT2 = 0;  
	
	flag++;
	if (flag >= 4){
		sleep_disable();  //zakazat sleep mod
	} 
} 
Je to vhodné, nebo bych měl něco upravit??? Za jakoukoli radu budu rád, protože tímto se skoro nikdo nezaobírá.
0

Napísať odpoveď
  • Podobné témy
    Odpovedí
    Zobrazení
    Posledný príspevok