František Pospíšil

Na svých stránkách popisuji cesty, kterými jsem došel k zamýšleným cílům. Cíle se občas během cesty změnily.

Programování

Čítač s GPS normálem – 4. Displej

Koncepce

Rozlišení měřícího přístroje, to znamená počet číslic na displeji, by měl odpovídat normálu, s kterým je měřená hodnota porovnávána. To znamená, že když mám v čítači jednoduchý krystalový oscilátor, bez teplotní kompenzace, nemá smysl mít na displeji víc než pět míst.

Kmitočtovým normálem popisovaného čítače je GPSDO. Vzhledem k jeho stabilitě budeme schopni měřit kmitočet 1GHz s rozlišením 0,01Hz. 1GHz, to je jednička, devět nul a k tomu dvě desetinná místa. Celkem je potřeba minimálně dvanácti-místný displej. Se znaky Hz to je čtrnáct míst. Výšku číslic chceme větší než 10mm a velikost předního panelu přístroje by měla být asi 220 x 80mm. K tomu je potřeba mít na panelu pár tlačítek pro ovládání čítače. Alfanumerický, ani TFT displej potřebných rozměrů s dostatečnou velikostí znaků jsme nenašli. Zajímavé by bylo použití digitronů, ale to bychom se připravili o možnost zobrazovat alfanumerické znaky. Takže použijeme 14-ti segmentový LED displej sestavený ze sedmi dvoumístných zobrazovačů 5241AS.

Výška znaku na zobrazovači je 0,54inch, to je 14mm. Rozteč řad nožiček zobrazovače je 15mm, takže se pod zobrazovače vejdou integrované obvody v 16-ti pinovém SSOP pouzdru, kterými bude displej ovládán. Deska plošných spojů potom může být úzká a dlouhá, tak jak bylo plánováno. Zobrazovače displeje budou napájeny sadou posuvných registrů a mikroprocesor je bude ovládat po sériové lince.

Součástky budou rozmístěny z obou stran dvouvrstvého plošného spoje, to pro ruční osazování není problém. Tlačítka a LEDky jsme uspořádali tak, aby se na panel vešly nápisy a do výřezu v desce BNC konentor.

Zapojení displeje

Čtrnáct znaků po čtrnácti segmentech, k tomu desetinné tečky a malý šestimístný displej postavený ze sedmisegmentů, to je 258 LEDek. K tomu pár dvoubarevných LEDek jako indikace provozních stavů čítače. Není potřeba aby svítily všechny najednou, použijeme multiplex. V jednom okamžiku bude svítit 1/4 diod, skupiny se budou střídat po 4ms. To je pořád ještě 70 diod, které je potřeba připojit k nějakému budiči. Ten bude ovládán po sériové lince. Existují specializované obvody, v podstatě velké posuvné registry, určené pro ovládání displejů. My použijeme běžně dostupný 74HC595, který se v SSOP pouzdru vejde pod displej. Posuvných registrů bude deset a budou ovládat anody zobrazovačů.

Katody budou ovládány tranzistorovým polem ULN2803. Budou potřeba tři, aby bylo možné proud rozdělit mezi jednotlivá pouzdra.

Úkolem mikroprocesoru bude, každou čtvrtou milisekundu připojit katody další ze čtyř skupin LEDek s pomocí dekodéru 74HC238. K zobrazení celého čísla je potřeba 16ms, to je 62,5Hz. Dost vysoký kmitočet na to, aby lidské oko nepoznalo blikání a nízký na to, aby měl procesor čas na ostatní práci.

Pro anody displeje procesor před přepnutím katod nahraje do posuvných registrů další skupinu čísel a signálem RCK překlopí klopné obvody typu D, které jsou na výstupu obvodů 74HC595.

Zapojení klávesnice

Pro ovládání čítače bude potřeba asi deset tlačítek. Tolik volných vývodů na procesoru nemáme a ani se mi nechce používat moc široký kabel k propojení desky displeje s hlavní deskou čítače. Tlačítka by bylo možné multiplexovat, ale to je pořád ještě 7 drátů. Procesor má integrovaný AD převodník, co kdybychom jej použili? I spotřeba místa na desce plošných spojů bude menší, když nebudu muset z tlačítek vytvářet síť. Když každé tlačítko připojí svůj rezistor do odporového děliče, kterým se vytvoří příslušné napětí, bude to fungovat. Nevýhoda tohoto řešení je, že stisk většího množství tlačítek s velkými hodnotami rezistorů odpovídá stisku jiného tlačítka s malou hodnotou rezistoru. Ale to v našem případě nevadí.

Odporový dělič je napájen svým stabilizátorem, aby klávesnice nebyla rušena provozem displeje.

Pořadí anod, připojených k posuvným registrům je upraveno tak, aby bylo optimalizováno využití místa na plošném spoji. I jednotlivé LEDky jsou do sítě zapojeny s ohledem na jejich umístění na desce. V programu to pak nějak vyřeším.

Programování displeje

Pro práci s displejem je potřeba mít v paměti uloženu znakovou sadu pro 14-ti segmentové zobrazovače. K tomu se bude hodit pole dat. Překladač jazyka C po zahájení běhu programu pole dat uloží do paměti RAM a čísla bude číst z ní. To je škoda, paměť RAM je malá a navíc by znaková sada mohla být během práce programu poškozena. V knihovně pgmspace.h jsou funkce, kterými je možné přesvědčit překladač, aby pole dat nechal v paměti ROM. Takže začátek znakové sady může vypadat např. takto:

const uint8_t AsciiChar[] PROGMEM = {
    0b00000000, 0b00000000, // 32 - prazdny znak
    0b10100000, 0b00000000, // 33 - ! znak " leve
    0b10000000, 0b00000001, // 34 - znak " prave
    0b11000100, 0b00000010, // 35 - # znak Anteny
    0b10100101, 0b01101100, // 36 - znak $
    0b10011000, 0b01000100, // 37 - % znak Alfa
    0b01111000, 0b00000100, // 38 - & znak Beta

Text, který bude zobrazován, si připravíme do pole dat v paměti RAM. Pro řetězec znaků bude potřeba funkce:

void Show_WriteString( const char* string, uint8_t x )
{    
    while( *string != '\0' )
    {
        DisplayArray[ (( 19 - x ) * 2 ) + 0 ] = pgm_read_byte(&( AsciiChar[ (( *string - 32 ) * 2 ) + 0 ]));    // ulozi data do pole, zobrazi se to v preruseni casovace
        DisplayArray[ (( 19 - x ) * 2 ) + 1 ] = pgm_read_byte(&( AsciiChar[ (( *string - 32 ) * 2 ) + 1 ]));
        string++;
        x++;
    }
}

Další funkce budou potřeba pro zobrazení čísel. Nevím, kdy tyto funce budou spuštěny, ani jak dlouho budou trvat. Prostě když program čítače chce zobrazit nové číslo, nebo text, tak funkci zavolá.

Vlastní ovládání obvodů displeje je náročné na čas, nová data do posuvných registrů musí být posílána pravidelně, aby displej neblikal. K tomu je na časovači procesoru nastavena perioda 4ms a časovač zavolá svoji obsluhu přerušení, ve které se z pole dat odešle jedna čtvrtina. Problém je, že znaky v poli dat jsou uspořádány postupně a do registrů je potřeba to posílat na přeskáčku.

for( DisplayCounter1 = 0; DisplayCounter1 < 5; DisplayCounter1++ )      //  smycka posilani dat na posuvne registry
{
    DisplayData = DisplayArray[ ((( DisplayCounter1 << 2 ) + DisplayCounter0 ) << 1 ) + 1 ];
    for( CountInt = 0; CountInt < 8; CountInt++ )
    {
        DisplayClk_clr;
        if ( (DisplayData&0x80) == 0x80 ) DisplayData_set
        else DisplayData_clr;
        DisplayData <<= 1;
        DisplayClk_set;
    }
    DisplayData = DisplayArray[ ((( DisplayCounter1 << 2 ) + DisplayCounter0 ) << 1 ) ];
    for( CountInt = 0; CountInt < 8; CountInt++ )
    {
        DisplayClk_clr; 
        if ( (DisplayData&0x80) == 0x80 ) DisplayData_set
        else DisplayData_clr;
        DisplayData = DisplayData << 1;
        DisplayClk_set;
    }
}

V programu je použito dost hloupé posílání dat na posuvné registry ve smyčkách s proměnnou CountInt. Přitom procesor má sériovou linku SPI a displej je připojen tak, aby bylo možné ji využít. Jenomže když jsem SPI v programu využil, tak diody v nepravidelných intervalech bliknou. Nevím proč.

Programování klávesnice

AD převodník klávesnice je spouštěn časovačem v intervalu 4ms stejně jako displej. AD převodník po ukončení převodu volá svoje přerušení, ve kterém se vyhodnotí, jestli bylo něco stisknuto

ISR( ADCA_CH0_vect )
{
    KeyNum = ADCA_CH0_RES;
    if(  KeyNum <  400 ) KeyNum = 17; else
    if(( KeyNum >  400 ) && ( KeyNum <  460 )) KeyNum =  1; else    // 6k8, odpory pro jednotlivá tlačítka R81 = 180k
    if(( KeyNum >  580 ) && ( KeyNum <  630 )) KeyNum =  2; else    // 12k
    if(( KeyNum >  680 ) && ( KeyNum <  730 )) KeyNum =  3; else    // 15k
    if(( KeyNum >  850 ) && ( KeyNum <  960 )) KeyNum =  4; else    // 22k
    if(( KeyNum > 1190 ) && ( KeyNum < 1280 )) KeyNum =  5; else    // 33k
    if(( KeyNum > 1530 ) && ( KeyNum < 1590 )) KeyNum =  6; else    // 47k
    if(( KeyNum > 1730 ) && ( KeyNum < 1790 )) KeyNum =  7; else    // 56k
    if(( KeyNum > 1980 ) && ( KeyNum < 2050 )) KeyNum =  8; else    // 68k
    if(( KeyNum > 2200 ) && ( KeyNum < 2290 )) KeyNum =  9; else    // 82k
    if(( KeyNum > 2500 ) && ( KeyNum < 2610 )) KeyNum = 10; else    // 100k
    if(( KeyNum > 2780 ) && ( KeyNum < 2880 )) KeyNum = 11;         // 120k
    else KeyNum = 0;
    if(( Status&0x10 ) && ( KeyNum > 1 )) KeyNum = 0;               // kdyz je Standby, tak se reaguje jenom na klavesu Standby
    if(( KeyNum == KeyBuffer ) && ( KeyResult == 0 ) && ( KeyNum > 0 )) KeyCounter++;
    else
    {
        KeyCounter = 0;
        KeyBuffer = KeyNum;
    }
    if( KeyCounter == 5 )
    {
        KeyCounter = 0;
        KeyResult = KeyNum;
        KeyTimer = 60;                                              // cela na dalsi stisk
    }
}

K naměřenému napětí je v proměnné KeyNum přiřazeno tlačítko. V proměnné KeyCounter jsou počítána jednotlivá měření, pět krát je měřeno a porováváno s předchozím tlačítkem, jehož hodnota je v KeyBuffer. Až po pátém měření je jistota, že stisk je stabilní a hodnota tlačítka je uložena do KeyResult. S touto hodnotou pracuje hlavní program čítače.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *