MODBUS RTU Coi

j_poool

Level-1
Beiträge
107
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
MODBUS RTU write coils

Hallo allerseits
Arbeiter derzeit auf ein Projekt wo 29St. A8R (8x Digital Output Relais) der Firma BD-Mechatronik eigebaut sind.
Die A8R habe ich schon öfters eingesetzt, dabei habe ich aber die Relais mit WriteSingleCoil geschaltet (siehe unten)
Dabei wird bei jedes Programmablauf die ModbusAddress um +1 geschaltet, jedes Ausgang wird dann separat geschaltet.

Mit diese Große Menge an Geräte wird das Schalten der Relais sehr langsam.

Kann mich jemand erklären wie ich das alles mit WriteMultipleCoil beschleunige?
Oder hat jemand ein Bespiel wie ich WriteMultipleCoil eisetze?

... Beckhoff SPS
Vielen Dank

Code:
1:

    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=0,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[0]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );




        IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF


2:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=1,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[1]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF
3:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=2,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[2]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF




4:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1,
    MBAddr:=3,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[3]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF


5:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=4,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[4]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF


6:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=5,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[5]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF






7:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=6,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[6]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF




8:
    ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
    Quantity:=1 ,
    MBAddr:=7,
    cbLength:=1,
    pMemoryAddr:= ADR(arrOut[7]),
    Execute:= TRUE,
    Timeout:= tTimeout,
    BUSY=>bBUSY );


IF NOT bBusy THEN
            ModbusRTU.WriteSingleCoil(Execute:= FALSE);
            IF ModbusRTU.Error THEN
                iStepConfig := 0;
            ELSE
                iStepConfig :=iStepConfig+1;
            END_IF
        END_IF
 
Zuletzt bearbeitet:
WriteMultipleCoil geht ganz bestimmt nur auf EINEN Slave.

Ich kenn das RTU Protokoll so:
Es wird an einen Slave etwas gesendet und dann auf die Antwort gewartet.
Egal ob man Write oder Read macht.
ERST DANN kann man einen weiteren Slave bearbeiten.

Um es zu beschleunigen habe ich innerhalb vom OB1 die Modbus-Geschichte mehrmals aufgerufen.
Könnte ja sein, dass inzwischen die Antwort gekommen ist. Dann zum nächsten Slave...

Auch ich habe mich geärgert, weil es so langsam ist.
Noch dazu wenn es einen Hersteller (aus Japan) gibt, bei dem der eine FreqUmr max 115kBaud kann, der andere nur 38kBaud.
Somit alles mit 38kBaud betreiben.
ECHT BLÖD

Es ginge schneller wenn man mehrere RTU-Master hätte.

Verbessert mich, wenn ich falsch liege. :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nach meine Kenntnisse kann ich nur 1 Befehl pro Slave ausführen, das gleichzeitige write oder read auf einen Slave geht nicht, oder?
Kann ich aber das mehrfache schreiben von Coils auf ein Slave ausführen, das will ich eben mit WriteMultipleCoils schaffen.
Wenn der Slave 8 Ausgänge hat wie kann ich diese gleichzeitig schalten?
Ich kann einfach nicht den WriteMultipleCoils so zusammenstellen dass die Ausgänge so geschaltet werden wie sie im Array [0..7] gleichzeitig an den Slave gesendet und geschaltet werden.
Vielen Dank
 
Danke Holger
Nein, mehrere Masters werde ich sicherlich nicht einsetzten da ich ja die RS485 onboard auf mein CX habe.
Ich kann nur nicht verstehen wieso immer nur das 1. Coil auf mein Slave geschaltet wird wenn ich WriteMultipleCoils verwende.

Code:
ModbusRTU.WriteMultipleCoils(UnitID:=ModbusAddress[4],
	Quantity:=8 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDigiOut01),
	pMemoryAddr:= ADR(arrDigiOut01),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );

Beim verwenden von ReadRegs gelingt es mir zB. Fühlerwerte zu lesen.

Code:
ModbusRTU.ReadRegs (UnitID:=ModbusAddress[3],
	Quantity:=8,
	MBAddr:=8,
	cbLength:=SIZEOF( arrWI03),
	pMemoryAddr:= ADR(arrWI03),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );

Wie gesagt nur das einmalige Schalten der Coils auf ein Slave gelingt mir nicht.
Danke für den Support
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hej j_poool,

ich kenne die Beckhoff-SPS und die verwendete Modbus-Funktion nicht näher. Vorausgesetzt du hast sie richtig parametriert würde mich interessieren was auf der Leitung zu sehen ist. Also Modbus RS485 ggf. über Wandler auf serielle PC-Schnittstelle und mit einem Terminalprogramm mitlesen was auf dem Bus läuft. Die Modbus-Telegramme sind ja einfach strukturiert und genügend dokumentiert. So kannst du schnell sehen ob die Startadresse im Slave, die Anzahl der Coils usw. richtig im Telegramm eingetragen sind und übertragen werden.

Gruss Corrado
 
Ist die MB Adressse 0 für den Slave wirklich richtig ?
welchen Online Wert hat cbLenght?
Welches Datenformat hat arrDigiOut01 (Word)?

Nachtrag:
Welche MB Error Nummer kommt?
 
Zuletzt bearbeitet:
Hallo Corrado!!
Auslesen von Regs oder Schreiben von Coils funktioniert einwandfrei wie ich es programmiert habe...
Code:
IF  bEnable THEN

	CASE iStepConfig OF
0:


ModbusRTU.WriteSingleCoil(Execute:= FALSE); (* initialize *)
ModbusRTU.ReadInputStatus(Execute:= FALSE);
ModbusRTU.ReadRegs(Execute:= FALSE);


		(* select one out of eight Modbus slaves *)
		Unit := Unit + 1;
		IF Unit > 11 THEN (*!!! Max Units eintragen !!!*)
			Unit := 1;
		END_IF


		iStepConfig := 1;


	(*=================*)
	(* test data only!!! *)
		IF Unit = 1 THEN
	 		x := x + 1;
			IF x >= 100 THEN x := 0; END_IF
			FOR i := 0 TO 9 DO
				MBdata[i] := i*100 + x;
			END_FOR
		END_IF
	(*=================*)


(****************************************** Ausgänge ModBus A8R  ******************************************)
1:


	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=0,
	cbLength:=1(*SIZEOF( arrOut[0])*),
	pMemoryAddr:= ADR(arrOut[0]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


2:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=1,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[1]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF
3:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=2,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[2]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




4:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1,
	MBAddr:=3,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[3]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


5:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=4,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[4]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


6:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=5,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[5]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF






7:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=6,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[6]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




8:
	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=1 ,
	MBAddr:=7,
	cbLength:=1,
	pMemoryAddr:= ADR(arrOut[7]),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


(****************************************** Eingänge ModBus EI  ******************************************)


9:


	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[4],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI04),
	pMemoryAddr:= ADR(arrDI04),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


10:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[6],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI06),
	pMemoryAddr:= ADR(arrDI06),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF
11:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[7],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI07),
	pMemoryAddr:= ADR(arrDI07),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




12:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[8],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI08),
	pMemoryAddr:= ADR(arrDI08),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


13:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[9],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI09),
	pMemoryAddr:= ADR(arrDI09),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


14:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[10],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI10),
	pMemoryAddr:= ADR(arrDI10),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF






15:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[11],
	Quantity:=4 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI11),
	pMemoryAddr:= ADR(arrDI11),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF






(****************************************** Einänge ModBus WI  ******************************************)
16:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[3],
	Quantity:=8,
	MBAddr:=8,
	cbLength:=SIZEOF( arrWI03),
	pMemoryAddr:= ADR(arrWI03),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF
17:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[4],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI04),
	pMemoryAddr:= ADR(arrWI04),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


18:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[6],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI06),
	pMemoryAddr:= ADR(arrWI06),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF


19:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[7],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI07),
	pMemoryAddr:= ADR(arrWI07),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




20:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[8],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI08),
	pMemoryAddr:= ADR(arrWI08),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




21:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[9],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI09),
	pMemoryAddr:= ADR(arrWI09),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




22:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[10],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI10),
	pMemoryAddr:= ADR(arrWI10),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=iStepConfig+1;
			END_IF
		END_IF




23:
ModbusRTU.ReadRegs (
UnitID:=ModbusAddress[11],
	Quantity:=4,
	MBAddr:=4,
	cbLength:=SIZEOF( arrWI11),
	pMemoryAddr:= ADR(arrWI11),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.ReadRegs(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=0;
			END_IF
		END_IF


(**************************************************test*****************************************************)
(*
24:
	ModbusRTU.ReadInputStatus (
UnitID:=ModbusAddress[1],
	Quantity:=8 ,
	MBAddr:=0,
	cbLength:=SIZEOF( arrDI01),
	pMemoryAddr:= ADR(arrDI01),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );


IF NOT bBusy THEN
			ModbusRTU.ReadInputStatus(Execute:= FALSE);
			IF ModbusRTU.Error THEN
				iStepConfig := 0;
			ELSE
				iStepConfig :=0;
			END_IF
		END_IF
*)
END_CASE


END_IF
(*******************************************************************************************************)
FtrigBusy(CLK:=ModbusRTU.BUSY );
IF FtrigBusy.Q THEN
	IF ModbusRTU.Error THEN
		LastModbusError := ModbusRTU.ErrorDiagnostics;
		LastErrorstate := iStepConfig;
		CounterError := CounterError + 1;
	ELSE
		CounterSuccess := CounterSuccess + 1;
	END_IF
END_IF

Nur, so wie es hier mit WriteSingleCoil programmiere (CASE 1 bis 8) wird alles sehr langsam (nicht wenn ich nur 1-2 Slaves habe), da ich jedes einzelne Bit pro Slave schreibe.
Das hängt in erster Linie durch die Variable tTimeout (<50ms Fehler Modbus).
Um alles zu beschleunigen will ich alles in WriteMultipleCoils umwandeln damit ich zB. Slave 1 die Coils in ein Array (0..7) habe und diese nur in eine CASE Funktion schreiben kann.
Hoffentlich habe ich mich gut ausgedrückt. :-D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ist denn arrDigiOut01 für ein Array?
Frage hat sich gerade beantwortet. Müsste ein Array of Bit sein, falls ja liegt genau da der Fehler. Hier mal ein Auszug aus der TC2 Doku:

Modbus_01.PNG

Wenn Du anstatt eines Array of Bit nur ein Byte überträgst (cbLength dann 1 und nicht 8 ) sollte es gehen.

Gruß

Oliver
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hej j_poool,

natürlich macht es Sinn die Modbus-Funktion 15 (Force Multiple Outputs) zu verwenden wenn die Bits (Coils, Outputs) alle nebeneinander liegen. Vorausgesetzt dass du die Funktion "ModbusRTU.WriteMultipleCoils(..." auch richtig versorgt hast und dein Slave die Modbus-Funktion 15 versteht sollte es gehen.

Es sind doch nur 3 mögliche Fehlerursachen:
  1. Beckhoff-SPS-Funktion falsch parametriert
  2. Beckhoff-SPS-Funktion hat Bug
  3. Slave versteht Modbus-Funktion-15 nicht oder nicht richtig

Darum habe ich dir vorgeschlagen zu untersuchen was wirklich auf der leitung übertragen wird. Tip: Die Antwort des Slave zeigt auch einen Fehlercode.

Gruss Corrado
 
Die Lösung hat Oliver ja bereits genannt.
Was mir noch aufgefallen ist, wenn ein Slave (z.B. 2) ausfällt, werden auch alle anderen nicht mehr abgefragt, da du den Schrittzähler löschst.
Desweiteren ist eine Auswertung der Fehlercodes durchaus hilfreich bei einem Problem;). Eventuell solltest du dir auch überlegen, besonders die digitalen Eingänge bei einem Fehler mit einem Ersatzwert zu beschreiben.

Szenario:
An Slave 4 ist ein Taster "vor" der als TRUE gelesen wird. Jetzt fällt Slave 3 aus. Deine Schrittkette kommt nicht mehr zu dem Punkt wo der Taster neu gelesen wird. Deine Variable für Taster"vor" bleibt also auf Ewigkeit TRUE.
Holger
 
Was mir noch aufgefallen ist, wenn ein Slave (z.B. 2) ausfällt, werden auch alle anderen nicht mehr abgefragt, da du den Schrittzähler löschst.

Szenario:
An Slave 4 ist ein Taster "vor" der als TRUE gelesen wird. Jetzt fällt Slave 3 aus. Deine Schrittkette kommt nicht mehr zu dem Punkt wo der Taster neu gelesen wird. Deine Variable für Taster"vor" bleibt also auf Ewigkeit TRUE.
Holger
Ja, ist mir auch aufgefallen, werde das auch dementsprechend umändern, trotzdem Danke ;)
 
