Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATMEGA8] Cyfrowy termometr i kalkulator

bdfhjk 24 Jul 2008 15:11 13114 57
e-mierniki
  • #31
    bdfhjk
    Level 11  
    Podłączone są dobrze, sprawdziłem przykładając miernik pomiedzy podstawkę a wyświetlacz. Wtedy świeci. A numerkow jest kilka i nie wiem który. Na zdjęciu je dobrze widać ale jak trzeba to przepisze. Końcowy schemat to ten z 1kohm przy porcie d
  • e-mierniki
  • #32
    Balu
    Level 38  
    Super ja też jak przyłożę miernik... IZOLACJI między wyświetlacz a tv to się świeci... a czasem nie...
    JAKI MIERNIK?
    JAK PRZYŁOŻONY?
    Nie zakładaj że byliśmy przy tym wszyscy...

    Dodano po 52 [sekundy]:

    P.S. Pokaż - wklej który schemat mnie się nie chce szukać.
  • e-mierniki
  • #33
    bdfhjk
    Level 11  
    schemat:

    [ATMEGA8] Cyfrowy termometr i kalkulator

    Powodem jednak były błędy w lutowaniu. Teraz tylko nie działają przyciski.
  • #35
    bdfhjk
    Level 11  
    Przyciski już działają. Teraz tylko nie wiem jak skalibrować pomiar temperatury. Termistor mam 10kohm połączony z vcc i szeregowo 1kohm oraz rezystor 10kohm połączony z masą. W środku zbudowanego w ten sposób dzielnika znajduje się kabel połączony z wejściem ADC. Czy jest lepszy sposób niż porównywanie wyniku ADC ze zwykłym termometrem?
  • #36
    Balu
    Level 38  
    Sprawdzenie krzywych w datashecie do termoelementu...
    Albo jak piszesz...

    Dodano po 58 [sekundy]:

    Ew. Wsadzenie dobrze zaizolowanego czujnika do wrzątku - 100stopni:)

    (Bo potrzebujesz raczej dwóch punktów pomiarowych, żeby wyznaczyć krzywą... a tym wypadku prostą:) ).
  • #37
    bdfhjk
    Level 11  
    Czy jest jakiś uniwersalny ds do termorezystorów? Mój nie jest w żaden sposób oznakowany poza pomarańczowym i czarnym paskiem ...
  • #38
    snow
    Level 30  
    Balu wrote:

    (Bo potrzebujesz raczej dwóch punktów pomiarowych, żeby wyznaczyć krzywą... a tym wypadku prostą:) ).


    No chyba nie do końca bo termistory nie są liniowe. Jakoś nie zauważyłem w jakim zakresie ma być pomiar temperatury. Ja kiedyś przybliżałem wielomianem 3-go lub 4-go stopnia LM35 :) i wyszło "w miarę" w zakresie 25-100st. a co dopiero taki termistor ;)
  • #39
    bdfhjk
    Level 11  
    Będzie służył jako termometr mierzący temperaturę w pomieszczeniu jeżeli jest to możliwe, tzn. wykorzystując zwykły termistor.
  • #40
    snow
    Level 30  
    A to dwu punktowy powinien podołać ;)

    Dodano po 43 [minuty]:

    Najprosciej to wrzuć do wody o temp. 40 st (raczej więcej w pomieszczeniu nie ma) i do lodówki (nie wiem ile masz w lodówce stopni - najlepiej czymś zmierz), odczytaj wartości z przetwornika, ułóż równanie i niech ci przelicza na stopnie.
  • Helpful post
    #41
    dawid512
    Level 32  
    A jeden DS18B20 załatwił by sprawę... zamiast kombinować z termistorami i kalibracją.
  • #42
    Balu
    Level 38  
    Nie wiem czemu wszyscy się na te nieszczęscne dsy upierają, dla mnie 1wire jest najbardziej poronioną magistralą;/

    A nie lepiej jakiś liniowy czujnik analogowy?:/
  • #43
    dawid512
    Level 32  
    Może i jest poroniona Balu ale za to DS'a nie trzeba kalibrować.
  • #44
    snow
    Level 30  
    No i zaletą DS'a jest to że po wymianie egzemplarza nie trzeba kalibrować od nowa. Zresztą akurat w tym projekcie to taniej będzie dać termistor i sobie ułożyć równanie niż pchać się w DS'a bo za wiele nieliniowości w zakresie 15 stopni to on nie powinien wprowadzać. Gorzej jak się chce robić od -55 do +127:) jak to ma DS.
  • #45
    bdfhjk
    Level 11  
    Oto mój kod w wersji beta:

    Code:

    /***************************************************************************
     *   Copyright (C) 2008 by bdfhjk                                          *
     *   Version 0.6B                                                          *
     *                                                                         *
     *   This program is free software; you can redistribute it and/or modify  *
     *   it under the terms of the GNU General Public License as published by  *
     *   the Free Software Foundation; either version 2 of the License, or     *
     *   (at your option) any later version.                                   *
     *                                                                         *
     *   This program is distributed in the hope that it will be useful,       *
     *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
     *   GNU General Public License for more details.                          *
     *                                                                         *
     ***************************************************************************/




    #include <inttypes.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    /*
    #include <alloca.h>
    #include <assert.h>
    #include <ctype.h>
    #include <errno.h>
    #include <math.h>
    #include <setjmp.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <avr/boot.h>
    #include <avr/eeprom.h>
    #include <avr/fuse.h>
    #include <avr/sleep.h>
    #include <avr/lock.h>
    #include <avr/pgmspace.h>
    #include <avr/power.h>
    */

    #define sbi(port, bit) (port) |= (1 << (bit))
    #define cbi(port, bit) (port) &= ~(1 << (bit))

    //PC5 - tranzystor od DIS1 (lewy wyświetlacz)
    //PORTD - sterowanie wyświetlaczami
    //PB0 - tranzystor od DIS2 (prawy wyświetlacz)
    //PB1 - PB2 - diody kontrolne
    //PC1 - PC4 - przyciski
    //PC3, PC1, PC4, PC2

    //-------------------
    unsigned int L[10];
    unsigned int P[10];

    unsigned int lw;

    //uint16_t nap;


    //unsigned int buf;
    unsigned int tryb;
    unsigned int znak;
    unsigned int krok;
    unsigned int LDP, PDP;
    unsigned long int a, b, c, num; //moduł calc

    unsigned long int nap;



    void czekaj(int czas)
    {
       unsigned int i = 0;
       unsigned int j = 0;
       unsigned int k = 0;

          for(i =0; i < 255; i++)
          {
             for(j =0; j < 10; j++)
             {
                for(k = 0; k < czas; k++)
                {
                    asm("nop");
                }
             }
          }
    }

    void czekaj_m(unsigned int czas)
    {
       unsigned int i = 0;
       unsigned int j = 0;
       unsigned int k = 0;

          for(i =0; i < 10; i++)
          {
             for(j =0; j < 10; j++)
             {
                for(k = 0; k < czas; k++)
                {
                    asm("nop");
                }
             }
          }
    }

    void init (void)
    {
       sbi(DDRC, PC5);

       DDRD = 0xFF;

       sbi(DDRB, PB0);

       sbi(DDRB, PB1);
       sbi(DDRB, PB2);

    //---------------------------------

       sbi(PORTC, PC1);
       sbi(PORTC, PC2);
       sbi(PORTC, PC3);
       sbi(PORTC, PC4);

       cbi(PORTC, PC5);

       PORTD = 0xFF;

       cbi(PORTB, PB0);

       sbi(PORTB, PB1);
       sbi(PORTB, PB2);
       asm("nop");

    //----------------------------------

       L[0] = 0b10000001;
       L[1] = 0b11110011;
       L[2] = 0b01001001;
       L[3] = 0b01100001;
       L[4] = 0b00110011;
       L[5] = 0b00100101;
       L[6] = 0b00000101;
       L[7] = 0b11110001;
       L[8] = 0b00000001;
       L[9] = 0b00100001;

       P[0] = 0b00100100;
       P[1] = 0b01101111;
       P[2] = 0b00110010;
       P[3] = 0b00100011;
       P[4] = 0b01101001;
       P[5] = 0b10100001;
       P[6] = 0b10100000;
       P[7] = 0b00101111;
       P[8] = 0b00100000;
       P[9] = 0b00100001;

       lw = 0;

    //---------------------------

       cbi(TCCR0, CS02); //clkdiv64
       sbi(TCCR0, CS00);
       sbi(TCCR0, CS01);

       sbi(TIMSK, TOIE0);

    //---------------------------

       sbi(ADMUX, REFS0);
       sbi(ADCSRA, ADEN);
       sbi(ADCSRA, ADIE);
       sbi(ADCSRA, ADPS0); //dla 1Mhz
       sbi(ADCSRA, ADPS1);
       //sbi(ADCSRA, ADFR);



       lw = 99;
       num = 0;
       tryb = 0;
       znak = 0;
       LDP = 0;
       PDP = 0;
       
       czekaj_m(10);
       cbi(PORTB, PB2);
       cbi(PORTB, PB1);   
       sei();

    }


    void test (unsigned int czas)
    {   
       cbi(TIMSK, TOIE0);
       PORTD = 0xFF;

       cbi(PORTD, PD0);
       czekaj_m(czas);
       sbi(PORTD, PD0);
       cbi(PORTD, PD1);
       czekaj_m(czas);
       sbi(PORTD, PD1);
       cbi(PORTD, PD2);
       czekaj_m(czas);
       sbi(PORTD, PD2);
       cbi(PORTD, PD3);
       czekaj_m(czas);
       sbi(PORTD, PD3);
       cbi(PORTD, PD4);
       czekaj_m(czas);
       sbi(PORTD, PD4);
       cbi(PORTD, PD5);
       czekaj_m(czas);
       sbi(PORTD, PD5);
       cbi(PORTD, PD6);
       czekaj_m(czas);
       sbi(PORTD, PD6);
       cbi(PORTD, PD7);
       czekaj_m(czas);
       sbi(PORTD, PD7);

       sbi(TIMSK, TOIE0);

    }

    void test2 (unsigned int czas)
    {
       cbi(TIMSK, TOIE0);
       PORTD = 0xFF;


       unsigned int i = 0;
       
       sbi(PORTB, PB0);
       cbi(PORTC, PC5);

       for (i=0; i < 10; i++)
       {
          PORTD = L[i];
          czekaj_m(czas);
       }

       cbi(PORTB, PB0);
       sbi(PORTC, PC5);
       

       for (i=0; i < 10; i++)
       {
          PORTD = P[i];
          czekaj_m(czas);
       }
       sbi(TIMSK, TOIE0);
    }

    //--------odświeżanie wyświetlacza--------

    void odswiezL (void)
    {
       unsigned int c = lw / 10;
       PORTD = L[c];
       if (LDP == 1) cbi(PORTD, PD0);
       sbi(PORTB, PB0);
       cbi(PORTC, PC5);
    }

    void odswiezP (void)
    {
       unsigned int c = lw % 10;
       PORTD = P[c];
       if (PDP == 1) cbi(PORTD, PD5);
       cbi(PORTB, PB0);
       sbi(PORTC, PC5);
    }

    ISR(TIMER0_OVF_vect)
    {
          odswiezL();
          czekaj_m(1);
          odswiezP();
          czekaj_m(1);
    }

    //------------------------------------------

    ISR(ADC_vect)      //wczytanie pomiaru ADC do pamięci
    {
       nap = ADCW;
       //nap = ADCL;
       //buf = ADCH;
    }

    void wyswietl(unsigned int czas, unsigned long int liczba)
    {
       PDP = 0;
       lw = (unsigned int) (liczba / 100);
       czekaj_m(czas);
       PDP = 1;
       lw = (unsigned int) ( (liczba / 10) % 100);
       czekaj_m(czas);
       PDP = 1; LDP = 1;
       lw = (unsigned int) (liczba % 100);
       czekaj_m(czas);
       PDP = 0; LDP = 0;
    }

    void prezentuj(void)
    {
       sbi(ADCSRA, ADSC);
       czekaj_m(20);
       if (tryb == 1) wyswietl(50, nap); else lw = (nap % 100);
    }



    void migaj(unsigned int czas)
    {
       sbi(PORTB, PB2);
       czekaj_m(czas);
       cbi(PORTB, PB2);
       czekaj_m(czas);
       sbi(PORTB, PB2);
       czekaj_m(czas);
       cbi(PORTB, PB2);
       czekaj_m(czas);
    }

    void calc(void)
    {
       lw = num;
       if (znak == 1)
       {
          if (krok == 0) {a = num; migaj(1); czekaj(1); }
          if (krok == 1) {b = num; migaj(1); czekaj(1); }
          krok++;
          if (krok == 2) {c = (a + b); krok = 0; migaj(5); if (c >= 100) wyswietl(70, c); else {lw = c % 100; num = c % 100;}  }
          znak = 0;
       }
    }

    void zmien_tryb(void)
    {
       sbi(PORTB, PB2);

       while ( bit_is_clear(PINC, PC1) )
       {
          tryb++;
          if (tryb == 3) tryb = 0;
          lw = (tryb*10) + tryb;
           czekaj(1);
       }
       cbi(PORTB, PB2);
    }

    void debug(void)
    {
       if ( ( bit_is_clear(PINC, PC3) ) & ( bit_is_clear(PINC, PC1) ) )
       {
          lw = 88;
          czekaj(1);
          test(30);
          test2(30);
          unsigned int i = 0; while (i != 99) {i++; lw = i; czekaj_m(5);}
       }
    }


    //----------------------------------------------

    int main (void)
    {
       init();
       
       while (1)
       {
          if (tryb == 0) prezentuj();
          if (tryb == 1) prezentuj();
          if (tryb == 2) calc();
                
          if ( bit_is_clear(PINC, PC3) ) { debug(); znak = 1;}
          if ( bit_is_clear(PINC, PC1) ) { zmien_tryb(); }
          if ( bit_is_clear(PINC, PC4) ) { if (num < 99) num++; else num = 0; czekaj_m(5); }
          if ( bit_is_clear(PINC, PC2) ) { if (num > 0) num--; czekaj_m(5); }
       }
       while (1) { }
       while (1) { asm("nop"); }
       while (0) { }

       return(0);
    }


    Dodałem funkcje kalkulatora, a temperatura wyświetla się w dwóch trybach (1 - tylko 2 ostatnie cyfry, 2 - wszystkie 4 cyfry pomiaru ADC ). Wszystko działa dobrze, może ktoś ma pomysł na dalszy rozwój bo kod zajmuje jedynie 3.5KB. Wciąż myślę jak to skalibrować... nie wiem czy termistor się nie uszkodzi od wody?
  • #46
    snow
    Level 30  
    bdfhjk wrote:
    Wszystko działa dobrze, może ktoś ma pomysł na dalszy rozwój bo kod zajmuje jedynie 3.5KB.


    Napisz to w Bascomie :lol: :twisted:

    bdfhjk wrote:
    Wciąż myślę jak to skalibrować... nie wiem czy termistor się nie uszkodzi od wody?


    Nie powinien, tyle że ty chciałeś pokojowe temperatury mierzyć to nie wiem czy jest sens wrzucać do wrzątku i kalibrować. Jak mniej punktów przyjmiesz do opisania równaniem tym prostsze ono wyjdzie.
  • #47
    bdfhjk
    Level 11  
    Pracuję nad nową wersją oprogramowania. Kalibracja jakoś mi wyszła, a dodatkowo zaimplementowałem odejmowanie, mnożenie i dzielenie. Jak napisać potęgowanie liczby przez liczbę?
  • Helpful post
    #48
    maly_elektronik
    Level 23  
    W sprawie tych rezystorów do switch'y to nie musisz ale pamietaj ze jak ustawisz pin na wejście to musisz go podciągnąć do plusa albo przez rezystor albo programowo poprzez PORTx = 0xYY (y - numer pinu do którego podciągasz plus)
  • #49
    Klima
    Level 30  
    W ogólnym przypadku:
    exp(wykładnik * ln(podstawa))
  • #50
    bdfhjk
    Level 11  
    To z biblioteki math (AVR) ?
  • #51
    bdfhjk
    Level 11  
    Quote:

    exp(wykładnik * ln(podstawa))


    Co oznacza ln ? nie ma tego w math. Czym to zastąpić?
  • Helpful post
    #53
    snow
    Level 30  
    logarytm naturalny o podstawie "e", w math jest jako log(double __x);
  • #54
    bdfhjk
    Level 11  
    Czyli
    exp(wykładnik * log(podstawa)) ?
  • #55
    bdfhjk
    Level 11  
    Nie wiem czemu, ale ma taki błąd:

    Code:

    avr-gcc -mmcu=atmega8  Termometr.o    -o Termometr.elf
    c:/winavr-20080610/bin/../lib/gcc/avr/4.3.0/../../../../avr/lib/avr4\libc.a(floatsisf.o): In function `__floatunsisf':
    (.text.fplib+0x0): multiple definition of `__floatunsisf'
    c:/winavr-20080610/bin/../lib/gcc/avr/4.3.0/avr4\libgcc.a(_usi_to_sf.o):(.text+0x0): first defined here
    c:/winavr-20080610/bin/../lib/gcc/avr/4.3.0/../../../../avr/bin/ld.exe: region text is full (Termometr.elf section .text)
    c:/winavr-20080610/bin/../lib/gcc/avr/4.3.0/../../../../avr/bin/ld.exe: region text is full (Termometr.elf section .text)
    make: *** [Termometr.elf] Error 1
    Build failed with 2 errors and 0 warnings...


    jeżeli dodam linijkę if (tryb == 7) c = exp(b * log(a));
    a jeżeli dodam samo if (tryb == 7) c = log10(a);
    (lub if (tryb == 7) c = log(a);)

    Code:

    Loaded plugin STK500
    Loaded plugin AVR GCC
    Loaded partfile: C:\Program Files\Atmel\AVR Tools\PartDescriptionFiles\ATmega8.xml
    gcc plug-in: Error: Object file not found on expected location C:\Documents and Settings\bdfhjk\Pulpit\Termometr\default\Termometr.elf
    gcc plug-in: Error: Object file not found on expected location C:\Documents and Settings\bdfhjk\Pulpit\Termometr\default\Termometr.elf


    Sama instrukcja exp() działa poprawnie. Jak mam zaimplementować logarytm?
  • Helpful post
    #56
    Klima
    Level 30  
    "region text is full" - za duży rozmiar kodu wynikowego?

    A wracając do potęg - jakie konkretnie to są potęgi? Bo jak wykładnik jest całkowity, to sprawa jest znacznie prostsza, ale to chyba sam wiesz dobrze, prawda?
  • #57
    klops_mops
    Level 17  
    maly_elektronik wrote:
    W sprawie tych rezystorów do switch'y to nie musisz ale pamietaj ze jak ustawisz pin na wejście to musisz go podciągnąć do plusa albo przez rezystor albo programowo poprzez PORTx = 0xYY (y - numer pinu do którego podciągasz plus)


    Nie chcę zakładać nowego tematu więc napiszę tutaj:

    Otóż też mam parę switchy na porcie D, piny 1,2,3 są jako wejścia i im podaję stan niski (przez switcha) to muszę dodać jakiś rezystor na te piny łączący je z +5V ? Jeśli tak to jaki? 4.7 kOhm ?

    Pozdrawiam
  • #58
    bdfhjk
    Level 11  
    klops_mops wrote:

    Otóż też mam parę switchy na porcie D, piny 1,2,3 są jako wejścia i im podaję stan niski (przez switcha) to muszę dodać jakiś rezystor na te piny łączący je z +5V ? Jeśli tak to jaki? 4.7 kOhm ?

    Nie wiem, ale nie zaszkodzi nigdy...


    Co do mojego projektu :
    Po ostatecznym rozwiązaniu wszystkich problemów publikuje gotowy projekt, zwłaszcza z myślą o początkujących, żeby nie mieli takich problemów jak ja. Dziękuję wszystkim za pomoc w jego realizacji.
    Poniżej załącznik z pełną dokumentacją : schemat + PCB(ścieżki i montażowy) + kod źródłowy wersja 1.00 (łącznie ze wsadem .hex) + prowizoryczna instrukcja obsługi.
    Proszę o komentarze i pomysły co dodać w wersji 1.1 :-)