www.elektronik.si
Optimiziranje arduino code
Pojdi na stran 1, 2  Naslednja  :||:
www.elektronik.si -> Arduino sekcija

Avtor: malciKraj: Polhov Gradec PrispevekObjavljeno: Sre Nov 28, 2018 10:24 pm    Naslov sporočila:  Optimiziranje arduino code
----------------------------------------------------------------------------
Pozdravljeni!

Do sedaj sem za branje vrednosti iz serijske komunikacije ( za nastavitve..) uporabljal način, kot je v spodnji kodi. A pri zadnjem programu se je pa teh else if stavkov nabralo že več kot 20, pa še nekaj jih moram dodati. Kako bi se dalo ta void optimizirati, oz, kako narediti vsaj bolj preglednega?

lp
Uroš
Koda:
if (Serial.available()>0) {   
              delay(50);
              uart1();
          }


void uart1() {
  String sprejem=Serial.readString();
  Serial.print("Sprejel sem: ");
  Serial.println(sprejem);


  if (sprejem.indexOf("imax")>-1){                                                           // če vsebuje niz imax
          sprejem=sprejem.substring(sprejem.indexOf("imax")+4,sprejem.indexOf("imax")+7);     // izloči imax
          Imax=sprejem.toInt();                                                             //preostanek spremeni v int 
              Serial.println (" Imax: " + String(Imax));                                    // izpiši novo vrednost
     }else if (sprejem.indexOf("umax")>-1){  // če vsebuje niz Umax
          sprejem=sprejem.substring(sprejem.indexOf("umax")+4,sprejem.indexOf("umax")+8);
          Umax=sprejem.toInt();
              Serial.println (" Umax: " + String(Umax));
     }else if (sprejem.indexOf("utot")>-1){  // če vsebuje niz Utot
          sprejem=sprejem.substring(sprejem.indexOf("utot")+4,sprejem.indexOf("utot")+8);
          Utot=sprejem.toInt();
              Serial.println (" Utot: " + String(Utot));
     }else if (sprejem.indexOf("ufull")>-1){  // če vsebuje niz Ufull
          sprejem=sprejem.substring(sprejem.indexOf("ufull")+5,sprejem.indexOf("ufull")+9);
          Ufull=sprejem.toInt();
              Serial.println (" Ufull: " + String(Ufull));
     }else if (sprejem.indexOf("itot1")>-1){  // če vsebuje niz Itot1
          sprejem=sprejem.substring(sprejem.indexOf("itot1")+5,sprejem.indexOf("itot1")+8);
          Itot1=sprejem.toInt();
              Serial.println (" Itot1: " + String(Itot1));
     }else if (sprejem.indexOf("itot2")>-1){  // če vsebuje niz Itot2
          sprejem=sprejem.substring(sprejem.indexOf("itot2")+5,sprejem.indexOf("itot2")+8);
          Itot2=sprejem.toInt();
              Serial.println (" Itot2: " + String(Itot2));
     }else if (sprejem.indexOf("itot0")>-1){  // če vsebuje niz Itot0
          sprejem=sprejem.substring(sprejem.indexOf("itot")+4,sprejem.indexOf("itot")+8);
          Itot=sprejem.toInt();
             Serial.println (" Itot: " + String(Itot));
     }else if (sprejem.indexOf("izpis1")>-1){                                             // če vsebuje niz izpis1
          izpis1=!izpis1;                                                                 // izpis1 je lahko true/false
             Serial.println (" izpis1=" + String(mer));         
     }else if (sprejem.indexOf("izpis2")>-1){  // če vsebuje niz izpis2
          izpis2=!izpis2;
              Serial.println (" izpis2=" + String(mer));         
     }else if (sprejem.indexOf("mer")>-1){  // če vsebuje niz mer
          mer=!mer;
          Serial.println (" meritve=" + String(mer));         
     }else if (sprejem.indexOf("act")>-1){  // če vsebuje niz act
          active=!active;
          Serial.println (" active: " + String(active));         
     }else if (sprejem.indexOf("x")>-1){  // če vsebuje niz x   (x13250  > nastavi napetost na DAC1 ..)
          sprejem=sprejem.substring(sprejem.indexOf("x")+1,sprejem.indexOf("x")+6);
          Vout1=sprejem.toInt();
          Serial.print (" Vout1: " + String(Vout1));
     }else if (sprejem.indexOf("y")>-1){  // če vsebuje niz y  (y13250  > nastavi napetost na DAC2 ..)
          sprejem=sprejem.substring(sprejem.indexOf("y")+1,sprejem.indexOf("y")+6);
          Vout2=sprejem.toInt();
          Serial.print (" Vout2: " + String(Vout2));
     }else if (sprejem.indexOf("cal")>-1){                      // če vsebuje niz cal  (kalibracija)
          Itotref=adc1; Itot1ref=adc2; Itot2ref=adc3;
          Serial.println("kalibracija.......");
     }else if (sprejem.indexOf("izp")>-1){  // če vsebuje niz izp
        izp1();         
     }else if (sprejem.indexOf("t1")>-1){  // če vsebuje niz t1
          sprejem=sprejem.substring(sprejem.indexOf("t1")+2,sprejem.indexOf("t1")+5);
          T1=sprejem.toInt();
          Serial.println (" T1: " + String(T1));
     }else if (sprejem.indexOf("t2")>-1){  // če vsebuje niz t2
          sprejem=sprejem.substring(sprejem.indexOf("t2")+2,sprejem.indexOf("t2")+5);
          T2=sprejem.toInt();
          Serial.println (" T2: " + String(T2));
     }else if (sprejem.indexOf("captrim")>-1){  // če vsebuje niz captrim
          sprejem=sprejem.substring(sprejem.indexOf("captrim")+7,sprejem.indexOf("captrim")+10);
          CapTrim=sprejem.toInt();
          Serial.println (" CapTrim: " + String(CapTrim));
     }else if (sprejem.indexOf("cap")>-1){  // če vsebuje niz cap
          sprejem=sprejem.substring(sprejem.indexOf("cap")+3,sprejem.indexOf("cap")+7);
          Capacity=sprejem.toInt();
          Serial.println (" Capacity: " + String(Capacity));
     }else if (sprejem.indexOf("eeprom")>-1){  // če vsebuje niz eeprom
        eeprom();         
     }
           
  }

Avtor: Jaka57Kraj: Grosuplje PrispevekObjavljeno: Sre Nov 28, 2018 11:43 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Če bi bili tvoji stringi enake dolžine, bi lahko uporabil switch...case:

Koda:
switch sprejem.substring(1, n) {

case string1:
   //kar nekaj
   break;
case string2:
   //kar nekaj
   break;
.
.
.
default:
   //kar nekaj
   break;
}


Za meritev pošiljaš "mer" (trije karakterji) toda za izpis pošiljaš komplet vse karakterje. Lahko bi prav tako pošiljal samo tri, recimo "iz1" oz "iz2".....
V končni fazi, bi lahko pošiljal samo dva, na začetku programa pa imaš definirane stringe, kaj je kaj, npr. captrim="ct", izpis1="i1" itd.

Seveda pa to ne gre če pošiljaš kombinacije stringov.

Avtor: igo PrispevekObjavljeno: Čet Nov 29, 2018 12:35 am    Naslov sporočila:  
----------------------------------------------------------------------------
Jaka57 je napisal/a:
Če bi bili tvoji stringi enake dolžine, bi lahko uporabil switch...case:

V bistvu sploh ni potreben string, ampak zadostuje navaden char (8 bitov = 1 byte). Paket je potem sestavljen v obliki [Velicina][...Vrednost...], kjer je Velicina vedno 8-bitni char, Vrednost pa ima lahko povsem različne oblike zapisa.
Sprejemna in oddajna enota morata poznati pomen Velicine in obliko Vrednosti (itak to ti določiš), ostalo je trivialno. Ni nujno, da so vse case številke zasedene, ampak jih lepo pregledno izbereš po lastnostih.

Koda:
switch sprejem.substring(1, n) {

case 11: // 1 byte
   //kar nekaj
   break;
case 12:
   //kar nekaj
   break;
.
.
.
case 21: // 2 byta unsigned int
...
case 22:
...
case 31: // 2 byta signed int
...
case 32:
...
case 41: // 4 byti unsigned long
...
case 42:
...
case 81: // 4 byti signed long
...
case 91: // float
...
case 101: // ukaz1, naj nekaj naredi
...
case 111: // ukaz, naj pošlje nazaj obdelano Veličino 11
...
default:
   //kar nekaj
   break;
}

Avtor: đzuroKraj: Ljubljana PrispevekObjavljeno: Ned Dec 02, 2018 3:48 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Vrednost spremenljivke naj bo istega tipa in pa enake dolzine

Avtor: Jaka57Kraj: Grosuplje PrispevekObjavljeno: Ned Dec 02, 2018 6:15 pm    Naslov sporočila:  
----------------------------------------------------------------------------
đzuro je napisal/a:
Vrednost spremenljivke naj bo istega tipa in pa enake dolzine

Naprimer?

Avtor: igo PrispevekObjavljeno: Ned Dec 02, 2018 11:42 pm    Naslov sporočila:  
----------------------------------------------------------------------------
To sploh ni nujno. Prvi byte (Velicina) je vse, kar je za switch pomembno, znotraj posameznega case primera pa se lahko potem prebere podatek dolg med 0 in n byti. 0 zato, ker je lahko Velicina že veljaven ukaz sprejemni enoti, ostalo pa po potrebi glede na število bytov, ki jih zasede spremenljivka, ki jo posamezen case napolni.

Je pa dobro, da se pred izhodom iz switch vedno izprazne sprejemni buffer, da ne bi po nesreči kaj notri ostalo, kar bi se ob naslednjem vstopu v switch obnašalo kot Velicina ali podatek, skupaj s še kakšnimi medtem prejetimi byti.

Avtor: malciKraj: Polhov Gradec PrispevekObjavljeno: Pon Dec 03, 2018 11:13 am    Naslov sporočila:  
----------------------------------------------------------------------------
Pozdravljeni!

Sem včeraj malo nadaljeval...
V Switch-case je lahko Int ali Char. To je dejansko 255 možnosti z 1 Bytom - to je vredu.
Samo z logičnostjo je pa nekoliko težje (oz ne znam smiselno uporabiti #define).
Če sedaj pošljem "Imax200" s tem mislim da je dovoljen maximalni tok 200A.
Če pa pošljem npr. "A200" je pa isto, samo da moram imeti dodatno tabelo na papirju, kjer imam legendo ( da A pomeni Imax)
Bom tako naredil, da privarčujem nekaj spomina in pridobim na preglednosti.
Zaenkrat hvala vsem.

lp
Uroš

Koda:


void uart1() {

  String sprejem=Serial.readString();
  char spr=sprejem.charAt(0);
         
     }


switch (spr) {

case 98: //"a"
   Serial.println("A B C test");
   break;
case 97: //"b"
   Serial.println("TEST XYZ");
   break;
 
 
 
default:
   //kar nekaj
   break;
}




  if (sprejem.indexOf("imax")>-1){  // če vsebuje niz imax
          sprejem=sprejem.substring(sprejem.indexOf("imax")+4,sprejem.indexOf("imax")+7);
          Imax=sprejem.toInt();

Avtor: Jaka57Kraj: Grosuplje PrispevekObjavljeno: Tor Dec 04, 2018 10:15 pm    Naslov sporočila:  
----------------------------------------------------------------------------
malci, saj ne rabiš uporabljat #define.
Ko sem napisal, da definiraš na začetku spremenljivke, sem mislil, da prirediš imenom veličin vrednost, npr:
char Imax='A';
char Izpis1="B";

in na oddajni strani enako, potem lahko še vedno vse delaš z Imax, Izpis1,itd. in ne rabiš vsakič gledat na papir.

in tako naprej in preko serijskega porta potem letijo 'A'<vrednost>, 'B'<vrednost>, itd.
in switch...case lahko potem izgleda takole:

Koda:
switch sprejem.substring(1, n) {

case Imax:
   //kar nekaj
   break;
case Izpis1:
   //kar nekaj
   break;
.
.
.
case Umax:
   //kar nekaj
   break;
...

default:
   //kar nekaj
   break;
}

Toda, če ta ista imena veličin uporabljaš naprej v programu, boš moral definirati druga imena veličin, npr :
char Maximalni_tok='A';
char Prvi_izpis='B';
char Drugi_izpis='H';
itd.
in to samo zato, da je del programa switch...case preglednejši, vse ostalo, kar si sedaj napisal v programu pa lahko ostane enako,
saj bi pri uporabi 'A', 'B',....., dejansko moral gledati na papir.

S tem, da gre char spremenljivka od -128 do 127 (signed), byte pa od 0 do 255 (unsigned).

Avtor: malciKraj: Polhov Gradec PrispevekObjavljeno: Sob Dec 08, 2018 10:18 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Citiram:
Če pa pošljem npr. "A200" je pa isto, samo da moram imeti dodatno tabelo na papirju, kjer imam legendo ( da A pomeni Imax)

To sem mislil v času testiranja, ko običajno delam še s terminalom.

Sem sedaj preuredil kodo na način kot je videti spodaj, in sem zadovoljen. Privarčeval 11% prostora ( iz 64 na 53%) pa tudi bolj pregledno je.

Hvala za za pomoč

lp

Koda:
 do{
 int len=sprejem.length();  if (len<3) break;
 byte ind=sprejem.indexOf(';',0);
 String str1= sprejem.substring(0, ind);
         sprejem=sprejem.substring(ind+1,len);  // sprejem se zmanjša za niz do prvega podpičja
         spr=str1.charAt(0);  // iz str1 pridobi prvi znak
         str1=str1.substring(1,str1.length()); // str1 je preostanek ( običajno vrednost)

switch (spr) {

case 97: //a
     Imax=str1.toInt(); Serial.println (" Imax: " + String(Imax));
     break;
case 98: //b
     Umax=str1.toInt(); Serial.println (" Umax: " + String(Umax));
     break;
case 99: //c
     Utot=str1.toInt(); Serial.println (" Utot: " + String(Utot));
     break;
case 100: //d
     Ufull=str1.toInt(); Serial.println (" Ufull: " + String(Ufull));
     break;
case 101: //e
     Itot1=str1.toInt(); Serial.println (" Itot1: " + String(Itot1));
     break;
case 102: //f
     Itot2=str1.toInt(); Serial.println (" Itot2: " + String(Itot2));
     break;
case 103: //g
     Itot=str1.toInt(); Serial.println (" Itot: " + String(Itot));
     break;
case 104: //h  //izpis 1
     izp1();
     break;
case 105: //i  //izpis 2
     izp2();
     break;
case 106: //j
     mer=!mer; Serial.println("Meritve" + String(mer));
     break; 
case 107: //k
....
....
....

Avtor: igo PrispevekObjavljeno: Ned Dec 09, 2018 1:11 am    Naslov sporočila:  
----------------------------------------------------------------------------
Ali imaš znotraj loop(){...} zanke samo do{....} zanko ali do{....}while(...) zanko?

Če de najprej do{... , se bo tisto znotraj {...} najprej izvršilo, nato pa preverilo, ali se sme ponoviti.
Dostikrat je varneje najprej preveriti, ali se sme nekaj izvršiti:

setup()
{
...
nacin=1;
}

loop()
{
Zanka:
while(nacin==1){....}
while(nacin==2){....}
...
goto Zanka; // najhitrejši in najučinkovitejši način za kroženje zanke
}


Če pa je znotraj loop() samo do{...} zanka, jo vrzi ven, saj je loop() že sama po sebi zanka. S tistim goto Zanka pravtako prihraniš nekaj malega virov in časa.

Avtor: malciKraj: Polhov Gradec PrispevekObjavljeno: Ned Dec 09, 2018 10:33 am    Naslov sporočila:  
----------------------------------------------------------------------------
ne, imam tudi while.


Se da še kak byte privarčevati. Sicer nisem v krizi s prostorom, a vseeno,


Koda:


void loop(){
          if (Serial.available()>0) {    // če je na voljo niz, potem pojdi na void uart1
              delay(50);
              uart1();
          }
.
.
.
}


void uart1() {
  char spr;
  String sprejem=Serial.readString();     // sprejem ima poljubno dolžino oblike  a250;b6900,c145.....
  Serial.print("Sprejel sem: ");
  Serial.println(sprejem);
     
///// parsing /////

 
    int ii=0;                      // to bi se verjetno dalo tudi izpustiti???
  do{
     int len=sprejem.length();  if (len<3) break; //Serial.println("dolzina=" + String(len));
     byte ind=sprejem.indexOf(';',0);
     String str1= sprejem.substring(0, ind);
             sprejem=sprejem.substring(ind+1,len);  // sprejem se zmanjša za niz do prvega podpičja
             spr=str1.charAt(0);  // iz str1 pridobi prvi znak
             str1=str1.substring(1,str1.length()); // str1 je preostanek ( običajno vrednost)
   
    switch (spr) {
   
    case 97: //a
         Imax=str1.toInt(); Serial.println (" Imax: " + String(Imax));
         break;
    case 98: //b
         Umax=str1.toInt(); Serial.println (" Umax: " + String(Umax));
         break;
    case 99: //c
         Utot=str1.toInt(); Serial.println (" Utot: " + String(Utot));
         break;
    case 100: //d
         Ufull=str1.toInt(); Serial.println (" Ufull: " + String(Ufull));
         break;
    case 101: //e
      ...
...
...
    case 41: //A   
         T2ref2=str1.toInt(); Serial.println ("T2ref2: " + String(T2ref2));
         break;                                                                         
    default:
       //kar nekaj
       break;
    }     
   
  } while (ii=1);   // II nima nikoli vrednost 1 - vedno se zaključi v z break
}

Avtor: vpeterKraj: Maribor okolica PrispevekObjavljeno: Ned Dec 09, 2018 11:18 am    Naslov sporočila:  
----------------------------------------------------------------------------
Namesto
Koda:
case 97: // a

lahko tudi napišeš
Koda:
case 'a': // Imax

Je pa zgoraj Jaka57 napisal kako se znebiti črk, da je program preglednejši.

Posodobljeno:
Koda:
const char   Imax = 'a';
const char Izpis1 = 'b';

    case Imax:
         break;


Nazadnje urejal/a vpeter Ned Dec 09, 2018 2:26 pm; skupaj popravljeno 2 krat

Avtor: tilz0RKraj: Črnomelj PrispevekObjavljeno: Ned Dec 09, 2018 12:47 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Super predlogi, vendar predlagam, da se prepričate kaj predlagate. Spremenljivka ne more biti del case stavka v C++, ker ni konstantna vrednost. Razen, če bo const ali constexpr.

Avtor: Jaka57Kraj: Grosuplje PrispevekObjavljeno: Ned Dec 09, 2018 8:21 pm    Naslov sporočila:  
----------------------------------------------------------------------------
tilz0R je napisal/a:
Super predlogi, vendar predlagam, da se prepričate kaj predlagate. Spremenljivka ne more biti del case stavka v C++, ker ni konstantna vrednost. Razen, če bo const ali constexpr.

Drži!

Avtor: tilz0RKraj: Črnomelj PrispevekObjavljeno: Ned Dec 09, 2018 8:25 pm    Naslov sporočila:  
----------------------------------------------------------------------------
Vrži tvojo idejo v prevajalnik.

Stran 1 od 2

Powered by phpBB © 2001,2002 phpBB Group