Jednorozměrné pole

Patrik
Příspěvky: 199
Registrován: 02 dub 2020, 09:58
Reputation: 0

Jednorozměrné pole

Příspěvek od Patrik » 22 dub 2020, 16:51

Ahoj,

chci se zeptat. Mám tento problém (asi s polem), jak mně to je hlášeno od kolegů - uvažuji, jestli není problém právě zde.

Mám nadeklarováno pole o 216 prvků

Kód: Vybrat vše

unsigned int pocet [216] = {};  //
Nepsal jsem tam 216x0.. To by mělo být všude, ne? Když to vypíši, tak nula je u každého prvku.

Podle mě je někde problém zde v následujícím kódu při nulování. Vlastně to pole pocet slouží jen k tomu, kolikrát uživatel přiložil kartu a prováděl odběr... může až 8x za 600 minut = 10 hodin... až bude p = 600 minut, tak dojde k nulování viz níže: Jenže zde nuluji pouze prvky pole které měly alespoň jeden vstup... ostatní byly nula, tak proč je zase nulovat zpět... ovšem možná toto je právě ta chyba měl bych nulovat vše? Ovšem i při nulování, když vypíšu do Serialu všechny prvnky pole pocet, tak jsou všechny nula... Takže problém nevidím... Přeskočím kod a pokračuji dále.

Kód: Vybrat vše

if (p == 600){
          lcd.setCursor (0, 1);
          lcd.print("                ");
          p = 0;
          for (int i = 0; i != length_card; i++) {
             if (pocet [i] == 1 || pocet [i] == 2 || pocet [i] == 3 || pocet [i] == 4 || pocet [i] == 5 || pocet [i] == 6 || pocet [i] == 7 || pocet [i] == 8){
               pocet [i] = 0;
               z [i] = 40;
             }
             if (pocet [i] == 8) {
              card [i] = card [i] - 10;
               Serial.print ("card [i] po nulovani: ");
               Serial.println (card [i]);
             }
             Serial.print ("pocet [i] po nulovani: ");
             Serial.println (pocet [i]);   
             Serial.print ("Vraceni z [i] zpet na 40: ");
             Serial.println (z [i]);
          }
          Serial.print ("p po nulovani");
          Serial.println (p);
           }
Zde pokračuji viz další kody - jestliže uživatel měl v cyklu (čas na otevření 40 s a dosáhlo tedy cyklus 1 s = tak se mu přiřadí do pole 8 i když vstupoval jen jednou, tak už poté prostě nevstoupí - přečerpal limit - cyklus je dole). pokud vstupuje poprvé tak se mu z pocet [a] k dané kartě přiřadí 1 viz kod niže

Kód: Vybrat vše

 if (z[a] == 1){
     pocet [a] = 8;
     lcd.clear();
      lcd.setCursor (0, 0);
      lcd.print ("Prekrocen denni");
      lcd.setCursor (0, 1);
      lcd.print ("limit.");
      delay (1500);
      break;
   
    }
    else
    pocet [a]++;
podle vstupu se mu přiřazuje jednotlivý čas: (doba otevření): jinak dodám, že z je nastaveno u všech na 40. Další pole z o 216 prvcich

Kód: Vybrat vše

if (pocet [a] == 1)
    {
      b = 40;
    }
    if (pocet [a] == 2 && z [a] > 35)
    {
      b = 35;
    }
    if (pocet [a] == 3 && z [a] > 30)
    {
      b = 30;
    }
    if (pocet [a] == 4 && z [a] > 25)
    {
      b = 25;
    }
    if (pocet [a] == 5 && z [a] > 20)
    {
      b = 20;
    }
    if (pocet [a] == 6 && z [a] > 15)
    {
      b = 15;
    }
    if (pocet [a] == 7 && z [a] > 10)
    {
      b = 10;
    }
    if (pocet [a] == 8 && z [a] > 5)
    {
      b = 5;
    }
     if (pocet [a] == 8)
       {
       card [a] = card [a] + 10;
       Serial.print ("Card [a]");
       Serial.println (card [a]);
       }
    
No a na základě přiřazeného b (to je vlastně čas jak dlouho daná věc zůstane otevřená, tak má být vlastně tak dlouhý odpočet)

viz cykl níže:

Kód: Vybrat vše

