rccardany
Posts: 14
Joined: Wed May 22, 2019 4:27 pm

AD Wandler MCP 3008

Wed May 22, 2019 4:44 pm

Hallo zusammen

für meine Hausautomatisierung benötige ich jede Menge analoge Eingänge.
Daher habe ich mich mit Analog Digital Wandlern beschäftigt.
Mittels GPIO möchte AD Wandler ansprechen und die 8 Eingänge auslesen.

Nach einigem recherchieren bin ich nun so weit:
Den AD Wandler habe ich wie folgt angeschlossen:

Code: Select all

RaspberryPi 	MCP3008
Pin 1 (3.3V) 	Pin 16 (VDD)
Pin 1 (3.3V) 	Pin 15 (VREF)
Pin 6 (GND) 	Pin 14 (AGND)
Pin 23 (SCLK) 	Pin 13 (CLK)
Pin 21 (MISO) 	Pin 12 (DOUT)
Pin 19 (MOSI) 	Pin 11 (DIN)
Pin 24 (CE0) 	Pin 10 (CS/SHDN)
Pin 6 (GND) 	Pin 9 (DGND)
Die SPI Schnittstelle habe ich aktiviert über:

Code: Select all

sudo raspi-config
Außerdem habe ich ein Python-Skript gefunden, mit dem die Abfrage / Ausgabe möglich sein sollte:

Code: Select all

from spidev import SpiDev
 
class MCP3008:
    def __init__(self, bus = 0, device = 0):
        self.bus, self.device = bus, device
        self.spi = SpiDev()
        self.open()
 
    def open(self):
        self.spi.open(self.bus, self.device)
    
    def read(self, channel = 0):
        adc = self.spi.xfer2([1, (8 + channel) << 4, 0])
        data = ((adc[1] & 3) << 8) + adc[2]
        return data
            
    def close(self):
        self.spi.close()
Abfrage:

Code: Select all

from MCP3008 import MCP3008
adc = MCP3008()
value = adc.read( channel = 0 ) # Den auszulesenden Channel kannst du natürlich anpassen
print("Anliegende Spannung: %.2f" % (value / 1023.0 * 3.3) )
Leider erhalte ich als Output immer nur: (Obwohl an jedem Ausgang zum Testen stumpfe Spannungsteiler angeschlossen sind)

Code: Select all

Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Anliegende Spannung: 0.00
Nach weiterem nachforschen bin ich auf folgenden code gestoßen:

Code: Select all

import spidev
import time
import os
import RPi.GPIO as GPIO, time, os

#Setup GPIO
GPIO.setmode(GPIO.BCM)

cs1 = 17

GPIO.setup(cs1, GPIO.OUT)

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)

