Originally created by: Nicolai_Hanssing
System: CoDeSys 220.127.116.11 with Infranor CD1k CanOpen drives
Target: WinCE Cybelec
When using an axis with linear configuration I get some wrong behaviour when the feedback-position (DINT) rolls over at 2^31:
The raw 32bit feedback-position from the drive is available in:
AXIS_REF.dwActPosition (OBS: this is unsigned version, but it matches the binary transmission from the drive)
AXIS_REF.fActPosition - Current actual positon, scaled.
AXIS_REF.fSetPosition - Current setpoint from Position-profiler, scaled.
Now all these values are fine until the drive roll-over of the 32bit SIGNED position: 16#80000000 (2^31)
The setpoint for the drive is continous, when the roll-over hapens (ie. no following error), but is this is by luck i dont know....
'AXIS_REF.fActPosition' changes sign, and follows the dwActPosition, if that is typecasted into a DINT.
But 'AXIS_REF.fSetPosition' does not, it continous to grow.
So you get a large difference (2^32) between fActPosition and fSetPosition. This does not make sense, and is a bug....
Exspected behaviour would be one of the two below:
a) Act/Set-Position would both change sign.
b) Act/Set-Position would both be continous.
So we have this bug, but is it CoDeSys or is there something wrong with the Drive-libs?
I have some question I hope some will be able to answer:
What is the largest linear position, for a linear axis in the profiler?
How is the relation-ship between fSetPos (From profiler) and Actual command defined, when a roll-over has occured on either feedback or command-setpoint?
Please feel free to only answer part of the questions in seperate posts.
I'll try to see if I can provoke more strange behavior.
Changing the axis to a modolu-axis, causes the discrepency to not appear when position-rollover from drive occurs.
However if I run the axis with modulo, how can I correctly transform the 32bit DINT feedback-value to an actual positionvalue?
My investigations so far has led me to the follwoing construct:
(* pAx is a pointer to AXIS_REF. *)
(* Lets calculate actual position from dwActpos (modulo axis) *)
dwOffset := LREAL_TO_DWORD(pAx^.fOffsetPosition*pAx^.fScalefactor);
((pAx^.dwActPosition-dwOffset) MOD pAx^.dwOneTurn) / pAx^.fScalefactor;
Firstoff I need to treat the feedback-value as DW instad of DI?
Then get the current offset and convert to DW by scalefactor (not precise, anyone know where to get the DW-offsetvalue to avoid rounding-errors?).
Apply axis modulo as found in AXIS_REF.dwOneTurn.
However this is not precise!
I think it is due to rounding-errors in the calculation of dwOffset.
So anyone have a sure, fast and precise way of transforming a 32bit DINT value to a corresponding AXIS_REF.fActPosition-domain?
Notes on application: We're reading a 32bit capture-positon in the drive, wich is currently not supported by MC_TouchProbe(), and therefor need to do this conversion.
The lack of precision in previous post, is due to a bug wich I have posted in a new thread.
I have now found a way(?) to convert an actual 32bit position, and transform it into the TechUnits-domain for a rotary axis (modulo):
(* Lets try to calculate actual position from dwActpos *)
(* OBS: pAx : POINTER TO AXIS_REF *)
ActPosition := ((pAx^.dwActPosition-pAx^.dwPosOffsetForResiduals) MOD pAx^.dwOneTurn)/pAx^.fScalefactor;
TmpLReal := pAx^.fOffsetPosition-TRUNC(pAx^.fOffsetPosition / pAx^.fPositionPeriod)*pAx^.fPositionPeriod;
ActPosition := ActPosition - TmpLReal;
WHILE ActPosition>=pAx^.fPositionPeriod DO
WHILE ActPosition<0 DO
I however dont understand why the value in AXIS_REF.fOffsetPosition is not kept within .fPositionPeriod?
When perofrming multiple MC_SetPos() calls the value can become extremely large, causing many iterations in the while-loops, wich is inefficient, so I had to add the TRUNC() calculation to keep it O(1) effecient.
It will also lead to loss of precision eventually when the LREAL value gets big enough!
I realise that increment-precision is kept until 2^51 for double precision LREAL, but it still seems wrong?
Is this intended by 3S?
Log in to post a comment.