EPICS Home

Experimental Physics and Industrial Control System


 
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  <20242025  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  <20242025 
<== Date ==> <== Thread ==>

Subject: RE: An error occurred while using aSub to process Modbus data
From: Mark Rivers 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: Tue, 5 Nov 2024 23:08:37 +0000

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")
}

 

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);

    *pout1 = doseRate;

    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                      0

 

What should I modify? Please help me.  

 

Feng


References:
An error occurred while using aSub to process Modbus data LONG FENG via Tech-talk

Navigate by Date:
Prev: Re: Smaract MCS2 position polling issue Peterson, Kevin M. via Tech-talk
Next: EPICS Archiver compatibility w/Debian 12, Tomcat 10 Windsor Tanner 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  <20242025 
Navigate by Thread:
Prev: Re: An error occurred while using aSub to process Modbus data Érico Nogueira Rolim via Tech-talk
Next: EPICS Archiver compatibility w/Debian 12, Tomcat 10 Windsor Tanner 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  <20242025