NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » ADC HELP!!!

December 29, 2010
by jasongillikin
jasongillikin's Avatar

I don't know where I went wrong.

basically I am trying to make a differential temp controller, but I can't get the ADC to read properly... I am alternating between MUX0 and MUX1 being on and storing the values as 8 bit (ADLAR=1)..

I tried running my motor on program by itself, and it makes an LED blink, so I know that part works...

does anyone know where I went wrong with the code?

// tempsensor.c
// for NerdKits with ATmega168
// mrobbins@mit.edu

#define F_CPU 14745600

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:
//

// PC0 -- temperature sensor analog input

//Motor Stuff
void motorOn(){
//Pin =PB5
//
DDRB|= (1<<DDB5);
PORTB|= (1<<PORTB5);
//DELAY 1 MINUTE (60000 MICROSECONDS)
delay_ms (1000);
PORTB & (1<<PORTB5);
delay_ms (1000);}
//COLLECTOR STUFF

void collectorAdcInit() {
//set ADC for external reference (5v) single ended...
//ADLAR =1 sets 8Bit read ADCH.
//MUX=0 means ADC0 pin is on
//MUX=1 means ADC1 pin is on
ADMUX= 0;
ADMUX= (1<<ADLAR)| (1<<MUX0);

// set ADC to be enable with a clock prescale of 1/128
// so the ADC clock runs @ 115.2kHz
ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)  | (1<<ADPS0);
ADCSRA |= (1<<ADSC);

}

uint8_t collectorAdc_Read() {
//read from ADC, waiting for conversion to finish , and wait
//for it to be cleared
while (ADCSRA & (1<<ADSC)) {
// do nothing (open Set) as long as  ADSC =1
}
uint8_t collectorResult=ADCH;

collectorResult=collectorResult*5000/256/10;

// sets ADSC to 1 to get next conversion started

ADCSRA |= (1<<ADSC);

return collectorResult;}
//
//
// Storage
//
//

void storageAdcInit() {
//set ADC for external reference (5v) single ended...
//ADLAR =1 sets 8Bit read ADCH.
//MUX=0 means ADC0 pin is on
//MUX=1 means ADC1 pin is on
ADMUX = 0;
ADMUX = (1<<ADLAR)|(1<<MUX1);

// set ADC to be enable with a clock prescale of 1/128
// so the ADC clock runs @ 115.2kHz
ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)  | (1<<ADPS0);
ADCSRA |= (1<<ADSC);

}

uint8_t storageAdc_Read() {
//read from ADC, waiting for conversion to finish , and wait
//for it to be cleared
while (ADCSRA & (1<<ADSC)) {
// do nothing (open Set) as long as  ADSC =1
}

uint8_t storageResult=ADCH;

storageResult=storageResult*5000/256/10;

// sets ADSC to 1 to get next conversion started

ADCSRA |= (1<<ADSC);

// RETURNS VALUES IN DEGREES... 5000MV/256STEPS/10MV PER DEG
return storageResult;}

int main() {

for(;;)
{
//
// INITIALIZE AND READ COLLECTOR AND STORAGE ADCs
   void collectorAdcInit();
   uint8_t collectorAdc_Read();
   void storageAdcInit();
   uint8_t storageAdc_Read();
//
// COMPARE TWO VALUES IN DEGREES
uint8_t collectorResult;
uint8_t storageResult;
uint8_t tempDiff;

tempDiff=collectorResult-storageResult;

if (tempDiff>5)
{
   // turn motor on and wait 1 minute
   void motorOn();}
}
}
December 30, 2010
by Ralphxyz
Ralphxyz's Avatar

Hi jasongillikin, I posted my multisensor code in this thread http://www.nerdkits.com/forum/thread/6/. There is also a good discussion about multi sensors there.

Hope this helps.

Ralph

December 30, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi jasongillikin,

I think you the way you are setting ADMUX isn't quite right. The 3 bits MUX2-0 are used to select between the 6 ADC inputs. You need to use the table on page 257 of the datasheet if you want to set it bit by bit. However you can quickly note that MUX2-0 for ADC0=0, and for ADC1 it equals one. So to select ADC0 just set ADMUX = 0, or ADMUX = 1 for the ADC0 pin. You probably need to OR something else in there to make sure your left adjusting is still right.

One other tip I I have for you is to make your init function such that you only need to call it once. The speed at which you need to read is probably slow enough that you can afford to set the mux channgel, start the conversion, and wait for it to finish inside your "read" function, the init function should really just be called once to set up the ADC as a whole.

Humberto

December 31, 2010
by jasongillikin
jasongillikin's Avatar

thanks for everyones help, I am confused on setting the ADC bitwise. I think its the 8 bit ADC thats throwing me off. I guess i just don't see the need to do 10 bit for this. am I using the ADLAR bit correctly? i mean if I set ADMUX=1 thats 00000001 and I really want 00100001 for 8 bit right?

I had another question about the LM34, over what temperature range does it follow Ohm's law. I know its 1 degree F per 10mV, but does that start @ 0 Degrees? and if so will a (-)10degree F result in (-)10 mV. how do ADC's react to (-) Voltage? do they have (-) registers

one more question, I noticed when I debugged that I had to declare variables in both my sub functions and in the main function. is this because I didn't declare them as universal variables? if so, is it better to declare all Vars as universal?

thanks again for all the help, I just started learning C by reading "C++ For Dummies" trying to make some sense of it all.

Jason

January 01, 2011
by Rick_S
Rick_S's Avatar

I think you're getting things a bit mixed up.

When you said: "I guess i just don't see the need to do 10 bit for this. "

You don't have a choice, the ADC is a 10 bit converter on these micro's. That simply means that the result of a read will be 10 bits long or from 0 to 1023 decimal. The converter is 8 channel which means you can read from 8 different inputs.

The ADMUX register does not control how many bits are returned, it is simply there to:

  1. Pick which ADC input you are using to get the reading from the A-D converter(4 MUX bits).
  2. Choose which source your reference voltage is(two reference selection bits).
  3. And set how the 10bit data is organized in the result (ADLAR bit).

The ATMega168 has 8 independant inputs for the ACD but can only read from them one at a time.

If you look at the tempsensor code, you will see in the adc_init() function, the ADMUX=0; line. Notice the two comment lines above. They tell you what that line does. If you look at the datasheet, you'll see that the ADMUX register is broken down like this

Bit7    Bit6    Bit5    Bit4    Bit3    Bit2    Bit1    Bit0
REFS1   REFS0   ADLAR    --     MUX3    MUX2    MUX1    MUX0

If you look at the tables below that in the datasheet, you'll see that if all those are zero as set in the tempsensor program then:

REFS1 and REFS2 both zero = AREF, Internal Vref turned off -- In other words, it uses the reference voltage at the AREF pin of the microcontroller for its reference and shuts off it's internal reference.

ADLAR = 0 is the default This places the upper two bits of the 10 bit result in register ADCH and the lower 8 bits in register ADCL This allows us to get our 10 bit result by simply adding the upper bits shifted 8 places to our lower bits as seen in the adc_read() function.

The lower 4 bits are the MUX0 thru MUX3 bits and the represent the port we are reading. With them set at 0, we are reading from ADC0.

The other register you see reference in the adc_init() function is ADCSRA or the ADC Control and Status Register A. You really don't have to worry a whole lot about that one for basic operation other than to know the way it is set in the adc_init() function is perfectly fine for normal operation and that setting bit 6 (ADSC) in this register will trigger a conversion.

I hope this helped some without totally overwhelming you :D

Rick

January 01, 2011
by Rick_S
Rick_S's Avatar

One other thing, The ADC on the micro will not accept negative voltage without bad things happening. But as wired, you don't have to worry about that. The LM34 as it is setup will only read from 5 deg F to 300 deg F. (from it's datasheet) That would be an output voltage of 50mv to 3000mv or .05 to 3V. While the LM34 is capable of reading temperatures below that, it has to be wired differently to swing to the negative side of things.

Rick

January 04, 2011
by jasongillikin
jasongillikin's Avatar

thanks for your help again Rick, I misread the datasheet and thought I saw "8 Bit ADC" and now I see its "8 channel ADC"

in regard Reference voltage, if both REFS1 and REFS0 are set to 0 then the reference voltage is 5V from VOC. and since the full scale deflection of the LM34 is 3V, you should never get a ADC reading more than 615 steps (3V/5V*1024 steps) correct?

if you needed better resolution would you put a voltage divider for 3V on the internal Reference giving you the ability to use all 1024 steps?

