RaspberryPI Kunbus
https://revolution.kunbus.com/
Revolution Pi is an open, modular and cost-effective industrial PC based on the well-known Raspberry Pi. Housed in a slim DIN rail housing, the three available base modules can be expanded with a variety of suitable I/O modules and fieldbus gateways. The 24V-operated modules can be connected via a pluggable terminal strip connection and can be configured using a graphical configuration tool.
How to install EPICS on a Kunbus-systeme:
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_CTYPE = "UTF-8",
LC_TERMINAL = "iTerm2",
LC_TERMINAL_VERSION = "3.3.2",
LANG = "en_GB.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("en_GB.UTF-8").
adduser: Only root may add a user or group to the system.
in /etc/ssh/sshd_config disable accept env
#AcceptEnv LANG LC_*
as user "pi"
add epics to sudo /etc/group
remove teamviewer and update systeme
sudo apt purge teamviewer-revpi
sudo rm sources.list.d/teamviewer-revpi.list
sudo apt update
sudo apt upgrade
login as user epics:
cd EPICS
clone actual base:
cd base-7.0.3
make
Add to .bashrc :
export EPICS_HOST_ARCH=linux-arm
export PATH=${EPICS_BASE}/bin/${EPICS_HOST_ARCH}:${PATH}
example IOCSwitchBox at FHI:
cd FHI
epics@RevPi127xx:~/FHI/IOCSwitchBox $ makeBaseApp.pl -t example IOCSwitchBox
epics@RevPi127xx:~/FHI/IOCSwitchBox $ makeBaseApp.pl -i -t example IOCSwitchBox
make
total 36
drwxr-xr-x 3 epics epics 4096 Aug 27 13:06 bin
drwxr-xr-x 4 epics epics 4096 Aug 27 13:06 configure
drwxr-xr-x 2 epics epics 4096 Aug 27 13:06 db
drwxr-xr-x 2 epics epics 4096 Aug 27 13:06 dbd
drwxr-xr-x 2 epics epics 4096 Aug 27 13:06 include
drwxr-xr-x 3 epics epics 4096 Aug 27 13:05 iocBoot
drwxr-xr-x 4 epics epics 4096 Aug 27 13:05 IOCSwitchBoxApp
drwxr-xr-x 3 epics epics 4096 Aug 27 13:06 lib
-rw-r--r-- 1 epics epics 900 Aug 27 13:05 Makefile
Start IOC
chmod u+x st.cmd
#!../../bin/linux-arm/IOCSwitchBox
< envPaths
epicsEnvSet("IOC","iocIOCSwitchBox")
epicsEnvSet("TOP","/home/epics/FHI/IOCSwitchBox")
epicsEnvSet("EPICS_BASE","/home/epics/EPICS/base-7.0.3")
cd "/home/epics/FHI/IOCSwitchBox"
## Register all support components
dbLoadDatabase "dbd/IOCSwitchBox.dbd"
IOCSwitchBox_registerRecordDeviceDriver pdbbase
## Load record instances
dbLoadTemplate "db/user.substitutions"
dbLoadRecords "db/IOCSwitchBoxVersion.db", "user=epics"
dbLoadRecords "db/dbSubExample.db", "user=epics"
#var mySubDebug 1
#traceIocInit
cd "/home/epics/FHI/IOCSwitchBox/iocBoot/iocIOCSwitchBox"
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.3.1-DEV
## EPICS Base built Aug 26 2019
############################################################################
iocRun: All initialization complete
## Start any sequence programs
#seq sncExample, "user=epics"
epics> dbl
epics:IOCSwitchBox:version
epics:circle:angle
epics:line:a
epics:circle:x
epics:circle:y
epics:calcExample
epics:calcExample1
epics:calc1
epics:calcExample2
epics:calc2
epics:calcExample3
epics:calc3
epics:circle:step
epics:circle:period
epics:circle:tick
epics:compressExample
epics:aSubExample
epics:subExample
epics:line:b
epics:aiExample
epics:aiExample1
epics:ai1
epics:aiExample2
epics:ai2
epics:aiExample3
epics:ai3
epics:xxxExample
epics>
RevPi C-Code:
use tools:
Found 2 devices:
Address: 0 module type: 95 (0x5f) RevPi Core V1.2
Module is present
input offset: 113 length: 6
output offset: 119 length: 5
Address: 31 module type: 96 (0x60) RevPi DIO V1.4
Module is present
input offset: 0 length: 70
output offset: 70 length: 18
Here the documentation of Kunbus is somewhat misleading:
length should be one of 1|2|4.
E.g.: -w 0,4,31224205:
Write value 31224205 hex (=824328709 dez) to offset 0.
Write value aaaa hex (=43690 dez) to offset 70.
Disable useless services:
epics@RevPi127xx:~/REVPI/piControl $ sudo systemctl disable apache2
Starting NTP Service in FHI-FEL lan. Now build the "Device Support" in the example. Easiest in the sub-record.
Therefore add the call to the DIO in ...App/src/dbSubExample.c.
(copy the "writeData" function from the piControl/piTest and include the header and in the Makefile piControlIf.c)
Determine the offset to the port afterwards correctly or build it into the init, this is really just quick and dirty to show what you can do fast.
#include <dbDefs.h>
#include <registryFunction.h>
#include <subRecord.h>
#include <aSubRecord.h>
#include <epicsExport.h>
int mySubDebug;
#include "piControlIf.h"
/***********************************************************************************/
/*!
* @brief Write data to process image
*
* Write <length> bytes to a specific offset of process image.
*
* @param[in] Offset
* @param[in] Length
* @param[in] Value to write
*
************************************************************************************/
void writeData(int offset, int length, unsigned long i32uValue)
{
int rc;
if (length != 1 && length != 2 && length != 4) {
printf("Length must be one of 1|2|4\n");
return;
}
rc = piControlWrite(offset, length, (uint8_t *) & i32uValue);
if (rc < 0) {
printf("write error \n");
} else {
printf("Write value %lx hex (=%ld dez) to offset %d.\n", i32uValue, i32uValue, offset);
}
}
static long mySubInit(subRecord *precord)
"dbSubExample.c" 84 lines, 2159 characters
#include <stdio.h>
#include <dbDefs.h>
#include <registryFunction.h>
#include <subRecord.h>
#include <aSubRecord.h>
#include <epicsExport.h>
int mySubDebug;
#include "piControlIf.h"
/***********************************************************************************/
/*!
* @brief Write data to process image
*
* Write <length> bytes to a specific offset of process image.
*
* @param[in] Offset
* @param[in] Length
* @param[in] Value to write
*
************************************************************************************/
void writeData(int offset, int length, unsigned long i32uValue)
{
int rc;
if (length != 1 && length != 2 && length != 4) {
printf("Length must be one of 1|2|4\n");
return;
}
rc = piControlWrite(offset, length, (uint8_t *) & i32uValue);
if (rc < 0) {
printf("write error \n");
} else {
printf("Write value %lx hex (=%ld dez) to offset %d.\n", i32uValue, i32uValue, offset);
}
}
static long mySubInit(subRecord *precord)
{
}
}
static long mySubInit(subRecord *precord)
{
if (mySubDebug)
printf("Record %s called mySubInit(%p)\n",
precord->name, (void*) precord);
printf("Will init piRegister ..\n");
return 0;
}
static long mySubProcess(subRecord *precord)
{
if (mySubDebug)
printf("Record %s called mySubProcess(%p)\n",
precord->name, (void*) precord);
epicsUInt32 val;
val = precord->a;
printf ("write %x\n", val);
writeData(70, 2, val);
return 0;
}
static long myAsubInit(aSubRecord *precord)
{
if (mySubDebug)
printf("Record %s called myAsubInit(%p)\n",
precord->name, (void*) precord);
return 0;
}
static long myAsubProcess(aSubRecord *precord)
{
if (mySubDebug)
printf("Record %s called myAsubProcess(%p)\n",
precord->name, (void*) precord);
return 0;
}
/* Register these symbols for use by IOC code: */
epicsExportAddress(int, mySubDebug);
epicsRegisterFunction(mySubInit);
epicsRegisterFunction(mySubProcess);
epicsRegisterFunction(myAsubInit);
epicsRegisterFunction(myAsubProcess);
Then extend the Makefile in src by:
# rather than directly into the IOC application, that
# causes problems on Windows DLL builds
IOCSwitchBoxSupport_SRCS += dbSubExample.c
IOCSwitchBoxSupport_SRCS += devIOCSwitchBoxVersion.c
IOCSwitchBoxSupport_SRCS += IOCSwitchBoxHello.c
IOCSwitchBoxSupport_SRCS += initTrace.c
This of course has to be copied into the directory (with the header file from piTest) first.
then make and restart ioc, then that's to set outputs:
Old : epics:subExample.A 4
New : epics:subExample.A 8
Noch ein bischen Datenbank und IOC
epics@RevPi12773:~/FHI/IOCSwitchBox/IOCSwitchBoxApp/Db $ ls -l
total 28
-rw-r--r-- 1 epics epics 176 Aug 27 13:05 IOCSwitchBoxVersion.db
-rw-r--r-- 1 epics epics 246 Aug 29 11:20 kunbus.db
-rw-r--r-- 1 epics epics 482 Aug 29 19:10 Makefile
drwxr-xr-x 2 epics epics 4096 Aug 29 10:05 O.Common
drwxr-xr-x 2 epics epics 4096 Aug 29 10:05 O.linux-arm
-rw-r--r-- 1 epics epics 1320 Aug 29 19:10 switch.db
-rw-r--r-- 1 epics epics 462 Aug 29 19:18 switch.substitutions
epics@RevPi12773:~/FHI/IOCSwitchBox/IOCSwitchBoxApp/Db $ more Makefile
TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS BELOW HERE
# Install databases, templates & substitutions like this
DB += IOCSwitchBoxVersion.db
DB += kunbus.db
DB += switch.db
DB += switch.substitutions
# If <anyname>.db template is not named <anyname>*.template add
# <anyname>_TEMPLATE = <templatename>
include $(TOP)/configure/RULES
#----------------------------------------
# ADD EXTRA GNUMAKE RULES BELOW HERE
epics@RevPi12773:~/FHI/IOCSwitchBox/IOCSwitchBoxApp/Db $ more kunbus.db
record(sub,"$(P):kunbusDeviceSwitchBox")
{
field(INAM,"kunbusSubInit")
field(SNAM,"kunbusSubProcess")
# Input B is Offset to Kunbus device register, can be determined with piTest -d
field(INPB,"70")
field(INPA,"0")
field(PINI,"YES")
}
epics@RevPi12773:~/FHI/IOCSwitchBox/IOCSwitchBoxApp/Db $ more switch.db
record(mbbiDirect, "FHIFEL:Degauss:SwitchBox") {
field(INP, "FHIFEL:kunbusDeviceSwitchBox.A")
}
record (calcout,"Degauss:InternalPV:$(SWNR)") {
field(INPA, "FHIFEL:Degauss:SwitchBox:SW$(SWNR).RVAL")
field(CALC, "(L&K)+(A&(~K))")
field(INPK, "$(MSK)")
field(INPL, "$(KREG) PP")
field(OOPT, "On Change")
field(OUT, "$(KREG) PP")
}
record(mbbo, "FHIFEL:Degauss:SwitchBox:SW$(SWNR)") {
field(DESC, "Controls SW$(SWNR) switch pol of $(MAGNET)")
field(NOBT,"2")
field(SHFT,"$(SHFT)")
field(OUT, "Degauss:InternalPV:$(SWNR) PP")
field(ZRVL, "0")
field(ONVL, "1")
field(TWVL, "2")
field(THVL, "3")
field(FRVL, "0")
field(FVVL, "0")
field(SXVL, "0")
field(SVVL, "0")
field(EIVL, "0")
field(NIVL, "0")
field(TEVL, "0")
field(ELVL, "0")
field(TVVL, "0")
field(TTVL, "0")
field(FTVL, "0")
field(FFVL, "0")
field(ZRST, "Off")
field(ONST, "Fwd")
field(TWST, "Rev")
field(THST, "Invalid")
field(THSV, "INVALID")
field(FRSV, "INVALID")
field(FVSV, "INVALID")
field(SXSV, "INVALID")
field(SVSV, "INVALID")
field(EISV, "INVALID")
field(NISV, "INVALID")
field(TESV, "INVALID")
field(ELSV, "INVALID")
field(TVSV, "INVALID")
field(TTSV, "INVALID")
field(FTSV, "INVALID")
field(FFSV, "INVALID")
field(IVOV, "0")
field(IVOA, "Set output to IVOV")
}
epics@RevPi12773:~/FHI/IOCSwitchBox/IOCSwitchBoxApp/Db $ more switch.substitutions
file db/switch.db {
pattern { SWNR, SHFT, MSK, KREG, MAGNET }
{ 1, 0, 0xfffffffc, "FHIFEL:kunbusDeviceSwitchBox.A", DC01CP }
{ 2, 2, 0xfffffff3, "FHIFEL:kunbusDeviceSwitchBox.A", DC02CP }
{ 3, 4, 0xffffffcf, "FHIFEL:kunbusDeviceSwitchBox.A", DC03CP }
{ 4, 6, 0xffffff3f, "FHIFEL:kunbusDeviceSwitchBox.A", DC04CP }
{ 5, 8, 0xfffffcff, "FHIFEL:kunbusDeviceSwitchBox.A", XXXXXX }
{ 6, 10, 0xfffff3ff, "FHIFEL:kunbusDeviceSwitchBox.A", XXXXXX }
}
epics@RevPi12773:~/FHI/IOCSwitchBox/iocBoot/iocIOCSwitchBox $ ls -l
total 16
-rw-r--r-- 1 epics epics 154 Aug 29 10:05 envPaths
-rw-r--r-- 1 epics epics 124 Aug 27 13:05 Makefile
-rw-r--r-- 1 epics epics 369 Aug 27 13:05 README
-rwxr--r-- 1 epics epics 661 Aug 29 19:21 st.cmd
epics@RevPi12773:~/FHI/IOCSwitchBox/iocBoot/iocIOCSwitchBox $ more st.cmd
#!../../bin/linux-arm/IOCSwitchBox
#- You may have to change IOCSwitchBox to something else
#- everywhere it appears in this file
< envPaths
cd "${TOP}"
## Register all support components
dbLoadDatabase "dbd/IOCSwitchBox.dbd"
IOCSwitchBox_registerRecordDeviceDriver pdbbase
## Load record instances
dbLoadRecords "db/IOCSwitchBoxVersion.db", "user=epics"
dbLoadRecords "db/kunbus.db", "P=FHIFEL"
dbLoadTemplate "db/switch.substitutions"
#- Set this to see messages from mySub
#var kunbusSubDebug 1
#- Run this to trace the stages of iocInit
#traceIocInit
cd "${TOP}/iocBoot/${IOC}"
iocInit
## Start any sequence programs
#seq sncExample, "user=epics"