for (int i = b; i > 0; i = i - 1) {
      // Unlock the door and lock it after 5 seconds
      digitalWrite(RELAY_IN1, LOW);
      digitalWrite(RELAY_IN2, LOW);
      digitalWrite(RELAY_IN3, LOW);
      digitalWrite(RELAY_IN4, LOW);
      digitalWrite (LED_BLUE, HIGH);
     /* Serial.println ("Aaaaaaaaaaaa");
      Serial.println (a);
      Serial.println ("IIIIIIIIII");
      Serial.println (i); */
     if (i == 1)
      z [a] = 1;
     Serial.println (i);
      g++;
      

/*cteni = digitalRead (vyp);
      
  Serial.println (cteni);
  Serial.println (vyp);

      if (cteni == LOW)
    {
      
      lcd.setCursor (0,0);
      lcd.print ("                ");
      lcd.setCursor(3, 0);
      lcd.print("!Ukonceno!");
      Serial.println ("Ukonceno zmacnutim tlacitka");

        
       
        digitalWrite (LED_YELLOW, HIGH);
          delay(300);
         digitalWrite (LED_RED, HIGH);
         delay(300);
         digitalWrite (LED_BLUE, HIGH);
        delay(300);
         digitalWrite (LED_YELLOW, LOW);
         delay(300);
          digitalWrite (LED_RED, LOW);
          delay(300);
          digitalWrite (LED_BLUE, LOW);
          delay(300);
         
        
    //  z [a] = i;
      break;
       
     }

Jenže... Někdy dojde prostě k tomu, že má povolený přístup a ihned se to uzavře... tzn okamžitě.. Schváleno, uzavřeno... jako by v cyklu pod b byla přiřazena nula... A já nevím proč.. testuji to v domácím prostředí..


Podle mě problém nastává až při uběhnutí prvních 10 hodin a nulování prvků karet (vlastně nuluji všem přístupy na 0 a přiřazuji všem znova čas 40 s)

Děkuji moc :)

Edit: s tím časem, že se jim přístup schválí ale pak hned zamítne mi hlásí dle mě většina lidí kteří během 10 hodin právě nevyužili přístup ani jednou.. Uvažuji jestli však pomůže tam dát ještě při nulováni početu do podmínky pocet == 0... Ale jestli to pomůže, když mi to vypisuje že je vše nula..

Patrik
Příspěvky: 199
Registrován: 02 dub 2020, 09:58
Reputation: 0

Re: Jednorozměrné pole

Příspěvek od Patrik » 22 dub 2020, 21:53

Takže po celkovém restartu vše funguje bez problému...

Chtěl bych se zeptat, jestli může být problém v tom, pokud mám pole o určitém počtu prvků... Které mám deklarováno takto:

Kód: Vybrat vše

unsigned int pocet [216] = {};  // v poctu je jen cislo do 10
 
Tedy chci mít ve všech prvcích nuly. Když to vypíši, tak ve všech prvcích nuly jsou... Ale pak upravím hodnoty pole od např. pocet[100] do pocet [150] na hodnoty přiřad = 5... Následně chci všechny prvky pole pocet od pocet [0] do pocet [216] nulovat... ovšem nenuluji všechny, ale v podmínce jen ty, kde byla provedená změna.. to znamená pocet [100] až pocet [150]... Může to mít na to nějaký vliv? Může to nějak ovlivnit? Dle mého názoru ne... Vypíši prvky pole po nulování a vše je nula...

Uživatelský avatar
gilhad
Příspěvky: 778
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Jednorozměrné pole

Příspěvek od gilhad » 23 dub 2020, 02:21

Prijde mi to nejake slozite a misty divne.
- pises o poli "pocet" (ktere zabira skoro 0.5 kB ze 2 kB RAM, cili ctvrtinu), a v kodu jsou minimalne dve dalsi pole o stejnem poctu prvku (tedy pouzito pravdepodobne 3/4 RAM jen pro ta pole) a volany nejake knihovny, ktere zabiraji kdovikolik RAM taky - nemuze se stat, ze ti RAM dojde, tedy spis pri nejakem volani knihoven ti stack nahodne prepise nejake promenne (at uz v poli, nebo jinde)?
- pokud potrebujes vynulovat cele pole v RAM, je urcite rychlejsi ho cele vynulovat, nez pro kazdy prvek vyhodnocovat zda neni nulovy pomoci slozitych podminek s poli. To same pro prirazeni (predpokladam) defaultni hodnoty 40 do pole "z" (neni moc jasne, co obsahuje a ze jmena to nevyplyva)
- osobne bych pouzil spis

Kód: Vybrat vše

 if (pocet [i] >= 1 || pocet [i] <= 8) 
nez to cele vyjmenovavat. Nasledne by taky bylo lepe videt, ze pokud pri splneni teto podminky vynulujes pocet, tak dalsi podminka

Kód: Vybrat vše

if  (pocet[i] == 8)
by nemela byt nikdy splnena
- ostatne pokud "// v poctu je jen cislo do 10", tak co 9 a 10? Pokud nejsou tyto hodnoty pouzity (a neni mozne jich dosahnout), tak podminka vyse by stacila

Kód: Vybrat vše

if (pocet [i] >= 1)
pripadne jeste nazorneji

Kód: Vybrat vše

if (pocet [i] != 0)
(pokud by tam vubec mela byt) a nemoznost nasledneho

Kód: Vybrat vše

if  (pocet[i] == 8)
by byla zrejma
-

Kód: Vybrat vše

if (z[a] == 1){
     pocet [a] = 8;
 // ....
    }
    else
    pocet [a]++;
nemuze se stat, ze "z[a]" bude ruzne od 1 vickrat a tim padem pocet[a] nekontrolovane naroste? A pripadne se tak vyhne kontrole viz vyse? (bez celeho programu tezko rict)
-

Kód: Vybrat vše

unsigned int pocet [216] = {};  // v poctu je jen cislo do 10
je-li komentar pravdou, proc nepouzit treba byte a neusetrit tak pulku pameti tim polem zabrane?

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Jednorozměrné pole

Příspěvek od pavel1tu » 23 dub 2020, 07:21

Nemohu to nikde najít, ale já žiji v domění (určitě mylném), že proměnná deklarující počet položek v array je typu uint8_t, alespoň kdysi byla.
Řešilo se to někdy hodně dávno, ale nejsem si jistý. Tudíž jen 255 max., já na to narazil, když jsem zkoumal, proč někteří používají knuhovny typu arduino_array.h.

Další možnost je, že máš použito hodně paměti, ATmega ja známá svojí fragmentací paměti, pak může nastat problém, ale to se většinou zakousne.

Další možnost je, že jsi někde použil proměnnou co pracuje s polem a ta je jen typu uint8_t, kdoví co kam potom přeteče.

Co to testnout do 255 položek, nebo použít něco s větší pamětí.

PS: pomohlo by pár informací, když už tu není celý kod, typ Arduina, kolik ti to zabírá paměti atd.
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Patrik
Příspěvky: 199
Registrován: 02 dub 2020, 09:58
Reputation: 0

Re: Jednorozměrné pole

Příspěvek od Patrik » 23 dub 2020, 09:22

Děkuji pánové.

Při kompilaci programu mně je psáno využití paměti:

Sketch uses 15764 bytes (6%) of program storage space. Maximum is 253952 bytes.
Global variables use 5156 bytes (62%) of dynamic memory, leaving 3036 bytes for local variables. Maximum is 8192 bytes.

Za celou dobu programu - co se mění. Takže běží čas, který je proměných typu int: ovšem dochází pokaždé k nulování, když čas dosáhna 60 sekund. Dále se mění právě jedna proměnná typu int.. která se zvedá o jedno číslo až po číslo 600, kdy do jde k restartu všech hodnot. Tím pádem pole pocet [216] zpátky na nulové hodnoty a pole z [216] vše zpátky na 40.

Uvažoval jsem také, jestli není problém v tom, že mám právě pole z typu unsigned char.. Ale to by nemělo být.. právě jsem tam měl také integer a nechtěl jsem zabírat více paměti... Mám to momentálně jen na zkoušku, toho počtu, který může být také v unsigned char jsem si také všiml :-) děkuji.
unsigned char je vlastně to stejné, co byte, ne? Zlepším přehlednost kodu a za chvilku odepíši znova :)

Edit: přepíši ty datové typy do byte (tam kde jsou čísla max od 0 do 255).
Stav paměti nyní po změně:
Sketch uses 15676 bytes (6%) of program storage space. Maximum is 253952 bytes.
Global variables use 4940 bytes (60%) of dynamic memory, leaving 3252 bytes for local variables. Maximum is 8192 bytes.
Pro Pavla položek v poli mám max 216. Kolik polí používám: Takže unsigned long int card [216], String users [216], byte pocet [216], byte z [216]. To jsou všechna pole se kterými pracuji.
Dále dodám - pole String users [216] je po celou dobu běhu programu neměnné (retezce se neupravují). Pole card [216] je také většinou neměnné.. prostě jsou tam čísla karet, kvůli vstupu o 6 pozicích... Mění se jen ta čísla - když měl vstup vícekrát než 8x nebo čas odpočtu čas z dané karty dosáhl čísla jedna, tak k danému poli card se provede toto: card = card + 10; - vlastně aby mu to poté tu kartu zamítnulo... No, a jak po 600 minutách dochází k resetu hodnot, tak se hledají ty proměnné typu pole pocet , které měly hodnotu 8 a právě u nic se provede navíc (kromě toho, že se vynuluje pole pocet = 0 a do pole z se zase přiřadí 40 z = 40, tak se navíc provede ještě card = card [i] -10; aby byla karta opět funční.


Dále doplním.. Mohl by být problem s polem String? TOto pole je po celou dobu programu neměnné... Mám zde text max o 10 písmen v každém poli tzn users [216] = třeba mám toto users[216] = {"NovakP","NovakM", "NovakT",.... } pokud jsem to pole String dal do poznámek, tak mám najednou výsledek paměti viz kompilace:
Sketch uses 10918 bytes (4%) of program storage space. Maximum is 253952 bytes.
Global variables use 2402 bytes (29%) of dynamic memory, leaving 5790 bytes for local variables. Maximum is 8192 bytes.

A pro gilhad: Pokud vím, tak moje Arduino mega 2560 má celkovou paměť ram 8 KB, takže by neměl být problém ne? Viz také zabrání 60 % paměti ze 100 a 40 % rezerva se mi jeví celkem jako dostačující... Schválně jsem zkusil pár polí přidat a Arduino při kompilaci mě upozorní na možnou nestabilitu až v případě, kdy je zabráno více jak 81 % paměti

Patrik
Příspěvky: 199
Registrován: 02 dub 2020, 09:58
Reputation: 0

Re: Jednorozměrné pole

Příspěvek od Patrik » 23 dub 2020, 10:07

Jinak tohle je ten cyklus který používám:

Kód: Vybrat vše

for (int i = b; i > 0; i = i - 1) {
      // Unlock the door and lock it after 5 seconds
      digitalWrite(RELAY_IN1, LOW);
      digitalWrite(RELAY_IN2, LOW);
      digitalWrite(RELAY_IN3, LOW);
      digitalWrite(RELAY_IN4, LOW);
      digitalWrite (LED_BLUE, HIGH);
     /* Serial.println ("Aaaaaaaaaaaa");
      Serial.println (a);
      Serial.println ("IIIIIIIIII");
      Serial.println (i); */
     if (i == 1)
      z [a] = 1;
     Serial.println (i);
      g++;
      

cteni = digitalRead (vyp);
      
  Serial.println (cteni);
  Serial.println (vyp);

      if (cteni == LOW)
    {
      
      lcd.setCursor (0,0);
      lcd.print ("                ");
      lcd.setCursor(3, 0);
      lcd.print("!Ukonceno!");
      Serial.println ("Ukonceno zmacnutim tlacitka");

        
       
        digitalWrite (LED_YELLOW, HIGH);
          delay(300);
         digitalWrite (LED_RED, HIGH);
         delay(300);
         digitalWrite (LED_BLUE, HIGH);
        delay(300);
         digitalWrite (LED_YELLOW, LOW);
         delay(300);
          digitalWrite (LED_RED, LOW);
          delay(300);
          digitalWrite (LED_BLUE, LOW);
          delay(300);
         
        
    //  z [a] = i;
      break;
       
     }
 

Akorát uvažuji, že jsem při nahrání programu a při testech zapomněl z[a] = i v poznámkách.. to možná dělá občasny problém s přiřazovaním času... Ale nemělo by to způsobit takový problém jako nyní:

To znamená... před cyklem proběhne toto:

Kód: Vybrat vše

 if (z[a] == 1){
     pocet [a] = 8;
     lcd.clear();
      lcd.setCursor (0, 0);
      lcd.print ("Prekrocen denni");
      Serial.println ("Prekrocen denni limit");
      lcd.setCursor (0, 1);
      lcd.print ("limit.");
      delay (1500);
      break;
   
    }
    else
    pocet [a]++;
    Serial.print ("Pocet [a] po, ma byt o jedno vice");
    Serial.println (pocet [a]); 

    if (pocet [a] == 1)
    {
      b = 40;
    }
    if (pocet [a] == 2 && z [a] > 35)
    {
      b = 35;
    }
    if (pocet [a] == 3 && z [a] > 30)
    {
      b = 30;
    }
    if (pocet [a] == 4 && z [a] > 25)
    {
      b = 25;
    }
    if (pocet [a] == 5 && z [a] > 20)
    {
      b = 20;
    }
    if (pocet [a] == 6 && z [a] > 15)
    {
      b = 15;
    }
    if (pocet [a] == 7 && z [a] > 10)
    {
      b = 10;
    }
    if (pocet [a] == 8 && z [a] > 5)
    {
      b = 5;
    }
     if (pocet [a] == 8)
       {
       card [a] = card [a] + 10;
       Serial.print ("Card [a]");
       Serial.println (card [a]);
       }
a po pak ten cyklus:

Kód: Vybrat vše

for (int i = b; i > 0; i = i - 1) {
      // Unlock the door and lock it after 5 seconds
      digitalWrite(RELAY_IN1, LOW);
      digitalWrite(RELAY_IN2, LOW);
      digitalWrite(RELAY_IN3, LOW);
      digitalWrite(RELAY_IN4, LOW);
      digitalWrite (LED_BLUE, HIGH);
     /* Serial.println ("Aaaaaaaaaaaa");
      Serial.println (a);
      Serial.println ("IIIIIIIIII");
      Serial.println (i); */
     if (i == 1)
      z [a] = 1;
     Serial.println (i);
      g++;
      

cteni = digitalRead (vyp);
      
  Serial.println (cteni);
  Serial.println (vyp);

      if (cteni == LOW)
    {
      
      lcd.setCursor (0,0);
      lcd.print ("                ");
      lcd.setCursor(3, 0);
      lcd.print("!Ukonceno!");
      Serial.println ("Ukonceno zmacnutim tlacitka");

        
       
        digitalWrite (LED_YELLOW, HIGH);
          delay(300);
         digitalWrite (LED_RED, HIGH);
         delay(300);
         digitalWrite (LED_BLUE, HIGH);
        delay(300);
         digitalWrite (LED_YELLOW, LOW);
         delay(300);
          digitalWrite (LED_RED, LOW);
          delay(300);
          digitalWrite (LED_BLUE, LOW);
          delay(300);
         
        
    //  z [a] = i;
      break;
       
     }
    

To b vlastně udává čas cyklu.. jak dlouho se to bude provádět.. a do b se přiřadí hodnota dle pole z[a] = 40... to znamená... např... pan Novák má card [100], string [100] označuje nováka jeho pocet [100] má být nula a navysit se až při pruběhu cyklu o + 1... z [100] je rovno 40... A ten čas 40 co je v z se uklada na zaklade kdy zmačkne tlacitko a pokud ho nezmáčkne a čas mu dojde až do 1 tak se přiřadí do pole pocet[100] = 8 a tím se mu zablokuje karta, protože se provede card[100] = card[100] + 10;... ovšem ted nevím proč mám // z[a] = i; v poznámkách... na to jsem zapomněl to odstranit..

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Jednorozměrné pole

Příspěvek od kiRRow » 23 dub 2020, 10:20

Nebylo by lepší a přehlednější to řešit pomocí datových struktůr, než pomocí polí ?

Patrik
Příspěvky: 199
Registrován: 02 dub 2020, 09:58
Reputation: 0

Re: Jednorozměrné pole

Příspěvek od Patrik » 23 dub 2020, 13:29

Hmm, tak daleko ještě nejsem.. Mohl bys mně dat nějaký příklad jak bys to například řešil?

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Jednorozměrné pole

Příspěvek od pavel1tu » 23 dub 2020, 13:47

Patrik píše:
23 dub 2020, 13:29
Hmm, tak daleko ještě nejsem.. Mohl bys mně dat nějaký příklad jak bys to například řešil?
Já to řeknu takto,
nevíme o co jde - co vše potřebuješ nějak jednoduše řečeno řešit - prostě mapu programu co kdy a jak, nebo prostě co má zařízení dělat
z kousků kodu které nikomu nejdou nahrát do arduina je mi nanic, tak to dávej tak, aby ten kus šel nahrát a ladit

PS: připomíná mi to únikovku co teď vyrábíme, ale jedeme na DUE + asi až 30x Nano, mezi sebou BT
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Patrik
Příspěvky: 199
Registrován: 02 dub 2020, 09:58
Reputation: 0

Re: Jednorozměrné pole

Příspěvek od Patrik » 23 dub 2020, 13:53

Dobře Pavle, přidám celý kod.. jen odmažu jména a popíši co to má vlastně dělat... Já jinak mám v tom kódu trošku nepořádky, tak si sám musím v tom udělat pořádek :) Moment

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 14 hostů