thanks again,

jason

January 04, 2011
by Ralphxyz
Ralphxyz's Avatar

I get 1024 steps. I think you are complicating a easy operation.

From the Specsheet:

23.5.2 ADC Voltage Reference

The reference voltage for the ADC (VREF) indicates the conversion range for the ADC. Single ended channels that exceed VREF will result in codes close to 0x3FF. VREF can be selected as either AVCC, internal 1.1V reference, or external AREF pin (Pin21).

If you followed the Nerdkit User Guide AREF is 5v (VCC). I really do not think you need to concern your self with REFS1 and REFS0, at least I do not see any benifit just to get the ADC working.

Just my 2 cents worth. maybe I am completely missing what you are trying to do.

Ralph

January 04, 2011
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi Jason,

If you really wanted a higher resolution temperature reading, you're correct that you could use a lower AREF voltage and that would make the volts/step number smaller. That would mean that each degree of temperature change would appear as more ADC steps, effectively giving you greater resolution. At most, this might give you "effectively" 1 more bit of resolution if you used a 2.5V reference, or "effectively" 2 more bits of resolution if you used a 1.25V reference, when compared to the normal 5V reference configuration.

I should also mention that what we recommend with sampling the temperature reading many times and averaging also produces more effective resolution. This is formally known as "oversampling and decimation". Basically, you can take thousands or tens of thousands of ADC measurements per second with your microcontroller, but for your end purpose (display on a screen, or control a device) you may only need 1 to 10 readings per second. By averaging over lots of ADC readings, and relying on the idea that the signal is noisy but that the noise is centered around the "true" value, you can get a result that has much more effective resolution than the ADC increment itself. Please see this paper from Atmel which describes this technique in a bit more detail. Because of how the statistical averages work out (and after making a bunch of assumptions about how the noise is distributed), you basically need to average 4 samples to get 1 extra bit of effective resolution, 16 samples for 2 bits, 64 samples for 3 bits, 256 samples for 4 bits, and so on.

Mike

January 04, 2011
by Ralphxyz
Ralphxyz's Avatar

And of course if accuracy is what you are looking for you need a more precise temperature sensor than the LM34 that comes with the Nerdkit.

Ralph

January 04, 2011
by mongo
mongo's Avatar

A little sensor I have been using for years is the AD590. It delivers 1uA per degree K. If you offset the -273.15 for zero, you have a very accurate input. I do it with a 250 ohm resistor between the negative terminal and ground. If you measure the voltage, it comes out to 1 mV per degree C. Connect the positive to about +8V to +12V.

If you have a reading of 273 mV across the resistor, then you are reading zero degrees C or 32 deg F.

January 18, 2011
by jasongillikin
jasongillikin's Avatar

So, the issue remains... I still have an unworking Differential controller. For a while I thought it was a ATMEGA... so i got a new one (and new LM34's) and it still isn't working.

if I run Mikes's multisensor program (http://www.nerdkits.com/forum/thread/6/)and put delay before the main() loop starts again, so I can read it. the numbers are comming out all messed up. and even the difference doesn't add up.

for instance (just two examples b/c I am running it right now): A=130, B=132, A-B= -20 A=133, B=132, A-B= 110

also when I remove either of the LM34's or change the ADMUX to an empty input, the thing still reads!

I have no idea what is going on makes no sense to me

here is the code I am running...

void adc_init() {
  // set analog to digital converter
  // for external reference (5v), single ended input ADC0
  ADMUX = 0;

  // set analog to digital converter
  // to be enabled, with a clock prescale of 1/128
  // so that the ADC clock runs at 115.2kHz.
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

  // fire a conversion just to get the ADC warmed up
  ADCSRA |= (1<<ADSC);
}

uint16_t adc_read() {
  // read from ADC, waiting for conversion to finish
  // (assumes someone else asked for a conversion.)
  // wait for it to be cleared
  while(ADCSRA & (1<<ADSC)) {
    // do nothing... just hold your breath.
  }
  // bit is cleared, so we have a result.

  // read from the ADCL/ADCH registers, and combine the result
  // Note: ADCL must be read first (datasheet pp. 259)
  uint16_t result = ADCL;
  uint16_t temp = ADCH;
  result = result + (temp<<8);

  // set ADSC bit to get the *next* conversion started
  ADCSRA |= (1<<ADSC);

  return result;
}

double sampleToFahrenheit(uint16_t sample) {
  // conversion ratio in DEGREES/STEP:
  // (5000 mV / 1024 steps) * (1 degree / 10mV)
  //    ^^^^^^^^^^^      ^^^^^^^^^^
  //     from ADC         from LM34
  return sample * (5000.0 / 1024.0 / 10.0);
}

int main() {
  // start up the LCD
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_home();

  // start up the Analog to Digital Converter
  adc_init();

  // start up the serial port
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

  // holder variables for temperature data
  uint16_t last_sample = 0;
  double this_temp;
  double temp_avg;
  uint8_t i;

/*
    while(1) {
    // take 100 samples and average them!
    temp_avg = 0.0;
    for(i=0; i<100; i++) {
      last_sample = adc_read();
      this_temp = sampleToFahrenheit(last_sample);

      // add this contribution to the average
      temp_avg = temp_avg + this_temp/100.0;
    }

 */

uint16_t sensor1, sensor2;
int16_t difference;
while(1) {
  // read sensor 0 (on pin PC0)
  ADMUX=0;
  sensor1 = adc_read();

  // read sensor 1 (on pin PC1)
  ADMUX=5;
  sensor2 = adc_read();

  difference = sensor1 - sensor2;
  lcd_home();
  fprintf_P(&lcd_stream, PSTR("A = %d, B = %d"), sensor1, sensor2);
  lcd_line_two();
  fprintf_P(&lcd_stream, PSTR("A-B = %d"), difference);
  delay_ms (10000);
  sensor1=0;
  sensor2=0;
}

  return 0;
}

HOWEVER......

I was just using that code to trouble shoot my setup.

my code I want to run is

//Motor Stuff void motorOn(){ //Pin =PB5 // DDRB|= (1<<DDB5); PORTB|= (1<<PB5); //DELAY 1 MINUTE (60000 MICROSECONDS)

    delay_ms (60000);
    PORTB &= (1<<PB5);
    delay_ms (500);}
    //COLLECTOR STUFF

    void collectorAdcInit() {
    //set ADC for external reference (5v) single ended...
    //ADMUX=0 means ADC0 pin is on
    //ADMUX=1 means ADC1 pin is on
    ADMUX=5;

    // set ADC to be enable with a clock prescale of 1/128
    // so the ADC clock runs @ 115.2kHz
    ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)  | (1<<ADPS0);
    ADCSRA |= (1<<ADSC);

    }

    uint16_t collectorAdc_Read() {
    //read from ADC,

    // read ADCL and ADCH Because we are using 10 Bit ADC
    // must shift ADCH to left 8 bit so it doesn't write over
    // ADCL.
    // Also, ADCL Must be read first (see pg 259 of datasheet)

     uint16_t collectorResult=ADCL;
    uint16_t collectorTemp=ADCH;
    collectorResult= (collectorResult+(collectorTemp<<8));

    collectorResult= collectorResult * (5000 / 1024 / 10);

    delay_ms (500);

    return collectorResult;}
    //
    //
    // Storage
    //
    //

    void storageAdcInit() {
    //set ADC for external reference (5v) single ended...
    ////ADMUX=0 means ADC0 pin is on
    //ADMUX=5 means ADC5 pin is on
    ADMUX =0;

    // set ADC to be enable with a clock prescale of 1/128
    // so the ADC clock runs @ 115.2kHz
    ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)  | (1<<ADPS0);
    ADCSRA |= (1<<ADSC);

    }

    uint16_t storageAdc_Read() {
    //read from ADC

    uint16_t storageResult=ADCL;
    uint16_t storageTemp=ADCH;
    storageResult= (storageResult+(storageTemp<<8));

    // RETURNS VALUES IN DEGREES... 5000MV/1024STEPS/10MV PER DEG

    storageResult= storageResult * (5000 / 1024 / 10);

    delay_ms (500);

    return storageResult;}

    int main() {

    for(;;)
    {
    //
    // INITIALIZE AND READ COLLECTOR AND STORAGE ADCs
    uint16_t collectorResult=0;
    uint16_t storageResult=0;

       collectorAdcInit();
        uint16_t collectorAdc_Read();
        storageAdcInit();
        uint16_t storageAdc_Read();

    //
    // COMPARE TWO VALUES IN DEGREES

    int16_t tempDiff;

    tempDiff=(collectorResult-storageResult);

      // turn motor on and wait 1 minute
        if (tempDiff>0)
         {motorOn();}
    }}

    When I run this program, I have an LED set up on PB5 so, when the motor is on the LED turns on for a minute, then turns off. That part work great (I know because I tested it as a stand alone program)

    However, when I run the program above, the light never turns on.  The only way I can get it to come on is to change

tempDiff=(collectorResult-storageResult); to tempDiff=(collectorResult-storageResult)+1;

which leads me to believe that tempDiff<0 all the time everytime. which is contradictory to the result from the troubleshooting code I mentioned first.

a solution to my code working would be great (that way I can learn what I did wrong)

January 18, 2011
by bretm
bretm's Avatar

A=130, B=132, A-B= -20 A=133, B=132, A-B= 110

It's probably working just fine. With A=130 and B=132 it's displaying -2. The "0" is left over from some previous info that you wrote out. When A=133 and B=132 it's displaying 1. The "10" is also left over from some previous output.

also when I remove either of the LM34's or change the ADMUX to an empty input, the thing still reads!

Probably not--it's just still showing whatever was left over from before.

Write some spaces after your numbers.

January 19, 2011
by jasongillikin
jasongillikin's Avatar

oh I also forgot to mention that when I apply heat to one of the sensors(doesn't matter which one) both of the numbers change.

As far as the values being left over from something else it should stay the same after I remove the sensors, but it keeps behaving just like it did when the sensors were in.

January 19, 2011
by bretm
bretm's Avatar

Both of those programs still have some problems.

Add the spaces after the display and see what's still broken.

In the first program, you're doing this:

ADMUX = 0;
sensor1 = adc_read();
ADMUX = 5;
sensor2 = adc_read();

This won't do what you expect. The adc_read function waits for the conversion to complete and then immediately starts another conversion. If you do this in a loop, what happens is that the first adc_read starts the next conversion using ADC0, so when that conversion is complete the ADC0 value gets stored in sensor2. Setting ADMUX=5 during the middle of the conversion doesn't change it. Then, the second time you call adc_read while ADMUX=5, adc_read starts a new conversion after sampling ADC5 (the current ADMUX) so sensor1 will get the result of that conversion the next time through the loop. You need to change adc_read to start the conversion at the start of the function and then wait for it to complete. Don't start a new conversion before returning.

The second program does the ADMUX stuff in the right order, but it has a different problem:

collectorResult = collectorResult * (5000 / 1024 / 10);

What is the value of (5000 / 1024 / 10)? Working from left to right we have 5000 / 1024 which is 4, and then we have 4 / 10 which is 0. So this is equivalent to

collectorResult= collectorResult * 0;

What you might want is

collectorResult = (collectorResult * 5000) / 1024 / 10;

but this won't work either. collectorResult is a uint16_t which means the range is 0 to 65535. If you multiply 1023 by 5000 you get 5115000 which overflows that by quite a bit. You should do this instead, which should cause it to use 32-bit math:

collectorResult = (collectorResult * 5000L) / 1024 / 10;

Another problem is this:

uint16_t collectorAdc_Read();

That doesn't actually call the function and store the result in collectorResult. It's actually not even a function call at all, it's a function declaration. I'm a little surprised it compiles. It should say

collectorResult = collectorAdc_Read();

The variable called "collectorResult" inside the collectorAdc_Read function is local to that function. It's unrelated to the other collectorResult variable you declared in main().

Same issue with storageResult and storageAdc_Read and storageResult * (5000 / 1024 / 10).

January 31, 2011
by jasongillikin
jasongillikin's Avatar

Okay, almost got it... I can see the light... just a few more bugs to iron out maybe you guys can help me...

Progress so far

1) got my motor (led light) to turn on (when heat applied via touching sensor) 2) got my motor to turn off... 3) got an accumulator to work to average readings

Existing problems I think are related to noise in the ADC... or some type of number overflow...

1) sometimes LED turns on without heat being applied to collector sensor 2) even after heat is removed from collector sensor motor comes on again (I figured it was residual heat, until I turned the motor On delay up to 1 minute... and it still happened) 3) when I apply heat to storage sensor it still makes motor come on... Not supposed to happen since tempDiff=(storageResult-collectorResult)... motor on if tempDiff>10 3)even with collector sensor removed... motor still comes on

