3

I'm writing a simple application that reads voltage from analog input 0. Here is the code:

#define OUT 5
#define ADC 0

void setup() {
  ADMUX &= (0<<REFS0); //Setting reference voltage to internal 1.1V
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(0);
  float voltage = sensorValue * (1.1 / 1023.0);
  if (voltage>0.5) {
    digitalWrite(OUT,HIGH);
  } else {
    digitalWrite(OUT,LOW);
  }
}

When I apply 1 V on ADC0, the OUT pin is low. Seems like the reference voltage is not set properly. When I set VREF to VCC (5V), everything works fine.

I cannot find the mistake. Would appreciate any help:)

Edit:

Link to datasheet: http://www.atmel.com/images/doc8008.pdf

  • In your setup() function, why are you shifting a 0 and ANDing it? Also, providing a link to the datasheet (so we don't have to use The Google ourselves) is appreciated. – calcium3000 Jan 18 '17 at 20:13
  • Are you sure that you properly selected internal reference? IIRC, setting both REFS0 and REFS1 selects internal reference. So you need to replace that line with ADMUX |= (0xC0); – Rohat Kılıç Jan 18 '17 at 20:31
  • Sure, here's link to datasheet: atmel.com/images/doc8008.pdf – Em Ka Jan 19 '17 at 17:02
  • @Rohat Kılıç I believe there is no such thing as REFS1 in ATTINY 88 – Em Ka Jan 19 '17 at 17:37
1

The statement

ADMUX &= (0<<REFS0);

AND's the current value of ADMUX with zero, resulting in a zero value, and stores it into ADMUX.

To clear the REFS0 bit in ADMUX without affecting the rest of it, one generally would instead say

ADMUX &= ~(1<<REFS0);

which will AND its value with the complement of 1<<REFS0.

However, you should use the statement

analogReference(INTERNAL);

instead of setting ADMUX directly. One of the first statements executed in the analogRead() source code is

ADMUX = (analog_reference << 6) | (pin & 0x07);

which overrides reference selections made by just changing ADMUX.

Parameters INTERNAL and DEFAULT to analogReference() select either the 1.1 V internal bandgap reference or the default analog reference, Vcc.


Edit 1: If you replace ADMUX &= (0<<REFS0) with analogReference(INTERNAL) in setup and it still doesn't work, you will need to apply some more-powerful debugging aids. For example, check that you got the sketch to correctly compile and that you uploaded it ok. Check that AVCC is connected to Vcc, preferably through a low-pass filter, as noted in datasheet sections §1.1.2 and §17.9, “Analog Noise Canceling Techniques”. Then, try several voltage inputs to see at what level the LED comes on. If it doesn't ever come on, look for LED problems using a simple sketch like Blink. If it comes on consistently at some input voltage, work out what reference is being applied.


Edit 2: Apparently the source code of analogRead() is different for ATtiny parts vs others. The code that I see for it in ... /arduino/avr/cores/arduino/wiring_analog.c [your path may differ] is like the following (I've elided some comments and blank lines).

uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode) {
  analog_reference = mode;
}

int analogRead(uint8_t pin) {
  #if defined( CORE_ANALOG_FIRST )
    if ( pin >= CORE_ANALOG_FIRST ) pin -= CORE_ANALOG_FIRST; // allow for channel or pin numbers
  #endif
  ADC_SetVoltageReference( analog_reference );
  ADC_SetInputChannel( pin );
  ADC_StartConversion();
  while( ADC_ConversionInProgress() );
  return( ADC_GetDataRegister() );
}

Some ADC_... functions and constants are defined in ... avr/cores/tiny/core_adc.h; and which definition of ADC_SetVoltageReference() is used depends on conditional compilation. For a definitive check on how analogReference() is defined for your part, look for analogReference() within the assembly listing of your program. Obtain that listing as explained in several Arduino SE answers, for example in the “Making assembly listings” paragraph near the end of my answer to question #33033. Also, a forum.arduino.cc thread from late April 2016 has some discussion of reading ADC inputs on tinys; I don't know if it's relevant.

  • @EmKa, and does it work? – James Waldby - jwpat7 Jan 19 '17 at 17:25
  • OK, I put analogReference(INTERNAL) instead of ADMUX &= (0<<REFS0) in setup section, but still it doesn't work:( @jwpat7 – Em Ka Jan 19 '17 at 17:40
  • @EmKa, see edit 1. What test equipment do you have? DVM? Scope? Freq. meter? – James Waldby - jwpat7 Jan 19 '17 at 17:43
  • I have a scope. When I use VCC, it works, well more or less fine. But I want more detailed measure, that's why I want to use 1.1 internal reference voltage. @jwpat7 – Em Ka Jan 19 '17 at 17:48
  • When I use "analogReference(INTERNAL)" the output pin is always LOW. However with VCC (5V) it works more or less fine. There's a slight mistake, but it may be due to the fact, that I supply the uC from programmator, and it provides voltage under 5V. In calculations i use 5V @jwpat7 – Em Ka Jan 19 '17 at 17:54
0

In your setup section, you want to set or clear all relevant bits in admux.

  • Is it a question? – Em Ka Jan 19 '17 at 17:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.