Loading ...
Sorry, an error occurred while loading the content.

atmega8L avr with temp sensor

Expand Messages
  • welkyb
    Hi, I am doing my first avr exp using a temp sensor LM35 to blink blue green or red led according to the temp of the room. * Connected the leds to PORT B of
    Message 1 of 2 , Jul 3, 2009
    • 0 Attachment

      Hi,

      I am doing my first avr exp using a temp sensor LM35 to blink blue green or red led according to the temp of the room.

      • Connected the leds to PORT B of atmega8L uC and temp sensor to ADC 3 input.
      • Using internal oscillator 1MHz as clk, internal reference voltage of 2.56 as reference voltage in FREE RUNING MODE.
      • ADLAR = 0 i.e. right adjusted. 
      • Connected a 0.1uF decoupling capacitor at VREF pin as per datasheet, ¡°Internal 2.56V Voltage Reference with external capacitor at AREF pin¡±.
      • Using prolight leds 1W (for good intensity), transistor in saturation with Ic around 10mA.

      According to what I hv understood with temp sensor 10.0 mV/¢ªC scale factor, output voltage of sensor is input voltage of ADC ¡¦...

                                                      ADC = ( Vin * 1024 / Vref )

      If room temp= 30¢ªC, Vin = 300mV = 0.3V, So ADC = (.3*1024/2.56)=120. So I hv divided the result by 4.

       

       

       

      Fig b.png

       

       

      Here is my code that I hv written in AVR Studio4

      #include<avr\io.h>

      #define F_CPU 1000000UL

      #include <util/delay.h>

      int main (void)

      {

        unsigned int TEMP;

        ADMUX= (1<<REFS1)| (1<<REFS0)| (1<<MUX1)| (1<<MUX0);

        ADCSRA= (1<< ADEN )| (1<<ADFR);

        DDRB|=0xFF;

        while(1)

        {

          TEMP=ADCL+ADCH*256;           // ADCH is read only to update ADC data register, otherwise no need

           TEMP=TEMP/4;

           if(TEMP<=20) 

           PORTB=1<<PB1;                          //BLUE

          else if(TEMP>20&&TEMP<=28)

          PORTB=1<<PB0;                           //GREEN

          else if(TEMP>28&&TEMP<=35)

          PORTB=1<<PB3;                           //RED

         else

          PORTB= ((1<<PB1)| (1<<PB0)| (1<<PB3));

        }

      }

       

      But I don¡¯t know what the problem is; uC only blinks the led which satisfies the minimum criteria for temp i.e. blue. Even if I multiply the final TEMP variable by 10000 and keep min temp criteria for blue led to blink as less than 2¢ªC, then also only blue led blinks. It seems the uC is taking no voltage as input.

      I hv checked that if I write (PORTB=1<<PB0), then green led blinks or (PORTB=1<<PB3), then red led blinks instead of (PORTB=1<<PB1)

       

      I have connected output pin of sensor directly to uC, is there a problem in it or do I need to use more decoupling capacitors somewhere in the circuit.

       

    • s.holder123@btinternet.com
      Hi, Just a couple of points, 1) When you first start the ADC, DO A DUMMY READ as the first conversion is unreliable. 2) In order to start the ADC in free
      Message 2 of 2 , Jul 5, 2009
      • 0 Attachment
        Hi,

        Just a couple of points,

        1) When you first start the ADC, DO A DUMMY READ as the first conversion is unreliable.

        2) In order to start the ADC in free running mode you have to set the ADSC bit in the ADSCRA reg.

        3) When a conversion is complete the ADIF flag will be set and the ADSC bit will be cleared, look for this then get the conversion
        result, this way you are controlling the read process, then reset the ADIF flag.

        4) Set the sampling speed by setting the prescaler bits, in general the longer the sample time the
        greater the accuracy.

        5) As temperature is unlikely to change very quickly try to do the conversion as part of other routines
        so that all the processor time is not just about conversions, although in this case you are just getting
        used to using the device so shouldn't be a problem.

        6) It is ALWAYS!! A GOOD IDEA TO MODULARISE YOUR CODE, even when you are learning, this way you can build
        on what you have learned and reuse your code fairly easily into more complex code structures.

        I have include a simple example of a way to do what you wanted although generally i would always advise against
        using free running mode as unless you control it in a structured way (ie Interrupt in a real time system) it is difficult to always get a meaningful
        value.

        Simple Code Example.

        /*! Function Prtotypes */

        void ADC_Init(void);

        uint16_t ADC_Sample(void);


        #include<avr\io.h>

        #define F_CPU 1000000UL

        #include <util/delay.h>

        int16_t main (void)

        {

        int16_t Temp;

        /*! Set the Output Port. */
        PORTB = 0x00;
        DDRB = 0xFF;

        /*! Initialise ADC Settings. */
        ADC_Init();

        while(1)
        {
        /* Get the Conversion */
        Temp = ADC_Sample();

        /* Condition the result as required here */

        if(Temp <= 20)
        {
        PORTB = _BV(_PB1); //BLUE
        }
        else if( (Temp > 20) && (Temp <= 28) )
        {
        PORTB = _BV(_PB0); //GREEN
        }
        else if( (Temp > 28) && (Temp <= 35))
        {
        PORTB = _BV(PB3); //RED
        }
        else
        {
        PORTB= ( _BV(PB1) | _BV(PB0) | _BV(PB3) );
        }

        /*! Do other Stuff Here. */

        }

        return 1;

        }

        /*! Set up the ADC. */
        void ADC_Init(void)
        {
        /* Set Reference & prescaler. */
        ADMUX = ( _BV(REFS1) | _BV(REFS0) | _BV(MUX1) _BV(MUX0) );


        /*! Set Max prescaler & Enable A/D Converter and clear int bit. */
        ADCSRA |= ( _BV(ADEN) | _BV(ADIF) | _BV(ADPS2) | _BV(ADPS1)| _BV(ADPS0) );

        /*! Dummy Read. */
        ADCSRA |= ( _BV(ADSC) );

        /*! Wait for Conversion */
        while(bit_is_set(ADCSRA, ADSC));


        return;
        }


        /*! Get the Sample. */
        uint16_t ADC_Sample(void)
        {
        uint16_t Result = 0;
        uint8_t Cnt = 0;

        /*! Sample 4 times and average the result. */
        for (Cnt = 0; Cnt < 4; Cnt++)
        {
        /*! Clear hardware "conversion complete" flag. */
        ADCSRA |= (_BV(ADIF));

        /*! Start conversion. */
        ADCSRA |= (_BV(ADSC));

        /*! Wait for Conversion to finish */
        while(bit_is_set(ADCSRA, ADSC));

        /*! Store Conversion */
        Result += ((ADCL) | ((ADCH)<<8));

        }
        /*! Divide Result by 4. */
        Result >>= 2;


        return Result;

        }

        Hope that helps

        Regards


        --- In booksbybibin@yahoogroups.com, "welkyb" <welkyb@...> wrote:
        >
        >
        > Hi,
        >
        > I am doing my first avr exp using a temp sensor LM35 to blink blue green
        > or red led according to the temp of the room.
        >
        > * Connected the leds to PORT B of atmega8L uC and temp sensor to ADC
        > 3 input.
        > * Using internal oscillator 1MHz as clk, internal reference voltage
        > of 2.56 as reference voltage in FREE RUNING MODE.
        > * ADLAR = 0 i.e. right adjusted.
        > * Connected a 0.1uF decoupling capacitor at VREF pin as per
        > datasheet, ¡°Internal 2.56V Voltage Reference with external capacitor
        > at AREF pin¡±.
        > * Using prolight leds 1W (for good intensity), transistor in
        > saturation with Ic around 10mA.
        >
        > According to what I hv understood with temp sensor 10.0 mV/¢ªC scale
        > factor, output voltage of sensor is input voltage of ADC ¡¦...
        >
        > ADC = ( Vin * 1024 /
        > Vref )
        >
        > If room temp= 30¢ªC, Vin = 300mV = 0.3V, So ADC = (.3*1024/2.56)=120.
        > So I hv divided the result by 4.
        >
        >
        >
        >
        >
        >
        >
        > Fig b.png
        >
        >
        >
        >
        >
        > Here is my code that I hv written in AVR Studio4
        >
        > #include<avr\io.h>
        >
        > #define F_CPU 1000000UL
        >
        > #include <util/delay.h>
        >
        > int main (void)
        >
        > {
        >
        > unsigned int TEMP;
        >
        > ADMUX= (1<<REFS1)| (1<<REFS0)| (1<<MUX1)| (1<<MUX0);
        >
        > ADCSRA= (1<<ADEN)| (1<<ADFR);
        >
        > DDRB|=0xFF;
        >
        > while(1)
        >
        > {
        >
        > TEMP=ADCL+ADCH*256; // ADCH is read only to update ADC
        > data register, otherwise no need
        >
        > TEMP=TEMP/4;
        >
        > if(TEMP<=20)
        >
        > PORTB=1<<PB1; //BLUE
        >
        > else if(TEMP>20&&TEMP<=28)
        >
        > PORTB=1<<PB0; //GREEN
        >
        > else if(TEMP>28&&TEMP<=35)
        >
        > PORTB=1<<PB3; //RED
        >
        > else
        >
        > PORTB= ((1<<PB1)| (1<<PB0)| (1<<PB3));
        >
        > }
        >
        > }
        >
        >
        >
        > But I don¡¯t know what the problem is; uC only blinks the led which
        > satisfies the minimum criteria for temp i.e. blue. Even if I multiply
        > the final TEMP variable by 10000 and keep min temp criteria for blue led
        > to blink as less than 2¢ªC, then also only blue led blinks. It seems
        > the uC is taking no voltage as input.
        >
        > I hv checked that if I write (PORTB=1<<PB0), then green led blinks or
        > (PORTB=1<<PB3), then red led blinks instead of (PORTB=1<<PB1)
        >
        >
        >
        > I have connected output pin of sensor directly to uC, is there a problem
        > in it or do I need to use more decoupling capacitors somewhere in the
        > circuit.
        >
      Your message has been successfully submitted and would be delivered to recipients shortly.