mbuesch / pyprofibus

PROFIBUS-DP stack
https://bues.ch/a/profibus
GNU General Public License v2.0
133 stars 52 forks source link

Festo CPV Valve terminal #19

Closed Sigma1912 closed 3 years ago

Sigma1912 commented 3 years ago

Hi I'm quite new to Profibus and I'm trying to connect LinuxCNC to a Festo CPV valve terminal. Communication is established through a built in RS485 port, however there are timeouts during 'data_exchange'.
So it seems I'm missing something and I'd appreciate it if you could look this over and maybe point me in the right direction. Thanks.

Terminal output:

user@optiplex7010:~/linuxcnc-master-02072021/configs/pyprofibus-master/linuxcnc-demo-cpv10-ge$ ./run-linuxcnc-demo.sh 
LINUXCNC - 2.9.0~pre0
Machine configuration directory is '/home/user/linuxcnc-master-02072021/configs/pyprofibus-master/linuxcnc-demo-cpv10-ge/.'
Machine configuration file is 'linuxcnc-demo.ini'
Starting LinuxCNC...
emc/iotask/ioControl.cc 769: can't load tool table.
Found file(REL): ./linuxcnc-demo.hal
Note: Using POSIX realtime
Unexpected realtime delay on task 0 with period 20000
This Message will only display once per session.
Run the Latency Test and resolve before continuing.
Found file(REL): ./profibus.hal
GSD parser warning in 'cpv_0A35.gse' at line 14:
FMS_supp            = 0
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 63:
Unit_Diag_Bit(8)    = "CPI-connection to output modul"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 64:
Unit_Diag_Bit(9)    = "CPI-connection to input modul"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 65:
Unit_Diag_Bit(10)   = "short circuit / overload output"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 66:
Unit_Diag_Bit(11)   = "power load failure output module"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 67:
Unit_Diag_Bit(12)   = "sensor power supply < 10V"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 68:
Unit_Diag_Bit(13)   = "valve power supply < 20.4V"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 69:
Unit_Diag_Bit(14)   = "valve power supply < 10V"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 70:
Unit_Diag_Bit(15)   = "no update-mode"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 71:
Unit_Diag_Bit(16)   = "failure main module"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 72:
Unit_Diag_Bit(17)   = "failure 1. CP- module"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 73:
Unit_Diag_Bit(18)   = "failure 2. CP- module"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 74:
Unit_Diag_Bit(19)   = "failure 3. CP- module"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 75:
Unit_Diag_Bit(20)   = "failure 4. CP- module"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 95:
Bit(1) 1 0-1
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 100:
Bit(7) 1 0-1
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 105:
BitArea(0-1) 0 0-2
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 110:
unsigned8 0 0-255
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 114:
unsigned16 0 0-65535
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 118:
unsigned32 0 0-16777215
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 122:
unsigned32 0 0-4294967295
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 126:
unsigned8 91 0-255
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 132:
Info_Text = "Base unit CPV-SC with 16 digital outputs (valve coils)"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 133:
1
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 143:
Info_Text = "String extension with 8 digital outputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 144:
2
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 153:
Info_Text = "String extension with 16 digital outputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 154:
3
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 163:
Info_Text = "String extension with 24 digital outputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 164:
4
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 173:
Info_Text = "String extension with 32 digital outputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 174:
5
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 183:
Info_Text = "String extension with 8 digital inputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 184:
6
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 191:
Info_Text = "String extension with 16 digital inputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 192:
7
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 199:
Info_Text = "String extension with 24 digital inputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 200:
8
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 207:
Info_Text = "String extension with 32 digital inputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 208:
9
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 215:
Info_Text = "tool change mode with 32 inputs and 32 outputs"
 --> Ignored unknown line
GSD parser warning in 'cpv_0A35.gse' at line 216:
10
 --> Ignored unknown line
pyprofibus: DP slave 8 output: 2 bytes
pyprofibus: DP slave 8 input:  0 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
pyprofibus: Active DP slave (addr=8) pins:
pyprofibus: DP output:  profibus.slave.8.output.bit.0.0
pyprofibus: DP output:  profibus.slave.8.output.bit.0.1
pyprofibus: DP output:  profibus.slave.8.output.bit.0.2
pyprofibus: DP output:  profibus.slave.8.output.bit.0.3
pyprofibus: DP output:  profibus.slave.8.output.bit.0.4
pyprofibus: DP output:  profibus.slave.8.output.bit.0.5
pyprofibus: DP output:  profibus.slave.8.output.bit.0.6
pyprofibus: DP output:  profibus.slave.8.output.bit.0.7
pyprofibus: HAL configuration done
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
note: MAXV     max: 30.000 units/sec 1800.000 units/min
note: LJOG     max: 30.000 units/sec 1800.000 units/min
note: LJOG default: 10.000 units/sec 600.000 units/min
note: jog_order='XYZ'
note: jog_invert=set([])
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 13 13 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 7B 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 06 06 68 88 82 7D 3E 3E 21 24 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
DPM1: Data_Exchange timeout with slave 8
PHY-serial: TX   68 05 05 68 08 02 7D 00 00 87 16
PHY-serial: RX   E5
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: Slave 8 requests a new parameterization (Set_Prm).
DPM1: slave[08].state --> 'init'
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 13 13 68 88 82 7D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 9B 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 06 06 68 88 82 5D 3E 3E 21 04 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 5D 01 00 68 16
PHY-serial: RX   E5
DPM1: Data_Exchange timeout with slave 8
PHY-serial: TX   68 05 05 68 08 02 5D 00 00 67 16
PHY-serial: RX   E5
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: Slave 8 requests a new parameterization (Set_Prm).
DPM1: slave[08].state --> 'init'
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 13 13 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 7B 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 06 06 68 88 82 7D 3E 3E 21 24 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 00 00 87 16
PHY-serial: RX   E5
DPM1: Data_Exchange timeout with slave 8
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 5D 00 00 67 16
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: PROFIBUS fault:
Service not active on slave 8
DPM1: Data_Exchange timeout with slave 8
PHY-serial: TX   68 05 05 68 08 02 7D 00 00 87 16
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: Fatal fault detected
pyprofibus: Fatal PROFIBUS fault:
Service not active on slave 8
pyprofibus: LinuxCNC HAL module shutdown.