# Function to read SPI data from MCP3008 chip 1
# Channel must be an integer 0-7
def ReadChip1(channel):
  GPIO.output(cs1, False)
  adc = spi.xfer([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

# Define sensor channels - ReadChip1
input1 = 0
input2 = 1
input3 = 2
input4 = 3
input5 = 4
input6 = 5
input7 = 6
input8 = 7

while True:

  # Read input data each Channel
  input1_level = ReadChip1(input1)
  input2_level = ReadChip1(input2)
  input3_level = ReadChip1(input3)
  input4_level = ReadChip1(input4)
  input5_level = ReadChip1(input5)
  input6_level = ReadChip1(input6)
  input7_level = ReadChip1(input7)
  input8_level = ReadChip1(input8)

  # Print out results
  print "--------------------------------------------"
  print("input_channel_1: {}".format(input1_level))
  print("input_channel_2: {}".format(input2_level))
  print("input_channel_3: {}".format(input3_level))
  print("input_channel_4: {}".format(input4_level))
  print("input_channel_5: {}".format(input5_level))
  print("input_channel_6: {}".format(input6_level))
  print("input_channel_7: {}".format(input7_level))
  print("input_channel_8: {}".format(input8_level))
#  print "-----"
time.sleep(0.1)

close()

GPIO.cleanup()
Leider hier ein Ähnliches Ergebnis:

Code: Select all

input_channel_1: 0
input_channel_2: 0
input_channel_3: 0
input_channel_4: 0
input_channel_5: 0
input_channel_6: 0
input_channel_7: 0
input_channel_8: 0
Nach mehrfacher Verkabelungsprüfung bin ich mir sicher, den AD Wandler korrekt angeschlossen zu haben. Woran kann es liegen, dass ich die Werte nicht korrkt heraus bekomme? Müssen die verwendeten GPIOS aktiviert werden? Ich bin ratlos. Vorschläge ?!

pcmanbob
Posts: 6248
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: AD Wandler MCP 3008

Wed May 22, 2019 7:39 pm

Hallo.

Sorry, ich spreche kein Deutsch, hoffe google übersetzt das ok.

Sie müssen die Zeile hinzufügen

{ Hi.

Sorry don't speak German hope google translates this ok.

you need to add the line }


Code: Select all

spi.max_speed_hz=1000000
Einstellen der Kommunikationsgeschwindigkeit zwischen dem Pi und dem MCP3008.

so was

{ To set the communications speed between the pi and the MCP3008.

like this }

Code: Select all

import spidev
import time
import os
import RPi.GPIO as GPIO, time, os

#Setup GPIO
GPIO.setmode(GPIO.BCM)

cs1 = 17

GPIO.setup(cs1, GPIO.OUT)

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz=1000000

# Function to read SPI data from MCP3008 chip 1
# Channel must be an integer 0-7
def ReadChip1(channel):
  GPIO.output(cs1, False)
  adc = spi.xfer([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

# Define sensor channels - ReadChip1
input1 = 0
input2 = 1
input3 = 2
input4 = 3
input5 = 4
input6 = 5
input7 = 6
input8 = 7

while True:

  # Read input data each Channel
  input1_level = ReadChip1(input1)
  input2_level = ReadChip1(input2)
  input3_level = ReadChip1(input3)
  input4_level = ReadChip1(input4)
  input5_level = ReadChip1(input5)
  input6_level = ReadChip1(input6)
  input7_level = ReadChip1(input7)
  input8_level = ReadChip1(input8)

  # Print out results
  print "--------------------------------------------"
  print("input_channel_1: {}".format(input1_level))
  print("input_channel_2: {}".format(input2_level))
  print("input_channel_3: {}".format(input3_level))
  print("input_channel_4: {}".format(input4_level))
  print("input_channel_5: {}".format(input5_level))
  print("input_channel_6: {}".format(input6_level))
  print("input_channel_7: {}".format(input7_level))
  print("input_channel_8: {}".format(input8_level))
#  print "-----"
time.sleep(0.1)

close()

GPIO.cleanup()
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

rccardany
Posts: 14
Joined: Wed May 22, 2019 4:27 pm

Re: AD Wandler MCP 3008

Fri Jun 07, 2019 8:18 pm

Danke für die Hilfreiche Antwort!!
Das hat super funktioniert.

Bei der Weiterentwicklung sollen nun mehrere MCP3008 ADWandler zum Einsatz kommen.
Die Idee war jedem einen eigenen CS Pin zuzuweisen und diese dann bei der jeweiligen abfrage entsprechend anzusprechen.
Leider bekomme ich es noch nicht hin den CS Pin vom GPIO8 zu verschieben. Weiß jemand woran das liegt?

Code: Select all

import spidev
import time
import os
import RPi.GPIO as GPIO, time, os

GPIO.setmode(GPIO.BCM)
cs1 = 7
cs2 = 8

GPIO.setwarnings(False)
GPIO.setup(cs1, GPIO.OUT)
GPIO.setup(cs2, GPIO.OUT)

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1350000

# Function to read SPI data from MCP3008 chip
# Channel must be an integer 0-7
def ReadChannel1(channel):
  GPIO.output(cs1, True)
  GPIO.output(cs2, False)
  adc = spi.xfer([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data
  def ReadChannel2(channel):
  GPIO.output(cs1, False)
  GPIO.output(cs2, True)
  adc = spi.xfer([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

# Define sensor channels
# (channels 3 to 7 unused)
vr1_channel = 0
vr2_channel = 1
vr3_channel = 2
vr4_channel = 3
vr5_channel = 4
vr6_channel = 5
vr7_channel = 6
vr8_channel = 7

# Define delay between readings (s)
delay = 3

while True:

  # Read the joystick position data
  vr11_pos = ReadChannel1(vr1_channel)
  vr12_pos = ReadChannel1(vr2_channel)
  vr13_pos = ReadChannel1(vr3_channel)
  vr14_pos = ReadChannel1(vr4_channel)
  vr15_pos = ReadChannel1(vr5_channel)
  vr16_pos = ReadChannel1(vr6_channel)
  vr17_pos = ReadChannel1(vr7_channel)
  vr18_pos = ReadChannel1(vr8_channel)

  vr21_pos = ReadChannel2(vr1_channel)
  vr22_pos = ReadChannel2(vr2_channel)
  vr23_pos = ReadChannel2(vr3_channel)
  vr24_pos = ReadChannel2(vr4_channel)
  vr25_pos = ReadChannel2(vr5_channel)
  vr26_pos = ReadChannel2(vr6_channel)
  vr27_pos = ReadChannel2(vr7_channel)
  vr28_pos = ReadChannel2(vr8_channel)

  # Print out results
  print "----------------update----------------------"
  print("1 : {}".format(vr11_pos))
  print("2 : {}".format(vr12_pos))
  print("3 : {}".format(vr13_pos))
  print("4 : {}".format(vr14_pos))
  print("5 : {}".format(vr15_pos))
  print("6 : {}".format(vr16_pos))
  print("7 : {}".format(vr17_pos))
  print("8 : {}".format(vr18_pos))
  print "--------------------------------------------"
  print("1 : {}".format(vr21_pos))
  print("2 : {}".format(vr22_pos))
  print("3 : {}".format(vr23_pos))
  print("4 : {}".format(vr24_pos))
  print("5 : {}".format(vr25_pos))
  print("6 : {}".format(vr26_pos))
  print("7 : {}".format(vr27_pos))
  print("8 : {}".format(vr28_pos))

  # Wait before repeating loop
  time.sleep(delay)
GPIO.cleanup()



User avatar
mline
Posts: 1283
Joined: Sun Jan 27, 2013 1:47 pm
Location: Austria, Vienna

Re: AD Wandler MCP 3008

Fri Jun 07, 2019 10:08 pm

Bei def Readchannel2 hast du einen Fehler. Es fehlt eine Leerzeile zwischen return und der nachfolgenden Funktionsdefinition. Ausserdem ist def Readchannel2 eingerückt. Das sollte nicht eingerückt sein.

Dann wird CS auch noch mit einem LOW aktiviert (siehe Manual, der Pin ist im Chip negiert) und mit HIGH wieder deaktiviert. Willst du mehrere Abfragen am selben chip hintereinander durchführen, musst du den CS Pin wohl kurz toggeln (siehe Manual für die Mindestzeit des Pulses).
<~~>

rccardany
Posts: 14
Joined: Wed May 22, 2019 4:27 pm

Re: AD Wandler MCP 3008

Sat Jun 08, 2019 12:07 pm

danke für deine Antwort aber leider verstehe ich nicht ganz wo das Problem ist. (Das Skript kommt nicht von mir ist nur angepasst.)
Selbst verstehe ich leider wenig vom programmieren :(

aber mit meinem Halbwissen dachte ich reicht es einmalig den Pin auf Low (Rest auf HIGH) zu stellen. Warum ist das nicht so ?

User avatar
mline
Posts: 1283
Joined: Sun Jan 27, 2013 1:47 pm
Location: Austria, Vienna

Re: AD Wandler MCP 3008

Sat Jun 08, 2019 8:41 pm

rccardany wrote:
Sat Jun 08, 2019 12:07 pm
danke für deine Antwort aber leider verstehe ich nicht ganz wo das Problem ist. (Das Skript kommt nicht von mir ist nur angepasst.)
Selbst verstehe ich leider wenig vom programmieren :(
Wurde dann wohl beim Kopieren verändert.
Bei C++ zB wäre das einrücken egal. Bei python aber ist es ein elementarer Bestandteil der Funktion. Ist da was nicht korrekt, funktioniert das Script auch nicht.
Daher empfehle ich dir erstmal die Grundlagen für python zu lernen.
aber mit meinem Halbwissen dachte ich reicht es einmalig den Pin auf Low (Rest auf HIGH) zu stellen. Warum ist das nicht so ?

Da solltest du einen Blick in das Handbuch werfen. Da steht genau beschrieben welche Signale an welchen Pins anliegen müssen damit es klappt
<~~>

pcmanbob
Posts: 6248
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: AD Wandler MCP 3008

Sun Jun 09, 2019 7:32 am

Wenn Sie sich diesen Thread ansehen, erfahren Sie, wie Sie mit ceo und ce1 2 MCP3008 auf einem einzelnen Pi verwenden

viewtopic.php?t=148001
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

rccardany
Posts: 14
Joined: Wed May 22, 2019 4:27 pm

Re: AD Wandler MCP 3008

Sun Jun 09, 2019 2:03 pm

Danke für die Unterstützung
Inzwischen konnte ich etwas näher an den Ursprung meines Problems kommen.
Die ganze Zeit war das Problem, dass ich lediglich für AD Wandler 1 eine plausieble Rückmelduung bekommen habe.

Da ich zuvor folgende Belegung hatte
AD Wandler 1: CH1 zum Test belegt mit Spannungsteiler - Rest frei
AD Wandler 2: CH3 zum Test belegt mit Spannungsteiler - Rest frei
dachte ich eigentlich, dass ich den gesamten AD Wandler 2 nicht ansprechen kann.

Nachdem ich nun auch den CH1 vom AD Wandler 2 belegt habe, konnte ich feststellen, dass die Abfrage der jeweils 1. Channel funktioniert. NIcht jedoch die der weiteren.

Habt ihr eine Ahnung woran das liegt?

Hier der aktuelle Code

Code: Select all

import spidev
import time
import os
import RPi.GPIO as GPIO, time, os

#Setup GPIO
GPIO.setmode(GPIO.BCM)
cs1 = 5
cs2 = 6

GPIO.setup(cs1, GPIO.OUT)
GPIO.setup(cs2, GPIO.OUT)

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

# Function to read SPI data from MCP3008 chip 1
# Channel must be an integer 0-7
def ReadChip1(channel):
 GPIO.output(cs2, True)
 GPIO.output(cs1, False)
 adc = spi.xfer([1,(8+channel)<<4,0])
 data = ((adc[1]&3) << 8) + adc[2]
 return data

# Function to read SPI data from MCP3008 chip 2
# Channel must be an integer 0-7
def ReadChip2(channel):
 GPIO.output(cs1, True)
 GPIO.output(cs2, False)
 adc = spi.xfer([1,(8+channel)<<4,0])
 data = ((adc[1]&3) << 8) + adc[2]
 return data

# Define sensor channels - ReadChip1
input1 = 0
input2 = 1
input3 = 2
input4 = 3
input5 = 4
input6 = 5
input7 = 6
input8 = 7

# Define sensor channels - ReadChip2
input9 = 0
input10 = 1
input11 = 2
input12 = 3
input13 = 4
input14 = 5
input15 = 6
input16 = 7

while True:

 # Read input data each Channel
 time.sleep(1)
 input1_level = ReadChip1(input1)
 input2_level = ReadChip1(input2)
 input3_level = ReadChip1(input3)
 input4_level = ReadChip1(input4)
 input5_level = ReadChip1(input5)
 input6_level = ReadChip1(input6)
 input7_level = ReadChip1(input7)
 input8_level = ReadChip1(input8)

 time.sleep(1)
 input9_level = ReadChip2(input9)
 input10_level = ReadChip2(input10)
 input11_level = ReadChip2(input11)
 input12_level = ReadChip2(input12)
 input13_level = ReadChip2(input13)
 input14_level = ReadChip2(input14)
 input15_level = ReadChip2(input15)
 input16_level = ReadChip2(input16)

 print("GPIO Pin: {}--------------------------------".format(cs1))
 print("input_channel_1: {}".format(input1_level))
 print("input_channel_2: {}".format(input2_level))
 print("input_channel_3: {}".format(input3_level))
 print("input_channel_4: {}".format(input4_level))
 print("input_channel_5: {}".format(input5_level))
 print("input_channel_6: {}".format(input6_level))
 print("input_channel_7: {}".format(input7_level))
 print("input_channel_8: {}".format(input8_level))
 time.sleep(2)
 print("GPIO Pin: {}--------------------------------".format(cs2))
 print("input_channel_9: {}".format(input9_level))
 print("input_channel_10: {}".format(input10_level))
 print("input_channel_11: {}".format(input11_level))
 print("input_channel_12: {}".format(input12_level))
 print("input_channel_13: {}".format(input13_level))
 print("input_channel_14: {}".format(input14_level))
 print("input_channel_15: {}".format(input15_level))
 print("input_channel_16: {}".format(input16_level))
 time.sleep(2)

GPIO.cleanup()

pcmanbob
Posts: 6248
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: AD Wandler MCP 3008

Sun Jun 09, 2019 3:48 pm

Entschuldigung, aber Google Translate ist fehlgeschlagen. Ich glaube, Sie fragen, wie alle 8 Eingaben auf 2 MCP3008 gelesen werden sollen
mit CE0 und CE1
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

rccardany
Posts: 14
Joined: Wed May 22, 2019 4:27 pm

Re: AD Wandler MCP 3008

Sun Jun 09, 2019 5:27 pm

glücklicherweise habe ich nun auch das lösen können. (musste den entsprechenden GPIO Pin resetten)
Siehe Skript: (Die entsprechenden Stellen habe ich gekennzeichnet.

Code: Select all

import spidev
import time
import os
import RPi.GPIO as GPIO, time, os

#Setup GPIO
GPIO.setmode(GPIO.BCM)
cs1 = 5
cs2 = 6

GPIO.setup(cs1, GPIO.OUT)
GPIO.setup(cs2, GPIO.OUT)

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 1000000

# Function to read SPI data from MCP3008 chip 1
# Channel must be an integer 0-7
def ReadChip1(channel):
 GPIO.output(cs1, True) NEU MIT IN DEN CODE AUFGENOMMEN
 GPIO.output(cs2, True)
 GPIO.output(cs1, False)
 adc = spi.xfer([1,(8+channel)<<4,0])
 data = ((adc[1]&3) << 8) + adc[2]
 return data

# Function to read SPI data from MCP3008 chip 2
# Channel must be an integer 0-7
def ReadChip2(channel):
 GPIO.output(cs2, True) NEU MIT IN DEN CODE AUFGENOMMEN
 GPIO.output(cs1, True)
 GPIO.output(cs2, False)
 adc = spi.xfer([1,(8+channel)<<4,0])
 data = ((adc[1]&3) << 8) + adc[2]
 return data

# Define sensor channels - ReadChip1
input1 = 0
input2 = 1
input3 = 2
input4 = 3
input5 = 4
input6 = 5
input7 = 6
input8 = 7

# Define sensor channels - ReadChip2
input9 = 0
input10 = 1
input11 = 2
input12 = 3
input13 = 4
input14 = 5
input15 = 6
input16 = 7

while True:

 # Read input data each Channel
 time.sleep(1)
 input1_level = ReadChip1(input1)
 input2_level = ReadChip1(input2)
 input3_level = ReadChip1(input3)
 input4_level = ReadChip1(input4)
 input5_level = ReadChip1(input5)
 input6_level = ReadChip1(input6)
 input7_level = ReadChip1(input7)
 input8_level = ReadChip1(input8)

 time.sleep(1)
 input9_level = ReadChip2(input9)
 input10_level = ReadChip2(input10)
 input11_level = ReadChip2(input11)
 input12_level = ReadChip2(input12)
 input13_level = ReadChip2(input13)
 input14_level = ReadChip2(input14)
 input15_level = ReadChip2(input15)
 input16_level = ReadChip2(input16)

 print("GPIO Pin: {}--------------------------------".format(cs1))
 print("input_channel_1: {}".format(input1_level))
 print("input_channel_2: {}".format(input2_level))
 print("input_channel_3: {}".format(input3_level))
 print("input_channel_4: {}".format(input4_level))
 print("input_channel_5: {}".format(input5_level))
 print("input_channel_6: {}".format(input6_level))
 print("input_channel_7: {}".format(input7_level))
 print("input_channel_8: {}".format(input8_level))
 time.sleep(2)
 print("GPIO Pin: {}--------------------------------".format(cs2))
 print("input_channel_9: {}".format(input9_level))
 print("input_channel_10: {}".format(input10_level))
 print("input_channel_11: {}".format(input11_level))
 print("input_channel_12: {}".format(input12_level))
 print("input_channel_13: {}".format(input13_level))
 print("input_channel_14: {}".format(input14_level))
 print("input_channel_15: {}".format(input15_level))
 print("input_channel_16: {}".format(input16_level))
 time.sleep(2)

GPIO.cleanup()
Bleibt ein kleines letztes "Problem":
Die Werte der belegten CH sind plausiebel. Alle übrigen werde sind nicht auf 0 sondern irgend einem Wert und auch nicht immer gleich.
Gibts eventuell einen Tip, wie ich das lösen kann?

User avatar
mline
Posts: 1283
Joined: Sun Jan 27, 2013 1:47 pm
Location: Austria, Vienna

Re: AD Wandler MCP 3008

Sun Jun 09, 2019 5:35 pm

rccardany wrote:
Sun Jun 09, 2019 2:03 pm
Habt ihr eine Ahnung woran das liegt?
Wie bereits erwähnt, vermute ich, dass du nach dem lesen der 10 Bits (oder davor) einmal den CS Pin togglen musst, da du sonst irgendwann nur Nullen zurückbekommst.

Seite 19 im Manual:
If all 10 databits have been transmitted and the device continues to receive clocks while the CS is held low, the device will output the conversion result LSB first, as is shown in Figure 5-2. If more clocks are provided to the device while CS is still low (after the LSB first data has been transmitted), the device will clock out zeros indefinitely.
rccardany wrote:
Sun Jun 09, 2019 5:27 pm
Bleibt ein kleines letztes "Problem":
Die Werte der belegten CH sind plausiebel. Alle übrigen werde sind nicht auf 0 sondern irgend einem Wert und auch nicht immer gleich.
Gibts eventuell einen Tip, wie ich das lösen kann?

Das ist bei ADCs normal und kannst du nur vermeiden indem du ein definiertes Level bereitstellst (pullup/pulldown Widerstand) oder per Software auf plausible Werte prüfst ( -> Wert kann sich in einem bestimmten Zeitrahmen nur um einen bestimmten Wert ändern)
<~~>

rccardany
Posts: 14
Joined: Wed May 22, 2019 4:27 pm

Re: AD Wandler MCP 3008

Mon Jun 10, 2019 7:54 am

ich habe es jetzt so gelößt, dass ich alle nicht belegten Channel mittel Jumper gegen GND lege.
Funktioniert einwandfrei. :)

Return to “Deutsch”