RTV forum PL | NewsGroups PL

Optymalizacja algorytmu Bresenhama w ATmega128 do płynnego narastania prądu

ATmega, jak zaprogramować narastanie wartości sygn ału, bez

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Optymalizacja algorytmu Bresenhama w ATmega128 do płynnego narastania prądu

Robbo
Guest

Mon Oct 08, 2012 11:43 pm   



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

Dondu
Guest

Tue Oct 09, 2012 4:12 am   



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łamkowe, 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 bierzemy pod uwagę jedynie znak zmiennej decyzyjnej d."

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

Michoo
Guest

Tue Oct 09, 2012 7:29 am   



On 09.10.2012 01:43, Robbo wrote:
Quote:
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].
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

Piotr Gałka
Guest

Tue Oct 09, 2012 8:06 am   



Użytkownik "Robbo" <niemam@gmail.com> napisał w wiadomości
news:5073652e$0$26682$65785112@news.neostrada.pl...
Quote:
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).

Jestem lepszy w EMC niż algorytmach ale zaproponuję to, co mi się nasunęło.


Może w przypadku KI, 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.

Piotr Gałka
Guest

Tue Oct 09, 2012 8:18 am   



Użytkownik "Piotr Gałka" <piotr.galka@CUTTHISmicromade.pl> napisał w
wiadomości news:5073db09$1@news.home.net.pl...
Quote:

Użytkownik "Robbo" <niemam@gmail.com> napisał w wiadomości
news:5073652e$0$26682$65785112@news.neostrada.pl...
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).

Jestem lepszy w EMC niż algorytmach ale zaproponuję to, co mi się
nasunęło.

Może w przypadku KI, 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.

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.

Robbo
Guest

Tue Oct 09, 2012 10:19 am   



Witam,

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

Quote:
Albo czegoś nie zrozumiałem, albo to jest zwykła proporcja:

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

Quote:
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

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

Quote:
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.

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

Michoo
Guest

Tue Oct 09, 2012 10:50 am   



On 09.10.2012 12:19, Robbo wrote:
Quote:
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
Dokładnie. Ale tak długo jak zmiany są liniowe to wystarcza raz policzyć

iloraz różnicowy.

Quote:

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.

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ą?
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

Robbo
Guest

Tue Oct 09, 2012 2:49 pm   



Serdeczne Bóg zapłać. Wszystko ładnie działa.

Robbo

AlexY
Guest

Tue Oct 09, 2012 10:40 pm   



Użytkownik Robbo napisał:
Quote:
Serdeczne Bóg zapłać. Wszystko ładnie działa.

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

--
AlexY
http://nadzieja.pl/inne/spam.html
http://www.pg.gda.pl/~agatek/netq.html

Robbo
Guest

Wed Oct 10, 2012 10:03 am   



Nie ma problemu. Chętnie wyślę pocztą dobre piwo z małego browaru, a nie
sikacz z koncernu.

R.

Michoo
Guest

Thu Oct 11, 2012 7:52 pm   



On 10.10.2012 00:40, AlexY wrote:
Quote:
Użytkownik Robbo napisał:
Serdeczne Bóg zapłać. Wszystko ładnie działa.

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

Łą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

elektroda NewsGroups Forum Index - Elektronika Polska - Optymalizacja algorytmu Bresenhama w ATmega128 do płynnego narastania prądu

NOWY TEMAT