The gsd file:

;*****************************************************************************;
; Geraetestammdatei fuer CPV-Ventilinsel mit direktem Profibus DP-Anschluß   ;
; Hersteller: Fa. FESTO AG&Co., Ruiterstrasse 82, 73734 Esslingen             ;
;   FESTO Hotline-Tel.: 0711/347-3000                                           ;
;*****************************************************************************;
#Profibus_DP
GSD_Revision        = 5
Vendor_Name         = "Festo AG&Co."
Model_Name          = "Festo CPV-DI02"
Revision            = "28.06.06"
Ident_Number        = 0x0A35
Protocol_Ident      = 0
Station_Type        = 0
FMS_supp            = 0
Hardware_Release    = "12.05"
Software_Release    = "V1.3"
;
9.6_supp            = 1
19.2_supp           = 1
93.75_supp          = 1
187.5_supp          = 1
500_supp            = 1
1.5M_supp           = 1
3M_supp             = 1
6M_supp             = 1
12M_supp            = 1
;
MaxTsdr_9.6         = 20
MaxTsdr_19.2        = 20
MaxTsdr_93.75       = 20
MaxTsdr_187.5       = 20
MaxTsdr_500         = 20
MaxTsdr_1.5M        = 25
MaxTsdr_3M          = 50
MaxTsdr_6M          = 100
MaxTsdr_12M         = 200
;
Redundancy          = 0
Repeater_Ctrl_Sig   = 2
24V_Pins            = 0
Implementation_Type = "SPC3"
Bitmap_Device       = "pb_dicpn"
;Bitmap_Diag         = "pb_dicpd"
;Bitmap_SF           = "pb_dicps"
;
Freeze_Mode_supp    = 1
Sync_Mode_supp      = 1
Auto_Baud_supp      = 1
Set_Slave_Add_supp  = 0
Min_Slave_Intervall = 0x0005
;
Modular_Station     = 1
Max_Module          = 0x05
Max_Input_Len       = 0x04
Max_Output_Len      = 0x06
Max_Data_Len        = 0x000A
Modul_Offset        = 1
;
Fail_Safe           = 0
Slave_Family        = 4
Max_Diag_Data_Len   = 0x0010
;
Unit_Diag_Bit(8)    = "CP-Anschluss zu Ausgangsmodul"
Unit_Diag_Bit(9)    = "CP-Anschluss zu Eingangsmodul"
Unit_Diag_Bit(10)   = "Kurzschluss/Ueberlast Ausgang"
Unit_Diag_Bit(11)   = "Lastspg.ausfall Ausgangsmodul"
Unit_Diag_Bit(12)   = "Sensorversorgung < 10V"
Unit_Diag_Bit(13)   = "Versorgungsspg.Ventile < 20.4V"
Unit_Diag_Bit(14)   = "Versorgungsspg.Ventile < 10V"
Unit_Diag_Bit(15)   = "kein Update-Betrieb"
Unit_Diag_Bit(16)   = "Fehler Basismodul"
Unit_Diag_Bit(17)   = "Fehler 1. CP- Modul"
Unit_Diag_Bit(18)   = "Fehler 2. CP- Modul"
Unit_Diag_Bit(19)   = "Fehler 3. CP- Modul"
Unit_Diag_Bit(20)   = "Fehler 4. CP- Modul"
;
Max_User_Prm_Data_Len = 0x1E

;------------------Definition der Parametertexte-----------------

PrmText = 1                                  ; Referenznummer 1
Text(0) = "inaktiv"
Text(1) = "aktiv"
EndPrmText 

PrmText = 2                                 ; Referenznummer 2
Text(0) = "Ausgaenge zuruecksetzen"
Text(1) = "Ausgaenge Fault Mode"
Text(2) = "Ausgaenge Hold Last State"
EndPrmText

ExtUserPrmData = 1 "Monitor U-Last"                      ; Referenznummer 1
Bit(1) 1 0-1                                            ; Default = 1, Min = 0, Max = 1
Prm_Text_Ref = 1                                   ; Verweis auf Text-Definition 1
EndExtUserPrmData

ExtUserPrmData = 2 "Monitor Fehler CP-Line"                      ; Referenznummer 2
Bit(7) 1 0-1                                            ; Default = 1, Min = 0, Max = 1
Prm_Text_Ref = 1                                   ; Verweis auf Text-Definition 1
EndExtUserPrmData

ExtUserPrmData = 3 "Fault Mode"                  ; Referenznummer 3
BitArea(0-1) 0 0-2                                          ; Default = 0, Min = 0, Max = 3
Prm_Text_Ref = 2                                           ; Verweis auf Text-Definition 2
EndExtUserPrmData

ExtUserPrmData = 4 "Fault State 1byte"              ; Referenznummer 4
unsigned8 0 0-255                                        ; Default = 0, Min = 0, Max = 255
EndExtUserPrmData

ExtUserPrmData = 5 "Fault State 2byte"              ; Referenznummer 5
unsigned16 0 0-65535                                        ; Default = 0, Min = 0, Max = 65535
EndExtUserPrmData

ExtUserPrmData = 7 "Fault State 3byte"              ; Referenznummer 7
unsigned32 0 0-16777215                             ; Default = 0, Min = 0, Max = 16777215
EndExtUserPrmData

ExtUserPrmData = 8 "Fault State 4byte"              ; Referenznummer 8
unsigned32 0 0-4294967295                            ; Default = 0, Min = 0, Max = 4294967295
EndExtUserPrmData

ExtUserPrmData = 6 "Parameterbyte"                 ; Referenznummer 6
unsigned8 91 0-255                                 ; Default = 91, Min = 0, Max = 255
EndExtUserPrmData

;-------------------- Modultypen -------------------------
; <Module-Definition-List>
Module = "Basis:16DA" 0x21
1
Ext_Module_Prm_Data_Len = 7
Ext_User_Prm_Data_Const(0) = 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00
Ext_User_Prm_Data_Ref(3) = 1
Ext_User_Prm_Data_Ref(3) = 2
Ext_User_Prm_Data_Ref(4) = 3
Ext_User_Prm_Data_Ref(5) = 5
EndModule

Module = "CP-A08" 0x20
2
Ext_Module_Prm_Data_Len = 3
Ext_User_Prm_Data_Const(0) = 0x5B, 0x00, 0x00
Ext_User_Prm_Data_Ref(0) = 6
Ext_User_Prm_Data_Ref(1) = 3
Ext_User_Prm_Data_Ref(2) = 4
EndModule

Module = "CP-A16" 0x21
3
Ext_Module_Prm_Data_Len = 4
Ext_User_Prm_Data_Const(0) = 0x5B, 0x00, 0x00, 0x00
Ext_User_Prm_Data_Ref(0) = 6
Ext_User_Prm_Data_Ref(1) = 3
Ext_User_Prm_Data_Ref(2) = 5
EndModule

Module = "CP-A24" 0x22
4
Ext_Module_Prm_Data_Len = 6
Ext_User_Prm_Data_Const(0) = 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00
Ext_User_Prm_Data_Ref(0) = 6
Ext_User_Prm_Data_Ref(1) = 3
Ext_User_Prm_Data_Ref(2) = 7
EndModule

Module = "CP-A32" 0x23
5
Ext_Module_Prm_Data_Len = 6
Ext_User_Prm_Data_Const(0) = 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00
Ext_User_Prm_Data_Ref(0) = 6
Ext_User_Prm_Data_Ref(1) = 3
Ext_User_Prm_Data_Ref(2) = 8
EndModule

Module = "CP-E08" 0x10
6
Ext_Module_Prm_Data_Len = 1
Ext_User_Prm_Data_Const(0) = 0x5B
Ext_User_Prm_Data_Ref(0) = 6
EndModule

Module = "CP-E16" 0x11
7
Ext_Module_Prm_Data_Len = 1
Ext_User_Prm_Data_Const(0) = 0x5B
Ext_User_Prm_Data_Ref(0) = 6
EndModule

Module = "CP-E24" 0x12
8
Ext_Module_Prm_Data_Len = 1
Ext_User_Prm_Data_Const(0) = 0x5B
Ext_User_Prm_Data_Ref(0) = 6
EndModule

Module = "CP-E32" 0x13
9
Ext_Module_Prm_Data_Len = 1
Ext_User_Prm_Data_Const(0) = 0x5B
Ext_User_Prm_Data_Ref(0) = 6
EndModule

Module = "Werkzeugw. A/E:32/32" 0x33
10
Ext_Module_Prm_Data_Len = 9
Ext_User_Prm_Data_Const(0) = 0x5B, 0x5B, 0x5B, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00
Ext_User_Prm_Data_Ref(0) = 6
Ext_User_Prm_Data_Ref(1) = 6
Ext_User_Prm_Data_Ref(2) = 6
Ext_User_Prm_Data_Ref(3) = 6
Ext_User_Prm_Data_Ref(4) = 3
Ext_User_Prm_Data_Ref(5) = 8
EndModule

My config:

; ----------------------------------------------- ;
;                                                 ;
; PROFIBUS configuration                          ;
;                                                 ;
; This file configures a pyprofibus instance.     ;
;                                                 ;
; ----------------------------------------------- ;

; General settings
[PROFIBUS]
; Enable/disable debug mode.
; 0 -> no debugging.
; 1 -> DP debugging.
; 2 -> DP and PHY debugging.
debug=2

; PHY protocol layer configuration
[PHY]

; The PHY layer driver type.
type=serial

; The PHY device name/path.
; Can be a device like /dev/ttyS0 or /dev/ttyAMA0 for 'serial'.
dev=/dev/ttyS3

; The Profibus on-wire baud rate.
baud=19200

; FDL protocol layer configuration
[FDL]

; DP protocol layer configuration
[DP]

; The master device class. Either 1 or 2.
master_class=1

; The Profibus address of this device.
master_addr=2

; ---
; Slave configurations
; Add as many [SLAVE_xxx] sections as needed.
; ---

; First slave configuration
[SLAVE_0]

; Optional slave name. Will be stored in slaveConf.name and slaveDesc.name.
; pyprofibus does not use the name internally.
name=cpv10

; This slave's Profibus address
addr=8

; The path to the GSD file.
gsd=cpv_0A35.gse

; Boolean: Sync mode enabled/available?
sync_mode=1

; Boolean: Freeze mode enabled/available?
freeze_mode=1

; 8 bit integer specifying the Profibus group ident mask.
group_mask=1

; This slave's watchdog timeout, in milliseconds.
watchdog_ms=300

; Module configuration.
; For each module plugged into the slave, add a module_xxx
; entry with the name of the module.
; The module name must match the name from the GSD file (approximately).
; The modules are used in the order of the index number.
module_0=Base module:16DO

; The number of output bytes this slave transmits to the
; master in Data_Exchange.
; This usually depends on the modules plugged into the slave.
output_size=2

; The number of input bytes this slave expects to receive
; in Data_Exchange.
; This usually depends on the modules plugged into the slave.
input_size=0

