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:

pi@RevPi127xx:~ $ adduser epics
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

# Allow client to pass locale environment variables
#AcceptEnv LANG LC_*

as user "pi"

sudo adduser epics
add epics to sudo /etc/group

remove teamviewer and update systeme

sudo apt remove teamviewer-revpi
sudo apt purge teamviewer-revpi
sudo rm sources.list.d/teamviewer-revpi.list

sudo apt update
sudo apt upgrade

login as user epics:

mkdir EPICS
cd EPICS

clone actual base:

git clone --recursive -b 7.0 https://git.launchpad.net/epics-base base-7.0.3
cd base-7.0.3
make

Add to .bashrc :

export EPICS_BASE=${HOME}/EPICS/base-7.0.3
export EPICS_HOST_ARCH=linux-arm
export PATH=${EPICS_BASE}/bin/${EPICS_HOST_ARCH}:${PATH}

example IOCSwitchBox at FHI:

mkdir FHI
cd FHI

epics@RevPi127xx:~/FHI/IOCSwitchBox $ makeBaseApp.pl -t example IOCSwitchBox
epics@RevPi127xx:~/FHI/IOCSwitchBox $ makeBaseApp.pl -i -t example IOCSwitchBox

make
epics@RevPi127xx:~/FHI/IOCSwitchBox $ ls -l
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

cd iocBoot/iocIOCSwitchBox/
chmod u+x st.cmd
epics@RevPi127xx:~/FHI/IOCSwitchBox/iocBoot/iocIOCSwitchBox $ ./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:

git clone https://github.com/RevolutionPi/piControl.git

use tools:

epics@RevPi127xx:~/REVPI/piControl $ piTest -d
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:

-w <o>,<l>,<v>: Writes <l> bytes with value <v> (as hex) to offset <o>.
length should be one of 1|2|4.
E.g.: -w 0,4,31224205:
Write value 31224205 hex (=824328709 dez) to offset 0.
epics@RevPi12773:~/REVPI/piControl $ piTest -w 70,2,43690
Write value aaaa hex (=43690 dez) to offset 70.

Disable useless services:

epics@RevPi127xx:~/REVPI/piControl $ sudo systemctl stop apache2
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 <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)
"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:

# Link locally-provided code into the support library,
# 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.

->>>> IOCSwitchBoxSupport_SRCS += piControlIf.c

then make and restart ioc, then that's to set outputs:

$ caput epics:subExample.A 8

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"
Page last modified on August 30, 2019, at 10:05 AM
Powered by PmWiki