Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

wtorek, 22 marca 2011

Problem znaku zapytania podczas konwersji float do znaków ASCII w celu wyświetlenia na np. LCD itp.


Autor: Dondu

Ponieważ co jakiś czas otrzymuję pytania dot. problemu znaku zapytania przy konwersji za pomocą funkcji z rodziny printf, sprintf, itp.:


Anonimowy
... kiedy chcę wysłać liczbę to na terminalu wyświetla się tylko ?

Anonimowy
... kiedy importuje projekt do ATMEL Studio 6.1, linkuje 2 biblioteki libprint_flt.a i libm.a i wgrywam to już zamiast rps i ms/obr pokazują się pytajniki. Mógłbyś mi powiedzieć co robię źle?

Anonimowy
... potem podczas proby wysylania cyfry w wyniku otrzymuje wyswietlony na ekranie znak zapytania.

Anonimowy
wysłanie liczby daje efekt w postaci "?"

Anonimowy
Chciałbym na ekranie telefonu (chodzi o system Android - dop. red.) wyświetlać wartości odczytywane przez mikrokontroler z czujnika temperatury, niestety sposób przedstawiony powyżej generuje na ekranie pytajniki.


postanowiłem skrobnąć ten krótki artykuł.

Chodzi o moment, w którym obliczoną liczbę typu float (zmiennoprzecinkową) konwertujemy za pomocą funkcji  printf, sprintf, itp. do postaci ciągu znaków ASCII, w celu np. jej wyświetlenia na LCD, czy też wysłania za pomocą jakiegoś interfejsu np. RS-232C do odbiornika np. komputera.


Anonimowy
Na LCD wyświetla mi się"U=? [V]". Natomiast wartość nieprzeliczona wyświetla się normalnie.



Objawy

Zamiast otrzymania za pomocą w/w funkcji prawidłowo sformatowanego wyniku w postaci ciągu znaków otrzymujemy znak zapytania.


Przykład - Spodziewasz się ładnie sformatowanych liczb:


Przykład prawidłowej konwersji liczby typu float.
Przykład prawidłowej konwersji liczb float na ciągi znaków.
Pochodzi z artykułu: RS-232: Komunikacja ATmega8 z komputerem

a otrzymujesz jedynie znaki zapytania (przykład dostarczony przez Anonimowego):


Przykład nieprawidłowej konwersji liczby typu float.
Przykład nieprawidłowej konwersji liczb float na ciągi znaków.

Powyższy przykład pokazuje wysyłanie danych z mikrokontrolera w formie znaków ASCII przez RS-232 do komputera. Ale jak już wspomniałem wcześniej te same objawy dot. LCD, itp.



Rozwiązanie

Należy wykonać dwie czynności dodając w opcjach projektu:


1. dodanie bibliotek libm.a oraz libprintf_flt.a

Wersja dla AVR Studio:

AVR Studio - Dodawanie bibliotek.
Przykład dla AVR Studio 4.xx

Wersja dla Atmel Studio:


Atmel Studio - ustawienia projektu.
Atmel Studio - ustawienia projektu.


Atmel Studio - dodanie bibliotek.
Atmel Studio - dodanie bibliotek.


2. dodanie opcji linkera:

Wersja dla AVR Studio:

AVR Studio - Dodawanie opcji linkera.
Przykład dla AVR Studio 4.xx


Na niebiesko zaznaczyłem pole, w którym po kolei powinieneś wpisać wszystkie parametry i klikając przycisk Add, dla każdego parametru osobno. Efekt końcowy ma być taki jak na powyższym screen-ie - kolejność parametrów nie ma znaczenia.

Aby nie było wątpliwości co do literek:
-WI
-lprintf_flt
-lm
-u
vfprintf

Zauważ, że vfprintf jako jedyny nie ma poprzedzającego znaku minus (myślnika).

Szczegóły w zakresie opcji linkera znajdziesz pod niniejszym linkiem: <stdio.h>: Standard IO facilities


Wersja dla Atmel Studio:


Atmel Studio - opcje linkera.
Atmel Studio - opcje linkera. 


Nie zapomnij zapisać ustawień :-)



Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

