A/D mcp3424 I2C

Fragen zu Raspberry, FritzBox, Microcontroller, UART, etc...
Antworten
tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

A/D mcp3424 I2C

Beitrag von tgreif » Do 31. Mär 2016, 17:39

Hallo an alle , ich bin ein weiterer neuer, mit einem hoffentlich kleinem problem .
ich wuerde gerne ein A/D ueber di I2C Schnittstelle ansteuern. di Kommunikation selbst funktioniert schon . das mcp3424 wird mit dem befehl "i2cdetect -y 1" mit der Adresse 0x68 erkannt.
leider habe ich absolut keine Ahnung wie ich jetzt mit Gambas die werte auslesen.
hat einer von euch schon ein kleines Programm ??? gibt es eine Beispielanwendung unter Gambas??

danke im voraus

tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tgreif » Mo 4. Apr 2016, 21:35

hallo an alle .

ich habe mitlerweile die werte mit pyton auslesen koennen .

soweit so gut .
leider habe ich aber immer noch keine loesung in gambas gefunden .

Frigo2010
Foriker
Beiträge: 12
Registriert: Sa 13. Feb 2016, 08:30
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von Frigo2010 » Di 5. Apr 2016, 10:59

Hallo

Ich weiß zwar nicht was du genau machen möchtest, aber eventuell hilft dir das hier weiter

http://www.strippenstrolch.de/5-5-2-RS2 ... ambas.html


Gruß

Frigo

PS: https://www.google.de/search?q=i2c+gambas&oq=i2c+gambas

tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tgreif » Mi 6. Apr 2016, 18:21

hallo Frigo2010

danke fuer den tip . werd mal durchschauen ob es mir hilft.
im prinzip moecte ich an den i2c bus ein ad wandler mit 4 kanaelen haengen , und dann die ausgelesenen werte im programm weiterverarbeiten.
im moment benutze ich python und kann mitlerweile die kanaele auslesen . das python program starte ich in gambas mit dem exec befehl und uebergebe dann die werte der 4 kanaele an 4 verschiedene textboxen. dafuer benutze ich di python files von ABelectronics
git clone https://github.com/abelectron ... raries.git
:

Code: Alles auswählen

Dim ttx As String
TextBox6.text = TextBox6.text + Str(1) 
   
Exec ["python", "/home/pi/Scaricati/ABElectronics_Python3_Libraries-master/ADCPi/demo-readvoltage.py", "-p"] To ttx

''auslesen der werte und in text box anzeigen
TextBox1.text = Mid(ttx, 1, 8)  'chanel 1
TextBox2.text = Mid(ttx, 10, 9) 'chanel 2
TextBox3.text = Mid(ttx, 19, 9) 'chanel 3
TextBox4.text = Mid(ttx, 28, 9) 'chanel 4

End
allerdings waere es schoen wenn ich mit gambas die werte der analogeingange direkt auslesen koente , damit ich nicht ein externes programm starten muss.

tux_
Moderator
Beiträge: 950
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tux_ » Mi 6. Apr 2016, 18:51

Wenn du dafuer schon eine Extra-Bibliothek in Python hast, dann bist du doch in der gluecklichen Situation, sie nur noch auf Gambas umschreiben zu muessen. Ich kann zwar kein Python, aber es sieht so aus, als muesstest du nur die Klasse ADCPi[1] portieren. Nach kurzem Druebersehen scheint der Code recht geradlinig zu sein. Fuer i2c kannst du vielleicht einfach Dateien in /dev verwenden[2]. In Gambas sind hierbei die Instruktionen Open, Read, Write und Seek[3] relevant.

[1] https://github.com/abelectronicsuk/ABEl ... E_ADCPi.py
[2] https://www.kernel.org/doc/Documentatio ... -interface
[3] http://gambaswiki.org/wiki/cat/stream
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tgreif » Mi 6. Apr 2016, 20:20

