ATmega, jak zaprogramować narastanie wartości sygn ału, bez użycia operacji zmiennoprzecinkowych?

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Polish to

Threaded View
Witam,

Używam mikrokontrolera ATmega128. W moim programie użytkownik ustawia  
wartość prądu (liczba całkowita od 0 do 1000) oraz czas (od 1 do 40 sekund).  
Prąd ma narosnąć od 0 do wartości ustawionej w ustawionym czasie. Funkcja  
służąca do obliczania aktualnej wartości prądu podczas jego narastania jest  
wywoływana z pewną częstotliwością (od 10 do 60Hz, zależnie od ustawienia w  
parametrach programu). Zatem narastanie prądu odbywa się w liczbie kroków  
wyrażonej wzorem: K = czas[s] * częstotliwość[Hz].
Żeby uniknąć obliczeń zmiennoprzecinkowych, zastosowałem algorytm Bresenhama  
do kreślenia odcinków. Zapowiada się, że będzie to działać bardzo szybko,  
gdy K >= wartość prądu.
Gdy K < wartość prądu, to algorytm Bresenhama normalnie kreśli odcinek w  
pętli "idąc po zmiennej Y". Tymczasem ja działam w osi odciętych, czyli X (u  
mnie jest to liczba kroków, w których prąd ma narosnąć). Bez większych  
problemów przerobiłem ten algorytm tak, aby dla K < wartość prądu, "szedł on  
po zmiennej X". Przy czym po tej przeróbce uzyskałem podpętlę (while), która  
niekiedy będzie wykonywać się wiele razy (dla pojedynczego kroku w osi X),  
co spowolni algorytm. Inną metodą, zamiast tej podpętli, byłoby zastosowanie  
dzielenia, co też nie jest rozwiązaniem, gdyż dzielenie realizowane jest  
przez kompilator także w pętli.
Poniżej przedstawiłem algorytm, który stosuję -- na razie to jest wersja  
kreśląca grafikę (tak łatwiej mi obserwować działanie tego algorytmu), a nie  
funkcja wywoływana z pewną częstotliwością i sterująca prądem.
Algorytm działa prawidłowo. Przy czym może działać niekiedy wolno (pętla  
while może wykonywać się wiele razy) dla K < wartość prądu -- no i to jest  
mój problem.
Mam pytanie do Was, jak przyspieszyć ten algorytm?
A jeśli się nie da, to byłbym wdzięczny za naprowadzenie na jakiś inny  
sposób zaprogramowania opisanego problemu (narastania wartości w pewnej  
liczbie kroków).

Ilustracja graficzna działania poniżej zaprezentowanego algorytmu:  
http://imageshack.us/a/img341/925/74439722.png

    K = czas * czestotliwosc;

    if (K >= wartoscPradu) {
        for (t = 0; t <= K; t++) {
            drawPixel(px, py);
            y += wartoscPradu + 1;
            if (y >= K + 1)
                y -= K + 1, py++;
            px++;
        }
    } else {
        for (t = 0; t <= K; t++) {
            while (1) {
                x += K + 1;
                if (x >= wartoscPradu + 1) {
                    drawPixel(px, py);
                    x -= wartoscPradu + 1, px++;
                    py++;
                    break;
                }
                py++;
            }
        }
    }


Pozdrawiam i z góry dziękuję za pomoc,
Robbo  


Re: ATmega, jak zaprogramować narastanie wartości sygnału, bez użycia operacji zmiennoprzecinkowych?
cyt:

"Algorytm może działać zarówno na liczbach zmiennoprzecinkowych jak
 i całkowitych, ale ze względów wydajnościowych wykorzystuje się  
najczęściej realizacje całkowitoliczbowe. Zatem jeżeli początkowa
 wartość zmiennej decyzyjnej d lub jej przyrosty wychodzą nam ułamk
owe, to mnożymy zarówno zmienną decyzyjną d jak i jej przyrosty tak
 by uzyskać liczby całkowite. Możemy tak zrobić gdyż do decyzji b
ierzemy pod uwagę jedynie znak zmiennej decyzyjnej d."

źródło: http://www.algorytm.org/podstawy-grafiki/algorytm-bresenhama .
html

Re: ATmega, jak zaprogramować narastanie wa rtości sygnału, bez użycia operacji zmi ennoprzecinkowych?
On 09.10.2012 01:43, Robbo wrote:
Quoted text here. Click to load it
Albo czegoś nie zrozumiałem, albo to jest zwykła proporcja:
I(s)=I(S0)+(I(Se)-I(S0))*((s-S0)/(Se-S0))
I(s)=I(S0)+(I(Se)-I(S0))/(Se-S0) * (s-S0)
gdzie s - czas, S0 - czas początkowy, Se - czas końcowy

Przekształcasz to sobie na:
I(t)=I(T0)+t*dI
I(t)=I(t-1)+dI

Raz wyliczasz iloraz różnicowy dI, potem masz w każdym cyklu jedno  
dodawanie i jeden shift.


--  
Pozdrawiam
Michoo

Re: ATmega, jak zaprogramować narastanie wartości sygnału, bez użycia operacji zmiennoprzecinkowych?
Witam,

Dziękuję za odpowiedź, która mam nadzieję naprowadzi mnie na właściwe tory.

Quoted text here. Click to load it

Tak. Prąd ma przyrastać w K krokach o wartość maxPrąd/K w każdym kroku.

Quoted text here. Click to load it

Czas będzie zawsze liczony od zera. Prąd początkowy także będzie narastać od  
zera.
Więc jeśli I(S0) = 0, S0 = 0. Zatem powyższe formuły można uprościć do:
I(s) = I(Se) * (s/Se)
I(s) = I(Se)/Se*s

Quoted text here. Click to load it

Tu bym prosił o wyjaśnienie. Mało spałem i chyba nie do końca myślę, dlatego  
proszę o wybaczenie.

Czy dI będzie wartością zmiennoprzecinkową?
W jaki sposób będzie użyty shift?

Czy chodzi o to, że przy wyliczaniu dI robimy shift w lewo, aby nie tracić  
precyzji, a działać na liczbach całkowitych. Potem działamy na dużych  
wartościach dI, a tuż przed użyciem wartości I robimy shift w prawo?

Robbo



Re: ATmega, jak zaprogramować narastanie wa rtości sygnału, bez użycia operacji zmi ennoprzecinkowych?
On 09.10.2012 12:19, Robbo wrote:
Quoted text here. Click to load it
Dokładnie. Ale tak długo jak zmiany są liniowe to wystarcza raz policzyć  
iloraz różnicowy.

Quoted text here. Click to load it
Stałoprzecinkową, np. o 16 bitach części całkowitej i 16 po przecinku:

uint16_t I=0;
uint32_t I_accu=0;
uint32_t dI;
time_t last_time=0;

void new_setting(/**/){
   dI=(I_target<<16)/time_slices;
}
void calc(time_t t){
   I_accu+=dI*(t-last_time);
   I=I_accu>>16;
   last_time=t;
}

--  
Pozdrawiam
Michoo

Re: ATmega, jak zaprogramować narastanie wartości sygnału, bez użycia operacji zmiennoprzecinkowych?
Serdeczne Bóg zapłać. Wszystko ładnie działa.

Robbo  


Re: ATmega, jak zaprogramować narastanie war tości sygnału, bez użycia operacji zmiennopr zecinkowych?
Użytkownik Robbo napisał:
Quoted text here. Click to load it

Jakie bóg zapłać? Chłopaki piwa by się napili ;)

--  
AlexY
http://nadzieja.pl/inne/spam.html
We've slightly trimmed the long signature. Click to see the full one.
Re: ATmega, jak zaprogramować na rastanie wartości sygnału, bez u życia operacji zmiennoprzecinkow ych?
Nie ma problemu. Chętnie wyślę pocztą dobre piwo z małego browaru, a nie  
sikacz z koncernu.

R.  


Re: ATmega, jak zaprogramować narastanie war tości sygnału, bez użycia operacji zmiennopr zecinkowych?
On 10.10.2012 00:40, AlexY wrote:
Quoted text here. Click to load it
Łączę zainteresowanie elektroniką i piwem:

http://grota.be/photos/016/chmiel.jpg
http://grota.be/photos/016/gotowanie.jpg
http://grota.be/photos/016/temp.png

--  
Pozdrawiam
Michoo

Re: ATmega, jak zaprogramować narastanie wartości sygnału, bez użycia operacji zmiennoprzecinkowych?

Quoted text here. Click to load it
Jestem lepszy w EMC niż algorytmach ale zaproponuję to, co mi się nasunęło.

Może w przypadku K<I podzielić I/n (n=2,4,8,...) aż będzie K>I, a potem  
pętla już jak dla przypadku K>I, tylko py++ zastąpić py+=n.
"Schodki" wyjdą większe niż z twojej części else, ale jeśli dzielenie przed  
pętlą nie byłoby problemem to może być n=2,3,4,5,.... i wtedy to chyba już  
wyjdzie prawie to samo.
P.G.  


Re: ATmega, jak zaprogramować narastanie wartości sygnału, bez użycia operacji zmiennoprzecinkowych?

Quoted text here. Click to load it

Poprawka.
Jednak nie prawie to samo bo będą stałe przyrosty a czasem brak przyrostu.  
Przyrosty zmienne są jednak bliższe ideału.
P.G.  


Site Timeline