Commit f383e089 authored by Kuner, Bernhard's avatar Kuner, Bernhard
Browse files

Add support for phyMotion IO-Modules

parent 3a9c4ef3
# PhytronIoCtrl Port
- Support for phyMotion digital and analog IO modules
- Command interface to the phyMotion controler by stringout -in records and IOC shell
## Setup and shell commands
Each IO-Card needs its own port. The number count is not the slot number in the device, but
the number as used to identify the card in a phyMotion command. So the count of the first
analog and digital card begin by 1.
Configuration is neccessary for Analog cards to set the mode - unipolar, bipolar..
``
drvAsynIPPortConfigure("BOX1","193.149.12.226:22222",0,0,1)
# Each card needs its own port.
#Arg0: IP-Port name
#Arg1: PhytronIo port name
#Arg2: Card number as used by the command
#Arg3: Timeout [ms]
#Arg4: Configuration String
phytronCreateIoCtrl( "BOX1","DIG1", 1, 200,"")
phytronCreateIoCtrl( "BOX1","DIG2", 2, 200,"")
# Set AIO modules to bipolar
phytronCreateIoCtrl( "BOX1","AIO1", 1, 200,"DA1.1T1;DA1.2T1;DA1.3T1;DA1.4T1;AD1.1T1;AD1.2T1;AD1.3T1;AD1.4T1")
phytronCreateIoCtrl( "BOX1","AIO2", 2, 200,"DA2.1T1;DA2.2T1;DA2.3T1;DA2.4T1;AD2.1T1;AD2.2T1;AD2.3T1;AD2.4T1")
``
Shell commands:
- ``phycmd <cmd>``: one or list of commands, Return `VALUE|ACK|NACK|ERR` for a single command, something
strange for a list of commands.
- ``phytronReport``: show the card type of each slot in the device, NACK for empty slots.
## Support for these interfaces.
- n = card number as defined in the port
- m = address in the record link
* readInt32 reasons:
* DIN: Read digital port (Command 'EGnR')
* AIN: Read analog port 1 (Command: 'ADn.m') ..
* DOUT: Readback digital output port (Command: 'AGnR')
* AOUT: Readback analog port 1 (Command: 'DAn.m') ..
* writeInt32 reasons:
* DOUT: Write digital port (Command: 'AGn.Sval')
* AOUT: Write analog port 1 (Command: 'DAn.m=val') ..
* readOctet, writeOctet:
* CMD: stringout record will send an arbitrary command and store the response to be read by stringin record.
This string interface is intended to be used for sequencers and scripts to get
a communication channel to the phyMotion device. The response of a command will
contain the ``DATA`` or the strings ``ACK``, ``NACK`` if there is no data. ``ERR`` will
be set for a corruped message.
## Example:
``
record(longin,"MO1:inDig") {
field(DESC,"read digital port")
field(DTYP,"asynInt32")
field(INP,"@asyn(BOXIO,0)DIN")
field(FLNK,"MO1:inAi1")
}
record(longout,"MO1:setDig") {
field(DESC,"set digital port")
field(DTYP,"asynInt32")
field(OUT,"@asyn(BOXIO,0)DOUT")
}
record(longin,"MO1:rdbkDig") {
field(DESC,"rdbk set value")
field(DTYP,"asynInt32")
field(INP,"@asyn(BOXIO,0)DOUT")
}
record(ao,"PHYIO:setVoltAIO2:1") {
field(DESC,"set AIO2, bipolar output")
field(DTYP,"asynInt32")
field(OUT,"@asyn(AIO2,1)AOUT")
field(LINR,"SLOPE")
field(ESLO,"0.00030518")
field(EOFF,"0")
field(EGU ,"V")
field(LOPR,"-10")
field(HOPR,"10")
field(PREC,"4")
field(FLNK,"PHYIO:rdVoltAIO2:1")
}
record(ai,"PHYIO:rdVoltAIO2:1") {
field(DESC,"rd AIO2 bipolar input")
field(DTYP,"asynInt32")
field(INP,"@asyn(AIO2,1)AIN")
field(SCAN,"")
field(LINR,"SLOPE")
field(ESLO,"0.0012208")
field(EOFF,"0")
field(EGU ,"V")
field(LOPR,"-10")
field(HOPR,"10")
field(PREC,"4")
field(FLNK,"PHYIO:rdbkVoltAIO2:1")
}
# command interface
record(stringout,"MO1:setCmd") {
field(DESC,"MO1 Command")
field(DTYP,"asynOctetWrite")
field(OUT, "@asyn(BOXIO,0)CMD")
field(FLNK,"MO1:rdCmd")
}
record(stringin,"MO1:rdCmd") {
field(DESC,"cmd response")
field(DTYP,"asynOctetRead")
field(INP,"@asyn(BOXIO,0)CMD")
field(FLNK,"MO1:rdIntCmd")
}
record(longin,"MO1:rdIntCmd") {
field(DESC,"cmd response as int")
field(INP,"MO1:rdCmd")
}
``
......@@ -4,19 +4,34 @@ include $(TOP)/configure/CONFIG
#----------------------------------------
# Build the IOC application
LIBRARY_IOC += phytronAxisMotor
DBD += phytronSupport.dbd
# The following are compiled and added to the support library
phytronAxisMotor_SRCS += phytronAxisMotor.cpp
phytronAxisMotor_SRCS += phytronAxisMotor.cpp phytronIoCtrl.cpp
INC += phytronAxisMotor.h
INC += phytronAxisMotor.h phytronIoCtrl.h
phytronAxisMotor_LIBS += motor
phytronAxisMotor_LIBS += asyn
phytronAxisMotor_LIBS += $(EPICS_BASE_IOC_LIBS)
# Test with PHYIOC
PROD_IOC = PHYIOC
PHYIOC_SRCS += PHYIOC_registerRecordDeviceDriver.cpp SoftIocMain.cpp
PHYIOC_LIBS += motor
PHYIOC_LIBS += asyn
PHYIOC_LIBS += phytronAxisMotor
PHYIOC_LIBS += $(EPICS_BASE_IOC_LIBS)
PHYIOC_DBD += base.dbd asyn.dbd motorSupport.dbd
PHYIOC_DBD += drvAsynIPPort.dbd phytronSupport.dbd
DBD += PHYIOC.dbd
#===========================
include $(TOP)/configure/RULES
......
/*************************************************************************\
* Copyright (c) 2016 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH (HZB), Berlin, Germany.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
\*************************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "epicsThread.h"
#include "iocsh.h"
int main(int argc,char *argv[])
{
/* Check for PIDFILE in environment and create PID file if set */
FILE* pidfile;
char* pidfilename = getenv("PIDFILE");
if (pidfilename) {
pidfile = fopen(pidfilename, "w");
if (pidfile) {
fprintf(pidfile, "%u\n", getpid());
fclose(pidfile);
} else {
perror("Can't open PID file:");
}
}
if(argc>=2) {
iocsh(argv[1]);
epicsThreadSleep(.2);
}
iocsh(NULL);
return(0);
}
This diff is collapsed.
/*************************************************************************\
* Copyright (c) 2016 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH (HZB), Berlin, Germany.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
\*************************************************************************/
#ifndef phytronIoCtrl_H
#define phytronIoCtrl_H
#include <string>
#include <epicsTypes.h>
#ifdef __cplusplus
#include <asynPortDriver.h>
#define MAX_CONTROLLER_STRING_SIZE 256
#define DEFAULT_CONTROLLER_TIMEOUT 2.0
#define NUM_PHYIO_PARAMS 5
#define dInString "DIN"
#define ainString "AIN"
#define dOutString "DOUT"
#define aoutString "AOUT"
#define cmdString "CMD"
class phytronIoCtrl : public asynPortDriver {
public:
phytronIoCtrl(const char *portName, const char *asynPortName, int numCards,int timeout);
virtual ~phytronIoCtrl();
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
virtual asynStatus readOctet(asynUser *pasynUser, char *value, size_t maxChars,size_t *nActual, int *eomReason);
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus writeOctet(asynUser *pasynUser, const char *value, size_t maxChars,size_t *nActual);
virtual void report(FILE *fp, int level);
char *getCmdBuf() {return cmdBuf;}
char *getControllerName() {return controllerName_;}
/* Functions for direct controller access, work with the first created port */
asynStatus cmd(const char *cmd, char*response, size_t MaxResponseLen) ;
asynStatus setParam(const char *paramStr, int dbg=0);
private:
/* These are convenience functions for controllers that use asynOctet interfaces to the hardware */
asynStatus writeController(const char *output, double timeout);
asynStatus writeReadController(asynUser *pasynUser, const char *value, size_t maxChars,char *data, int *acknowledge, size_t *response_len);
int cardNr;
char * controllerName_;
asynUser *pController_;
int dIn_;
int ain_;
int dOut_;
int aout_;
int cmd_;
char cmdBuf[MAX_CONTROLLER_STRING_SIZE]; // store last response of stringout writeRead
double timeout_;
asynStatus lastStatus;
};
phytronIoCtrl* findController(const char *portName);
#endif /* _cplusplus */
#endif /* */
registrar(phytronRegister)
registrar(phytronIoRegister)
#!../../bin/linux-x86_64/PHYIOC
cd ../..
epicsEnvSet IOC PHYIOC
epicsEnvSet IOCSH_PS1 "${IOC}>"
dbLoadDatabase "dbd/$(IOC).dbd",0,0
${IOC}_registerRecordDeviceDriver pdbbase
drvAsynIPPortConfigure("BOX1","193.149.12.226:22222",0,0,1)
#phytronCreateController ("MOU1", "BOX1", 250, 250, 1000)
#phytronCreateAxis("MOU1", 1, 1)
#phytronCreateAxis("MOU1", 2, 1)
phytronCreateIoCtrl( "BOX1","DIG1", 1, 200,"")
phytronCreateIoCtrl( "BOX1","DIG2", 2, 200,"")
# Set AIO modules to bipolar
phytronCreateIoCtrl( "BOX1","AIO1", 1, 200,"DA1.1T1;DA1.2T1;DA1.3T1;DA1.4T1;AD1.1T1;AD1.2T1;AD1.3T1;AD1.4T1")
phytronCreateIoCtrl( "BOX1","AIO2", 2, 200,"DA2.1T1;DA2.2T1;DA2.3T1;DA2.4T1;AD2.1T1;AD2.2T1;AD2.3T1;AD2.4T1")
phyreport DIG1
dbLoadRecords db/asynRecord.db "P=test:,R=DIG1,PORT=DIG1,ADDR=-1,OMAX=0,IMAX=0"
dbLoadRecords db/asynRecord.db "P=test:,R=DIG2,PORT=DIG2,ADDR=-1,OMAX=0,IMAX=0"
dbLoadRecords db/asynRecord.db "P=test:,R=AIO1,PORT=AIO1,ADDR=-1,OMAX=0,IMAX=0"
dbLoadRecords db/asynRecord.db "P=test:,R=AIO2,PORT=AIO2,ADDR=-1,OMAX=0,IMAX=0"
#dbLoadRecords db/phyRecords.db
dbLoadRecords db/phyIo.db
setIocLogDisable 1
iocInit
#asynSetTraceMask("DIG1",0,0x9)
#asynSetTraceIOMask("DIG1",0,5)
#asynSetTraceMask("DIG2",0,0x9)
#asynSetTraceIOMask("DIG2",0,0x5)
#asynSetTraceMask("AIO1",0,0x9)
#asynSetTraceIOMask("AIO1",0,0x5)
#asynSetTraceMask("AIO2",0,0x9)
#asynSetTraceIOMask("AIO2",0,0x5)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment