- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: I2C - ein Buch mit 7 Siegeln :( [verbinden 2er Controller]

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.01.2008
    Ort
    Siegen, Germany, Germany
    Beiträge
    441

    I2C - ein Buch mit 7 Siegeln :( [verbinden 2er Controller]

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo zusammen,
    nach einigem hin und her habe ich mich nun doch entschlossen I²C zum verbinden meiner Controller zu verwenden. Ich schildere einfach nochmal kurz was genau ich vor habe.

    Derzeit besteht die Schaltung aus 2 Controllern:

    1 x Mega32 - soll der Master sein, Sensorenwerte kommen hier rein und werden in "Bewegung" umgesetzt.

    1 x Mega8 - Dient zur Motorsteuerung, demnach müsste das ja der Slave sein.

    Der Mega32 soll dem Mega8 nun bestimmt Befehle senden z.B. "A1", der Mega8 weis nun was er zu tun hat z.B. vorwärts fahren.
    ---

    Nun schreib ich einfach mal eben auf, was ich bereits über I²C erfahren habe und hoffe, dass das der Richtigkeit entspricht.

    Ich weis bereits, dass es immer einen Master geben muss und mehrere Slaves geben kann, jede I²C Komponente hat eine bestimmte Adresse, mit der sie eindeutig angesprochen werden kann.

    Zum Schaltungsaufbau:
    Ich muss ja 2 Ports pro Controller zur Verfügung stellen für SDA und SCL, diese werden dann mit den Komponenten verbunden und über einen 1K Widerstand auf VCC gezogen? (sollte ich hier mist erzählen, bitte korrigieren )

    ---
    Kommen wir nun zu meiner eigentlichen Frage, wie zum Teufel programmiert man das nun In Bascom, wie sage ich welchem Controller wer Master und wer Slave ist, wie kann ich z.B. einen String senden und den beim anderen wieder empfangen?

    Ich weis, dass sich eine I²C Routine folgendermaßen aufbaut:

    Code:
    i2c_init 
    i2c_start 
    i2c_sendebyte(slaveid) 
    i2c_sendebyte(wert1) 
    i2c_sendebyte(wert2) 
    i2c_stop
    aber ich habe kA wie man das jetzt als sinnvolles Programm zusammen setzt.

    Bin für jede Art von Hilfe sehr dankbar, es gibt ja auch zu diesem Thema nicht wirklich gute Tutorials, habe zumindest keine gefunden, bis auf das hier im RN Wissen.

    LG
    Daniel

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hallo,

    der Teil zum Master ist in Bascom schon enthalten, gibt auch schon genug Beispiele überall dazu.
    Nur für I2C-Slave ist nichts enthalten, deshalb die etwas komplizierte Wiki-Seite um das selber hinzubekommen. Man könnte sich auch die Lib bei MCS kaufen um den Slave mit Basocm-internen Mitteln hinzubekommen, damit hab ich aber keine Erfahrung

    Um mehrere Zeichen zu übertragen, musst Du dir noch eine Art Protokoll überlegen, abgesehen vom Start/Stop usw. damit der Slave weiss was auf ihn zu kommt. Als Beispiel könnte man die Beschreibungen der Boards für Motorsteuerungen hernehmen. Bei diesen ist die Anzahl der Bytes pro Übertragung meist festgelegt, und jedes Byte hat eine feste funktion, also Befehle oder Werte.
    Schau einfach mal in die Beschreibung vom RN-Motorcontrol, ist zumindest ein Ansatz.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    09.05.2007
    Beiträge
    202
    Hallo Daniel,

    du solltest (zumindest beim Slave) auf jeden Fall die Pins für SCL und SDA verwenden, die hardwaremäßig dafür vorgesehen sind.

    Folgender Code für einen Slave sollte funktionieren. Es wird z. B. der Buchstabe S oder X übertragen, gefolgt von einem weiteren Wert:

    Code:
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    'Subs deklarieren
    Declare Sub Twi_init_slave
    
    'SDA = pind.4 ; SCL = pind.5 (Hardware TWI)
    
    Waitms 100
    Call Twi_init_slave                                         ' TWI aktivieren
    
    Const Maxanzahlbyte = 2                                     ' Wenn mehr Zeichen kommen werden diese verworfen !
    Dim Messagebuf(maxanzahlbyte) As Byte
    Dim Anzahlbuf As Byte                                       ' Anzahl Zeichen die gesendet wurden
    Dim Neuemsg As Byte                                         ' zeigt an wenn eine neue Message gültig ist
    
    Dim Twi_control As Byte                                     ' Controlregister lokale kopie
    Dim Twi_status As Byte
    Dim Twi_data As Byte
    dim tmp as byte
    Const Slaveid = &H82                                        'Adresse für I2C
    
    
    Twi_data = 0
    Anzahlbuf = 0
    Neuemsg = 0
    
    Do
    
        ' schauen ob TWINT gesetzt ist
        Twi_control = Twcr And &H80                             ' Bit7 von Controlregister auslesen
    
        If Twi_control = &H80 Then
            Twi_status = Twsr And &HF8                          ' Status ->Bit3 bis Bit7
    
            Select Case Twi_status
    
                ' Slave Adress received, wir sind gemeint !
                Case &H60 :
                    Twcr = &B11000100                           ' TWINT löschen, erzeugt ACK
                    Anzahlbuf = 0
                    Neuemsg = 0                                 ' Flag für Message ungültig
    
                ' Byte mit ACK
                Case &H80 :
                    If Anzahlbuf < Maxanzahlbyte Then
                        Incr Anzahlbuf                          ' zähler +1
                        Messagebuf(anzahlbuf) = Twdr
                    End If
                    Twcr = &B11000100                           ' TWINT löschen, erzeugt ACK
    
                ' Stop oder restart empfangen
                Case &HA0 :
                    Twcr = &B11000100                           ' TWINT löschen, erzeugt ACK
                    ' es müssen 2 Byte sein, damit das Paket OK ist
                    If Anzahlbuf = 2 Then
                        Neuemsg = 1                             ' Flag für Message gültig
                    Else
                        Neuemsg = 0                             ' Flag für Message ungültig
                    End If
                'Master will ein Byte haben
                Case &HA8:
                     Twdr = Vers
                     Twcr = &B11000100
                'Master will weiteres Byte haben
                Case &HB8:
                     'TWDR = Count
                     'incr Count
                     'Twcr = &B11000100
                ' letztes Byte mit NACK, brauchen wir nicht
                Case &H88 :
                Case &HF8 :
                ' Fehler, dann reset TWI
                Case &H00 :
                    Twcr = &B11010100                           ' TWINT löschen, reset TWI
                ' was anderes empfangen, sollte nicht vorkommen
                Case Else :
                    Twcr = &B11000100                           ' TWINT löschen, erzeugt ACK
    
            End Select
    
        End If
    
        ' ein gültiges Paket angekommen
        If Neuemsg = 1 Then
            Neuemsg = 0                                         ' Flag wieder löschen
            Select Case Messagebuf(1)
                      Case "S":
                      Tmp = Messagebuf(2)
                      'Mache etwas damit
                      
                      Case "X":
                      Tmp = Messagebuf(2)
                      'Mache etwas anderes
                  Case Else:
            End Select
        Waitms 100
        End If
    
        Waitms 10
    
    Loop
    
    
    End
    
    
    ' TWI als slave aktivieren
    Sub Twi_init_slave
        Twsr = 0                                                ' status und Prescaler auf 0
        Twdr = &HFF                                             ' default
        Twar = Slaveid                                          ' Slaveadresse setzen
        Twcr = &B01000100                                       ' TWI aktivieren, ACK einschalten
    End Sub
    Gruß, Stefan

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    09.05.2007
    Beiträge
    202
    Mit dem Master sendest du einfach:

    Code:
       I2cstart
       I2cwbyte Slaveadr
       I2cwbyte &H58                                            '58 = X
       I2cwbyte Wert1
       I2cstop
    'oder 
       I2cstart                                                 
       I2cwbyte Slaveadr                                        
       I2cwbyte &H53                                            '53 = S
       I2cwbyte Wert2
       I2cstop
    SlaveAdr und SlaveId im Code für den Slave müssen natürlich identisch sein. Du kannst da eine beliebige Adresse verwenden. Lediglich bei den I2C-Bausteinen (PCF, PCA u. s. w) sind die Adressen vorgegeben.
    Gruß, Stefan

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.01.2008
    Ort
    Siegen, Germany, Germany
    Beiträge
    441
    Hallo StevieL,
    vielen Dank!! Dein Beitrag hat mir sehr geholfen, hab es damit hinbekommen und muss sagen, wenn man erstmal durch I2C durchgeblickt hat, ist es eine echt tolle Sache

    Ein Problem habe ich allerdings noch:

    Ich lese die UART Eingabe von einem Konsolen Programm mit der Funktion inkey() aus, da erhalte ich die Eingabe, also die Buchstaben im ASCII Format, soweit ich weis. Wie kann ich diese Eingabe nun kompatibel zum senden mit I2C machen, da brauche ich das im ? Hex Format ?

    Gibt es da eine Funktion die mir das umrechnet? oder wie könnte man das lösen?

    Nochmal vielen Dank für deine Hilfe!

    LG
    Daniel

    "Update"
    Sehe grade die Funktion inkey() gibt nur den ASCII Wert an.
    z.B.: X = 88, S = 83
    hmm

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    09.05.2007
    Beiträge
    202
    Hallo Daniel,

    ob du das als Hexwert, Binärwert oder sonstwie hast, spielt ja keine Rolle. Dein Slave muss nur wissen, auf welchen Wert er wie reagieren muss. Der Code, den ich gepostet habe, ist ein Programm von mir, da habe ich nur ein paar Sachen rausgelöscht. Vollständig ist das:
    Code:
    Select Case Messagebuf(1)
                   Case "S":
                      Tmp = Messagebuf(2)
                      If Tmp <> Portstate Then 'liegt der Wert so schon an?
                         Portd = Tmp
                         Portstate = Tmp
                      End If
                   Case "X":
                      Tmp = Lookup(messagebuf(2) , Prozente) 'Werte aus Tabelle holen
                      Pwm1a = Tmp
                      Pwm1b = Tmp
                  Case Else:
            End Select
    In diesem Teil werden ja die beiden gesendeten Bytes ausgewertet. Abhängig vom ersten Byte wird der Wert des zweiten Bytes umgesetzt. Ob man da jetzt Case "S" schreibt oder Case 88 ist Wurst. Mein Beispiel verwende ich für eine Lampensteuerung, die in meine Aquarienbeleuchtung eingebaut ist. Wenn "S" gesendet wird, wird das nächste Byte ausgewertet und auf den Port D gelegt. Hiermit werden die Vorschaltgeräte mehrerer Leuchtstoffröhren ein- oder ausgeschaltet. Wird ein "X" gesendet und danach ein Wert zwischen 0 und 100 (=Prozent) werden zwei Vorschaltgeräte über PWM angesteuert und sorgen für die Dimmung.

    Edit: Das Grundgerüst des Programm stammt natürlich aus der RN-Wiki!
    Gruß, Stefan

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.01.2008
    Ort
    Siegen, Germany, Germany
    Beiträge
    441
    Ok danke, dann habe ich es verstanden, das mit dem zweiten Byte hatte ich in meinem Programm auch schon so gemacht.

    1. Byte sagt dem Mega8 worum es eigentlich geht, z.B. Geschwindigkeit und das 2. Byte gibt den Wert der Geschwindigkeit an.

    Nochmal vielen Dank!

    LG
    Daniel

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.01.2008
    Ort
    Siegen, Germany, Germany
    Beiträge
    441
    Hallo habe doch nochmal eine Frage zum Thema.

    Bin jetzt auf folgendes Problem gestoßen, bei den I2C Modulen (nehmen wir zum Beispiel mal das Kompassmodul CMPS03) sende ich dem Modul (da ist ja auch ein MC auf dem Board) ein bestimmtes Byte und bekomme dann den entsprechenden Wert zurück (in diesem Beispiel die Himmelsrichtung) wie lässt sich so etwas nun wieder realisieren, ich dachte bei der ganzen Sache wird nur eine Übertragung zum Slave durchgeführt, wie aber kommen nun die Daten aus dem Slave zum Master?

    Wenn ich meinem Motorsteuerungsboard z.B. jetzt eine Firmware Version gebe und ich möchte die per I2C auslesen, wie müsste ich da vorgehen? Muss ich den Master da dann auch als "Slave" programmieren, so dass der auch empfangen kann und den Slave als "Master"... ich bin mal wieder sehr verwirrt - schwieriges Thema, dieses I2C

    Bin wieder für Tipps sehr dankbar.

    LG und frohe Ostern
    Daniel Weber

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    09.05.2007
    Beiträge
    202
    Hi,

    schau dir doch mal in der Bascom-Hilfe die I2C-Befehle an. Da wirst du auch Befehle zum Lesen finden.

    Dann schaust du mal im Code des Slaves bei

    Code:
    'Master will ein Byte haben
             Case &HA8:
                     Twdr = Vers
                     Twcr = &B11000100
                'Master will weiteres Byte haben
                Case &HB8:
                     TWDR = Count
                     incr Count
                     Twcr = &B11000100
    Vers ist bei mir eine Konstante, die die aktuelle Firmwareversion beinhaltet.
    Gruß, Stefan

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.01.2008
    Ort
    Siegen, Germany, Germany
    Beiträge
    441
    Hallo,
    vielen Dank für deine Antwort, habe mir das in der Hilfe nochmal angeschaut und festgestellt, dass ich das "r" in I2crbyte total überlesen habe

    Naja habe dann mal versucht anhand der Beispiele aus dem RN Wissen und der Bascom Hilfe einen Code auf die Beine zu stellen, leider liest der Master bei mir immer 255 aus.

    Habe das so versucht:

    Master:
    Code:
    Function Mc_firmware() As Byte
    Local Firmware As Byte
    Local Slaveid As Byte
    Local Slaveid_read As Byte
    Slaveid = &H82
    Slaveid_read = &HA8
    
    
    I2cstart                                                    
    I2cwbyte Slaveid                                            'slave adsress
    I2cwbyte 0                                                   'aus dem Beispiel
    I2cstart                                                    'repeated start
    I2cwbyte Slaveid_read                                       'slave address (read) weis nicht genau was da hinkam, hatte gedacht '&HA8'
    I2crbyte Firmware , Nack                                    'read byte
    I2cstop
    
    
    
    
       Mc_firmware = Firmware
    
    
    End Function
    das ganze versuche ich dann mit Print "Aktueller Version" ; Mc_firmware()
    auszulesen, bekomme aber wie gesagt immer den Wert 255.

    Bin ich überhaupt auf dem richtigen Weg?? wie kommt man auf die slaveid_read?

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test