Arduino schéma - arduino.sk

Prvky pola

Programovanie arduina
Príspevky: 33
Registrovaný: Pia 26. Jún 2015 21:17:41

Re: Prvky pola

Poslaťod barado » Uto 05. Jan 2016 20:07:01

budvar10 píše:Barado je to trochu veľa písania na mňa ale pokúsim sa.
1. Áno premenná vytvorí miesto, ale tie stringy budú zaberať miesto vo flash aj v RAM. Je to konštanta a každý pokus o jej zmenu je "memory access violation", samozrejme na Atmege sa dá aj to. Ale toto súvisí aj s bodom 3. Dá sa predsa zadefinovať dvojrozmerné pole number[10][11] a máš pole pre 10 mobilných čísel. Globálna premenná bude automatický inicializovaná nulami.
2. NULL proste zapíšeš do pamäťového miesta, ktoré môže patriť inej premennej, je to fatálna chyba. Znakové reťazce nemajú info o max. dĺžke, končia nulou a programátor musí ustriehnuť aby nikde v programe sa nepresiahla max dĺžka. RAM je usporiadaná ako reťaz bajtov a premenné v nej sú ukladané jedna za druhou. Dá sa aj zistiť toolom (napr. avr-objdump), čo nasleduje za serialString.
3. Ty chceš uložiť serialString do number[0] ale to sa nestane, resp. inak než si myslíš. number[0], rovnako aj ostatné, je pointer na pamäťové miesto, kde je uložený reťazec "0999999999" - konštanta. Ty ale neprepíšeš tento reťazec, len zmeníš pointer na identický so serialString. Od tej chvíle čo je v jednom, je aj v druhom, keďže obidva ukazujú na to isté miesto v RAM. Céčko je low level jazyk a reťazce typu char * sa nepresúvajú takto. Proste sa to musí robiť bajt po bajte alebo je na to funkcia strcpy, memcpy....
Existuje class String a tam to samozrejme funguje cez =, ale to je objektová úroveň a ak by si šiel do podrobností, tiež je za tým kopírovanie bajt po bajte.

Ešte pre vysvetlenie:
1. number je smerník na pole smerníkov = adresa v RAM kde začína number[0], number[1]....
2. number[0] je smerník na reťazec = adresa v RAM, kde sa nachádza 0999999999 a NULL; takto to je aj s number[1] atď
3. serialString je smerník/adresa na reťazec desiatich bajtov v RAM.
Jednoduchým pokusom zistíš, že ak po tomto príkaze number[0]=serialString; zmeníš obsah serialString, zmení sa aj number[0].



DAKUJEM

Kód: Vybrať všetko
#include <EEPROM.h>

// premenne
int index;               //index precitaneho cisla zo serial.read
char serialString[16];   //buffer pre nacitavanie zo serial
char number[10][11];     //dvojrozmerne pole 


void setup()
{
  Serial.begin(9600);                                              //start serial
}

void loop()

  if (Serial.available())               //Test na prichod stringov
  {
    char ch=Serial.read();              //ulozenie jedneho stringu do premennej
    if(index<10 && ch>='0' && ch<='9')  //test na to ci to je cislo
    {
      serialString[index]=ch;           //ulozim string do buffera s prislusnym indexom
      index++;                          //zvysenie indexu
    }
    else                                //ak nie je cislo alebo je zadanych viac ako 10 cisel
    {
      serialString[index]=0;            //terminating null
      index=0;                          //reset indexu
      Serial.print("Precital som ");    //vypis na serial
      Serial.println(serialString);     //vypis co som nacital zo serial portu
      strcpy(number[0], serialString);  //ulozenie precitaneho cisla do pola cislo 0
      Serial.println(number[0]);        //vypis prveho pola cisiel
      Serial.println(number[1]);        //vypis druheho pola cisiel
      eepromSaveAdress();               //ulozenie do eeprom
      eepromReadAdress();               //nacitanie do eeprom
      Serial.println(number[1]);        //vypis druheho pola cisiel uz nacitaneho z eeprom
 
    }
  }
}

void eepromReadAdress(void)              //nacitanie adries z eeprom
{
  static int eepromAdress;
  eepromAdress=0;
  for(int i=0;i<10; i++)
  {
    number[1][i]=EEPROM.read(eepromAdress); 
    eepromAdress++;
  }
  eepromAdress=0;
  number[1][10]=0;
}

void eepromSaveAdress(void)
{
  static int eepromAdress;
  eepromAdress=0;
  for(int i=0;i<11; i++)
  {
    EEPROM.update(eepromAdress,number[0][i]);
    eepromAdress++;
  }
}

Obrázok užívateľa
Príspevky: 43
Registrovaný: Str 25. Feb 2015 22:19:54
Bydlisko: Fintice

Re: Prvky pola

Poslaťod dzooky » Uto 05. Jan 2016 22:30:55

Otazocka
Ked budem mat takto dvojprvkove pole, viem naraz vyvolat cele cislo napr check_numbers[1][1-11] ci len separe jednotive cisla daneho cisla.
Pytam sa preto, ze porovnavanie resp overovanie cisel ma nastarosti GSM kniznica ktora porovnava cele cislo alebo budem musiet zaviest premennu, kde si vyskladam dane cislo a to poslem porovnavat.

Príspevky: 33
Registrovaný: Pia 26. Jún 2015 21:17:41

Re: Prvky pola

Poslaťod barado » Uto 05. Jan 2016 22:51:18

dzooky píše:Otazocka
Ked budem mat takto dvojprvkove pole, viem naraz vyvolat cele cislo napr check_numbers[1][1-11] ci len separe jednotive cisla daneho cisla.
Pytam sa preto, ze porovnavanie resp overovanie cisel ma nastarosti GSM kniznica ktora porovnava cele cislo alebo budem musiet zaviest premennu, kde si vyskladam dane cislo a to poslem porovnavat.


Ahoj. Skusil som toto: - nefungovalo
Kód: Vybrať všetko
      if (number[0] == number[1])
      {
        Serial.println("cisla 0 a 1 su rovnake");
      }
      else
      {
        Serial.println("cisla 0 a 1 su rozdielne");
      }
      if (number[0] == number[2])
      {
        Serial.println("cisla 0 a 2 su rovnake");
      }
      else
      {
        Serial.println("cisla 0 a 2 su rozdielne");
      }     


a skusil som toto: - fungovalo
Kód: Vybrať všetko
      if (strcmp(number[0], number[1])==0)
      {
        Serial.println("cisla 0 a 1 su rovnake");
      }
      else
      {
        Serial.println("cisla 0 a 1 su rozdielne");
      }
      if (strcmp(number[0], number[2])==0)
      {
        Serial.println("cisla 0 a 2 su rovnake");
      }
      else
      {
        Serial.println("cisla 0 a 2 su rozdielne");
      }     

Obrázok užívateľa
Príspevky: 133
Registrovaný: Štv 06. Nov 2014 12:06:09

Re: Prvky pola

Poslaťod budvar10 » Str 06. Jan 2016 10:07:39

@barado
Všetky tieto aritmetické, logické operácie atď, sa so znakovými reťazcami nedajú robiť. Je to to isté ako so už písal:
if (number[0] == number[1]) tu dôjde k porovnaniu adries reťazcov. Po lopate povedané, či sú dané reťazce na tom istom mieste v RAM, t.j. či je to to isté miesto. Ak chceš zistiť či sú rovnaké obsahovo, musíš použiť napr. tú funkciu strcmp.

Takéto porovnanie if (number[0] == number[1]) by fungovalo pri objektoch String. Avšak so String by ste zas mohli mať problémy s rýchlym vyčerpaním pamäte, ak celkom nerozumiete ako to funguje.

@dzooky
Neviem, či ťa dobre rozumiem, ale ak máš dvojrozmerné pole check_numbers[10][11] tak to je ako v krížovke:
check_numbers[1][1] je jeden znak povedzme '9',
check_numbers[1] je jeden celý riadok "0909333666", t.j. celé telefónne číslo v tvojom prípade a môžeš s tým rovno operovať.
Netreba nič vyskladať.