20 komentarzy:

  1. Witam
    Używam Atmel Studio (wersja 6.0), dodałem biblioteki libm.a oraz libprintf_flt.a zgodnie z instrukcją (chociaż była już dodana domyślnie jedna biblioteka oznaczona "m" - usunąłem ją), nie mogę jednak wykonać drugiego kroku - nie mam w ogóle opcji Use vprintf libary. Co na to poradzić?
    Z góry dziękuję za wszelką pomoc

    OdpowiedzUsuń
    Odpowiedzi
    1. Witaj. Jaką wersje AS masz zainstalowaną?

      Usuń
    2. Mam wersję 6.0.1703 - beta

      Usuń
    3. Faktycznie za problem była odpowiedzialna wersja mojego Atmel Studio - po aktualizacji problem się rozwiązał. Dzięki Dondu, sam nie wiem dlaczego nie zwróciłem na to uwagi :)

      Usuń
  2. Dodałem bibliotekę libprintf_flt.a w atmel studio wersja 6.2 kilka dni temu w jednym projekcie i było ok. Teraz robię kolejny projekt i nie przyniosło to spodziewanego efektu. :/ Pamiętam że w pierwszym projekcie też miałem z tą biblioteką problemy ale jakoś ruszyło, teraz nie chce. Czy oprócz dodania biblioteki "libprintf_flt.a" bo libm już mam trzeba wykonywać jeszcze jakieś dodatkowe czynności ?

    OdpowiedzUsuń
    Odpowiedzi
    1. Zaznaczyć w opcjach linkwera Use vprintf library.

      Usuń
    2. Jest to pokazane w tym artykule na grafice z podpisem: "Atmel Studio - opcje linkera."

      Usuń
  3. 1. Zapewne niektórym przydałaby się informacja jak to zrobić w Eclipse, który jest również popularnym środowiskiem.
    2. W przykładzie ze strony: http://mikrokontrolery.blogspot.com/2011/03/rs-232-atmega8-komputer-terminal.html można linię:

    sprintf(usart_bufor, "%f", 0.3187 * odb_x * odb_x + 2 * odb_x - 7);

    zastąpić przez:

    dtostrf(0.3187 * odb_x * odb_x + 2 * odb_x - 7, 12, 5, usart_bufor);

    Oczywiście należy wtedy dołączyć stdlib.h

    Pozdrawiam. :-)

    OdpowiedzUsuń
    Odpowiedzi
    1. W eclipse należy pstąpić dokładnie tak samo jak to zostało opisane w artykule. Oczywiście inaczej wyglądają okienka w których dodaje się biblioteki i definiuje symbole. Rozwiązanie pokazane przez ciebie nie jest równoważne z użyciem sprintf - zapewnia konwersję float na ASCII lecz nie formatuje łańcucha.

      Usuń
    2. Próbowałem zarówno sposobem Anonimowego, jak i sposobem wstawienia wartości -WI
      -lprintf_flt
      -lm
      -u
      vfprintf
      do opcji C/C++ Build
      Korzystam z Eclipse, próbowałem to zrobić w sposób następujący:
      Project Properties -> C/C++ Build -> Zakładka: Builder Settings -> Odhaczyć "Use default..." -> wybrać z listy wartości "-lprintf_flt... itd"
      Jeśli gdzieś zbłądziłem, lub robię coś źle, to proszę o pomoc. Bo próbowałem też wielu innych rzeczy i nic nie pomaga.
      Pozdrawiam

      Usuń
    3. Nie pamiętam jak się to robi w Eclipse, ale gdy go używałem, to dało się to prawidłowo ustawić. Zastanów się jednak nad zmianą środowiska na oryginalne Atmel Sudio tym bardziej, że ma wbudowany symulator.

      Usuń
    4. Dzięki za szybką odpowiedź :)
      Niestety Atmel Studio nie ma możliwości obsługi USBasp, wiem że napisałeś fajny poradnik jak to ustawić, ale niestety czegoś nie do końca zrozumiałem i odpuściłem gdy nie działało. Może kiedyś (wygląda na to że niedługo :P ) jeszcze raz nad tym usiądę i spróbuję ponownie. Póki co walczę z tym Eclipse.
      Ritchie'go i Karnighana znalazłem implementację funkcji void itoa(int n, char s[]). Ma ona pewne wady, ale może warto spróbować...

      Usuń
    5. *W książce Ritchiego
      Wybaczcie, zmęczenie :P

      Usuń
    6. Witam ponownie :)
      Problem rozwiązany, szczerze mówiąc nie ma potrzeby dodawania opcji w linkerze podanych w artykule powyżej (oczywiście są one na dłuższą metę przydatne).
      Rozwiązaniem problemu konwersji i znaków zapytania jest zastosowanie funkcji:
      char* dtostrf(double WartoscKonwertowana, signed char _width, unsigned char _prec, char *ŁancuchZnakowy);
      Całość wyjaśniona jest w książce Pana Tomasza Francuza Język C dla mikrokontrolerów (str 91 wyd. Helion)

      Pozdrawiam

      Usuń
  4. Zaczęło działać, jednak teraz wynik na wyświetlaczu mi się zamraża na wartości pierwszej zmierzonej zaraz po uruchomieniu i przy zmienianiu pozycji pokrętła potencjometru nie zmienia się, jedynie od czasu do czasu spontanicznie się zmieni lub po dłuższym czasie. Przy wyświetlaniu samych kroków (adc bez modyfikacji) taka sytuacja nie ma miejsca. Czym to może być spowodowane?

    OdpowiedzUsuń
    Odpowiedzi
    1. Niewielkie zmniejszenie czasu opóźnienia poprawiło sytuację jednak niewiele. Dodam, że dla mniejszych wyświetlanych wartości proces przebiega znacznie lepiej. Czy to możliwe, żeby funkcja sprintf() była aż tak zasobożerna?

      Usuń
    2. Jednak funkcja sprintf() nie ma na to wpływu. Problem pojawił się gdy mojemu mikrokontrolerowi przyszło wykonywać operację na zmiennych typu float wobec może to komentarz pod niewłaściwym postem, ale czy ktoś zna rozwiązanie tego problemu?

      Usuń
    3. Bez poznania Twojego programu nie mamy jak pomóc.

      Usuń
    4. Anonimie, dodawałeś funkcję sei() przed rozpoczęciem pętli while(1) ?

      Pozdrawiam

      Usuń
  5. Skąd wziąć te biblioteki?
    Bo albo jestem ślepy albo ich nigdzie nie widzę bo za każdym razem jak wporwadze je z katalogu WinAvr i wprowadze te funkcje do linker options to dostaje błąd
    c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: cannot find -l\libm

    OdpowiedzUsuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.