tlacitka vyhodnotenie nabeznej-dobeznej hrany

Martin dik za nakopnutie :slight_smile: presne take nieco som potreboval. Urcite dam vediet ako to ide.

Takze chlapi znovu ozivujem starsiu temu ale potreboval by som poradit. Skusal som kod ktory tu dal Martin na vyhodnotenie nabeznej hrany. Vsetko funguje ako ma po par upravach. A to by som chcel zistit ze preco. Davam tu cast kodu (cely je o par riadkov vysie) popisem co som upravil. Takze namiesto POCET_TLACITOK som musel zvysit hodnotu na 5 (povodne bola 4 vid define vysie) ak som mal hodnotu 4 fungovali mi len prve 3 tlacitka. Stvrte vobec nereagovalo. Az po zvyseni hodnoty na 5.

Dalej snazim sa pochopit cely kod ako pracuje nerozumiem cyklu for. Ten mi spravi napr 4 cykly. V kazdom cykle sa dekrementuje premena casovac_tl* o jedno alebo o celý cas ktory je ulozeny v CAS_NABEZNEJ_HRANY. Lebo cykly su 4 a cas je 25 ktory sa musi dekrementovat. Dekrementuje sa 4x po 25? Dufam ze som sa zrozumitelne vyjadril :slight_smile:

[code]

// kazdu ms pod prerusenim budes spustat nasledovny kod

void fn_vyhodnot_tl(void)
{
aktualny_stav_tl = fn_stav_tlacitok();
// POZOR, vsetko bude fungovat do poctu tlacitok 8. Pre 16 tlacitok treba zmenit typy premennych z bajtov na wordy. Casovace netreba, ak cas na ustalenu roznost stavov ma byt mensi ako 256ms.
for(uint8_t i = 0; i < POCET_TLACITOK; i++) {

// testujem pripadnu zmenu stavu
if ( TST(aktualny_stav_tl, i ) != TST(stary_stav_tl,i )  ) {
   // samotna zmena stavu nestaci,
   // este aj "casovac" musi dopocitat do nuly
   if (casovac_tl*) (casovac_tl*--;

   // ak roznost stavov trvala zelanu dobu,
   // mozeme ju akceptovat a spravit prislusne vyhodnotenia
   else {
      if TST(aktualny_stav_tl,i) {
         SET(stary_stav_tl,i );
         SET(nabezna_hrana_tl,i );
         casovac_tl* = CAS_DOBEZNEJ_HRANY;
      }
      else {
         RES(stary_stav_tl, i );
         SET(dobezna_hrana_tl,i );
         casovac_tl* = CAS_NABEZNEJ_HRANY;
      }
   }
}

// ak by sa i na jednu vzorku oba stavy rovnali,
// "casovac" sa znovu nastavi na hodnotu predvolby tu
else {
   if TST(aktualny_stav_tl,i) {
      casovac_tl* = CAS_DOBEZNEJ_HRANY;
   }
   else casovac_tl* = CAS_NABEZNEJ_HRANY;
}

} [/code]*******

Ahoj,

nerozumiem tvrdeniu, že for prebehne na 4 cykly.

Ak je počet tlačítk rovný 4, potom zbehne index 0,1,2 a 3. Index 4 samozrejme nezbehne. Ten by už bol piaty v poradí.

príkaz

casovac_tl*--; 

znamená, že sa premenná dekrementuje o 1. Výsledok je presne taký, ako keby si napísal

casovac_tl* = casovac_tl* - 1; 

**

tejto časti som neporozumel. Každý vstup má svoje samostatné počítadlo. A to sa každým zavolaním tohto kódu zníži o jedna až pokiaľ nedosiahne hodotu nula. Potom sa prednastaví na predvoľbu. Sú štyri, úplne nezávislé od seba, akurát tá predvoľba je pre ne rovnaká.

Veselé skúmanie :slight_smile:*

Ten skrateny zapis dekrementu mi je jasny. Ak aj by nebol lahko si to nastudujem v niektorej knihe C.
Co si neviem nastudovat je algoritmus kodu tak musim koumat alebo sa opytat :slight_smile:. Nieco som uz pochopil nieco nie je stale jasne.

Napr. cyklus for preco prave ako koncovy vyraz je uvedny POCET_TLACITOK? Problem je ten ze ak necham pocet 4. Vobec mi nereaguje tlacidlo ktore je definovane ako 4. Ak nastavim napr. na 3 tak nereaguje 3 a 4 tlacidlo. Az pri pocte 5 mu reaguju vsetky tlacitka.

Dalej by som sa chcel spytat kvoli comu je premena casovac_tl* definovana ako pole. V ramci skumania som ju skusil zadefinovat ako uint_8 casovac_tl ; ale kod nefungoval.

Este by ma zaujimalo ako dlho trva nabezna hrana. Vsimol som si ze sa vynuluje vo funkcii fn_bola_nabezna_hrana_v1 . Tu funkciu si volam v hlavnej slucke je to v poriadku?

Dufam ze sa lepsie vyjadrim : pri kazdom zavolani funkcie fn_vyhodnot_tl() cyklus for vykona 4x to co ma v zatvorke. Kedze si tu funkciu volam kazdu 1mS v preruseni. Cize kazdu 1mS si otestujem 4x zmenu stavu tlacitok (aktualny_stav_tl a stary_stav_tl). Je to tak?*

takže to skúsme ešte raz

uvedeny kod nie je ani nejako optimalizovany a ani si neberiem pravo na jeho uplnost, ci bezchybnost. Skladam rozny kod z roznych inych kodov. Ide len o ilustraciu principu


// nejake define pre zjednodusenie zapisu, tusim so to teraz zkopcil z kodu pre ATmega328. Je to jedno, je to len na ilustraciu postupu. Nie je dolezite, preco som si piny procesora oznacil ako D3_A, D3_B, D4_A a D4_B. S tymto prikladom to nijako nesuvisi

#define	D3_A	  0	  // PB0-ICP
#define	OUT_D3_A 	  (DDRB |= (1<<D3_A))	
#define	IN_D3_A 	     (DDRB &= ~(1<<D3_A))	
#define	SET_D3_A 	  (PORTB |= (1<<D3_A))
#define	RES_D3_A 	  (PORTB &= ~(1<<D3_A))
#define	GET_D3_A 	  (PINB & (1<<D3_A))

#define	D3_B	  7	  // PD7-AIN1
#define	OUT_D3_B 	  (DDRD |= (1<<D3_B))	
#define	IN_D3_B 	     (DDRD &= ~(1<<D3_B))	
#define	SET_D3_B 	  (PORTD |= (1<<D3_B))
#define	RES_D3_B 	  (PORTD &= ~(1<<D3_B))
#define	GET_D3_B 	  (PIND & (1<<D3_B))

#define	D4_A	  4	  // PC4-ADC4
#define	OUT_D4_A 	  (DDRC |= (1<<D4_A))	
#define	IN_D4_A 	     (DDRC &= ~(1<<D4_A))	
#define	SET_D4_A 	  (PORTC |= (1<<D4_A))
#define	RES_D4_A 	  (PORTC &= ~(1<<D4_A))
#define	GET_D4_A 	  (PINC & (1<<D4_A))

#define	D4_B	  5	  // PC5-ADC5
#define	OUT_D4_B 	  (DDRC |= (1<<D4_B))	
#define	IN_D4_B 	     (DDRC &= ~(1<<D4_B))	
#define	SET_D4_B 	  (PORTC |= (1<<D4_B))
#define	RES_D4_B 	  (PORTC &= ~(1<<D4_B))
#define	GET_D4_B 	  (PINC & (1<<D4_B))

#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))
#define RES(BAJT,BIT) ((BAJT) &= ~(1<<(BIT)))
#define NEG(BAJT,BIT) ((BAJT) ^= (1<<(BIT)))
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))

#define FALSE 0
#define TRUE 255

// pre testovanie tlacitka tieto dva casy mozu byt kludne rovnake a schovane pod jednu konstatnu
// uvadzam to tu aby si videl, ze mozes testovat cas pre kazdu hranu zvlast
#define CAS_DOBEZNEJ_HRANY 10
#define CAS_NABEZNEJ_HRANY 12

