Märklin CAN Bus Geschwindigkeit Setzen

#1 von henrikl2000 , 08.10.2021 11:18

Hallo

Ich habe ein Problem mit dem Märklin CAN-Bus.
Ich habe als Ausgangspunkt das FreeBasic-Beispiel von DiegoGarcia verwendet, das ich ins VB.Net übersetzt habe.

Ich kann Stopp / Go senden und Geschwindigkeit von einer Lokomotive abfragen, aber wenn ich versuche, die Geschwindigkeit einzustellen, kann ich sehen, dass der CS2 nicht versteht, was ich meine.
Laut Märklin CAN CS2 Protokoll Ver. 2.0 Seite 30:
Geschwindigkeit muss als xx von 1000 angegeben werden.

In meinem Code ist:
DLC ist auf 6 eingestellt
Byte 2 gleich Protokoll MM2
Byte 3 gleich Lokomotiv-Adresse

Byte 4 (b4) und 5 (b5) gleich Geschwindigkeit

Testergebnisse
Dezimal 100: b4 = & H0 / b5 = & H64 OK
Dezimal 200: b4 = & H0 / b5 = & HC8 nicht OK
Dezimal 300: b4 = & H1 / b5 = & H2C OK
Dezimal 400: b4 = & H1 / b5 = & H90 nicht OK
Dezimal 500: b4 = & H1 / b5 = & HF4 nicht OK
Dezimal 600: b4 = & H2 / b5 = & H58 OK
Dezimal 700: b4 = & H2 / b5 = & HBC nicht OK
Dezimal 800: b4 = & H3 / b5 = & H20 OK
Dezimal 900: b4 = & H3 / b5 = & H84 nicht OK
Dezimal 1000: b4 = & H3 / b5 = & HE8 nicht OK

Ich habe versucht, die Geschwindigkeit als Hexadezimal und als Dezimal einzustellen. Gleiches Ergebnis.

Was muss ich tun, um die Geschwindigkeit richtig zu berechnen?

Danke im Voraus
Henrik

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 
    
Private Sub Stummiforum(lokID As Byte, lokSpeed As Integer)
 
' - Packet size 13 Bytes
' - Bytes 1 bis 4 sind die Meldungskennung.
' - Byte 5 entspricht dem DLC der CAN-Meldung.
' - Bytes 6 - 13 sind die entsprechenden Nutzdaten. Dabei nicht benötigte Bytes sind mit 00 zu füllen.
 
Dim i As Integer ' als Laufvariable
Dim myDLC As Byte ' Anzahl der Datenbytes im CAN-Paket, 1 Byte (eigentlich nur ein Nibble)
Dim myPrio As Byte ' Priorität des befehls, 1 Nibble (4 Bits)
Dim myResponseBit As Byte ' wenn wir als PC-Programm senden, ist dieses Bit immer 0
Dim myStartWord As UShort ' die Kombination aus Prio, Command und Responsebit
Dim myUID As ULong ' Zieladresse des Objektes auf dem CAN, 32 Bits
Dim myHash As UShort ' unser Hash, 16 Bits
Dim myCommand As Byte ' unser Befehl, 8 Bits
Dim mySubCommand As Byte ' unser Unterbefehl, 8 Bits
Dim myDataBytes(7) As Byte ' array[0..7] Of Byte, immer genau 8 Bytes
Dim mySendingStr As String ' diese Zeichenkette werden wir über das UDP-Socket senden
Dim samletBytes As Byte()
Dim client As New UdpClient()
 
myPrio = 0 ' wir haben keine Priorität
'mySubCommand = 0 ' Stopp
myHash = &H4711 ' wie im Beispiel, kann aber auch &h0300 sein (als Minimum)
myUID = &H0 ' UID = 0 bedeutet: sende den Befehl an alle
 
For i = 0 To 7 ' Märklins Doku zählt auch von D0 .. D7
myDataBytes(i) = 0 ' init array
Next
 
myCommand = 8
myDLC = 6
 
myStartWord = ((myPrio << 12) + (myCommand) + (myResponseBit And 1) And &HFFFF)
myDataBytes(0) = ((myUID >> 24) And &HFF) ' Big Endian encoding
myDataBytes(1) = ((myUID >> 16) And &HFF)
myDataBytes(2) = ((myUID >> 8) And &HFF)
myDataBytes(3) = lokID
 
' bit nr. 2 = protocol (0 = MM2 / 40 = MFX / C0 = DCC
' bit nr. 3 = lok adresse
' bit nr. 4 og 5 = hastighed
' 00084711 6 00 00 08 03 03 20 Lok Geschwindigkeit SX1 Adr 3, V=0x0320=800 von 1024
' 00084711 6 00 00 08 03 00 A0 Lok Geschwindigkeit SX1 Adr 3, V=0x00A0=10 von 1024
' 00084711 6 00 00 40 01 03 20 Lok Geschwindigkeit mfx Adr 1, V=0x0320=800 von 1024
' 00084711 6 00 00 C0 03 01 20 Lok Geschwindigkeit DCC Adr 3
' 00084711 6 00 00 C0 03 00 A0 Lok Geschwindigkeit DCC Adr
 
Dim hexStr As String = lokSpeed.ToString("X4")
 
Dim b4 = "&H" & hexStr.Substring(0, 2)
Dim b5 = "&H" & hexStr.Substring(hexStr.Length - 2)
'Dim b4 As Integer = CInt("&H" & hexStr.Substring(0, 2))
'Dim b5 As Integer = CInt("&H" & hexStr.Substring(hexStr.Length - 2))
 
myDataBytes(4) = b4
myDataBytes(5) = b5
 