solutions I have tried

1)adding 1 sec delay before each reading... 2)bumping up the number of readings in the accumulator average to 500 or even 1000. 3)changing uint_16's to int_16's

Glad for the breakthroughs, but still don't have a working product... as I mentioned before all hardware is new.

and here is my code...

void motorOn(){

//Pin =PB5
//
DDRB|= (1<<DDB5);
PORTB|= (1<<PB5);
//DELAY 1 MINUTE (60000 MICROSECONDS)
delay_ms (5000);
PORTB &= (0<<PB5);
delay_ms (1000);
}

//COLLECTOR STUFF

 void collectorAdcInit() {
//set ADC for external reference (5v) single ended...
//ADLAR =1 sets 8Bit read ADCH.
//MUX=0 means ADC0 pin is on
//MUX=1 means ADC1 pin is on
ADMUX=5;

// set ADC to be enable with a clock prescale of 1/128
// so the ADC clock runs @ 115.2kHz
ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)  | (1<<ADPS0);
ADCSRA |= (1<<ADSC);

}

uint16_t collectorAdc_Read() {
//read from ADC, waiting for conversion to finish , and wait
//for it to be cleared

int i=0;
uint16_t collectorResult=0;
uint16_t collectorTemp=0;
uint16_t accumulator=0;
// read ADCL and ADCH Because we are using 10 Bit ADC
// must shift ADCH to left 8 bit so it doesn't write over
// ADCL.
// Also, ADCL Must be read first (see pg 259 of datasheet)
for (i=0;i<100;i++)
{

collectorResult=ADCL;
collectorTemp=ADCH;
collectorResult= (collectorResult+(collectorTemp<<8));

accumulator=(accumulator+collectorResult);

}

collectorResult= accumulator/i;

collectorResult = (collectorResult* 5000L) / 1024 / 10;

//test//

return collectorResult;
}

//
//
// Storage
//
//

void storageAdcInit() {
//set ADC for external reference (5v) single ended...
//ADLAR =1 sets 8Bit read ADCH.
//MUX=0 means ADC0 pin is on
//MUX=1 means ADC1 pin is on
ADMUX =0;

// set ADC to be enable with a clock prescale of 1/128
// so the ADC clock runs @ 115.2kHz
ADCSRA|= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1)  | (1<<ADPS0);
ADCSRA |= (1<<ADSC);

}

uint16_t storageAdc_Read() {
//read from ADC, waiting for conversion to finish , and wait
//for it to be cleared

// read ADCL and ADCH Because we are using 10 Bit ADC
// must shift ADCH to left 8 bit so it doesn't write over
// ADCL.
// Also, ADCL Must be read first (see pg 259 of datasheet)
int i=0;
uint16_t storageResult=0;
uint16_t storageTemp=0;
uint16_t accumulator=0;
for(i=0;i<100;i++)
{
 storageResult=ADCL;
 storageTemp=ADCH;
storageResult= (storageResult+(storageTemp<<8));
accumulator= (storageResult+accumulator);

}

storageResult= (accumulator/i);
//farenheit conversion
storageResult= (storageResult * 5000L) / 1024 / 10;

// RETURNS VALUES IN DEGREES... 5000MV/1024STEPS/10MV PER DEG
return storageResult;}

int main() {

for(;;)
{
//
// INITIALIZE AND READ COLLECTOR AND STORAGE ADCs
uint16_t collectorResult=0;
uint16_t storageResult=0;

//collector reading

collectorAdcInit();
collectorResult= collectorAdc_Read();

//delay just to make sure no reading overlap

delay_ms (1000);

//storage reading
storageAdcInit();
storageResult= storageAdc_Read ();
//delay just to make sure no overlap

delay_ms (1000);
//
// COMPARE TWO VALUES IN DEGREES

int16_t tempDiff=0;

tempDiff=(collectorResult-storageResult);

  // turn motor on and wait 1 minute
    if (tempDiff>10){

     motorOn();

     }}}

Post a Reply

Please log in to post a reply.

Did you know that you can make a spooky Halloween Jack-O-Lantern with a microcontroller? Learn more...