Author Topic: Rpi Pico/AD7994 weirdness  (Read 1948 times)

0 Members and 1 Guest are viewing this topic.

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Rpi Pico/AD7994 weirdness
« on: August 21, 2023, 02:35:18 am »
I'll preface this by saying I know practically nothing about coding. I've written stuff for Arduinos here and there over the years, but that's it.

I'm currently trying to use an AD7994 (4 channel 12 bit I2C ADC) with a Raspberry Pi Pico for a project and I keep hitting the exact same issue. I won't bother posting code here at this point because I've tried all sorts of variations and nothing has worked, so I'm assuming I'm doing something fundamentally wrong and I need a fresh start.

I can read in data OK, and manipulate it (with scaling etc) as I want. The problem is that no matter what I try, reading channel 3 always returns the value of channel 1. Even if I start with fresh code that only reads one channel and adjust the code to test channels one at a time, channel 3 will show the value at channel 1's input pin instead.

I got suspicious of the ADC I was using so I just replaced it, but nope, the issue is not the hardware. There are no shorted pins or anything else either, I can measure directly at the ADC pins and voltages are as expected- just not in software. I guess the issue must be related to controlling the multiplexer in the ADC, but I don't understand why it works fine for channels 1/2/4 and just not 3.

Any ideas on what might cause this? Or suggestions on a test code I could use as a starting point to see if I can get a proper read from all channels with code written by someone who isn't a moron like me?

Thanks!
 

Offline MikeK

  • Super Contributor
  • ***
  • Posts: 1314
  • Country: us
Re: Rpi Pico/AD7994 weirdness
« Reply #1 on: August 22, 2023, 12:51:40 am »
There's an Arduino library...Did you try that?
 

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #2 on: August 22, 2023, 07:07:21 am »
There's an Arduino library...Did you try that?

No, as I said I was using this as an opportunity to try out a Pico and start learning a bit of Micropython

If it was critical I would have moved on in another direction, but as it's kind of a side project/learning thing I'm keen to try to understand what would cause this strange behaviour
 

Offline Shonky

  • Frequent Contributor
  • **
  • Posts: 290
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #3 on: August 22, 2023, 08:49:08 am »
Post your absolute bare minimum code. I suspect you've got a bit in the wrong place or similar.
 
The following users thanked this post: David Aurora

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #4 on: August 22, 2023, 09:49:35 am »
Post your absolute bare minimum code. I suspect you've got a bit in the wrong place or similar.

Yeah next chance I get I'll put together a super bare bones test and post it here, hopefully the screw up is obvious to someone other than me  ;D
 

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #5 on: March 11, 2024, 02:14:20 am »
10 years later I finally got back to this  :-DD

OK, so I used ChatGPT as a starting point here. Again, I know absolutely nothing about writing Python/micropython stuff so the idea for this project was to start with a very basic code and build/modify from there to learn a bit. Like I know enough to flash some LEDs or perform some calculations or whatever, but absolutely nothing about interfacing with ADCs and so on.

This thing is just supposed to read 4 voltages and I'll manipulate that info to do stuff from there. I've successfully written code to do what I want to do with that data multiple times now so apparently I'm not completely braindead, but given I can't get the right data in whatever else I'm writing is useless.

After a few tweaks on the ChatGPT starting point the code below basically works (this has none of my data manipulation stuff, just bare bones reading), but with a couple issues:
Code: [Select]
import time
from machine import I2C, Pin

# Define the SDA and SCL pins for the Raspberry Pi Pico
i2c = I2C(0, sda=Pin(0), scl=Pin(1))  # Use GPIO 0 for SDA, GPIO 1 for SCL
ad7994_address = 0x21  # Replace XX with the AD7994 I2C address
reference_voltage = 5  # Reference voltage in volts

# Define the CONVST pin
convst_pin = Pin(2, Pin.OUT)  # Use GPIO 2 as the CONVST pin

# Function to initiate ADC conversion
def initiate_conversion():
    convst_pin.value(1)  # Set CONVST pin high
    time.sleep_us(10)  # Minimum pulse width for CONVST (10 microseconds)
    convst_pin.value(0)  # Set CONVST pin low

# Function to read 12-bit data from the AD7994 and scale to voltage
def read_ad7994(i2c, address):
    # Read from all 4 channels sequentially
    readings = []
    for channel in range(4):
        initiate_conversion()  # Initiate ADC conversion
        time.sleep_ms(10)  # Wait for the ADC conversion to complete (adjust this delay if needed)

        i2c.writeto(address, bytes([0x80 | (channel << 4)]))  # Write to the config register for the specified channel
        time.sleep_ms(1)  # Wait for the configuration write to complete (adjust this delay if needed)
        data = i2c.readfrom(address, 2)
        value = ((data[0] << 8) | data[1]) & 0xFFF
        voltage = (value / 4095.0) * reference_voltage
        readings.append(voltage)

    return tuple(readings)

# Main loop to continuously read and print data from the AD7994
while True:
    channel_voltages = read_ad7994(i2c, ad7994_address)
    print("Channel 1: {:.2f} V".format(channel_voltages[0]))
    print("Channel 2: {:.2f} V".format(channel_voltages[1]))
    print("Channel 3: {:.2f} V".format(channel_voltages[2]))
    print("Channel 4: {:.2f} V".format(channel_voltages[3]))

    time.sleep(2)  # Add a delay between readings (adjust as needed)



I've got this set up on a breadboard with a simple test- 1V going into channel 1, 2V going into channel 2, 3V going into channel 3, 4V going into channel 4.

Problem 1 is that the order is reversed. So channel 1 prints as 4V/channel 4 prints as 1V, etc.

That's not a big deal as I can change that in the print function, but I'd like to understand why this is happening in the first place.

Problem 2 is the main problem- channel 2 in the code above (which is actually channel 3 on the ADC) should be printing 3V, but it always prints 1V. The other 3 channels all give the correct readings.

There is DEFINITELY 3V on that pin, and I've even swapped IC's to rule out a bad ADC. Something about literally every working variation of the code that I've managed to punch in means it never reads this particular pin properly. And yeah, given that I know jack shit, I'm absolutely stumped as to why.

If it helps, data sheet for the ADC is here- https://www.analog.com/media/en/technical-documentation/data-sheets/ad7993_7994.pdf

I will absolutely buy a beer/coffee for the first person who can help me fix this/understand what is going on because I'm just bashing my head against the wall here haha
 

Offline shabaz

  • Regular Contributor
  • *
  • Posts: 145
Re: Rpi Pico/AD7994 weirdness
« Reply #6 on: March 11, 2024, 03:10:25 am »
I'm not familiar with the ADC (it seems overly complicated compared to typical ADS111x!), but am OK-ish with MicroPython. It looks like you're using the Mode 1 of operation (page 28 of the AD7994 datasheet.
Not 100% sure how to do it, but it looks like you've got to first write to a config register to choose the desired channel, and then pulse the *CONVST pin to power-up the device and initiate the conversion, and then write to the device to select the result register, and then perform the read. Maybe the portions of code below (untested) may help move forward a bit (hopefully!), or it may need further tweaks. I may have misread bits of that datasheet portion, so it may need double-checking.


Code: [Select]
CONV_RESULT_REG = 0x00
CONFIG_REG = 0x02

def initiate_conversion():
    convst_pin.value(1)  # Set CONVST pin high
    time.sleep_us(20)  # Minimum pulse width for CONVST (10 microseconds but we can make it 20 to be sure)
    convst_pin.value(0)  # Set CONVST pin low


def read_ad7994(i2c, address):
    # Read from all 4 channels sequentially
    readings = []
    for channel in range(4):
# select the channel
b = bytes([CONFIG_REG, 0x08 | 1<<channel+4])  # 0x18/0x28/0x48/0x88 corresponds to channel 0-3
i2c.writeto(address, b)

# now toggle the CONV pin
        initiate_conversion()  # Initiate ADC conversion
        time.sleep_us(10)  # Conversion time (could be made shorter later if it works)

# set the device to the result (conversion result) register
b = bytes([CONV_RESULT_REG])
i2c.writeto(address, b)


# now read in the result for that channel
data = i2c.readfrom(address, 2)

# get rid of the 4 most significant bits
        value = ((data[0] << 8) | data[1]) & 0xFFF

# scaling
        voltage = (value / 4095.0) * reference_voltage
        readings.append(voltage)

    return tuple(readings)
 

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #7 on: March 11, 2024, 03:20:28 am »
I'm not familiar with the ADC (it seems overly complicated compared to typical ADS111x!), but am OK-ish with MicroPython. It looks like you're using the Mode 1 of operation (page 28 of the AD7994 datasheet.
Not 100% sure how to do it, but it looks like you've got to first write to a config register to choose the desired channel, and then pulse the *CONVST pin to power-up the device and initiate the conversion, and then write to the device to select the result register, and then perform the read. Maybe the portions of code below (untested) may help move forward a bit (hopefully!), or it may need further tweaks. I may have misread bits of that datasheet portion, so it may need double-checking.


Code: [Select]
CONV_RESULT_REG = 0x00
CONFIG_REG = 0x02

def initiate_conversion():
    convst_pin.value(1)  # Set CONVST pin high
    time.sleep_us(20)  # Minimum pulse width for CONVST (10 microseconds but we can make it 20 to be sure)
    convst_pin.value(0)  # Set CONVST pin low


def read_ad7994(i2c, address):
    # Read from all 4 channels sequentially
    readings = []
    for channel in range(4):
# select the channel
b = bytes([CONFIG_REG, 0x08 | 1<<channel+4])  # 0x18/0x28/0x48/0x88 corresponds to channel 0-3
i2c.writeto(address, b)

# now toggle the CONV pin
        initiate_conversion()  # Initiate ADC conversion
        time.sleep_us(10)  # Conversion time (could be made shorter later if it works)

# set the device to the result (conversion result) register
b = bytes([CONV_RESULT_REG])
i2c.writeto(address, b)


# now read in the result for that channel
data = i2c.readfrom(address, 2)

# get rid of the 4 most significant bits
        value = ((data[0] << 8) | data[1]) & 0xFFF

# scaling
        voltage = (value / 4095.0) * reference_voltage
        readings.append(voltage)

    return tuple(readings)

That worked! Thanks! DM me your PayPal and I'll buy you that drink!

I'll read through that code properly later on to try to wrap my thick skull around how it works for next time
 

Offline shabaz

  • Regular Contributor
  • *
  • Posts: 145
Re: Rpi Pico/AD7994 weirdness
« Reply #8 on: March 11, 2024, 03:33:48 am »
Ahh the offer alone is thanks enough, I liked the coding challenge : ) Very happy that it worked out. Thanks for testing it and confirming so quickly!
 
The following users thanked this post: David Aurora

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #9 on: March 11, 2024, 04:19:48 am »
In that case let me know a charity/cause you'd like to support and I'll spread the good karma around a bit  :)

Thanks again!
 
The following users thanked this post: shabaz

Offline shabaz

  • Regular Contributor
  • *
  • Posts: 145
Re: Rpi Pico/AD7994 weirdness
« Reply #10 on: March 11, 2024, 05:31:09 am »
Great idea! I contribute a [albeit tiny, I should do more] bit to Oxfam monthly, so would be nice to know they got a bit extra this month. Or any other helping-poor-related charity you're ok with. Thanks for this!
 
The following users thanked this post: David Aurora

Offline David AuroraTopic starter

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Rpi Pico/AD7994 weirdness
« Reply #11 on: March 11, 2024, 10:55:45 am »
Consider it done  :)
 
The following users thanked this post: shabaz


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf