tutorial question aka why do you do that?

I have a quick silly question. I was browsing the tutorials to try and get familiar with the arduino and i saw the following example:
"This function will read a sensor five times with analogRead() and calculate the average of five readings. It then scales the data to 8 bits (0-255), and inverts it, returning the inverted result.

int ReadSens_and_Condition(){
  int i;
  int sval = 0;

  for (i = 0; i < 5; i++){
    sval = sval + analogRead(0);    // sensor on analog pin 0

  sval = sval / 5;    // average
  sval = sval / 4;    // scale to 8 bits (0 - 255)
  sval = 255 - sval;  // invert output
  return sval;


my specific question is about this line:

sval = sval / 4; // scale to 8 bits (0 - 255)

why do we do this? isn’t the value already in 8 bit format? since an analogue sensor would report a value from 0 - 255 anyways right? so
taking the average of 5 values i.e. (255+255+255+255+255)/5 = 255 is the average…and binary 11111111 = decimal 255. So we are already an 8 bit value are we not?

or is it since the MCU has a 16-bit architecture that values read in from an analogue sensor are actually 16 bit values and we are scaling them down to 8 bits? but then shouldn’t we just divide by 2? as 16/2=8?

Im rather confused, could someone help me to understand please?

No. The A-D converter on the AVR returns a 10-bit value.

As westfw said the Analog to Digital convertor returns 10 bit results.

In order to convert the value from 10bit to 8bit it has to be scaled down. A 10bit value can hold a maximum of 1024 and an 8bit value can hold a maximum of 256.

In other words an 8bit value is a quarter of the size of a 10 bit value. So inorder to scale it down to being an 8bit value we have to divide by four. In otherwords we are mapping a value in the 0-1024 range to a value in the 0-256.

Thats the simple explanation.

There is another way of converting a 10 bit value to an 8 bit value, using bit shifting. You simply shift the 10bit value 2 bits to the right to make it into an 8bit value.

Shifting a value 1 bit to the right is the same as dividing by to, so shifting 2 bits to the right is the same as dividing by 4. So the code could also have been written as

sval = sval >> 4

The trick of shifting values to the right to divide by 2 and shifting to the right to mulitply by 2 is something assembly language programmers often use. But since we have the lovely abstraction of the Wiring language we don't have to worry about that.

I checked now in the playground and found this which explains the whole thing about bit shifting for math if you are interested in reading further:


Oh my thank you so much, i understand now. Wonderful!

Thanks for clearing this up you two.

sval = sval >> 4

Should be

sval = sval >> 2

And usually the avr-gcc compiler is smart enough to convert that into shifts, and not the Wiring lib, its a lib, not a pre-processor/pre-compiler/compiler thingie.

or is it since the MCU has a 16-bit architecture

Just to clarify, the ATmega328 has an 8-bit architecture. The A-D converter result is internally represented by two registers (ADCH and ADCL). ADCL is the low byte and ADCH is the high byte, unless you set the A-D converter to left-aligned mode, in which case you can get an 8-bit value directly from ADCH.

Luckily, the Ardunio libraries hide this complexity and let you work directly with the full 10-bit value. Point being simply that the ATmega328 is just a lowly 8-bit MCU. Even the ATmega2560 on the Arduino Mega is just a really big 8-bit microcontroller.