• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 1 głosów - średnia: 1
  • 1
  • 2
  • 3
  • 4
  • 5
duże liczby - zamiana stringa na double lub float
#1
Nie działaja mi zamiana dużych liczb ze stringa na float.
Nie działa mi nawet zwykłe dodawanie dużych liczb.


Kod:
void setup() {

Serial.begin(38400);

float test;
test=40000000+1;
Serial.println(test);

}

void loop() {}
Daje w wyniku 40000000.00

Docelowo chodzi o wprowadzenie z klawiatury numerycznej 4x4 liczyby w zakresie do 40mln, zapiasnie jej do stringa a następnie przekształcenie na float. I to nie działa. Funcje typu toDouble() i toFloat() też dają takie zaokrąglony wyniki.

Kod:
void setup() {

Serial.begin(38400);

String test="40000001";

Serial.println(test.toFloat());

}

void loop() {}
 
Funkcji sscanf nie kumam, no chyba że ktoś mi tu napisze jak za jej pomocą "40.000.001" przekształcić na float.
 
Odpowiedź
#2
Duble w ardunio nie działa a float jest do 7 cyfr. Po co w ogóle ci float z tego ?? jaki sens zmiana stringa do floata?? nie lepiej działać na dużych liczbach??
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#3
@Jarewa0606 wyjaśnił problem. Jak chcesz czegoś więcej niż zabawy porzuć AVR. Może nie zauważyłeś ale GCC na AVR praktycznie się nie rozwija i ma ogromne ograniczenia, jak wspomniany tu doble-float czy ograniczenie prawie wszystkiego do 16-bit więc nie działa << 16.
Porzuć AVR na rzecz lepszych i przy okazji tańszych ARM no chyba, że jesteś wyznawcą MK.

Używam ARM bo:
- ARM przeważnie są tańsze niż AVR o podobnym wyposażeniu oferując zdecydowanie większe możliwości (DMA, więcej bardziej zaawansowanych niż w AVR peryferii) i szybkość działania.
- ARM, przy tym samym zegarze jest ok 7 razy szybszy od AVR, a maksymalne częstotliwości taktowania zaczynają się od 24MHz a kończą na 650 (w przypadku rodziny STM32).
- W przeważającej większości mają więcej pamięci RAM i można robić duże bufory nadawcze dla UART, I2c, SPI, USB.
- Maja bogatsze wyposażenie (liczba USART/UART, I2C, SPI, timerów) i większe możliwości tychże peryferii. 12 UART w STM32 nie jest problemem, AVR max 4. Można dołożyć np SC16IS7xx ale 1 UART to ok 10zł, 2 ok 19zł).
- Mają DMA (AVR ATmega/tiny nigdy o czymś takim nie słyszały).
- Wiele ARM ma USB, w AVR to rzadkość a USB jest teraz pewnym standardem.

- Sprzętowe sterowanie przepływem i kierunkiem transmisji (RS485), wykrywanie końca ramki, określanie prędkości transmisji.
- Wersje z Ethernetem, AVR nie ma z ETH.
- Wszystkie timery 16-bit (można łączyć w 32-bit) a wiele wersji posiada 32-bit.
- ADC 12..16-bit, CA 12-bit.
- ADC do 80MS/s (LPC), 18MS/s (STM32).
- Mają wielopoziomowy system przerwań (15 poziomów, Xmega tylko 3, Mega/Tiny 0 ale najnowsze wersje maja już 2/3 poziomy).
- Zdecydowanie większe pojemności pamięci FLASH (do 2MB) i RAM (do 1MB) o czym nawet AVR Xmega mogą tylko pomarzyć.
- Sprzętowe interfejsy CAN, LCD równoległe, matryce LCD kolor 18-bit.
- Stany wyjątkowe: Błąd magistrali i podobne jak w MC68k (dawne MAC, Amiga).
- Kilkadziesiąt razy tańsze narzędzia. Ddebuger STM32 - 13zł vs badaj najtańszy klon JTAG-ICE 45zł (tylko JTAG), ATATMEL-ICE-PCB 300zł, w obudowie 700 (Basic 470zł), Dragon ok 450zł.

- CubeMX do konfigurowania i generowania kodu (najnowszy także IDE i kompilator).
- Podczas debugowania na bieżąco widzę stan zmiennych w AVR po zatrzymaniu uC.
- Nie muszę się zastanawiać czy dana jest w ram czy flasch aby użyć stosownej funkcji (z sufiksem _P).
- Argument w sprintf, scanf itp nie jest ograniczony do 16-bit (int) lecz do 32-bit.
- Przesuwane bitu (w lewo) nie jest ograniczone do 16 bitów.
- W AVR nie ma typu double, ma taki sam zakres jak float. I tak dobrze, że od którejś tam wersji, typ long long ma 64-bity a nie jak wcześniej 32-bit tak samo jak long.
- AVR nie mają FPU, STM32 wiele rodzin posiada FPU.
- Odkładanie na stos w przerwaniu rejestrów, które czasem nie są używane (R0, R1, RAMPZ, rejestr statusu) co wymusza czasem używanie wstawek ASM.

