System: CoDeSys 2.3.7.5 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.
Regards
Nicolai Hanssing
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2008-02-19
Originally created by: Nicolai_Hanssing
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);Β ActPosition:=Β ((pAx^.dwActPosition-dwOffset)MODpAx^.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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2008-02-20
Originally created by: Nicolai_Hanssing
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)MODpAx^.dwOneTurn)/pAx^.fScalefactor;TmpLReal:=pAx^.fOffsetPosition-TRUNC(pAx^.fOffsetPosition/pAx^.fPositionPeriod)*pAx^.fPositionPeriod;ActPosition:=ActPosition-TmpLReal;WHILEActPosition>=pAx^.fPositionPeriodDOΒ ActPosition:=ActPosition-pAx^.fPositionPeriod;END_WHILEWHILEActPosition<0DOΒ ActPosition:=ActPosition+pAx^.fPositionPeriod;END_WHILE
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?
Regards
Nicolai
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Originally created by: Nicolai_Hanssing
System: CoDeSys 2.3.7.5 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.
Regards
Nicolai Hanssing
Originally created by: Nicolai_Hanssing
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:
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.
Originally created by: Nicolai_Hanssing
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):
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?
Regards
Nicolai