Hallo blueOcean
Baudrate habe ich auf verschieden Einstellungen getestet (9600,19200,38400)

Hast du Erfahrung mit BD Modbus Geräte?

Code:
wOut01 : WORD;
Code:
1:	ModbusRTU.WriteSingleCoil (
UnitID:=ModbusAddress[Unit],
	Quantity:=8 ,
	MBAddr:=0,
	cbLength:=SIZEOF( wOut01)*),
	pMemoryAddr:= ADR(wOut01),
	Execute:= TRUE,
	Timeout:= tTimeout,
	BUSY=>bBUSY );




		IF NOT bBusy THEN
			ModbusRTU.WriteSingleCoil(Execute:= FALSE);
			
				iStepConfig :=iStepConfig+1;
			
		END_IF

Sollte eingentlich passen....

Wie ich die Digitale Eingänge auslese (zB. wIn01 = 3, dh. Eingang 1 und 2 sind TRUE )
Könnte ich auch die Ausgänge so schreiben (zB. wOut01 := 4, dh. Ausgang 3 geht auf TRUE)

Danke
 
bitte nicht Vergessen:

cbLength : Größe des verwendeten Datenvariable für Sende- oder Lese-Aktionen in Bytes. cbLength muss größer oder gleich der durch Quantity bestimmten übertragenen Datenmenge sein. Bei Wortzugriffen gilt z. B.: [cbLength >= Quantity * 2]. cbLength kann mit SIZEOF(ModbusDaten) berechnet werden.

aus FUNCTION_BLOCK ModbusRtuMaster_PcCom
http://infosys.beckhoff.de/content/...usrtu_master_pccom.htm?id=3906700278390470754


evtl. so : cbLength:= 2* RtuMaster.Quantity,

und die Weiterschaltbedingung ist immer eine fallende Flanke am Busy. (mache ich so ist aber nicht bindend)

welche Reaktionszeiten erwartest Du an den Modulen? denn ein Modbusbefehl mit Antwort belegt gerne mal 600ms bei 9600 bd da die Antwort in der Regel nicht gleich nach dem Empfang vom Slave Quittiert wird. Du könntest mit dem TC Scope mal messen wie lange der Busy ansteht bzw. wie lange der Durchlauf deiner Schrittkette dauert.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo An alle!!
Vielen Dank an alle. Die Lösung ist tatsächlich diese die ich oben genannt habe,
mein Fehler war dass ich auf alte Programmierungen die Variablen in cbLenght und pMemoryAddr als Array of BOOL deklariert habe.
Da muss eine WORD Variable hinzugefügt werden.
 
Zurück
Oben