Benutzer-Werkzeuge

Webseiten-Werkzeuge


raspberry:raspberry_gpio_read_adc0831

Einen AD Wandler ADC0831 mit dem Raspberry PI verwenden

Für den Anschluss des AD Wandler ADC0831 mit dem Raspberry PI werden drei GPIO Ports verwendet. Zu beachten ist aber, das der ADC0831 mit 5V betrieben wird, die GPIO Ports aber NUR 3,3V verwenden dürfen!

Die Pegel für den Ausgang des ADC0831 sind deshalb entsprechend über einen Spannungsteiler anzupassen (siehe Pegelwandler ).

Der gemessene Wert wird als 8bit Datenword seriell eingelesen, per CS (Chip Select) auf LOW wird das auslesen initialisiert, ein Takt wird auf CLK gelegt, es muss zwei Taktzyklen gewartet werden und auf DO kann das 8bit Datenword ausgelesen werden.

Am Pin 5 des ADC0831 liegt die Vref (Reference Voltage) an, bis zu der mit dem Baustein gemessen werden kann.

Der Pin 5 wird ebenfalls an die 5V Versorgungsspannung gelegt.

Der Wert des 5V Ausgangs auf Pin 2 des Raspberry ist aber leider nicht genau 5V sondern etwas niedriger, ca. 4.5~4,7V .

Das bedeutet, um genaue Messungen zu erhalten muss der exakte Wert gemessen und in der Software berücksichtigt werden! Leider ändert dieser sich auch noch zusätzlich ständig im Betrieb.

Der ADC0831 ist ein 8bit Wandler, d.h. der Messbereich von 0 bis Vref (Reference Voltage) wird in 256 diskrete Schritte (0…255) unterteilt.

Bei einer Spannung von zum Beispiel 4.5 Volt beträgt damit die Auflösung pro Messpunkt Vref/255=0,0176V.

Der ausgelesene Messwert muss daher auf in Bezug auf Vref und die 8bit Auflösung in eine Spannungswert umgerechnet werden, mit:

  • Referenz Spannung * ermittelter Wert / (Anzahl der möglichen diskreten Werte eines 8 Bit Wandlers = 255 )

Als Teiler verwende ich 255, lege ich auf Vin die Referenz Spannung wird der Wert 255 eingelesen ⇒ Vin = Vref = Referenz Spannung * (255/255) = Vref!

Datasheet:

Pin Belegung:

adc0831 Pin Belegung

Timing um einen Messwert zu erfassen:

adc0831 Timing um einen Messwert zu erfassen

Anschluss an den Raspberry:

 Anschluss an die GPIO Ports des  Raspberry PI

Verbesserung - Stabile Spannungsreferenz

Um einen höhere Genauigkeit zu erreichen, ist mit dem schwankenden 5V Wert (ist auch unterschiedlich je nach angeschlossenen USB Netzteil!) ist eine Spannungsreferenz notwendig.

Im einfachsten Fall ist eine Z-Diode denkbar, allerdings muss der entsprechende minimale Strom fließen, was den gesamt Stromverbrauch wieder etwas erhöht (siehe auch Dimensionierung einer Stabilisierungsschaltung mit Z-Diode).

Weitere Beispiele für eine Referenz-Spannungsquelle:

Alternativ kann ein LM 317 für eine einfache Referenzspannungsquelle dienen:

Schaltbild:

 LM 317 Standard Beschaltung

In einem Test habe ich einen LM 317 im TO-92 Gehäuse mit 2 * 470Ohm beschaltet und ~2,54V damit erzielt. Diese 2,54V dienen als Vref für den Pin 5 und werden in der Software als Referenzwert verwendet.

Besser geeignet ist wohl ein LM336-2.5 zum Beispiel für 2,56V als Referenz.

Spannungsteiler

Nun kann von 0 bis 2,54Volt gemessen werden, d.h. für höhere Spannung benötigen wir einen Beschaltung für den Eingang, im einfachsten Fall einen hochohmigen Spannungsteiler.

Der Eingangswiderstand des AD beträgt laut Datenblatt nur (Maximum Reference Input Resistance ⇒ ~3.5 KOhm )

Programm

Ablauf:

  1. Ein High to Low Signal an CS anlegen um die Messung zu starten
  2. Status von DO überwachen bis Flanke auf LOW
  3. 2* Taktzyklus an CLK senden
  4. Daten vom DO einlesen
  5. Daten bitweise verarbeiten
  6. Nachdem 8 bit empfangen wurden HIGH an CS und Takt aus
  7. Voltage Wert aus dem emfangenden Daten Word errechnen
    1. Referenz Spannung * ermittelter Wert / (Anzahl der möglichen diskreten Werte eines 8 Bit Wandlers = 255 )
  8. Messung mehrfach durchführen und den Mittelwert bilden

Ein einfaches erstes Beispiel Programm:

meter.py
import RPIO
import time
import sys
import getopt
 
# suppress warning
RPIO.setwarnings(False)
 
# Which RPIO Numbering you like to use
RPIO.setmode(RPIO.BCM)
# Set the used RPIO PORTs
# OUT
cs_port = 17
clk_port = 27
RPIO.setup(cs_port, RPIO.OUT)
RPIO.setup(clk_port, RPIO.OUT)
# IN
do_port = 22
RPIO.setup(do_port, RPIO.IN)
 
# Clock Time
clock_time = 0.001  # 1ms
 
# Global referenz valu
ref_voltage = 2.540
 
# runs
v_runs = 10
 
 
# Helper Function to set the bits
# set a bit to 1
def setBit(int_type, offset):
    mask = 1 << offset
    return (int_type | mask)
 
 
# set a bit to 0
def clearBit(int_type, offset):
    mask = ~(1 << offset)
    return (int_type & mask)
 
 
# get the real Voltage value from the extracted value
def getVolt(vvalue):
    # Value of the Voltage at the Pin 5 - Vref
    # Not real exact 5V in Raspberry!
    # Adjust to your real value!
    global ref_voltage
    # the ADC0831 has a 8bit resolution => 256 discrete values possible
    return_val = (vvalue * ref_voltage) / float(255)
    return return_val
 
 
# Read the Value from Pin 6 - DO
def read_meter(value):
    # start reading the MSB first
    offset = 7
    #to debug the binary value
    bin_string = ""
 
    # first Clock Cycle
    RPIO.output(clk_port, RPIO.HIGH)
    time.sleep(clock_time)
    RPIO.output(clk_port, RPIO.LOW)
    time.sleep(clock_time)
    #second Clock Cycle
    RPIO.output(clk_port, RPIO.HIGH)
 
    # Now we can start measurement
    for clock in range(8):
        time.sleep(clock_time)
        RPIO.output(clk_port, RPIO.LOW)
        # Read if HIGH or LOW and set the value
        if RPIO.input(do_port):
            bin_string = bin_string + "1"
            value = setBit(value, offset)
        else:
            bin_string = bin_string + "0"
            value = clearBit(value, offset)
        # debug the result
        # print "Port 22 => {0:5} :: bit offset {1}".format(str(RPIO.input(do_port)),offset)
        offset -= 1
        #
        time.sleep(clock_time)
        RPIO.output(clk_port, RPIO.HIGH)
    #Print the result
    print "Value => {0:10.4f} :: binFormat :: {1} :: Bin Value :: {2}".format(getVolt(value), bin_string, value)
    return getVolt(value)
 
 
def main(argv):
    global ref_voltage
    global v_runs
    try:
        opts, args = getopt.getopt(argv, "hv:r:", ["vref=", "runs="])
    except getopt.GetoptError:
        print sys.argv[0] + " -v <referenzvoltage> -r <runs> "
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print sys.argv[0] + " -v <referenzvoltage> -r <runs> "
            sys.exit()
        elif opt in ("-v", "--vref"):
            ref_voltage = float(arg)
        elif opt in ("-r", "--runs"):
            v_runs = int(arg)
    print "Referenz Voltage => {0:10.4f} :: Runs :: {1}".format(ref_voltage, v_runs)
 
 
if __name__ == "__main__":
    main(sys.argv[1:])
 
 
# init first time 
RPIO.output(cs_port, RPIO.HIGH)
RPIO.output(clk_port, RPIO.LOW)
time.sleep(clock_time)
RPIO.output(cs_port, RPIO.LOW)
RPIO.output(clk_port, RPIO.HIGH)
time.sleep(clock_time)
RPIO.output(cs_port, RPIO.HIGH)
RPIO.output(clk_port, RPIO.HIGH)
 
v_avg = 0.0
 
#read the values and get the average value as result
for clock in range(v_runs):
    # set the CS Line to LOW and wait 
    RPIO.output(cs_port, RPIO.LOW)
    time.sleep(clock_time)
    # set the clock to LOW as Starting value
    RPIO.output(clk_port, RPIO.LOW)
    # Read the DO output
    v_avg += read_meter(0)
    # End reading the DO Value
    RPIO.output(cs_port, RPIO.HIGH)
    time.sleep(clock_time)
    RPIO.output(clk_port, RPIO.LOW)
 
print "Total Value => {0:10.4f}".format(v_avg / float(v_runs))
 
#Set a defined Value for the next start
RPIO.output(cs_port, RPIO.HIGH)
RPIO.output(clk_port, RPIO.HIGH)

Quellen

ADC0834 - 4 Kanal Variante

Pin DGNG versus Pin AGND

  • DGNG = Digital Ground
  • AGND = Analog Ground

Ziel ist am Ende ein gemeinsamer Massepunkt um den unterschiedlichen Anforderungen an GND in den jeweiligen Zweig gerecht zu werden:

Siehe folgendes Papier ⇒ http://www.analog.com/static/imported-files/tutorials/MT-031.pdf


Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
raspberry/raspberry_gpio_read_adc0831.txt · Zuletzt geändert: 2016/08/13 22:04 von Gunther Pippèrr