"If" wrong interpreted when ADC=1023?
If ADMUX:ADLAR is set your code will crash &amp; burn when you left shift high &lt;&lt; 8, because you are shifting data into the sign bit of "high-promoted-to-int" = undefined behavior. Are you sure ADLAR is not set? You have commented it out. If ADLAR is not set, your code will probably work, by luck. 

You need to read up on implicit integer promotion. In this shift operation, the uint8_t variable high will get implicitly promoted to an int, which is a signed int16 (assuming int is 16 bit), which is not what you want or need.

Also, in order to write deterministic, portable programs, get rid of the int type, it should never be used in embedded systems programming. Use uint16_t instead. 

Also, (if ADLAR is not set) what makes you think bits 7 to 2 in ADCH contain jolly-good-data? The manual doesn't mention what reading those bits will give you.

To turn your code into production quality, change it in the following ways:

uint16_t adc_read (void)
{
    // Start the conversion
    ADCSRA |= 1 &lt;&lt; ADSC;

    // Wait for it to finish
    while (ADCSRA &amp; (1 &lt;&lt; ADSC))
        ; // semicolon on separate line to show that this was intentional


    uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
    uint8_t high = ADCH; // unlocks both

    const uint8_t ADCH_DATA_MASK = 0x03; // the two MSB of 10 bit ADC value
    high = high &amp; ADCH_DATA_MASK; // mask out data, discard junk

    return (uint16_t)high &lt;&lt; 8 | (uint16_t)low;
}


Your main() code needs to be adapted to support the above changes. In main(), you may have to convert the uint16_t to int16_t for your algorithm to work.