- Maureli, Tytuł: uint64_t ciekawostka Wrzucam parę cennych informacji na temat błędu dotyczącego operacji AND na liczbach typu uint64_t w avr-gcc
https://stackoverflow.com/questions/5009...operations
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85805



Przykładowo, wysyłanie danych do WS2812 w przypadku Arduino (nie ważne AVR, ARM czy ESP) blokuje CPU na czas tej operacji. Nie wiem jak w przypadku ESP i ARM ale w AVR blokowane są przerwania. To oznacza, że w tym czasie nie będą np odbierane znaki przez UAR, nie działa USB, itp. Transmisja do LED może trwać nawet kilkadziesiąt ms. W ARM, sama transmisja będzie trwać tyle samo ale CPU będzie zajęty tylko przez kilkaset ns bo wysyłaniem danych zajmuje się DMA.
To samo z LCD, w AVR CPU zajęty 100% w czasie wysyłania danych (typowo 20..40ms w przypadku kolorowego wyświetlacza), na ARM us.

Wysyłanie na AVR danych do wyświetlacza w czasie dziesiątek ms jest możliwe, że ma wymaganą ilość pamięci RAM na bufor. Wyświetlacz 96x64 wymaga 12'288bajtów RAM (z Mega w grę wchodzi tylko Mega1284), 128x128 wymaga 32kB RAM, więc Mega odpada. Wymusza to stawianie punktu po punkcie, co zajmuje ok 3 razy więcej czasu.
Namacalne dowody:
https://www.elektroda.pl/rtvforum/topic3588785.html
Zainstalowałem bibliotekę „TFT_ILI9163C-master” ze strony „Nettigo”. Uruchomiłem przykład „Cube”, efekty widać na filmie.
https://es2.000webhostapp.com/Szescian_3...no_UNO.mp4
Zagoniłem do pracy ARM STM32F411CE. Zegar ustawiłem na 60MHz, co pozwoliło taktować SPI częstotliwością 15MHz, maksymalną dopuszczalną dla IL9306. Przeniosłem bibliotekę z Arduino, oto efekt:
https://es2.000webhostapp.com/Szescian_3...ez_DMA.mp4
Słaby coś ten ARM, animacja niewiele szybsza (użyłem HAL, gdyby wykorzystać dostęp rzez rejestry animacja byłaby prawie 2 razy szybsza niż na UNO). Nie, to nie ARM słaby tylko programista, który przeniósł kod nie wykorzystując możliwości sprzętowych ARM. Stworzyłem bufor na dane dla wyświetlacza (128*160*2=40960bajtów) i zagoniłem do pracy DMA. Efekt:
https://es2.000webhostapp.com/Szescian_3D_ARM_z_DMA.mp4
Na koniec porównanie ARM z AVR, gdzie na AVR wyraźnie widać rysowanie tła podczas jego zmiany.
https://es2.000webhostapp.com/Szescian_3...vs_AVR.mp4
https://es2.000webhostapp.com/Szescian_3...ne_tlo.mp4
Forum: https://www.elektroda.pl/rtvforum/topic3588785.html

Akcelerator LCD forum: https://forbot.pl/forum/topic/16876-akce.../#comments pokrewny temat: https://www.elektroda.pl/rtvforum/topic3588785.html
Akcelerator LCD YT: https://www.youtube.com/playlist?list=PL...acjvhzPRdM https://www.youtube.com/playlist?list=PL...86bcULhy33
Akcelerator WS2812: https://forum.atnel.pl/post222192.html#p222192


Dla początkujących: https://stm32.eu/2019/01/31/nowa-ksiazka...-dostepna/
Kod z delay to nie kod, to DEMO!
Możliwości sprzętowe uC trzeba wykorzystywać a nie /machać/. GPIO!
Jestem a usilnie chcę być amatorem to dwie różne rzeczy.

http://er-mik.prv.pl/projekty edw.php 
http://er-mik.prv.pl/projekty_avt.php
 
Odpowiedź
#4
To się nazywa pobić rekord w wypisywaniu bzdur...

A tak dla wyjaśnienia - typ float, czyli zmiennopozycyjny pojedynczej precyzji jest reprezentowany tak samo na ARM, jak i na AVR, RISCV i wielu innych platformach. Jest to ustandaryzowany przez IEEE format.
W każdym przypadku będzie więc tak, że dodając bardzo małe liczny do bardzo dużych dostajemy niedokładny wynik. Można oczywiście użyć typu o podwójnej precyzji, ale to tylko "przesunie" problem, wystarczy że wartości będą odpowiednio większe i pojawi się dokładnie to samo zjawisko.
Tak jak napisał kolega @Jarewa0606, używasz nieodpowiedniego typu, dlatego wyniki są niezgodne z oczekiwaniami. Ale to nie ma nic wspólnego z tymi bzdurami o wyższości ARM nad AVR.
 
Odpowiedź
#5
Tu się akurat z tobą nie zgodzę AMR ma sprzętowe wspomaganie FPU dlatego przy liczbach zmiennoprzecinkowych AMR and AVR to przepaść...
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#6
Sprawdźmy co na to Wikipedia.

Posłużę się takim rysunkiem:

[Obrazek: 1280px-IEEE-754-single1.svg.png]

Część całkowita zapisywana jest w postaci potęgi liczby dwa: 2^E
Trzydziestodwu bitowa reprezentacja liczby float wygląda następująco:

[Obrazek: 1fe7ee91c66c8a5c3e56f28a520684ff83f15763] gdzie B to podstawa systemu liczbowego, czyli w naszym przypadku 2.
Dodawanie, lub odejmowanie takich liczb wygląda tak:
[Obrazek: c0cc5ce40aedf83695e8262de6ef6c36da5a631f]
Jeśli wykładniki tych liczb znacznie się od siebie różnią, to mantysa mniejszej liczby zostaje bardzo silnie zdenormalizowana.
"W szczególnym przypadku, jeśli E 1 − E 2 jest większe niż liczba cyfr mantysy, to po denormalizacji mantysa będzie miała wartość 0, a liczba o mniejszym wykładniku nie wpłynie na wynik dodawania bądź odejmowania."
Co właśnie stało się w Twoim przypadku.

P.S.
Te wszystkie scanfy, sprintfy itp. nic nie wskórają.

P.S.2
Możesz pobawić się w ustawieniach linkera, bo o ile pamiętam to są jakieś biblioteki, które ten problem załatwią.
A sorry, zapomniałem że to Arduino i nie pobawisz się linkerem.

P.S.3
(01-03-2020, 11:45)Jarewa0606 napisał(a): Tu się akurat z tobą nie zgodzę AMR ma sprzętowe wspomaganie FPU  dlatego przy liczbach zmiennoprzecinkowych AMR and AVR to przepaść...

FPU zwiększy prędkość obliczeń, ale nie precyzję. Normalizacja zawsze przesuwa bity aby pozbyć się części całkowitej, więc obcina mantysę o 8 bitów.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#7
@Jarewa060, jeśli masz rdzeń ARM z koprocesorem arytmetycznym, to operacje mogą być wspierane sprzętowo i wyniki uzyskasz dużo szybciej. Inna sprawa że większość mikrokontrolerów z rdzeniem ARM ma wyższe taktowanie i po prostu działa szybciej niż AVR, ale to wszystko i tak jest bez znaczenia. Błędy pojawiają się z przyczyn o których wspomniał @Robson Kerman i nie pomoże tutaj nawet zmiana na x86_64.
Więc w kwestii optymalizacji czasu obliczeń, użycie ARM może być wskazane. Układy z tymi rdzeniami mają mnóstwo zalet, ale w tym konkretnym przypadku pisanie o DMA to jakieś absurdalne bzdury i zupełne niezrozumienie tematu. Co w sumie nie powinno dziwić, jak i to że po raz kolejny pojawiają się wzmianki o p. Kardasiu.
 
Odpowiedź
#8
Chłopy nie bądźcie (co niektórzy) jak baby. Chłop je konkretny, baba nie je. Ja nie pytam o wyższość gruszek nad jabłkami tylko chcę rozwiązać problem. STM-a też mam, X-megi też ale to ma być na adurninie.
Liczby typu float muszą być bo takimi liczbami z arduino jest karmiony generator na AD9850 który ma dokładność ułamków Hertza zasięg do kilkudziesięciu MHz więc muszę mieć możliwość zapodania liczby np 19000123.1Hz

Pytanie jest proste.
Da się z tymi liczbami czy nie, jak się da to jak, jak się nie da to trudno i idę na piwo.
Pozdro.
 
Odpowiedź
#9
Więc odpowiedź jest prosta - typem float się nie da, czas iść na piwo Smile
 
Odpowiedź
#10
No to jakim się da, jakimś się musi dać.
Przykładowo, wprowadzam sobie z klawiatury (doklejam kolejne char-y) do stringa wartości i powstaje sobie łańcuch str=[29123123].
Jak to zamienić na liczbę. Mowa o liczbach 8-cyfrowych.
toInt() toFloat() toDouble() - nie działa prawidłowo.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości