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 | 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 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Re: An error occurred while using aSub to process Modbus data |
From: | Érico Nogueira Rolim via Tech-talk <tech-talk at aps.anl.gov> |
To: | LONG FENG <feng98716 at gmail.com>, "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov> |
Date: | Mon, 4 Nov 2024 11:33:32 +0000 |
Hi all,
I want to process Modbus format data, but it's not going very smoothly.My record file content is as follows:record(waveform, "Sensor:waveform")
{
field(DESC, "read data")
field(DTYP, "stream")
field(NELM, "40")
field(FTVL, "UCHAR")
field(INP, "@RS485Test.proto getData SI")
field(SCAN, "5 second")
field(FLNK, "ProcessSensorData")
}
I'm assuming you have made sure that Sensor:waveform is working correctly, and that ProcessSensorData is being processed as well.
record(aSub, "ProcessSensorData")
{
field(INAM, "init_dose")
field(SNAM, "dose")
field(INPA, "Sensor:waveform NPP NMS")
Setting FTA and NOA here might also be useful.
field(FTVE, "DOUBLE")
This field should be FTVA, no?
field(OUTA, "Sensor:ai NPP NMS")
I normally use PP for output records.
field(NOVA, "1")
}
record(ai, "Sensor:ai")
{
field(DESC, "Dose Measurement")
field(INP, "ProcessSensorData.VALA NPP NMS")
You don't need an INP field in this record, the ProcessSensorData record will write into it already.
field(PREC, "3")
field(EGU, "µSv/h")
field(SCAN, "Passive")
}
dose.c:#include <epicsExport.h>
#include <aSubRecord.h>
#include <registryFunction.h>
int init_dose(struct aSubRecord *psub) {
double *p1 = (double *)psub->vala;
*p1 = 0;
return 0;
}
int dose(struct aSubRecord *psub) {
char *inData;
double *pout1, doseRate;
unsigned char readData[4] = {0};
inData = (char *)psub->a;
pout1 = (double *)psub->vala;
// For example, the returned data is: 01 04 0c 14 7b 3e 2e 00 03 00 00 00 00 00 00 ad c9. '14 7b' represents the low byte, and '3e 2e' represents the high byte.
readData[0] = inData[4];
readData[1] = inData[3];
readData[2] = inData[6];
readData[3] = inData[5];
doseRate = *((float*)readData);
C detail and probably not relevant for your issue, I don't think you can guarantee readData is correctly aligned for a float. A more portable implementation could use memcpy to copy readData into an intermediary float variable.
*pout1 = doseRate;
You're not setting "psub->neva" to 1 here, to indicate that you wrote into one value of this array.
return 0;
}
epicsRegisterFunction(init_dose);
epicsRegisterFunction(dose);
I used caget to observe Sensor:ai, and the result is always:Sensor:ai 2.20405e-38
I think I made a mistake in my processing function, so I wrote a simple test program as follows:#include <epicsExport.h>#include <aSubRecord.h>
#include <registryFunction.h>
int init_dose(struct aSubRecord *psub) {
double *p1 = (double *)psub->vala;
*p1 = 0;
return 0;
}
int dose(struct aSubRecord *psub) {
char *inData;
double *pout1, doseRate;
inData = (char *)psub->a;
pout1 = (double *)psub->vala;
doseRate = inData[3]*0.1;
*pout1 = doseRate;
return 0;
}
epicsRegisterFunction(init_dose);
epicsRegisterFunction(dose);
However, the result is always:Sensor:ai 0What should I modify? Please help me.
Feng
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.