It’s an analog-to-digital signal, converted on cheap hardware, and it’s pretty much guaranteed to be noisy and +/- 10% off spec. It’ll be even noisier if the MCU is doing anything during the conversion. So, it’s safe to assume that you’ll need to scale the values and run a lowpass over them to get any reasonably-sane output.
As for LVP, I think you’re correct that you need to just turn it off until the other functions are working.
Also, it might be helpful to declare all your global variables as volatile. Since the source file isn’t used as a module by other files, declaring globals as static has no effect. Volatile, however, tells the compiler to assume the variable is being changed by other threads or interrupts, and should never be trusted or cached.
I see something else which could be causing issues too…
while(1) {
if (ADCSRA & (1 << ADIF)) {
...
}
// Start conversion for next time through
ADCSRA |= (1 << ADSC);
}
It looks like you’re re-starting the conversion again before it has a chance to finish. The re-start should probably be inside the if, not after it.
You could also just busy-wait on the result, since the code isn’t doing anything else at the time. For example, this is how I block until I get a voltage reading:
uint8_t get_voltage() {
// Start conversion
ADCSRA |= (1 << ADSC);
// Wait for completion
while (ADCSRA & (1 << ADSC));
// Return the raw value, caller can decide what to do with it
return ADCH;
}