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 to comment
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 to comment
Share on other sites

Hallo,

 

ich habe den Post oben nochmal geändert. Die Korrekte Meldung wird in zwei Strings geschnitten. Die Länge des "gesuchten" Strings ist 17 und mal wird in 9 und 8 und mal in 10 uns 7 geschnitten.

 

Ich erhalte immer zwei Antworten aus dem Callback obwohl es nur eine sein dürfte.

Link to comment
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 to comment
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 to comment
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 to comment
Share on other sites

Wenn jetzt alles prima läuft, kannst du uns etwas über das MFC sagen, ich vermute es ist diesmal nicht die Microsoft Foundation Classes ::)

 

Ich bekomme immer allergische Reaktionen in meinen Gehirnzellen ;D wenn da mit Fachausdrücken hantiert wird, wo man sich erstmal nix vorstellen kann.

Link to comment
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 to comment
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 to comment
Share on other sites

buntstifte, es funktioniert also mit Putty aber nicht mit deinem eigenen Programm? Dann muss es ja an deinem eigenen Programm liegen. Öffnest du in deinem Programm die richtige serielle Schnittstelle, stellst du die Baudrate, Parität und Stopbits richtig ein?

Link to comment
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 to comment
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 to comment
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.

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.

 Share

×
×
  • Create New...