Hej Rea,
The most common protocol to talk to a motion controller
seems to be ASCII (and that is what we find everywhere...)
However, if you need to write binary data and read binary data
and you know how many bytes you get as a response from the controller,
you can use this function:
asynStatus asynMotorController::writeReadController(const char *output,
char *input, size_t maxChars, size_t *nread, double timeout)
Note 1:
You can use the pre-allocated buffers
outString_, inString_
(as long as your data is shorter that the buffersize)
And yes, memcpy may be better than snprintf, kind of.
Note 2:
You can even build up your own data structure and use that.
Make sure to not mess up the endianess or alignemnts and try to
stick to fixed data type like uint8_t, uint16_t and friends.
Do not hesitate to ask more questions.
/Torsten
On 2026-06-26 09:50, Rea Domitrović via Tech-talk wrote:
Hi Mark,
thanks for taking the time. I followed the debug instructions you
gave here: https://epics.anl.gov/tech-talk/2017/msg00282.php <https://
epics.anl.gov/tech-talk/2017/msg00282.php> - thanks for clarifying what
is actually needed.
I suspect this message is what's wrong, i.e. the writes are not actually
getting through to the motor:
2026/06/26 09:39:45.144 asynMotorController:writeFloat64 error, status=1
axis=0, function=1, value=-150000.000000
2026/06/26 09:39:45.148 devMotorAsyn::asynCallback: EXIT:zpos
pasyn{Float64,Int32}->write returned
To me, it smells like the problem is in the fact the motor doesn't use
ASCII-compatible strings to communicate - every message has to start
with a five-byte header of the following structure: 0xAA, length,
idempotence counter, 0x00, frame type. That null byte is presumably
making communication difficult; that is why everywhere in the source
code I used memcpy instead of sprintf to build the outString. A test IOC
made with StreamDevice instead of Motor confirms the motor is responsive
to that kind of communication; I was able to turn the servo on and poll
it for position using StreamDevice, but not actually move it.
Is it even possible to use the Model 3 framework to communicate with
something that uses such a specific and non-standard byte stream, or
will I have to find a different way? Kind regards,
Rea
------------------------------------------------------------------------
*From:* Mark Rivers <rivers at cars.uchicago.edu>
*Sent:* Thursday, June 25, 2026 4:35:51 PM
*To:* tech-talk at aps.anl.gov; Rea Domitrović
*Subject:* Re: EPICS support for Fastech motors
H Rea,
You have set the asynTraceMask to enable lots of debugging. That is OK,
but it makes it hard to see the real errors from warning and
informational messages. For example these messages are printed with
ASYN_TRACE_FLOW, they are not really errors.
2026/06/25 15:29:48.311 asynPortDriver:getDoubleParam: port=motorExit
error getting parameter 9 MOTOR_ENCODER_POSITION, in list 0, value undefined
2026/06/25 15:29:48.311 asynPortDriver:getDoubleParam: port=motorExit
error getting parameter 5 MOTOR_VELOCITY, in list 0, value undefined
This message
2026/06/25 15:07:46.444 asynMotorController:writeFloat64: Set driver
motorExit, axis 0 move absolute to 0.000000, base velocity=500.000000,
velocity=25000.000000, acceleration=245000.000000
is being printed here. It is just an informational message.
https://urldefense.us/v3/__https://github.com/epics-modules/motor/blob/__;!!G_uCfscf7eWS!fs3Q3dFfefRa8O3WpY_fCal9SNYY7rdJifOzcM2Lg1JdW_AoXJ374qo4mVpNfD9YB90Q8NWBtMExq9JM9cU$
f3d089bae20d04f8b9ed18fcfdc55274075d6a42/motorApp/MotorSrc/
asynMotorController.cpp#L328 <https://urldefense.us/v3/__https://
github.com/epics-modules/motor/blob/
f3d089bae20d04f8b9ed18fcfdc55274075d6a42/motorApp/MotorSrc/
asynMotorController.cpp*L328__;Iw!!G_uCfscf7eWS!
YyBnhmn8oSzP0Q7YGyZRHwOrKRtwVx6pVJVzL_7hWYrhD4vCyf_2K9axzV2KLsXHJfby10TfQ8-jHe0SehaOIdd-KSC7aA$>
However, this message:
2026/06/25 15:07:46.445 asynMotorController:writeFloat64 error, status=1
axis=0, function=1, value=0.000000
is being printed here:
https://urldefense.us/v3/__https://github.com/epics-modules/motor/blob/__;!!G_uCfscf7eWS!fs3Q3dFfefRa8O3WpY_fCal9SNYY7rdJifOzcM2Lg1JdW_AoXJ374qo4mVpNfD9YB90Q8NWBtMExq9JM9cU$
f3d089bae20d04f8b9ed18fcfdc55274075d6a42/motorApp/MotorSrc/
asynMotorController.cpp#L428 <https://urldefense.us/v3/__https://
github.com/epics-modules/motor/blob/
f3d089bae20d04f8b9ed18fcfdc55274075d6a42/motorApp/MotorSrc/
asynMotorController.cpp*L428__;Iw!!G_uCfscf7eWS!
YyBnhmn8oSzP0Q7YGyZRHwOrKRtwVx6pVJVzL_7hWYrhD4vCyf_2K9axzV2KLsXHJfby10TfQ8-jHe0SehaOIdfrAqeHkQ$>
Function=1 is a move absolute command, so it is consistent with the
first message. status=1 means that your driver's pAxis->move() function
returned -1. It was called from here:
https://urldefense.us/v3/__https://github.com/epics-modules/motor/blob/__;!!G_uCfscf7eWS!fs3Q3dFfefRa8O3WpY_fCal9SNYY7rdJifOzcM2Lg1JdW_AoXJ374qo4mVpNfD9YB90Q8NWBtMExq9JM9cU$
f3d089bae20d04f8b9ed18fcfdc55274075d6a42/motorApp/MotorSrc/
asynMotorController.cpp#L324-L325 <https://urldefense.us/v3/__https://
github.com/epics-modules/motor/blob/
f3d089bae20d04f8b9ed18fcfdc55274075d6a42/motorApp/MotorSrc/
asynMotorController.cpp*L324-L325__;Iw!!G_uCfscf7eWS!
YyBnhmn8oSzP0Q7YGyZRHwOrKRtwVx6pVJVzL_7hWYrhD4vCyf_2K9axzV2KLsXHJfby10TfQ8-jHe0SehaOIdeQizbqlg$>
If you set your asynTrace flags to ERROR|WARNING you will only see the
more important messages.
Mark
------------------------------------------------------------------------
*From:* Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of Rea
Domitrović via Tech-talk <tech-talk at aps.anl.gov>
*Sent:* Thursday, June 25, 2026 8:53 AM
*To:* tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>
*Subject:* Re: EPICS support for Fastech motors
Hi all,
thanks so much for pointing me in the right direction so far. I've got
to the point where I've got the structure of a driver based on the MCB4B
driver and with inspiration from the SmarAct driver; however, at
runtime, I'm getting errors that I'm struggling to diagnose. If someone
could help me understand, I would be most grateful. Relevant info is
below. Best,
Rea Domitrović
Institut Ruđer Bošković
Zagreb, Croatia
Source code is here: https://urldefense.us/v3/__https://github.com/redomitro/motorFastech__;!!G_uCfscf7eWS!fs3Q3dFfefRa8O3WpY_fCal9SNYY7rdJifOzcM2Lg1JdW_AoXJ374qo4mVpNfD9YB90Q8NWBtMExNp2K54g$ <https://
urldefense.us/v3/__https://urldefense.us/v3/__https://github.com/redomitro/motorFastech__;!!__;!!G_uCfscf7eWS!fs3Q3dFfefRa8O3WpY_fCal9SNYY7rdJifOzcM2Lg1JdW_AoXJ374qo4mVpNfD9YB90Q8NWBtMEx0fR0RiM$
G_uCfscf7eWS!
ckejUTszXgikK0HKxA_InFEgeEyYG2lD41P9WU4hEdAGledQERL0dK2U_KIYaLsarWXmtRkeqsmdlOkbbDFNsrR52DGXQg$>
IOCinit output:
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_MOVE_REL, index=0
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_MOVE_ABS, index=1
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_MOVE_VEL, index=2
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_HOME, index=3
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_STOP_AXIS, index=4
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_VELOCITY, index=5
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_VEL_BASE, index=6
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_ACCEL, index=7
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_POSITION, index=8
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_RESOLUTION, index=12
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_ENCODER_RATIO, index=13
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_PGAIN, index=14
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_IGAIN, index=15
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_DGAIN, index=16
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_HIGH_LIMIT, index=17
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_LOW_LIMIT, index=18
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_CLOSED_LOOP, index=19
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_STATUS, index=25
2026/06/25 15:29:48.311 asynPortDriver:drvUserCreate:
drvInfo=MOTOR_UPDATE_STATUS, index=26
2026/06/25 15:29:48.311 motorExit 0 registerInterruptUser
2026/06/25 15:29:48.311 asynPortDriver:getDoubleParam: port=motorExit
error getting parameter 9 MOTOR_ENCODER_POSITION, in list 0, value undefined
2026/06/25 15:29:48.311 asynPortDriver:getDoubleParam: port=motorExit
error getting parameter 5 MOTOR_VELOCITY, in list 0, value undefined
2026/06/25 15:29:48.311 asynMotorController:readGenericPointer:
MotorStatus = status34, position=425203751.000000, encoder
position=0.000000, velocity=0.000000
2026/06/25 15:29:48.311 motorExit asynManager::queueLockPort locking port
2026/06/25 15:29:48.311 motorExit asynManager::queueLockPort created
queueLockPortPvt=0x561069c8f7a0
2026/06/25 15:29:48.311 motorExit asynManager::queueLockPort created
queueLockPortPvt=0x561069c8f7a0, event=0x561069c979e0, mutex=0x561069c97990
2026/06/25 15:29:48.311 motorExit asynManager::queueLockPort taking
mutex 0x561069c97990
2026/06/25 15:29:48.311 motorExit asynManager::queueLockPort queueing
request
2026/06/25 15:29:48.311 motorExit addr 0 queueRequest priority 0 not
lockHolder
2026/06/25 15:29:48.311 motorExit schedule queueRequest timeout in
2.000000 seconds
2026/06/25 15:29:48.311 motorExit asynManager::queueLockPort waiting for
event
2026/06/25 15:29:48.312 motorExit 0 autoConnect
2026/06/25 15:29:48.312 asynPortDriver:connect:, pasynUser=0x561069c83188
2026/06/25 15:29:48.312 asynManager::portThread port=motorExit callback
2026/06/25 15:29:48.312 motorExit asynManager::queueLockPortCallback
signaling begin event
2026/06/25 15:29:48.312 motorExit asynManager::queueLockPortCallback
waiting for mutex from queueUnlockPort
2026/06/25 15:29:48.312 motorExit asynManager::queueLockPort got event
from callback
2026/06/25 15:29:48.312 EXIT:zpos devMotorAsyn::statusCallback new
value=[p:425203751.000000,e:0.000000,s:22]
2026/06/25 15:29:48.312 asynMotorController:writeFloat64: Set driver
motorExit, axis 0 encoder ratio=1.000000
2026/06/25 15:29:48.312 asynMotorController:writeFloat64:: axis=0,
function=13, value=1.000000
2026/06/25 15:29:48.312 asynFloat64SyncIO wrote: 1.000000e+00
2026/06/25 15:29:48.312 motorExit queueUnlockPort
2026/06/25 15:29:48.312 motorExit asynManager::queueUnlockPort waiting
for event
2026/06/25 15:29:48.313 motorExit queueUnlockPort unlock mutex
0x561069c97990 complete.
2026/06/25 15:29:48.313 devMotorAsyn::init_controller, EXIT:zpos set
encoder ratio to 1.000000
2026/06/25 15:29:48.313 devMotorAsyn::init_controller, EXIT:zpos setting
of position not required, position=425203751.000000, mres=0.000200,
dval=0.000000, rdbd=0.0002002026/06/25 15:29:48.313 EXIT:zpos
devMotorAsyn::update_values, needUpdate=1
2026/06/25 15:29:48.313 devMotorAsyn::build_trans: EXIT:zpos
motor_cmnd=19, pact=0, value=375000.000000
2026/06/25 15:29:48.313 devAsynMotor::build_trans: calling queueRequest,
pmsg=0x561069c97c40, sizeof(*pmsg)=24pmsg->command=14, pmsg-
>interface=1, pmsg->dvalue=375000.000000
2026/06/25 15:29:48.313 motorExit addr 0 queueRequest priority 0 not
lockHolder
2026/06/25 15:29:48.313 devMotorAsyn::build_trans: EXIT:zpos
motor_cmnd=20, pact=0, value=-375000.000000
2026/06/25 15:29:48.313 devAsynMotor::build_trans: calling queueRequest,
pmsg=0x561069c97c90, sizeof(*pmsg)=24pmsg->command=15, pmsg-
>interface=1, pmsg->dvalue=-375000.000000
2026/06/25 15:29:48.313 motorExit addr 0 queueRequest priority 0 not
lockHolder
2026/06/25 15:29:48.313 asynManager::portThread port=motorExit callback
2026/06/25 15:29:48.313 devMotorAsyn::asynCallback: EXIT:zpos
pmsg=0x561069c97c40, sizeof(*pmsg)=24, pmsg->command=14,pmsg-
>interface=1, pmsg->ivalue=0, pmsg->dvalue=375000.000000, pasynUser-
>reason=17
2026/06/25 15:29:48.313 asynMotorController:writeFloat64: Set driver
motorExit, axis 0 high limit=375000.000000
2026/06/25 15:29:48.313 asynMotorController:writeFloat64:: axis=0,
function=17, value=375000.000000
2026/06/25 15:29:48.313 asynManager::portThread port=motorExit callback
2026/06/25 15:29:48.313 devMotorAsyn::asynCallback: EXIT:zpos
pmsg=0x561069c97c90, sizeof(*pmsg)=24, pmsg->command=15,pmsg-
>interface=1, pmsg->ivalue=0, pmsg->dvalue=-375000.000000, pasynUser-
>reason=18
2026/06/25 15:29:48.313 asynMotorController:writeFloat64: Set driver
motorExit, axis 0 low limit=-375000.000000
2026/06/25 15:29:48.313 asynMotorController:writeFloat64:: axis=0,
function=18, value=-375000.000000
Output when attempting to caput absolute position:
2026/06/25 15:07:44.438 192.168.0.204:3001 UDP write 3
\xaa\v\a
2026/06/25 15:07:46.444 asynMotorController:writeFloat64: Set driver
motorExit, axis 0 move absolute to 0.000000, ba
se velocity=500.000000, velocity=25000.000000,
acceleration=245000.000000
2026/06/25 15:07:46.445 asynMotorController:writeFloat64 error, status=1
axis=0, function=1, value=0.000000
2026/06/25 15:07:46.445 devMotorAsyn::asynCallback: EXIT:zpos
pasyn{Float64,Int32}->write returned
2026/06/25 15:07:46.445 EXIT:zpos devMotorAsyn::update_values, needUpdate=1
------------------------------------------------------------------------
*From:* Mark Rivers <rivers at cars.uchicago.edu>
*Sent:* Wednesday, June 17, 2026 21:07
*To:* Torsten Bögershausen; tech-talk at aps.anl.gov; Rea Domitrović
*Subject:* Re: EPICS support for Fastech motors
Hi Rea,
*
I see that driver developers prefer to use octet-based
communication rather than use the manufacturer-provided libraries.
Is there a reason why that is the case, or is it simply that octet-
based communicaton is more universal?
Manufacturer libraries will be provided for specific operating system
and specific versions of those OS. That can restrict where they can be
deployed. They may restrict redistribution, which prevents including
them in the motor Github repository. They almost certainly won't be
supported on real-time OS like RTEMS or vxWorks.
*
Further, the Fastech controller allows both octet-based
communication and library-based communication, but octet-based
communication requires the master to send a one-byte "sync number"
which serves as an idempotence token. I assume it would be necessary
to implement that myself; could I be using some sort of global
variable, and how do I make sure that I never land on the same
number twice in a row?
Many protocols have something like that. You just have a member
variable in your driver class that increments by 1 on each message it
sends, and wraps back to 0 after 255.
Mark
------------------------------------------------------------------------
*From:* Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of Rea
Domitrović via Tech-talk <tech-talk at aps.anl.gov>
*Sent:* Wednesday, June 17, 2026 8:34 AM
*To:* Torsten Bögershausen <tboegi at edom.se>; tech-talk at aps.anl.gov
<tech-talk at aps.anl.gov>
*Subject:* Re: EPICS support for Fastech motors
Hi Torsten,
thanks for pointing me in the right direction. I'm looking at the manual
and the source for other submodules now (motorSmarAct and motorAcs); I
see that driver developers prefer to use octet-based communication
rather than use the manufacturer-provided libraries. Is there a reason
why that is the case, or is it simply that octet-based communicaton is
more universal?
Further, the Fastech controller allows both octet-based communication
and library-based communication, but octet-based communication requires
the master to send a one-byte "sync number" which serves as an
idempotence token. I assume it would be necessary to implement that
myself; could I be using some sort of global variable, and how do I make
sure that I never land on the same number twice in a row? Kind regards,
Rea
------------------------------------------------------------------------
*From:* Torsten Bögershausen <tboegi at edom.se>
*Sent:* Wednesday, June 10, 2026 1:49:41 PM
*To:* Rea Domitrović; tech-talk at aps.anl.gov
*Subject:* Re: EPICS support for Fastech motors
Hej Rea,
I haven't worked with them, no.
If you have Ethernet (not to be confused with EtherCAT),
I read the manual as if they use UDP for communication,
and knowing that you can write a simple model 3 driver, I think.
(Other suggestions are welcome of course)
/Torsten
On 2026-06-10 12:52, Rea Domitrović via Tech-talk wrote:
> Hi all,
>
>
> I'm working with some Fastech Ezi-Servo II Plus-E motors, and I was
> wondering if someone had already worked with them and/or made an EPICS
> driver or Motor submodule? This particular line of motors and
> drives uses an Ethernet interface. Kind regards,
>
>
> Rea Domitrović
>
> Institut Ruđer Bošković
>
> Zagreb, Croatia
>
Oprez: Ova poruka stigla je od vanjskog pošiljatelja. Prije otvaranja
poveznica ili privitaka provjerite pošiljatelja. Caution:This email
originated from an external sender. Please verify the sender before
opening links or attachments.
*Oprez:* Ova poruka stigla je od vanjskog pošiljatelja. Prije otvaranja
poveznica ili privitaka provjerite pošiljatelja. *Caution:*This email
originated from an external sender. Please verify the sender before
opening links or attachments.
*Oprez:* Ova poruka stigla je od vanjskog pošiljatelja. Prije otvaranja
poveznica ili privitaka provjerite pošiljatelja. *Caution:*This email
originated from an external sender. Please verify the sender before
opening links or attachments.
- References:
- EPICS support for Fastech motors Rea Domitrović via Tech-talk
- Re: EPICS support for Fastech motors Torsten Bögershausen via Tech-talk
- Re: EPICS support for Fastech motors Rea Domitrović via Tech-talk
- Re: EPICS support for Fastech motors Mark Rivers via Tech-talk
- Re: EPICS support for Fastech motors Rea Domitrović via Tech-talk
- Re: EPICS support for Fastech motors Mark Rivers via Tech-talk
- Re: EPICS support for Fastech motors Rea Domitrović via Tech-talk
- Navigate by Date:
- Prev:
RFC: add a mechanism to call epicsExit when signals are received Timothy Speight - STFC UKRI via Tech-talk
- Next:
Re: EPICS support for Fastech motors Mark Rivers via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
<2026>
- Navigate by Thread:
- Prev:
Re: EPICS support for Fastech motors Rea Domitrović via Tech-talk
- Next:
Re: EPICS support for Fastech motors Mark Rivers via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
<2026>
|