`

mbuesch commented 3 years ago

Hi. Thanks for your question.

The initialization phase of your logs actually looks quite good. It successfully enters Data_Exchange mode.

You configured input_size=0. Is that really intended? Pyprofibus currently doesn't correctly support unidirectional Data_Exchange. (out or in being zero bytes). Simply because that operating mode has not been implemented, yet. You might want to take a look at the Data_Exchange section in dp_master.py.

Sigma1912 commented 3 years ago

; The number of output bytes this slave transmits to the ; master in Data_Exchange. ; This usually depends on the modules plugged into the slave. output_size=2

; The number of input bytes this slave expects to receive ; in Data_Exchange. ; This usually depends on the modules plugged into the slave. input_size=0

I guess this doesn't really make any sense, since it should be other way around it seems. But then the output pins are not created in HAL

...
 --> Ignored unknown line
pyprofibus: DP slave 8 output: 0 bytes
pyprofibus: DP slave 8 input:  2 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
./profibus.hal:25: parameter or pin 'profibus.slave.8.output.bit.0.0.active' not found
Shutting down and cleaning up LinuxCNC...
pyprofibus: LinuxCNC HAL module shutdown.
Sigma1912 commented 3 years ago

Thanks for your response I'll have a look at it.

mbuesch commented 3 years ago

But then the output pins are not created in HAL

Hm, that could actually be a bug. I'm not quite sure right now. It's quite confusing what's in and what's out for slave, master, hal and so on :)

In pyprofibus-linuxcnc-hal you could try to swap the assignments of inputSize and outputSize. (around line 526 at the createHalPins() call)

mbuesch commented 3 years ago

Reading through the code: The HAL pins are named from the slave perspective. So it possibly is correct as implemented. You just need to use the slave.8.input... pins. These are HAL_OUT. That seems to be correct, I think.

Sigma1912 commented 3 years ago

Thanks again, I'll give it a try.

mbuesch commented 3 years ago

Cool. The bigger problem is in the main Data_Exchange code, though. I'm quite sure that needs some changes for unidirectional transfers. There's even a TODO comment in there. :)

I'm not sure how that change would look like. It could possibly be as simple as don't using the timeout mechanism for input-only slaves.

Sigma1912 commented 3 years ago

So as a first quick try I commented out lines 606...612 in dp_master.py:


            if dataExInData is None:
                if slave.pendingReqTimeout.exceed():
                    self.__debugMsg("Data_Exchange timeout with slave %d" % (
                            slave.slaveDesc.slaveAddr))
                    slave.faultDeb.fault()
                    slave.pendingReq = None
            else:

But now I get state_machine timeouts:


PHY-serial: TX   68 05 05 68 08 02 7D 00 00 87 16
PHY-serial: RX   E5
DPM1: State machine timeout! Trying to re-initializing slave 8...
DPM1: Trying to initialize slave 8...

I have also tried to inject a value for 'data'ExInData' but then the master doesn't wait for the slave to respond before sending the next request. I guess the problem is that the master needs to wait for the slave to send the acknowledge (E5) and then continue before the timeout is exceeded. So maybe I would need to parse the response to see if it contains E5.

[edit] looks like the E5 in the response is correctly parsed as an SC but the telegram is flagged as 'Fdl' instead of 'SD..' :

PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
telegram : FdlTelegram(sd=SC, haveLE=False, da=None, sa=None, fc=None, dae=Empty, sae=Empty, du=None, haveFCS=False, ed=None)
DPM1: Data_Exchange timeout with slave 8

Not sure if it's just the 'du=None' that needs to be addressed or if the 'FdlTelegram' itself causes problems.

Sigma1912 commented 3 years ago

Ok, I'm a step further. I think.

I inserted this at line 589 in dp_master.py ( not sure if all of the four lines at the end are required but I just copied that from the else block with the comment '# We received some data'.:

        if slave.shortAckReceived:
                print(":line590: SHORT_ACK RECIEVED")
                slave.pendingReq = None
                slave.faultDeb.ok()
                slave.restartStateTimeout()
                self._releaseSlave(slave)

So now I don't get the timeouts as before during data_exchange but after a short while I get an RS-fault (SAP not enabled) response from the slave 'Service not active on slave 8'. I'm at a loss as to why this happens since the request from the master doesn't change at all:

pyprofibus: DP slave 8 output: 2 bytes
pyprofibus: DP slave 8 input:  0 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
pyprofibus: Active DP slave (addr=8) pins:
pyprofibus: DP output:  profibus.slave.8.output.bit.0.0
pyprofibus: DP output:  profibus.slave.8.output.bit.0.1
pyprofibus: DP output:  profibus.slave.8.output.bit.0.2
pyprofibus: DP output:  profibus.slave.8.output.bit.0.3
pyprofibus: DP output:  profibus.slave.8.output.bit.0.4
pyprofibus: DP output:  profibus.slave.8.output.bit.0.5
pyprofibus: DP output:  profibus.slave.8.output.bit.0.6
pyprofibus: DP output:  profibus.slave.8.output.bit.0.7
pyprofibus: HAL configuration done
Unexpected realtime delay on task 0 with period 20000
This Message will only display once per session.
Run the Latency Test and resolve before continuing.

DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 13 13 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 7B 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 06 06 68 88 82 7D 3E 3E 21 24 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
note: MAXV     max: 30.000 units/sec 1800.000 units/min
note: LJOG     max: 30.000 units/sec 1800.000 units/min
note: LJOG default: 10.000 units/sec 600.000 units/min
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
note: jog_order='XYZ'
note: jog_invert=set([])
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECIEVED
PHY-serial: TX   68 05 05 68 08 02 7D 05 00 8C 16
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: PROFIBUS fault:
Service not active on slave 8
DPM1: Data_Exchange timeout with slave 8
PHY-serial: TX   68 05 05 68 08 02 5D 05 00 6C 16
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: Fatal fault detected
pyprofibus: Fatal PROFIBUS fault:
Service not active on slave 8
pyprofibus: LinuxCNC HAL module shutdown.
Shutting down and cleaning up LinuxCNC.. 
mbuesch commented 3 years ago

Very nice. Does the slave show some life before you get the SAP fault? (e.g. some valve switching, as requested by the TX data).

mbuesch commented 3 years ago

Oh I just noticed that right before the fault you receive a different telegram from the slave: PHY-serial: RX 10 02 08 03 0D 16

Can you try to decode this? It might be some diagnosis request or something else that has to be serviced.

Sigma1912 commented 3 years ago

The slave correctly switches the valves and after about half a second it goes into error mode as the pyprofibus component shuts down because of the fault. But it did that also before I made the changes to dp_master.py.

According to this : https://www.felser.ch/profibus-manual/funktionscode.html I interpret the Response Function Code as being hex 03 -> slave , 'RS = SAP not enabled' Which seems strange since in Data_exchange mode there is no SAP, as I understand it.

Problem is I don't have another profibus device so I can't test if the device itself is faulty. Although the one I have was supposed to come from a working machine. The only thing I could do is have a look at the data with a scope. But really I don't expect it to send different request telegrams then what it prints to the terminal.

[edit] Scope shows the same as the terminal, so no indication as to what may be causing the slave to consistently throw that fault.

mbuesch commented 3 years ago

I don't think the device is broken. But I can only guess what's going on here. My guess would be: The slave expects some kind of periodic non-Data_Exchange telegram every couple of milliseconds. For example like a diagnosis data fetch or something like that. The slave has no way to send a diagnostic request with the short-ack. So expecting the master to periodically poll the diagnosis data would make some sense.

Do you have an S7 or something similar? Then you could sniff the Profibus. That way you could check which packets are being sent around.

In any case, I think your changes would be a nice contribution, once resolved this. Feel free to open a Pull Request, as soon as you feel comfortable with the changes.

Sigma1912 commented 3 years ago

One thing I notice it that with half the baud rate (ie 9600) the master does one reinitialization before shutting down:

PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 13 13 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 7B 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 06 06 68 88 82 7D 3E 3E 21 24 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: PROFIBUS fault:
Service not active on slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: Slave 8 requests a new parameterization (Set_Prm).
DPM1: slave[08].state --> 'init'
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 13 13 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 7B 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 06 06 68 88 82 7D 3E 3E 21 24 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   E5
:line590: SHORT_ACK RECEIVED
PHY-serial: TX   68 05 05 68 08 02 7D 01 00 88 16
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: Fatal fault detected
pyprofibus: Fatal PROFIBUS fault:
Service not active on slave 8
pyprofibus: LinuxCNC HAL module shutdown.

I also notice that the fault occurs after 15 data requests while with 19200baud it seems to be after 30 requests. So maybe there is indeed a timeout running in the slave. Although one would expect to find a reference in the device documentation. Unfortunately I don't have any other device.

mbuesch commented 3 years ago

The fatal HAL shutdown upon SAP failure probably is not really clever behaviour. I think the HAL or the dp-master core should try to debounce this fault better and retry a couple of times. But in your case that probably won't help. It will eventually shutdown anyway. So it's not the highest priority to fix now.

In the Data_Exchange handler you can see the path where it branches off to the diagnosis request state if the slave requested it. You might try with a simple counter that does this branch every 10 DX telegrams or so. It that works, we could have a more clever solution with a timer.

Sigma1912 commented 3 years ago

Thanks for your suggestion. I've inserted a counter and got it working (mostly). But the way I'm doing it is not quite right, because i don't really know what I'm doing. Simply doing a diagnosis request from inside the data_exchange loop causes an 'Ignoring telegram in DataExchange with slave 8' and a 'Data_Exchange timeout with slave 8' that is recovered though. As you suggested, there would have to be a cleverer solution for this but I'm out of my depth really.

...
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: Ignoring telegram in DataExchange with slave 8:
DpTelegram_SlaveDiag_Con(da=0x02, sa=0x08, fc=0x08, dsap=0x3E, ssap=0x3C, b0=0x00, b1=0x0C, b2=0x00, masterAddr=0x02, identNumber=0x0A35)
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 08 02 7D 14 14 AF 16
...
    def __runSlave_dataExchange(self, slave):
        #TODO: add support for in/out-only slaves
        dataExInData = None

        if slave.stateJustEntered():
            self.__debugMsg("Initialization finished. "
                "Running Data_Exchange with slave %d..." %\
                slave.slaveDesc.slaveAddr)
            slave.flushRxQueue()
            slave.dxStartTime = monotonic_time()

        if slave.shortAckReceived:
            slave.pendingReq = None
            slave.faultDeb.ok()
            slave.restartStateTimeout()
            self._releaseSlave(slave)
            self.__ScCount += 1

            if (self.__ScCount > 10):
                # Send a SlaveDiag request
                self.__send(slave,
                telegram=DpTelegram_SlaveDiag_Req(
                da=slave.slaveDesc.slaveAddr,
                sa=self.masterAddr),
                    timeout=0.05)
                                # Reset short confirmation counter
                self.__ScCount = 0
...
mbuesch commented 3 years ago

Ok, I understand. But that's not a problem. Would you like to fork this repo and upload your current changes anyway? I think that would be a good starting point to implement a more generic and/or correct solution. Even if the real solution would look completely different.

Sigma1912 commented 3 years ago

I created a fork here https://github.com/Sigma1912/pyprofibus/tree/master/pyprofibus with the modified dp_master.py.

Thanks for making this profibus stack available.

mbuesch commented 3 years ago

I'll try to prepare an experimental change for in-only slaves based on your changes. I'll let you know once that's ready for testing. Thanks!

mbuesch commented 3 years ago

I created a branch for the work on support for input-only slaves: https://github.com/mbuesch/pyprofibus/tree/in-only-slave

You may want to take a look at it. This code currently is mostly untested. But you might want to try it and give me some feedback.

Thanks.

Sigma1912 commented 3 years ago

Thanks for the update. I think the same confusion about the input_bytes and output_bytes trips me up again:

Because of this in line 625 in dp_master.py:

            if (dataExInData is not None or
                (slaveOutputSize == 0 and slave.shortAckReceived)):
                # We received some data.
                slave.pendingReq = None
                slave.faultDeb.ok()
                slave.restartStateTimeout()
                self._releaseSlave(slave)

I'm forced to change 'pyprofibus.conf' to output_size=0, input_size=4 (which would be correct if we look at the comments in the file) I get:

--> Ignored unknown line
pyprofibus: DP slave 8 output: 0 bytes
pyprofibus: DP slave 8 input:  4 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
./profibus.hal:25: parameter or pin 'profibus.slave.8.output.bit.0.0.active' not found
Shutting down and cleaning up LinuxCNC...
pyprofibus: LinuxCNC HAL module shutdown.
Note: Using POSIX realtime
LinuxCNC terminated with an error.  You can find more information in the log:
    /home/user/linuxcnc_debug.txt
and
    /home/user/linuxcnc_print.txt
as well as in the output of the shell command 'dmesg' and in the terminal

Because now the component creates the wrong hal-pins (ie. In HAL environment we need hal-pins with direction IN not OUT):

Screenshot from 2021-10-14 10-34-10

If you look at this hal command (which worked fine before because I "wrongly" defined 'output_bytes=4' and 'input_bytes=0'):

net estop-out   <= halui.estop.is-activated => profibus.slave.8.output.bit.0.0

We connect 'halui.estop.is-activated' (which is a hal-pin of direction OUT) to ' profibus.slave.8.output.bit.0.0' (which is, and needs to be, of hal-direction IN) Screenshot from 2021-10-14 10-44-26

However, now with the "correct" 'output_bytes=0' and 'input_bytes=4', there are only hal-pins created with hal-direction OUT (ie. 'profibus.slave.8.input.bit.x.x') and these are useless because in the hal-environment we cannot connect a pin of hal-direction OUT to another pin of hal-direction OUT.

I'll try and disable all hal related connections and see what the communication looks like.

Sigma1912 commented 3 years ago

So I disabled all Hal-connections to see what I get running your 'in-only-slave' fork. As far as I can tell, all goes well until we enter 'data_exchange' mode. Then the master sends PHY-serial: TX 10 08 02 7D 87 16 which seems odd to me and shortly after that the slave claims a configuration error.

pyprofibus: DP slave 8 output: 0 bytes
pyprofibus: DP slave 8 input:  4 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
pyprofibus: Active DP slave (addr=8) pins:
pyprofibus: HAL configuration done
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 17 17 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 5B 00 00 00 D6 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 07 07 68 88 82 7D 3E 3E 21 21 45 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   10 08 02 7D 87 16
PHY-serial: RX   E5
PHY-serial: TX   10 08 02 7D 87 16
PHY-serial: RX   10 02 08 03 0D 16
DPM1: Ignoring telegram in DataExchange with slave 8:
DpTelegram(da=0x02, sa=0x08, fc=0x03, dsap=None, ssap=None, du=Empty)
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 06 05 00 FF 0A 35 D5 16
DPM1:  >ERROR<  Slave 8 reports a faulty configuration (Chk_Cfg).
DPM1: Slave 8 requests a new parameterization (Set_Prm).
DPM1: slave[08].state --> 'init'
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
...

In comparison this is the terminal output from my working modification: Note, after entering 'data_exchange' mode the master sends PHY-serial: TX 68 07 07 68 08 02 7D 00 00 00 00 87 16 which seems correct.

pyprofibus: DP slave 8 output: 4 bytes
pyprofibus: DP slave 8 input:  0 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
pyprofibus: Active DP slave (addr=8) pins:
pyprofibus: HAL configuration done
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 17 17 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 5B 00 00 00 D6 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 07 07 68 88 82 7D 3E 3E 21 21 45 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: Ignoring telegram in DataExchange with slave 8:
DpTelegram_SlaveDiag_Con(da=0x02, sa=0x08, fc=0x08, dsap=0x3E, ssap=0x3C, b0=0x00, b1=0x0C, b2=0x00, masterAddr=0x02, identNumber=0x0A35)
DPM1: Data_Exchange timeout with slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
Sigma1912 commented 3 years ago

It seems that if the 'output_byte' is 0 then no data is sent because if I define 'output_byte=1' the master sends one byte once 'data_exchange' mode is established:

pyprofibus: DP slave 8 output: 1 bytes
pyprofibus: DP slave 8 input:  4 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
pyprofibus: Active DP slave (addr=8) pins:
pyprofibus: HAL configuration done
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
note: MAXV     max: 1.200 units/sec 72.000 units/min
note: LJOG     max: 1.200 units/sec 72.000 units/min
note: LJOG default: 1.000 units/sec 60.000 units/min
note: AJOG     max: 90.000 units/sec 5400.000 units/min
note: AJOG default: 45.000 units/sec 2700.000 units/min
PHY-serial: TX   10 08 02 49 53 16
note: jog_order='XYZABCUVW'
note: jog_invert=set([])
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 17 17 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 5B 00 00 00 D6 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 07 07 68 88 82 7D 3E 3E 21 21 45 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
DPM1: line 646 outData is not None
line 651: sending data:
PHY-serial: TX   68 04 04 68 08 02 7D 00 87 16
line 658: data sent: 
PHY-serial: RX   E5
DPM1: line 646 outData is not None
line 651: sending data:
PHY-serial: TX   68 04 04 68 08 02 7D 00 87 16
line 658: data sent: 
PHY-serial: RX   10 02 08 03 0D 16
pyprofibus: PROFIBUS fault:
Service not active on slave 8
DPM1: Data_Exchange timeout with slave 8
DPM1: line 646 outData is not None
line 651: sending data:
line 658: data sent: 
DPM1: Data_Exchange timeout with slave 8
DPM1: line 646 outData is not None
line 651: sending data:
line 658: data sent: 
DPM1: Data_Exchange timeout with slave 8
DPM1: Many errors in Data_Exchange. Requesting diagnostic information...
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
Sigma1912 commented 3 years ago

Ok I made some changes to your dp_master.py and I have it running nicely now:

pyprofibus: DP slave 8 output: 4 bytes
pyprofibus: DP slave 8 input:  0 bytes
Warning in GSD 'cpv_0A35.gse': DPv1 User_Prm_Data override ignored
pyprofibus: Running PROFIBUS-DP master...
pyprofibus: ready.
pyprofibus: Active DP slave (addr=8) pins:
pyprofibus: DP output:  profibus.slave.8.output.bit.0.0
pyprofibus: DP output:  profibus.slave.8.output.bit.0.2
pyprofibus: DP output:  profibus.slave.8.output.bit.0.4
pyprofibus: DP output:  profibus.slave.8.output.bit.0.6
pyprofibus: DP output:  profibus.slave.8.output.bit.1.0
pyprofibus: DP output:  profibus.slave.8.output.bit.1.2
pyprofibus: DP output:  profibus.slave.8.output.bit.1.4
pyprofibus: DP output:  profibus.slave.8.output.bit.1.6
pyprofibus: DP output:  profibus.slave.8.output.bit.2.0
pyprofibus: DP output:  profibus.slave.8.output.bit.2.1
pyprofibus: DP output:  profibus.slave.8.output.bit.2.2
pyprofibus: DP output:  profibus.slave.8.output.bit.2.3
pyprofibus: DP output:  profibus.slave.8.output.bit.2.4
pyprofibus: DP output:  profibus.slave.8.output.bit.2.5
pyprofibus: DP output:  profibus.slave.8.output.bit.2.6
pyprofibus: DP output:  profibus.slave.8.output.bit.2.7
pyprofibus: HAL configuration done
DPM1: Trying to initialize slave 8...
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: TX   10 08 02 49 53 16
PHY-serial: RX   10 02 08 00 0A 16
DPM1: slave[08].state --> 'wait for diag'
DPM1: Requesting Slave_Diag from slave 8...
PHY-serial: TX   68 05 05 68 88 82 6D 3C 3E F1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 02 05 00 FF 0A 35 D1 16
DPM1: slave[08].state --> 'wait for Prm'
DPM1: Sending Set_Prm to slave 8...
PHY-serial: TX   68 17 17 68 88 82 5D 3D 3E B8 1E 01 00 0A 35 01 00 00 00 82 00 00 00 5B 00 00 00 D6 16
note: MAXV     max: 1.200 units/sec 72.000 units/min
note: LJOG     max: 1.200 units/sec 72.000 units/min
note: LJOG default: 1.000 units/sec 60.000 units/min
note: AJOG     max: 90.000 units/sec 5400.000 units/min
note: AJOG default: 45.000 units/sec 2700.000 units/min
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Cfg'
DPM1: Sending Chk_Cfg to slave 8...
PHY-serial: TX   68 07 07 68 88 82 7D 3E 3E 21 21 45 16
note: jog_order='XYZABCUVW'
note: jog_invert=set([])
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 00 00 00 00 67 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 00 00 00 00 87 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 01 00 8A 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 5D 3C 3E E1 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
PHY-serial: TX   68 07 07 68 08 02 7D 01 01 11 00 9A 16
PHY-serial: RX   E5
DPM1: slave[08].state --> 'wait for Data_Exchange-ready'
DPM1: Requesting Slave_Diag (WDXRDY) from slave 8...
PHY-serial: TX   68 05 05 68 88 82 7D 3C 3E 01 16
PHY-serial: RX   68 0B 0B 68 82 88 08 3E 3C 00 0C 00 02 0A 35 D9 16
DPM1: slave[08].state --> 'Data_Exchange'
DPM1: Initialization finished. Running Data_Exchange with slave 8...
PHY-serial: TX   68 07 07 68 08 02 5D 01 01 11 00 7A 16
PHY-serial: RX   E5
...

I implemented my previous solution with the counter and with your conditionals I don't get any timeouts anymore. However I had to swap 'input_byte' and 'output_byte' back to my original "wrong" definition and also swap the conditionals in your modifications, since with 'output_byte=0' the master doesn't send any data during 'data_exchange' mode ( see posts above): https://github.com/Sigma1912/pyprofibus/blob/master/pyprofibus/dp_master.py

There probably still is a more elegant solution than that counter but the 'input_byte' vs 'output_byte' thing seems to run a bit deeper. Maybe it would just be easiest to swap the comments in the pyprofibus.conf file?

Thanks for your patience

mbuesch commented 3 years ago

Maybe it would just be easiest to swap the comments in the pyprofibus.conf file?

That would be a breaking change, except for LinuxCNC users. And also it makes sense to have the slave configuration see things from the slave's perspective.

Therefore I'd rather like to swap the meaning of input and output in the LinuxCNC HAL module.

Sigma1912 commented 3 years ago

Mind you that will not solve the problem that the master seems to be only sending as many bytes of data as have been declared as 'output_bytes'. See posts above.

So the issue isn't just a question of definition. Setting output_bytes=0 doesn't work for my 'input-only-slave' because the master doesn't send any data during 'data_exchange'. I haven't been able to figure out why though.

mbuesch commented 3 years ago

Whether any data is sent fully depends on your user code. If slaveDesc.setOutData() (That's the master's perspective. Should probably be renamed to something like setMasterOutData) is called with some data, then it will be sent.

mbuesch commented 3 years ago

Whether any data is sent fully depends on your user code.

Ah ok I just realized that the user code is in LinuxCNC HAL. And we already found out that the LinuxCNC HAL is buggy (swapped in/out). So that's the same problem.

mbuesch commented 3 years ago

I rebased the branch on top of the fix from #21. I think that should fix the confusion in the HAL. (The diagnosis part is not yet included).

Disclaimer: Nothing of that has been tested on real hardware by me, yet. :)

Sigma1912 commented 3 years ago

Thanks for all your prompt work. I've had a bit of a rethink and changed my mind regarding the naming of the hal-pins. I think you had it correct before (ie no-input-slaves like my valve block should create hal-pins 'profibus.slave.n.output.bit.x.y' with the needed hal-direction IN) as this corresponds with other hardware connecting to hal like mesa cards. My apologies for sending you on a loop there, I got confused.

So I've changed the files 'pyprofibus-linuxcnc-hal', 'linuxcnc-demo-dummyphy/profibus.hal' and 'linuxcnc-demo-et200s/profibus.hal' accordingly.

I've also modified 'dp_master.py' again to include the required diag request using the counter.

https://github.com/Sigma1912/pyprofibus

This works nicely now with my Festo hardware with the correct definition 'output_byte=0' and 'input_byte=4'.

PS I'm not sure I'm actually doing this right when I change 'master' on my fork.

mbuesch commented 3 years ago

ie no-input-slaves like my valve block should create hal-pins 'profibus.slave.n.output.bit.x.y' with the needed hal-direction IN

Your slave is a input-only slave, right? It only receives data. Payload data is only sent from master to slave. (The other way around is just ACKs). That's my definition of input-only.

Therefore the current HAL (after change) implements profibus.slave.n.input.bit.x.y with direction HAL_IN. And you need to specify output_size=0 and input_size=4 in the config.

That makes perfect sense to me.

PS I'm not sure I'm actually doing this right when I change 'master' on my fork.

It would be more idiomatic, if you would create your own branch derived from the branch that you want to modify. Then just commit your changes. That would make it way easier to review and diff.

Sigma1912 commented 3 years ago

Your slave is a input-only slave, right? It only receives data. Payload data is only sent from master to slave. (The other way around is just ACKs). That's my definition of input-only.

Ah, yes. I was looking at it from the hardware perspective, since I have a valve block and a digital output module connected but no input modules. 'Input-only' as seen from the profibus perspective because the slave sends no data back to the master. So in our profibus perspective it is an 'Input-only-device', I'll stick with that.

Therefore the current HAL (after change) implements profibus.slave.n.input.bit.x.y with direction HAL_IN. And you need to specify output_size=0 and input_size=4 in the config.

I think here is exactly the problem. In HAL we should think 'hardware'. When I look at how the hal-pins are created for the much used interface cards made by MESA it becomes clear that, in HAL, I want my hardware inputs to be represented as 'x.input.y' and my _hardware_outputs as 'x.output.y' because that's what the signal really is in the machine context. That is what the 'hardware abstraction layer' represents. It's fine to define 'input' and 'output' in context of the communication interface in the configuration file but once that is done and we move to the hardware abstraction layer we want to follow the established convention of calling a hardware input an '.input.x' and a hardware output an '.output.x'
The bug was that the previous version created 'profibus.slave.n.output.bit.x.y' pins according to how many 'output_bytes' were defined. I got confused because I started to see things from the profibus perspective and I think that is wrong in the HAL context.

It would be more idiomatic, if you would create your own branch derived from the branch that you want to modify. Then just commit your changes. That would make it way easier to review and diff.

Ah yes, I recall that you asked me to create a 'branch' and I went ahead and created a 'fork'. Thanks for pointing that out again. That was sloppy reading on my part.

Thanks

mbuesch commented 3 years ago

In HAL we should think 'hardware'.

Well, the HAL pin direction (HAL_IN or HAL_OUT) purely defines the direction of that single pin. IN-pins are read-from and OUT pins are write-to. The perspective is the HAL signal here. There's no hardware here, yet.

we want to follow the established convention of calling a hardware input an '.input.x' and a hardware output an '.output.x'

Yeah, well. I think somebody always thinks that stuff is the wrong way around, no matter how we define it. ;)

I'll keep it as-is, because that's consistent with the pyprofibus config. And I think it makes sense when reading the string profibus.slave.n.output.bit.x.y that it's the profibus slave output. That's literally what's written there. (And it's also very hard to define what a "hardware output" is. We don't know the hardware in pyprofibus. We only care about the Profibus bus data telegrams)

Sigma1912 commented 3 years ago

I have tested your latest changes to the 'in-only-slave' branch and it works nicely. The settable diag request frequency is very user friendly. Note: I have tested it with my version of 'pyprofibus-linuxcnc-hal' as I didn't feel like changing all my hal files again. I still think the pin naming is unfortunate and will cause a lot of unnecessary confusion to hal users. It pains me even more because it was me who suggested that ill concieved change.

Thanks for all your work.

mbuesch commented 3 years ago

I have tested your latest changes to the 'in-only-slave' branch and it works nicely.

Thanks a lot for testing.

I still think the pin naming is unfortunate

I'll think about changing the naming to something completely different that's less ambiguous than input/output.

mbuesch commented 3 years ago

I changed the terms from input to mosi and from output to miso. That completely avoids any assumption about whether we are talking about device out/in or PB out/in. And it also avoids the previously necessary assumption about the perspective.

I think that's a good tradeoff.

And I also merged the input-only-branch into the master branch. Any further development will take place in the master branch.

Sigma1912 commented 3 years ago

Wouldn't it be better to use such terms as 'mosi' and 'miso' inside the communication layer? Maybe 'output_size' could be 'miso_size' and 'input_size' could be 'mosi_size'? That would then free up 'input' and 'output' for the hardware layer in HAL. But I guess that would mean that existing configuration files needed to be modified.

mbuesch commented 3 years ago

I think that neither input nor output are particular good names, when it comes to the pyprofibus LinuxCNC HAL module. Calling something that goes into the slave an output, just because it might correspond to a physical output line of the slave, doesn't really make complete sense. A Profibus slave can be much more complex than simple I/O devices, where every bit maps to a relay, for example. A bit that's sent to the Profibus slave does not have to be coupled in any way to some kind of physical output. Same for bits received from the slave.

By using miso/mosi it's more clear that we're talking about the profibus side of the slave and not the physical side of the slave. Because that's really all pyprofibus and the pyprofibus HAL module care about. There's no knowledge in pyprofibus about what the device does with the data.

The user is free to name the connected HAL signal as input, output or anything else, to give it some hardware related meaning.

And I think it's not such a big deal either. One cannot really get this wrong. If one accidentally swaps miso/mosi, then LinuxCNC will throw an error. It's then just a matter of simply swapping these.

That said, I also don't want to spread the use of the terms miso/mosi throughout the rest of the code. Just because these terms are already allocated to SPI for most people. There I'd rather like to spell the terms out (See recent commits changing some internal names).

And the terms output_size/input_size are explained unambiguously in the corresponding comments. And it is in compliance with all other options in the [SLAVE_x] section. All these options configure what the slave does. Not what the master does.

Sigma1912 commented 3 years ago

The user is free to name the connected HAL signal as input, output or anything else, to give it some hardware related meaning.

And I think it's not such a big deal either. One cannot really get this wrong. If one accidentally swaps miso/mosi, then LinuxCNC will throw an error. It's then just a matter of simply swapping these.

True.

Thanks.

mbuesch commented 3 years ago

The change has been integrated in the pyprofibus release 1.11. Thanks for your report and especially for your great help in testing and suggestions!