PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RS232 to I2C Adapter von Robotikhardware



tobiokanobi
01.06.2009, 21:06
Hallo,

ich habe mir vor kurzem den RS232 to I2C Adapter von Robotikhardware zugelegt und hoffentlich richtig zusammengebaut ;-)

Nun meine Frage(n):

Zwar ist da ein Test-Programm dabei, da ich aber nicht unter Windows arbeite, ist es recht sinnlos für mich (auch daß VB Programm). Benötige ich noch eine zusätzliche Treiber Software (für den Adapter)? Wie spreche ich nun "den Adapter" an? Als RS232 oder I2C? (Damit meine ich, ich öffne ja den RS232 (ttyPL2303...)...

Weiß jemand einen Beispiel Code (in C, C++ ,...)

Ich habe folgende Konfiguration: iMAC -> USB to RS232 (PL2303) -> RS232 to I2C Adapter -> MotorController MD23

DANKE!

tobias

Jaecko
02.06.2009, 09:36
Also wenn es wirklich der gleiche Adapter ist, wie der den ich mal nachgebaut hab, ( http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=73&products_id=68 ) dann reichts, wenn man da mit den Steuerleitungen arbeitet. 2 davon sind für SCL/SDA-Ausgang, die anderen beiden für SCL/SDA-Eingang.

Und ob das mit dem USB-RS232-Wandler geht, hängt davon ab, ob das ein wirklich _gutes_ Teil ist oder nur so'n 1-Euro-Billigteil aus China, bei dem nur Rx und Tx durchgegeben sind.

tobiokanobi
04.06.2009, 11:46
Danke für die Antwort!

Vom Computer wird ja nur der serielle (rs232) Ausgang des Adapters erkannt und mit

/dev/tty.PL2303-XXXX

angelegt, aber nicht der dahintersteckende I2C Adapter erkannt (da dieser ja auch keine Driver Software besitzt).

Soll ich somit einfach den tty.PL2303-XXXX Port aufmachen und an diesen einfach die BusAdr, Daten,... senden und der I2C Adapter formatiert mir diese Daten dann einfach um?

Liebe Grüße,

Tobias

Jaecko
04.06.2009, 12:01
Der I2C-Adapter muss nicht erkannt werden. Du musst nur irgendwie (eigener Treiber oder eigene Software) den Pegel der Statusleitungen ändern bzw. überwachen. Und genau da kommt der Punkt, ob das Kabel eben Billigware ist (nur Rx/Tx und damit nutzlos, da diese Leitungen nicht benötigt werden) oder ob auch wirklich die Steuerleitungen verwendet werden.

Wenn ich mich jetzt am Schaltplan nicht verschaut habe, müsste das die folgende Belegung sein:
DTR: SDA "schreiben"
RTS: SCL "schreiben"
DSR: SDA "lesen"
CTS: SCL "lesen"

tobiokanobi
09.06.2009, 22:15
Danke, werde es probieren, habe es zur Zeit einmal anders gelöst.

Zum USB/RS232 Adapter: Es ist der der auch im Robotikhardwareshop verkauft wird.

Lg,

Tobias

Roberto
11.12.2009, 17:34
Hallo Leute.... schreibe mal gleich hier dazu....
Habe mir jetzt auch den I2C Adapter für die RS232 gebaut...
Signale gibt er aus.... nur scheinen mir die Signale nicht ganz zu stimmen...
Im Anhang ein Bild mit dem DSO aufgenommen, für Schreiben, in Adresse 5.
Mir scheint das da 8Bit für die Adresse verwendet werden stat 7 Bit.
(Bit 128 wird auch dargestellt)
Das R/W Bit scheint auch falsch zu sein?!
Beim R/W Bit sehe ich keinen Unterschied zwischen Lesen oder schreiben..?!
Oder sehe ICH da etwas falsch?
normal 7 Bit Adresse, 1Bit R/W(wobei 0= schreiben) und dann ein Ack-Bit.

Ich habe mal ins Programm geschaut. Mir scheint da gibt es aber nur 8Bit Adressierungen.?!

Hat jemand eine Idee/Tipp??

Danke

l.G. Roberto

Roberto
11.12.2009, 17:36
Bild nochmal.........................

Jaecko
11.12.2009, 17:50
Die Adresse ist immer 8 Bit. Das "unterste" Bit ist R/W.
D.h. wenn du Adresse 5 adressierst, dann adressiert du eigentlich Adr. 4 + Lesen-Bit.

Also vom Diagramm her les ich die Bits als: 0000 0101 1
D.h. Adr. 4 + Lesen Bit + NAK-Bit (d.h. das Gerät mit der Adresse 4 antwortet nicht bzw. ist nicht vorhanden.)

Roberto
11.12.2009, 18:40
Hallo Jaecko
Danke für die schnelle Antwort :-)

Habe aber Adresse 5! Also 0000 0101 (Als 8 Bit)
Nach meiner Meinung müsste das so ausschauen:

0000 101 = (7Bit Adresse)= 5, dann 0 für schreiben und 1 für NAck
Also: 0000 1010 1
Es scheint aber so auszuschauen: 0000 0101 1

Ein Lesen von Adresse 5 schaut z.B. so aus: --> Anhang
Müsste eigentlich so ausschauen: 0000 101 11
Schaut aber so aus: 0000 010 11

Bei Adresse 128 (die es normal gar nicht geben dürfte, wird das erste Bit gesetzt ? (=MSB)

l.G. Roberto
Ps: Tolle Projekte hast Du da auf deiner Home..!
Den Can-Bus muss ich mir auch mal vornehmen :-)

Ps.:
Ich werde es jetzt mal mit einem 24C32 probieren..

Jaecko
11.12.2009, 19:57
Beim I2C gibt es nur gerade Adressen. Das letzte Bit (also gerade oder ungerade) ist das R/W-Bit. Die übrigen 7 Bits werden ohne Shiften angegeben; d.h. Adresse 128 gibt es: 1000 000x. Es sind alle Adressen im Bereich 0, 2, 4, 6, ... 250, 252, 254 möglich (wobei 0 für General Call freigehalten werden sollte)

Also wenn du 0000 101x adressieren willst, dann ist das die Adresse 10 für schreiben, 11 für lesen. (0000 1010 binär = 10 Dezimal).
D.h. was die I2C-Hardware ausspuckt, stimmt schon. Du gibst Adresse 5 an (0000 0101) an, das Lesen-Bit wird gesetzt (ist aber schon 1, d.h. es bleibt bei 0000 0101) und die I2C-Hardware schickt an die eigentliche Adresse 4 einen Lese-Auftrag (+1).

Wenn im Datenblatt eines Geräts dann wirklich 0000 101 als Adresse angegeben ist, dann muss rechts noch das fehlende 8. Bit (R/W) angehängt werden.

Bei den 24C-EEPROMS sind die Adress-Bits z.B. 1010 A2 A1 A0 x.
D.h. die möglichen Adressen sind 0xA0, 0xA2, 0xA4, ... 0xAE (160, 162, 164,... 174).

Nachtrag: am CAN-Bus ist die Adressierung wieder etwas einfacher *g*. Da sinds 11 bzw. 29 Bit und nur diese für die Adresse. Also Adresse 5 ist da dann wirklich 000 0000 0101.

Roberto
11.12.2009, 20:35
Hallo Jaecko
Ja, du hast Recht...
Da war ja mal was mit lesen = +1
Durch die Binärzahlen hatte ich das ganz vergessen .

Ich hatte jetzt ein 24C EEProm angesprochen. (schreiben)
(EEprom noch nicht angehängt)

Adresse 160 mit einen Schreibwert von 000
Ergibt Binär: 1010 0000 0000 0000
161 ergibt das gleiche: 1010 0000 0000 0000 (wegen schreiben)
162 ergibt : 1010 0011 0000 0000 (falsch ?)
163 ergibt : 1010 0011 0000 0000 (falsch ?)
164 ergibt : 1010 0100 0000 0000
irgendwie fehlt da aber das NAck-Bit ??
Wenn ich dann schreibe
160 und 128: 1010 0000 1000 0000
dann zeiht mir das EEprom den 1er von 128er (2.Wert), gegen Masse!!!
Also zu : 1010 0000 0000 0000
(Adressleitungen vom EEprom sind alle auf Low. Also Adresse 160)

