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: Help getting modbus module started |
From: | Mark Rivers via Tech-talk <tech-talk at aps.anl.gov> |
To: | "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>, Christian Pauly <pauly at physik.uni-wuppertal.de> |
Date: | Wed, 15 Feb 2023 13:24:06 +0000 |
Hi Christian,
> But how do i have to define the ai(?)-record in FUrecords.db now, to read
a single word from the given address 0x2103 using the IN_int function as defined above ?
You are using absolute Modbus addressing because you set the modbusStartAddress
argument to drvModbusAsynConfigure to -1. That means that the "offset" parameter in the record INP link field is the absolute Modbus address, 0x2103 in your case. That is explained here: https://epics-modules.github.io/modbus/#epics-device-support
The record definition depends on what you want to do with the value in that register. Perhaps the simplest is just to read it into a longin record.
This is the example here: https://github.com/epics-modules/modbus/blob/master/modbusApp/Db/longin.template
# longin record template for register inputs
record(longin,"$(P)$(R)") {
field(DTYP,"asynUInt32Digital")
field(INP,"@asynMask($(PORT) $(OFFSET) 0xFFFF)")
field(SCAN,"$(SCAN)")
}
You could load this as follows, for example:
dbLoadRecords("$(MODBUS)/db/longin.template", "P=IOC:, R=longin1, PORT=IN_int, OFFSET=0x2103, SCAN=1 second")
Note that because you are using absolute addressing the driver will not periodically poll, and you therefore cannot use SCAN=I/O Intr, you need to use a periodic scan rate, or Passive
and arrange to processes the record some other way.
If the register contains an integer value that you want to convert to a double in engineering units then you could use an ai record with LINEAR conversion like this example:
# ai record template for register inputs
record(ai, "$(P)$(R)") {
field(DTYP,"asynInt32")
field(INP,"@asynMask($(PORT) $(OFFSET) $(BITS))MODBUS_DATA")
field(LINR,"LINEAR")
field(EGUL,"$(EGUL)")
field(EGUF,"$(EGUF)")
field(HOPR,"$(EGUF)")
field(LOPR,"$(EGUL)")
field(PREC,"$(PREC)")
field(SCAN,"$(SCAN)")
}
The meaning of the BITS argument in the INP field is explained here: https://epics-modules.github.io/modbus/#asynint32.
If your A/D was 12-bit unipolar you would set BITS=12. The EGU* fields set the values of the engineering units for the minimum and maximum values of the A/D, e.g. 0 and 4095 for a 12-bit A/D. PREC is the number of digits you want EPICS to display, and the
other fields are as above.
Mark
From: Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of Christian Pauly via Tech-talk <tech-talk at aps.anl.gov>
Sent: Tuesday, February 14, 2023 6:56 PM To: tech-talk at aps.anl.gov <tech-talk at aps.anl.gov> Subject: Re: Help getting modbus module started Great, thanks for the quick help !
Now it works, the ioc starts and is running. But now i am stuck with defining a record using the modbus interface. As a simpe start, I would like to read a single word (int16) from a given address 0x2103 of master device with id=1, using modbus read function type 3. the relevant part of my st.cmd at the moment looks like this: drvAsynSerialPortConfigure("RS485", "/dev/ttyUSB0", 0, 0, 0) asynSetOption("RS485",0,"baud","9600") asynSetOption("RS485",0,"parity","none") asynSetOption("RS485",0,"bits","7") asynSetOption("RS485",0,"stop","2") asynOctetSetOutputEos("RS485",0,"\r\n") asynOctetSetInputEos("RS485",0,"\r\n") modbusInterposeConfig("RS485",2,1000,5) drvModbusAsynConfigure(IN_int,"RS485",1,3,-1,1,UINT16,1000,0) asynSetTraceIOMask("RS485",0,4) ## Load record instances dbLoadTemplate "FUrecords.db" But how do i have to define the ai(?)-record in FUrecords.db now, to read a single word from the given address 0x2103 using the IN_int function as defined above ? without using template- and substitution files like in all examples i found so far ?? (for sure that is the more clever way, but before i try to understand that part i would like to have a running example first) Thanks again for any help ! Christian On 2/14/23 20:23, Pierrick M Hanlet via Tech-talk wrote: > I almost forgot, you'll also need to add modbus to your > $TOP/configure/RELEASE file (assuming that you have the modbus module). > This may not be precisely worded, but when adding a module, you need to > define its path in $TOP/configure/RELEASE and then > add the modules (lib / dbd) to the $TOP/xxxApp/src/Makefile. > Cheers, > Pierrick > > > > On 2/14/23 13:02, Pierrick M Hanlet via Tech-talk wrote: >> Hi Christian, >> You will also need to add some things to your xxxApp/src/Makefile: >> - xxx_DBD+=modbusSupport.dbd >> - xxx_DBD+=drvAsynSerialPort.dbd >> - xxx_LIBS+=modbus >> >> I think that this should do it for you. >> Good luck, >> Pierrick >> >> >> On 2/14/23 11:38, Christian Pauly via Tech-talk wrote: >>> Hi folks >>> >>> I am trying hard to set up a Raspberry running an EPICS IOC for a >>> Delta VFD motor driver / frequency inverter. The device is controlled >>> via modbus, using a large set of individual 16bit integer read/write >>> registers for configuration, and few more registers for control. >>> At the moment it is configured to talk Modbus ASCII via RS485, and >>> with a simple Python program using minimalmodbus-lib i can talk to the >>> controller. >>> >>> Now i started with a fresh EPICS 3.15.7 base, (in ~/EPICS/base) and >>> installed ASYN-R4-43 (~/EPICS/modules/asyn-R4-43) and modbus >>> (~/EPICS/modules/modbus_R3-2). >>> I initiated a new application ~/EPICS/projects/FUcontrol, >>> ran "makeBaseApp.pl -t example FUcontrol", "makeBaseApp.pl -i -t >>> example FUcontrol" - and thats basically it. >>> >>> And now i am stuck how to include modbus (includes / libs / dbd files) >>> into my exampleApp. >>> >>> I kind of managed to include ASYN already by adding >>> ASYN=... to the RELEASE file >>> >>> and to the Makefile: >>> FUcontrol_LIBS += asyn >>> >>> In my ioc startup st.cmd i can run the commands >>> drvAsynSerialPortConfigure("RS485", "/dev/ttyUSB0", 0, 0, 0) >>> to configure the interface. >>> >>> But if i add >>> modbusInterposeConfig("RS485",2,1000,0) >>> i get an error on startup claiming that modnusinterposeconfig can not >>> be found. >>> >>> >>> So: >>> Is there any simple step-by-step instructions how to add modbus to an >>> existing ioc application ? >>> I could not find anything "simple" in the documentation. I saw the >>> examples which come with modbus, but all these already look quite >>> complicated to me... >>> >>> Or any good advise on how to continue from here ? >>> >>> Thanks for any help ! >>> >>> Christian >>> >>> >>> >>> >>> > |