ul-gh / PiPyADC

Python classes for interfacing Texas Instruments analog-to-digital converters with the Raspberry Pi
GNU Lesser General Public License v2.1
69 stars 27 forks source link

Erratic Readings on ADC1256 #22

Closed acatphd closed 4 years ago

acatphd commented 4 years ago

First, let me say THANK YOU for developing PiPyADC!! Setup was straightforward and worked "out of the box". I have set it up with the WaveShare High-Precision AD/DA Board on a new RPi4 running Raspian Buster.

I am using the board to measure the drain characteristics of batteries. Simply put , the circuit consists of a load resistor across a battery, the voltage measured across the resistor from AD0 to AINCOM/Ground, using a one shot measurement (I'll attach the code below as a txt file for a simpler portion of the measuring part of the program). The battery voltage is always between 0-1.5 Volts.

The problem is that the reading from either a "one-shot" or "sequence" reading will produce a value of 0 volts in an irregular pattern over time, or, yet more infrequently an erroneous voltage value altogether. I should point out that even running the example code, example.py or example_2.py results in the same behavior. So perhaps my board has some defect. I have noticed that it seems to vary depending on the sample rate and delay values but I'm not sure if this is reproducible. I've checked all my connections etc., but I am wondering if there is some specific settings or code that is critical to reproducible behavior?

Measure.txt

ul-gh commented 4 years ago

Hi,

please excuse the late reply, I had some busy weeks.

I just now tested with my Raspi and I can not confirm the zeros. However, there is a small issue with your example, please see the comments I made to your file right at the code block at the bottom of this reply.

I do not currently own an RPi 4 - I tested with Raspi 2 and 3 versions. Of course there could be some issue with the Pi 4 which I do not know of yet.

Can you please test if the changes I explaned below fix your issue and if not, can you maybe test with an RPi 3?

Apart from this, maybe I am ordering a Pi 4 in the near future, then I can test the board with the newer hardware.

The issue I found was that you are calling ADS1256.reset() in every loop. This resets the hardware configuration registers and thus these must be re-initialised to the desired values - except you want the hardware defaults (wich is especially with a deactivated input buffer).

Please test this:

#!/usr/bin/python
# -*- coding: utf-8 -*-
""" Based on PiPyADC: Example file for class ADS1256 in module
see https://github.com/ul-gh/PiPyADC
Hardware: Waveshare ADS1256 board interfaced to the Raspberry Pi 3

"""
from __future__ import print_function
import sys
import time
from ADS1256_definitions import *
from pipyadc import ADS1256
import bench_config as conf

# Input pin for the potentiometer on the Waveshare Precision ADC board:
POTI = POS_AIN0|NEG_AINCOM

ads = ADS1256(conf)
# reset() is automatically called during initialisation from the constructor,
# however, if it is explicitly called like this:
ads.reset()
# then by resetting the ADC to base state, it must be re-configured afterwards,
# e.g. activate the input buffer, set data rate etc.
ads.adcon         = conf.adcon
ads.drate         = conf.drate
ads.gpio          = conf.gpio
# This one is important, as it activates/deactivates the input buffer
ads.status        = conf.status

def do_measurement():
    # You should not call ads.reset() in the loop!
    ##ads.reset() - NO!
    # You /could/ always start the self-calibration routine, however this should
    # normally only seldom be necessary, e.g. when temperature changes much.
    ads.cal_self()
    # The rest is OK
    raw_channel_pair = ads.read_oneshot(POTI)
    volts = ads.v_per_digit * raw_channel_pair
    return volts

while True:
    volts = do_measurement()
    while volts <= 0:
        volts= do_measurement()
        print('Measured <= ZERO!')
    print('VOLTAGE=', volts)
    time.sleep(0.1)
acatphd commented 4 years ago

Many thanks for looking into this and your suggestions. I tried numerous iterations of the code, and although I cannot be certain that I tried this particular one, I believe I tried the code with and without the ads.reset in the loop. Separately I tried measurements with C++ code provided by the manufacturer in China with the same erratic behavior. Because of some comments in various forums that indicated there were some issues with samples of this particular PCB I decided there was at least some possibility of a hardware problem, I returned the board, and instead employed an Adafruit ADS1015 with the RPi4 which worked perfectly. So I'm very sorry I could not test your suggestions, but thank you for looking into the issue.