<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    Jsem zvyklý spíš používat float a teprve když není místo, se floatu
    zbavit za cenu zesložitění programu. Třeba na ATtiny416 je float
    skoro nereálnej, na ATmega32, nebo AVR64DD32 s ním není problém. Ono
    to hodně naběhne prvním použitím, ale pak už moc nepřibývá. A
    přehlednost výpočtů se dramaticky zlepší.<br>
    <br>
    A ano, při zobrazování či odesílání postupně dělím deseti, to snad
    ani jinak nejde:-)<br>
    Tzn. z mist se udělá násobitel, např. ze 2 je 100, tím se floatový
    vstup vynásobí a předhodí se funkci cislo(long). Ale důležitý je, že
    se to stane až v uartSend.<br>
    <br>
    Pro mě je důležité, že mezi změřením a odesláním jsou floatové
    výpočty. Když se vejdou, zmizí veškeré starosti s přetýkáním, co
    nastávají při celočíselných výpočtech a snaze o zachování přesnosti.<br>
    takže pak máme třeba:<br>
    <br>
    #define AD_samples (1024.0)<br>
    #define AD_uInDiv   (1 + 110.0/10.0)<br>
    #define AD_uOutDiv (1 + 110.0/22.0)<br>
    #define AD_ref           (4.096)<br>
    ...<br>
    <br>
    kde ve funkci cekej je:<br>
    <br>
    if (adSync==1) {<br>
        adSync=0;<br>
        adUin = (adData[AD_first] - offset) * násobitel<br>
        ...<br>
    přičemž offset a násobitel jsou z těch definů, nebo z EEPROM float
    eCalConst..., kde je výchozí hodnota z těch definů.<br>
    A zajímavější je, když je výstup třeba teplota z termistoru s
    charakteristikou B3950, nebo konduktometr, kde je ale z EMC a
    dalších důvodů na vstupu ještě sériovej a paralaelní R.<br>
    <br>
    Tabulky mívám na grafickém displeji, na to je pak tab(x), která
    posune příští psaní na požadovanou pozici, font je třeba i
    proporcionální. Nebo jsem měl pole dispTabs, kde byly začátky na
    který skočí \t. A to se dá zrovna celkem dobře použít i na sériáku,
    dělá to pak až putchar2, když mu přijde \t a on ví kolik bylo od
    posledního \n.<br>
    Ale vizuální tabulky na sériáku moc nemívám, většinou max. takový
    napůl, kde se jen normálně použije \t. Až když to začne vadit,
    přidám uartTabs[].<br>
    <br>
    PH<br>
    <br>
    <div class="moz-cite-prefix">Dne 20.04.2024 v 14:01 Martin Záruba
      napsal(a):<br>
    </div>
    <blockquote type="cite"
      cite="mid:07035d67-bd13-4ca5-8b45-c6fcaf944dee@volny.cz">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <p><font face="Arial">Nojo, jenže pak s tím neuděláte tabulku. Je
          potřeba, aby například pokud je hodnota 3753, napsalo to
          |3753mV| ale pokud je 53, napsalo to |  53mV| a ne |53mV|.
          Tedy aby celý řetězec (včetně toho mV) byl stále (například) 6
          znaků.<br>
        </font></p>
      <p><font face="Arial">Zkusil jste, kolik to zabere paměti? Podle
          toho, co píšete to dělá převod na float. To ale na osmibitu je
          hrůza. Já si hraju jen s "grafikou". Číslo stále dělím deseti,
          to je i na osmibitu snadné. A vypisuji zbytek po dělení. No a
          někam vrazím jakoukoli "výplň", třeba tu tečku. Pak to vypadá
          jako desetinné číslo, které ale je v celočíselném formátu
          uloženo třeba 10x 100x nebo jak se chce větší, což je myslím
          ten nejefektivnější způsob, jak na malinkém procesoru zobrazit
          desetinné číslo.</font></p>
      <p><font face="Arial">Zkoušel jsem také použít ultoa(). Ale je to
          větší a stejně musíte výsledek formátovat.</font></p>
      <p><font face="Arial">Napadlo mě ještě nejprve první smyčkou
          zjistit délku masky a pak nadefinovat pole buf pomocí malloc.
          A na konci ho uvolnit. Pak by většinou bylo malinké. Co si
          myslíte o tomto nápadu? <br>
        </font></p>
      <pre class="moz-signature" cols="72">Martin Záruba</pre>
      <div class="moz-cite-prefix">Dne 20.4.2024 v 12:29 Pavel Hudeček
        napsal(a):<br>
      </div>
      <blockquote type="cite"
        cite="mid:674463bf-438e-4e67-88aa-34cf0e2f0c10@seznam.cz">
        <meta http-equiv="Content-Type"
          content="text/html; charset=UTF-8">
        Ne, v mém příkladu je přeci stav uBat1=3753,
        tak uartSend("\1mV", adUbat1, 0); vypíše 3753mV<br>
        Pokud by adUbat bylo 53, vypíše 53mV<br>
        a pokud by bylo zadáno uartSend("\1mV", adUbat1, 3);<br>
        vyleze 3753,000mV<br>
        nebo třeba 3753,001, pokud float hodnota nevyšla přesně 3753,000<br>
        <br>
        Nějak tak to fungovalo, už je to dlouho.<br>
        Ale jak se tu o tom teď diskutuje a ještě jsme na kroužku došli
        k sériáku, tak si asi konečně udělám tu knihovnu, kde tohle bude
        jedno z přetížení.<br>
        <br>
        PH<br>
        <br>
        <div class="moz-cite-prefix">Dne 20.04.2024 v 11:27 Martin
          Záruba napsal(a):<br>
        </div>
        <blockquote type="cite"
          cite="mid:62da3616-1d24-431d-9cf0-0c397e03b07f@volny.cz">
          <meta http-equiv="Content-Type"
            content="text/html; charset=UTF-8">
          <p><font face="Arial">Jen dotaz: Co vypíše:</font></p>
          <p><font face="Arial">uBat1 je 53</font></p>
          <p><font face="Arial">uartSend("\1mV",adUbat1,0);<br>
            </font></p>
          <p><font face="Arial">nevypíše to</font></p>
          <p><font face="Arial">53mV      ?</font></p>
          <pre class="moz-signature" cols="72">Martin Záruba</pre>
          <div class="moz-cite-prefix">Dne 20.4.2024 v 10:36 Pavel
            Hudeček napsal(a):<br>
          </div>
          <blockquote type="cite"
            cite="mid:cafe8589-63d8-448f-9f19-eb19f16669d4@seznam.cz">
            <meta http-equiv="Content-Type"
              content="text/html; charset=UTF-8">
            Tady asi došlo k mírnému nedorozumění:<br>
            Oba umíme zobrazit jen jednu hodnotu.<br>
            Oba umíme požadovaný počet des. míst.<br>
            Oba umíme text před ním i po něm.<br>
            Já nemám formátování tisíců, ale zas můžu ve výstupním textu
            použít #.<br>
            Zas to formátování s # se asi dá ohackovat, že zobrazí třeba
            2 čísla zakódovaný do jednoho longu?<br>
            <br>
            // adUin je 12,3456  uBat1 je 3753<br>
            // UART_sendDT je ','  UART_sendPosChr je '\1'<br>
            uartSend("Uin=\1 V\n", adUin, 2);<br>
            uartSend("\1mV", adUbat1, 0);<br>
            výsledek je:<br>
            Uin=12,34 V<br>
            3753mV<br>
            <br>
            Ten uartSend byl trochu prasáckej, mist nakopíruje do
            globální uartSendMist a pak zavolá cislo((long)(v * m)), kde
            m je třeba 1000 pro mist=3. A cislo pak do požadovaného
            místa vnutí oddělovač a uartSendMist vynuluje. Tohle jsem už
            někde měl i na ty tisíce, jen se to nevypínalo samo.<br>
            <br>
            Chystám se že bych si z těhle věcí konečně udělal nějakou
            knihovnu, zatím to jen kopíruju mezi projekty a nejčastějc
            si vystačím s putchar2, text na poslání textu a cislo na
            poslání longu.<br>
            takže posledně to bylo ve stylu<br>
            text("Uin="); cislo(static_cast<long>(1000.0*adUin));
            text(" mV\r\n");<br>
            <br>
            Buffer je na zásobníku, takže sám vznikne a sám zmizí.<br>
            Ale 100 B, to je 20 % RAMky na ATtiny816, což je hodně,
            případně 1,25 % na AVR64DD32, to už by bylo v pohodě.<br>
            Mě se to obecně nelíbí, protože rád používám děje na pozadí.
            Funkce cekej(uint32_t ms) je i víc než půlka programu a
            pokud možno všechno čekání volá aspoň cekej(0). No a když se
            těch čekání sejde více takových, kde mezitím vzniknul
            buffer..<br>
            Takže mám snahu takové buffery nedělat.<br>
            Další věc je, že mám snahu minimalizovat místa, kde je
            potřeba omezovat velikost stringu. Takže mě stačí buffer na
            10B celej vstup může mít 254, výstup až 264 a ve verzi s
            txtPred + txtPo můžou klidně oba texty mít do 254.<br>
            <br>
            Ovšem to s F a PSTR je pro mě novinka, za to díky.<br>
            <br>
            Byl jsem zvyklý na codevision, tam se daly deklarovat
            proměnné do RAM, EEPROM i Flash, "text" byl ve flash a
            všechno fungovalo do velké míry samo, včetně toho, že v
            EEPROM je pointer do flash. Super věc, pokud se po kompilaci
            k binárce sprostě přikopírujou UTF8 texty ve 4 jazycích a za
            ně bitmapa fontů. Při prvním spuštění program ve flash najde
            "Tady>>>", pak dohledá začátky jazyků, hlášky v
            default jazyku a nakonec font. Pointery hodí do EEPROM a
            odteď se může na displeji 10 ms po zapnutí objevit třeba
            normální čeština.<br>
            A v případě GCC jsem si myslel, že nic už takhle elegantně
            nepůjde.<br>
            Vlastně opravdu nejde, protože si sice můžu nadeklarovat
            proměnnou v EEPROM, ale nemůžu jí přímo používat, jen přes
            funkce na čtení a zápis EEPROM, který maj navíc hrozně
            dlouhý názvy. "Super" do vzorce se 3 kalibračníma
            konstantama.<br>
            Tak aspoň snad zas můžu mít texty ve flash:-)<br>
            <br>
            PH<br>
            <br>
            <div class="moz-cite-prefix">Dne 19.04.2024 v 21:23 Martin
              Záruba napsal(a):<br>
            </div>
            <blockquote type="cite"
              cite="mid:ab12d61f-7c9b-4434-9138-43db4d9875b4@volny.cz">
              <meta http-equiv="Content-Type"
                content="text/html; charset=UTF-8">
              <p><font face="Arial">Já to tak původně dělal, jenže byl
                  to mnohem složitější a vlastně můžete takto udělat jen
                  část než narazíte na první formátovací znak. Pak už je
                  to stejně jen odeslání čísla. protože nevíte, zda
                  nebude následovat další formátovací znak po libovolné
                  počtu "výplní". Tvar text,val, míst se mi nelíbil,
                  protože s ním neuděláte třeba 10mV. Takto je text
                  kdekoli, dokonce je kdekoli i třeba \n, takže nemá
                  smysl println. A varinta txtPred, val, míst, txtPo to
                  sice umí, ale jsou 4 parametry a stejně nejde udělat
                  třeba odskočené tisíce. Taky se mi líbí, že to sežere
                  i float. Předpokládím, že buffer se vytvoří na
                  zásobníku a po opuštění funkce zmizí. Je to tak?</font></p>
              <p><font face="Arial">Ještě to chci doplnit o možnost mít
                  formátovací řetězec ve flash. Není mi ale jasné, jaký
                  je rozdíl mezi PSTR("V paměti flash") a F("V paměti
                  flash"). Asi se mi víc líbí F(" "), je to kratší zápis
                  a dovoluje přetížení funkce. Ale možná má nějakou
                  nevýhodu, na kterou jsem nepřišel.<br>
                </font></p>
              <pre class="moz-signature" cols="72">Martin Záruba</pre>
              <div class="moz-cite-prefix">Dne 19.4.2024 v 20:50 Pavel
                Hudeček napsal(a):<br>
              </div>
              <blockquote type="cite"
cite="mid:b4bb63a0-c0e8-4e00-bb0f-836ae08e652c@seznam.cz">Moc pěkný. <br>
                Já bych teda akorát nekopíroval celý text do velkého
                bufferu a místo toho text před číslem rovnou odesílal v
                prvním do/while, pak převed a odeslal číslo a nakonec
                odeslal zbytek vstupního textu. <br>
                <br>
                Už jsem taky kdysi použil variantu, kdy se zadávají
                parametry (text, val, mist) a v textu je pak znak pro
                umístění čísla a des. míst se odešle podle hodnoty mist.
                Častějc mám ale (txtPred, val, mist, txtPo). <br>
                <br>
                Odesílání mám teda téměř vždy rovnou průběžně po znacích
                a odesílací funkce čeká jen na dokončení předchozího
                znaku, takže konverze na výstupní text probíhá paralelně
                s odesíláním. <br>
                <br>
                PH <br>
                <br>
                Dne 19.04.2024 v 19:23 Martin Záruba napsal(a): <br>
                <blockquote type="cite">Už jsem se Vás dost natrápil na
                  toto téma a měl jsem pocit, že nic moc úsporného a
                  jednoduše použitelného není. Jenže jsem paličatý a
                  zkusil jsem přece něco vymyslet. Požadavek byl: <br>
                  <br>
                  Výpis na požadovaný počet míst s možností textu před i
                  za číslem. <br>
                  <br>
                  Potlačení nevýznamných nul. <br>
                  <br>
                  Co nejúspornější kód jak funkce, tak volání, vhodný
                  pro malinky procesor. <br>
                  <br>
                  Přímý tisk bez nutnosti psaní Serial.print(); <br>
                  <br>
                  Vyrobil jsem toto, posuďte a navrhněte prosím co by
                  ještě šlo líp. <br>
                  <br>
                  <br>
                  void pr(int32_t h, const char* f) { <br>
                    char buf[100]; <br>
                    uint8_t i = 0xFF; <br>
                    int32_t x = abs(h); <br>
                    do { <br>
                      i++; <br>
                      buf[i] = f[i]; <br>
                    } while (f[i] != 0); <br>
                  <br>
                    do { <br>
                      i--; <br>
                      if (buf[i] == '#') { <br>
                        if (x != 0) { <br>
                          buf[i] = x % 10 + (uint8_t)'0'; <br>
                          if (h < 0 && x < 10) { <br>
                            i--; <br>
                            buf[i] = '-'; <br>
                          } <br>
                        } else { <br>
                          buf[i] = ' '; <br>
                        } <br>
                        x /= 10; <br>
                      } <br>
                    } while (i != 0); <br>
                    Serial.print(buf); <br>
                  } <br>
                  <br>
                  <br>
                  Funkce má jediný formátovací znak # <br>
                  <br>
                  Příklady: <br>
                  <br>
                  int32_t napetimV = 5432; <br>
                  pr(napetimV, "Pokus1=###.###V\n"); <br>
                  pr(-21,      "Pokus2=### zaporne cislo\n"); <br>
                  pr(9876543,  "Pokus3=# ### ### cislo s mezerami po
                  1000\n"); <br>
                  float a = 54.3; <br>
                  pr(a*10,     "Pokus4=####.# vypis float na 1 desetinne
                  misto\n"); <br>
                  <br>
                  Výsledek vypadá takto: <br>
                  <br>
                  Pokus1=  5.432V <br>
                  Pokus2=-21 zaporne cislo <br>
                  Pokus3=9 876 543 cislo s mezerami po 1000 <br>
                  Pokus4=   54.3 vypis float na 1 desetinne misto <span
                  style="white-space: pre-wrap">
</span></blockquote>
              </blockquote>
            </blockquote>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
  </body>
</html>