hallo tux danke fuer die antwort.
das script [1] https://github.com/abelectronicsuk ... E_ADCPi.py soll( so glaube ich) nur die konfiguration uebernehmen.
das eigentliche auslesen der werte wird mit diesen code gestartet. python3 code
#!/usr/bin/python3
from ABE_ADCPi import ADCPi
from ABE_helpers import ABEHelpers
import time
import os
"""================================================
ABElectronics ADC Pi 8-Channel ADC demo
Version 1.0 Created 29/02/2015
Requires python 3 smbus to be installed
run with: python3 demo-read_voltage.py
================================================
Initialise the ADC device using the default addresses and sample rate,
change this value if you have changed the address selection jumpers
Sample rate can be 12,14, 16 or 18
"""
i2c_helper = ABEHelpers()
bus = i2c_helper.get_smbus()
adc = ADCPi(bus, 0x68, 18)
    #while (True):
    # clear the console
     #os.system('clear')

    # read from adc channels and print to screen
print ("%02f" % adc.read_voltage(1))
print ("%02f" % adc.read_voltage(2))
print ("%02f" % adc.read_voltage(3))
print ("%02f" % adc.read_voltage(4))
    #print ("Channel 5: %02f" % adc.read_voltage(5))
    #print ("Channel 6: %02f" % adc.read_voltage(6))
    #print ("Channel 7: %02f" % adc.read_voltage(7))
    #print ("Channel 8: %02f" % adc.read_voltage(8))

    # wait 0.5 seconds before reading the pins again
 #   time.sleep(0.8)
in dem ich sowohl die schleife als auch das lesen der eingaenge 5-8 kommentiert habe .
ich wuerde es auch gerne umschreiben , ich weis leider nicht wie das geht .... :?: :?: :?:
Zuletzt geändert von tux_ am Mi 6. Apr 2016, 20:57, insgesamt 1-mal geändert.
Grund: Bitte die hicode-Tags fuer Programm-Code verwenden.

tux_
Moderator
Beiträge: 950
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tux_ » Mi 6. Apr 2016, 20:59

Das ADCPi uebernimmt nicht nur die Konfiguration. Mit adc.read_voltage() werden in deinem Schnipsel die gewuenschten Werte gelesen und adc ist vom Typ ADCPi. Also steht in der Klasse ADCPi auch drin, wie man Werte aus dem Geraet ausliest.
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tgreif » Mi 6. Apr 2016, 22:34

hallo tux danke .
wenn ich das dann richtig verstanden habe , macht folgender code python3 code
print ("%02f" % adc.read_voltage(1))
dass die werte ausgelesenwerden und dann im terminal ausgegeben werden mit der formatierung wi angegeben. richtig?
und der folgende code ist nicht nur konfiguratio , sondern notwendig zum auslesen! richtig? (entschuldige meine unwissenheit , bin neu sowohl bei linux, gambas, und python)
versuche aber mein bestes.. versprochen python3 code
#!/usr/bin/python3

"""
================================================
ABElectronics ADC Pi V2 8-Channel ADC
Version 1.0 Created 29/02/2015
Requires python 3 smbus to be installed
================================================
"""


class ADCPi:
    # internal variables

    __address = 0x68  # default address for adc 1 on adc pi and delta-sigma pi
    __address2 = 0x69  # default address for adc 2 on adc pi and delta-sigma pi
    __config1 = 0x9C  # PGAx1, 18 bit, continuous conversion, channel 1
    __currentchannel1 = 1  # channel variable for adc 1
    __config2 = 0x9C  # PGAx1, 18 bit, continuous-shot conversion, channel 1
    __currentchannel2 = 1  # channel variable for adc2
    __bitrate = 18  # current bitrate
    __conversionmode = 1 # Conversion Mode
    __pga = float(0.5)  # current pga setting
    __lsb = float(0.0000078125)  # default lsb value for 18 bit

    # create byte array and fill with initial values to define size
    __adcreading = bytearray()
    __adcreading.append(0x00)
    __adcreading.append(0x00)
    __adcreading.append(0x00)
    __adcreading.append(0x00)

    global _bus

    # local methods

    def __updatebyte(self, byte, bit, value):
            # internal method for setting the value of a single bit within a
            # byte
        if value == 0:
            return byte & ~(1 << bit)
        elif value == 1:
            return byte | (1 << bit)

    def __checkbit(self, byte, bit):
            # internal method for reading the value of a single bit within a
            # byte
        bitval = ((byte & (1 << bit)) != 0)
        if (bitval == 1):
            return True
        else:
            return False

    def __twos_comp(self, val, bits):
        if((val & (1 << (bits - 1))) != 0):
            val = val - (1 << bits)
        return val

    def __setchannel(self, channel):
        # internal method for updating the config to the selected channel
        if channel < 5:
            if channel != self.__currentchannel1:
                if channel == 1:
                    self.__config1 = self.__updatebyte(self.__config1, 5, 0)
                    self.__config1 = self.__updatebyte(self.__config1, 6, 0)
                    self.__currentchannel1 = 1
                if channel == 2:
                    self.__config1 = self.__updatebyte(self.__config1, 5, 1)
                    self.__config1 = self.__updatebyte(self.__config1, 6, 0)
                    self.__currentchannel1 = 2
                if channel == 3:
                    self.__config1 = self.__updatebyte(self.__config1, 5, 0)
                    self.__config1 = self.__updatebyte(self.__config1, 6, 1)
                    self.__currentchannel1 = 3
                if channel == 4:
                    self.__config1 = self.__updatebyte(self.__config1, 5, 1)
                    self.__config1 = self.__updatebyte(self.__config1, 6, 1)
                    self.__currentchannel1 = 4
        else:
            if channel != self.__currentchannel2:
                if channel == 5:
                    self.__config2 = self.__updatebyte(self.__config2, 5, 0)
                    self.__config2 = self.__updatebyte(self.__config2, 6, 0)
                    self.__currentchannel2 = 5
                if channel == 6:
                    self.__config2 = self.__updatebyte(self.__config2, 5, 1)
                    self.__config2 = self.__updatebyte(self.__config2, 6, 0)
                    self.__currentchannel2 = 6
                if channel == 7:
                    self.__config2 = self.__updatebyte(self.__config2, 5, 0)
                    self.__config2 = self.__updatebyte(self.__config2, 6, 1)
                    self.__currentchannel2 = 7
                if channel == 8:
                    self.__config2 = self.__updatebyte(self.__config2, 5, 1)
                    self.__config2 = self.__updatebyte(self.__config2, 6, 1)
                    self.__currentchannel2 = 8
        return

    # init object with i2caddress, default is 0x68, 0x69 for ADCoPi board
    def __init__(self, bus, address=0x68, address2=0x69, rate=18):
        self._bus = bus
        self.__address = address
        self.__address2 = address2
        self.set_bit_rate(rate)

    def read_voltage(self, channel):
        # returns the voltage from the selected adc channel - channels 1 to
        # 8
        raw = self.read_raw(channel)
        if (self.__signbit):
            return float(0.0)  # returned a negative voltage so return 0
        else:
            voltage = float(
                (raw * (self.__lsb / self.__pga)) * 2.471)
            return float(voltage)

    def read_raw(self, channel):
        # reads the raw value from the selected adc channel - channels 1 to 8
        h = 0
        l = 0
        m = 0
        s = 0

        # get the config and i2c address for the selected channel
        self.__setchannel(channel)
        if (channel < 5):            
            config = self.__config1
            address = self.__address
        else:
            config = self.__config2
            address = self.__address2
            
        # if the conversion mode is set to one-shot update the ready bit to 1
        if (self.__conversionmode == 0):
                config = self.__updatebyte(config, 7, 1)
                self._bus.write_byte(address, config)
                config = self.__updatebyte(config, 7, 0)
        # keep reading the adc data until the conversion result is ready
        while True:
            
            __adcreading = self._bus.read_i2c_block_data(address, config, 4)
            if self.__bitrate == 18:
                h = __adcreading[0]
                m = __adcreading[1]
                l = __adcreading[2]
                s = __adcreading[3]
            else:
                h = __adcreading[0]
                m = __adcreading[1]
                s = __adcreading[2]
            if self.__checkbit(s, 7) == 0:
                break

        self.__signbit = False
        t = 0.0
        # extract the returned bytes and combine in the correct order
        if self.__bitrate == 18:
            t = ((h & 0b00000011) << 16) | (m << 8) | l
            self.__signbit = bool(self.__checkbit(t, 17))
            if self.__signbit:
                t = self.__updatebyte(t, 17, 0)

        if self.__bitrate == 16:
            t = (h << 8) | m
            self.__signbit = bool(self.__checkbit(t, 15))
            if self.__signbit:
                t = self.__updatebyte(t, 15, 0)

        if self.__bitrate == 14:
            t = ((h & 0b00111111) << 8) | m
            self.__signbit = self.__checkbit(t, 13)
            if self.__signbit:
                t = self.__updatebyte(t, 13, 0)

        if self.__bitrate == 12:
            t = ((h & 0b00001111) << 8) | m
            self.__signbit = self.__checkbit(t, 11)
            if self.__signbit:
                t = self.__updatebyte(t, 11, 0)

        return t

    def set_pga(self, gain):
        """
        PGA gain selection
        1 = 1x
        2 = 2x
        4 = 4x
        8 = 8x
        """

        if gain == 1:
            self.__config1 = self.__updatebyte(self.__config1, 0, 0)
            self.__config1 = self.__updatebyte(self.__config1, 1, 0)
            self.__config2 = self.__updatebyte(self.__config2, 0, 0)
            self.__config2 = self.__updatebyte(self.__config2, 1, 0)
            self.__pga = 0.5
        if gain == 2:
            self.__config1 = self.__updatebyte(self.__config1, 0, 1)
            self.__config1 = self.__updatebyte(self.__config1, 1, 0)
            self.__config2 = self.__updatebyte(self.__config2, 0, 1)
            self.__config2 = self.__updatebyte(self.__config2, 1, 0)
            self.__pga = 1
        if gain == 4:
            self.__config1 = self.__updatebyte(self.__config1, 0, 0)
            self.__config1 = self.__updatebyte(self.__config1, 1, 1)
            self.__config2 = self.__updatebyte(self.__config2, 0, 0)
            self.__config2 = self.__updatebyte(self.__config2, 1, 1)
            self.__pga = 2
        if gain == 8:
            self.__config1 = self.__updatebyte(self.__config1, 0, 1)
            self.__config1 = self.__updatebyte(self.__config1, 1, 1)
            self.__config2 = self.__updatebyte(self.__config2, 0, 1)
            self.__config2 = self.__updatebyte(self.__config2, 1, 1)
            self.__pga = 4

        self._bus.write_byte(self.__address, self.__config1)
        self._bus.write_byte(self.__address2, self.__config2)
        return

    def set_bit_rate(self, rate):
        """
        sample rate and resolution
        12 = 12 bit (240SPS max)
        14 = 14 bit (60SPS max)
        16 = 16 bit (15SPS max)
        18 = 18 bit (3.75SPS max)
        """

        if rate == 12:
            self.__config1 = self.__updatebyte(self.__config1, 2, 0)
            self.__config1 = self.__updatebyte(self.__config1, 3, 0)
            self.__config2 = self.__updatebyte(self.__config2, 2, 0)
            self.__config2 = self.__updatebyte(self.__config2, 3, 0)
            self.__bitrate = 12
            self.__lsb = 0.0005
        if rate == 14:
            self.__config1 = self.__updatebyte(self.__config1, 2, 1)
            self.__config1 = self.__updatebyte(self.__config1, 3, 0)
            self.__config2 = self.__updatebyte(self.__config2, 2, 1)
            self.__config2 = self.__updatebyte(self.__config2, 3, 0)
            self.__bitrate = 14
            self.__lsb = 0.000125
        if rate == 16:
            self.__config1 = self.__updatebyte(self.__config1, 2, 0)
            self.__config1 = self.__updatebyte(self.__config1, 3, 1)
            self.__config2 = self.__updatebyte(self.__config2, 2, 0)
            self.__config2 = self.__updatebyte(self.__config2, 3, 1)
            self.__bitrate = 16
            self.__lsb = 0.00003125
        if rate == 18:
            self.__config1 = self.__updatebyte(self.__config1, 2, 1)
            self.__config1 = self.__updatebyte(self.__config1, 3, 1)
            self.__config2 = self.__updatebyte(self.__config2, 2, 1)
            self.__config2 = self.__updatebyte(self.__config2, 3, 1)
            self.__bitrate = 18
            self.__lsb = 0.0000078125

        self._bus.write_byte(self.__address, self.__config1)
        self._bus.write_byte(self.__address2, self.__config2)
        return
    
    def set_conversion_mode(self, mode):
        """
        conversion mode for adc
        0 = One shot conversion mode
        1 = Continuous conversion mode
        """
        if (mode == 0):
            self.__config1 = self.__updatebyte(self.__config1, 4, 0)
            self.__config2 = self.__updatebyte(self.__config2, 4, 0)
            self.__conversionmode = 0
        if (mode == 1):
            self.__config1 = self.__updatebyte(self.__config1, 4, 1)
            self.__config2 = self.__updatebyte(self.__config2, 4, 1)
            self.__conversionmode = 1
        #self._bus.write_byte(self.__address, self.__config1)
        #self._bus.write_byte(self.__address2, self.__config2)    
        return
