Vypocet podielu s PICkom

Zdravim Vas, mam jeden problem s vypoctom percentualneho podielu pomocou jedneho PICka. Uvediem priklad:

unsigned int A = 10000;
unsigned int B = 10000 * 0.5;

V tomto pripade bude mat premenna B hodnotu 5000. Samozrejme keby som pouzil ako nasobiacu konstantu cislo s vacsim poctom desatinnych miest tak sa vysledok zaokruhli co mi vobec nevadi. Problem je v tom ze pouzivam float premennu a stava sa mi ze mi raz za cas pride chybny vysledok. Ked natvrdo napisem ze B = 5000, alebo B = A - 5000 tak vsetko slape ako ma, problem je ak pouzijem konstantu float, comu by som tiez chapal nakolko MCU ma omnoho viac prace s vypoctom a nemusi to stihnut. Potreboval by som nejako nakopnut s tym, ze ako dokazem vypocitat percentualny podiel z premennej bez toho, aby som pouzil float hodnotu. Uz nad tym sedim moc dlho tak mi nenadavajte ak je to moc jednoduche :slight_smile:
Dakujem vam

Takhle Ti asi moc neporadím - ukaž ten kód.
No a bez float to jde. Záleží samozřejmě na absolutním rozsahu operandů, ale většinou se vejdeš buď do stejného typu nebo o jeden typ výše. Vynásob číslo ze kterého chceš spočítat procenta třeba 1000 a proveď výpočet. Výsledek “procent” tak získáš na 3 des. místa.

Mam jeden napad, dakujem za nakopnutie a uz asi viem ako to spravim aj bez float-u. Zajtra napisem ako som dopadol, ale myslim ze to pojde. Dakujem

Vacsinou je pouzitie float uplne zbytocne. Jednosucho staci cisla pouzivat vynasobene na pozadovanu presnost. Napriklad prud z cidiel psracovavam v uA a nie v mA na tri desatinne cisla vo forme float.

Ako presne to myslite? Uvedte nejaky priklad.
Ja som to robil nasledovne:

int A = 10000; //Namerana hodnota
int B = 80; //Pozadovane percenta
int C = (A * B) / 100; Vysledok v percentach

Problem je v tom ze stale to nechodi dobre. Neviem presne co sa deje ale pripada mi to akoby MCU nepocital spravne. Vysledok je uplna blbost, ak ale zapisem (A * B) / 100UL tak vysledok je spravny ale zasa mam problem s tym ze sem tam hodi zly vysledok. Skuste popisat ako to myslite vy. Dakujem Vam

chodi to zle lebo

80 * 1000 je 80000 a to je predsa viac ako 32767. MCU vysledok jednoducho zarovna na dany typ a je to. Musite si konrolovat velkost cisel.

da sa to spravit nasledovne bez float


#define DELACA_KONSTATNA 100 // 100L moze byt pozadovane, aby prekladac vedel, ze konstatna bude pouzita pre vacsie cislo ako je bajtovy rozsah konstatny

int16_t  a, b, v; 
// medzivysledok sa spracovava v 32b integeri, co je vypoctovo daleko menej narocne ako vo floate.
int32_t c; 

a = 1000;
b = 80;

// premenne treba dosledne pretypovavat
c = (int32_t) a * (int32_t) b / 100;

// kontrola, ci vysledok nahodou nie je vacsi ako 16bit integer
if (c > INT16_MAX) c = INT16_MAX;

// premenne treba dosledne pretypovavat
v = (uint16_t) c;

pouzitie desatin v ramci integeru sa robi sposobom pevnej desatinnej ciarky a nie pohyblivej ako je to vo float. Jednoducho sa dohodnem, ze cislo 16234 znamena 162.34 a cislo 7589 znamena 75.89.

Zdravim Vas, ano viem ze s tym int-om som napisal blbost, pisal som to ako priklad a neuvedomil som si to tak sa ospravedlnujem. No ale aj napriek tomu to nechodilo dostatocne rychlo ale problem som uz vyriesil inak a slape to, samozrejme ale dakujem za pomoc. Mal by som ale este jednu otazku:
Potrebujem pripojit na port paralelny d/a prevodnik a teda potrebujem 8 pinov, len ide o to ze piny ktore mozem pouzit su rozne. Potreboval by som vytvorit nieco ako pole kde kazdy prvok bude nazov portu v mnou zadanom poradi a tento prvok bude predstavovat 8bit premennu. Uvediem priklad:

unsigned int pole[3] = {LATAbits.LATA0, LATAbits.LATA1, LATAbits.LATA3}; pole = 0b1111; //vsetky vystupy budu v log.1 pole = 0b010; //PA1 bude v log.1 a ostatne v log 0 ...atd

Neberte to ako spravne zadanie, je to len priklad no neviem akoby som to mohol takto rozdelit aby som s tym mohol pracovat ako s jednou premennou. Dakujem Vam za pomoc

Musíš položit otázku tak aby se dala zvednout…

Ospravedlnujem sa, skusim to inak. Mam A/D prevodnik ktory mam pripojeny k MCU nasledovne:
D0 -> PORTA.0
D1 -> PORTA.1
D2 -> PORTA.2
D3 -> PORTB.2
D4 -> PORTB.3
D5 -> PORTB.4
D6 -> PORTB.5
D7 -> PORTB.7

Chcel by som vediet ako ‘‘zlucim’’ tieto vystupne porty do jednej, povedzme premennej, aby som mohol zapisovat na tieto porty cez tu danu premennu. Napriklad zapisem do premennej hodnotu 255 a cez nu sa nastavia vsetky porty do log.1 a pod. Pripadne ako by ste Vy riesili zapis hodnoty na tento prevodnik. Keby som mal AVRko tak by som si cely prevodnik hodil na jedne port a ked zapisem na tento port hodnotu tak ono si to automaticky porozdeluje lebo pracujem s celym portom naraz lenze teraz mam niektore vystupy na jednom a dalsie na inom porte. Snad som sa uz vyjadril spravne, ale samozrejme chapem ze cez net sa tazko nieco vysvetluje a este tazsie potom chape. Dakujem Vam

do promeny asi tezko …, a jinak nez to nastavovat postupne to asi nedas
slo by to treba takle

[code]#define D0 PORTA.0
.
.
#define D7 PORTB.7
#define ad_data_ready port…

void ad_out(unsigned int8 ad_val)
{
if (ad_val&128)output_high(D7); else output_low(D7);
if (ad_val&64) output_high(D6); else output_low(D6);
if (ad_val&32) output_high(D5); else output_low(D5);
if (ad_val&16) output_high(D4); else output_low(D4);
if (ad_val&8) output_high(D3); else output_low(D3);
if (ad_val&4) output_high(D2); else output_low(D2);
if (ad_val&2) output_high(D1); else output_low(D1);
if (ad_val&1) output_high(D0); else output_low(D0);

// set ad_data_ready

}

ad_out(0xaa);
[/code]

nebo si tam dej nakej “serial in / paraler out”
nebo to proste dej na jeden port (B ?)
nebo pouzi PICko s vice portama…

Buď jak píše Milo a nebo dvě konverzní tabulky pro rychlý přístup a pak 2x read-modify-write operace. Všechno záleží na tom jak rychle potřebuješ hrnout data ven a taky nezapomeň, že pokud nemá ten převodník triger, tak obě výše popsané metody vyprodukují na výstupu D/A glitche.

Zeptám se blbě, ale taky se C teprv učím, tak mi to kdyžtak snad odpustíte… a nešlo by vytvořit něco jako bitová struktura (resp. ona by vytvořit asi šla, ale - fungovalo by to)?

ono neco takovyho existuje ? to jako ze si porovnava data a pri zmene je hned pouziva ?

mozna by to fungovalo ale nevim jak se zapisuje do struktury (teda jestly to lze zapsat do vsech nejak najednou)

a vzhledem k tomu ze lze bud zapsat do 1 registru nebo zmenit jeden bit , tak pozadovany data budou na vystupu az na podruhy…

Možná jsem to blbě pojmenoval - myslím tím takový ten vstup STR (jako strobe). Obvod převezmě data na hranu/nebo úroveň a v ten moment provede konverzi. Píšu to proto, že nevím co tam bude mít za D/A. Třeba taková R2R je úplně bez inteligence :slight_smile:)

A ano, existuje> farnell.com/datasheets/78041.pdf
Takže když mu budeš “chrastit” datama vstupu, bude “chrastit” i analogový výstup.