Jump to content

RS232 Bricklet


Recommended Posts

Hallo,

ich versuche mit Python über das RS232 Bricklet einen MFC der Firma Bronkhorst anzusprechen. Nach längerem probieren, lesen und basteln habe ich das Kabel korrekt belegt und die ersten Tests gemacht.

 

Wenn ich im BrickViewer den Sollwert als ASCII String anfrage (':06030401210120\r\n') erhalte ich im BrickViewer die korrekte Antwort (':06030201210000\r\n').

 

Wenn ich das Loopback Beispiel aus der Dokumentation des Bricklets anpasse, wird der String korrekt geschrieben und ich sehe im BrickViewer die korrekte Antwort.

 

Wenn ich die Antwort über Python lesen möchte, erhalte ich ich allerdings immer zwei Antworten:

 

(':', '0', '6', '0', '3', '0', '2', '0', '1', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00')

 

('2', '1', '0', '0', '0', '0', '\r', '\n', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00')

 

Im BrickViewer kommt wiederum die korrekte Antwort als ganzes an.

 

Der BrickViewer selbst ist auch in Python geschrieben, allerdings passt die Lese-Funktion dort nicht zu meinem Problem, da hier ein Schneiden bei '\r\n' in der Mitte abgefangen wird.

 

Ich vermute so etwas wie ein Timing Problem, wäre aber für Anregungen sehr dankbar.

Link zu diesem Kommentar
Share on other sites

Hi,

Wenn ich es richtig verstanden habe, dann kommt ja grundsätzlich die richtige Antwort an, nur die "'\x00'" stören dich ?

 

Beachte bitte den Längen Parameter der zum Char Array mitgeliefert wird. Nur bis dahin ist das Array sinnvoll gefüllt.

'\x00' bedeutet einfach nur null, nichts... ignorieren.

 

hth

Link zu diesem Kommentar
Share on other sites

Auch im Brick Viewer wird die Antwort in zwei Teile ankommen. Die beiden Teile werden aber so schnell hintereinander ankommen, dass es so aussieht als würden sie in einem Stück ankommen.

 

RS232 ist streamorientiert, nicht paketorientiert. Es wäre auch okay, wenn die Daten Byteweise geliefert würden. Du musst einfach genauso wie Brick Viewer alle eingehenden Daten aneinanderhängen, um den Datenstrom zu rekonstruieren.

 

Dann kannst du wie Brick Viewer den Datenstrom anhand der \r\n in die einzelnen Nachrichten zerlegen.

 

class Reader(object):
    def __init__(self):
        self.data = ''

    def cb_read(self, message, length)
        self.data += ''.join(message[:length])

    def get_next_message(self):
        i = self.data.find('\r\n')

        if i < 0:
            return None
        else:
            message = self.data[:i]
            self.data = self.data[i + 2:]
            return message

Link zu diesem Kommentar
Share on other sites

Hallo,

 

vom Prinzip her verstehe ich was du meinst. Da ich aber noch nicht mit Klassen gearbeitet habe, weiss ich nicht wie ich es umsetzen soll. Ich habe den Beispiel-Code von der TF-Seite nur minimal geändert.

 

Ohne deinen Tipp bekomme ich immer noch reproduzierbar zwei getrennte Antworten. Wie kann ich deinen Vorschlag integrieren?

 

Schöne Grüße und ich bin dankbar für jede Anregung...

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-

HOST = "localhost"
PORT = 4223
UID = "uVr" # Change to your UID

from tinkerforge.ip_connection import IPConnection
from tinkerforge.bricklet_rs232 import BrickletRS232

# For this example connect the RX1 and TX pin to receive the send message

# Convert string to char array with length 60, as needed by write
def string_to_char_list(message):
    chars = list(message)
    chars.extend(['\0']*(60 - len(message)))
    return chars, len(message)

# Assume that the message consists of ASCII characters and
# convert it from an array of chars to a string
def char_list_to_string(message, length):
    return ''.join(message[:length])

# Callback function for read callback
def cb_read(message, length):
    s = char_list_to_string(message, length)
    print('Message (length: ' + str(length) + '): "' + s + '"')

if __name__ == "__main__":
    ipcon = IPConnection() # Create IP connection
    rs232 = BrickletRS232(UID, ipcon) # Create device object

    ipcon.connect(HOST, PORT) # Connect to brickd
    # Don't use device before ipcon is connected
    
    rs232.set_configuration(9, 0, 1, 8, 0, 0) 
    
    # Register read callback to function cb_read
    rs232.register_callback(rs232.CALLBACK_READ_CALLBACK, cb_read)

    # Enable read callback
    rs232.enable_read_callback()

    # Write "test" string
    rs232.write(*string_to_char_list(':06030401210120\r\n'))
    
    raw_input("Press key to exit\n") # Use input() in Python 3
    ipcon.disconnect()

Link zu diesem Kommentar
Share on other sites

Hier die Funktion der Read Klasse ohne Klasse. Dazu ersetzt du in deinem Beispiel die cb_read Funktion durch diese Version:

 

buffer = '' # Global buffer to collect all incoming data

# Callback function for read callback
def cb_read(message, length):
    s = char_list_to_string(message, length)
    
    # Append new data to global buffer
    global buffer
    buffer += s
   
    # Check if global buffer contains a complete response
    i = buffer.find('\r\n')

    if i >= 0:
        # Get response (without \r\n) from buffer
        response = buffer[:i]

        # Remove response (with \r\n) from buffer
        buffer = buffer[i + 2:]

        # Print response
        print('Response: ' + response)

 

Im Read Callback kommen die Daten immer noch stückweise an, daran ändert sich nichts. Der Code nutzt jetzt aber einen globalen Buffer in dem alle eingehenden Stück gesammelt werden. Dann wird in den Buffer geschaut, ob eine komplette Antwort (endet mit \r\n) im Buffer zusammen gesammelt wurde. Wenn ja wird sie aus dem Buffer entfernt und ausgegeben.

Link zu diesem Kommentar
Share on other sites

Hallo,

 

das mit den allergischen Reaktionen verstehe ich, ich kann da gerne aufklären.

 

Es handelt sich um einen Mass Flow Controller (MFC), im Prinzip ein elektrisches Stellventil für Gasflüsse. Die Steuerung über RS232 ist meiner Meinung nach die preiswerteste (nicht die einfachste) Methode, da man so nur die Spannungsversorgung des Geräts plus die RS232 benötigt.

 

Die Alternative wäre den analogen Ein- bzw. Ausgang des Gerätes plus die Spannungsversorgung zu nutzen. Das ist im Prinzip einfacher, benötigt aber eine Schnittstelle pro Regelgerät mehr.

 

Daher versuche ich mein Glück über die serielle Schnittstelle.

 

Schöne Grüße...

Link zu diesem Kommentar
Share on other sites

  • 1 year later...

Hallo assassin,

 

ich habe ein Projekt, wobei der MFC IQFlow der Bronkhorst über RS232 von einem Programm gesteuert, geregelt werden soll. Das Programm habe ich nicht mit Python sondern C#/WPF unter Windows 10 selbst geschrieben. Nachrichten-Senden & Empfängen habe ich mit Putty getestet. Das läuft sehr gut.

 

Zum Test der Kommunikation mit dem MFC habe ich versucht, erstmal eine Anfrage an ihn zuzusenden, also dataWrite(":06030401210120\r\n"), dann Codebefehle als Beispiele aus 919027-Benutzer-Handbuch RS232 Schnittstellen. Leider antwortet er immer noch nicht. Ich kriege gar nichts hin.

 

Die Kabeln, die ich verwende, habe alle von Bronkhorst gekauft und mit Bronkhorst-Programmen wie FlowDDE, FlowView getestet. Es funktionieren einwandfrei.

 

Ich habe versucht die Hilfe/Infos über RS232-Kommunikation mit Bronkhorst MFC von einem selbstgeschrieben Programm im Net zu recherchieren und nur hier gefunden.

 

Meine Frage ist, was oder wie man wieder testen/machen sollte? Ich vermute man muss erst davor irgendwas machen, bevor man z.B. eine Anfrage zum Soll-Wert zuschickt.

 

Es wäre für Anregungen sehr dankbar.

Link zu diesem Kommentar
Share on other sites

Hallo photron,

 

vielen Dank für deinen Tipp.

 

Die Einstellung/Einrichtung der RS232-Kommunikation mit dem MFC hatte ich genau wie Bronkhorst beschrieben programmiert:

"Die Kommunikationseinstellungen sind: 38400,n,8,1"

 

Mein eigenes Programm kann gut mit Putty und einer Serial-COM UWP-App bei dieser Einstellung kommunizieren, also Nachrichten erfolgreich gesendet und empfängt.

 

Gestern habe ich eine sehr alte Dokumentation der Bronkhorst '2007-09-12-Hyperterminal-RS232-Example' gefunden und gelesen. Es wird gesagt "At power up of the MFC the MFC sends an identification string to the RS232 port". Ich kriege das nicht hin.

Ich habe dann versucht per Hyperterminal und Putty eine Anfrage an seine Capacity ":060304014D014D\r\n" an ihn zuzuschicken. Die Antwort war ":0104". Per mein Programm kam aber gar nichts zurück, also kein ":0104". Eine Suche was ":0104" bedeutet hatte kein Erfolg.

 

Es wäre für Anregungen sehr dankbar.

 

 

Link zu diesem Kommentar
Share on other sites

Hallo FlyingDoc,

 

vielen Dank. Sorry habe ich noch nie gesagt, dass ich kein RS232 Bricklet sondern einen anderen USB-Serial-Adapter verwendet. Alles (MFC, Bronkhorst-Kabel und der Adapter) funktioniert doch gut im Test mit den Programmen von Bronkhorst wie FlowDDE, FlowView. Aber mit meinem eigenen C#-Programm geht es leider noch immer nicht.

 

Wie gesagt, ich habe das Thema 'direkt Kommunikation/Steuerung eines Bronkhorst-MFC über RS232' nur da im 4rum gefunden. Daher hätte ich gern die Hilfe von assassin, weil er schon mal mit diesem MFC gearbeitet hat, also mit dem MFC über RS232 direkt kommuniziert. Wie er schrittweise für den/die Direkt-Kommunikationsaufbau und -steuerung über RS232 gemacht hat, würde ich sehr gern wissen.

 

Schöne Grüße

Link zu diesem Kommentar
Share on other sites

Join the conversation

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

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...