Razzburry_Pie
Posts: 8
Joined: Thu Feb 16, 2017 4:50 pm

Reading Values from 12-bit ADC with Python with I2C

Fri Feb 23, 2018 8:05 pm

I would like to digitize the position of several potentiometers. I have successfully connected an 8-channel LTC2309 ADC to my RPi 2B via the I2C bus. I'm able to read bytes from the chip but unfortunately the output seems to be garbage. Numbers jump all over even when the pot is stationary. Changing the position of the pot doesn't seem to affect the readings either. It's all seemingly random output.

Reading the LTC2309 spec sheet, the output is in two bytes and bit-shifting is required to convert the reading into a usable result. I am not skilled at bit shifting so that could be an issue, I'm not sure. The first byte has 8 bits but they need to be shifted to the left by 4 places because they are the 2^12 thru 2^5 values. The second byte gives 4 bites followed by 4 trailing zeros and need to be shifted to the right by 4 to get the 2^4 thru 2^1 values. Theoretically adding them together after shifting should give the proper value.

Also complicating things is that the chip needs a 6-bit instruction word to tell it what mode to be in when taking readings. If I read it right I need to send 110010, padded with 00 on the right, to read Channel 0 in simple single-ended unipolar mode, with SLEEP turned off between readings. 11001000 is 0xC8 in hex.

Here's some sample output -- with the pot in a random position and not being turned:

Code: Select all

2560  3584  2063  2071  3072  2055  2087  2560  1543  2071
Any ideas what's wrong here? I'm scratching my head on this. Python test code and schematic below.

Spec sheet: http://cds.linear.com/docs/en/datasheet/2309fd.pdf
=================================

Code: Select all

import smbus2

ADDRESS = 0x08
INSTRCT = 0xC8

class my_test(object):
    def __init__(self):
        self.bus = smbus2.SMBus(1)

    def read_word(self):
        msg = self.bus.read_word_data(ADDRESS, INSTRCT)
        msb = (msg & 0xFF) << 4
        lsb = (msg & 0xF000) >> 12
        return (msb + lsb)

xx = my_test()
for i in range(0,21):
    zz = xx.read_word()
    print(zz)
    
Image

User avatar
joan
Posts: 13454
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Reading Values from 12-bit ADC with Python with I2C

Fri Feb 23, 2018 9:32 pm

It may be helpful to see the read word before you have extracted the value. The byte order may be reversed.

vpatron
Posts: 10
Joined: Thu Jul 11, 2013 5:22 am

Re: Reading Values from 12-bit ADC with Python with I2C

Fri Feb 23, 2018 11:56 pm

I'm not familiar with that ADC, but:

1) it seems fairly slow, do you need to put a delay between start of conversion and when you read the data?
2) Could you be reading the wrong input and just reading noise? You could try grounding the other inputs and see if you get 0 (or close to 0) readings.

-Vince

Razzburry_Pie
Posts: 8
Joined: Thu Feb 16, 2017 4:50 pm

Re: Reading Values from 12-bit ADC with Python with I2C

Sat Feb 24, 2018 2:13 am

I grounded the CH0 pin, same readings. I let it float, same readings. Will check the hardware end to double check to make sure things are connected correctly.

ddahms
Posts: 64
Joined: Tue Mar 18, 2014 3:38 pm

Re: Reading Values from 12-bit ADC with Python with I2C

Sat Feb 24, 2018 2:47 am

The datasheet says to put a 2.2uF cap on Vref pin 20, and a 10uF and 0.1uF cap on REFCOMP pin 1. Perhaps your circuit is oscillating without these caps. It might not be the cause of your problem but it can't hurt.

Razzburry_Pie
Posts: 8
Joined: Thu Feb 16, 2017 4:50 pm

Re: Reading Values from 12-bit ADC with Python with I2C

Thu Mar 01, 2018 5:16 am

Mail man just brought me a few MCP3008 chips. Hooked one up in a very similar circuit as above, except using hardware SPI instead of I2C. I also added a 4.096v reference chip to feed Vref. Used a couple of 1 uF caps to decouple both Vdd and Vref. I stole this code snippet:

Code: Select all

import spidev
import time
import os
 
# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz=500000
 
# Function to read SPI data from MCP3008 chip
# Channel must be an integer 0-7
def ReadChannel(channel):
  adc = spi.xfer2([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

Worked perfectly the first time I fired up the circuit.

I don't know why the LTC2309 didn't work for me. The '3008 is in a DIP package and easy to work with; the '2309 is a TSSOP. Bad soldering on my part?

Return to “Interfacing (DSI, CSI, I2C, etc.)”

Who is online

Users browsing this forum: No registered users and 10 guests