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 | 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 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Re: Weird behaviour in wait=True when using epics.Motor.get(something, something, wait=True) |
From: | Torsten Bögershausen via Tech-talk <tech-talk at aps.anl.gov> |
To: | "Marco A. Barra Montevechi Filho" <marco.filho at lnls.br>, Matt Newville <newville at cars.uchicago.edu> |
Cc: | SWC <swc at lnls.br>, "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov> |
Date: | Fri, 3 Feb 2023 06:42:38 +0000 |
Hej Marco, some (late) and hopefully useful response. To my knowledge and understanding, writing to a motorRecord field with wait=True does only make sense for the .VAL (or .DVAL, .RVAL) fields. Because that what is what the motorRecord code is written to do. I have been able to dig into the stuff a little bit more. 0) The motor is not moving: .DMOV is 1 1) we write 0 to the .CNEN field through channel access. The special() function in motorRecord is called with after=0 The special() function in motorRecord is called with after=1 A " WRITE_MSG(DISABL_TORQUE)" is send to the driver The record processes, process() is called Inside do_work() a GET_INFO is send to the driver The first callback is fired via recGblFwdLink() 2) Now things happen in parallel: 2a) The driver polls the motorController (at least a model 3 driver does), which may take some milliseconds, when we have an asyn motor connected via ethernet. The poll() completes, and the record is processed again. The second callback is fired via recGblFwdLink() 2b) The firmware inside the motion controller handles the
TORQUE message. This can take µsec, milliseconds. Depending on the driver/controller, the TORQUE message may enable TORQUE control, closed loop, or enables the amplier. This variable/code is used for different things: It is heavily driver dependent, for what CNEN is used. 3) The poller continues to poll in the background. If e.g. an encoder readback changes, the record will be processed again, and a third, forth... callback is fired via recGblFwdLink() Another reason for a callback is when the driver detects that the amplifier is now on in the controller. This takes some hundred milliseconds in our system. A model 3 driver may write the parameter "motorStatusPowerOn_". The motorRecord reflects this bit in the .MSTA field: { unsigned short pos_maint = (msta.Bits.EA_POSITION) ? 1 : 0; if (pos_maint != pmr->cnen) { pmr->cnen = pos_maint; db_post_events(pmr, &pmr->cnen, local_mask); } } So there is a possible readback of CNEN: the driver is able to update the .CNEN field! I did some testing here, but couldn't make sense out of the number of callbacks either Depending on the timing, it seems as if callbacks can be "bundled" in some way. If this is done on the IOC, or within python/pyepics, I don't know. Probably a wireshark run would reveal more details. As a kind of summary, integrating the answer from Mark, it looks as if the "wait=True" feature make only sense when writing to the ".VAL" field, and probably (not tested by me) to DVAL and/or RVAL. That is what the motorRecord is designed for. BR From: "Marco A. Barra Montevechi Filho" <marco.filho at lnls.br> Hi, Torsten! >The Record is processed twice, first because the update of the DLLM field. And another time when the motor had been polled caused by a "GET_INFO" transaction.
the command, it seems to me. However, when the record has processed the command, and send it to the controller, it doesn't mean that the controller has digested it fully. From: Torsten Bögershausen <Torsten.Bogershausen at ess.eu> Hej again, are we still wondering about callbacks and wait=True ? Writing to VELO give one callback and one camonitor event here. Writing to DLLM give 2 callbacks and 2 monitors. This feels like a bug to me, but I don't think it worth to fix it. The Record is processed twice, first because the update of the DLLM field. And another time when the motor had been polled caused by a "GET_INFO" transaction. Back to the wait=True question, if anybody is interested. Writing to CNEN with wait=True seems to wait for the Record to have processed the command, it seems to me. However, when the record has processed the command, and send it to the controller, it doesn't mean that the controller has digested it fully. What are you using CNEN for ? Often it is used it for "enabling the amplifier". Other definitions that I have seen are "closed loop" or "torque control". We use it for "enabling the amplifier". Once the controller has received the "enable", it make take 1 second until the amplifier is ready, and the motor can be moved. HTH From:
Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of Matt Newville via Tech-talk <tech-talk at aps.anl.gov> Hi Marco, On Thu, Jan 19, 2023 at 9:43 AM Marco A. Barra Montevechi Filho <marco.filho at lnls.br> wrote:
I suspect that the "sometimes get an initial callback" is because creating an `epics.Motor()`
will make an initial connection for PVs
to some fields, including I also see that writing to the DHLM and DLLM of the Motor Record causes two nearly simultaneous events with the same new value. I don't see that for all other fields, but the motor record is
complicated, and setting some values will cause a cascade of events. I suspect that setting DHLM will also set HLM (or maybe LLM if the direction is negative), which might then also update the DHLM value.
General answer: Some things are easier to control than other things. If you first fetch the value of "CNEN" or "DHLM", and then add the callback, you should only see changes from that initial value (all assuming that connections happen in time). I don't know how to get only 1 callback if DHLM is changed. --Matt Aviso Legal: Esta mensagem e seus anexos podem conter informações confidenciais e/ou de uso restrito. Observe atentamente seu conteúdo e considere eventual consulta ao remetente antes
de copiá-la, divulgá-la ou distribuí-la. Se você recebeu esta mensagem por engano, por favor avise o remetente e apague-a imediatamente. Disclaimer: This email and its attachments may contain confidential and/or privileged information. Observe its content carefully and consider possible querying to the sender before
copying, disclosing or distributing it. If you have received this email by mistake, please notify the sender and delete it immediately. |