• 基于EPICS stream模块的直流电源的IOC控制程序实例


    本实例程序实现了对优利德UDP6720系列直流电源的网络控制和访问,先在此介绍这个项目中使用的硬件:

    1、UDP6721直流电源:受控设备

    2、moxa串口服务器5150:将UDP6721直流电源设备串口连接转成网络连接

    3、香橙派Zero3:运行IOC程序。

    以下是实际连接图: 

     需要EPICS软件模块如下:

    1. base
    2. asyn
    3. stream
    4. autosave

    以下步骤描述如何建立这个IOC程序的过程:

    1、使用工具命令makeBaseApp.pl构建IOC程序架构,程序架构如下:

    1. root@orangepizero3:/usr/local/EPICS/program/udp6721# ls
    2. bin configure db dbd document iocBoot lib Makefile udp6721App

    2、修改confiure/RELEASE文件,增加依赖模块所在的路径:

    1. ...
    2. SUPPORT=/usr/local/EPICS/synApps/support
    3. ASYN=$(SUPPORT)/asyn
    4. STREAM=$(SUPPORT)/stream/streamDevice
    5. AUTOSAVE=$(SUPPORT)/autosave
    6. ...

    3、进入udp6721App/src/目录下,编写sub记录中所需要调用函数的源代码以及相应的dbd文件:

    1. // ubRecordSleep.c
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. int mySubDebug = 0;
    9. static long mySubInit(struct subRecord *precord)
    10. {
    11. if (mySubDebug)
    12. {
    13. printf("Record %s called mySubInit(%p)\n", precord->name, (void *)precord);
    14. }
    15. printf("subInit was called\n");
    16. return 0;
    17. }
    18. static long mySubProcess(struct subRecord * precord)
    19. {
    20. if(mySubDebug)
    21. {
    22. printf("Record %s called mySubProcess(%p)\n", precord->name,(void *)precord);
    23. }
    24. epicsThreadSleep(precord->val);
    25. return 0;
    26. }
    1. # subRecordSleepSupport.dbd
    2. variable(mySubDebug)
    3. function(mySubInit)
    4. function(mySubProcess)

    修改这个目录中的Makefile文件,指明所需要的数据库定义文件以及链接的库文件以及需要编译的源文件:

    1. TOP=../..
    2. include $(TOP)/configure/CONFIG
    3. #----------------------------------------
    4. # ADD MACRO DEFINITIONS AFTER THIS LINE
    5. #=============================
    6. #=============================
    7. # Build the IOC application
    8. PROD_IOC = udp6721
    9. # udp6721.dbd will be created and installed
    10. DBD += udp6721.dbd
    11. # udp6721.dbd will be made up from these files:
    12. udp6721_DBD += base.dbd
    13. udp6721_DBD += asyn.dbd
    14. udp6721_DBD += stream.dbd
    15. udp6721_DBD += subRecordSleepSupport.dbd
    16. udp6721_DBD += drvAsynIPPort.dbd
    17. udp6721_DBD += asSupport.dbd
    18. # Include dbd files from all support applications:
    19. #udp6721_DBD += xxx.dbd
    20. # Add all the support libraries needed by this IOC
    21. udp6721_LIBS += asyn
    22. udp6721_LIBS += stream
    23. udp6721_LIBS += autosave
    24. udp6721_SRCS += subRecordSleep.c
    25. # udp6721_registerRecordDeviceDriver.cpp derives from udp6721.dbd
    26. udp6721_SRCS += udp6721_registerRecordDeviceDriver.cpp
    27. # Build the main IOC entry point on workstation OSs.
    28. udp6721_SRCS_DEFAULT += udp6721Main.cpp
    29. udp6721_SRCS_vxWorks += -nil-
    30. # Add support from base/src/vxWorks if needed
    31. #udp6721_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
    32. # Finally link to the EPICS Base libraries
    33. udp6721_LIBS += $(EPICS_BASE_IOC_LIBS)
    34. #===========================
    35. include $(TOP)/configure/RULES

    4、进入udp6721App/Db/下编写协议文件,数据库实例文件和用于数据保存的req文件:

    1)数据库实例文件:

    1. record(stringin, "$(P)DeviceInfo")
    2. {
    3. field (DESC, "Read Device Info of PS1")
    4. field (DTYP, "stream")
    5. field (INP, "@udp6721.proto getIDNInfo PS1")
    6. field (PINI, "YES")
    7. field (SCAN, "10 second")
    8. }
    9. record(bo, "$(P)OnOff")
    10. {
    11. field (DESC, "Turn On/Off the Device")
    12. field (DTYP, "stream")
    13. field (OUT, "@udp6721.proto setSwitch PS1")
    14. field (ZNAM, "OFF")
    15. field (ONAM, "ON")
    16. field (PINI, "YES")
    17. field (FLNK, "$(P)OnOff_RBV")
    18. }
    19. record(bi, "$(P)OnOff_RBV")
    20. {
    21. field (DESC, "The Status of the Device")
    22. field (DTYP, "stream")
    23. field (INP, "@udp6721.proto getSwitch PS1")
    24. field (ZNAM, "OFF")
    25. field (ONAM, "ON")
    26. field (PINI, "YES")
    27. field (SCAN, "Passive")
    28. }
    29. record(ai, "$(P)Voltage_M")
    30. {
    31. field (DESC, "Output Voltage")
    32. field (DTYP, "stream")
    33. field (INP, "@udp6721.proto measureVoltage PS1")
    34. field (PREC, "2")
    35. field (PINI, "YES")
    36. }
    37. record(ai, "$(P)Current_M")
    38. {
    39. field (DESC, "Output Current")
    40. field (DTYP, "stream")
    41. field (INP, "@udp6721.proto measureCurrent PS1")
    42. field (PREC, "3")
    43. field (SCAN, "I/O Intr")
    44. }
    45. record(ai, "$(P)Power_M")
    46. {
    47. field (DESC, "Output Power")
    48. field (DTYP, "stream")
    49. field (INP, "@udp6721.proto measurePower PS1")
    50. field (PREC, "4")
    51. field (SCAN, "I/O Intr")
    52. }
    53. record(bi, "$(P)CVCC_RBV")
    54. {
    55. field (DESC, "Device Output Mode CV/CC")
    56. field (DTYP, "stream")
    57. field (INP, "@udp6721.proto getCVCC PS1")
    58. field (ZNAM, "CV")
    59. field (ONAM, "CC")
    60. field (SCAN, "1 second")
    61. field (PINI, "YES")
    62. }
    63. record(ai, "$(P)Voltage_RBV")
    64. {
    65. field (DESC, "Output Voltage")
    66. field (DTYP, "stream")
    67. field (INP, "@udp6721.proto getVoltage PS1")
    68. field (PREC, "2")
    69. field (PINI, "YES")
    70. }
    71. record(ai, "$(P)Current_RBV")
    72. {
    73. field (DESC, "Output Current")
    74. field (DTYP, "stream")
    75. field (INP, "@udp6721.proto getCurrent PS1")
    76. field (PREC, "3")
    77. field (PINI, "YES")
    78. }
    79. record(ao, "$(P)SetVoltage")
    80. {
    81. field (DESC, "Output Voltage")
    82. field (DTYP, "stream")
    83. field (OUT, "@udp6721.proto setVoltage PS1")
    84. field (PREC, "2")
    85. field (FLNK, "$(P)SubSleep")
    86. }
    87. record(ao, "$(P)SetCurrent")
    88. {
    89. field (DESC, "Output Current")
    90. field (DTYP, "stream")
    91. field (OUT, "@udp6721.proto setCurrent PS1")
    92. field (PREC, "3")
    93. field (FLNK, "$(P)SubSleep")
    94. }
    95. record(fanout, "$(P)Fanout")
    96. {
    97. field(SELM,"All")
    98. field(SCAN, "Passive")
    99. field(LNK0, "$(P)Voltage_M")
    100. field(LNK1, "$(P)Voltage_RBV")
    101. field(LNK2, "$(P)Current_RBV")
    102. }
    103. record(sub,"$(P)SubSleep")
    104. {
    105. field(INAM,"mySubInit")
    106. field(SNAM,"mySubProcess")
    107. field(VAL, "0.8")
    108. field(FLNK, "$(P)Fanout.PROC")
    109. }
    110. record(ao, "$(P)SetVProtectValue")
    111. {
    112. field (DESC, "Set Protect Voltage")
    113. field (DTYP, "stream")
    114. field (OUT, "@udp6721.proto setVProtectValue PS1")
    115. field (PREC, "2")
    116. field (FLNK, "$(P)VProtectValue_RBV")
    117. }
    118. record(ai, "$(P)VProtectValue_RBV")
    119. {
    120. field (DESC, "Protect Voltage")
    121. field (DTYP, "stream")
    122. field (INP, "@udp6721.proto getVProtectValue PS1")
    123. field (PREC, "2")
    124. field (PINI, "YES")
    125. }
    126. record(ao, "$(P)SetCProtectValue")
    127. {
    128. field (DESC, "Set Protect Currrent")
    129. field (DTYP, "stream")
    130. field (OUT, "@udp6721.proto setCProtectValue PS1")
    131. field (PREC, "3")
    132. field (FLNK, "$(P)CProtectValue_RBV")
    133. }
    134. record(ai, "$(P)CProtectValue_RBV")
    135. {
    136. field (DESC, "Protect Current")
    137. field (DTYP, "stream")
    138. field (INP, "@udp6721.proto getCProtectValue PS1")
    139. field (PREC, "3")
    140. field (PINI, "YES")
    141. }
    142. record(bo, "$(P)OnOffVProtectState")
    143. {
    144. field (DESC, "Set Volt Protect State")
    145. field (DTYP, "stream")
    146. field (ZNAM, "ON")
    147. field (ONAM, "OFF")
    148. field (OUT, "@udp6721.proto switchVProtectState PS1")
    149. field (FLNK, "$(P)OnOffVProtectState_RBV")
    150. }
    151. record(bi, "$(P)OnOffVProtectState_RBV")
    152. {
    153. field (DESC, "Volt Protect State")
    154. field (DTYP, "stream")
    155. field (ZNAM, "ON")
    156. field (ONAM, "OFF")
    157. field (INP, "@udp6721.proto getVProtectState PS1")
    158. field (PINI, "YES")
    159. }
    160. record(bo, "$(P)OnOffCProtectState")
    161. {
    162. field (DESC, "Set Current Protect State")
    163. field (DTYP, "stream")
    164. field (ZNAM, "ON")
    165. field (ONAM, "OFF")
    166. field (OUT, "@udp6721.proto switchCProtectState PS1")
    167. field (FLNK, "$(P)OnOffCProtectState_RBV")
    168. }
    169. record(bi, "$(P)OnOffCProtectState_RBV")
    170. {
    171. field (DESC, "Current Protect State")
    172. field (DTYP, "stream")
    173. field (ZNAM, "ON")
    174. field (ONAM, "OFF")
    175. field (INP, "@udp6721.proto getCProtectState PS1")
    176. field (PINI, "YES")
    177. }
    178. record(stringout, "$(P)SetRemote")
    179. {
    180. field (DESC, "Current Protect State")
    181. field (DTYP, "stream")
    182. field (OUT, "@udp6721.proto setRemote PS1")
    183. field (FLNK, "$(P)Remote_RBV")
    184. }
    185. record(bi, "$(P)Remote_RBV")
    186. {
    187. field (DESC, "Remote State")
    188. field (DTYP, "stream")
    189. field (INP, "@udp6721.proto getRemote PS1")
    190. field (ZNAM, "YES")
    191. field (ONAM, "NO")
    192. field (PINI, "YES")
    193. }

    协议文件:

    1. Terminator = LF;
    2. getIDNInfo {
    3. out "*IDN?";
    4. in "Uni-Trend,%s";
    5. }
    6. # Switch is an enum, either OFF or ON
    7. # use bi and bo records
    8. getSwitch {
    9. out "OUTPUT?"; in "%{OFF|ON}";
    10. }
    11. setSwitch {
    12. out "OUTPUT %{OFF|ON}";
    13. @init { getSwitch; }
    14. }
    15. measureVoltage {
    16. out "MEASure:ALL?";
    17. in "%f,%*f,%*f";
    18. }
    19. measureCurrent {
    20. in "%*f,%f,%*f";
    21. }
    22. measurePower {
    23. in "%*f,%*f,%f";
    24. }
    25. getCVCC {
    26. out "OUTPUT:CVCC?"; in "%{CV|CC}";
    27. }
    28. setVoltage {
    29. out "VOLTage %.2f";
    30. }
    31. getVoltage {
    32. out "VOLTage?";
    33. in "%f";
    34. }
    35. setCurrent {
    36. out "CURRent %.3f";
    37. }
    38. getCurrent {
    39. out "CURRent?";
    40. in "%f";
    41. }
    42. setVProtectValue {
    43. out "VOLTage:PROTection %.2f";
    44. }
    45. getVProtectValue {
    46. out "VOLTage:PROTection?";
    47. in "%f";
    48. }
    49. setCProtectValue {
    50. out "CURRent:PROTection %.3f";
    51. }
    52. getCProtectValue {
    53. out "CURRent:PROTection?";
    54. in "%f";
    55. }
    56. switchVProtectState {
    57. out "VOLTage:PROTection:STATe %{ON|OFF}";
    58. }
    59. getVProtectState {
    60. out "VOLTage:PROTection:STATe?";
    61. in "%{ON|OFF}";
    62. }
    63. switchCProtectState {
    64. out "CURRent:PROTection:STATe {ON|OFF}";
    65. }
    66. getCProtectState {
    67. out "CURRent:PROTection:STATe?";
    68. in "%{ON|OFF}";
    69. }
    70. setRemote {
    71. out "SYSTem:REMote";
    72. }
    73. getRemote {
    74. out "SYSTem:REMote?";
    75. in "%{YES|NO}";
    76. }

    存储配置文件:

    1. $(P)SetVoltage
    2. $(P)SetCurrent
    3. $(P)SetVProtectValue
    4. $(P)SetCProtectValue
    5. $(P)SetRemote

    编辑相同路径下的Makefile文件,添加以下:

    1. TOP=../..
    2. include $(TOP)/configure/CONFIG
    3. #----------------------------------------
    4. # ADD MACRO DEFINITIONS AFTER THIS LINE
    5. #----------------------------------------------------
    6. # Create and install (or just install) into /db
    7. # databases, templates, substitutions like this
    8. DB += udp6721.proto
    9. DB += udp6721.db
    10. DB += udp6721.req
    11. #----------------------------------------------------
    12. # If .db template is not named *.template add
    13. # _template =
    14. include $(TOP)/configure/RULES

    5 切换到顶层目录,执行make命令,进行编译。

    6 进入启动目录 iocBoot/iocudp6721/:

    创建两个目录autosave和req,并且在req下添加一个auto_settings.req文件,内容如下:

    file udp6721.req  P=$(P)

    7 编辑启动文件st.cmd,内容如下:

    1. #!../../bin/linux-aarch64/udp6721
    2. #- You may have to change udp6721 to something else
    3. #- everywhere it appears in this file
    4. < envPaths
    5. cd "${TOP}"
    6. ## Register all support components
    7. dbLoadDatabase "dbd/udp6721.dbd"
    8. udp6721_registerRecordDeviceDriver pdbbase
    9. # UDP6721设备的IP地址和连接端口
    10. drvAsynIPPortConfigure("PS1", "192.168.3.101:4001", 0, 0 ,1)
    11. ## Load record instances
    12. epicsEnvSet ("STREAM_PROTOCOL_PATH", "$(TOP)/db/")
    13. dbLoadRecords("db/udp6721.db","P=UDP6721:")
    14. set_requestfile_path("$(TOP)/db")
    15. set_requestfile_path("$(TOP)/iocBoot/$(IOC)/req/")
    16. # 通过调用set_savefile_path函数指定你想要.sav文件被写到哪个目录中。
    17. set_savefile_path("$(TOP)/iocBoot/$(IOC)/autosave/")
    18. # 使用set_pass_restoreFile()函数
    19. # 指定哪些save文件要在记录初始化前(pass 0)前被恢复,以及哪些save文件在记录初始化后(pass 1)被恢复
    20. set_pass1_restoreFile("auto_settings.sav")
    21. save_restoreSet_numSeqFiles(3)
    22. save_restoreSet_SeqPeriodInSeconds(600)
    23. save_restoreSet_RetrySeconds(60)
    24. save_restoreSet_CAReconnect(1)
    25. save_restoreSet_CallbackTimeout(-1)
    26. cd "${TOP}/iocBoot/${IOC}"
    27. iocInit
    28. create_monitor_set("auto_settings.req",5,"P=UDP6721:")

    8 启动这个IOC,用dbl查看加载的记录实例:

     ../../bin/linux-aarch64/udp6721 st.cmd
    1. epics> dbl
    2. UDP6721:Voltage_M
    3. UDP6721:Current_M
    4. UDP6721:Power_M
    5. UDP6721:Voltage_RBV
    6. UDP6721:Current_RBV
    7. UDP6721:VProtectValue_RBV
    8. UDP6721:CProtectValue_RBV
    9. UDP6721:SetVoltage
    10. UDP6721:SetCurrent
    11. UDP6721:SetVProtectValue
    12. UDP6721:SetCProtectValue
    13. UDP6721:OnOff_RBV
    14. UDP6721:CVCC_RBV
    15. UDP6721:OnOffVProtectState_RBV
    16. UDP6721:OnOffCProtectState_RBV
    17. UDP6721:Remote_RBV
    18. UDP6721:OnOff
    19. UDP6721:OnOffVProtectState
    20. UDP6721:OnOffCProtectState
    21. UDP6721:Fanout
    22. UDP6721:DeviceInfo
    23. UDP6721:SetRemote
    24. UDP6721:SubSleep

    9 用CSS查看连接以上记录实例:

    可以通过以上图形界面设置直流电源的电压和电流输出。 

    程序下载:【免费】利德UDP6720系列直流电源IOC程序资源-CSDN文库

    以下是此设备的编程手册:

    1. 1.*IDN?
    2. 查询设备信息。
    3. 2.MEASure:VOLTage?
    4. MEASure:CURRent?
    5. MEASure:POWEr?
    6. 查询回读电压\电流\功率值。
    7. 3.MEASure:ALL?
    8. 同时查询回读电压、电流、功率值。
    9. 4.[SOURce:]VOLTage <value>
    10. [SOURce:]CURRent <value>
    11. 设置输出电压(电流)值,如果已打开保护功能且设置值大于保护值时,设置无效。
    12. 5.[SOURce:]VOLTage:PROTection <value>
    13. [SOURce:]CURRent:PROTection <value>
    14. 设置过压(过流)保护功能的保护值。
    15. 6.[SOURce:]VOLTage:PROTection:STATe {ON|OFF}
    16. [SOURce:]CURRent:PROTection:STATe {ON|OFF}
    17. 打开或关闭过压(过流)保护功能。
    18. 7.[SOURce:]VOLTage?
    19. [SOURce:]CURRent?
    20. 查询输出电压(电流)值。
    21. 8.[SOURce:]VOLTage:PROTection?
    22. [SOURce:]CURRent:PROTection?
    23. 查询过压(过流)保护功能的保护值。
    24. 9.[SOURce:]VOLTage:PROTection:STATe?
    25. [SOURce:]CURRent:PROTection:STATe?
    26. 查询过压(过流)保护功能的开关状态。返回“ON”或“OFF”。
    27. 10.OUTPut {ON|OFF}
    28. 打开或关闭输出。
    29. 11.OUTPut?
    30. 查询输出开关状态。返回“ON”或“OFF”。
    31. 12.OUTPut:CVCC?
    32. 查询输出恒压恒流状态。返回“CV”或“CC”
  • 相关阅读:
    中秋节——嫦娥奔月
    搜索引擎-01-概览
    mysql存储引擎
    【C++入门】多继承(菱形继承)及其二义性问题
    使用flash_download_tool工具烧录esp8266的固件但无法烧录成功
    “第五十天” 机组--数据的表示
    “双面”九号公司:小米、顺为资本等减持,高禄峰推高价回购方案
    ats 6.2.3中diags.log日志滚存遇到的assert崩溃问题并解决
    服务器之间传文件夹,文件夹内容为空
    Ubuntu平铺左、右、上、下、1/2、1/4窗口(脚本)
  • 原文地址:https://blog.csdn.net/yuyuyuliang00/article/details/134175579