logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATMega168PA][C]Rzutowanie INT-FLOAT

excray 14 Sty 2012 10:33 2146 3
  • #1 10394527
    excray
    Poziom 41  
    Mam prosty programik który mierzy napięcie i prąd na boczniku 2R (1R+1R a pomiar jest na połowie bocznika):
    main.c
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    lcd.c
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Napięcie wynosi ok. 1,2V a prąd rzędu 60mA. Niestety nie wychodzi mi przeliczenie mocy. W ADC otrzymuję wartość 600 więc z wymnożenia 600*1200 powinienem otrzymać wartość rzędu 720000. Niestety zamiast tego dostaję w zależności od zmian prądu zupełnie inne wartości i na dodatek raz dodatnie raz ujemne, wszystkie nieprawidłowe. Podejrzewam że problem jest z rzutowaniem zmiennej float na int albo w samej funkcji LCD_INT. Prąd i napięcie wyświetlane są prawidłowo.
  • Pomocny post
    #2 10394551
    krru
    Poziom 33  
    W języku C zastosowane operacje i funkcje zależą od typu parametrów, a nie od oczekiwanego typu wyniku. W C++ rozwinięto to do pojęcia przeciążania funkcji, i można mieć kilka funkcji o tej samej nazwie, ale różnych parametrach i kompilator sam wybierze odpowiednią wersję. Mnożenie to też pewien rodzaj funkcji zwany operatorem.

    Mnożenie p = i*u wykonywane jest więc na typie int, który w AVR ma AFAIK 16 bitów i wychodzi przepełnienie.
    Trzeba zmienić typ na float przed mnożeniem albo poprzez rzutowanie, albo konstrukcją typu:

    p = u;
    p *= i;

    Oczywiście takiej liczy nie da się skonwertować na int, chyba że odkomentujesz to p/=1000.

    Drugie rozwiązanie to zamiana int na 32 bitowy typ np uint32_t (może być bez znaku, wyniki ADC są nieujemnie).
  • Pomocny post
    #3 10394573
    mirekk36
    Poziom 42  
    Ależ w funkcji lcd_int() nie masz nic wspólnego z rzutowaniem zmiennych a szczególnie float.

    Jest tylko zamiana liczby binarnej na ASCII za pomocą wbudowanej funkcji ITOA (Integer To ASCII)

    zastanów się jakie zakresy liczb może pomieścić typ int (czytałeś o typach ? - spróbuj zajrzeć do tabelki bo masz taką w książce na 1000%) to po pierwsze wyjaśni ci się od razu dlaczego zamiast liczby 720000 otrzymujesz jakieś liczby ujemne albo inne dziwolągi.

    Jak zajrzysz do tabelki to zobaczysz przede wszystkim że 720000 gigantycznie przekracza zakres int

    i jeśli nadal będziesz chciał wyświetlać tak wielkie liczby - to zajrzyj do pomocy w PDF w folderze WInAVR o nazwie LIBC - tam wśród opisów wielu wbudowanych funkcji znajdziesz na pewno funkcję itoa() ale także jej bliźniaczą wersję dla większego zakresu (typu liczb)

    przecież 720000 to zmieści się dopiero w typie long int - jeśli zobaczysz w tabelce . Reasumując - zainteresuj się funkcją

    ltoa() czyli Long to ASCII

    wystarczy więc w kodzie zamienić itoa() na ltoa() ale i zmienić typ rgumenu funkcji z int na long int albo od razu uint32_t

    spróbuj - ale pamiętaj zawsze o typach i mniej więcej chociaż zakresach liczb jakie mogą przechowywać

    albo napisz własną funkcję do konwersji liczb binarnych na ASCII - taki przykład też masz w książce.
  • #4 10394609
    excray
    Poziom 41  
    mirekk36 napisał:
    zastanów się jakie zakresy liczb może pomieścić typ int (czytałeś o typach ? - spróbuj zajrzeć do tabelki bo masz taką w książce na 1000%) to po pierwsze wyjaśni ci się od razu dlaczego zamiast liczby 720000 otrzymujesz jakieś liczby ujemne albo inne dziwolągi.

    Jak zajrzysz do tabelki to zobaczysz przede wszystkim że 720000 gigantycznie przekracza zakres int

    Ależ ja to wiem. Dlatego p zostało zdefiniowanie jako float. Nie wiedziałem tylko że kompilator w nosie ma to że wynik zadeklarowany jest jako float. Niemniej za ltoa należy się jak nic pomógł. Dziękuję wszystkim. Zamykam temat.
REKLAMA