Hi Feng,
As several of us said in response to your original post, the best way to do this is with the EPICS Modbus driver. You have been trying for over a week to do it, first with streamDevice
and now with asub.
Here is all you need to do it with the Modbus driver
drvAsynSerialPortConfigure("SI", "/dev/ttyS3")
asynSetOption("SI", 0, "baud", "9600")
asynSetOption("SI", 0, "bits", "8")
asynSetOption("SI", 0, "parity", "none")
asynSetOption("SI", 0, "stop", "1")
asynSetOption("SI", 0, "clocal", "Y")
asynSetOption("SI", 0, "crtscts", "N")
#modbusInterposeConfig(const char *portName,
# modbusLinkType linkType, # 0=TCP, 1=RTU, 2=ASCII
# int timeoutMsec,
# int writeDelayMsec)
modbusInterposeConfig("SI", 1, 1000, 50)
# drvModbusAsynConfigure(
# char *portName,
# char *octetPortName,
# int modbusSlave,
# int modbusFunction,
# int modbusStartAddress,
# int modbusLength,
# modbusDataType dataType,
# int pollMsec,
# char *plcType)
# Read 6 registers. Function code=4. Poll every 1000 ms
drvModbusAsynConfigure("SI_REG_IN", "SI", 1, 4, 0, 6, 0, 1000, "Pressure")
## Load record instances
dbLoadRecords("../../db/RS485Test.db")
Change RS485Test.db to the following. This should put the first 4 bytes (2 registers) into the Dose longin record as a 32-bit integer, and then put the next 2 bytes (1 register) into the
Units mbbi record.
record(ai, "Sensor:Dose")
{
field(DTYP, "asynInt32")
field(INP,"@asyn(SI_REG_IN 0)INT32_LE")
field(SCAN, "I/O Intr")
}
record(mbbi, "Sensor:Units") {
field(DTYP, "asynInt32")
field(INP, "@asyn(SI_REG_IN 2)INT16")
field(ZRVL, "1"
field(ZRST, "CPS"
field(ONVL, "2"
field(ONST, "CPM"
field(TWVL, "3"
field(TWST, "
uSv/h"
field(SCAN, "I/O Intr")
}
I can’t test this, so there could be some minor errors. But it should work once those are fixed. You can change the longin record to an ai record if you need to apply scaling, etc.
Mark
From: Tech-talk <tech-talk-bounces at aps.anl.gov>
On Behalf Of LONG FENG via Tech-talk
Sent: Monday, November 4, 2024 2:55 AM
To: tech-talk at aps.anl.gov
Subject: An error occurred while using aSub to process Modbus data
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")
}
record(aSub, "ProcessSensorData")
{
field(INAM, "init_dose")
field(SNAM, "dose")
field(INPA, "Sensor:waveform NPP NMS")
field(FTVE, "DOUBLE")
field(OUTA, "Sensor:ai NPP NMS")
field(NOVA, "1")
}
record(ai, "Sensor:ai")
{
field(DESC, "Dose Measurement")
field(INP, "ProcessSensorData.VALA NPP NMS")
field(PREC, "3")
field(EGU, "µSv/h")
field(SCAN, "Passive")
}
#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);
*pout1 = doseRate;
return 0;
}
epicsRegisterFunction(init_dose);
epicsRegisterFunction(dose);
I used caget to observe Sensor:ai, and the result is always:
I think I made a mistake in my processing function, so I wrote a simple test program as follows:
#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:
What should I modify? Please help me.