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.

Basic Electronics » acd with 2 inputs?

June 30, 2011
by nimaaj
nimaaj's Avatar

is it possible to use the analog to digital converter on the atmega chip to measure 2 signal voltages?

I imagine it may be possible to make one measurement in a few milliseconds and then switch the signal over using transistors(?) or flagged opamps(?) to be measured for another few milliseconds and then switch back again

is this possible? if so can anyone propose a scheme? thanx

June 30, 2011
by Rick_S
Rick_S's Avatar

The ATMega168 and 328 both have 6 ADC inputs on pins 23 thru 28. If you search the forum you'll find references to other projects that have done this. To do this, a small modification to the tempsensor project will get you up and running. To change channels to read, you'll need to change the ADMUX register. The datasheet will also give you some great info.

Rick

June 30, 2011
by Ralphxyz
Ralphxyz's Avatar

Hi nimaaj, like Rick said search the forum for Multi-Sensor you will see lots of discussions.

Ralph

July 01, 2011
by nimaaj
nimaaj's Avatar

Thank you very much. This made it much easier than I had anticipated.

now I have another problem. setting the admux to 0 and 1 the inputs work fine. but admux 2 and 3 do not return the expected values no matter what input is connected to the corresponding pins. Is there any specific treatments i need to do to use the third and fourth pins for input?

July 01, 2011
by nimaaj
nimaaj's Avatar

I should add that, when input three and four are shorted to the ground or vcc the correct output is displayed however when the signal such as the one that is applied to inputs 1 and 2 are connected to pin 3 or 4 the correct input is not displayed.

It is behaving as if pin 3 and 4 have an intrinsic voltage coming out through an internal resistor.. any help would be appreciated.

July 01, 2011
by Ralphxyz
Ralphxyz's Avatar

[quote] Is there any specific treatments i need to do to use the third and fourth pins for input? [/quote]

Short answer NO!

That is strange if you are literally switching input 1 or 2 with input 3 or 4 with out any difference in wiring or code (besides pointing to the correct pin).

Show us your code please.

In retrospect I have gotten similar behavior, but there was something "I was doing" unknowingly.

Ralph

July 03, 2011
by BobaMosfet
BobaMosfet's Avatar

Make sure you have the ADC pins configured as inputs. They all reference ADC Ref, don't change this, and whatever you measure must be on the same ground loop.

BM

July 03, 2011
by nimaaj
nimaaj's Avatar

thanks for the replies, I have attached the code. Also all inputs are relative to the same ground. I tested the circuit by applying the same analog input to the different input pins, but only the first 2 inputs return acceptable results.

#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/io_328p.h"

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

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;  
}

int main() {
  lcd_init();
  uint16_t last_sample = 0;
  double this_inp;
  double input1;
  double input2;
  double input3;
  uint16_t i;

    // start up the LCD
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);

  // 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;

  while(1) {
    // take 100 samples and average them!
    ADMUX=0;
    input1 = 0.0;
    for(i=0; i<1000; i++) {
      last_sample = adc_read();
      this_inp = last_sample;

      // add this contribution to the average
      input1 = input1 + this_inp/1000.0;
    }
    input1=(input1/10.24);

    ADMUX=1;
    input2 = 0.0;
    for(i=0; i<1000; i++) {
      last_sample = adc_read();
      this_inp = last_sample;

      // add this contribution to the average
      input2 = input2 + this_inp/1000.0;
    }

    input2 = (input2/10.24);

    ADMUX=2;
    input3 = 0.0;
    for(i=0; i<1000; i++) {
      last_sample = adc_read();
      this_inp = last_sample;

      // add this contribution to the average
      input3 = input3 + this_inp/1000.0;
    }

    input3 = (input3/10.24);

    lcd_home();

    fprintf_P(&lcd_stream, PSTR("input 1: %.2f"), input1);

    //PORTC &= ~(1<<PC3);
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("input 2: %.2f"), input2);

    lcd_line_three();
    fprintf_P(&lcd_stream, PSTR("input 3: %.2f"), input3);

    // write message to serial port
    //printf_P(PSTR("%.2f Percent \r\n"), input1);
    //delay_ms(50);
  }

  return 0;
}
July 03, 2011
by Ralphxyz
Ralphxyz's Avatar

Are you switching between the same sensor or using different sensors?

What do you get when you tie all pins to Grn at the same time?

What do you get when you tie all pins to Vcc (+) at the same time?

Ralph

July 03, 2011
by nimaaj
nimaaj's Avatar

I am using the same sensor for all pins.

I am getting 0 when all pins are grounded.

I get 100 when all pins are tied to Vcc+

July 04, 2011
by Ralphxyz
Ralphxyz's Avatar

Darn, ok, now what sensors are you using? Are you using the same type sensors on all of the pins?

I do not know why you age seeing 100 @ Vcc you should be seeing 1024 there must be a division in your code, that shouldn't matter any way.

Have you tried running my Multi-sensor code? That works for me.

Ralph

July 07, 2011
by Hexorg
Hexorg's Avatar

Ralph, he's doing a division by 10.24 to get a scale from 0 to 100 instead of 0-1023... Which makes me realize, nimaaj, you should divide by 10.23, because ADC will output 1023 maximum (1023 = 0b111111111111). But like Ralph said, that shouldn't affect the result dramatically. I don't see anything bad in the code, so check your wiring, something might be wrong there.

July 07, 2011
by bretm
bretm's Avatar

One minor problem, and probably not the main issue, is that you need to throw away the first sample you take after changing ADMUX because the previous reading started a new measurement with the prior ADMUX value. Or you could just change the sampling function so it doesn't do that.

The tempsensor code really needs a comment added to it to warn people that its not suitable for multi-channel ADC.

July 07, 2011
by nimaaj
nimaaj's Avatar

thanks for the responses. I will modify the code to get rid of the first reading. At this point I'm thinking that the adjacent pins on the board are connected by some resistance or through a short somehow, or possibly a damaged chip. But I have been occupied with another project for the past few days. I have ordered new chips from nerdkits and will be testing the circuit again after my other project is completed. If I manage to figure out the problem I will post it on the forums.

July 13, 2011
by nimaaj
nimaaj's Avatar

Ok so I got my new chip today. I tried the new chip and I'm still getting the same results That is if I set 3 pins for input : 1) when left floating they read 3% to 4% of 5 Volts 2)when one of the pins is connected to +VS, that pin reads 100% of 5 Volts and the other 2 pins read 30% to 40% of 5 Volts!! 3) when a voltage somewhere between 0 and 5 Volts is connected to one of the adc inputs it will give the correct reading but it will also effect the other 2 unconnected adc pin readings!!

At this point I'm thinking I should put high resistances between adc pins and ground to act as a pull down resistor for the floating pins... Or if anyone else has any ideas or suggestions I'd be very grateful

July 13, 2011
by nimaaj
nimaaj's Avatar

new finding:

Ok I was using a program I made to plot the adc readings as a time graph on my laptop and it seems that the pins charge and discharge like capacitors. I've attached a picture of the graph:

alt image text The yellow is adc 1 and the red is adc 2. The jump in voltage is when i short the one of the adcs to +VS

July 13, 2011
by BobaMosfet
BobaMosfet's Avatar

nimaaj-

I hate to see you flounder. First of all, yes- you are experiencing capacitive effects- that is what you would expect. It virtually univeral in electrical engineering that you tie your inputs hi or low to eliminate this problem. Outputs are less bothersome.

As for ADC resolution, that is 1024, not 1023, as some have suggested. Zero to 1023 is, in fact, 1024 discrete values.

BM

July 14, 2011
by Ralphxyz
Ralphxyz's Avatar

And since the other pns are "floating" what do you care what they might read?

If you want to read them as ADC input then you have to have an ADC source (0 - 5v) they can not be left floating.

Ralph

Post a Reply

Please log in to post a reply.

Did you know that SPDT stands for "Single Pole, Double Throw"? Learn more...