Zuletzt geändert von tux_ am Do 7. Apr 2016, 08:04, insgesamt 1-mal geändert.
Grund: Bitte hicode- statt code-Tags verwenden

tux_
Moderator
Beiträge: 950
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tux_ » Do 7. Apr 2016, 08:19

und der folgende code ist nicht nur konfiguratio , sondern notwendig zum auslesen! richtig?
Ja, die Funktionen read_voltage() und read_raw() tun das.
(entschuldige meine unwissenheit , bin neu sowohl bei linux, gambas, und python)
versuche aber mein bestes.. versprochen
Das wusste ich nicht. An sich passiert dort auf der Python-Seite nicht viel auszer Bit-Operationen und Arithmetik. Beides gibt es in Gambas auch. Es koennte aber ein Problem sein, als Linux-Neuling an die I2C-Daten zu kommen. Wie du vielleicht siehst, besteht die Hauptarbeit von read_voltage() daraus, read_raw() aufzurufen. read_raw() wiederum ruft im wesentlichen nur self._bus.read_i2c_block_data(address, config, 4) auf (der Rest des Codes in der Funktion sind Rechnungen). Wenn ich mich nicht irre ist self._bus vom Typ SMBus, der wiederum hier[1] in C implementiert ist. Dort sieht man, dass die Python-Bibliothek auch nur mit Wasser kocht und das /dev-Interface verwendet, dessen Beschreibung ich dir gestern verlinkt habe.

Vielleicht finde ich heute abend auch etwas Zeit, zumindest den C-Code in Gambas zu uebersetzen.

[1] https://github.com/abelectronicsuk/ABEl ... usmodule.c
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

tux_
Moderator
Beiträge: 950
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tux_ » Do 7. Apr 2016, 18:11

Im Anhang ist ein Versuch, die SMBus-Klasse in Gambas zu schreiben. Beachte aber, dass ich den Code nicht getestet habe. Gar nicht. Ich habe nicht einmal ein RPi. Der Code koennte einfach funktionieren, er koennte abstuerzen, die CPU aufheizen oder sonstwas. Du arbeitest hier auszerdem an der haesslichsten Seite von Gambas: der Schnittstelle zu C-Bibliotheken bzw. zum Kernel. Die Alternative zu solchen Hacks wie im Anhang ist eine ordentliche I2C-Komponente fuer Gambas. Bisher hat sich dafuer wohl aber noch niemand ernsthaft interessiert. Deshalb gibt es sie nicht.
i2c-0.0.1.tar.gz
(12.21 KiB) 255-mal heruntergeladen
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tgreif » Do 7. Apr 2016, 20:42

hi tux
vielen dank .
ich werde sie gleichmal probieren und dir dann bescheid geben .

bis dann :)

tgreif
Foriker
Beiträge: 14
Registriert: Sa 12. Mär 2016, 14:59
Kontaktdaten:

Re: A/D mcp3424 I2C

Beitrag von tgreif » Fr 8. Apr 2016, 17:29

Hallo Tux .
habe das gestern ausprobiert. beim starten gibt es keine fehlermeldung.
werde diese tage mal sehen wie ich da weiter komme .
besten dank .
vielleicht erbamt sich ja mal einer daer das kann eine komponente fuer den i2c zu programmiere. ( nicht ein newbe wie ich)

bis dann

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast