This example program implements network control and access to the UDP6720 series DC power supply. First, let’s introduce the hardware used in this project:
1. UDP6721 DC power supply: controlled equipment
2. moxa serial port server 5150: converts the UDP6721 DC power supply device serial port connection into a network connection
3. Orange Pie Zero3: Run the IOC program.
Here is the actual connection diagram:
The required EPICS software modules are as follows:
- base
- asyn
- stream
- autosave
The following steps describe the process of setting up this IOC program:
1. Use the tool command makeBaseApp.pl to build the IOC program architecture. The program architecture is as follows:
root@orangepizero3:/usr/local/EPICS/program/udp6721# ls bin configure db dbd document iocBoot lib Makefile udp6721App
2. Modify the confiure/RELEASE file and add the path where the dependent modules are located:
... SUPPORT=/usr/local/EPICS/synApps/support ASYN=$(SUPPORT)/asyn STREAM=$(SUPPORT)/stream/streamDevice AUTOSAVE=$(SUPPORT)/autosave ...
3. Enter the udp6721App/src/ directory and write the source code of the function that needs to be called in the sub record and the corresponding dbd file:
// ubRecordSleep.c #include <stdio.h> #include <dbDefs.h> #include <epicsThread.h> #include <registryFunction.h> #include <subRecord.h> #include <epicsExport.h> int mySubDebug = 0; static long mySubInit(struct subRecord *precord) { if(mySubDebug) { printf("Record %s called mySubInit(%p)\ ", precord->name, (void *)precord); } printf("subInit was called\ "); return 0; } static long mySubProcess(struct subRecord * record) { if(mySubDebug) { printf("Record %s called mySubProcess(%p)\ ", precord->name,(void *)precord); } epicsThreadSleep(precord->val); return 0; }
# subRecordSleepSupport.dbd variable(mySubDebug) function(mySubInit) function(mySubProcess)
Modify the Makefile in this directory to specify the required database definition files, linked library files, and source files that need to be compiled:
TOP=../.. include $(TOP)/configure/CONFIG #--------------------------------------------- #ADD MACRO DEFINITIONS AFTER THIS LINE #============================== #============================== #Build the IOC application PROD_IOC = udp6721 # udp6721.dbd will be created and installed DBD + = udp6721.dbd # udp6721.dbd will be made up from these files: udp6721_DBD + = base.dbd udp6721_DBD + = asyn.dbd udp6721_DBD + = stream.dbd udp6721_DBD + = subRecordSleepSupport.dbd udp6721_DBD + = drvAsynIPPort.dbd udp6721_DBD + = asSupport.dbd # Include dbd files from all support applications: #udp6721_DBD + = xxx.dbd # Add all the support libraries needed by this IOC udp6721_LIBS + = asyn udp6721_LIBS + = stream udp6721_LIBS + = autosave udp6721_SRCS + = subRecordSleep.c # udp6721_registerRecordDeviceDriver.cpp derives from udp6721.dbd udp6721_SRCS + = udp6721_registerRecordDeviceDriver.cpp # Build the main IOC entry point on workstation OSs. udp6721_SRCS_DEFAULT + = udp6721Main.cpp udp6721_SRCS_vxWorks + = -nil- # Add support from base/src/vxWorks if needed #udp6721_OBJS_vxWorks + = $(EPICS_BASE_BIN)/vxComLibrary # Finally link to the EPICS Base libraries udp6721_LIBS + = $(EPICS_BASE_IOC_LIBS) #============================ include $(TOP)/configure/RULES
4. Enter udp6721App/Db/ to write the protocol file, database instance file and req file for data saving:
1) Database instance file:
record(stringin, "$(P)DeviceInfo") { field (DESC, "Read Device Info of PS1") field (DTYP, "stream") field (INP, "@udp6721.proto getIDNInfo PS1") field (PINI, "YES") field (SCAN, "10 second") } record(bo, "$(P)OnOff") { field (DESC, "Turn On/Off the Device") field (DTYP, "stream") field (OUT, "@udp6721.proto setSwitch PS1") field (ZNAM, "OFF") field (ONAM, "ON") field (PINI, "YES") field (FLNK, "$(P)OnOff_RBV") } record(bi, "$(P)OnOff_RBV") { field (DESC, "The Status of the Device") field (DTYP, "stream") field (INP, "@udp6721.proto getSwitch PS1") field (ZNAM, "OFF") field (ONAM, "ON") field (PINI, "YES") field (SCAN, "Passive") } record(ai, "$(P)Voltage_M") { field (DESC, "Output Voltage") field (DTYP, "stream") field (INP, "@udp6721.proto measureVoltage PS1") field (PREC, "2") field (PINI, "YES") } record(ai, "$(P)Current_M") { field (DESC, "Output Current") field (DTYP, "stream") field (INP, "@udp6721.proto measureCurrent PS1") field (PREC, "3") field (SCAN, "I/O Intr") } record(ai, "$(P)Power_M") { field (DESC, "Output Power") field (DTYP, "stream") field (INP, "@udp6721.proto measurePower PS1") field (PREC, "4") field (SCAN, "I/O Intr") } record(bi, "$(P)CVCC_RBV") { field (DESC, "Device Output Mode CV/CC") field (DTYP, "stream") field (INP, "@udp6721.proto getCVCC PS1") field (ZNAM, "CV") field (ONAM, "CC") field (SCAN, "1 second") field (PINI, "YES") } record(ai, "$(P)Voltage_RBV") { field (DESC, "Output Voltage") field (DTYP, "stream") field (INP, "@udp6721.proto getVoltage PS1") field (PREC, "2") field (PINI, "YES") } record(ai, "$(P)Current_RBV") { field (DESC, "Output Current") field (DTYP, "stream") field (INP, "@udp6721.proto getCurrent PS1") field (PREC, "3") field (PINI, "YES") } record(ao, "$(P)SetVoltage") { field (DESC, "Output Voltage") field (DTYP, "stream") field (OUT, "@udp6721.proto setVoltage PS1") field (PREC, "2") field (FLNK, "$(P)SubSleep") } record(ao, "$(P)SetCurrent") { field (DESC, "Output Current") field (DTYP, "stream") field (OUT, "@udp6721.proto setCurrent PS1") field (PREC, "3") field (FLNK, "$(P)SubSleep") } record(fanout, "$(P)Fanout") { field(SELM,"All") field(SCAN, "Passive") field(LNK0, "$(P)Voltage_M") field(LNK1, "$(P)Voltage_RBV") field(LNK2, "$(P)Current_RBV") } record(sub,"$(P)SubSleep") { field(INAM,"mySubInit") field(SNAM,"mySubProcess") field(VAL, "0.8") field(FLNK, "$(P)Fanout.PROC") } record(ao, "$(P)SetVProtectValue") { field (DESC, "Set Protect Voltage") field (DTYP, "stream") field (OUT, "@udp6721.proto setVProtectValue PS1") field (PREC, "2") field (FLNK, "$(P)VProtectValue_RBV") } record(ai, "$(P)VProtectValue_RBV") { field (DESC, "Protect Voltage") field (DTYP, "stream") field (INP, "@udp6721.proto getVProtectValue PS1") field (PREC, "2") field (PINI, "YES") } record(ao, "$(P)SetCProtectValue") { field (DESC, "Set Protect Current") field (DTYP, "stream") field (OUT, "@udp6721.proto setCProtectValue PS1") field (PREC, "3") field (FLNK, "$(P)CProtectValue_RBV") } record(ai, "$(P)CProtectValue_RBV") { field (DESC, "Protect Current") field (DTYP, "stream") field (INP, "@udp6721.proto getCProtectValue PS1") field (PREC, "3") field (PINI, "YES") } record(bo, "$(P)OnOffVProtectState") { field (DESC, "Set Volt Protect State") field (DTYP, "stream") field (ZNAM, "ON") field (ONAM, "OFF") field (OUT, "@udp6721.proto switchVProtectState PS1") field (FLNK, "$(P)OnOffVProtectState_RBV") } record(bi, "$(P)OnOffVProtectState_RBV") { field (DESC, "Volt Protect State") field (DTYP, "stream") field (ZNAM, "ON") field (ONAM, "OFF") field (INP, "@udp6721.proto getVProtectState PS1") field (PINI, "YES") } record(bo, "$(P)OnOffCProtectState") { field (DESC, "Set Current Protect State") field (DTYP, "stream") field (ZNAM, "ON") field (ONAM, "OFF") field (OUT, "@udp6721.proto switchCProtectState PS1") field (FLNK, "$(P)OnOffCProtectState_RBV") } record(bi, "$(P)OnOffCProtectState_RBV") { field (DESC, "Current Protect State") field (DTYP, "stream") field (ZNAM, "ON") field (ONAM, "OFF") field (INP, "@udp6721.proto getCProtectState PS1") field (PINI, "YES") } record(stringout, "$(P)SetRemote") { field (DESC, "Current Protect State") field (DTYP, "stream") field (OUT, "@udp6721.proto setRemote PS1") field (FLNK, "$(P)Remote_RBV") } record(bi, "$(P)Remote_RBV") { field (DESC, "Remote State") field (DTYP, "stream") field (INP, "@udp6721.proto getRemote PS1") field (ZNAM, "YES") field (ONAM, "NO") field (PINI, "YES") }
Agreement document:
Terminator = LF; getIDNInfo { out "*IDN?"; in "Uni-Trend,%s"; } # Switch is an enum, either OFF or ON # use bi and bo records getSwitch { out "OUTPUT?"; in "%{OFF|ON}"; } setSwitch { out "OUTPUT %{OFF|ON}"; @init { getSwitch; } } measureVoltage { out "MEASure:ALL?"; in "%f,%*f,%*f"; } measureCurrent { in "%*f,%f,%*f"; } measurePower { in "%*f,%*f,%f"; } getCVCC { out "OUTPUT:CVCC?"; in "%{CV|CC}"; } setVoltage { out "VOLTage %.2f"; } getVoltage { out "VOLTage?"; in "%f"; } setCurrent { out "CURRent %.3f"; } getCurrent { out "CURRent?"; in "%f"; } setVProtectValue { out "VOLTage:PROTection %.2f"; } getVProtectValue { out "VOLTage:PROTection?"; in "%f"; } setCProtectValue { out "CURRent:PROTection %.3f"; } getCProtectValue { out "CURRent:PROTection?"; in "%f"; } switchVProtectState { out "VOLTage:PROTection:STATe %{ON|OFF}"; } getVProtectState { out "VOLTage:PROTection:STATe?"; in "%{ON|OFF}"; } switchCProtectState { out "CURRent:PROTection:STATe {ON|OFF}"; } getCProtectState { out "CURRent:PROTection:STATe?"; in "%{ON|OFF}"; } setRemote { out "SYSTem:REMote"; } getRemote { out "SYSTem:REMote?"; in "%{YES|NO}"; }
Store configuration file:
$(P)SetVoltage $(P)SetCurrent $(P)SetVProtectValue $(P)SetCProtectValue $(P)SetRemote
Edit the Makefile in the same path and add the following:
TOP=../.. include $(TOP)/configure/CONFIG #--------------------------------------------- #ADD MACRO DEFINITIONS AFTER THIS LINE #------------------------------------------------ --- # Create and install (or just install) into <top>/db # databases, templates, substitutions like this DB + = udp6721.proto DB + = udp6721.db DB + = udp6721.req #------------------------------------------------ --- # If <anyname>.db template is not named <anyname>*.template add # <anyname>_template = <templatename> include $(TOP)/configure/RULES
5. Switch to the top-level directory and execute the make command to compile.
6 Enter the startup directory iocBoot/iocudp6721/:
Create two directories, autosave and req, and add an auto_settings.req file under req with the following content:
file udp6721.req P=$(P)
7 Edit the startup file st.cmd with the following content:
#!../../bin/linux-aarch64/udp6721 #- You may have to change udp6721 to something else #- everywhere it appears in this file < envPaths cd "${TOP}" ## Register all support components dbLoadDatabase "dbd/udp6721.dbd" udp6721_registerRecordDeviceDriver pdbbase #IP address and connection port of UDP6721 device drvAsynIPPortConfigure("PS1", "192.168.3.101:4001", 0, 0 ,1) ## Load record instances epicsEnvSet ("STREAM_PROTOCOL_PATH", "$(TOP)/db/") dbLoadRecords("db/udp6721.db","P=UDP6721:") set_requestfile_path("$(TOP)/db") set_requestfile_path("$(TOP)/iocBoot/$(IOC)/req/") # Specify the directory where you want the .sav file to be written to by calling the set_savefile_path function. set_savefile_path("$(TOP)/iocBoot/$(IOC)/autosave/") # Use set_pass<N>_restoreFile() function # Specify which save files should be restored before recording initialization (pass 0), and which save files should be restored after recording initialization (pass 1) set_pass1_restoreFile("auto_settings.sav") save_restoreSet_numSeqFiles(3) save_restoreSet_SeqPeriodInSeconds(600) save_restoreSet_RetrySeconds(60) save_restoreSet_CAReconnect(1) save_restoreSet_CallbackTimeout(-1) cd "${TOP}/iocBoot/${IOC}" iocInit create_monitor_set("auto_settings.req",5,"P=UDP6721:")
8 Start this IOC and use dbl to view the loaded record instance:
../../bin/linux-aarch64/udp6721 st.cmd
epics> dbl UDP6721:Voltage_M UDP6721:Current_M UDP6721:Power_M UDP6721:Voltage_RBV UDP6721:Current_RBV UDP6721:VProtectValue_RBV UDP6721: CProtectValue_RBV UDP6721:SetVoltage UDP6721:SetCurrent UDP6721:SetVProtectValue UDP6721:SetCProtectValue UDP6721:OnOff_RBV UDP6721:CVCC_RBV UDP6721:OnOffVProtectState_RBV UDP6721:OnOffCProtectState_RBV UDP6721:Remote_RBV UDP6721:OnOff UDP6721:OnOffVProtectState UDP6721:OnOffCProtectState UDP6721:Fanout UDP6721:DeviceInfo UDP6721:SetRemote UDP6721:SubSleep
9 Use CSS to view the above record example:
The voltage and current output of the DC power supply can be set through the above graphical interface.
Program download: [Free] Lid UDP6720 series DC power supply IOC program resources-CSDN library
The following is the programming manual for this device:
1.*IDN? Query device information. 2.MEASure:VOLTage? MEASure:CURRent? MEASure:POWEr? Query the readback voltage\current\power value. 3.MEASure:ALL? At the same time, query the readback voltage, current, and power values. 4.[SOURce:]VOLTage <value> [SOURce:]CURRent <value> Set the output voltage (current) value. If the protection function is turned on and the setting value is greater than the protection value, the setting is invalid. 5.[SOURce:]VOLTage:PROTection <value> [SOURce:]CURRent:PROTection <value> Set the protection value of overvoltage (overcurrent) protection function. 6.[SOURce:]VOLTage:PROTection:STATe {ON|OFF} [SOURce:]CURRent:PROTection:STATe {ON|OFF} Turn on or off the overvoltage (overcurrent) protection function. 7.[SOURce:]VOLTage? [SOURce:]CURRent? Query the output voltage (current) value. 8.[SOURce:]VOLTage:PROTection? [SOURce:]CURRent:PROTection? Query the protection value of overvoltage (overcurrent) protection function. 9.[SOURce:]VOLTage:PROTection:STATe? [SOURce:]CURRent:PROTection:STATe? Query the switch status of the overvoltage (overcurrent) protection function. Returns "ON" or "OFF". 10.OUTPut {ON|OFF} Turn the output on or off. 11.OUTPut? Query the output switch status. Returns "ON" or "OFF". 12.OUTPut:CVCC? Query the output constant voltage and constant current status. Return "CV" or "CC"
The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. C Skill Tree Home Page Overview 193997 people are learning the system