12 bits ADC rawdata range question

Hello,

I'm new on this .

I bought a 12 bits ADC I2C. I connected it expected to get raw data from 0 4095 (or so).
In practice I get raw data from about 17 to 3317 or such. I have no idea why ?
I tried different Wire.read methods and different potentiometer and sensors..

any hint ?

ADC:

http://wiki.seeed.cc/Grove-I2C_ADC/

What is the value of V_REF? What voltage do you read on the input (Vin)pin when you read 3317? Please post your entire sketch.

the documentation of the ADC encoder says the internal encoder reference is 3.00V

my 12 bits absolute rotary encoder sends data voltage from 0 to 5 v.

12 bits sensor: https://dis-sensors.com/en/products/rotary-encoders/qr30n-360hb-vk/

Thus to answer your question for 360 degree position (the last position before the encoder drops to 0V) i get 3301 and 4.84 volts.

//include the library
#include <eRCaGuy_NewAnalogRead.h>
#include <Wire.h>
#include "rgb_lcd.h"

rgb_lcd lcd;
 int getdata;
const int colorR = 255;
const int colorG = 100;
const int colorB = 00;

 
#define ADDR_ADC121             0x50
 
#define V_REF 3.00
 
#define REG_ADDR_RESULT         0x00
#define REG_ADDR_ALERT          0x01
#define REG_ADDR_CONFIG         0x02
#define REG_ADDR_LIMITL         0x03
#define REG_ADDR_LIMITH         0x04
#define REG_ADDR_HYST           0x05
#define REG_ADDR_CONVL          0x06
#define REG_ADDR_CONVH          0x07
 
unsigned int getData;
float analogVal=0;         // convert
void init_adc()
{
  Wire.beginTransmission(ADDR_ADC121);        // transmit to device
  Wire.write(REG_ADDR_CONFIG);                // Configuration Register
  Wire.write(0x20);
  Wire.endTransmission();  
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setRGB(colorR, colorG, colorB);
  // Print a message to the LCD.
  lcd.print("ProtoV0.1 He55e");
}
 
void read_adc()     //unsigned int *data
{

// unasigned int data[2];
 
    Wire.beginTransmission(ADDR_ADC121);        // transmit to device
    Wire.write(REG_ADDR_RESULT);                // get result
    Wire.endTransmission();
 
    Wire.requestFrom(ADDR_ADC121, 2);           // request 2byte from device
    delay(1);
    if(Wire.available()<=2)
    {
      getData = (Wire.read()&0x0f)<<8;
      getData |= Wire.read();
    }
      
    Serial.print("getData:");
    Serial.println(getData);
    delay(5);
    Serial.print("The analog value is:");
    Serial.print(getData*V_REF*2/4096); 
    Serial.println("V");
    Serial.print("The angle is");
    //Serial.print(analogRead(getData)); 
    Serial.println("°");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("analog: ");
    lcd.setCursor(9, 0);
    lcd.print(getData);
    lcd.setCursor(0, 1);
    lcd.print("volt :");
    lcd.setCursor(9, 1);
    lcd.print(getData*V_REF*2/4096);
}
void setup()
{
  Serial.begin(9600);
  Wire.begin();
  init_adc();
}
 
void loop()
{  read_adc();//adcRead);
   delay(300);
}

he55e:
the documentation of the ADC encoder says the internal encoder reference is 3.00V

my 12 bits absolute rotary encoder sends data voltage from 0 to 5 v.

I guess either the ADC is using your 5v rail as reference and the 5v from the encoder is actually slightly less or you are dividing the 5v signal to 3v with some tolerance.

What ADC are you using ?
How are you presenting the rotary encoder signal ?

Yours,
TonyWilk

@he55e use code tags please ....

Based on your posts, you’re using a breakout board with the ADC121C021 ADC, to read the QR30N-360HB-VK encoder.
(this is how to present your hardware)

The datasheet of the ADC does not mention a 3V internal reference, instead it explicitly states that it takes an external reference voltage, called VA. It also states that the input voltage may not be more than VA + 0.3V (absolute maximum rating). That 0.3V is probably due to a clamping diode.

Your breakout board itself has a fixed 3V reference built in - at least that’s what the product page of Seeed tells you. This also means your input voltage should never be more than 3.3V.

Now your encoder’s description mentions a total range of 0-5V, which is too much for your ADC. When you go over this 3.3V you may damage the chip. So the proper way to connect this encoder to this ADC is by using a voltage divider that brings it down to 3V. A 10k + 15k divider would do so (but with 5% tolerance parts you may end up with a too high voltage at the high end).

Wow ! This is a fantastic answer ! :o :smiley: I have to confess I did not expect it.

I apologize for the poor form of my request and will improve that in my future questions.

Being french speaking, I'm not entirely sure I understand the term "breakout" in this context.

I'm now working on fully understand your answer. As you pointed out, according to the ADC121C021 ADC

Operating Ratings(1) (2)
Operating Temperature Range −40°C ≤ TA ≤ +105°C
Supply Voltage, VA +2.7V to 5.5V
Analog Input Voltage, VIN 0V to VA
Digital Input Voltage(3) 0V to 5.5V
Sample Rate up to 188.9 ksps
(3) The inputs are protected as shown below. Input voltage magnitudes up to 5.5V, regardless of VA, will not cause errors in the conversion.
result. For example, if VA is 3V, the digital input pins can be driven with a 5V logic device.

  • I'm still not sure what that fixed 3V reference is used for (comparing and improved the analog input accuracy? )
  • I couldn't find where it is stated that " the input voltage may not be more than VA + 0.3V (absolute maximum rating). " Still I believe your answer and wonder if Va coud't be set as 5.0 or 5.5V as stated in the Operating Ratings data of the ADC121C021 ADC ?
  • I'm using a Grove/Seeed I2C shield on arduino uno (wifi) and there is a 3v/5V switch on the shield. it is currently set on 5V in order to correctly power the I2C Grove LCD .
  • In any case I'll implement your volage divider ASAP and test it out hoping it will solve the issue.

Thank you again all !! My tiny brain was overclocking here.

TonyWilk:
I guess either the ADC is using your 5v rail as reference and the 5v from the encoder is actually slightly less or you are dividing the 5v signal to 3v with some tolerance.

What ADC are you using ?

How are you presenting the rotary encoder signal ?

Yours,
TonyWilk

Hello thank you for your answer !

  1. Grove ADC
  2. I'm not sure what "presenting" exactly means but I'm using a 9V battery to power it and the - connected to the GND pin of the Arduino. then the analog data pin connected to the SCL pin of the I2C ADC.

he55e:
I’m still not sure what that fixed 3V reference is used for (comparing and improved the analog input accuracy? )

All ADCs need a reference voltage - that’s your full scale. Basically, the input voltage is compared to that voltage, and the output gives you the ratio between the two. When your input voltage goes over this reference, the ADC will output it’s 100% value (4095 in this case) or release the magic smoke and stop working.

I couldn’t find where it is stated that " the input voltage may not be more than VA + 0.3V (absolute maximum rating). "

That’s in the data sheet of the ADC. Not in the Grove description page.

Still I believe your answer and wonder if Va coud’t be set as 5.0 or 5.5V as stated in the Operating Ratings data of the ADC121C021 ADC ?

Yes - but not with that specific breakout board (a breakout board is simply a board that “breaks out” a chip - usually adding supporting hardware such as filtering caps and pull-up resistors, and in this case a voltage reference - and which makes it a lot easier to work and experiment with). It has a 3V reference built in.

all clear now ! :smiley_cat:

basically the choices are :

  1. Voltage divider (will I lose any accuracy here) ? I suppose not !?
  2. Change ADC adafruit.com 16 bits wide range 4 inputs as 1 have 2 encoders to manage ? (someone told me I need a 16 bit encoder to clearly read a 12bit encoder)

thank you very much again. I'll be able to sleep tonight !

moderator: fixed link

Your link is broken, but I think you're trying to link to this ADS1115 breakout which indeed will do the job. It has a programmable gain so you don't need a voltage divider. It's effectively 15 bits (it's a signed int, can go negative when using it as comparator).

Indeed if you want to read the full 12-bit range of your output, you must have a greater than 12-bit input. After all for very conversion you do lose some precision.

The voltage divider doesn't make you lose precision by itself, but it typically brings the maximum voltage to maybe 90% full scale, so there you lose some precision as well.

Awesome forum !
Thank you so much .
All clear, I know what I have to do now !