Neberte to v zlom páni, ale odporúčam vám prečítať si niečo ako Kernighan & Ritchie: Programovací jazyk C. Nie je to veľmi hrubá kniha. A ešte ma napadlo, že tieto veci sa dajú skúšať aj na hocijakom PC a pekne debugerom ísť po príkazoch a sledovať, čo sa tam deje. Toto je štandard ANSI C, takže si stačí nainštalovať nejaké vývojové prostredie. Je ich plno voľne dostupných, aj Microsoft Visual Studio je už free. Pre Linux je to trocha komplikovanejšie, treba zvlášť stiahnúť gcc, ale to vlastne máte s Arduino IDE a potom napr. NetBeans (tu celkom nie som doma).

Príspevky: 33
Registrovaný: Pia 26. Jún 2015 21:17:41

Re: Prvky pola

Poslaťod barado » Str 06. Jan 2016 13:43:02

@budvar10
Uz ako maly som pokukoval o moznostiach tychto malych masiniek. Vyrastal som v dobe basicu a pascalu. Dokonca sme v skole robili na diernych stitkoch. No nejak som to zanedbal a tak som sa k priamemu kontaktu s AVR dostal az minuly rok. Aj to len prostrednictvom ARDUINA. Som uz starsi a nikdy sa uz nedostanem svojimi vedomostami na uroven, aby som mohol priamo programovat AVR v C-cku a o assembleri uz ani nehovorim.
No ARDUINO je tak jednoduche, ze dava nam LAMOM aspon si splnit male sny.
Su vsak ludia, ktory Arduinom opovrhuju. Lenze tu sme na http://arduino.sk a vyskyt nas LAMOV je tu pomerne velky.
Preto dakujem tym, ktory sa vedia nad tym povzniest a su ochotni poradit s problemom, ktory na prvy pohlad nevieme vyriesit. Ano daju sa precitat tisicky stran knih, no ak s tym nerobim v jednom kuse, tak dnes to viem, ale zajtra uz mozno nie.
Knihu uz mam vytlacenu a idem skusit studovat. Dakujem.
A neboj neberiem to osobne. Som rad, ze poradis.

Obrázok užívateľa
Príspevky: 133
Registrovaný: Štv 06. Nov 2014 12:06:09

Re: Prvky pola

Poslaťod budvar10 » Str 06. Jan 2016 19:55:30

Barado, nechcel som vás "pérovať" alebo čo, bolo to odporúčanie. Poradím rád, ak viem. Aj preto som na fóre a s lamami nemám problém. V každom prípade, tie základy C si treba prečítať. Tá kniha, to je taká biblia C.

Príspevky: 33
Registrovaný: Pia 26. Jún 2015 21:17:41

Re: Prvky pola

Poslaťod barado » Str 06. Jan 2016 20:39:54

Nie to neber tak, že som sa urazil. To nie. Kniha veľa poradí. Veď hneď na druhej strane je "You mean I have to call a function to compare two character strings?". Takže keby som ju čítal a samozrejme niekedy s tými stringami robil, tak by som to vedel. Zas na druhej strane poskytuje príliš veľa informácií a pre arduino sú mätúce. Napríklad printf. Tak reku hneď skúsim nech viem, čo to robí.
Kód: Vybrať všetko
printf("Hello!");

Arduino IDE to normálne skompiluje. Tak reku paráda naozaj to funguje.
Tak dávam.
Kód: Vybrať všetko
lcd.printf("Hello!");

No Arduino IDE to kompiluje s chybou. Potom samozrejme hneď ma trkne, že čo robím za sprostosti, veď knižnica lcd takú funkciu nepozná.
Takže keby pošlem do arduino to printf("Hello!");, čo to vlastne v arduine urobí? Neviem... A zas som na pochybách... Viem, že v počítači by to na MSDOS konzolu vypísalo Hello!
Ale to už sme dosť mimo tému a ospravedlňujem sa dzooky-mu, že mu zasieram vlákno.

Obrázok užívateľa
Príspevky: 43
Registrovaný: Str 25. Feb 2015 22:19:54
Bydlisko: Fintice

Re: Prvky pola

Poslaťod dzooky » Str 06. Jan 2016 21:50:21

budvar10 píše:@dzooky
Neviem, či ťa dobre rozumiem, ale ak máš dvojrozmerné pole check_numbers[10][11] tak to je ako v krížovke:
check_numbers[1][1] je jeden znak povedzme '9',
check_numbers[1] je jeden celý riadok "0909333666", t.j. celé telefónne číslo v tvojom prípade a môžeš s tým rovno operovať.
Netreba nič vyskladať.


Dik za info
Vypis mi ide ale rovnakym sposobom tam priradit hodnotu to mi uz nejde.
Kód: Vybrať všetko
check_numbers[i] = "0123456789";

Tu vypise
Kód: Vybrať všetko
error: invalid array assignment
   check_numbers[1] = "0123456789";
                    ^
exit status 1
invalid array assignment


Dajaku knizocku o Ccku mam, no pamatam ze na vyske to bolo daco pre mna nezrozumitelne
Zacinal som na assembleri a teraz vela PHP kde nic netreba deklarovat :D
Naposledy upravil dzooky dňa Uto 19. Jan 2016 12:49:16, celkovo upravené 1

Príspevky: 33
Registrovaný: Pia 26. Jún 2015 21:17:41

Re: Prvky pola

Poslaťod barado » Str 06. Jan 2016 22:18:58


Dik za info
Vypis mi ide ale rovnakym sposobom tam priradit hodnotu to mi uz nejde.
Kód: Vybrať všetko
check_numbers[i] = "0123456789";

