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

[Bascom] Attiny2313 - UART - Atmega328

maximus22_kr 22 Gru 2011 10:34 2660 10
REKLAMA
  • #1 10290864
    maximus22_kr
    Poziom 18  
    Witam
    Używam Attiny2313 do pomiaru dwóch temperatur z DS18B20. Wynik ( Integer ) przesyłam bez żadnej obróbki przez UART przewodem 40 cm do Atmega328.
    Atmega rozbija odebrane dane i jest obróbka

    Kod Attiny2313
    
    $regfile = "attiny2313.dat"
    $crystal = 8000000
    $baud = 4800
    
    '********************* Konfiguracja magistrali 1-Wire
    Config 1wire = Portd.5
    
    '********************* Konfiguracja wejść i wyjść
    Config Portb.0 = Output
    Set Portb.0
    
    '********** Konfiguracja Timer0   500 x 2 ms = 1 sekunda - Timer2 załaduj 6 do Timer2 - 250  dla Kwarc = 8 MHz
    
    Config Timer0 = Timer , Prescale = 256                      ' Dla Prescale 64 - 1 sekunda = 500
    On Timer0 Czas
    Enable Interrupts
    Load Timer0 , 6
    Enable Timer0
    
    '********************* Deklaracje zmiennych
    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte
    Dim I1 As Integer
    Dim I2 As Integer
    Dim Licznik1 As Integer
    Dim Licznik2 As Integer
    Dim Flaga_led As Bit
    
    Declare Sub Odczytaj
    Led Alias Portb.0
    Flaga_led = 0
    Cursor Off
    
    '********************* Adres pierwszego DS18B20
    Dsid1(1) = &H28
    Dsid1(2) = &H9F
    Dsid1(3) = &H79
    Dsid1(4) = &H25
    Dsid1(5) = &H03
    Dsid1(6) = &H00
    Dsid1(7) = &H00
    Dsid1(8) = &H00
    
    '********************* Adres drugiego DS18B20
    Dsid2(1) = &H28
    Dsid2(2) = &H24
    Dsid2(3) = &H47
    Dsid2(4) = &H25
    Dsid2(5) = &H03
    Dsid2(6) = &H00
    Dsid2(7) = &H00
    Dsid2(8) = &HD9
    
    Cls
    
    Do
    
    '********************* odczyt pierwszego DS18B20
       1wreset
       1wwrite &H55
       1wverify Dsid1(1)
       1wwrite &HBE
       I1 = 1wread(2)
    
    '********************* odczyt drugiego DS18B20
       1wreset
       1wwrite &H55
       1wverify Dsid2(1)
       1wwrite &HBE
       I2 = 1wread(2)
    
    '********************* konwersja dla wsaystkich DS18B20
       1wreset
       1wwrite &HCC
       1wwrite &H44
     Wait 1
    
    Loop
    End
    
    Sub Odczytaj
    Licznik2 = 0
    Reset Led
    
    Print I1 ; "," ; I2 ; Chr(13);
      Licznik1 = 0
    
    Set Led
    Flaga_led = 0
    End Sub
    
    '*********************  Timer2 - 2 ms x 500 = 1 sekunda
    Czas:
    Timer0 = Timer0 + 6
    Incr Licznik1
    Incr Licznik2
    
    If Licznik1 = 2000 Then
      Gosub Odczytaj
      Flaga_led = 1
    
    End If
    
    If Licznik2 = 400 Then
     Flaga_led = 0
    
     End If
    
    Return
    


    Kod Atmega328
    
    $regfile = "m328pdef.dat"
    $crystal = 8000000
    $baud = 4800                                                ' predkość transmisji
    $hwstack = 128                                              ' rozmiar stosu sprzętowego
    $swstack = 128                                              ' rozmiar stosu programowego
    $framesize = 128                                            ' rozmiar ramki
    
    '*********************
    'Enable Interrupts
    
    Config Serialin = Buffered , Size = 8 , Bytematch = 13
    Enable Serial
    
    Dim Flaga_rs As Bit
    Dim Ss1 As String * 6
    Dim Ss2 As String * 6
    
    '********************* Deklaracje zmiennych temperatury
    Dim Tmp As Byte
    Dim Tmp1 As Integer
    Dim Tmp2 As Integer
    Dim Tmp11 As String * 3
    Dim Tmp22 As String * 3
    Dim Przecinek1 As Byte
    Dim Przecinek2 As Byte
    Dim Ttt As String * 10
    
    
    Do
    
    If Flaga_rs = 1 Then
      Ttt = ""
      Input Ttt
      Flaga_rs = 0
    End If
    
    '***************************** Wyciągniecie ze stringu
    
    Tmp = Instr(ttt , "," )
    Przecinek1 = Tmp - 1
    Przecinek2 = Tmp + 1
    
    Tmp11 = Mid(ttt , 1 , Przecinek1)
    Tmp1 = Val(tmp11)
    
    Tmp22 = Mid(ttt , Przecinek2 , 3 )
    Tmp2 = Val(tmp22)
    
    
    '***************************** Obliczanie temperatury
    
    '********************* Obliczenia dla pierwszego
     Tmp1 = Tmp1 * 10
       Tmp1 = Tmp1 / 16
       'If I1 > 0 Then Cls
       Ss1 = Str(tmp1)
       Ss1 = Format(ss1 , " 0.0")
    
    
    '********************* Obliczenia dla drugiego
       Tmp2 = Tmp2 * 10
       Tmp2 = Tmp2 / 16
       'If I2 > 0 Then Cls
       Ss2 = Str(tmp2)
       Ss2 = Format(ss2 , " 0.0")
    
    Loop
    End
    
    '*********************** Obsługa bufora UART
    Serial0charmatch:
    Flaga_rs = 1
    Return
    


    W sumie problemów jest klika:
    występują czasem przekłamania i Atmega odbiera jakieś dziwne znaki, np. z minusem ( gdzie nie powinno go być ), nie wiem ,czy wynika to z długości kabelka UART

    Kod obliczający temperaturę dobrze się sprawdzał na innym układzie Atmega, gdy temperatura była od razu wyświetlana na LCD - oczywiście minusowa również.
    Natomiast tutaj jeden z czujników jest za oknem i pomimo ujemnej temperatury zatrzymuje się na 0.0 ( sprawdzałem też na mrożonce )
  • REKLAMA
  • REKLAMA
  • #3 10291269
    maximus22_kr
    Poziom 18  
    Zastosowałem w obu układach kwarce 8Mhz, do tego szybkość transmisji UART 4800. Układy spięte taśmą trzy przewodową - Rx/Tx/GND, zasilane z portów USB jednego komputera.

    Te przekłamania są losowe, muszę jeszcze sprawdzić, jak to działa z komputerem przez dłuższy czas.

    Zastanawia mnie, dlaczego mimo odpięcia zasilania z płytki Attiny2313 dalej układ działa ( tzn. świeci się dioda sygnalizująca zasilanie - tylko trochę słabiej ), czy port UART może przenosić napięcie zasilania ?

    wieczorem sprawdzę jeszcze fusebity - zwłaszcza tej na Attiny2313, bo ją uruchamiałem dopiero wczoraj.

    Jeśli chodzi zmienne to ( przy sytuacji, gdy dojdą prawidłowo ):
    - zmienna ttt wyświetla wartości prawidłowo ( nawet minusowe )
    - zmienne tmp1 i tmp2 również
    - wynik końcowy dla zmiennej ss1 ( czujnik jest za oknem ) nie schodzi poniżej 0.0, chyba kontrolerowi jest obojętne skąd pochodzą dane do obliczeń, ważne są odpowiednie typy zmiennych i kolejność obliczeń
  • #4 10291330
    MichałKob
    Poziom 20  
    Na każdym porcie procesora są dwie diody: jedna anodą do pinu, katodą do +Vcc, a druga anodą do masy, katodą do pinu. Służą one do zabezpieczenia procesora, ale czasami wychodzą takie śmieszne sytuacje, że przez nie procesor bierze sobie zasilanie :)
    Może da się wyeliminować błędy sumą kontrolną: Trzeba dodać jeszcze jedną zmienną Byte i po kolei dodawać do niej wszystkie zmienne danych (najwyżej się przepełni) i wysłać ją razem z nimi, a potem w odbiorniku także wyliczyć jej oczekiwaną na podstawie danych wartość i porównać z tą przesłaną. W ten sposób zamiast krzaków przynajmniej pozostanie stary wynik :)
  • #5 10297698
    maximus22_kr
    Poziom 18  
    Może trzeba zmienić sposób wywoływania odczytu czujników ?

    Te błędne wartości nie są przypadkowe - np. wskazania pierwszego to wartość z drugiego i na odwrót
  • #6 10298484
    Mundi1970
    Poziom 24  
    Podstawowy błąd w programie odbierającym dane to za mały bufor, dane mogą być nadpisywane. Bufor powinien mieć minimum 14 bajtów, zmienne są wysyłane w postaci łańcucha np. "-32768,-32768",$0D. Do prawidłowej pracy bufora wymagane jest globalne włączenie przerwań (Enable Interrupts).

    Kod: text
    Zaloguj się, aby zobaczyć kod


    EDIT:
    Pasowałby też jakiś nagłówek na początku wysyłanych danych, urządzenia przy włączaniu nie muszą jednocześnie wystartować. Więc może się zdarzyć że dane nie zostaną całkowicie odczytane.
  • REKLAMA
  • #7 10298840
    maximus22_kr
    Poziom 18  
    Dziękuję Koledze Mundi1970 za radę.

    W sumie z buforem to chciałem oszczędnie, jeśli chodzi o pamięć.

    Co do nagłówka, to chodzi o coś takiego jak jest w ciągu GPS? Czyli zawsze jest na początku GPRMC ? Czyli jeśli jest to znaczy, że początek ciągu jest odebrany prawidłowo.
    W sumie ma to dodatkowy sens, bo w przypadku większej liczby urządzeń już po RS485, każde będzie mieć swój nagłówek, traktowany jako ID.

    Jeśli uda mi się ustawić poprawne połączenie RS232 to wystarczy tylko dorobić obsługę przełączania układu MAX485 i też powinno działać ?
  • REKLAMA
  • #8 10299029
    Fredy
    Poziom 27  
    Wystarczy jeden unikatowy znak na początku np #.
    Wtedy w odbiorniku otwierasz bufor dopiero wtedy gdy odczytasz ten znak.
    No i na końcu warto dodać CRC.
  • #9 10299071
    Mundi1970
    Poziom 24  
    maximus22_kr napisał:
    W sumie z buforem to chciałem oszczędnie, jeśli chodzi o pamięć.

    Dane można wysyłać przez Printbin, a odebrać przez Inputbin. Nadając zmienną integer funkcją Printbin wysyłasz 2 bajty.

    Nagłówkiem może być jakiś bajt, nic nie przeszkadza żeby stworzyć sobie jakiś format przesyłania danych ;).

    nagłówek bajt X
    zmienna 1 long
    zmienna 2 word
    zmienna 3 byte
    suma kontrolna (zmienna 1-3)
    znacznik końca pakietu


    Wtedy można funkcją Inkey() wyszukać pierwszy bajt nagłówka, a dalej odczytywać przez Inputbin. Jeżeli dane będą poprawne, odbiorca może odpowiedzieć nadawcy. Nadawca po wysłaniu danych oczekuje przez pewien czas na odpowiedź, jeżeli jej nie otrzyma to TIMEOUT. Jeżeli był timeout to wysyła jeszcze raz te same dane, jeżeli nie to nowe dane.
  • #10 10299785
    maximus22_kr
    Poziom 18  
    może jakoś zabezpieczyć stałość ciągu po stronie nadajnika:

    
    If I1 <100 Then
    
    Else if I1 < Then
    
    Else I1 = I1
    
    


    w jaki sposób dodać) lub zera do zmiennej typu Integer, tak, aby zawsze był trzycyfrowy ?
  • #11 10300065
    Mundi1970
    Poziom 24  
    maximus22_kr napisał:
    w jaki sposób dodać) lub zera do zmiennej typu Integer, tak, aby zawsze był trzycyfrowy ?

    Kod: text
    Zaloguj się, aby zobaczyć kod
REKLAMA