1

I am trying to read a analogue voltage using the ADC in attiny85. But the ADC register always read 1023 irrespective of what input is given.

Moreover when the ADC pin is measured with a multimeter it shows nearly 3.1V. I aasumed that it is pulled up but the fact is, when i connect the pin to its analog input , the voltage at the pin disturbs the input voltage circuit. I dont know why this happens. the same code worked well before 6 months but now it is not. reason unknown. could anyone explain me what I'm actually doing wrong? I am using USBasp as my programmer and attiny85 as my target microcontroller, arduino as my compiler. Also i tried compiling using WinAVR but still the analogue input pin is at a voltage near 3.1V. thanks in advance:)

#define F_CPU 16000000UL
#define myTx PB1 //PB1
#define myRx PB0 //PB0
#define ADC_CH_2 PB4
#define ADC_CH_3 PB3

#include <SoftwareSerial.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
float ADCval;
int i = 0, p;

SoftwareSerial myPort(myRx, myTx); //rx,tx

ISR(ADC_vect) {

  p = ADCW;
  ADCval = (float)p * 5.00f / 1024.0f;


  //logging the data
  myPort.print(i++);
  myPort.print(" ADC: ");
  myPort.print(p);

  myPort.print(" voltage: ");
  myPort.println(ADCval);

}

int main(void) {
myPort.begin(9600);
MCUCR &= ~(1 << PUD); //disabling Pull Up Disable i.e, enabling pullups

//I/O configuration
DDRB &= ~(1 << ADC_CH_2) & ~(1 << ADC_CH_3); //configuring as input
PORTB |= (1 << ADC_CH_2) | (1 << ADC_CH_3); //  writing 1 to an input pin activates pullup-resistor
DIDR0 |= (1 << ADC_CH_2) | (1 << ADC_CH_3); // disable digital buffer
myPort.print("DDRB: ");
myPort.println(DDRB);

myPort.print("PORTB: ");
myPort.println(PORTB);

//ADC configuration

ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADIE); //enable conversion complete interrupt
ADCSRA |= (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2); // prescaler 128 - 16000000/128=125khz;
myPort.print("ADCSRA: ");
myPort.println(ADCSRA);

ADMUX &= ~(1 << ADLAR); // right most shift in ADCH and ADCL i.e, ADCH has two MSB bits and ADCL has 8 LSB bits



ADMUX |= (1 << REFS1) | (1 << REFS2); ADMUX &= ~(1 << REFS0); //Vref as 2.56V
ADMUX |= (1 << MUX1) | (1 << MUX0) ; ADMUX &= ~(1 << MUX2) & ~(1 << MUX3); //adc3

sei(); // enable all interrupts
myPort.print("ADMUX: ");
myPort.println(ADMUX);

while (1)
{
_delay_ms(1000);
ADCSRA |= 1 << ADSC;
myPort.print("DDRB: ");
myPort.println(DDRB);
myPort.print("ADMUX: ");
myPort.println(ADMUX);
myPort.print("ADCSRA: ");
myPort.println(ADCSRA);
myPort.print("PORTB: ");
myPort.println(PORTB);

}




return 0;
}

Update

the following image describes my output of different ADC channels for the same input voltage.

output of ADC channel 2

output of ADC channel 3

It'sDK
  • 23
  • 7
  • I'm investigating that code but I've to ask, thats ok? ADMUX &= ~(1 << MUX2) & ~(1 << MUX3); Instead of ADMUX &= ~(1 << MUX2) | ~(1 << MUX3); And there I'm sure you wanted to do DDRB &= ~(1 << ADC_CH_2) | ~(1 << ADC_CH_3); Does temp is an address to ADMUX? – dunajski May 11 '19 at 08:31
  • 3
    Floating point operations and serial data logging in an ISR is ill-advised at best. – Clifford May 11 '19 at 09:04
  • @dunajski actually the variable temp is ADMUX. while entering the code here i forgot to change it. – It'sDK May 11 '19 at 09:26
  • There is a law, when you ask about few things someone answer just on one question :-). How about the rest of problems I asked about and then I think you should edit your post to make him more 'attractive' to answer without those bugs. – dunajski May 11 '19 at 09:29
  • my apologies @dunajski, i will edit it and repost it. thank you for correcting me. – It'sDK May 11 '19 at 09:36
  • Using floating point on a AVR in the first place, is just plain wrong. We're talking about one of the slowest computers still manufactured, 30 years old technology. It is not a PC. It does not have a FPU. – Lundin May 13 '19 at 08:44
  • Anyway, this might as well be a hardware problem, making this borderline off-topic. Questions like these are better asked at https://electronics.stackexchange.com/ but if so, provide schematics and trouble-shooting steps. – Lundin May 13 '19 at 08:46
  • Btw the code setting ADMUX seems mighty fishy. I don't know this MCU, so correct me if I'm wrong, but it seems that you first set ref to internal 2.56V then changes it to "reserved", which is some forbidden register value. You then select channel ADC3 and then immediately change it to something else. – Lundin May 13 '19 at 09:17
  • Sorry, I could not understand what do you mean by the term "reserved" and I dint change my ADC reference once set. Also i dint change my ADC channel too. It is shown in my code also . And can you explain me what makes you to came to this conclusion plz. Might be it will get me to the solution. – It'sDK May 13 '19 at 11:29
  • For example `ADMUX |= (1 << REFS1) | (1 << REFS2); ADMUX &= ~(1 << REFS0);` This writes to the register twice. Which is one reason why it's awful style to write several statements on a single line. – Lundin May 13 '19 at 13:48
  • I provided several statements in single line to help me write comments side by side fro better readability. But according to my understanding, it does not change the behavior of the ADC. suggestions plz, if am wrong. – It'sDK May 13 '19 at 16:42

1 Answers1

3

When the ADC configured with 2.56V as a reference voltage then all voltages at level 2.56 and above will be read as ADC's maximum value, i.e. 1023. The same goes for 3.1 V.

Probably the issue is in the enabled internal pull-up:

PORTB |= (1 << ADC_CH_2) | (1 << ADC_CH_3); //  writing 1 to an input pin activates pullup-resistor

Enabled pull-up will source additional current and change the voltage at the input. You should never use internal pull-ups with ADC since the pull-up's value is different from part to part in range 20k...50k, and it is hard to predict exact value.

You should disable it:

PORTB &= ~(1 << ADC_CH_2) & ~(1 << ADC_CH_3); //  disable pull-ups

Use external pull-up of the known value, if needed.

AterLux
  • 4,566
  • 2
  • 10
  • 13
  • pullups disabled. but still left with the same issue. – It'sDK May 11 '19 at 13:28
  • But it does not change my answer: 3.1V > 2.56V, you will have ADC value 1023. Either check your schematics or use another reference voltage (e.g. Aref or AVCC) in `REFS1:0` bits of `ADMUX` register – AterLux May 11 '19 at 18:09
  • Thanks a lot @AterLux, the solution that you suggested to disable pullups works for other adc pins. but adc3 still reads 1023 even after disabling pullups. what might be the reason for it?? – It'sDK May 11 '19 at 21:39
  • i applied a test input of 421mV using a resistive potential divider and verified it using a multimeter. The ADC reads correct value in adc2, adc1. but adc3 reads 1023. – It'sDK May 11 '19 at 21:48
  • I got the solution. When I replaced the part (mcu) with another attiny85, everything is working as expected. Thanks you all for this discussion – It'sDK May 14 '19 at 17:33