Und da ist auch die Adresse so beschrieben wie Du gemeint hast.
A0 ist das zweite Bit von dem ersten Byte :-(
Also ist A0 eigentlich A1 ?!

Ich habe den Code mal angehängt:


Option Strict Off
Option Explicit On
Imports Microsoft.VisualBasic.PowerPacks
Friend Class frmi2cmain
Inherits System.Windows.Forms.Form
'I2C-Bus realisiert an der PC RS232-Schnittstelle
'
'Über einen einfachen Adpater RN_PC->I2CBUS (siehe robotikhardware.de)
'können I2C-Bus LCD´s, Boards, Chips, Roboternetz-Baords jetzt
'auch über den PC angesteuert werden. Der Adapter wird einfach in
'den seriellen Port gesteckt. Wie üblich, können zahlreiche Busteilnehmer
'angeschlossen werden. Der I2C-Bus ist Steckerkompatibel zum üblichen
'Roboternetz-Standard
'Der I2C Bus Treiber liegt hier im Visual Basic Quellcode vor
'Wichtig sind die Funktionen:
'sub i2c_init()
'sub i2c_start()
'sub i2c_stop()
'subi2c_SendByte(wert As Byte)
'Function i2c_EmpfangeByte() As Byte
'
'Die Funktionen können ähnlich wie in Bascom verwendet werden:
'Beispielübertragung:
' i2c_init
' i2c_start
' i2c_sendebyte(slaveid)
' i2c_sendebyte(wert1)
' i2c_sendebyte(wert2)
' i2c_stop
'
'Dieses Programm demonstriert die Anwendung und stellt die Funktionen
'für eigene Anwendungen bereit
'Passenden Adapter gibts als Bausatz oder nur Platine übe robotikhardware.de
'Autor: Frank
' ---------------------------------------------------------------------------



Private Sub buttInit_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles buttInit.Click
LabelHinweis.Visible = True
i2c_init()
ZeigePegel()
End Sub

Private Sub buttReadbytes_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles buttReadbytes.Click
Dim i As Short
System.Diagnostics.Debug.Write("Empfange:")
buttReadbytes.Enabled = False
If slaveid.Text = "" Then
MsgBox("Eine Slave ID braucht man schon")
Exit Sub
End If
If Val(txtAnzahl.Text) > 5 Then
MsgBox("Es klappt im Demo nur mit 5 Zahlen")
Exit Sub
End If

For i = 0 To 4
txtEWert(i).Text = ""
Next

i2c_start()
i2c_SendByte(CByte(slaveid.Text))
delay()
For i = 0 To CDbl(txtAnzahl.Text) - 1
txtEWert(i).Text = CStr(i2c_EmpfangeByte)
delay()
If i < (CDbl(txtAnzahl.Text) - 1) Then
i2c_ack((True)) : Debug.Print("ack")
Else
i2c_ack((False)) : Debug.Print("no ack")
End If
delay()
Next i
i2c_stop()
buttReadbytes.Enabled = True
End Sub

Private Sub buttSCL_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles buttSCL.Click
Dim status As Boolean
status = MSComm1.CTSHolding 'SCL Eingang
set_scl((Not status)) 'SCL Ausgang
ZeigePegel()

End Sub

Private Sub buttSDA_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles buttSDA.Click
Dim status As Boolean
status = MSComm1.DSRHolding 'SDA Eingang
set_sda((Not status)) 'SDA Ausgang
ZeigePegel()
End Sub



Private Sub buttSendByte_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles buttSendByte.Click
Dim i As Short
buttSendByte.Enabled = False

i2c_start()
i2c_SendByte(CByte(txtwert(0).Text))
For i = 1 To 5
If txtwert(i).Text = "" Then Exit For
i2c_SendByte(CByte(txtwert(i).Text))
delay()
Next i
i2c_stop()

ZeigePegel()
buttSendByte.Enabled = True
End Sub


Private Sub frmi2cmain_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load

MSComm1.PortOpen = True
i2c_init()
ZeigePegel()
End Sub







'************************************************* ********
' I2C-Funktionen

'Initialisiert I2C Bus
'Muss nur einmal im Programm aufgerufen werdne
Sub i2c_init()
i2c_stop()
delay()
End Sub

Sub i2c_start()
Do
System.Windows.Forms.Application.DoEvents()
Loop Until (get_scl() = True) And (get_sda() = True) 'Warte bis Bus frei
set_sda((0))
delay()
set_scl((0))
delay()

End Sub

Sub i2c_stop()
set_sda((0))
set_scl((1))
stopa:
If get_scl() = 0 Then GoTo stopa
set_sda((1))
End Sub

Sub i2c_ack(ByRef ack As Boolean)
If ack = True Then
set_sda((0))
pulse()
Else
set_sda((1))
pulse()
delay()
End If
End Sub

Sub i2c_SendByte(ByRef wert As Byte)
Dim i As Short
Dim bitmask As Byte

bitmask = 128
For i = 1 To 7
set_sda((0))
If (wert And bitmask) > 0 Then
set_sda((1))
Else
set_sda((0))
End If
bitmask = bitmask / 2
delay()
pulse()
Next i
delay()
pulse()
delay()
End Sub

'Liest ein Byte vom I2C-Port
Function i2c_EmpfangeByte() As Byte
Dim i As Short
Dim bitmask As Byte

set_sda((1))

i2c_EmpfangeByte = 0
bitmask = 128
For i = 1 To 8

set_scl((1))
empanga:
If get_scl() = 0 Then GoTo empanga
If get_sda() = True Then
i2c_EmpfangeByte = i2c_EmpfangeByte Or bitmask
End If
bitmask = bitmask / 2
set_scl((0))
delay()
Next i
End Function



'Funktionen um Pegel bei SDA und SCL zu setzen oder zu lesen

Sub set_sda(ByRef zustand As Boolean)
MSComm1.DTREnable = zustand
End Sub

Sub set_scl(ByRef zustand As Boolean)
MSComm1.RTSEnable = zustand
End Sub

Function get_scl() As Boolean
get_scl = MSComm1.CTSHolding
End Function

Function get_sda() As Boolean
get_sda = MSComm1.DSRHolding
End Function

Sub pulse()
set_scl((1)) 'Clock High bedeutet Datenbyte liegt an
pulse1:
If get_scl() = 0 Then GoTo pulse1
set_scl((0)) 'Nur bei Null darf Datenbit auf Datenleitung gelegt werden
End Sub

'Kurze Pause, je nach Busgeschwindigkeit
Sub delay()
Dim i As Object
For i = 1 To 255
Next i
End Sub

'Funktion zeigt Pegel visuell in dem Fenster an
Sub ZeigePegel()
If get_sda = True Then 'Ist SDA High?
LabelSDAPegel.Text = "High"
ShapeSDA.FillColor = System.Drawing.ColorTranslator.FromOle(QBColor(10) )
Else
LabelSDAPegel.Text = "Low"
ShapeSDA.FillColor = System.Drawing.ColorTranslator.FromOle(QBColor(2))
End If

If get_scl() = True Then 'Ist SDA High?
LabelSCLPegel.Text = "High"
ShapeSCL.FillColor = System.Drawing.ColorTranslator.FromOle(QBColor(10) )
Else
LabelSCLPegel.Text = "Low"
ShapeSCL.FillColor = System.Drawing.ColorTranslator.FromOle(QBColor(2))
End If
End Sub






Private Sub frmi2cmain_FormClosed(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
set_sda((1))
set_scl((1))

End Sub

Private Sub MSComm1_OnComm(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MSComm1.OnComm

End Sub

Private Sub Frame2_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Frame2.Enter

End Sub

Private Sub Frame1_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Frame1.Enter

End Sub
End Class



l.G. Roberto

Ps.:
Lesen ergibt:

160 = 1010 0000 11111111
161 = 1010 0000 11111111
162 = 1010 0011 11111111
163 = 1010 0011 11111111
164 = 1010 0100 11111111

???

Jaecko
11.12.2009, 20:52
Also wenn bei dem EEPROM (24C32) alle Adress-Pins auf Masse liegen und du nur 0xA0 als Adresse sendest, müsste ein ACK zurückkommen. Wenn NAK kommt, gibts kein Gerät mit der Adresse (oder es ist defekt etc.)
162 = 1010 0011 stimmt dann, wenn du von 162 lesen willst.

Bei den I2C-EEPROMs wars von der Kommunikation her so:
Master: START senden
Master: Adresse "schreiben" senden (Schreiben, letztes Bit = 0)
Slave: ACK
Master: High-Adresse Speicherzelle
Slave: ACK
Master: Low-Adresse Speicherzelle
Slave: ACK
Master: (repeated) START
Master: Adresse "lesen" senden (letztes Bit = 1)
Slave: ACK + Byte in gewählter Speicherzelle
Master: ACK (wenn mehr Bytes gewünscht werden) oder NAK, wenns genug ist.
Master: STOP.

Wenn du nen Code in C brauchst, mit dem man solche EEPROMs schreibt/liest, sags einfach, dann stell ich die hier mal rein. Ist evtl. ne Hilfe.

Roberto
11.12.2009, 21:56
Hallo Jaecko
Frage:
Stimmst Du mir zu, dass die Binärwerte, die ich oben geschrieben habe, falsch sind ? (162 und 163)

Irgendwie fehlt mir da auch ein ACK-Bit ?

Bei Adresse 160 müsste ich doch haben: (schreiben)
1010 0000 1 0000 0000
Hatte aber nur:
1010 0000 0000 0000
Darum habe ich ja als zweites Byte ein 128 geschrieben, damit mir das EEprom diese 1 nach Masse ziehen kann, was es dann auch tut :-)

l.G.Robert Und Danke für die Infos :-)

Jaecko
11.12.2009, 22:05
Also 162 müsste 1010 0010 sein, nicht 1010 0011.
163 stimmt, 164 ebenfalls.

Ein ACK/NAK kriegst du in jedem Fall nach dem Adressbyte. Die Frage ist nur woher. Wenn als 9. Bit ne 0 kommt, hat irgendjemand auf die Adresse reagiert.
Du müsstest dir mal (sofern von der Auflösung her möglich) eine ganze I2C-Übertragung anschauen, also von START bis STOP.
Dann lässt sich recht einfach feststellen, ob irgendwo ein ACK-Bit fehlt bzw. was denn da eigentlich gesendet wird. Das blöde ist hier aber, dass man nicht sehen kann, wer sendet.

Und dass du beim Lesen 11111111 kriegst, liegt daran, dass der Leerlaufpegel des I2C gelesen wird (es ist ja niemand da, der SDA auf die entsprechenden richtigen Pegel setzt)

Roberto
11.12.2009, 22:24
Start und Stop sind vorhanden.

Bei dem Programm kann man eine Adresse eingeben und dann halt 1 bis 5 Daten-Byte
Beim Senden von der Adresse und einem Daten-Byte sind dann aber nur 16Bit :-(

Jaecko
12.12.2009, 16:02
Komisch irgendwie. Bei 2 gesendeten Bytes hätte ich 18 Bit erwartet.
Kannst du dem EEPROM mal 3 Datenbytes schicken und die Übertragung mal aufzeichnen und hier reinstellen?
Also 1 Adressbyte (0xA0 oder wie er adressiert ist) + 3 Daten z.B. 0x00, 0xAA, 0x55. Damit sollte der EEPROM den Wert 0x55 an die Adresse 0x00AA schreiben. Vielleicht sieht man da dann was auffälliges.

Steckt der Adapter bei dir direkt an nem echten COM-Port oder ist da ein USB-RS232-Wandler dazwischen?

Roberto
15.12.2009, 20:57
Hallo Jaecko

Habe inzwischen weiterprobiert.
Irgendwie muss ich mich wohl mit den Bit's verzählt haben... sind eh
18 Bit bei 2 Byte.

Habe das inzwischen auch so hinbekommen, dass das Programm beim Senden auch das Ack-Bit auf High setzt.
Anscheinend braucht es das aber gar nicht... Es schreibt da wohl blind raus ?!
Das mit dem Lesen, muss ich erst hinbekommen (EEprom)

Andere Frage:
Bei Slave-Adresse 0, müssten sich da alle Geräte mit dem Ack-Bit melden ?
Auch ein EEprom ?
Sehe da nix :-(

l.G. Robert

Jaecko
15.12.2009, 22:30
Das Ack-Bit muss Low für ACK sein; High-Level ist NAK (Leerlaufpegel)
Nach dem Start wird immer die Slave-Adresse gesendet, sofern der Bus frei ist. Erkennt der Master dann ein NAK (9. Bit high), sollte er eigentlich die Kommunikation abbrechen, da der adressierte Slave ja nicht antwortet bzw. nicht existiert.

Bei Adresse 0 reichts, wenn einer ACK sendet.
Ob das Gerät auf den General Call reagiert, steht im Datenblatt bzw. wird in der Firmware (AVR) festgelegt.
Bei nem EEPROM macht der GC wenig Sinn. Ist eher, um allgemeine Daten zu verbreiten wie z.B. Uhrzeit senden; wer sie braucht, schreibt mit, die anderen ignorierens einfach ("Adresse 0? Bin ich nicht.")