Tu vypise [codeerror: invalid array assignment
check_numbers[1] = "0123456789";
^
exit status 1
invalid array assignment[/code]

Dajaku knizocku o Ccku mam, no pamatam ze na vyske to bolo daco pre mna nezrozumitelne
Zacinal som na assembleri a teraz vela PHP kde nic netreba deklarovat :D


No a to je presne o tom, čo stále píše budvar10. @budvar10 Neboj mi to raz pochopíme.
Nemôžeš priradiť takýmto jednoduchým spôsobom string do stringu. Na to je funkcia strcpy
http://www.tutorialspoint.com/c_standard_library/c_function_strcpy.htm

Takže to musíš urobiť týmto spôsobom.

Kód: Vybrať všetko
strcpy(check_numbers[1], "0123456789");


A nezabudni na to, že pole 10 je vlastne check_numbers[9], lebo sa zacina od 0 nuly
Takže deklaruješ:
check_numbers[10][11]
no voláš ich cez
check_numbers[0][0]
check_numbers[0][1]
check_numbers[0][2]
.
.
check_numbers[0][10]
.
.
check_numbers[9][10]

Obrázok užívateľa
Príspevky: 133
Registrovaný: Štv 06. Nov 2014 12:06:09

Re: Prvky pola

Poslaťod budvar10 » Štv 07. Jan 2016 9:33:12

barado píše:
Kód: Vybrať všetko
printf("Hello!");

Tak printf je pane špecialita. Určite sa nedá použiť len tak jednoducho. Treba si uvedomiť ako to funguje na OS. Printf posiela formatovaný výstup na stdout - štandardný výstup, ale Arduino žiaden nemá vytvorený.
Určite sa to nedá takto lcd.printf. Arduino špecialist zatracujú túto skvelú funkciu (na arduino.cc), ale ja som opačného názoru. Je to skvelá funkcia pre výstup na terminál na LCD sa to až tak veľmi nehodí.
Tu som niečo vysekol z jedného môjho programu:

Kód: Vybrať všetko
// --------------------------------------------------------------------------------------
//
//                                     *** USART ***

/* USART stdio implementation */
#if !defined(__AVR__)
   #define  fdev_setup_stream(stream, put, get, rwflag)
#endif

#define SERIAL_SPEED 9600         // baud rate 300, 1200, 2400, 4800, 9600, 14400,
                           // 19200, 28800, 38400, 57600, 115200 or also partial

static  FILE usartout;            // FILE structure to reference custom USART I/O
static  inline int usart_putchar(char c, FILE *stream) { Serial.write(c); return(0); }
                           // output function (this works because Serial.write,
                           // although of type virtual, already exists

// --------------------------------------------------------------------------------------

void setup()
{
/* USART start */
   serial_speed = EEPROM.read_dword(EEA_SERIAL_SPEED);

   if((int32_t) serial_speed <= 0)   serial_speed = SERIAL_SPEED;
                                 // test for 0xFFFFFFFF and zero
   Serial.begin(serial_speed);            // Serial.begin(SERIAL_SPEED);

/* USART file descriptor setup */
   fdev_setup_stream(&usartout,         // stream - I/O device
                  usart_putchar,      // function to write one char to device
                  NULL,            // function to read one char from device
                 _FDEV_SETUP_WRITE);   // flag (READ; WRITE; RW == READ | WRITE)

/* set the USART as the standard output device STDOUT */
   #if defined(__AVR__)
      stdout = &usartout;
   #endif
}


printf potom bude fungovať na sériovú linku. Ak by si chcel aj LCD, musíš si vytvoriť preň stream. Veľa ľudí riši formátovanie tak, že použijú sprintf pre zápis do buffra a potom už idú cez .print(), ale tam potom naviac
kód a čas spracovania tzv. overhead.
Naposledy upravil budvar10 dňa Štv 07. Jan 2016 9:48:28, celkovo upravené 1

Obrázok užívateľa
Príspevky: 133
Registrovaný: Štv 06. Nov 2014 12:06:09

Re: Prvky pola

Poslaťod budvar10 » Štv 07. Jan 2016 9:44:37

@dzooky
Barado teraz zabodoval, treba na to strcpy. Áno je to únavné, používať na všetko nejakú funkciu, ale tu je presne to, že tie dáta majú byť v EEPROM aby sa dali meniť za behu programu a aby si to pamätal po vypnutí alebo resete. Tak šup, daj to do EEPROM.
A ešte pozor, všetky zadefinované konštanty sú uložené vo flash a pri štarte sa nakopírujú do RAM a tam zostanú počas celého behu programu. Ide hlavne o stringy, pretože ti ľahko zaplnia celú pamäť. Preto sa používa PROGMEM, PSTR, alebo F makrá, aby sa načítali len, keď to treba a mohli sa potom vymazať z RAM. Ale teraz je to na mňa veľa na vysvetľovanie.
No predsa ešte, už keď som to začal. Páni pozrite si strcpy_P napríklad.

Príspevky: 33
Registrovaný: Pia 26. Jún 2015 21:17:41

Re: Prvky pola

Poslaťod barado » Štv 07. Jan 2016 22:00:12

budvar10 píše:@dzooky
Barado teraz zabodoval, treba na to strcpy. Áno je to únavné, používať na všetko nejakú funkciu, ale tu je presne to, že tie dáta majú byť v EEPROM aby sa dali meniť za behu programu a aby si to pamätal po vypnutí alebo resete. Tak šup, daj to do EEPROM.
A ešte pozor, všetky zadefinované konštanty sú uložené vo flash a pri štarte sa nakopírujú do RAM a tam zostanú počas celého behu programu. Ide hlavne o stringy, pretože ti ľahko zaplnia celú pamäť. Preto sa používa PROGMEM, PSTR, alebo F makrá, aby sa načítali len, keď to treba a mohli sa potom vymazať z RAM. Ale teraz je to na mňa veľa na vysvetľovanie.
No predsa ešte, už keď som to začal. Páni pozrite si strcpy_P napríklad.


HA, že zabodoval... Veď si sa aj dosť natrápil.
Pozrel som ... a ešte to bude dosť dlhá cesta poznávania.
Takže progmem, by mi mohol napríklad pomôcť uložiť do FLASH(ktorú nemôžem prepisovať) rôzne chybové hlásenia(ktoré nepotrebujem prepisovať) a potom cez strcpy_P by som ich mohol z tej FLASH dostať do buffera, ktorý potom pošlem na HMI :) . A toto všetko mi ušetrí SRAM(pamäť, ktorú môžem prepisovať).

Obrázok užívateľa
Príspevky: 133
Registrovaný: Štv 06. Nov 2014 12:06:09

Re: Prvky pola

Poslaťod budvar10 » Pia 08. Jan 2016 8:06:39

Áno.

Predchádzajúci

Späť na Software