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

Konwersja string na integer w Bascom dla DS18B20 - jak zaokrąglić?

janek1815 30 Sie 2005 08:49 8300 16
  • #1 1776390
    janek1815
    Poziom 38  
    Posty: 4513
    Pomógł: 372
    Ocena: 1062
    witam mam nastepujacy problem w bascom moze banalny ale nie moge go przesskoczyc:(brak logicznego myslenia)
    chodzi o pomiar temperatury na ds 18b20
    przed wyswietleniem temperatury formatuje liczbe za pomoca polecenia:
    Str_temp = Fusing(temp , "#.&")
    wiec z liczby np: 22.6255 zostaje mi 22.6 i moge to wyswietlic jest ok tylko liczba jest zapisana jako string
    a ja potrzebuje liczbe 22.6 lub 226 tylko integer do dalszych obliczen najlepiej przed uzyciem polecenia fusing
    wiec pytanie jak zamienic string na integer lub jak odrzucic te trzy ostatnie liczby po przecinku aby zostaloa tylko jedna liczba
    dziekuje
  • #2 1776585
    Jaca
    Poziom 32  
    Posty: 1332
    Pomógł: 239
    Ocena: 217
    Ja to robię w następujący sposób (BASCOM AVR):
    1. Trzymam temperaturę w zmiennej typu integer, np. 36.6 °C to liczba 366;
    2. Aby wyświetlić temperaturę np. na LCD deklaruję zmienną typu string i przepisuję do niej temperaturę za pomocą funkcji Str(). Następnie formatuję przygotowany string przy użyciu funkcji Format i wyświetlam.

    Przykład:

    Dim Temp As Integer
    Dim Disp As String * 5
    
    Temp = 366 'odczytana wartość temperatury
    Disp = Str(Temp)
    Disp = Format(Disp , "  0.0")
    Locate 1 , 1
    Lcd Disp


    Pozdrawiam...
  • #3 1776861
    janek1815
    Poziom 38  
    Posty: 4513
    Pomógł: 372
    Ocena: 1062
    moj listing:
    1wreset
    1wwrite &H55
    For I = 1 To 8
    1wwrite Nr_ukladu(i)
    Next I
    1wwrite &HBE
    T(1) = 1wread()
    T(2) = 1wread()


    1wreset
    Tt = Makeint(t(1) , T(2))
    Temp = Tt / 16

    Str_temp = Fusing(temp , "#.&")

    Locate 1 , 10
    Lcd Tt
    Locate 1 , 1
    Lcd Temp
    Locate 2 , 1
    Lcd "Temp.(" ; R ; ")" ; Str_temp
    End Sub
    temp wynosi 23,3125
    str_temp jest 23,3
    tt czyli integer 373
    gdzie jest blad. nie mialem problemow z ds1820 a z tym ds18b20 nie moge sobie poradzic

    moze ma ktos gotowa procedure odczytu dla ds 18b20
    ale tak aby wynikiem byl integer 3 cyfrowy czyli zamiast 22,3 stopnia
    bylo 223 tak jak to ma miejsce w ds1820
  • #4 1776986
    K_o_n_r_a_d
    Poziom 23  
    Posty: 318
    Pomógł: 86
    Ocena: 9
    Z tego co widzę to ten string potrzebny jest Ci tylko do wyświetlania.
    Ja wyrzuciłbym stringa a obliczenia dokonywał tylko na tt (tt - integer).
    tt=Makeint(t(1),T(2))
    tt=tt*10
    tt=tt/16
    i teraz tt zawiera temperature pomnożoną *10 (23,5st - tt=235) a reszta została obcięta, może lepiej byłoby zaokrąglić, ale...
    Pozdrawiam, Konrad.
  • Pomocny post
    #5 1776996
    Kminek
    Poziom 15  
    Posty: 200
    Pomógł: 21
    Ocena: 16
    Hej!

    Zobaczcie jak ja to robię, może komuś sie to przyda:

    'Powiedzmy ze zmienna Liczba(single) wynosi 22.62555426
    Temp = Int(liczba) ' dzieki temu poleceniu odcinam czesc setna czyli
    ' zmiennej Temp(byte) przypisuje liczbę 22
    Liczba = Frac(liczba) ' dzieki temu poleceniu odcinam czesc
    ' dziesiętną czyli zmiennej Liczba(single) przypisuje
    ' liczbe 0.62555426
    Liczba = Liczba * 100' mnożąc razy sto otrzymuję liczbę 62.555426
    Liczba = Int(liczba) ' ponownie odcinam cześc dziesiętną przypisując
    ' zmiennej Liczba(single) liczbe 62
    Setna = Liczba ' Przypisanie zmiennej Setna(byte) liczby 62

    Dzięki tym operacją otrzymuję dwie zmienne typy byte: Temp i Setna które odpowiednio wynoszą 22 i 62. Moim zdaniem jest to lepsze rozwiązanie ponieważ pozbywamy się zmiennej typu single i operujemy na dwóch zmiennych typu byte. I tak np. wyświetlenie temperatury sprowadza się do: Lcd "T: "; Temp ; "," ; Setna ;"C"

    Pozdrawiam
  • #6 1777902
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    Kminek napisał:
    Hej!
    Zobaczcie jak ja to robię, może komuś się to przyda:

    Fajnie :D , tylko sprawdź ile pamięci programu na to zużywasz :|
    Zauważyłem , że niektórzy z kolegów są bardzo rozrzutni.
    Choćby takie kwiatki:
    
    1wreset
    1wwrite &H55
    For I = 1 To 8
    1wwrite Nr_ukladu(i)
    Next I
    1wwrite &HBE
    T(1) = 1wread()
    T(2) = 1wread()
    

    Toż to woła o pomstę do nieba :D
    Czy wszyscy używają ATMega128(lub 256) :?:
    Nie wierzę :wink:

    Piotrek
  • #7 1784197
    janek1815
    Poziom 38  
    Posty: 4513
    Pomógł: 372
    Ocena: 1062
    zumek jesli masz na mysli mnie to uzywam atmega32 i mam jeszcze 12kb wolnego miejsca wiec jest ok ale jak braknie to przejde na atmega 128 . dziekuje wszystkim za pomoc
  • #8 1854647
    e11
    Poziom 17  
    Posty: 331
    Ocena: 14
    Cytat:
    Fajnie , tylko sprawdź ile pamięci programu na to zużywasz
    Zauważyłem , że niektórzy z kolegów są bardzo rozrzutni.
    Choćby takie kwiatki:
    Kod:

    1wreset
    1wwrite &H55
    For I = 1 To 8
    1wwrite Nr_ukladu(i)
    Next I
    1wwrite &HBE
    T(1) = 1wread()
    T(2) = 1wread()


    Toż to woła o pomstę do nieba

    Zumek podpowiedz mniej doświadczonym jak powinno być i w czym jest problem . Swoją drogą jak w bascomie sprawdzić ile zajmują pamięci dane linijki programu albo cały program. Co robićkiedy w procku zaczyna brakować pamięci i jak można okroić program , co jest najbardziej pamięciożerne. Pozdrawiam
  • #9 1856693
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    e11 napisał:

    ...
    Zumek podpowiedz mniej doświadczonym jak powinno być i w czym jest problem .

    Przytoczony przez Ciebie(i mnie) fragment programu, jest jak najbardziej prawidłowy - z punktu widzenia kompilatora - i będzie działał jak trzeba :D
    Jest tylko jedno "ale".Niepotrzebnie zużyjemy klawiaturę :wink: i - co w tym przypadku jest jeszcze straszniejsze - pamięc programu.
    Poniżej przykład hmmm ... optymalizacji:
    
    Const Dlafor = 1       'informacja dla preprocesora
    
    $regfile = "m8def.dat"
    Config 1wire = Pind.1
    Dim I As Byte , T(2) As Byte , Nr_ukladu(9) As Byte , T1 As Integer
    
    1wreset
    1wwrite &H55
    #if Dlafor       'skompiluje się , dla Const Dlafor=1 (większy od zera)
       For I = 1 To 8
          1wwrite Nr_ukladu(i)
       Next I
       1wwrite &HBE
       T(1) = 1wread()
       T(2) = 1wread()
       T1 = Makeint(t(1) , T(2))
    
    #else       'skompiluje się , dla Const Dlafor=0
    
    '   For I = 1 To 8
    '      1wwrite Nr_ukladu(i)
    '   Next I
       1wwrite Nr_ukladu(1) , 8       'równoważnik 3 powyższych lini
    
       1wwrite &HBE       'bez zmian
    
    '   T(1) = 1wread()
    '   T(2) = 1wread()
    '   T1 = Makeint(t(1) , T(2))
       T1 = 1wread(2)       'równoważnik 3 powyższych lini
    
    #endif
    
    End
    

    Po kompilacji otrzymujemy kod wynikowy w bajtach:
    dla Const Dlafor = 1 540 B - skompiluje się kod między #if-#else
    dla Const Dlafor = 0 444 B - skompiluje się kod między #else-#endif
    Udało się w tym przykładzie zaoszczędzić 96 B pamięci programu , czyli ~20% , a to "nie w kij dmuchał" ;)
    e11 napisał:

    Swoją drogą jak w bascomie sprawdzić ile zajmują pamięci dane linijki programu albo cały program.

    CTRL+W lub kliknąć w "łapka trzymająca kartkę z tekstem" - innymisłowy zajrzeć do raportu.
    e11 napisał:

    Co robićkiedy w procku zaczyna brakować pamięci i jak można okroić program , co jest najbardziej pamięciożerne. Pozdrawiam

    Trudne pytanie :(
    Potrzebna będzie ... wnikliwość,ciekawość,upór i ... odrobina doświadczenia :D

    Piotrek
  • #10 1859639
    e11
    Poziom 17  
    Posty: 331
    Ocena: 14
    Dzięki za odpowiedź ale najbardziej to mi brak doświadczenia:|
    Ale po woli nie od razu Kraków zbudowano:D
    O! gdzie się podziały uśmiechy :cry: ha nie wstawiłem spacji :D i to jest właśnie nowe doświadczenie
  • #11 1896378
    TOMSON
    Poziom 19  
    Posty: 458
    Pomógł: 2
    Ocena: 40
    Z kumplem coś takiego wypociliśmy i działa bardzo dobrze a bardziej zmniejszyć sie już nie dało

    $crystal = 4000000
    Config Lcd = 16 * 1a
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config 1wire = Portd.0
    Dim I As Integer
    Dim S As Single
    Deflcdchar 0 , 7 , 5 , 7 , 32 , 32 , 32 , 32 , 32
    Display On
    Cursor Off
    Cls
    Do
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Waitms 800
    1wreset
    1wwrite &HCC
    1wwrite &HBE
    I = 1wread(2)
    S = I / 16
    Locate 1 , 1
    Lcd S ;
    Locate 1 , 8
    Lcd Chr(0) ;
    Lowerline
    Locate 2 , 1
    Lcd "C"
    Loop
    End
  • #12 1896586
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    TOMSON napisał:
    Z kumplem coś takiego wypociliśmy i działa bardzo dobrze a bardziej zmniejszyć sie już nie dało

    Czyżby :?:
    
    $crystal = 4000000
    Config Lcd = 16 * 1a
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config 1wire = Portd.0
    Dim I As Integer , Ss As String * 6
    'Dim S As Single
    Deflcdchar 0 , 7 , 5 , 7 , 32 , 32 , 32 , 32 , 32
    Display On
    Cursor Off
    Cls
    Do
       1wreset
       1wwrite &HCC
       1wwrite &H44
       Waitms 800
       1wreset
       1wwrite &HCC
       1wwrite &HBE
       I = 1wread(2)
    'S = I / 16
       I = I * 10        'na dokładkę zwiększona rozdzielczość do 0.1 C 
       I = I / 16
       Ss = Str(i)
       Ss = Format(ss , "  0.0")
    'Locate 1 , 1
    'Lcd S ;
       Home
       Lcd Ss ; Chr(0) ; "C";" ";
    'Locate 1 , 6
    'Lcd Chr(0) ; "C";
    'Lowerline
    'Locate 1 , 7
    'Lcd "C"
    Loop
    


    Domyślam się , że chodzi o DS18B20 ;)

    Piotrek
  • #13 1896827
    TOMSON
    Poziom 19  
    Posty: 458
    Pomógł: 2
    Ocena: 40
    Ja to tylko tu zrobiłem żeby prawidłowo wyswietlało na wyswietlaczu
    a tu inna wersja jak chcesz dokładniej

    $crystal = 4000000
    Config Lcd = 16 * 1a
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config 1wire = Portd.0
    Dim I As Integer
    Dim S As Single
    Deflcdchar 0 , 7 , 5 , 7 , 32 , 32 , 32 , 32 , 32
    Display On
    Cursor Off
    Cls
    Do
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Waitms 800
    1wreset
    1wwrite &HCC
    1wwrite &HBE
    I = 1wread(2)
    S = I / 16
    Locate 1 , 1
    Lcd S ;
    Locate 1 , 8
    Lcd Chr(0) ;
    Lowerline
    Locate 2 , 1
    Lcd "C"
    Loop
    End
    wersja poprzednia optymalizowana do AT90S2313
  • #14 1896925
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    Nie rozumiemy się , chyba ;)
    Ja się pytam - dlaczego używasz , zmienej S typu SINGLE :?:
    Przecież te kilka linijek kodu , pożera Ci 90% Atmelka 2313.

    Piotrek

    PS
    I gdzie ta optymalizacja :?:
  • #15 1898441
    TOMSON
    Poziom 19  
    Posty: 458
    Pomógł: 2
    Ocena: 40
    witam
    jest i wersja bez tej funkcji z pomiarem temp + i - i zajmuje też 98% pamieci procka ale obecnie program jest przerobiony do atmegi 8 to ponizej

    $regfile = "m8def.dat"
    $crystal = 4000000
    Config Lcd = 16 * 1a
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config 1wire = Portd.0
    Dim Temp1 As Byte
    Dim Temp2 As Byte
    Dim Setne As Byte
    Dim T As Byte
    Dim Znak As String * 1
    Deflcdchar 0 , 7 , 5 , 7 , 32 , 32 , 32 , 32 , 32
    Cursor Off
    Cls
    Do
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Waitms 800
    1wreset
    1wwrite &HCC
    1wwrite &HBE
    Temp1 = 1wread()
    Temp2 = 1wread()
    If Temp2 >= 248 Then
    Temp1 = 255 - Temp1
    Temp2 = 255 - Temp2
    Znak = "-"
    Else
    Znak = "+"
    End If
    Setne = 0

    Temp1.0 = 0
    Temp1.1 = 0
    Temp1.2 = 0

    Setne.3 = Temp1.3

    Temp1.3 = 0

    Temp1 = Temp1 / 16
    Temp2 = Temp2 * 16
    If Setne = 8 Then
    Setne = 5
    Else
    Setne = 0
    End If
    T = Temp1 + Temp2
    If T < 10 Then
    Locate 1 , 1
    Lcd "Temp: " ; Znak ; T ;
    Lowerline
    Locate 2 , 1
    Lcd "." ; Setne ; Chr(0) ; "C"
    Else
    Locate 1 , 1
    Lcd "Temp:" ; Znak ; T ;
    Lowerline
    Locate 2 , 1
    Lcd "." ; Setne ; Chr(0) ; "C"
    End If
    Loop
    End
  • #16 3296019
    KaczorGSM
    Poziom 15  
    Posty: 132
    Pomógł: 1
    Ocena: 66
    Jaca napisał:
    Ja to robię w następujący sposób (BASCOM AVR):
    1. Trzymam temperaturę w zmiennej typu integer, np. 36.6 °C to liczba 366;
    2. Aby wyświetlić temperaturę np. na LCD deklaruję zmienną typu string i przepisuję do niej temperaturę za pomocą funkcji Str(). Następnie formatuję przygotowany string przy użyciu funkcji Format i wyświetlam.

    Przykład:

    Dim Temp As Integer
    Dim Disp As String * 5
    
    Temp = 366 'odczytana wartość temperatury
    Disp = Str(Temp)
    Disp = Format(Disp , "  0.0")
    Locate 1 , 1
    Lcd Disp


    Pozdrawiam...


    Prawie działą :)
    W zakresie temperatur -0.9 do 0.9 C program głupieje (resetuje procek lub mamy zwiechę)
  • #17 3403861
    vikelf
    Poziom 13  
    Posty: 81
    Pomógł: 2
    Ocena: 3
    Pytanie do bardziej doświadczonych:

    W jaki sposób najoptymalniej wyświetlać wartości zmiennych na LCD?
    Czy przy wyświetlaniu zmiennej o wartości (0, 1000) trzeba stosować if.. then..elseif..elseif....else ?

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy konwersji i formatowania pomiaru temperatury z czujnika DS18B20 w języku Bascom AVR. Problem polega na przekształceniu wyniku pomiaru temperatury, który jest początkowo w postaci liczby zmiennoprzecinkowej lub stringa (np. "22.6"), na wartość typu integer do dalszych obliczeń. Proponowane rozwiązania obejmują przechowywanie temperatury jako liczby całkowitej pomnożonej przez 10 (np. 23,5°C jako 235), co umożliwia łatwe operacje matematyczne bez konieczności używania zmiennych typu Single. Wskazano, że funkcja Fusing służy głównie do formatowania wyświetlania, a obliczenia lepiej wykonywać na wartościach integer. Przykłady kodu pokazują odczyt danych z DS18B20, konwersję surowych danych na temperaturę, a także metody optymalizacji pamięci programu na mikrokontrolerach Atmel (np. ATmega32, ATmega8, AT90S2313). Poruszono także kwestie obsługi temperatur ujemnych i wyświetlania na LCD z formatowaniem do jednej cyfry po przecinku. Wskazano, że operacje na zmiennych typu byte zamiast Single mogą znacznie zmniejszyć zużycie pamięci. Dyskusja zawiera przykładowe fragmenty kodu do odczytu i wyświetlania temperatury z DS18B20 w Bascom AVR oraz sugestie dotyczące optymalizacji i zaokrąglania wyników.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA