leonhard.pleuger Posted October 20, 2020 at 12:22 PM Posted October 20, 2020 at 12:22 PM (edited) Hallo zusammen, ich möchte über das "RS485-Bricklet" vier Schlauchwaagengefäße ansteuern und den Hydrostatischen Druck über die Funktion "Read Holding Registers" mit einer Frequenz von 2 Hz auslesen.Für einen ersten Test habe ich Anfragen über den "Brick Viewer" geschickt und die gewünschte Antwort bekommen.Nun ist es aber erforderlich, dass ich diese Anfragen automatisiert über Matlab stelle.Es ist mir möglich auf Grundlage des Beispielcodes "Loopback" eine Verbindung herzustellen, allerdings ist es mir nicht möglich über den "write"-Befehl eine einzelne oder sich wiederholende Anfrage zu stellen.Bei aktiver Verbindung zwischen Matlab und dem RS485-Bricklet kann ich parallel über den Brickviewer einen Input geben, dessen Output mir dann sowohl im Brickviewer, als auch in Matlab angezeigt wird.Was mache ich momentan noch falsch? Wäre Super, wenn mir da jemand weiterhelfen könnte. :)Beste GrüßeLeonhard clc clear all global data import com.tinkerforge.IPConnection; import com.tinkerforge.BrickletRS485; import java.lang.String; % For this example connect the RX+/- pins to TX+/- pins on the same Bricklet % and configure the DIP switch on the Bricklet to full-duplex mode HOST = 'localhost'; PORT = 4223; UID = 'DKf'; % Change XYZ to the UID of your RS485 Bricklet input('Press key to start\n', 's'); ipcon = IPConnection(); % Create IP connection rs485 = handle(BrickletRS485(UID, ipcon), 'CallbackProperties'); % Create device object ipcon.connect(HOST, PORT); % Connect to brickd % Don't use device before ipcon is connected % Set Mode to RS485 rs485.setMode(BrickletRS485.MODE_RS485); % Enable full-duplex mode rs485.setRS485Configuration(9600, BrickletRS485.PARITY_EVEN, ... BrickletRS485.STOPBITS_1, BrickletRS485.WORDLENGTH_7, ... BrickletRS485.DUPLEX_HALF); % Register read callback to function cb_read set(rs485, 'ReadCallback', @(h, e)cb_read(e)); % Enable read callback rs485.enableReadCallback(); % Write "ASCII" string (Adresse und Befehl) rs485.write(String(':9003015E00020C\r\n').toCharArray()); %SWA 144 rs485.write(String(':8E03015E00020E\r\n').toCharArray()); %SWB 142 rs485.write(String(':8D03015E00020F\r\n').toCharArray()); %SWC 141 rs485.write(String(':8F03015E00020D\r\n').toCharArray()); %SWD 143 input('Press key to exit\n', 's'); %Alternative für input ipcon.disconnect(); % Callback function for read callback function cb_read(e) global data tmp_t = now; % fprintf('Message: "%s"\n', e.message); fprintf(e.frameCount); B = convertCharsToStrings(e.message); C = [tmp_t; B]; data = [data, C]; end Edited October 20, 2020 at 01:56 PM by leonhard.pleuger Quote
photron Posted October 20, 2020 at 01:00 PM Posted October 20, 2020 at 01:00 PM Was mich auf den ersten Blick stutzig macht ist die Wordlength von 7 Bit, üblich wären 8 Bit. Auf den zweiten Blick kommt die Frage warum du in deinem Programm das Bricklet im RS485 Modus verwendest und händisch Modbus versuchst zu sprechen, wenn du im Brick Viewer erfolgreich das Bricklet mit Modbus Master Modus verwendest mit der Read Holding Registers Funktion. Du solltest nicht auf das Loopback Beispiel aufsetzten, sondern auf das Modbus Master Besipiel:https://www.tinkerforge.com/de/doc/Software/Bricklets/RS485_Bricklet_MATLAB.html#modbus-master-matlab Und dieses von modbusMasterWriteSingleRegister auf modbusMasterReadHoldingRegisters umstellen. Quote
leonhard.pleuger Posted October 20, 2020 at 01:40 PM Author Posted October 20, 2020 at 01:40 PM (edited) Hallo, vielen Dank für die schnelle Antwort. Die 7 Bit Wordlength ist schon richtig, da vom Schlauchwaagenherrsteller so vorgegeben. (bei 8 Bit kommt nur Kauderwelsch raus). Bis jetzt habe ich ausschließlich im RS485 Modus gearbeitet, sowohl im Brickviewer, als auch in Matlab. Im Modbus Master Modus bekomme ich bis jetzt einen "Request Timeout". Wenn ich jetzt deine Hinweise umsetze, bekomme ich ein Exception Code: -1, also einen Timeout und keinerlei Daten für "e.holdingRegisters". clc clear all global expected_request_id; global counter; global data; import com.tinkerforge.IPConnection; import com.tinkerforge.BrickletRS485; HOST = 'localhost'; PORT = 4223; UID = 'DKf'; % Change XYZ to the UID of your RS485 Bricklet input('Press key to start\n', 's'); counter = 0; ipcon = IPConnection(); % Create IP connection rs485 = handle(BrickletRS485(UID, ipcon), 'CallbackProperties'); % Create device object ipcon.connect(HOST, PORT); % Connect to brickd % Don't use device before ipcon is connected % Set operating mode to Modbus RTU master rs485.setMode(BrickletRS485.MODE_MODBUS_MASTER_RTU); % Modbus specific configuration: % - slave address = 1 (unused in master mode) % - master request timeout = 1000ms rs485.setModbusConfiguration(144, 3000) % Configuration rs485.setRS485Configuration(9600, BrickletRS485.PARITY_EVEN, ... BrickletRS485.STOPBITS_1, BrickletRS485.WORDLENGTH_7, ... BrickletRS485.DUPLEX_HALF); % Register Modbus master write single register response callback to function % cb_modbus_master_write_single_register_response set(rs485, 'ModbusMasterReadHoldingRegistersResponseCallback', ... @(h, e) cb_modbus_master_read_holding_register_response(e)); % Write 65535 to register 42 of slave 17 17,42,65535 expected_request_id = rs485.modbusMasterReadHoldingRegisters(144, 350, 2); %SW144 register 350;351 input('Press key to exit\n', 's'); ipcon.disconnect(); % Callback function for Modbus master write single register response callback function cb_modbus_master_read_holding_register_response(e) global expected_request_id; global counter; global data tmp_t = now; % counter = counter + 1; fprintf('Request ID: %i\n', e.requestID); fprintf('Expected Request ID: %i\n', expected_request_id); fprintf('Exception Code: %i\n', e.exceptionCode); fprintf('Holding Registers: %i\n', e.holdingRegisters); B = convertCharsToStrings(e.holdingRegisters); C = [tmp_t; B]; data = [data, C]; if e.requestID ~= expected_request_id fprintf('Error: Unexpected request ID\n'); end end Demo_Modbus_PC_HS_Serie.pdf Edited October 20, 2020 at 01:42 PM by leonhard.pleuger Quote
photron Posted October 20, 2020 at 03:04 PM Posted October 20, 2020 at 03:04 PM Ich fürchte der Modbus Modus des Bricklets für 7 Bit ist ungetestet. Daher jetzt eine Rolle rückwärts 😜. Da es mit Brick Viewer funktioniert müssen wir jetzt nur finden was in deinem initialen Programm nicht passt. Was genau hast du in Brick Viewer als Anfrage eingeben? Und hast du dabei das Encoding auf "ASCII" oder "Raw (Hex Bytes)" gestellt? Quote
leonhard.pleuger Posted October 20, 2020 at 03:23 PM Author Posted October 20, 2020 at 03:23 PM (edited) Das Encoding ist auf ASCII. Ich habe mal einen Screenshot angehängt. Auf diese Art funktioniert es ohne Probleme. Edited October 20, 2020 at 03:36 PM by leonhard.pleuger Quote
photron Posted October 20, 2020 at 04:57 PM Posted October 20, 2020 at 04:57 PM Okay, um einmal meine Verwirrung zu klären. Der Sensor den du da verwendest sprichst Modbus ASCII und das was du da schickst sieht auch nach korrektem Modbus ASCII aus, daher auch die 7 Bit. Die Modbus Funktionen des Bricklets sind für Modbus RTU, meinen Ratschlag das zu nutzen kannst du ignorieren, das funktioniert nicht. Es sieht auf den ersten Blick so aus als hättest du dein Vorgehen von Brick Viewer korrekt in dein Programm übertragen. Eine Unterschied könnte noch sein, dass du in Brick Viewer zwischen den 4 Anfragen die du schickst etwas Zeit vergeht, weil du händisch die Anfrage wechseln musst. In deinem Programm schickst du die 4 Anfragen aber direkt nacheinander raus. Du lässt also dem ersten Sensor gar keine Zeit zu antworten, sondern quatscht ihm sofort mit der Anfrage für den zweiten Sensor dazwischen. Versuch also mal in deinem Programm nur die erste Anfrage zu schicken, oder zwischen den Anfragen eine kurze Pause einzubauen, damit die Sensoren auch eine Chance haben zu antworten. Quote
Paffenholz Posted October 20, 2020 at 06:41 PM Posted October 20, 2020 at 06:41 PM Hallo, besten Dank für die Hinweise. Die Anfrage können wir auch alleine also nur an einen Sensor stellen (aus kommentieren der anderen Zeilen) und lange warten, es zeigt sich leider das gleich Verhalten. Wir erhalten auch auf recht kurze Klickabfolgen auf das „WriteLine“ im BrickViewer die oben genannte Rückmeldung über das CallBack in Matlab. Das schnelle “zu quatschten” kann also nicht die Ursache sein. Was steckt denn hinter dem “WriteLine” Button im BrickViewer für ein Befehl. Wie wird der umgesetzt und gesendet? An der Stelle muss es ja einen Unterschied geben. Die Matlab write Funktion gibt auch die Anzahl an geschriebene Zeichen zurück, auch eine Kontrolle mit einem Oszillograph hat gezeigt, dass Daten rausgehen... nur scheinen Sie nicht korrekt anzukommen mittels der Matlab write Funktion. Da die Daten ja auch im Callback zurückkommen, sollten die Schnittstellen-Parameter ja grundsätzlich stimmen. Quote
photron Posted October 21, 2020 at 09:20 AM Posted October 21, 2020 at 09:20 AM Sehr komisch. Da habe ich keine gute Idee zu. Das initiale Programm sollte einfach funktionieren, abgesehen von den 4 Writes direkt nacheinander. Für mein Verständnis: Aus Brick Viewer heraus funktioniert alles wie erwartet. Wenn die Anfrage gesendet wird kommt eine passenden Antwort darauf. Wenn ihr das aber aus eurem Programm heraus macht kommt keine Antwort. Wenn aber euer Programm läuft und ihr parallel dazu in Brick Viewer die Anfrage sendet, dann kommt eine passenden Antwort in eurem Programm und in Brick Viewer an. Habe ich das so richtig verstanden? Was passiert wenn Brick Viewer bereits läuft und ihr euer Programm startet? Dann kommt weder in Brick Viewer noch in eurem Programm eine Antwort an. Sprich das Problem scheint zu sein, dass der Sensor die Anfrage nicht versteht/empfängt wenn sie von eurem Programm gesendet wird und deswegen gar nicht antwortet. Das Problem ist nicht, dass die Antwort zwar kommt, aber euer Programm sie nicht erhält, wenn die Anfrage auch durch euer Programm gesendet wurde? Hier ein paar schlechte Ideen 😜 1) Es gibt eine sehr kleine Chance, dass sich Brick Viewer und euer Programm über den Zustand des Read Callbacks in die Quere kommen. Wenn in Brick Viewer der Tab des RS485 Bricklets ausgewählt wird, dann merkt dich Brick Viewer ob der Read Callback bereits aktiv war. Falls nicht, dann wird der Callback aktiviert und beim Verlassen des Tabs wieder deaktiviert. Daher testet bitte mal Brick Viewer zu beenden und dann euer Programm auszuführen. Ich erwarte allerdings nicht, dass das hilft, denn damit das ein Problem sein könnte müsstet ihr in Brick Viewer den Tab verlassen genau zwischen euer Programm sendet die Anfrage und die Antwort kommt an. Unwahrscheinlich. 2) Startet mal alle Hardware neu. Also den ganzen Tinkerforge Aufbau und die Sensoren einmal vom Strom trennen, kurz Warten und wieder anschließen. Nur um sicherzustellen, dass die Hardware nicht einfach in einem verwirrten Zustand ist. Auch Unwahrscheinlich. 3) Brick Viewer ruft auch nur die Write Funktion auf. Habt ihr mit dem Oszilloskop mal die Anfrage von Brick Viewer und eurem Programm verglichen? Dort sollte keine Unterschied bestehen. Per Oszilloskop solltet ihr auch sehen können, ob vom Sensor einfach keine Antwort kommt oder ob eine Antwort kommt, dass Bricklet sie aber nicht versteht, wenn die auslösende Anfrage von eurem Programm gesendet wurde. 1 Quote
leonhard.pleuger Posted October 22, 2020 at 01:02 PM Author Posted October 22, 2020 at 01:02 PM Hi, das fasst die Situation gut zusammen. Es macht allerdings keinen Unterschied, in welcher Reihenfolge Brickviewer und Matlab gestartet werden. es kommt immer das gleiche Ergebnis raus. Versuche, die Hardware neu zu starten, den BrickViewer zu beenden oder Pausen in das Programm einzubauen, haben nicht zum gewünschten Ergebnis geführt. Wir haben mal ein Oszilloskop angeschlossen und dann Anfragen gestellt. Es erscheint dasselbe Signal, unabhängig davon, ob Matlab oder der Brickviewer anfragt. Allerdings konnten wir nur die Anfragen und nicht die Antworten sehen. Ich würde sagen, dass das das Problem darauf einschränkt, dass Matlab die Antwort des Sensors nicht auslesen kann. Quote
photron Posted October 22, 2020 at 04:29 PM Posted October 22, 2020 at 04:29 PM Die Anfrage sieht also auf dem Oszilloskop identisch aus, egal ob aus Matlab oder aus Brick Viewer gesendet, sprich der Sensor kann das nicht unterscheiden. Aber es kommt in Brick Viewer und Matlab nur eine Antwort an, wenn Brick Viewer die Anfrage gestellt hat, aber nicht wenn Matlab die Anfrage stellt. Das verwirrt mich weiterhin sehr. Interessant wäre jetzt noch zu sehen, was mit der Antwort laut Oszilloskop ist. Ob der Sensor sie wirklich nicht sendet. Ich nehme an auf dem RS485 Bricklet ist die aktuelle Firmware 2.0.5 drauf. Falls nicht, updated bitte mal über Brick Viewer. Okay, mal ganz zurück zum Anfang. Funktioniert das unveränderte Loopback Beispiel in Matlab, unter der Annahme das Bricklet ist entsprechend der Angaben im Beispiel verkabelt und der DIP Schalter passend eingestellt? Funktioniert das Loopback Beispiel mit eurer 9600 7E1 Konfiguration? Wobei ihr hier für Loopback auf Full-Duplex stellen müsst, statt auf Half-Duplex wie beim Sensoraufbau. rs485.setRS485Configuration(9600, BrickletRS485.PARITY_EVEN, ... BrickletRS485.STOPBITS_1, BrickletRS485.WORDLENGTH_7, ... BrickletRS485.DUPLEX_FULL); Quote
leonhard.pleuger Posted October 23, 2020 at 02:02 PM Author Posted October 23, 2020 at 02:02 PM Hallo, wir haben den Fehler gefunden. Schuld waren die letzten vier Zeichen "\r\n", die Matlab im ASCII Befehl falsch interpretiert hat. Die Nachricht darf also nicht die folgende Form haben: ':9003015E00020C\r\n' Wenn der write Befehl folgendermaßen aussieht, wird das gewünschte Ergebnis ausgegeben. cr = sprintf('\r'); %carriage return lf = newline; %line feed rs485.write([':9003015E00020C', cr, lf]); Der Terminatior muss also extra angehängt werden. Sehr vielen Dank für die Hilfe. :-) Quote
photron Posted October 23, 2020 at 03:13 PM Posted October 23, 2020 at 03:13 PM Ja, das erklärt alles perfekt. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.