mySendingStr = Chr(myStartWord >> 8) + Chr(myStartWord And &HFF)
mySendingStr = mySendingStr + Chr((myHash >> 8) And &HFF) + Chr(myHash And &HFF) 'And &HFF) ' + Chr(myHash And &HFF)
mySendingStr = mySendingStr + Chr(myDLC And &HFF)
 
For i = 0 To 7
mySendingStr = mySendingStr + Chr(myDataBytes(i) And &HFF) ' wir gehen mit "AND &hFF" auf Nummer sicher...
Next
 
samletBytes = Encoding.ASCII.GetBytes(mySendingStr)
 
Dim toSend(12) As Byte
Array.Copy(samletBytes, 0, toSend, 0, 12)
 
client.Connect("192.168.1.250", 15731)
client.Send(toSend, toSend.Length)
client.Close()
End Sub
 
 


henrikl2000  
henrikl2000
Beiträge: 4
Registriert am: 13.03.2020


RE: Märklin CAN Bus Geschwindigkeit Setzen

#2 von DiegoGarcia , 08.10.2021 17:50

Hallo Henrik,

das Setzen einer Lokgeschwindigeit habe ich unter RealBasic/Xojo wie folgt implementiert:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 
const cCS2normMaxSpeed = 126
dim pCS2HashString As Integer
 

Sub SetMyHash(thisWord As Integer)
begin
dim myWord As Integer
 
myWord = SetHashToCS2Format( thisWord ) // ensure that the Bits 7..9 are set to 0x110
 
// if (myWord >= &h5000) then
if (myWord <= 0) then // changed in C2XH v0.16a9 and in SDL v0.8a04
pCS2HashString = ChrB(&h03) + ChrB(0) // BIG Endian
else
pCS2HashString = ChrB(Bitwise.BitAnd(Bitwise.ShiftRight(thisWord, 8), &hFF)) + ChrB(Bitwise.BitAnd(thisWord, &hFF))
end
end sub
 

Function LokBefehl(LokNr as integer, newGeschwindigkeit as integer) As String
// Input-Range: newGeschwindigeit = 0 .. 126
begin
dim MeldungsKennung As String
dim DLC As String
dim LocalID As Integer
dim LocIDstring As String
dim calculatedSpeed As Integer // (0) = Stop; (>=1000) = Vmax
 
if (LokNr > 0) then // must be counted from 1

MeldungsKennung = ChrB(0) + ChrB(&h08) + me.pCS2HashString // prio=0, Loco-speed, not-response, CS2-Hash
DLC = ChrB(6) // six bytes length of data to be interpreted by device
LocalID = LokNr // MM2-Loco #1 = &h0001
LocIDstring = ChrB(BitWise.ShiftRight(LocalID, 24) MOD 256) + ChrB(BitWise.ShiftRight(LocalID, 16) MOD 256) + ChrB(BitWise.ShiftRight(LocalID, 8) MOD 256) + ChrB(LocalID MOD 256) // BIG ENDIAN
if (newGeschwindigkeit = 0) then
calculatedSpeed = 0
elseif (newGeschwindigkeit >= cCS2normMaxSpeed) then
calculatedSpeed = 1008
else
calculatedSpeed = newGeschwindigkeit * 8 // use this fix multiplier
end

Return MeldungsKennung + DLC + LocIDstring + ChrB(calculatedSpeed \ 256) + ChrB(calculatedSpeed MOD 256) + ChrB(0) + ChrB(0) // set speed, extended to 13 bytes

else
Return p13ZeroBytes
end
end function
 



Vielleicht hilft es Dir ja. Evtl. liegt es daran, dass Du als Grenze "1000" genommen hast und nicht "1008".

Ciao
Diego


talks are cheap, and they don't mean much .…


henrikl2000 hat sich bedankt!
 
DiegoGarcia
Metropolitan (MET)
Beiträge: 2.797
Registriert am: 15.04.2007
Steuerung mfx

zuletzt bearbeitet 08.10.2021 | Top

RE: Märklin CAN Bus Geschwindigkeit Setzen

#3 von henrikl2000 , 09.10.2021 11:15

Hallo Diego,

Vielen Dank für deine Antwort.
Der Fehler in mein (oder mehr eine Übersetzung dein Code) ist bei der Konvertierung von String zu Bytes.

1
2
 
 samletBytes = Encoding.ASCII.GetBytes(mySendingStr)
 
 


Richtig
b4 : &H00 / b5 : &H64
087117600045010000

Falsch
b4 : &H00 / b5 : &HC8
08711760004506300
63 sollte hier C8 sein

Ich habe das geklärt mit folgendem Code. Leider sehr ungeschickt.

1
2
3
4
5
6
7
8
9
10
11
12
 
  Dim toSend(12) As Byte
Array.Copy(samletBytes, 0, toSend, 0, 12)
 
For i = 0 To toSend.Length - 1
Debug.Print(toSend(i).ToString)
If i = 9 Then
toSend(i) = myDataBytes(4)
ElseIf i = 10 Then
toSend(i) = myDataBytes(5)
End If
Next
 
 



Du hast übrigens recht das max. nicht 1000 sondern 1008 ist.
Danke noch vielmals für deine Hilfe.

Gruß,
Henrik


DiegoGarcia hat sich bedankt!
henrikl2000  
henrikl2000
Beiträge: 4
Registriert am: 13.03.2020


   

Märklin CS3 Soundwiedergabe per PC-Steuerung
Bremsstrecke über den PC

  • Ähnliche Themen
    Antworten
    Zugriffe
    Letzter Beitrag
Xobor Einfach ein eigenes Forum erstellen
Datenschutz