Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Rejestrator temperatury [ATtiny2313][C]

pibza 29 Gru 2010 23:59 3499 15
  • #1 29 Gru 2010 23:59
    pibza
    Poziom 9  

    Witam wszystkich Forumowiczów!
    Jestem uczniem 3 klasy technikum i już od pół roku zacząłem interesować się programowaniem uK. Pisałem w C bo to dla mnie prosty język. Ostatnio zadałem sobie problem (no dobra chcę zaszpanować przed kumplami :P). Chcę zrobić dobory rejestrator temperatury w pokoju. Wybrałem sobie uK ATtiny 2313, układ DS1820 (czujka temperatury) i pamięć eeprom 24c04 do przechowywania wyników. Zakres temperatury miał być od 15 do 50C z krokiem 0,1C. I gdy zabrałem się za pisanie programu natrafiłem na kilka problemów  Linia 1-wire jest chyba dobrze napisana, tylko wydaje mi się że coś nie hula zapis do pamięci. I kompletnie nie umiem poradzić sobie z przesłaniem tych danych do kompa.. Opis układu: Po wciśnięciu przycisku S1 rejestrator ma zacząć działać. Przerwanie (zbocze z układu NE555) budzi go z trybu idle (obniżony pobór mocy) i następuje obsługa linii 1-wire. Nie wiem czy dobrze zrealizowałem warunek końca (czyli ma zliczyć do 1440 (tyle pomiarów) i potem się wyłączy.. Po włączeniu przycisku S2 ma się dokonać przesłanie danych do komputera i tu już kompletnie nie wiem jak to zrobić… Może inny algorytm? Bardzo proszę o pomoc i wszelką poradę!!


    Oto mój listning programu:


    Code:


    #include <avr\io.h>
    #include <stdio.h>
    #include <inttypes.h>
    #include <avr\delay.h>
    #include <avr\interrupt.h>
    #include <avr\sleep.h>
    #include <avr/eeprom.h>


    #define DQ 9

    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)
    #define IN_DQ PIND & _BV(DQ)

    int i = 1; // zmienna sterujaca zapisaem do pamięci

    char msb, lsb, temp;

    float d1, d2;

    // procedura opóźniająca o (5+5*t)* 0,25 us dla 4MHz kwarcu
    void delay(unsigned char t)
    {
       do
       {
          asm("nop");
          
       }while(--t);
    }

    // procedura reset
    void ow_reset(void)
    {
       CLR_DQ; // stan niski na linii 1wire
       delay(255); //
       delay(119); // opóźnienie ok 480us
       //delay(1);
       SET_DQ;// stan wysoki na linii 1wire
       delay(255); //
       delay(119); // opóźnienie ok 480 us
    }
    // procedura zapisu bitu na linię 1wire
    void ow_write_bit(char b)
    {
       cli(); // zablokowanie przerwań
       CLR_DQ; // stan niski na linii 1wire
       delay(7); // opóźnienie 10us
       if(b)




          SET_DQ; // jeśli parametr jest niezerowy to ustaw stan wysoki na linii
       delay(80); // opóźnienie 100us
       SET_DQ; // stan wysoki na linii 1wire
       sei(); // odblokowanie pzrerwań
    }

    char ow_read_bit(void)
    {
       cli();
       CLR_DQ;
       delay(1);
       SET_DQ;
       delay(11);
       sei();
       if(IN_DQ)
          return 1;
       else
          return 0;
    }

    unsigned char ow_read_byte(void)
    {
       unsigned char i;
       unsigned char value = 0;
       for (i=0;i<8;i++)
       {
          if(ow_read_bit()) value|=0x01<<i;
          delay(6);
       }
       return(value);
    }

    void ow_write_byte(char val)
    {
       unsigned char i;
       unsigned char temp;
       for (i=0; i<8; i++)
       {
          temp = val >> i;
          temp &= 0x01;
          ow_write_bit(temp);
       }
       delay(5);
    }






    int main ()
    {
       //ustawienie wyjść portów
       DDRD = 0x73;
       PORTD = 0x77;
       
       DDRB = 0xff;
       PORTB = 0xff;
       
       
       
       
       sei();
       
       set_sleep_mode(SLEEP_MODE_IDLE); //tryb power-down gdyby tracił zawartość RAM czy można tryb Idle ( bity z 11 na 00)
       
       int zakoncz = 1440; // ilość ileracji programu
       
       //pobranie temperatur w doborym cyklu
       while(zakoncz)
       {
          
          zakoncz--;
          sleep_mode();
       }
       
       
       // wyłącznie całego układu
       cli();
       set_sleep_mode(SLEEP_MODE_PWR_DOWN);
       sleep_mode();
       
       return (0);
    }
    ISR(SIGN_INT1)
    {
          
          ow_reset();
          ow_write_byte(0xCC);
          ow_write_byte(0x44);
          _delay_ms(250);
          _delay_ms(250);
          _delay_ms(250);
          ow_reset();
          ow_write_byte(0xCC);
          ow_write_byte(0xBE);
          lsb = ow_read_byte();
          msb = ow_read_byte();

          lsb = lsb >> 4;
          msb &= 0x07;
          msb = msb << 4;
          temp = lsb | msb;
          d2 = temp / 10;
          d1 = temp % 10;
          eeprom_write_block(&d2,(0x04+&i), sizeof(&d2));
          eeprom_write_block(&d1,(0x08+&i), sizeof(&d1));  //argumentem jest adres, a drugim dana, powinno więc bć eeprom_write_byte(&liczba_LED,1);, 
          i = i *4;
    }

       



    Tutaj zamieszczam swój schemat ideowy.

    Rejestrator temperatury [ATtiny2313][C]

    0 15
  • #2 30 Gru 2010 00:38
    LordBlick
    VIP Zasłużony dla elektroda

    Następny... Procedura przerwania nie służy do obsługi Litanii do Św. Diody... Ustaw te wypociny w main tak, aby sprawdzały czy było przerwanie (np. jakąś zmienną globalną z atrybutem volatile) i coś z tym robiły gdy zaszło.

    0
  • #3 30 Gru 2010 12:47
    pibza
    Poziom 9  

    Wprowadziłem sugerowanie zmiany (dziękuję bardzo!). Ostatnio zapomniałem dodać, że komunikacja z komputerem miała by się odbywać poprzez port USB) ale mam nadzieję, że jest to czytelne z schematu. I co dalej miałbym zmienić/wprowadzić?

    0
  • #4 30 Gru 2010 18:26
    LordBlick
    VIP Zasłużony dla elektroda

    Programowałeś w ogóle µC ? Co to za dywagacje na sucho ?

    0
  • #5 30 Gru 2010 18:58
    pibza
    Poziom 9  

    tak - pisałem o tym we wstępie. Ale wyjątkowo nie umię poradzić sobie z tym problemem. I dlatego proszę o pomoc..

    0
  • #6 31 Gru 2010 00:12
    LordBlick
    VIP Zasłużony dla elektroda

    Może wymuszę pewną logikę w dyskusji - skoro masz kod, to czy z nim coś zrobiłeś ? Czy kompilator sypie błędami i jakimi ? Jeśli nie to do jakiego momentu dochodzi (łatwe do stwierdzenia przy pomocy symulacji lub LED podpiętej pod wolny pin) ?

    0
  • #7 31 Gru 2010 09:48
    pibza
    Poziom 9  

    Heh… Ja widzę, że się nie rozumiemy. Kompilator nie informuje o żadnych błędach, program jest napisany dobrze, ale nie umiem sobie poradzić z przeniesieniem zapisanych danych w pamięci 24C08. Kompletnie nie wiem jak to rozwiązać. A skoro nie wiem jak to zrobić, nie jestem w 100% czy w pamięci jest zapisywana liczba o żądanej dokładności – DS18B20. Cały problem polega na przeniesieniu danych z pamięci do komputera, nawet tego nie zacząłem pisać w programie, bo kompletnie nie wiem jak. Domyślam się, że trzeba będzie skorzystać z rejestru USART – asynchroniczny lub synchroniczny nadajnik lub odbiornik – Attiny2313 posiada taki rejestr.

    0
  • #8 31 Gru 2010 14:34
    LordBlick
    VIP Zasłużony dla elektroda

    Po co przenosić cokolwiek do PC ? Wstawiasz w kodzie porównanie z jakąś wartością odczytaną, którą wcześniej zapisywałeś, i jeśli się zgadza to np. LED świeci... Nadmienię jeszcze że t2313 ma również USI mogące pracować w trybie TWi czyli I²C do obsługi EEPROM... A co do zabierania się do czegokolwiek to google odpowiadają najszybciej ;)

    0
  • #9 01 Sty 2011 14:11
    pibza
    Poziom 9  

    heh... Jak rejestrator dobowy zapisuje co minutę pomiar, bo jak to ma być na LED wyświetlane? :/ poza tym dane sobie na kompie w Excel'u obrobię i mam wykres. Poza tym wiem, że wujek Google wie niby wszystko ale gdy przychodzi co do czego to nie ma nic :/ Pomiarów jest 1440! i one muszą być zapisane do pamięci a z pamięci na PC!

    0
  • #10 01 Sty 2011 18:05
    LordBlick
    VIP Zasłużony dla elektroda

    Miałem na myśli etap sprawdzenia kodu zapisu do pamięci, a nie docelowy. Najczęściej projekt rozwija się etapami. Poprawność kodu na etapie odczyt/zapis eeprom można najprościej sprawdzić tak, jak proponowałem. Jeśli chodzi o przesyłanie danych, to jest na AVRFreaks tutorial obsługi transmisji na przerwaniach oraz bez przerwań(oczywiście jest to okazja do szlifowania angielskiego technicznego).

    0
  • #11 06 Sty 2011 00:29
    pibza
    Poziom 9  

    Zabrałem się ostro do pracy i już wiem, gdzie tkwi błąd! uC nie obsługuje przerwania. Pozmianiałem kilka razy kod ale to nadal nic nie dało

    0
  • #12 06 Sty 2011 01:07
    LordBlick
    VIP Zasłużony dla elektroda

    Pomieszałeś dwa sposoby obsługi transmisji - nie można stosować dwóch w tym samym czasie.
    Proponuję tu obsługę na przerwaniach i do niej się odniosę.
    1. Nie widzę wywołania inicjalizacji nadawania USART w main(). Powinno to polegać na włączeniu na stałe TXCIE. UDRIE natomiast włączasz na starcie transmisji i na jej końcu wyłączasz.
    2. W przerwaniu od TXC jest totalny chaos:
    - Nazwa wektora SING_USART0_TXC coś śpiewająca... ;)
    - Radośnie odkryłem tu ... inicjalizację USART, która nie będzie wywołana, bo USART nie został zainicjowany...
    - Co to za while ? Poczytaj jeszcze raz o obsłudze przerwań - mają być jak najkrótsze i żadnych dziwnych pętli.
    - To przerwanie służy do zakończenia transmisji, a nie kontynuacji, w przypadku, gdy nie musimy reagować po zakończeni transmisji (np. w RS485 przełączanie na odbiór), nie ma potrzeby w ogóle się nim przejmować - wystarczy zostawić je "na pusto".
    3. Brakuje obsługi UDRE w przerwaniu do obsługi właściwej transmisji.
    4. nadajznak() do kosza, w samym przerwaniu od UDRE (wywoływane, gdy wysłanie nastepnego znaku jest możliwe) wpisujesz UDR0=dana_z_np_bufora; i nic więcej nie kombinujesz z pętlami - na jedno przerwanie może być wysłany tylko jeden bajt.
    5. Dane z eeprom (odczyt z tej pamięci musi być niezależny od transmisji) najpierw przygotowujesz w pętli głównej (bufor ?) a w przerwaniu wysyłasz jeden bajt przygotowanych danych. Oczywiście musisz sobie sterowanie pomiędzy main i przerwaniem jakoś ułożyć (wskaźnik jakiegoś bufora typu voilatie), aby main nadążał z danymi z eeprom, którego odczyt jest wooolnyyy...
    W ATtiny2313 jest tylko jeden USART, więc nie występuje numeracja rejestrów i bitów tych rejestrów (nie UBRR0, tylko UBRR itd.)
    Ogólnie to proszę sobie poczytać Datasheet-a od układu w sekcji USART.

    0
  • #13 06 Sty 2011 09:54
    mirekk36
    Poziom 42  

    A ja proponuję poczytać jednak przynajmniej jakiś kurs C albo książkę bo na chwilę obecną poza setką błędów, które opisał m.in kolega wyżej to twój program (o ile można go nazwać programem) przede wszystkim wykona się tylko JEDEN RAZ i KONIEC. Zatrzyma się na amen, a ty czekasz czy coś się dzieje.

    0
  • #14 06 Sty 2011 10:42
    kaczart
    Poziom 14  

    Zacznij od "Kurs programowania mikrokontrolerów w C" przedstawiany kilka lat temu w elektronice dla wszystkich (znadziesz w necie). Już po pierwszej lekcji byś wiedział że w main, musisz dać pętle nieskończoną (a nie jakieś while(zakoncz)), a w obsługach przerwań wywoływać tylko krótkie czasowo procedury. Przerobisz 5-6 lekcji z tego kursu i bez problemu zrobisz, to co chcesz zrobić. Do DS18x20 znajdziesz również gotowe biblioteki w C - dobrze jest się uczyć na takich gotowcach i podglądać jak inni piszą kod.

    pozdrawiam

    0
  • #15 06 Sty 2011 13:17
    asembler
    Poziom 32  

    Ja bym się zastanowił na zasilaniu rejestratora z baterii. Pomijając większą ilośc zastosowań (mozemy zostawic w lodówce) to dodatkowo nie ma potrzeby dołączania zewnetrznej pamięci bo stosując np atmege 8 mamy do dyspozycji RAM 1024 pomiarów. W zalezności od gęstości pomiarów można pokryc pomiarami dość długi odcinek czasu (4 tyg.)Dodatkowo bardzo prosto zrealizowac nie tylko zapis temperatury ale też czas w którym te pomiary były dokonywane.

    0
  • #16 06 Gru 2013 11:27
    pibza
    Poziom 9  

    Dziękuję za pomoc

    Pozdrawiam :)

    0