[Solved] Can I set analogRead() for 8-bit resolution?

I’ve see how it works perfectly to use

ADMUX |= (1 << ADLAR);

to left align the ADC value, so I can read highest 8 bits from the ADCH register. But this is for use with only one analog-input pin. Instead, I need to read all 8 analog pins – so I’m still using analogRead().

The above line of code seems to have no effect on analogRead(), where I’m still getting only the two most significant bits with highByte(), separated from the rest of the bits in lowByte().

So what’s the best way to read the 8 most siginifcant bits in one byte, from all eight analog pins?

Yes. See: analogReadResolution() - Arduino Reference

johnwasser:
Yes. See: https://www.arduino.cc/en/Reference/AnalogReadResolution

Unfortunately that is for Due and Zero only.

If you look at wiring_analog.c at the source for analogRead you see this:

// set the analog reference (high two bits of ADMUX) and select the
	// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
	// to 0 (the default).
#if defined(ADMUX)
	ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif

So it is undoing your change and setting ADLAR back to 0.

To do what you want you may have to roll your own analogRead function.

OK guys, thanks for your valuable input.

Having read it, I’ve decided a simple divide-by-4 is probably the best way. I tried it and it works, returning a number between 0 and 255 for the byte receiving it.

Here’s a copy of the complete sketch. It’s in an Arduino Pro Mini, radioing back data on heart rate, skin conductance, temperature, etc.

The “max(1,” on each line is to prevent each from ever sending a “0” byte, because I’m using “0” to mean:
“Set complete. Begin a new line.”

#include <SPI.h>
#include <Mirf.h>
#include <MirfHardwareSpiDriver.h>

byte samps;
unsigned long mill = millis();
byte cnt = 1;

void setup()
{
  ADMUX |= (1 << ADLAR);
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"serv1");
  Mirf.setTADDR((byte *)"clie1");
  Mirf.payload = 10;
  Mirf.config();
}

void loop()
{
  byte bb [10];
  if (millis() > mill)
  {
    mill += 100;
    bb[0] = max(1,analogRead(A0)/4);
    bb[1] = max(1,analogRead(A1)/4);
    bb[2] = max(1,analogRead(A2)/4);
    bb[3] = max(1,analogRead(A3)/4);
    bb[4] = max(1,analogRead(A4)/4);
    bb[5] = max(1,analogRead(A5)/4);
    bb[6] = max(1,analogRead(A6)/4);
    bb[7] = max(1,analogRead(A7)/4);
    bb[8] = cnt;
    bb[9] = 0;
    cnt++;
    if (cnt == 0)
      cnt = 1;
    while (Mirf.isSending()) { };
    Mirf.send(bb);
  }
}

found this .iin my archive, should work on UNO

//
//    FILE: analogRead8.h
//  AUTHOR: Rob Tillaart
//    DATE: 2015-05-15
//
// PUPROSE: fast analogRead 8 bit 
//

#ifndef analogRead8_h
#define analogRead8_h

#define ANALOGREAD8_VERSION "0.0.1"

int analogReadP(uint8_t pin, uint8_t prescale=7)
{
    uint8_t ADCSRA_TMP = ADCSRA;
    prescale = constrain(prescale, 2, 7);
    ADCSRA = (ADCSRA | 0x07) & (0xF8 | prescale);
    int value = analogRead(pin);
    ADCSRA = ADCSRA_TMP;
    return value;
}

#endif
// --- END OF FILE ---

and this sketch

#define FASTADC 1

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define AREF_11V  28
#define AREF_GND  29


void setup()
{
  Serial.begin(115200) ;

  uint32_t start ;
  int i ;

  delay(100);
  Serial.print("ADCTEST: ") ;
  int x = analogRead(AREF_11V) ;
  Serial.println(x) ;
  Serial.println(1125300UL / x) ; // 1100 mV * 1023
  Serial.println() ;

  delay(100);
  Serial.print("ADCTEST: ") ;
  x = analogRead(AREF_11V) ;
  Serial.println(x) ;
  Serial.println(1125300UL / x) ;
  Serial.println() ;

  delay(100);

  Serial.print("ADCTEST: ") ;
  x = analogRead(AREF_GND) ;
  Serial.println(x) ;
  Serial.println() ;

  delay(100);

  Serial.print("ADCTEST: ") ;
  start = micros() ;
  for (i = 0 ; i < 1000 ; i++)
    analogRead(0) ;
  Serial.print(micros() - start) ;
  Serial.println(" usec (1000 calls)") ;

  delay(1000);

#if FASTADC
  int ADCSRA_tmp = ADCSRA;
  // set prescale to 2
  sbi(ADCSRA, ADPS2) ;
  sbi(ADCSRA, ADPS1) ;
  cbi(ADCSRA, ADPS0) ;
#endif

  Serial.print("ADCTEST: prescale 02: ") ;
  start = micros() ;
  for (i = 0 ; i < 1000 ; i++)
    analogRead(0) ;
  Serial.print(micros() - start) ;
  Serial.println(" usec (1000 calls)") ;

#if FASTADC
  // set prescale to 16
  sbi(ADCSRA, ADPS2) ;
  cbi(ADCSRA, ADPS1) ;
  cbi(ADCSRA, ADPS0) ;
#endif

  Serial.print("ADCTEST: prescale 16: ") ;
  start = micros() ;
  for (i = 0 ; i < 1000 ; i++)
    analogRead(0) ;
  Serial.print(micros() - start) ;
  Serial.println(" usec (1000 calls)") ;

#if FASTADC
  // set prescale to 64
  cbi(ADCSRA, ADPS2) ;
  cbi(ADCSRA, ADPS1) ;
  cbi(ADCSRA, ADPS0) ;
#endif

  Serial.print("ADCTEST: prescale 64: ") ;
  start = micros() ;
  for (i = 0 ; i < 1000 ; i++)
    analogRead(0) ;
  Serial.print(micros() - start) ;
  Serial.println(" usec (1000 calls)") ;

#if FASTADC
  // reset to normal again
  ADCSRA = ADCSRA_tmp;
#endif

  Serial.print("ADCTEST: ") ;
  start = micros() ;
  for (i = 0 ; i < 1000 ; i++)
    analogRead(0) ;
  Serial.print(micros() - start) ;
  Serial.println(" usec (1000 calls)") ;

  for (int i = 0; i < 8; i++) testADC(i);
}


void testADC(int n)
{
  ADCSRA = (ADCSRA | 7) & (0xF8 | n);
  Serial.print("ADCTEST: prescale ") ;
  Serial.print(n) ;
  Serial.print(": ") ;
  uint32_t sum = 0;
  uint32_t start = micros() ;
  for (int i = 0 ; i < 1000 ; i++)
    sum += analogRead(A0) ;
  Serial.print(micros() - start) ;
  Serial.println(" usec (1000 calls)") ;
  Serial.println(sum / 1000);
}


void loop()
{
}
bb[0] = max(1,analogRead(A0)/4);

Since 4 is a power of 2, this goes much faster with the equivalent bitshift:

bb[0] = max(1,analogRead(A0) >> 2);

Well thank you both for the additional code and ideas.

Although an interesting concept, the first idea probably isn't what I want, because it adds several more lines of code for the AVR to execute (including the call of two more functions, one being the original "analogRead()").

But I'm now using the second idea of replacing the line:

bb[0] = max(1,analogRead(pin)/4);

with the line:

bb[0] = max(1,analogRead(pin) >> 2);

because this change has the single effect of making my sketch run faster.

So now those 8 lines are:

    bb[0] = max(1,analogRead(A0) >> 2);
    bb[1] = max(1,analogRead(A1) >> 2);
    bb[2] = max(1,analogRead(A2) >> 2);
    bb[3] = max(1,analogRead(A3) >> 2);
    bb[4] = max(1,analogRead(A4) >> 2);
    bb[5] = max(1,analogRead(A5) >> 2);
    bb[6] = max(1,analogRead(A6) >> 2);
    bb[7] = max(1,analogRead(A7) >> 2);

Again, Thank you both!