uint8_t fn_stav_tlacitok(void)
{
uint8_t input = 0;

   IN_D3_A;
   IN_D3_B;
   IN_D4_A;
   IN_D4_B;

   if (!GET_D3_A) input |= 0x0001;
   if (!GET_D3_B) input |= 0x0002;
   if (!GET_D4_A) input |= 0x0004;
   if (!GET_D4_B) input |= 0x0008;

   // tymto som si zoradil styri tlacitka pekne v bajte po jednotlivych bitoch za sebou, bez ohladu ako su lubovolne porozhadzovane v roznych vstupnych registroch fyzickych IO portov.
// to umoznuje spracovat vsetky styri tlacitka rovnakym algoritmom len s posunutym indexom v poli
   return(input);
}

void fn_vyhodnot_tl(void)
{
    aktualny_stav_tl = fn_stav_tlacitok();
    // POZOR, vsetko bude fungovat do poctu tlacitok 8. Pre 16 tlacitok treba zmenit typy premennych z bajtov na wordy. Casovace netreba, ak cas na ustalenu roznost stavov ma byt mensi ako 256ms.

   // toto je for(), ktory zabezpeci ze sa test stavu zmeny urovne postupne spravi pre vsetky styri tlacitka. Preto i bude postupne nadobudat hodnotu 0, 1, 2 a nakoniec 3
// kazde tlacitko ma svoj samostatny casovac v premennej casovac_tl*, kde i je index tlacitka od 0 do 3. Preto Ti uz nejde na hodnotu 4. Ale hodnota 4  by zodpovedala uz piatemu tlacitku (0,1,2,3 a 4)

    for(uint8_t i = 0; i < POCET_TLACITOK; i++) {

    // testujem pripadnu zmenu stavu
          // otestuje i-ty bit zodpovedajuci i-temu tlacitku v premennej aktualny_stav_tl, ktory sa zobral z premennej input z funkcie fn_stav_tlacitok() a porovnam ho na zmenu (rozdiel, nerovna sa) na i-ty bit v premennej stary_stav_tl

    if ( TST(aktualny_stav_tl, i ) != TST(stary_stav_tl,i )  ) {
       // samotna zmena stavu nestaci,
       // este aj "casovac" musi dopocitat do nuly
       if (casovac_tl*) casovac_tl*--;

       // ak roznost stavov trvala zelanu dobu,
       // mozeme ju akceptovat a spravit prislusne vyhodnotenia
      // i-ty bit v stary_stav_tl zodpovedajuci i-temu tlacitku nastavime podla i-teho bitu z bajtu aktualny_stav_tl
       else {
          // otestuje i-ty bit v premennej aktualny_stav_tl, ktory sa zobral z premennej input z funkcie fn_stav_tlacitok()
          if TST(aktualny_stav_tl,i) {
             SET(stary_stav_tl,i );
             SET(nabezna_hrana_tl,i );
             casovac_tl* = CAS_DOBEZNEJ_HRANY;
          }
          else {
             RES(stary_stav_tl, i );
             SET(dobezna_hrana_tl,i );
             casovac_tl* = CAS_NABEZNEJ_HRANY;
          }
       }
    }

    // ak by sa i na jednu vzorku oba stavy rovnali,
    // "casovac" sa znovu nastavi na hodnotu predvolby tu
    else {
       if TST(aktualny_stav_tl,i) {
          casovac_tl* = CAS_DOBEZNEJ_HRANY;
       }
       else casovac_tl* = CAS_NABEZNEJ_HRANY;
    }

ak by si to chcel spravit pre kazde tlacitko osobitne, mohol by si napisat styri krat prakticky rovnaky program ako napriklad nasledujuci, len by si v nich musel postupne zamenit IN_D3_A a GET_D3_A za IN_D3_B a GET_D3_B a tak dalej. A to su velmi minimalne zmeny v algoritme

void fn_vyhodnot_tlacitko_d3_a(void)
{
// este by sa to chcelo s touto premennou pohrat, aby sa nahodou po zapnuti zariadenia nevyhodnotil stav stlacenia tlacitka, ale tym to teraz nekomplikujme

// je jedno ako sa premenna casovac_tl_d3_a vola. Kludne sa moze volat iba casovac_tl. Zjednodusi to potom "zprehladnenie" po rozkopirovani tejto rutiny pre kazde tlacitko osobitne
static uint8_t dobezna_hrana_tl = FALSE, nabezna_hrana_tl = TRUE;
static uint8_t  novy_stav_tl, stary_stav_tl = FALSE;
static uint8_t  casovac_tl_d3_a = CAS_DOBEZNEJ_HRANY;

    // testujem pripadnu zmenu stavu
   IN_D3_A;
   // test hodnoty vstupu tlacitka bude v algoritme pouzity viac krat
   // preto si ho na zaciatku odpamatame, aby nahodou nenadobudal rozne stavy v priebehu vyhodnocovania algoritmu. Co ked by niekto nahodou tlacitko stlacil prave uprstred behu tejto rutiny? :-)
   if (GET_D3_A) novy_stav_tl = TRUE;
   else  novy_stav_tl = FALSE;
   

    if ( (novy_stav_tl == TRUE) && (stary_stav_tl == FALSE)  ) {
       // samotna rozdielnost stavu nestaci,
       // este aj "casovac" musi dopocitat do nuly
       if (casovac_tl_d3_a) casovac_tl_d3_a--;

       // ak roznost stavov trvala zelanu dobu,
       // mozeme ju akceptovat a spravit prislusne vyhodnotenia
       else {
          if (novy_stav_tl == TRUE) {
             stary_stav_tl = TRUE;
             nabezna_hrana_tl = TRUE;
             casovac_tl_d3_a = CAS_DOBEZNEJ_HRANY;
          }
          else {
             stary_stav_tl = FALSE;
             dobezna_hrana_tl = TRUE;
             casovac_tl_d3_a = CAS_NABEZNEJ_HRANY;
          }
       }
    }

    // ak by sa i na jednu vzorku oba stavy rovnali,
    // "casovac" sa znovu nastavi na hodnotu predvolby tu
    else {
       if (novy_stav_tl == TRUE) {
          casovac_tl_d3_a = CAS_DOBEZNEJ_HRANY;
       }
       else casovac_tl_d3_a = CAS_NABEZNEJ_HRANY;
    }

Ak ale pojdes cestou samosteneych programov pre kazde tlacitko a v jednom zistich chybicku, musis ju opravovat 4x a to sa este mozes niekde aj pomylit. Preto je dobre veslmi podobne cinnosti zpodobnit do takej miery, aby si ich mohol postupne zbehnut za sebou v jednej slucke.*******

Martin veeeelka vdaka za obsiahly koment ku kodu teraz uz mi je vsetko jasne.

Nasiel som aj chybu preco mi stvrte tlacitko nereagovalo ked som zadal do cyklu for pocet 4(cize i sa inkrementoval 0,1,2,3). Mal som definovane tlacitka a posledne ESCAPE definovane ako 4 mi vracalo hodnotu 16. Uplna hovadina. To ze to bola chyba mi doslo az po tvojom obsiahlom komente ked som pochopil na co je tam cyklus for a premena i. Tu je cast kodu kde bola chyba:

[code]#define POCET_TLACITOK 4

#define CAS_NABEZNEJ_HRANY 25
#define CAS_DOBEZNEJ_HRANY 41

#define SIPKA_HORE 1
#define SIPKA_DOLE 2
#define ENTER 3
#define ESCAPE 4

#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))

unsigned char klavesnica(void){
		
unsigned char aktual=0;

if((PIND&(1<<PD2))==0) SET(aktual,SIPKA_HORE);

if((PIND&(1<<PD6))==0) SET(aktual,SIPKA_DOLE);

if((PIND&(1<<PD7))==0) SET(aktual,ENTER);	

if((PINB&(1<<PB0))==0) SET(aktual,ESCAPE); 

return (aktual);
				[/code]

Takze ESCAPE už máš definované ako 0. Alebo nejaké iné tlačitko

príkaz

bajt = bajt | (1<<0)

hovorí posuň jednotku o nula miest do ľava, čo znamená, že su prekladač nechá na prvej pozícii a premenna bajt bude mať na konci nstavený bit 0 (v poradí) na hodnotu 1.

Hej hej zadefinoval som to ako nulu. Presiel som snad tisickrat ten kod ale stale mi to unikalo.

Inak velmi sikovny algoritmus na snimanie hran. Mohlo by sa to pouzit aj na enkoder?

Mohlo by sa to pouzit na hocico :slight_smile: