Skocz do zawartości

[Bascom] Konwersja integer na single i odwrotnie


nanab

Pomocna odpowiedź

Mam problem z konwersją single na integer. Wcześniej operowałem tylko na liczbach całkowitych i wszystko ładnie działało, jednak teraz potrzebuję większej dokładności.

Wcześniej miałem coś takiego:

   Integral = Integral + Diff                               

  Integral = Integral * Ki                                      'Ki = 2

zmieniłem na coś takiego:

   Integral = Integral + Diff                               
  Integralsing = Integral                                    'konwersja integer na single
  Integralsing = Integralsing * Ki                       'Ki = 1.8
  Integral = Round(integralsing)                        'konwersja single na integer 

Wszystkie zmienne typu integer, tylko integralsing typu single i jedna stała-Ki.

Na pierwszej wersji wszystko działa jak należy, na drugiej nie działa wcale-wyrzuca jakieś ogromne wartości praktycznie niezależne od tego co na wejściu. Co robię źle?

Link do komentarza
Share on other sites

Z moich doświadczeń wynika, że Bascom jest dość "upośledzony" co do liczb zmiennoprzecinkowych, dlatego zawsze robiłem, tak że zamiast np Ki = 0.1, wpisywałem Ki = 1 i tak robiłem z każdym współczynnikiem, a na koniec wynik dzieliłem po prostu przez 1000 (Kp, Ki, Kd).

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Nie do końca rozumiem czemu przez 1000 a nie przez 10, no chyba że na końcu masz mnożenie a nie sumowanie 🙂 Spróbuję tej metody.

Na początek wymienię na coś takiego:

    Integral = Integral + Diff                               
  Integral = Integral * Ki                                  'Ki = 18 zamiast 1.8
  Integralsing = Integral                                   'konwersja
  Integralsing = Integralsing / 10
  Integral = Round(integralsing)                        'konwersja single na integer 

jak nie zadziała to czeka mnie przebudowa całego regulatora zgodnie z twoją metodą.

Możesz jeszcze napisać jak przerabiasz wynik na liczbę całkowitą? Bo w końcu po podzieleniu przez ten 1000 czy 10 pewnie zostanie coś po przecinku. Też przez polecenie round()? Czy może bascom automatycznie ucina sobie to co po przecinku?

Link do komentarza
Share on other sites

Liczba stałoprzecinkowa nie może mieć nic po przecinku, więc procesor (a nie kompilator) od razu wyrzuca wszystko co "po przecinku" (bez zaokrąglania!). W celu zaokrąglenia jak masz np. finalny_wynik/1000 możesz po prostu zrobić (finalny_wynik+500)/1000.

Poczytaj o fixedpoint math. To jest coś w stylu tego co pisze Treker, ale zamiast *10 czy *100 mnożysz przez liczby będące potęgą 2 (czyli np. *16 i potem /16). Powód jest taki, że mnożenie/dzielenie przez potęgi liczby 2 mikrokontrolery wykonują bardzo szybko za pomocą przesuwania bitów (w C jest to << i >>). Zamiast tracić setki i tysiące cykli procesora na mnożenie/dzielenie możesz zastąpić to kilkoma cyklami na przesunięcie bitów, a efekt ten sam.

Jeszcze jedna właściwość takich liczb to że jak masz liczbę a w formacie 12:4 (12 bitów całkowitych, 4 reszty czyli np 100*16 da 1600) i przemnożysz ją przez liczbę w formacie 12:4 to wynik będziesz miał 8:8 (ew. więcej bitów liczby całkowitej jak wynikiem będzie liczba 32bitowa a nie 16). Czyli żeby wrócić do wielkości całkowitej musisz podzielić przez 256 (przesunąć 8 bitów w prawo) a nie przez 16.

Analogicznie, tylko odwrotnie jest w drugą stronę (czyli 12:4/12:4 daje liczbę 16:0)

PS. W procesorach bez zintegrowanych funkcji zmiennoprzecinkowych omijaj takie typy jak ognia. Obliczenia na nich są BARDZO wolne (zazwyczaj 10-20 razy wolniejsze niż operacje na liczbach stałoprzecinkowych). Dla mikrokontrolera 8bitowego może to oznaczać tysiące lub nawet dziesiątki tysięcy cykli na jedną operację. Dodatkowo zamiana liczb zmiennoprzecinkowych na stałoprzecinkowe i odwrotnie to też czasochłonna operacja.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Nie do końca rozumiem czemu przez 1000 a nie przez 10, no chyba że na końcu masz mnożenie a nie sumowanie

Kp, Ki i Kd są u mnie 10 krotnie większe niż powinny, dlatego na końcu zamiast dzielić osobno 3 razy przez 10, to dziele raz na samym końcu przez 1000.

Link do komentarza
Share on other sites

Spróbowałem programu z mojego poprzedniego postu i jego modyfikacji bez zmiennych typu single, tj:

  Integral = Integral + Diff
  Integral = Integral * Ki                                 'Ki = 18 zamiast 1.8
  Integral = Integral + 5                                 ' zaokraglanie
  Integral = Integral / 10

I uzyskałem ciekawy efekt-może robot nie jeździ, ale ładnie gra 🙂 Silniki stoją i wydają dźwięki jak by pracowały na zablokowanych wałach. Dźwięki się zmieniają razem ze zmianą odczytów z sensorów-całkiem fajne organki 😃

Kp, Ki i Kd są u mnie 10 krotnie większe niż powinny, dlatego na końcu zamiast dzielić osobno 3 razy przez 10, to dziele raz na samym końcu przez 1000.

Chodziło mi o to, że P*10+I*10+D*10 = (P+I+D)*10 a nie *1000. No chyba że w swoim programie na końcu zamiast control = P+I+D masz control = P*I*D.

MirekCz, dzięki za naprowadzenie mnie na właściwy tor. Faktycznie niby proste działania a tak zasobożerne. Poczytam i spróbuję zrobić to na dzieleniu przez 8 albo 16.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.