stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
252 stars 93 forks source link

Read Array of REAL #338

Closed pedroaccwinkelmartins closed 1 year ago

pedroaccwinkelmartins commented 1 year ago

Good morning. I've been trying to access a memory address of my PLC that contains an array of three REAL values. This is the array: ARR1 AT %MW20: ARRAY [1..3] OF REAL := 2.4,3.7,12.2;

When I try and read it with pyads.Connection().read, it returns values that do not correspond to the value stored: plc = pyads.Connection(ams_net_id= '172.16.23.17.1.1', ams_net_port= 800, ip_address= '172.16.23.17') plc.open() string = plc.read(pyads.INDEXGROUP_MEMORYBYTE, 20, pyads.PLCTYPE_ARR_REAL(3)) print("leitura1: ", string)

Output: leitura1: [0.0, -107610976.0, 4.1736040401474384e-08]

Is there a problem with my code, or is there a problem in the package that is causing this?

chrisbeardy commented 1 year ago

Hi, I don't tend to use fixed memory addresses and read, i tend to only use read by name etc, however could this be linked to the %MW where this is a word of 16 bit whereas a real is 32 bit? also is the ams_net_port correct?, should this be 801?for plc 1

pedroaccwinkelmartins commented 1 year ago

Thanks for the input. However, I did try to assign the variable to a double word (D) instead of a word (W), but I'm still getting the same problem. As for the port, I'm able to read arrays of INT with the same function in that same port. So I think that should be fine. It's just these REAL arrays that I'm having trouble with (maybe some others that I haven't tried yet). leitura1: [-107610208.0, -107610976.0, 4.1736040401474384e-08]

chrisbeardy commented 1 year ago

Is port 800 the correct port though? You can check this through system config? there may be a weird qwerk here that some are reading OK. Have you also tried read_by_name and not assigning the variable a memory address? In TwinCat you don't need to assign memory addresses, it can manage it for you.

pedroaccwinkelmartins commented 1 year ago

I've checked in the TwinCat System Manager, in the PLC - Configuration branch, and the project there mentions the use of port 800. Should I change to 801? If so, how can I do that (I'm quite new to TwinCat)? I've tried your other suggestion, but the problem persisted. (Happy new year btw :))

chrisbeardy commented 1 year ago

if the system manager uses port 800 then this is the right port to specify. Is this the same plc as used in issue #339 ?

If so I suspect there is a link and there is an issue here with the BC9120?

I wonder if the BC9120 has a different endian or byte alignment size for the OS it uses etc. If so its likely pyads does not support this PLC.

pedroaccwinkelmartins commented 1 year ago

Yes, it is the same plc as used in issue #339 . Thanks for your help!

chrisbeardy commented 1 year ago

OK, can you close this issue as I believe it is linked to #339.

Thanks

sgaforbes84 commented 1 year ago

Hi, I'm experiencing a similar issue to this trying to read a structure from my PLC. The PLC structure definition is -

(Sorry for the terrible formating, I've not figured out how to make it nicer yet)

TYPE stCiJectData: STRUCT ControlPressureSensorReading : REAL; InjectionMode_ManualOrIMPS: BOOL; InjectionFinished: BOOL; InjectionIMPSPrimeCompleted: BOOL; InjectionIMPSPriming: BOOL; InjectionInProgress : BOOL; InjectionPause : BOOL; SetpointIMPSInjectionPressure: REAL; SetpointIMPSInjectionPrimePressure: REAL; SetpointTankPressure: REAL; TriggerMachineStop: BOOL; IMPS_Inputs: ARRAY [0..3] OF REAL; TankPressure: REAL; ScalesTareValue: REAL; ScalesTaredReading: REAL; ScalesUnTaredReading: REAL; TCInputs : ARRAY [0..3] OF REAL; HeatedHose: REAL; PinchValveHeater: REAL; TankAirTemperature: REAL; TankBasHeaterCartridges: REAL; TankResinProbe: REAL; TankWallHeaterBand: REAL; END_STRUCT END_TYPE

I'm using read_structure_by_name in my script - c = plc.read_structure_by_name("g_HMI.stCiJect", CiJectData_Struc)

This is my struct_def - CiJectData_Struc = ( ('ControlPressureSensorReading', pyads.PLCTYPE_REAL,1), ('InjectionMode_ManualOrIMPS', pyads.PLCTYPE_BOOL,1), ('InjectionFinished', pyads.PLCTYPE_BOOL,1), ('InjectionIMPSPrimeCompleted', pyads.PLCTYPE_BOOL,1), ('InjectionIMPSPriming', pyads.PLCTYPE_BOOL,1), ('InjectionInProgress', pyads.PLCTYPE_BOOL,1), ('InjectionPause', pyads.PLCTYPE_BOOL,1), ('SetpointIMPSInjectionPressure', pyads.PLCTYPE_REAL,1), ('SetpointIMPSInjectionPrimePressure', pyads.PLCTYPE_REAL,1), ('SetpointTankPressure', pyads.PLCTYPE_REAL,1), ('TriggerMachineStop', pyads.PLCTYPE_BOOL , 1), ('IMPS_Inputs', pyads.PLCTYPE_REAL,4), ('TankPressure', pyads.PLCTYPE_REAL,1), ('ScalesTareValue', pyads.PLCTYPE_REAL,1), ('ScalesTaredReading', pyads.PLCTYPE_REAL, 1), ('ScalesUnTaredReading', pyads.PLCTYPE_REAL, 1), ('TCInputs', pyads.PLCTYPE_REAL,4), ('HeatedHose', pyads.PLCTYPE_REAL,1), ('PinchValveHeater', pyads.PLCTYPE_REAL,1), ('TankAirTemperature', pyads.PLCTYPE_REAL,1), ('TankBasHeaterCartridges', pyads.PLCTYPE_REAL,1), ('TankResinProbe', pyads.PLCTYPE_REAL,1), ('TankWallHeaterBand', pyads.PLCTYPE_REAL,1) )

I get the correct value for the 1st REAL ('ControlPressureSensorReading'), but all subsequent values are incorrect. The BOOLs inbetween seem to be correct.

It looks like the REALS are being buffered with 16 '0' bits. I.e. here's an exmaple of a value on the PLC with binary conversion- 0.98 = 0011111101111010 1110000101001000. The value in python - -2.30584300921e+20 = 1110000101001000 0000000000000000

chrisbeardy commented 1 year ago

Are you using the attribute pack mode 1 for the structure definition?

sgaforbes84 commented 1 year ago

I wasn't, I am now and the issue is solved. Many thanks