Jump to content

Recommended Posts

Posted

Hallo,

 

ich habe ein Problem damit die UIDs von Base58 in Int umzurechnen. In der Doku steht:"UID "b1Q" (Base58) or 33688 (integer)" ich komme aber auf 582*34+23 = 114399.

 

Wie wird richtig gerechnet?

 

Grüße

Posted

Ich komme auf 33688 ;).

olaf@pc:~$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:38) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> BASE58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
>>> def base58decode(encoded):
...     value = 0
...     column_multiplier = 1
...     for c in encoded[::-1]:
...         column = BASE58.index(c)
...         value += column * column_multiplier
...         column_multiplier *= 58
...     return value
... 
>>> base58decode("b1Q")
33688

 

Händisch:

>>> BASE58 = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
>>> BASE58.index('b')
10
>>> BASE58.index('1')
0
>>> BASE58.index('Q')
48
>>> 10*58**2 + 0*58**1 + 48*58**0
33688

Posted

Ok. Danke, habe eine falsche Zeichntabelle verwendet.

 

Ich versuche direkt über die RS485 Extension (Slave, Adresse: 1) mit einem Ambient Light Bricklet (UID: b1Q) zu kommunizieren. Wenn ich folgendes sende müsste ich doch die Helligkeit als Antwort erhalten:

 

Modbus Adress: 0x01

Func. Code:    0x64

Seq. Num:      0x01

UID:          0x98 0x83 0x00 0x00

Packet Length: 0x08

Func ID:      0x01

Seq. Num.:    0x18

Flags:        0x00

CRC16:        0xAE 0x41

 

Ich bekomme aber nur 0x00 zurück. Habe ich irgendwo einen Fehler übersehen?

Posted

Baudrate überall 250000, Parität und Stopbits passen auch. Als Master verwende ich einen Raspberry mit einem RS485 zu UART Wandler. Die gesendeten Daten passen und wurden mit einem Terminalprogramm überprüft. Sie kommen auch am Stack an, habs mit nem Oszi gemessen.

Posted

Sprichts du denn das Protokoll auch so wie hier beschrieben:

 

http://www.tinkerforge.com/de/doc/Low_Level_Protocols/Modbus.html#requests-and-responses

 

Sprich pollst du den Slave für Responses nachdem du ihm den Request gesendet hast? Slaves dürfen von sich aus keinen Response senden, sondern nur als Antwort auf einen Request.

 

Edit:

 

Hätte mal richtig lesen sollen. Wie handhabt dein RS485 Wandler den Transmitter und Receiver Enable? Steuerst du das von Hand, oder passiert das automatisch?

 

Wenn der Transmitter auf der Master-Seite aktiviert ist wenn der Slave antwortet dann kann die Antwort verfälscht ankommen.

Posted

Habe meinen Fehler gefunden. Lag am Receiver Enable. Ich habe am RS485 Wandler zu früh auf Empfangen umgeschaltet, so wurden die letzten bits nicht gesendet. Jetzt bekomme ich eine Antwort.

 

Danke für die Hilfe!!!

  • 2 weeks later...
Posted

Hallo,

 

zur Hardware:

-Rasperry Pi mit aktuellem Raspian und Python 3

-Raspicomm Erweiterung für RS485 (andere RS485 Boards bei denen man den RTC Pin für die Datenrichtung manuell setzen muss gehen auch, machen das programmieren aber sehr aufwändig)

-ein Stück dreiadriges Kabel

-Masterbrick mit RS485 Extension

 

Hier der Python Code. Er funktioniert ist aber ein erster Entwurf und noch nicht optimiert.

 

@borg: passt denn die Bestätigung nach erfolgreicher Abfrage:

0x01, 0x64, modbus_sequence, crc16

 

 

import serial
import time
import crc16


def get_value(port, mod_adr, mod_seq, tcp_seq, func_id):		#Abfrage des Bricks

flag = True													#Flag True bis Abfrage erfolgreich


req = bytearray([0x01, 0x64, mod_seq, mod_adr[0], mod_adr[1], mod_adr[2], mod_adr[3], 0x08, func_id, tcp_seq, 0x00])		#bytearray für modbus/tcp Abfrage

crc_req = 0xFFFF
for x in range (0, 11):										#Prüfsumme berechnen
	crc_req = crc16.calcByte( int.from_bytes(req[x:x+1], byteorder='big'), crc_req)

req[11:13] = crc_req.to_bytes(2, byteorder='little')		#Prüfsumme anhängen


ack = bytearray([0x01, 0x64, mod_seq])						#bytearray für modbus Bestätigung

crc_ack = 0xFFFF
for x in range (0, 3):										#Prüfsumme berechnen
	crc_ack = crc16.calcByte( int.from_bytes(ack[x:x+1], byteorder='big'), crc_ack)

ack[3:5] = crc_ack.to_bytes(2, byteorder='little')			#Prüfsumme anhängen



while flag:													#solange Abfrage nicht erfolgreich
	port.write(req)											#Abfrage schicken
	ans = b'\x00'
	ans = port.read(20)										#Antwort empfangen

	leng = int.from_bytes(ans[7:8], byteorder='big')		#Länge des TCP Packets bestimmen

	crc_ans = 0xFFFF
	for x in range (0, leng+3):								#Prüfsumme der Antwort berechnen
		crc_ans = crc16.calcByte( int.from_bytes(ans[x:x+1], byteorder='big'), crc_ans)

	if bytearray([0x01, 0x64, mod_seq, mod_adr[0], mod_adr[1], mod_adr[2], mod_adr[3]]) in ans[0:7]:		#Antwort mit Abfrage vergleichen (Adresse)
		if (int.from_bytes(ans[leng+3:leng+5], byteorder='little')) == crc_ans:				#Prüfsumme kontrollieren
			port.write(ack)									#Bestätigung senden
			if leng > 8:									#wenn Daten vorhanden
				val = int.from_bytes(ans[11:11+leng-8], byteorder='little')			#Daten ausgeben
				return val
			else:
				return 0
			flag = False
	else:
		flag = True											#fehlerhafte Antwort, erneuter Versuch



if __name__ == "__main__":										#Hauptprogramm

port = serial.Serial(port='/dev/ttyRPC0', baudrate=115200, timeout=2)		#Port öffnen, 115200 Baud, 8N1


time.sleep(.1)

mod_adr = bytearray([0x98, 0x83, 0x00, 0x00])				#Adresse des Brick/Bricklet
mod_seq = 0x01												#Modbus sequence number
tcp_seq = 0x01												#TCP sequence number
func_id = 0x01												#Funktions ID

value = get_value(port, mod_adr, mod_seq, tcp_seq,func_id)	#Abfrage

print ("Wert: %d\n" % value)								#Wert ausgeben

 

Verbesserungsvorschläge und Fragen sind natürlich wilkommen.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...