This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Fairly odd format of stored values in register of ADC128D818

Other Parts Discussed in Thread: ADC128D818

Hello!


I have a question about the ADC128D818, and I hope this is the correct subforum. I connected the ADC to a Raspberry Pi and communicate via SMB through a small Python script. And everything works fine, at least when I read/write the 8Bit register. If I want to read/write the 16Bit Register, I get some fairly odd values.


My reference voltage is 4,095V and the voltage at one input is about 3.3V. Which means, that I should get something like 0x0cef (3300). But what I actually get is 0x0e0cf (57551). I could understand it when two bytes would be shifted, but THIS? I really don't understand this result and why it is like this. I tried another ADC and it behaved in the same way.


I have wrote a small code to bitshift the value to a "correct" format. But it really bugs me.

Have I done something wrong? Or is there something I overred?

Would be nice if someone could help me with this.

Cheers.

Ben

  • Hi Benjamin,

    Moving your post to the Precision ADC forum for better support.

    Thanks,
    Siby
  • Hi Ben,

    If you set the part to Mode 0 and try reading 27h using the format as shown in Figure 31, do you get the correct value?

    Mike
  • Hi Mike.

    This seems to be ok, at least mostly. I copied the output below.

    Address | Value in Register|Value as dec|Value conversion for Voltage

    --------------------------------------------
    0x27   0x2e   46   0.526V
    --------------------------------------------
    0x27   0x2e   46   0.526V
    --------------------------------------------
    0x27   0x802e   32814   0.654V
    --------------------------------------------
    0x27   0x2f   47   0.527V
    --------------------------------------------
    0x27   0x802e   32814   0.654V
    --------------------------------------------
    0x27   0x802e   32814   0.654V
    --------------------------------------------
    0x27   0x802d   32813   0.653V
    --------------------------------------------
    0x27   0x802d   32813   0.653V
    --------------------------------------------
    0x27   0x802d   32813   0.653V
    --------------------------------------------
    0x27   0x2d   45   0.525V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x802c   32812   0.652V
    --------------------------------------------
    0x27   0x2c   44   0.524V
    --------------------------------------------
    0x27   0x2c   44   0.524V
    --------------------------------------------
    0x27   0x2c   44   0.524V
    --------------------------------------------
    

    Ow, not that you think that I live in Mordor, but the starting value was 25 and I heated it up a little bit. (Fun Fact: At the moment I see snow outside of my window -.-)

    I also included the schematics, maybe there is something wrong. And also my code which produced this output

      1 import smbus
      2 import time
      3 import struct
      4 
      5 def reverse(x):
      6     tmp = (x  << 4) & 0x0f00
      7     tmp |= (x >> 8) & 0x00f0
      8     tmp |= (x & 0x000f)
      9     return tmp
     10 
     11 
     12 # Legit addresses for ADC128D818
     13 ADC_ADDRESS         = [0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f, 0x35, 0x36, 0x37]
     14 ADC_ADDRESS         = 0x1d
     15 # Support Values
     16 READ = 0
     17 WRITE = 1
     18 
     19 # Register
     20 ADC_CONFIG          = 0x00
     21 ADC_INTERRUPT       = 0x01
     22 ADC_INTERRUPT_MASK  = 0x03
     23 ADC_CONV_RATE       = 0x07
     24 ADC_CH_DISABLE      = 0x08
     25 ADC_ONE_SHOT        = 0x09
     26 ADC_DEEP_SHUTDOWN   = 0x0a
     27 ADC_ADV_CONFIG      = 0x0b
     28 ADC_STATUS          = 0x0c
     29 ADC_CH_READ         = [0x27]#[0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27]
     30 ADC_LIMIT_MIN       = [0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38]
     31 ADC_LIMIT_MAX       = [0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x39]
     32 ADC_MANU_ID         = 0x3e
     33 ADC_REV_ID          = 0x3f
     34 
     35 # Create I2C Session
     36 adc128 = smbus.SMBus(1)
     37 if adc128.read_byte_data(ADC_ADDRESS, ADC_STATUS) <= 1:
     38 
     39     adc128.write_byte_data(ADC_ADDRESS, ADC_CONFIG, 0x00)
     40 
     41     tmp = 0b111111101
     42     if adc128.read_byte_data(ADC_ADDRESS, ADC_CH_DISABLE) != tmp:
     43         print "ADC_CH_DISABLE_set"
     44         adc128.write_byte_data(ADC_ADDRESS, ADC_CONFIG, tmp)
     45     else:
     46         print "ADC_CH_DISABLE already set"
     47 
     48     if adc128.read_byte_data(ADC_ADDRESS, ADC_ADV_CONFIG) != 0x01:
     49         print "ADC_ADV_Config set"
     50         adc128.write_byte_data(ADC_ADDRESS, ADC_ADV_CONFIG, 0x01)
     51     else:
     52         print "ADC_ADV_CONFIG already set"
     53 
     54     if adc128.read_byte_data(ADC_ADDRESS, ADC_CONFIG) != 0x01:
     55         print "ADC_CONFIG set"
     56         adc128.write_byte_data(ADC_ADDRESS, ADC_CONFIG, 0x01)
     57     else:
     58         print "ADC_CONFIG already set"
     59 
    

    Ausgabe.pdf

  • Maybe the first 4 Bits are only random, which would explain this output of the temperature. So I should be able to cut this off by make an & 0x0FFF

    EDIT: OK, but it doesnt work for the other register, as the third bid is always 0 so if I would make an &0x0FFF it get only an byte the the value. Which seems to work. surprisingly, but the additional 4 Bit would be nice.

  • Hi Ben,

    It looks like you are getting the correct value for the temperature reading. You should be doing a 2 byte read. Looking at one of the values you got, 0x802e, the least significant bit of the MSB is 0 so that means the value is positive. The LSB contains the temperature, 0x2e = 46 decimal, divide this by 2 to get the temperature of 23C. This is described on page 29 of the datasheet.

    If you connect IN0 to ground and do a 2 byte Mode 0 read of register 20h you should get xxxx 0000 0000 0000 (x = don' care). When you use this value you should throw away the top four bits.

    If you connect IN0 to the Vref and do a 2 byte Mode 0 read of register 20h you should get xxxx 1111 1111 1111.

    Mike
  • Hi Mike.

    I am able to read this indeed, but in some strange way. In the smbus library there are two methods to achieve a 2 byte read. The first oneis really only a 2 byte read. It gives you the content of the register you want. The second method reads, I think 32 byte, which are mostly empty and filled with fs. The only difference between these two output is, that the bytes are switched.

    So I get an 0xf0ff or an 0xfff0. Now I assume that the second one is in some kind of correct order but with this order of bits 0x[LSB]...[MSB].  And if it would be like this, it would be OK, but I made some small table with the output of the ADC128 with the values I calculated and in comparison to the measured and adjusted voltage on the input.

    Output Correct Output Measured Voltage Adjusted Voltage
    0x102e 0x21e 0,542 0,748
    0x8037 0x387 0,887 0,899
    0x503e 0x25e 0,878 1,009
    0xf04f 0x4ff 1,279 1,291
    0x3057 0x537 1,335 1,408
    0xb05a 0x5ba 1,466 1,463
    0x505c 0x55c 1,372 1,489
    0x3061 0x631 1,585 1,568
    0x3062 0x632 1,57 1,583
    0x306c 0x63c 1,596 1,743
    0x7070 0x770 1,904 1,812
    0x3078 0x738 1,848 1,936
    0x708c 0x87c 2,172 2,26
    0x80a3 0xa83 2,691 2,692
    0x20b5 0xb25 2,853 2,912
    0x70c2 0xc72 3,186 3,126
    0x80ce 0xc8e 3,214 3,31
    0xf0ff 0xfff 4,095 4,1
  • Hi Ben,

    It does seem like the software the the Raspberry Pi uses is moving the values that are read around before sending them out. You will probably need to rearrange it in the software so that it is in the correct order.

    If you have the equipment (scope or logic analyzer) you can monitor the I2C lines during a read and you should see them come out of the ADC128D818 in the order shown in Figure 31 in the datasheet MSB first and then LSB.

    Mike
  • Hi Mike.

    Jip, I have a scope since yesterday, but I wasn't able to measure this much. But I will do it at the weekend.

  • Soooo...I was able to obeserve the I2C communication, and I was also able to locate the address, register and data bytes. And it looks pretty much like in the datasheet. What I also see is, that the databytes are switched, as I mentioned above.

    Sorry, that I cant attach a picture of it. Its an old CRT digital oscilloscope, so no USB Port or so. I drew it in inkscape ^^

    So, now I know that it seems, that the Pi recognize the data correctly. I have really no idea where the problem is, because it is the second IC I tried. And it would surprise me, if a third chip would behave in an other way.
  • Hi Ben,

    Sorry for the delay, I had to find a part and look at it in the lab, since it has been awhile since I have used this part.

    Here is what I am seeing with the part.

    I set it up by writing 0x01 to register 0x07 and also writing 0x01 to register 0x00. This sets it using the internal Vref, puts it in Mode0, makes it continually convert and then starts the conversion.

    Then I read register 0x27, which is the internal temperature sensor.

    It gave me back two bytes: 0x1680. Convert this to binary: 0001 0110 1000 0000. Since the the temperature is 9 bits long discard the 7 least significant bits which gives 0 0010 1101 which is 0x02D, convert to decimal: 45 and then divide by 2 for a temperature of 22.5C which is close to the room temperature.

    Then I put my finger on the part to warm it up a little and got the value 0x1D00 --> 0001 1101 0000 0000, remove the bottom 7 bits --> 0 0011 1010, convert to decimal, 58, divide by 2 for a temp of 29C.

    Next I read register 0x20 while putting various voltages on the IN0 pin.

    Starting with 2.56V on IN0, this gives 0xFFF0, convert to binary --> 1111 1111 1111 0000. Since this register is 12 bits discard the lower 4 bits, this gives 1111 1111 1111 --> 0xFFF which is what the value should be.

    Next I tried about 2.52V on the input. This gave 0xFA30 --> 1111 1010 0011 0000, discard lower 4 bits, --> 1111 1010 0011 --> which is 0xFA3. The calculated value is 0xFC0. The difference is from measurement error.

    Mike
  • Hi Mike.

    Ok, I see. I thought that the upper 4 bits where the ones which aren't necessary. Now I get some correct and stable values. But I have to say, that I can't find a hind to this in the datasheet. Have I overlooked something?

    But anyway! Thanks for your help!

    Cheers,
    Benjamin