lgt8fx icon indicating copy to clipboard operation
lgt8fx copied to clipboard

Wrong analogReadResolution on boot

Open jayzakk opened this issue 3 years ago • 14 comments

As https://www.arduino.cc/en/Reference.AnalogReadResolution states

It defaults to 10 bits (returns values between 0-1023) for backward compatibility with AVR based boards.

This doesn't seem to be true - at LGT8F. I got values up to 4096, which made my "regular" code not working.

I guess we should change this behaviour.

jayzakk avatar Aug 12 '20 16:08 jayzakk

I can confirm, 12 bit seems to be default. I only see 4064 as max value though, not 4096.

seisfeld avatar Aug 21 '20 08:08 seisfeld

4096 would be impossible in 12 bits, but 4095 should be the highest value ^^

I'd like to change the default in wiring_analog.c

Old:

uint8_t analog_resbit = 0;
uint8_t analog_resdir = 0;

Corrected:

uint8_t analog_resbit = 2;
uint8_t analog_resdir = 1;

Any comments on this?

jayzakk avatar Aug 21 '20 09:08 jayzakk

Well, 12bit being 4096 (including 0) of course, but that is not what I observe. The highest value I measure is 4064.

seisfeld avatar Aug 21 '20 09:08 seisfeld

I'm willing to take a PR to start with 10 bits by default :)

dbuezas avatar Sep 20 '20 14:09 dbuezas

Ok, will PR it (was thinking I already did so LOL)

jayzakk avatar Sep 20 '20 19:09 jayzakk

If in wiring_analog.c at line 30 default variables will be set like below, the analogRead() default resolution could be 10 bit.

uint8_t analog_resbit = 2;
uint8_t analog_resdir = 1;

Ohh sorry. Jayzakk commented it before me.

LaZsolt avatar Oct 23 '20 14:10 LaZsolt

@seisfeld The gain error correction is the reason of the maximum ADC value is 4064.

// gain-error correction
#if defined(__LGT8FX8E__)
	pVal -= (pVal >> 5);
#elif defined(__LGT8FX8P__)
	pVal -= (pVal >> 7);
#endif

It is not mentioned by LGT8Fx databook. What is it for this correction?

LaZsolt avatar Oct 23 '20 15:10 LaZsolt

Good catch @LaZsolt !

seisfeld avatar Oct 23 '20 15:10 seisfeld

Here is a demonstration program of the ADC gain error. I think the ADC gain error should be mentioned in readme.

void setup() {
  Serial.begin(38400);
  
  analogReference(INTERNAL2V048);
  analogReadResolution(12);
  pinMode(DAC0, ANALOG);

  
//------------------------------------------------------
  uint16_t value;

  Serial.print(F("If ADMUX set AGND then ADC output: "));
  value = analogRead(AGND);
  Serial.print(value);  
  Serial.println( (value == 0) ? F("") : F("    ( Must be 0, is'n it? ADC not linear around zero valtage.)"));

  bitSet(ADMUX,4);      // ADMUX switch to DAC output
  printvalueatDAC(0);
  printvalueatDAC(1);
  printvalueatDAC(2);
  printvalueatDAC(3);
  printvalueatDAC(4);
  printvalueatDAC(250);
  printvalueatDAC(251);
  printvalueatDAC(252);
  printvalueatDAC(253);
  printvalueatDAC(254);
  printvalueatDAC(255);
  Serial.println();
  Serial.println(F("The maximum ADC value should be at the maximum DAC output value, but not. The reason is the gain error."));
  Serial.println();
  Serial.println(F("End test."));
  Serial.println();
}// end setup  

void printvalueatDAC(uint8_t x){
  delay(100);
  analogWrite(DAC0, x);
  Serial.print(F("If  DAC  ==  "));
  if (x < 10 ) Serial.print(F(" "));
  if (x < 100) Serial.print(F(" "));
  Serial.print(DALR);
  Serial.print(F("  then ADC output: "));
  Serial.println(directADCread());
}

static uint16_t adcReadNow()
{
  // start the conversion
  bitSet(ADCSRA, ADSC);

  // ADSC is cleared when the conversion finishes
  while (bit_is_set(ADCSRA, ADSC));

  return ADC;
}

int directADCread(){
  uint16_t pVal;
  uint16_t nVal;

#if defined(ADCSRA) && defined(ADCL)
  #if defined(__LGT8FX8P__)
  bitSet(ADCSRC, SPN);
  nVal = adcReadNow();
  bitClear(ADCSRC, SPN);
  #endif
  
  pVal = adcReadNow();

  #if defined(__LGT8FX8P__)
  pVal = (pVal + nVal) >> 1;
  #endif
#else
  // we dont have an ADC, return 0
  pVal = 0;
#endif

  // gain-error correction
#if defined(__LGT8FX8E__)
  pVal -= (pVal >> 5);
#elif defined(__LGT8FX8P__)
  pVal -= (pVal >> 7);
#endif

  return pVal;
}// end directADCread


void loop() {
}

LaZsolt avatar Oct 24 '20 11:10 LaZsolt

@LaZsolt I have a question regarding this gain correction thing. I'm using 2.048V as reference and set the ADC to 12bit. When I want to calculate expected ADC values like:

Resolution of the ADC

What do i use as ADC resolution in that formula? 4096 or 4064?

seisfeld avatar Jan 26 '21 10:01 seisfeld

The resolution is 4064. Slightly bigger gain decrease the resolution. But replace "System Voltage" to "Reference Voltage". Voltage Measured = Reference / Resolution * ADC Reading

LaZsolt avatar Jan 26 '21 13:01 LaZsolt

Thanks. Will take 4064 in all calculations and verify with multimeter. You're right about the ref voltage of course. (The formula image is not mine, I grabbed it off the web just for illustration.)

seisfeld avatar Jan 26 '21 13:01 seisfeld

@seisfeld

Thanks. Will take 4064 in all calculations and verify with multimeter. You're right about the ref voltage of course. (The formula image is not mine, I grabbed it off the web just for illustration.)

As I writed above "Slightly bigger gain decrease the resolution" is true, but in calculations must use 4096. If the gain error wasn't so big then the ADC value reach the maximum when the input reach the reference voltage. But becase of error the ADC value reach the maximum before the input reach the reference voltage. So the ADC value decreased by gain correction for the good calculation. I hope it is understandable.

4096         Reference Voltage
----   =   ---------------------
4063       Max Voltage Mesasured

LaZsolt avatar Apr 02 '21 12:04 LaZsolt

@jayzakk and @dbuezas: Help wanted? Here it is.

For the backward compatibility of the default analogReadResolution I merged this maintenance with my last Pull request. https://github.com/dbuezas/lgt8fx/pull/130

LaZsolt avatar Apr 02 '21 13:04 LaZsolt

Is this issue also closed by #130 ?

dwillmore avatar Jan 12 '23 19:01 dwillmore

Yes.

dbuezas avatar Jan 12 '23 20:01 dbuezas