mirror of
https://github.com/Binary-Coalescence/motorDSM.git
synced 2025-08-04 21:55:40 -05:00
Compare commits
114 Commits
Author | SHA1 | Date | |
---|---|---|---|
7e111d5931
|
|||
21a553fd3f
|
|||
cae5b2e8f8
|
|||
daf3527a1e
|
|||
39db58a2e9
|
|||
66996c3bf2
|
|||
ffab0885cb
|
|||
b6cdd85d80
|
|||
8be8f42df0
|
|||
cd37aa6d09
|
|||
d225024d69
|
|||
![]() |
3fcff74a1b | ||
760716f342 | |||
75a1ff060d | |||
4a7868285f
|
|||
c6edb953a5
|
|||
f85ae07d2b | |||
3ecb9676c0 | |||
c4d9507f84
|
|||
5e36582ecc
|
|||
d605ceceae
|
|||
bf680d0c6f
|
|||
03a93101c1 | |||
95c227a553 | |||
10028ba1c1
|
|||
ffada72c50
|
|||
72d6fb6c05
|
|||
3614a806ea
|
|||
f8f457c1c0
|
|||
b25f608e98
|
|||
![]() |
841b6f5b41 | ||
2379c90d90 | |||
cf26f426df | |||
c1025d711b | |||
8fc33fa14d
|
|||
05a223bd17
|
|||
5d706d4879
|
|||
707850e879
|
|||
8ec61fb3dc
|
|||
90b0fa8836
|
|||
40cfb47f05
|
|||
1a4794a9b2
|
|||
a3d6a24a01
|
|||
c8dbd0916d
|
|||
e9ca810318
|
|||
bf7b557dd7
|
|||
0600cba84d
|
|||
51fceaf7d7
|
|||
66ef37cb10
|
|||
200b68857d
|
|||
d0532c2552
|
|||
45c8ff064e
|
|||
4351ab56e3
|
|||
a90eea829a
|
|||
7b9f2870ca
|
|||
f73608c596
|
|||
19731d2f37
|
|||
a4012dda64
|
|||
c812afbe4e
|
|||
7551465733
|
|||
bdec17808a
|
|||
29a78e1023
|
|||
c930a77811
|
|||
df98f6667a
|
|||
37d22e58dd
|
|||
8c053dfa62
|
|||
4ab244925d
|
|||
5d343b33d1
|
|||
0d84bb4a29
|
|||
448e26ac23
|
|||
19467e5b5b
|
|||
402584345f
|
|||
c5eebd9597
|
|||
341bbb5980
|
|||
71ae063b23
|
|||
b8b090a804
|
|||
273e545759
|
|||
ba71c79a92
|
|||
996439589a
|
|||
d412000373
|
|||
9fa37e8cd0
|
|||
9a3d3d773d
|
|||
6c841c9041
|
|||
9403c24df0
|
|||
7b3675fbdf
|
|||
a1827ca152
|
|||
c2cbaf6bfd
|
|||
1b366684d0
|
|||
8101fcae72
|
|||
629c55bba4
|
|||
b616133ace
|
|||
c1ffe8b805
|
|||
c11e11659b
|
|||
b56a1f9a35
|
|||
4837e8f597
|
|||
0c32dd28eb
|
|||
0841ff3e15
|
|||
1205814767
|
|||
67eee854c0
|
|||
a4d5388531
|
|||
07f07d16ad
|
|||
a43acb8537
|
|||
d24486dfb4
|
|||
a2d7256948
|
|||
4615467616
|
|||
417802a9b4
|
|||
a92fda6560
|
|||
7d7774072c
|
|||
b03cda55ac
|
|||
eec0a1d8f0
|
|||
2df164b697
|
|||
c9db06b418
|
|||
fd6b276fc9
|
|||
4a9b6a91e0
|
1
.ci
1
.ci
Submodule .ci deleted from 5764601630
@@ -1,3 +0,0 @@
|
|||||||
BASE=3.14
|
|
||||||
|
|
||||||
include modules
|
|
@@ -1,3 +0,0 @@
|
|||||||
BASE=3.15
|
|
||||||
|
|
||||||
include modules
|
|
@@ -1,3 +0,0 @@
|
|||||||
BASE=7.0
|
|
||||||
|
|
||||||
include modules
|
|
@@ -1,70 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import re
|
|
||||||
|
|
||||||
# Setup ANSI Colors (copied from cue.py)
|
|
||||||
ANSI_RED = "\033[31;1m"
|
|
||||||
ANSI_GREEN = "\033[32;1m"
|
|
||||||
ANSI_YELLOW = "\033[33;1m"
|
|
||||||
ANSI_BLUE = "\033[34;1m"
|
|
||||||
ANSI_MAGENTA = "\033[35;1m"
|
|
||||||
ANSI_CYAN = "\033[36;1m"
|
|
||||||
ANSI_RESET = "\033[0m"
|
|
||||||
ANSI_CLEAR = "\033[0K"
|
|
||||||
|
|
||||||
def cat(filename):
|
|
||||||
'''
|
|
||||||
Print the contents of a file
|
|
||||||
'''
|
|
||||||
with open(filename, 'r') as fh:
|
|
||||||
for line in fh:
|
|
||||||
print(line.strip())
|
|
||||||
|
|
||||||
def sanity_check(filename):
|
|
||||||
'''
|
|
||||||
Include the contents of a file in the github-actions log
|
|
||||||
'''
|
|
||||||
print("{}Contents of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
|
||||||
cat(filename)
|
|
||||||
print("{}End of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
|
||||||
|
|
||||||
if 'HOME' in os.environ:
|
|
||||||
# Linux & OS X
|
|
||||||
cache_dir = os.path.join(os.environ['HOME'], ".cache")
|
|
||||||
else:
|
|
||||||
# Windows
|
|
||||||
cache_dir = os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH'], ".cache")
|
|
||||||
|
|
||||||
module_dir = os.getenv('GITHUB_WORKSPACE')
|
|
||||||
|
|
||||||
# Copy the github-actions RELEASE.local to the configure dir
|
|
||||||
filename = "configure/RELEASE.local"
|
|
||||||
shutil.copy("{}/RELEASE.local".format(cache_dir), filename)
|
|
||||||
|
|
||||||
# Get the variable from the example release file
|
|
||||||
example = "configure/EXAMPLE_RELEASE.local"
|
|
||||||
fh = open(example, "r")
|
|
||||||
lines = fh.readlines()
|
|
||||||
fh.close()
|
|
||||||
pObj = re.compile('(MOTOR_[^=]+)')
|
|
||||||
module_var = None
|
|
||||||
for line in lines:
|
|
||||||
mObj = pObj.match(line)
|
|
||||||
if mObj != None:
|
|
||||||
module_var = mObj.group()
|
|
||||||
break
|
|
||||||
|
|
||||||
# Add the path to the driver module to the RELEASE.local file, since it is needed by the example IOC
|
|
||||||
fh = open(filename, "a")
|
|
||||||
fh.write("{}={}\n".format(module_var, module_dir))
|
|
||||||
fh.close()
|
|
||||||
sanity_check(filename)
|
|
||||||
|
|
||||||
# Enable the building of example IOCs
|
|
||||||
filename = "configure/CONFIG_SITE.local"
|
|
||||||
fh = open(filename, 'w')
|
|
||||||
fh.write("BUILD_IOCS = YES")
|
|
||||||
fh.close()
|
|
||||||
sanity_check(filename)
|
|
@@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import pprint
|
|
||||||
|
|
||||||
pprint.pprint(dict(os.environ), width = 1)
|
|
||||||
|
|
||||||
#!print("{}", breakmehere)
|
|
||||||
|
|
@@ -1,9 +0,0 @@
|
|||||||
MODULES="sncseq ipac asyn autosave busy motor"
|
|
||||||
|
|
||||||
SNCSEQ=R2-2-9
|
|
||||||
IPAC=master
|
|
||||||
ASYN=R4-42
|
|
||||||
AUTOSAVE=R5-10-2
|
|
||||||
BUSY=R1-7-3
|
|
||||||
MOTOR=master
|
|
||||||
MOTOR_RECURSIVE=NO
|
|
@@ -1,43 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
# ugly hack: copy cue.py so that it can be imported
|
|
||||||
shutil.copy('.ci/cue.py', '.ci-local/travis')
|
|
||||||
from cue import *
|
|
||||||
|
|
||||||
def cat(filename):
|
|
||||||
'''
|
|
||||||
Print the contents of a file
|
|
||||||
'''
|
|
||||||
with open(filename, 'r') as fh:
|
|
||||||
for line in fh:
|
|
||||||
print(line.strip())
|
|
||||||
|
|
||||||
def sanity_check(filename):
|
|
||||||
'''
|
|
||||||
Include the contents of a file in the travis log
|
|
||||||
'''
|
|
||||||
print("{}Contents of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
|
||||||
cat(filename)
|
|
||||||
print("{}End of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
|
||||||
|
|
||||||
# Add the path to the driver module to the RELEASE.local file, since it is needed by the example IOC
|
|
||||||
update_release_local('MOTOR_ACS', os.getenv('TRAVIS_BUILD_DIR'))
|
|
||||||
|
|
||||||
# Copy the travis RELEASE.local to the configure dir
|
|
||||||
filename = "configure/RELEASE.local"
|
|
||||||
shutil.copy("{}/RELEASE.local".format(cachedir), filename)
|
|
||||||
sanity_check(filename)
|
|
||||||
|
|
||||||
# Enable the building of example IOCs
|
|
||||||
filename = "configure/CONFIG_SITE.local"
|
|
||||||
fh = open(filename, 'w')
|
|
||||||
fh.write("BUILD_IOCS = YES")
|
|
||||||
fh.close()
|
|
||||||
sanity_check(filename)
|
|
||||||
|
|
||||||
# Remove cue.py
|
|
||||||
os.remove('.ci-local/travis/cue.py')
|
|
||||||
os.remove('.ci-local/travis/cue.pyc')
|
|
211
.github/workflows/ci-scripts-build-full.yml
vendored
211
.github/workflows/ci-scripts-build-full.yml
vendored
@@ -1,211 +0,0 @@
|
|||||||
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
|
||||||
# (see: https://github.com/epics-base/ci-scripts)
|
|
||||||
|
|
||||||
# This is YAML - indentation levels are crucial
|
|
||||||
|
|
||||||
# Set the 'name:' properties to values that work for you (MYMODULE)
|
|
||||||
|
|
||||||
name: "GHA full build"
|
|
||||||
|
|
||||||
# Only run manually
|
|
||||||
on:
|
|
||||||
workflow_dispatch
|
|
||||||
|
|
||||||
env:
|
|
||||||
SETUP_PATH: .ci-local:.ci
|
|
||||||
# For the sequencer on Linux/Windows/MacOS
|
|
||||||
APT: re2c
|
|
||||||
CHOCO: re2c
|
|
||||||
BREW: re2c
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-base:
|
|
||||||
name: ${{ matrix.name }}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
# Set environment variables from matrix parameters
|
|
||||||
env:
|
|
||||||
CMP: ${{ matrix.cmp }}
|
|
||||||
BCFG: ${{ matrix.configuration }}
|
|
||||||
BASE: ${{ matrix.base }}
|
|
||||||
WINE: ${{ matrix.wine }}
|
|
||||||
RTEMS: ${{ matrix.rtems }}
|
|
||||||
RTEMS_TARGET: ${{ matrix.rtems_target }}
|
|
||||||
EXTRA: ${{ matrix.extra }}
|
|
||||||
TEST: ${{ matrix.test }}
|
|
||||||
SET: ${{ matrix.set }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# Job names also name artifacts, character limitations apply
|
|
||||||
include:
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: gcc
|
|
||||||
configuration: default
|
|
||||||
wine: "64"
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-20 gcc-9 + MinGW"
|
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: gcc
|
|
||||||
configuration: static
|
|
||||||
wine: "64"
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-20 gcc-9 + MinGW, static"
|
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: gcc
|
|
||||||
configuration: static
|
|
||||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-20 gcc-9 C++11, static"
|
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: clang
|
|
||||||
configuration: default
|
|
||||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-20 clang-10 C++11"
|
|
||||||
|
|
||||||
### fails building autosave
|
|
||||||
#!- os: ubuntu-20.04
|
|
||||||
#! cmp: gcc
|
|
||||||
#! configuration: default
|
|
||||||
#! rtems: "4.10"
|
|
||||||
#! base: "7.0"
|
|
||||||
#! set: modules
|
|
||||||
#! name: "Ub-20 gcc-9 + RT-4.10"
|
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: gcc
|
|
||||||
configuration: default
|
|
||||||
rtems: "4.9"
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-20 gcc-9 + RT-4.9"
|
|
||||||
|
|
||||||
### fails building asyn
|
|
||||||
#!- os: ubuntu-20.04
|
|
||||||
#! cmp: gcc
|
|
||||||
#! configuration: default
|
|
||||||
#! rtems: "5"
|
|
||||||
#! rtems_target: RTEMS-pc686-qemu
|
|
||||||
#! base: "7.0"
|
|
||||||
#! set: modules
|
|
||||||
#! name: "Ub-20 gcc-9 + RT-5.1 pc686"
|
|
||||||
|
|
||||||
### fails building autosave
|
|
||||||
#!- os: ubuntu-20.04
|
|
||||||
#! cmp: gcc
|
|
||||||
#! configuration: default
|
|
||||||
#! rtems: "5"
|
|
||||||
#! rtems_target: RTEMS-beatnik
|
|
||||||
#! test: NO
|
|
||||||
#! base: "7.0"
|
|
||||||
#! set: modules
|
|
||||||
#! name: "Ub-20 gcc-9 + RT-5.1 beatnik"
|
|
||||||
|
|
||||||
- os: ubuntu-18.04
|
|
||||||
cmp: gcc
|
|
||||||
configuration: default
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-18 gcc-7"
|
|
||||||
|
|
||||||
### g++-8 not found
|
|
||||||
#!- os: ubuntu-18.04
|
|
||||||
#! cmp: gcc-8
|
|
||||||
#! utoolchain: true
|
|
||||||
#! configuration: default
|
|
||||||
#! base: "7.0"
|
|
||||||
#! set: modules
|
|
||||||
#! name: "Ub-18 gcc-8"
|
|
||||||
|
|
||||||
#!- os: ubuntu-20.04
|
|
||||||
#! cmp: gcc-8
|
|
||||||
#! utoolchain: true
|
|
||||||
#! configuration: default
|
|
||||||
#! base: "7.0"
|
|
||||||
#! set: modules
|
|
||||||
#! name: "Ub-20 gcc-8"
|
|
||||||
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: clang
|
|
||||||
configuration: default
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Ub-20 clang-10"
|
|
||||||
|
|
||||||
- os: macos-latest
|
|
||||||
cmp: clang
|
|
||||||
configuration: default
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "MacOS clang-12"
|
|
||||||
|
|
||||||
- os: windows-2019
|
|
||||||
cmp: gcc
|
|
||||||
configuration: default
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Win2019 MinGW"
|
|
||||||
|
|
||||||
- os: windows-2019
|
|
||||||
cmp: gcc
|
|
||||||
configuration: static
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Win2019 MinGW, static"
|
|
||||||
|
|
||||||
- os: windows-2019
|
|
||||||
cmp: vs2019
|
|
||||||
configuration: default
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Win2019 MSC-19"
|
|
||||||
|
|
||||||
- os: windows-2019
|
|
||||||
cmp: vs2019
|
|
||||||
configuration: static
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "Win2019 MSC-19, static"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: Automatic core dumper analysis
|
|
||||||
uses: mdavidsaver/ci-core-dumper@master
|
|
||||||
- name: "apt-get install"
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
- name: "apt-get install ${{ matrix.cmp }}"
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y install software-properties-common
|
|
||||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install ${{ matrix.cmp }}
|
|
||||||
if: matrix.utoolchain
|
|
||||||
- name: Sanity Check
|
|
||||||
run: python .ci-local/github-actions/sanity-check.py
|
|
||||||
- name: Prepare and compile dependencies
|
|
||||||
run: python .ci/cue.py prepare
|
|
||||||
- name: Patch main module
|
|
||||||
run: python .ci-local/github-actions/post-prepare.py
|
|
||||||
- name: Build main module
|
|
||||||
run: python .ci/cue.py build
|
|
||||||
- name: Run main module tests
|
|
||||||
run: python .ci/cue.py test
|
|
||||||
- name: Upload tapfiles Artifact
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: tapfiles ${{ matrix.name }}
|
|
||||||
path: '**/O.*/*.tap'
|
|
||||||
- name: Collect and show test results
|
|
||||||
run: python .ci/cue.py test-results
|
|
109
.github/workflows/ci-scripts-build.yml
vendored
109
.github/workflows/ci-scripts-build.yml
vendored
@@ -1,109 +0,0 @@
|
|||||||
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
|
||||||
# (see: https://github.com/epics-base/ci-scripts)
|
|
||||||
|
|
||||||
# This is YAML - indentation levels are crucial
|
|
||||||
|
|
||||||
# Set the 'name:' properties to values that work for you (MYMODULE)
|
|
||||||
|
|
||||||
name: "GHA build"
|
|
||||||
|
|
||||||
# Trigger on pushes to the master branch and PRs
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- 'documentation/*'
|
|
||||||
- '**/*.html'
|
|
||||||
- '**/*.md'
|
|
||||||
- '.github/workflows/ci-scripts-build-full.yml'
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- 'documentation/*'
|
|
||||||
- '**/*.html'
|
|
||||||
- '**/*.md'
|
|
||||||
- '.github/workflows/ci-scripts-build-full.yml'
|
|
||||||
|
|
||||||
env:
|
|
||||||
SETUP_PATH: .ci-local:.ci
|
|
||||||
# For the sequencer on Linux/Windows/MacOS
|
|
||||||
APT: re2c
|
|
||||||
CHOCO: re2c
|
|
||||||
BREW: re2c
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-base:
|
|
||||||
name: ${{ matrix.name }}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
# Set environment variables from matrix parameters
|
|
||||||
env:
|
|
||||||
CMP: ${{ matrix.cmp }}
|
|
||||||
BCFG: ${{ matrix.configuration }}
|
|
||||||
BASE: ${{ matrix.base }}
|
|
||||||
WINE: ${{ matrix.wine }}
|
|
||||||
RTEMS: ${{ matrix.rtems }}
|
|
||||||
RTEMS_TARGET: ${{ matrix.rtems_target }}
|
|
||||||
EXTRA: ${{ matrix.extra }}
|
|
||||||
TEST: ${{ matrix.test }}
|
|
||||||
SET: ${{ matrix.set }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# Job names also name artifacts, character limitations apply
|
|
||||||
include:
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
cmp: gcc
|
|
||||||
configuration: default
|
|
||||||
base: "7.0"
|
|
||||||
set: modules
|
|
||||||
name: "7.0 Ub-20 gcc-9"
|
|
||||||
|
|
||||||
- os: macos-latest
|
|
||||||
cmp: clang
|
|
||||||
configuration: default
|
|
||||||
base: "3.15"
|
|
||||||
set: modules
|
|
||||||
name: "3.15 MacOS clang-12"
|
|
||||||
|
|
||||||
- os: windows-2019
|
|
||||||
cmp: vs2019
|
|
||||||
configuration: static
|
|
||||||
base: "3.15"
|
|
||||||
set: modules
|
|
||||||
name: "3.15 Win VS2019, static"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- name: Automatic core dumper analysis
|
|
||||||
uses: mdavidsaver/ci-core-dumper@master
|
|
||||||
- name: "apt-get install"
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
- name: "apt-get install ${{ matrix.cmp }}"
|
|
||||||
run: |
|
|
||||||
sudo apt-get -y install software-properties-common
|
|
||||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install ${{ matrix.cmp }}
|
|
||||||
if: matrix.utoolchain
|
|
||||||
- name: Sanity Check
|
|
||||||
run: python .ci-local/github-actions/sanity-check.py
|
|
||||||
- name: Prepare and compile dependencies
|
|
||||||
run: python .ci/cue.py prepare
|
|
||||||
- name: Patch main module
|
|
||||||
run: python .ci-local/github-actions/post-prepare.py
|
|
||||||
- name: Build main module
|
|
||||||
run: python .ci/cue.py build
|
|
||||||
- name: Run main module tests
|
|
||||||
run: python .ci/cue.py test
|
|
||||||
- name: Upload tapfiles Artifact
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: tapfiles ${{ matrix.name }}
|
|
||||||
path: '**/O.*/*.tap'
|
|
||||||
- name: Collect and show test results
|
|
||||||
run: python .ci/cue.py test-results
|
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
*~
|
*~
|
||||||
O.*
|
O.*
|
||||||
*.swp
|
*.swp
|
||||||
|
*.bak
|
||||||
*BAK.adl
|
*BAK.adl
|
||||||
bin/
|
bin/
|
||||||
db/
|
db/
|
||||||
@@ -16,3 +17,4 @@ auto_settings.sav*
|
|||||||
auto_positions.sav*
|
auto_positions.sav*
|
||||||
.ccfxprepdir/
|
.ccfxprepdir/
|
||||||
*.local
|
*.local
|
||||||
|
*_history
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
|||||||
[submodule ".ci"]
|
|
||||||
path = .ci
|
|
||||||
url = https://github.com/epics-base/ci-scripts
|
|
143
.travis.yml
143
.travis.yml
@@ -1,143 +0,0 @@
|
|||||||
# .travis.xml for use with EPICS Base ci-scripts
|
|
||||||
# (see: https://github.com/epics-base/ci-scripts)
|
|
||||||
|
|
||||||
language: cpp
|
|
||||||
compiler: gcc
|
|
||||||
dist: xenial
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.cache
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- SETUP_PATH=.ci-local:.ci
|
|
||||||
# for the sequencer on Windows
|
|
||||||
- CHOCO=re2c
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
# for all EPICS builds
|
|
||||||
- libreadline6-dev
|
|
||||||
- libncurses5-dev
|
|
||||||
- perl
|
|
||||||
# for clang compiler
|
|
||||||
- clang
|
|
||||||
# for mingw builds (32bit and 64bit)
|
|
||||||
- g++-mingw-w64-i686
|
|
||||||
- g++-mingw-w64-x86-64
|
|
||||||
# for RTEMS cross builds
|
|
||||||
- qemu-system-x86
|
|
||||||
homebrew:
|
|
||||||
packages:
|
|
||||||
# for the sequencer
|
|
||||||
- re2c
|
|
||||||
update: true
|
|
||||||
|
|
||||||
install:
|
|
||||||
- python .ci/cue.py prepare
|
|
||||||
# ugly hacks go here:
|
|
||||||
- python .ci-local/travis/post-prepare.py
|
|
||||||
|
|
||||||
script:
|
|
||||||
- python .ci/cue.py build
|
|
||||||
- python .ci/cue.py test
|
|
||||||
- python .ci/cue.py test-results
|
|
||||||
|
|
||||||
# If you need to do more during install and build,
|
|
||||||
# add a local directory to your module and do e.g.
|
|
||||||
# - ./.ci-local/travis/install-extras.sh
|
|
||||||
|
|
||||||
# Define build jobs
|
|
||||||
|
|
||||||
# Well-known variables to use
|
|
||||||
# SET source setup file
|
|
||||||
# EXTRA content will be added to make command line
|
|
||||||
# STATIC set to YES for static build (default: NO)
|
|
||||||
# TEST set to NO to skip running the tests (default: YES)
|
|
||||||
# VV set to make build scripts verbose (default: unset)
|
|
||||||
|
|
||||||
# Usually from setup files, but may be specified or overridden
|
|
||||||
# on a job line
|
|
||||||
# MODULES list of dependency modules
|
|
||||||
# BASE branch or release tag name of the EPICS Base to use
|
|
||||||
# <MODULE> branch or release tag for a specific module
|
|
||||||
# ... see README for setup file syntax description
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
|
|
||||||
# Older Base releases
|
|
||||||
|
|
||||||
- env: SET=base3-14
|
|
||||||
|
|
||||||
- env: SET=base3-14 BCFG=static
|
|
||||||
|
|
||||||
- env: SET=base3-15
|
|
||||||
|
|
||||||
- env: SET=base3-15 BCFG=static
|
|
||||||
|
|
||||||
# Default gcc, static build
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
|
|
||||||
- env: SET=base7-0 BCFG=static
|
|
||||||
|
|
||||||
# Default clang build
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
compiler: clang
|
|
||||||
|
|
||||||
- env: SET=base7-0 EXTRA="CMD_CXXFLAGS=-std=c++11"
|
|
||||||
compiler: clang
|
|
||||||
|
|
||||||
# Trusty: compiler versions very close to RHEL 7
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
dist: trusty
|
|
||||||
|
|
||||||
- env: SET=base7-0 BCFG=debug
|
|
||||||
dist: trusty
|
|
||||||
|
|
||||||
# Other gcc versions (added as an extra package)
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
compiler: gcc-6
|
|
||||||
addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } }
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
compiler: gcc-7
|
|
||||||
addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } }
|
|
||||||
|
|
||||||
# Cross-compilations to Windows using MinGW and WINE
|
|
||||||
|
|
||||||
- env: SET=base7-0 WINE=32 TEST=NO BCFG=static
|
|
||||||
|
|
||||||
- env: SET=base7-0 WINE=64 TEST=NO
|
|
||||||
|
|
||||||
# Windows builds
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
os: windows
|
|
||||||
compiler: vs2017
|
|
||||||
|
|
||||||
- env: SET=base7-0 BCFG=static
|
|
||||||
os: windows
|
|
||||||
compiler: vs2017
|
|
||||||
|
|
||||||
- env: SET=base7-0 BCFG=debug
|
|
||||||
os: windows
|
|
||||||
compiler: vs2017
|
|
||||||
|
|
||||||
# MacOS build
|
|
||||||
|
|
||||||
- env: SET=base7-0
|
|
||||||
os: osx
|
|
||||||
compiler: clang
|
|
||||||
|
|
||||||
# Cross-compilation to RTEMS
|
|
||||||
|
|
||||||
- env: SET=base7-0 RTEMS=4.9
|
|
||||||
|
|
||||||
- env: SET=base7-0 RTEMS=4.10
|
|
234
README.md
234
README.md
@@ -1,11 +1,231 @@
|
|||||||
# motorAcs
|
motorDSM
|
||||||
EPICS motor drivers for the following [Advanced Control Systems Corporation](http://www.acsmotion.com) controllers: MCB-4B
|
==========
|
||||||
|
|
||||||
[](https://github.com/epics-motor/motorAcs/actions/workflows/ci-scripts-build.yml)
|
EPICS motor drivers for the following [Dynamic Structures and Materials](https://www.dynamic-structures.com/) motor controllers: MD-90
|
||||||
<!--[](https://travis-ci.org/epics-motor/motorAcs)-->
|
|
||||||
|
|
||||||
motorAcs is a submodule of [motor](https://github.com/epics-modules/motor). When motorAcs is built in the ``motor/modules`` directory, no manual configuration is needed.
|
motorDSM is a submodule of [motor](https://github.com/epics-modules/motor). When motorDSM is built in the ``motor/modules`` directory, no manual configuration is needed.
|
||||||
|
|
||||||
motorAcs can also be built outside of motor by copying it's ``EXAMPLE_RELEASE.local`` file to ``RELEASE.local`` and defining the paths to ``MOTOR`` and itself.
|
motorDSM can also be built outside of motor by copying it's ``configure/EXAMPLE_RELEASE.local`` file to ``RELEASE.local`` and defining the paths to ``EPICS_BASE``, ``MOTOR``, and itself.
|
||||||
|
|
||||||
|
motorDSM contains an example IOC that is built if ``configure/CONFIG_SITE.local`` sets ``BUILD_IOCS = YES``. The example IOC can be built outside of the driver module. Copy ``iocs/dsmIOC/configure/EXAMPLE_RELEASE.local`` to ``RELEASE.local`` and uncomment and set the paths for the appropriate lines depending on whether motorDSM was built inside the motor module or independently.
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
Compiling motorDSM
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
To set up a full EPICS stack for development and testing, install and configure all of the following dependencies:
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
### epics-base
|
||||||
|
|
||||||
|
Install make, gcc, and perl packages if not already installed, then clone and build epics-base:
|
||||||
|
|
||||||
|
$ export SUPPORT=/path/to/install/directory
|
||||||
|
$ cd $SUPPORT
|
||||||
|
$ git clone git@github.com:epics-base/epics-base.git
|
||||||
|
$ cd epics-base
|
||||||
|
$ make distclean
|
||||||
|
$ make
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
### asyn
|
||||||
|
|
||||||
|
$ cd $SUPPORT
|
||||||
|
$ git clone git@github.com:epics-modules/asyn.git
|
||||||
|
|
||||||
|
You may need to install (on Arch Linux) ``rpcsvc-proto`` package to get ``rpcgen`` binary needed to make asyn.
|
||||||
|
|
||||||
|
In ``asyn/configure``, create the file ``RELEASE.local`` with contents:
|
||||||
|
SUPPORT=/path/to/install/directory
|
||||||
|
EPICS_BASE=/path/to/epics-base
|
||||||
|
|
||||||
|
In ``asyn/configure``, create ``CONFIG_SITE.local`` file with the line:
|
||||||
|
TIRPC=YES
|
||||||
|
if appropriate header files are in ``/usr/include/tirpc/rpc`` instead of ``/usr/include/rpc``.
|
||||||
|
|
||||||
|
$ cd $SUPPORT/asyn
|
||||||
|
$ make clean
|
||||||
|
$ make
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
### seq
|
||||||
|
|
||||||
|
$ cd $SUPPORT
|
||||||
|
$ git clone git@github.com:ISISComputingGroup/EPICS-seq.git seq
|
||||||
|
|
||||||
|
Install the ``re2c`` package (Arch) if needed.
|
||||||
|
|
||||||
|
Create ``seq/configure/RELEASE.local`` and set path for ``EPICS_BASE``. (Note this package seems to forget to git-ignore the .local file.)
|
||||||
|
|
||||||
|
Edit ``seq/configure/RELEASE`` to add the missing '-' before the ``include`` for ``ISIS_CONFIG`` on the next to last line. This seems to be a typo.
|
||||||
|
|
||||||
|
$ cd $SUPPORT/seq
|
||||||
|
$ make clean
|
||||||
|
$ make
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
### motor
|
||||||
|
|
||||||
|
$ cd $SUPPORT
|
||||||
|
$ git clone git@github.com:epics-modules/motor.git
|
||||||
|
|
||||||
|
Create ``motor/configure/RELEASE.local`` and set ``SUPPORT``, ``ASYN``, ``SNCSEQ``, and ``EPICS_BASE`` to the appropriate paths.
|
||||||
|
|
||||||
|
$ cd $SUPPORT/motor
|
||||||
|
$ make distclean
|
||||||
|
$ make
|
||||||
|
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
### motorDSM (this package)
|
||||||
|
|
||||||
|
$ cd $SUPPORT
|
||||||
|
$ git clone git@github.com:Binary-Coalescence/motorDSM.git
|
||||||
|
|
||||||
|
In ``motorDSM/configure``, copy ``EXAMPLE_RELEASE.local`` to ``RELEASE.local`` and set paths for ``EPICS_BASE``, ``MOTOR``, and ``MOTOR_DSM``.
|
||||||
|
|
||||||
|
In ``motorDSM/configure``, copy ``EXAMPLE_CONFIG_SITE.local`` to ``CONFIG_SITE.local`` and uncomment to set:
|
||||||
|
BUILD_IOCS = YES
|
||||||
|
|
||||||
|
In ``motorDSM/iocs/dsmIOC/configure``, copy ``EXAMPLE_RELEASE.local`` to ``RELEASE.local``. Comment out the "if built inside motor" lines, uncomment the "if built outside motor" lines, and set the path for ``MOTOR_DSM``.
|
||||||
|
|
||||||
|
$ cd $SUPPORT/motorDSM
|
||||||
|
$ make distclean
|
||||||
|
$ make
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
Configuring the IOC server
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
The directory `$SUPPORT/motorDSM/iocs/dsmIOC/iocBoot/iocDSM` contains example configurations for the IOC server that runs on the computer the motor controllers are attached to. The `st.cmd.md90` and `motor.substitutions.md90` files provide an example to configure and run one attached MD-90. The `st.cmd.md90.multi` and `motor.substitutions.md90.multi` files provide an example to configure and run eight attached MD-90s connected on ports `dev/ttyUSB0` through `/dev/ttyUSB7`. Add or remove lines from the `*.multi` files as necessary to configure a different number of attached MD-90s.
|
||||||
|
|
||||||
|
The parameters in the IOC startup scripts are detailed here, but the files should contain reasonable defaults to run as-is.
|
||||||
|
|
||||||
|
**1. Define a new serial port named "serial0" and set the location of the physical port**
|
||||||
|
|
||||||
|
`drvAsynSerialPortConfigure("[serial name]", "[device location]", 0, 0, 0)`
|
||||||
|
*e.g., `drvAsynSerialPortConfigure("serial0", "/dev/ttyUSB0", 0, 0, 0)`*
|
||||||
|
|
||||||
|
**2. Configure the port**
|
||||||
|
|
||||||
|
- Baud = 115200
|
||||||
|
- Bits = 8
|
||||||
|
- Parity = none
|
||||||
|
- Stop bits = 1
|
||||||
|
- Input end of message: "\r"
|
||||||
|
- Output end of message: "\r"
|
||||||
|
- Trace IO mask: 2
|
||||||
|
|
||||||
|
```
|
||||||
|
asynSetOption("[serial name]", 0, "baud", "115200")
|
||||||
|
asynSetOption("[serial name]", 0, "bits", "8")
|
||||||
|
asynSetOption("[serial name]", 0, "parity", "none")
|
||||||
|
asynSetOption("[serial name]", 0, "stop", "1")
|
||||||
|
asynOctetSetInputEos("[serial name]", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("[serial name]", 0, "\r")
|
||||||
|
asynSetTraceIOMask("[serial name]", 0, 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Here `[serial name]` is the name you assigned in step 1.
|
||||||
|
|
||||||
|
**3. Set initial parameters**
|
||||||
|
|
||||||
|
- Power supply enabled (`EPS` command)
|
||||||
|
- Deadband = 10 nm (`SDB 10` command)
|
||||||
|
|
||||||
|
```
|
||||||
|
asynOctetConnect("initConnection", [serial name], 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Create MD-90 Controller object**
|
||||||
|
|
||||||
|
`MD90CreateController([controller name], [serial name], 1, 100, 5000)`
|
||||||
|
|
||||||
|
Here `[controller name]` is the name of the motor to assign. Convention is to use "MD90n", starting with n=0.
|
||||||
|
|
||||||
|
**5. Intialize the IOC**
|
||||||
|
|
||||||
|
After the call to `iocInit` (still in the st.cmd.md90[.multi] file), set up some default values for EPICS process variables for each motor. The example below uses `DSM:m0`, but they should also be set for each motor configured in the IOC startup script if connecting more than one.
|
||||||
|
|
||||||
|
````
|
||||||
|
dbpf("DSM:m0.RTRY", "0") #sets retries to 0; this is automatic on the MD90
|
||||||
|
dbpf("DSM:m0.TWV", "0.1") #Tweak distance
|
||||||
|
dbpf("DSM:m0.VMAX", "1.0") #Sets max velocity to 1 mm/s
|
||||||
|
dbpf("DSM:m0.HVEL", "1.0") #Sets max velocity to 1 mm/s
|
||||||
|
````
|
||||||
|
|
||||||
|
**6. Update the substitutions file**
|
||||||
|
|
||||||
|
In the motor substitutions file (motor.substitutions.md90[.multi]), ensure the values in the `pattern` block's `PORT` field match the names used in the `std.cmd.md90[.multi]` file. Note that, despite this field being called "Port", it usese the names of the MD90 Controller object defined above (by default, MD900, MD901, etc). Do __not__ use the direct serial port names (by default, serial0, serial1, etc.).
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
Running the example IOC
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
To run the example IOC configured above:
|
||||||
|
|
||||||
|
1. Follow the steps in "Configuring the system for attached controllers" below.
|
||||||
|
|
||||||
|
3. In the ``iocs/dsmIOC/iocBoot/iocDsm`` directory, run
|
||||||
|
`$ ../../bin/linux-x86_64/dsm st.cmd.md90`
|
||||||
|
for one attached MD-90 controller, or
|
||||||
|
`$ ../../bin/linux-x86_64/dsm st.cmd.md90.multi`
|
||||||
|
for multiple attached MD-90 controllers. This is set up for eight controllers, so add or remove lines as appropriate if using a different number.
|
||||||
|
|
||||||
|
4. Test using the `caget` and `caput` programs from the `epics-base` package as described in the "Example usage" section below.
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
Example usage
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
1. After building, run the example IOC described above in one terminal window.
|
||||||
|
|
||||||
|
2. Open another terminal window on either the same computer as the IOC or another computer on the LAN and navigate to `[EPICS install directory]/epics-base/bin/linux-x86_64/` (or wherever you built EPICS base). You could alternatively add this directory to your PATH.
|
||||||
|
|
||||||
|
3. Set the "EPICS_CA_ADDR_LIST" environment variable to include the IP address of the server. If it's running on the same computer, you can use the loopback IP address:
|
||||||
|
`$ export EPICS_CA_ADDR_LIST='127.0.0.1'`
|
||||||
|
|
||||||
|
4. Use the `caget` and `caput` programs to read and set process variables, respectively.
|
||||||
|
|
||||||
|
For example, to get the current position (in encoder counts of 10 nm), use:
|
||||||
|
`$ ./caget DSM:m0.REP`
|
||||||
|
This reads the REP variable, which is the "Raw Encoder Position". Additionally, change `m0` to `m1`, `m2`, etc. to read the values from other motors when running more than one.
|
||||||
|
|
||||||
|
Homing the motor (must be done before you can issue position commands):
|
||||||
|
`$ ./caput DSM:m0.HOMF 1`
|
||||||
|
This starts the homing sequence in the forward direction. Alternatively, for homing starting in the reverse direction:
|
||||||
|
`$ ./caput DSM:m0.HOMR 1`
|
||||||
|
|
||||||
|
Moving to a position target:
|
||||||
|
`$ ./caput DSM:m0.VAL 2.345`
|
||||||
|
This moves the motor to 2.345 mm.
|
||||||
|
|
||||||
|
Setting a velocity target:
|
||||||
|
`$ ./caput DSM:m0.VELO 0.5`
|
||||||
|
This sets the velocity target to 0.5 mm/s. (Note that velocity targets are approximate only. They adjust the step rate of the motor and are not guaranteed to be exact.)
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
A note about velocity targets
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
The I-20 motor driven by the MD-90 is a closed loop "step and repeat" motor that takes full steps towards its position target until it is close, then will perform linear extensions to close the loop on the target position. This is handled internally on the MD-90, not by EPICS.
|
||||||
|
|
||||||
|
The velocity target parameter sets the step frequency at which the motor operates on its way to the target position. The speed is not closed loop, and will depend on external loads, environmental conditions, etc. A speed target of 1 mm/s will generate a roughly 1 mm/s motion, but it is not guaranteed.
|
||||||
|
|
||||||
|
Additionally, due to the way EPICS operates, setting `VELO` will not immediately send a command to the MD-90. Instead, EPICS remembers the last value you set, and will set this new velocity target when it sends the next move command. **However, the motor must not be in servo mode to accept a new velocity target.**
|
||||||
|
|
||||||
|
The motor enters servo mode when you send a new position target, and stays in servo mode until you issue a Stop command (by setting the `DSM:m0.STOP` parameter to 1).
|
||||||
|
|
||||||
|
If you do not disable servo prior to issuing a Move command at the new velocity, then `VELO` will become out of sync with the actual motor velocity, and EPICS will return error 3 "Cannot execute while moving" in its console each time you issue a Move command. This is because each Move command internally sends a "Set step frequency" command, which will error if you do not Stop the motor first. Reading the VELO parameter at this point will return the wrong value--it returns the value you requested, not the actual speed setting on the motor. To fix this, you must Stop the motor, then send a new Move command.
|
||||||
|
|
||||||
motorAcs contains an example IOC that is built if ``CONFIG_SITE.local`` sets ``BUILD_IOCS = YES``. The example IOC can be built outside of driver module.
|
|
||||||
|
@@ -1,336 +0,0 @@
|
|||||||
/*
|
|
||||||
FILENAME... MCB4BDriver.cpp
|
|
||||||
USAGE... Motor driver support for the ACS MCB-4B controller.
|
|
||||||
|
|
||||||
Mark Rivers
|
|
||||||
March 1, 2012
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <iocsh.h>
|
|
||||||
#include <epicsThread.h>
|
|
||||||
|
|
||||||
#include <asynOctetSyncIO.h>
|
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
#include "MCB4BDriver.h"
|
|
||||||
|
|
||||||
#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5)
|
|
||||||
|
|
||||||
/** Creates a new MCB4BController object.
|
|
||||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
|
||||||
* \param[in] MCB4BPortName The name of the drvAsynSerialPort that was created previously to connect to the MCB4B controller
|
|
||||||
* \param[in] numAxes The number of axes that this controller supports
|
|
||||||
* \param[in] movingPollPeriod The time between polls when any axis is moving
|
|
||||||
* \param[in] idlePollPeriod The time between polls when no axis is moving
|
|
||||||
*/
|
|
||||||
MCB4BController::MCB4BController(const char *portName, const char *MCB4BPortName, int numAxes,
|
|
||||||
double movingPollPeriod, double idlePollPeriod)
|
|
||||||
: asynMotorController(portName, numAxes, NUM_MCB4B_PARAMS,
|
|
||||||
0, // No additional interfaces beyond those in base class
|
|
||||||
0, // No additional callback interfaces beyond those in base class
|
|
||||||
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
|
||||||
1, // autoconnect
|
|
||||||
0, 0) // Default priority and stack size
|
|
||||||
{
|
|
||||||
int axis;
|
|
||||||
asynStatus status;
|
|
||||||
MCB4BAxis *pAxis;
|
|
||||||
static const char *functionName = "MCB4BController::MCB4BController";
|
|
||||||
|
|
||||||
/* Connect to MCB4B controller */
|
|
||||||
status = pasynOctetSyncIO->connect(MCB4BPortName, 0, &pasynUserController_, NULL);
|
|
||||||
if (status) {
|
|
||||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
|
||||||
"%s: cannot connect to MCB-4B controller\n",
|
|
||||||
functionName);
|
|
||||||
}
|
|
||||||
for (axis=0; axis<numAxes; axis++) {
|
|
||||||
pAxis = new MCB4BAxis(this, axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
startPoller(movingPollPeriod, idlePollPeriod, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new MCB4BController object.
|
|
||||||
* Configuration command, called directly or from iocsh
|
|
||||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
|
||||||
* \param[in] MCB4BPortName The name of the drvAsynIPPPort that was created previously to connect to the MCB4B controller
|
|
||||||
* \param[in] numAxes The number of axes that this controller supports
|
|
||||||
* \param[in] movingPollPeriod The time in ms between polls when any axis is moving
|
|
||||||
* \param[in] idlePollPeriod The time in ms between polls when no axis is moving
|
|
||||||
*/
|
|
||||||
extern "C" int MCB4BCreateController(const char *portName, const char *MCB4BPortName, int numAxes,
|
|
||||||
int movingPollPeriod, int idlePollPeriod)
|
|
||||||
{
|
|
||||||
MCB4BController *pMCB4BController
|
|
||||||
= new MCB4BController(portName, MCB4BPortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.);
|
|
||||||
pMCB4BController = NULL;
|
|
||||||
return(asynSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reports on status of the driver
|
|
||||||
* \param[in] fp The file pointer on which report information will be written
|
|
||||||
* \param[in] level The level of report detail desired
|
|
||||||
*
|
|
||||||
* If details > 0 then information is printed about each axis.
|
|
||||||
* After printing controller-specific information it calls asynMotorController::report()
|
|
||||||
*/
|
|
||||||
void MCB4BController::report(FILE *fp, int level)
|
|
||||||
{
|
|
||||||
fprintf(fp, "MCB-4B motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n",
|
|
||||||
this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_);
|
|
||||||
|
|
||||||
// Call the base class method
|
|
||||||
asynMotorController::report(fp, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a pointer to an MCB4BAxis object.
|
|
||||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
|
||||||
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
|
||||||
MCB4BAxis* MCB4BController::getAxis(asynUser *pasynUser)
|
|
||||||
{
|
|
||||||
return static_cast<MCB4BAxis*>(asynMotorController::getAxis(pasynUser));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a pointer to an MCB4BAxis object.
|
|
||||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
|
||||||
* \param[in] axisNo Axis index number. */
|
|
||||||
MCB4BAxis* MCB4BController::getAxis(int axisNo)
|
|
||||||
{
|
|
||||||
return static_cast<MCB4BAxis*>(asynMotorController::getAxis(axisNo));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// These are the MCB4BAxis methods
|
|
||||||
|
|
||||||
/** Creates a new MCB4BAxis object.
|
|
||||||
* \param[in] pC Pointer to the MCB4BController to which this axis belongs.
|
|
||||||
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
|
||||||
*
|
|
||||||
* Initializes register numbers, etc.
|
|
||||||
*/
|
|
||||||
MCB4BAxis::MCB4BAxis(MCB4BController *pC, int axisNo)
|
|
||||||
: asynMotorAxis(pC, axisNo),
|
|
||||||
pC_(pC)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reports on status of the axis
|
|
||||||
* \param[in] fp The file pointer on which report information will be written
|
|
||||||
* \param[in] level The level of report detail desired
|
|
||||||
*
|
|
||||||
* After printing device-specific information calls asynMotorAxis::report()
|
|
||||||
*/
|
|
||||||
void MCB4BAxis::report(FILE *fp, int level)
|
|
||||||
{
|
|
||||||
if (level > 0) {
|
|
||||||
fprintf(fp, " axis %d\n",
|
|
||||||
axisNo_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the base class method
|
|
||||||
asynMotorAxis::report(fp, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::sendAccelAndVelocity(double acceleration, double velocity)
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
int ival;
|
|
||||||
// static const char *functionName = "MCB4B::sendAccelAndVelocity";
|
|
||||||
|
|
||||||
// Send the velocity
|
|
||||||
ival = NINT(fabs(115200./velocity));
|
|
||||||
if (ival < 2) ival=2;
|
|
||||||
if (ival > 255) ival = 255;
|
|
||||||
sprintf(pC_->outString_, "#%02dV=%d", axisNo_, ival);
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
|
|
||||||
// Send the acceleration
|
|
||||||
// acceleration is in steps/sec/sec
|
|
||||||
// MCB is programmed with Ramp Index (R) where:
|
|
||||||
// dval (steps/sec/sec) = 720,000/(256-R) */
|
|
||||||
// or R=256-(720,000/dval) */
|
|
||||||
ival = NINT(256-(720000./acceleration));
|
|
||||||
if (ival < 1) ival=1;
|
|
||||||
if (ival > 255) ival=255;
|
|
||||||
sprintf(pC_->outString_, "#%02dR=%d", axisNo_, ival);
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
// static const char *functionName = "MCB4BAxis::move";
|
|
||||||
|
|
||||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
|
||||||
|
|
||||||
if (relative) {
|
|
||||||
sprintf(pC_->outString_, "#%02dI%+d", axisNo_, NINT(position));
|
|
||||||
} else {
|
|
||||||
sprintf(pC_->outString_, "#%02dG%+d", axisNo_, NINT(position));
|
|
||||||
}
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
// static const char *functionName = "MCB4BAxis::home";
|
|
||||||
|
|
||||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
|
||||||
|
|
||||||
if (forwards) {
|
|
||||||
sprintf(pC_->outString_, "#%02dH+", axisNo_);
|
|
||||||
} else {
|
|
||||||
sprintf(pC_->outString_, "#%02dH-", axisNo_);
|
|
||||||
}
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
static const char *functionName = "MCB4BAxis::moveVelocity";
|
|
||||||
|
|
||||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
|
||||||
"%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
|
||||||
functionName, minVelocity, maxVelocity, acceleration);
|
|
||||||
|
|
||||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
|
||||||
|
|
||||||
/* MCB-4B does not have jog command. Move 1 million steps */
|
|
||||||
if (maxVelocity > 0.) {
|
|
||||||
/* This is a positive move in MCB4B coordinates */
|
|
||||||
sprintf(pC_->outString_, "#%02dI+1000000", axisNo_);
|
|
||||||
} else {
|
|
||||||
/* This is a negative move in MCB4B coordinates */
|
|
||||||
sprintf(pC_->outString_, "#%02dI-1000000", axisNo_);
|
|
||||||
}
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::stop(double acceleration )
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
//static const char *functionName = "MCB4BAxis::stop";
|
|
||||||
|
|
||||||
sprintf(pC_->outString_, "#%02dQ", axisNo_);
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::setPosition(double position)
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
//static const char *functionName = "MCB4BAxis::setPosition";
|
|
||||||
|
|
||||||
sprintf(pC_->outString_, "#%02dP=%+d", axisNo_, NINT(position));
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
asynStatus MCB4BAxis::setClosedLoop(bool closedLoop)
|
|
||||||
{
|
|
||||||
asynStatus status;
|
|
||||||
//static const char *functionName = "MCB4BAxis::setClosedLoop";
|
|
||||||
|
|
||||||
sprintf(pC_->outString_, "#%02dW=%d", axisNo_, closedLoop ? 1:0);
|
|
||||||
status = pC_->writeReadController();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Polls the axis.
|
|
||||||
* This function reads the motor position, the limit status, the home status, the moving status,
|
|
||||||
* and the drive power-on status.
|
|
||||||
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
|
||||||
* and then calls callParamCallbacks() at the end.
|
|
||||||
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */
|
|
||||||
asynStatus MCB4BAxis::poll(bool *moving)
|
|
||||||
{
|
|
||||||
int done;
|
|
||||||
int driveOn;
|
|
||||||
int limit;
|
|
||||||
double position;
|
|
||||||
asynStatus comStatus;
|
|
||||||
|
|
||||||
// Read the current motor position
|
|
||||||
sprintf(pC_->outString_, "#%02dP", axisNo_);
|
|
||||||
comStatus = pC_->writeReadController();
|
|
||||||
if (comStatus) goto skip;
|
|
||||||
// The response string is of the form "#01P=+1000"
|
|
||||||
position = atof(&pC_->inString_[5]);
|
|
||||||
setDoubleParam(pC_->motorPosition_, position);
|
|
||||||
|
|
||||||
// Read the moving status of this motor
|
|
||||||
sprintf(pC_->outString_, "#%02dX", axisNo_);
|
|
||||||
comStatus = pC_->writeReadController();
|
|
||||||
if (comStatus) goto skip;
|
|
||||||
// The response string is of the form "#01X=1"
|
|
||||||
done = (pC_->inString_[5] == '0') ? 1:0;
|
|
||||||
setIntegerParam(pC_->motorStatusDone_, done);
|
|
||||||
*moving = done ? false:true;
|
|
||||||
|
|
||||||
// Read the limit status
|
|
||||||
sprintf(pC_->outString_, "#%02dE", axisNo_);
|
|
||||||
comStatus = pC_->writeReadController();
|
|
||||||
if (comStatus) goto skip;
|
|
||||||
// The response string is of the form "#01E=1"
|
|
||||||
limit = (pC_->inString_[5] == '1') ? 1:0;
|
|
||||||
setIntegerParam(pC_->motorStatusHighLimit_, limit);
|
|
||||||
limit = (pC_->inString_[6] == '1') ? 1:0;
|
|
||||||
setIntegerParam(pC_->motorStatusLowLimit_, limit);
|
|
||||||
limit = (pC_->inString_[7] == '1') ? 1:0;
|
|
||||||
setIntegerParam(pC_->motorStatusAtHome_, limit);
|
|
||||||
|
|
||||||
// Read the drive power on status
|
|
||||||
sprintf(pC_->outString_, "#%02dW", axisNo_);
|
|
||||||
comStatus = pC_->writeReadController();
|
|
||||||
if (comStatus) goto skip;
|
|
||||||
driveOn = (pC_->inString_[5] == '1') ? 1:0;
|
|
||||||
setIntegerParam(pC_->motorStatusPowerOn_, driveOn);
|
|
||||||
setIntegerParam(pC_->motorStatusProblem_, 0);
|
|
||||||
|
|
||||||
skip:
|
|
||||||
setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
|
|
||||||
callParamCallbacks();
|
|
||||||
return comStatus ? asynError : asynSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Code for iocsh registration */
|
|
||||||
static const iocshArg MCB4BCreateControllerArg0 = {"Port name", iocshArgString};
|
|
||||||
static const iocshArg MCB4BCreateControllerArg1 = {"MCB-4B port name", iocshArgString};
|
|
||||||
static const iocshArg MCB4BCreateControllerArg2 = {"Number of axes", iocshArgInt};
|
|
||||||
static const iocshArg MCB4BCreateControllerArg3 = {"Moving poll period (ms)", iocshArgInt};
|
|
||||||
static const iocshArg MCB4BCreateControllerArg4 = {"Idle poll period (ms)", iocshArgInt};
|
|
||||||
static const iocshArg * const MCB4BCreateControllerArgs[] = {&MCB4BCreateControllerArg0,
|
|
||||||
&MCB4BCreateControllerArg1,
|
|
||||||
&MCB4BCreateControllerArg2,
|
|
||||||
&MCB4BCreateControllerArg3,
|
|
||||||
&MCB4BCreateControllerArg4};
|
|
||||||
static const iocshFuncDef MCB4BCreateControllerDef = {"MCB4BCreateController", 5, MCB4BCreateControllerArgs};
|
|
||||||
static void MCB4BCreateContollerCallFunc(const iocshArgBuf *args)
|
|
||||||
{
|
|
||||||
MCB4BCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MCB4BRegister(void)
|
|
||||||
{
|
|
||||||
iocshRegister(&MCB4BCreateControllerDef, MCB4BCreateContollerCallFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
epicsExportRegistrar(MCB4BRegister);
|
|
||||||
}
|
|
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
FILENAME... MCB4BDriver.h
|
|
||||||
USAGE... Motor driver support for the ACS MCB-4B controller.
|
|
||||||
|
|
||||||
Mark Rivers
|
|
||||||
March 1, 2012
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "asynMotorController.h"
|
|
||||||
#include "asynMotorAxis.h"
|
|
||||||
|
|
||||||
#define MAX_MCB4B_AXES 4
|
|
||||||
|
|
||||||
// No controller-specific parameters yet
|
|
||||||
#define NUM_MCB4B_PARAMS 0
|
|
||||||
|
|
||||||
class epicsShareClass MCB4BAxis : public asynMotorAxis
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/* These are the methods we override from the base class */
|
|
||||||
MCB4BAxis(class MCB4BController *pC, int axis);
|
|
||||||
void report(FILE *fp, int level);
|
|
||||||
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
|
||||||
asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration);
|
|
||||||
asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards);
|
|
||||||
asynStatus stop(double acceleration);
|
|
||||||
asynStatus poll(bool *moving);
|
|
||||||
asynStatus setPosition(double position);
|
|
||||||
asynStatus setClosedLoop(bool closedLoop);
|
|
||||||
|
|
||||||
private:
|
|
||||||
MCB4BController *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
|
||||||
* Abbreviated because it is used very frequently */
|
|
||||||
asynStatus sendAccelAndVelocity(double accel, double velocity);
|
|
||||||
|
|
||||||
friend class MCB4BController;
|
|
||||||
};
|
|
||||||
|
|
||||||
class epicsShareClass MCB4BController : public asynMotorController {
|
|
||||||
public:
|
|
||||||
MCB4BController(const char *portName, const char *MCB4BPortName, int numAxes, double movingPollPeriod, double idlePollPeriod);
|
|
||||||
|
|
||||||
void report(FILE *fp, int level);
|
|
||||||
MCB4BAxis* getAxis(asynUser *pasynUser);
|
|
||||||
MCB4BAxis* getAxis(int axisNo);
|
|
||||||
|
|
||||||
friend class MCB4BAxis;
|
|
||||||
};
|
|
@@ -1,11 +0,0 @@
|
|||||||
# Advanced Control Systems driver support.
|
|
||||||
|
|
||||||
# Model 1 (non-asyn) driver
|
|
||||||
device(motor,VME_IO,devMCB4B,"ACS MCB-4B")
|
|
||||||
driver(drvMCB4B)
|
|
||||||
registrar(AcsRegister)
|
|
||||||
|
|
||||||
# Model 3 driver
|
|
||||||
registrar(MCB4BRegister)
|
|
||||||
|
|
||||||
|
|
@@ -1,4 +1,5 @@
|
|||||||
|
EPICS_BASE=
|
||||||
MOTOR=
|
MOTOR=
|
||||||
-include $(MOTOR)/modules/RELEASE.$(EPICS_HOST_ARCH).local
|
-include $(MOTOR)/modules/RELEASE.$(EPICS_HOST_ARCH).local
|
||||||
# path to motorAcs is needed to build the IOC inside motorAcs, but outside motor
|
# path to motorDsm is needed to build the IOC inside motorDsm, but outside motor
|
||||||
MOTOR_ACS=
|
MOTOR_DSM=
|
||||||
|
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
# Use motor/module's generated release file when buidling inside motor
|
# Use motor/module's generated release file when buidling inside motor
|
||||||
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
||||||
# Use motorAcs's RELEASE.local when building outside motor
|
# Use motorDsm's RELEASE.local when building outside motor
|
||||||
-include $(TOP)/configure/RELEASE.local
|
-include $(TOP)/configure/RELEASE.local
|
||||||
|
|
||||||
|
@@ -1,3 +1,22 @@
|
|||||||
|
# motorDSM Releases
|
||||||
|
|
||||||
|
## __v0.9.0-alpha__
|
||||||
|
|
||||||
|
### Changes since motorAcs R1-1-1
|
||||||
|
|
||||||
|
#### New features
|
||||||
|
* Global rename Acs -> DSM and MCB-4B -> MD-90
|
||||||
|
* Updated motor controller and axis methods to work with the DSM MD-90 controller
|
||||||
|
* Updated example IOC startup scripts for the MD-90
|
||||||
|
|
||||||
|
#### Modifications to existing features
|
||||||
|
* Removed Acs controller interface
|
||||||
|
|
||||||
|
#### Bug fixes
|
||||||
|
* None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# motorAcs Releases
|
# motorAcs Releases
|
||||||
|
|
||||||
## __R1-1-1 (2023-04-11)__
|
## __R1-1-1 (2023-04-11)__
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# ### ACS_MCB4B.iocsh ###
|
# ### DSM_MD90.iocsh ###
|
||||||
|
|
||||||
#- ###################################################
|
#- ###################################################
|
||||||
#- PORT - Serial port for communications
|
#- PORT - Serial port for communications
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
#- Default: 100
|
#- Default: 100
|
||||||
#- ###################################################
|
#- ###################################################
|
||||||
|
|
||||||
# ACS MCB-4B serial connection settings
|
# DSM MD-90 serial connection settings
|
||||||
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none")
|
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=115200, BITS=8, STOP=1, PARITY=none")
|
||||||
asynOctetSetInputEos( "$(PORT)", -1, "\r")
|
asynOctetSetInputEos( "$(PORT)", -1, "\r")
|
||||||
asynOctetSetOutputEos("$(PORT)", -1, "\r")
|
asynOctetSetOutputEos("$(PORT)", -1, "\r")
|
||||||
|
|
||||||
MCB4BCreateController("$(INSTANCE)", "$(PORT)", $(NUM_AXES=1), $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=100)))
|
MD90CreateController("$(INSTANCE)", "$(PORT)", $(NUM_AXES=1), $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=1000)))
|
@@ -1,6 +1,6 @@
|
|||||||
TOP = ../..
|
TOP = ../..
|
||||||
include $(TOP)/configure/CONFIG
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
IOCSH += ACS_MCB4B.iocsh
|
IOCSH += DSM_MD90.iocsh
|
||||||
|
|
||||||
include $(TOP)/configure/RULES
|
include $(TOP)/configure/RULES
|
537
dsmApp/src/MD90Driver.cpp
Normal file
537
dsmApp/src/MD90Driver.cpp
Normal file
@@ -0,0 +1,537 @@
|
|||||||
|
/*
|
||||||
|
FILENAME... MD90Driver.cpp
|
||||||
|
USAGE... Motor driver support for the DSM MD-90 controller.
|
||||||
|
|
||||||
|
Mark Rivers
|
||||||
|
March 1, 2012
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <iocsh.h>
|
||||||
|
#include <epicsThread.h>
|
||||||
|
|
||||||
|
#include <asynOctetSyncIO.h>
|
||||||
|
|
||||||
|
#include <epicsExport.h>
|
||||||
|
#include "MD90Driver.h"
|
||||||
|
|
||||||
|
#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5)
|
||||||
|
|
||||||
|
/** Creates a new MD90Controller object.
|
||||||
|
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||||
|
* \param[in] MD90PortName The name of the drvAsynSerialPort that was created previously to connect to the MD90 controller
|
||||||
|
* \param[in] numAxes The number of axes that this controller supports
|
||||||
|
* \param[in] movingPollPeriod The time between polls when any axis is moving
|
||||||
|
* \param[in] idlePollPeriod The time between polls when no axis is moving
|
||||||
|
*/
|
||||||
|
MD90Controller::MD90Controller(const char *portName, const char *MD90PortName, int numAxes,
|
||||||
|
double movingPollPeriod, double idlePollPeriod)
|
||||||
|
: asynMotorController(portName, numAxes, NUM_MD90_PARAMS,
|
||||||
|
0, // No additional interfaces beyond those in base class
|
||||||
|
0, // No additional callback interfaces beyond those in base class
|
||||||
|
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
||||||
|
1, // autoconnect
|
||||||
|
0, 0) // Default priority and stack size
|
||||||
|
{
|
||||||
|
int axis;
|
||||||
|
asynStatus status;
|
||||||
|
MD90Axis *pAxis;
|
||||||
|
static const char *functionName = "MD90Controller::MD90Controller";
|
||||||
|
|
||||||
|
/* Connect to MD90 controller */
|
||||||
|
status = pasynOctetSyncIO->connect(MD90PortName, 0, &pasynUserController_, NULL);
|
||||||
|
if (status) {
|
||||||
|
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||||
|
"%s: cannot connect to MD-90 controller\n",
|
||||||
|
functionName);
|
||||||
|
}
|
||||||
|
for (axis=0; axis<numAxes; axis++) {
|
||||||
|
pAxis = new MD90Axis(this, axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
startPoller(movingPollPeriod, idlePollPeriod, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Creates a new MD90Controller object.
|
||||||
|
* Configuration command, called directly or from iocsh
|
||||||
|
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||||
|
* \param[in] MD90PortName The name of the drvAsynIPPPort that was created previously to connect to the MD90 controller
|
||||||
|
* \param[in] numAxes The number of axes that this controller supports
|
||||||
|
* \param[in] movingPollPeriod The time in ms between polls when any axis is moving
|
||||||
|
* \param[in] idlePollPeriod The time in ms between polls when no axis is moving
|
||||||
|
*/
|
||||||
|
extern "C" int MD90CreateController(const char *portName, const char *MD90PortName, int numAxes,
|
||||||
|
int movingPollPeriod, int idlePollPeriod)
|
||||||
|
{
|
||||||
|
MD90Controller *pMD90Controller
|
||||||
|
= new MD90Controller(portName, MD90PortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.);
|
||||||
|
pMD90Controller = NULL;
|
||||||
|
return(asynSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Reports on status of the driver
|
||||||
|
* \param[in] fp The file pointer on which report information will be written
|
||||||
|
* \param[in] level The level of report detail desired
|
||||||
|
*
|
||||||
|
* If details > 0 then information is printed about each axis.
|
||||||
|
* After printing controller-specific information it calls asynMotorController::report()
|
||||||
|
*/
|
||||||
|
void MD90Controller::report(FILE *fp, int level)
|
||||||
|
{
|
||||||
|
fprintf(fp, "MD-90 motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n",
|
||||||
|
this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_);
|
||||||
|
|
||||||
|
// Call the base class method
|
||||||
|
asynMotorController::report(fp, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a pointer to an MD90Axis object.
|
||||||
|
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||||
|
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
||||||
|
MD90Axis* MD90Controller::getAxis(asynUser *pasynUser)
|
||||||
|
{
|
||||||
|
return static_cast<MD90Axis*>(asynMotorController::getAxis(pasynUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a pointer to an MD90Axis object.
|
||||||
|
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||||
|
* \param[in] axisNo Axis index number. */
|
||||||
|
MD90Axis* MD90Controller::getAxis(int axisNo)
|
||||||
|
{
|
||||||
|
return static_cast<MD90Axis*>(asynMotorController::getAxis(axisNo));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// These are the MD90Axis methods
|
||||||
|
|
||||||
|
/** Creates a new MD90Axis object.
|
||||||
|
* \param[in] pC Pointer to the MD90Controller to which this axis belongs.
|
||||||
|
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
||||||
|
*
|
||||||
|
* Initializes register numbers, etc.
|
||||||
|
*/
|
||||||
|
MD90Axis::MD90Axis(MD90Controller *pC, int axisNo)
|
||||||
|
: asynMotorAxis(pC, axisNo),
|
||||||
|
pC_(pC)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Reports on status of the axis
|
||||||
|
* \param[in] fp The file pointer on which report information will be written
|
||||||
|
* \param[in] level The level of report detail desired
|
||||||
|
*
|
||||||
|
* After printing device-specific information calls asynMotorAxis::report()
|
||||||
|
*/
|
||||||
|
void MD90Axis::report(FILE *fp, int level)
|
||||||
|
{
|
||||||
|
if (level > 0) {
|
||||||
|
fprintf(fp, " axis %d\n",
|
||||||
|
axisNo_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the base class method
|
||||||
|
asynMotorAxis::report(fp, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Print out message if the motor controller returns a non-zero error code
|
||||||
|
* \param[in] functionName The function originating the call
|
||||||
|
* \param[in] reply Reply message returned from motor controller
|
||||||
|
*/
|
||||||
|
asynStatus MD90Axis::parseReply(const char *functionName, const char *reply)
|
||||||
|
{
|
||||||
|
int replyStatus;
|
||||||
|
char replyString[256];
|
||||||
|
int replyValue;
|
||||||
|
asynStatus comStatus;
|
||||||
|
|
||||||
|
comStatus = asynSuccess;
|
||||||
|
|
||||||
|
if (reply[0] == '\0') {
|
||||||
|
comStatus = asynError;
|
||||||
|
replyStatus = -1;
|
||||||
|
} else if ( strcmp(reply, "Unrecognized command.") == 0 ) {
|
||||||
|
replyStatus = 6;
|
||||||
|
} else {
|
||||||
|
sscanf(reply, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyStatus != 0) {
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR,
|
||||||
|
"%s: %s\n",
|
||||||
|
functionName, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return comStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Acceleration currently unsupported with MD-90 controller
|
||||||
|
* \param[in] acceleration The accelerations to ramp up to max velocity
|
||||||
|
* \param[in] velocity Motor velocity in steps / sec
|
||||||
|
*/
|
||||||
|
asynStatus MD90Axis::sendAccelAndVelocity(double acceleration, double velocity)
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
int freq;
|
||||||
|
static const char *functionName = "MD90::sendAccelAndVelocity";
|
||||||
|
|
||||||
|
// Send the velocity
|
||||||
|
// Velocity provided in steps/sec
|
||||||
|
// Our unit step size of the encoder is 10 nm, but the motor moves in steps approx. 10 micrometers.
|
||||||
|
// Motor controller accepts step frequency in Hz.
|
||||||
|
freq = NINT(fabs(velocity / COUNTS_PER_STEP));
|
||||||
|
sprintf(pC_->outString_, "SSF %d", freq);
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
asynStatus MD90Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::move";
|
||||||
|
|
||||||
|
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||||
|
|
||||||
|
// Position specified in encoder steps (10 nm), but motor move commands are in nanometers
|
||||||
|
position = position * 10;
|
||||||
|
if (relative) {
|
||||||
|
sprintf(pC_->outString_, "CRM %d", NINT(position));
|
||||||
|
} else {
|
||||||
|
sprintf(pC_->outString_, "CLM %d", NINT(position));
|
||||||
|
}
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynStatus MD90Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
||||||
|
{
|
||||||
|
int sleepTime;
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::home";
|
||||||
|
|
||||||
|
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||||
|
|
||||||
|
// The MD-90 will start the home routine in the direction of the last move
|
||||||
|
// Here we first make a small move to set the desired direction before homing
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
sprintf(pC_->outString_, "SNS %d", SMALL_NSTEPS);
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
}
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forwards) {
|
||||||
|
sprintf(pC_->outString_, "ESF");
|
||||||
|
} else {
|
||||||
|
sprintf(pC_->outString_, "ESB");
|
||||||
|
}
|
||||||
|
if (!status) {
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
}
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
// Wait for the move to complete, then home
|
||||||
|
sleepTime = SLEEP_MARGIN * SMALL_NSTEPS * COUNTS_PER_STEP / maxVelocity;
|
||||||
|
if (sleepTime < HOME_SLEEP_MIN) {
|
||||||
|
sleepTime = HOME_SLEEP_MIN;
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(sleepTime));
|
||||||
|
|
||||||
|
sprintf(pC_->outString_, "HOM");
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
}
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynStatus MD90Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::moveVelocity";
|
||||||
|
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||||
|
"%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
||||||
|
functionName, minVelocity, maxVelocity, acceleration);
|
||||||
|
|
||||||
|
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||||
|
|
||||||
|
/* MD-90 does not have jog command. Move max 6000 steps */
|
||||||
|
sprintf(pC_->outString_, "SNS 6000");
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (maxVelocity > 0.) {
|
||||||
|
/* This is a positive move in MD90 coordinates */
|
||||||
|
sprintf(pC_->outString_, "ESF");
|
||||||
|
} else {
|
||||||
|
/* This is a negative move in MD90 coordinates */
|
||||||
|
sprintf(pC_->outString_, "ESB");
|
||||||
|
}
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynStatus MD90Axis::stop(double acceleration )
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::stop";
|
||||||
|
|
||||||
|
sprintf(pC_->outString_, "STP");
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The ACS driver used this to turn on/off the motor winding current, so
|
||||||
|
* we'll use this for enabling/disabling the persistent move state.
|
||||||
|
*/
|
||||||
|
asynStatus MD90Axis::setClosedLoop(bool closedLoop)
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::setClosedLoop";
|
||||||
|
|
||||||
|
if (closedLoop == 1) {
|
||||||
|
sprintf(pC_->outString_, "EPM");
|
||||||
|
} else {
|
||||||
|
sprintf(pC_->outString_, "DPM");
|
||||||
|
}
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the I Gain of the motor control loop. The motor is an I- controller
|
||||||
|
* and has no P or D terms.
|
||||||
|
* \param[in] iGain The current I gain in the control loop
|
||||||
|
*/
|
||||||
|
asynStatus MD90Axis::setIGain(double iGain)
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::setIGain";
|
||||||
|
|
||||||
|
iGain = iGain * 1000;
|
||||||
|
if (iGain < 1) iGain = 1.0;
|
||||||
|
if (iGain > 1000) iGain = 1000.0;
|
||||||
|
sprintf(pC_->outString_, "SGN %d", NINT(iGain));
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynStatus MD90Axis::doMoveToHome()
|
||||||
|
{
|
||||||
|
asynStatus status;
|
||||||
|
static const char *functionName = "MD90Axis::doMoveToHome";
|
||||||
|
|
||||||
|
sprintf(pC_->outString_, "CLM 0");
|
||||||
|
status = pC_->writeReadController();
|
||||||
|
if (!status) {
|
||||||
|
status = parseReply(functionName, pC_->inString_);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Polls the axis.
|
||||||
|
* This function reads the motor position, the limit status, the home status, the moving status,
|
||||||
|
* and the drive power-on status.
|
||||||
|
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
||||||
|
* and then calls callParamCallbacks() at the end.
|
||||||
|
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false).
|
||||||
|
*/
|
||||||
|
asynStatus MD90Axis::poll(bool *moving)
|
||||||
|
{
|
||||||
|
int replyStatus;
|
||||||
|
char replyString[256];
|
||||||
|
int replyValue;
|
||||||
|
int done;
|
||||||
|
int driveOn;
|
||||||
|
int homed;
|
||||||
|
double position;
|
||||||
|
double velocity;
|
||||||
|
asynStatus comStatus;
|
||||||
|
static const char *functionName = "MD90Axis::poll";
|
||||||
|
|
||||||
|
// TODO: Will need to add some more error handling for the motor return codes.
|
||||||
|
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 0);
|
||||||
|
|
||||||
|
// Read the drive power on status
|
||||||
|
sprintf(pC_->outString_, "GPS");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Power supply enabled state: 1"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
driveOn = (replyValue == 1) ? 1:0;
|
||||||
|
setIntegerParam(pC_->motorStatusPowerOn_, driveOn);
|
||||||
|
|
||||||
|
// Read the home status
|
||||||
|
sprintf(pC_->outString_, "GHS");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Home status: 1"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
homed = (replyValue == 1) ? 1:0;
|
||||||
|
setIntegerParam(pC_->motorStatusHomed_, homed);
|
||||||
|
|
||||||
|
// Read the moving status of this motor
|
||||||
|
sprintf(pC_->outString_, "STA");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Current status value: 0"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
done = (replyValue == 2) ? 0:1;
|
||||||
|
setIntegerParam(pC_->motorStatusDone_, done);
|
||||||
|
*moving = done ? false:true;
|
||||||
|
switch(replyValue) {
|
||||||
|
case 0: // Idle
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Idle\n", functionName);
|
||||||
|
break;
|
||||||
|
case 1: // Open loop move complete
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Open loop move complete\n", functionName);
|
||||||
|
break;
|
||||||
|
case 2: // Move in progress
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Move in progress\n", functionName);
|
||||||
|
break;
|
||||||
|
case 3: // Move stopped
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Move stopped\n", functionName);
|
||||||
|
break;
|
||||||
|
case 4: // Homing error
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Homing error\n", functionName);
|
||||||
|
break;
|
||||||
|
case 5: // Stance error
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Stance error (Error resetting pose during closed loop move)\n", functionName);
|
||||||
|
break;
|
||||||
|
case 6: // Stance complete
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Stance complete (Finished resetting pose, starting extension move)\n", functionName);
|
||||||
|
break;
|
||||||
|
case 7: // Open loop move error
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Open loop move error\n", functionName);
|
||||||
|
break;
|
||||||
|
case 8: // Closed loop move error
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Closed loop move error\n", functionName);
|
||||||
|
break;
|
||||||
|
case 9: // Closed loop move complete
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Closed loop move complete\n", functionName);
|
||||||
|
break;
|
||||||
|
case 10: // End of travel error
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: End of travel error\n", functionName);
|
||||||
|
if (position > 0) {
|
||||||
|
setIntegerParam(pC_->motorStatusHighLimit_, 1);
|
||||||
|
} else {
|
||||||
|
setIntegerParam(pC_->motorStatusLowLimit_, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 11: // Ramp move error
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||||
|
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Ramp move error\n", functionName);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the current motor position in encoder steps (10 nm)
|
||||||
|
sprintf(pC_->outString_, "GEC");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Current position in encoder counts: 1000"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %lf", &replyStatus, replyString, &position);
|
||||||
|
setDoubleParam(pC_->motorPosition_, position);
|
||||||
|
setDoubleParam(pC_->motorEncoderPosition_, position);
|
||||||
|
setIntegerParam(pC_->motorStatusAtHome_, (position == 0) ? 1:0); // home limit switch
|
||||||
|
setIntegerParam(pC_->motorStatusHome_, (position == 0) ? 1:0); // at home position
|
||||||
|
|
||||||
|
// Read the current motor step frequency to calculate approx. set velocity in (encoder step lengths / s)
|
||||||
|
sprintf(pC_->outString_, "GSF");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Current step frequency: 100"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
velocity = replyValue * COUNTS_PER_STEP;
|
||||||
|
setDoubleParam(pC_->motorVelocity_, velocity);
|
||||||
|
|
||||||
|
// Read the current motor integral gain (range 1-1000)
|
||||||
|
sprintf(pC_->outString_, "GGN");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Gain: 1000"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
setDoubleParam(pC_->motorIGain_, replyValue);
|
||||||
|
|
||||||
|
// Read the current motor persistent move state (using EPICS motorClosedLoop to report this)
|
||||||
|
sprintf(pC_->outString_, "GPM");
|
||||||
|
comStatus = pC_->writeReadController();
|
||||||
|
if (comStatus) goto skip;
|
||||||
|
// The response string is of the form "0: Current persistent move state: 1"
|
||||||
|
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||||
|
setIntegerParam(pC_->motorClosedLoop_, (replyValue == 0) ? 0:1);
|
||||||
|
|
||||||
|
// set some default params
|
||||||
|
setIntegerParam(pC_->motorStatusHasEncoder_, 1);
|
||||||
|
setIntegerParam(pC_->motorStatusGainSupport_, 1);
|
||||||
|
|
||||||
|
skip:
|
||||||
|
setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
|
||||||
|
callParamCallbacks();
|
||||||
|
return comStatus ? asynError : asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Code for iocsh registration */
|
||||||
|
static const iocshArg MD90CreateControllerArg0 = {"Port name", iocshArgString};
|
||||||
|
static const iocshArg MD90CreateControllerArg1 = {"MD-90 port name", iocshArgString};
|
||||||
|
static const iocshArg MD90CreateControllerArg2 = {"Number of axes", iocshArgInt};
|
||||||
|
static const iocshArg MD90CreateControllerArg3 = {"Moving poll period (ms)", iocshArgInt};
|
||||||
|
static const iocshArg MD90CreateControllerArg4 = {"Idle poll period (ms)", iocshArgInt};
|
||||||
|
static const iocshArg * const MD90CreateControllerArgs[] = {&MD90CreateControllerArg0,
|
||||||
|
&MD90CreateControllerArg1,
|
||||||
|
&MD90CreateControllerArg2,
|
||||||
|
&MD90CreateControllerArg3,
|
||||||
|
&MD90CreateControllerArg4};
|
||||||
|
static const iocshFuncDef MD90CreateControllerDef = {"MD90CreateController", 5, MD90CreateControllerArgs};
|
||||||
|
static void MD90CreateContollerCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
MD90CreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MD90Register(void)
|
||||||
|
{
|
||||||
|
iocshRegister(&MD90CreateControllerDef, MD90CreateContollerCallFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
epicsExportRegistrar(MD90Register);
|
||||||
|
}
|
53
dsmApp/src/MD90Driver.h
Normal file
53
dsmApp/src/MD90Driver.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
FILENAME... MD90Driver.h
|
||||||
|
USAGE... Motor driver support for the DSM MD-90 controller.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asynMotorController.h"
|
||||||
|
#include "asynMotorAxis.h"
|
||||||
|
|
||||||
|
#define MAX_MD90_AXES 1
|
||||||
|
|
||||||
|
// No controller-specific parameters yet
|
||||||
|
#define NUM_MD90_PARAMS 0
|
||||||
|
|
||||||
|
#define SLEEP_MARGIN 1.2 // Extra factor to wait after stepping before homing
|
||||||
|
#define HOME_SLEEP_MIN 1 // Minimum amount of time to wait after stepping/before homing
|
||||||
|
#define SMALL_NSTEPS 5 // Number of steps to take to set direction for homing routine
|
||||||
|
#define COUNTS_PER_STEP 1000.0 // Number of encoder counts per motor step (measured by testing)
|
||||||
|
|
||||||
|
class epicsShareClass MD90Axis : public asynMotorAxis
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/* These are the methods we override from the base class */
|
||||||
|
MD90Axis(class MD90Controller *pC, int axis);
|
||||||
|
void report(FILE *fp, int level);
|
||||||
|
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||||
|
asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration);
|
||||||
|
asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards);
|
||||||
|
asynStatus stop(double acceleration);
|
||||||
|
asynStatus poll(bool *moving);
|
||||||
|
asynStatus setClosedLoop(bool closedLoop);
|
||||||
|
asynStatus setIGain(double iGain);
|
||||||
|
asynStatus doMoveToHome();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MD90Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
||||||
|
* Abbreviated because it is used very frequently */
|
||||||
|
asynStatus sendAccelAndVelocity(double accel, double velocity);
|
||||||
|
asynStatus parseReply(const char *functionName, const char *reply);
|
||||||
|
|
||||||
|
friend class MD90Controller;
|
||||||
|
};
|
||||||
|
|
||||||
|
class epicsShareClass MD90Controller : public asynMotorController {
|
||||||
|
public:
|
||||||
|
MD90Controller(const char *portName, const char *MD90PortName, int numAxes, double movingPollPeriod, double idlePollPeriod);
|
||||||
|
|
||||||
|
void report(FILE *fp, int level);
|
||||||
|
MD90Axis* getAxis(asynUser *pasynUser);
|
||||||
|
MD90Axis* getAxis(int axisNo);
|
||||||
|
|
||||||
|
friend class MD90Axis;
|
||||||
|
};
|
@@ -5,18 +5,18 @@ include $(TOP)/configure/CONFIG
|
|||||||
# The following are used for debugging messages.
|
# The following are used for debugging messages.
|
||||||
USR_CXXFLAGS += -DDEBUG
|
USR_CXXFLAGS += -DDEBUG
|
||||||
|
|
||||||
DBD += devAcsMotor.dbd
|
DBD += devDsmMotor.dbd
|
||||||
|
|
||||||
LIBRARY_IOC = Acs
|
LIBRARY_IOC = dsm
|
||||||
|
|
||||||
SRCS += AcsRegister.cc
|
SRCS += dsmRegister.cc
|
||||||
|
|
||||||
# Advanced Control Systems driver support.
|
# Advanced Control Systems driver support.
|
||||||
SRCS += devMCB4B.c drvMCB4B.c
|
SRCS += devMD90.c drvMD90.c
|
||||||
SRCS += MCB4BDriver.cpp
|
SRCS += MD90Driver.cpp
|
||||||
|
|
||||||
Acs_LIBS += motor asyn
|
dsm_LIBS += motor asyn
|
||||||
Acs_LIBS += $(EPICS_BASE_IOC_LIBS)
|
dsm_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||||
|
|
||||||
include $(TOP)/configure/RULES
|
include $(TOP)/configure/RULES
|
||||||
|
|
11
dsmApp/src/devDsmMotor.dbd
Normal file
11
dsmApp/src/devDsmMotor.dbd
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Advanced Control Systems driver support.
|
||||||
|
|
||||||
|
# Model 1 (non-asyn) driver
|
||||||
|
device(motor,VME_IO,devMD90,"DSM MD-90")
|
||||||
|
driver(drvMD90)
|
||||||
|
registrar(dsmRegister)
|
||||||
|
|
||||||
|
# Model 3 driver
|
||||||
|
registrar(MD90Register)
|
||||||
|
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
/* File: devMCB4B.cc */
|
/* File: devMD90.cc */
|
||||||
|
|
||||||
/* Device Support Routines for motor */
|
/* Device Support Routines for motor */
|
||||||
/*
|
/*
|
||||||
@@ -20,21 +20,21 @@
|
|||||||
#include "motorRecord.h"
|
#include "motorRecord.h"
|
||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
#include "motordevCom.h"
|
#include "motordevCom.h"
|
||||||
#include "drvMCB4B.h"
|
#include "drvMD90.h"
|
||||||
#include "epicsExport.h"
|
#include "epicsExport.h"
|
||||||
|
|
||||||
#define STATIC static
|
#define STATIC static
|
||||||
|
|
||||||
extern struct driver_table MCB4B_access;
|
extern struct driver_table MD90_access;
|
||||||
|
|
||||||
#define NINT(f) (long)((f)>0 ? (f)+0.5 : (f)-0.5)
|
#define NINT(f) (long)((f)>0 ? (f)+0.5 : (f)-0.5)
|
||||||
|
|
||||||
volatile int devMCB4BDebug = 0;
|
volatile int devMD90Debug = 0;
|
||||||
extern "C" {epicsExportAddress(int, devMCB4BDebug);}
|
extern "C" {epicsExportAddress(int, devMD90Debug);}
|
||||||
|
|
||||||
static inline void Debug(int level, const char *format, ...) {
|
static inline void Debug(int level, const char *format, ...) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (level < devMCB4BDebug)
|
if (level < devMD90Debug)
|
||||||
{
|
{
|
||||||
va_list pVar;
|
va_list pVar;
|
||||||
va_start(pVar, format);
|
va_start(pVar, format);
|
||||||
@@ -45,35 +45,35 @@ static inline void Debug(int level, const char *format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Debugging levels:
|
/* Debugging levels:
|
||||||
* devMCB4BDebug >= 3 Print new part of command and command string so far
|
* devMD90Debug >= 3 Print new part of command and command string so far
|
||||||
* at the end of MCB4B_build_trans
|
* at the end of MD90_build_trans
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* ----------------Create the dsets for devMCB4B----------------- */
|
/* ----------------Create the dsets for devMD90----------------- */
|
||||||
STATIC struct driver_table *drvtabptr;
|
STATIC struct driver_table *drvtabptr;
|
||||||
STATIC long MCB4B_init(int);
|
STATIC long MD90_init(int);
|
||||||
STATIC long MCB4B_init_record(void *);
|
STATIC long MD90_init_record(void *);
|
||||||
STATIC long MCB4B_start_trans(struct motorRecord *);
|
STATIC long MD90_start_trans(struct motorRecord *);
|
||||||
STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd, double *, struct motorRecord *);
|
STATIC RTN_STATUS MD90_build_trans(motor_cmnd, double *, struct motorRecord *);
|
||||||
STATIC RTN_STATUS MCB4B_end_trans(struct motorRecord *);
|
STATIC RTN_STATUS MD90_end_trans(struct motorRecord *);
|
||||||
|
|
||||||
struct motor_dset devMCB4B =
|
struct motor_dset devMD90 =
|
||||||
{
|
{
|
||||||
{8, NULL, (DEVSUPFUN) MCB4B_init, (DEVSUPFUN) MCB4B_init_record, NULL},
|
{8, NULL, (DEVSUPFUN) MD90_init, (DEVSUPFUN) MD90_init_record, NULL},
|
||||||
motor_update_values,
|
motor_update_values,
|
||||||
MCB4B_start_trans,
|
MD90_start_trans,
|
||||||
MCB4B_build_trans,
|
MD90_build_trans,
|
||||||
MCB4B_end_trans
|
MD90_end_trans
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {epicsExportAddress(dset,devMCB4B);}
|
extern "C" {epicsExportAddress(dset,devMD90);}
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------- program data --------------------- */
|
/* --------------------------- program data --------------------- */
|
||||||
/* This table is used to define the command types */
|
/* This table is used to define the command types */
|
||||||
|
|
||||||
static msg_types MCB4B_table[] = {
|
static msg_types MD90_table[] = {
|
||||||
MOTION, /* MOVE_ABS */
|
MOTION, /* MOVE_ABS */
|
||||||
MOTION, /* MOVE_REL */
|
MOTION, /* MOVE_REL */
|
||||||
MOTION, /* HOME_FOR */
|
MOTION, /* HOME_FOR */
|
||||||
@@ -99,63 +99,63 @@ static msg_types MCB4B_table[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct board_stat **MCB4B_cards;
|
static struct board_stat **MD90_cards;
|
||||||
|
|
||||||
/* --------------------------- program data --------------------- */
|
/* --------------------------- program data --------------------- */
|
||||||
|
|
||||||
|
|
||||||
/* initialize device support for MCB4B stepper motor */
|
/* initialize device support for MD90 stepper motor */
|
||||||
STATIC long MCB4B_init(int after)
|
STATIC long MD90_init(int after)
|
||||||
{
|
{
|
||||||
long rtnval;
|
long rtnval;
|
||||||
|
|
||||||
Debug(5, "MCB4B_init: entry\n");
|
Debug(5, "MD90_init: entry\n");
|
||||||
if (!after)
|
if (!after)
|
||||||
{
|
{
|
||||||
drvtabptr = &MCB4B_access;
|
drvtabptr = &MD90_access;
|
||||||
(drvtabptr->init)();
|
(drvtabptr->init)();
|
||||||
}
|
}
|
||||||
|
|
||||||
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &MCB4B_cards);
|
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &MD90_cards);
|
||||||
Debug(5, "MCB4B_init: exit\n");
|
Debug(5, "MD90_init: exit\n");
|
||||||
return(rtnval);
|
return(rtnval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* initialize a record instance */
|
/* initialize a record instance */
|
||||||
STATIC long MCB4B_init_record(void *arg)
|
STATIC long MD90_init_record(void *arg)
|
||||||
{
|
{
|
||||||
struct motorRecord *mr = (struct motorRecord *) arg;
|
struct motorRecord *mr = (struct motorRecord *) arg;
|
||||||
long rtnval;
|
long rtnval;
|
||||||
|
|
||||||
Debug(5, "MCB4B_init_record: entry\n");
|
Debug(5, "MD90_init_record: entry\n");
|
||||||
rtnval = motor_init_record_com(mr, *drvtabptr->cardcnt_ptr,
|
rtnval = motor_init_record_com(mr, *drvtabptr->cardcnt_ptr,
|
||||||
drvtabptr, MCB4B_cards);
|
drvtabptr, MD90_cards);
|
||||||
return(rtnval);
|
return(rtnval);
|
||||||
Debug(5, "MCB4B_init_record: exit\n");
|
Debug(5, "MD90_init_record: exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* start building a transaction */
|
/* start building a transaction */
|
||||||
STATIC long MCB4B_start_trans(struct motorRecord *mr)
|
STATIC long MD90_start_trans(struct motorRecord *mr)
|
||||||
{
|
{
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end building a transaction */
|
/* end building a transaction */
|
||||||
STATIC RTN_STATUS MCB4B_end_trans(struct motorRecord *mr)
|
STATIC RTN_STATUS MD90_end_trans(struct motorRecord *mr)
|
||||||
{
|
{
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a part to the transaction */
|
/* add a part to the transaction */
|
||||||
STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr)
|
STATIC RTN_STATUS MD90_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr)
|
||||||
{
|
{
|
||||||
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
|
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
|
||||||
struct mess_node *motor_call;
|
struct mess_node *motor_call;
|
||||||
struct controller *brdptr;
|
struct controller *brdptr;
|
||||||
struct MCB4Bcontroller *cntrl;
|
struct MD90controller *cntrl;
|
||||||
char buff[30];
|
char buff[30];
|
||||||
int axis, card;
|
int axis, card;
|
||||||
RTN_STATUS rtnval;
|
RTN_STATUS rtnval;
|
||||||
@@ -170,19 +170,19 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
dval = (parms == NULL) ? 0.0 : *parms;
|
dval = (parms == NULL) ? 0.0 : *parms;
|
||||||
ival = NINT(dval);
|
ival = NINT(dval);
|
||||||
|
|
||||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||||
Debug(5, "MCB4B_build_trans: entry, motor_start_trans_com=%d\n", rtnval);
|
Debug(5, "MD90_build_trans: entry, motor_start_trans_com=%d\n", rtnval);
|
||||||
|
|
||||||
motor_call = &(trans->motor_call);
|
motor_call = &(trans->motor_call);
|
||||||
motor_call->type = MCB4B_table[command];
|
motor_call->type = MD90_table[command];
|
||||||
card = motor_call->card;
|
card = motor_call->card;
|
||||||
axis = motor_call->signal;
|
axis = motor_call->signal;
|
||||||
brdptr = (*trans->tabptr->card_array)[card];
|
brdptr = (*trans->tabptr->card_array)[card];
|
||||||
Debug(5, "MCB4B_build_trans: axis=%d, command=%d\n", axis, command);
|
Debug(5, "MD90_build_trans: axis=%d, command=%d\n", axis, command);
|
||||||
if (brdptr == NULL)
|
if (brdptr == NULL)
|
||||||
return(rtnval = ERROR);
|
return(rtnval = ERROR);
|
||||||
|
|
||||||
cntrl = (struct MCB4Bcontroller *) brdptr->DevicePrivate;
|
cntrl = (struct MD90controller *) brdptr->DevicePrivate;
|
||||||
|
|
||||||
|
|
||||||
if (trans->state != BUILD_STATE)
|
if (trans->state != BUILD_STATE)
|
||||||
@@ -192,8 +192,8 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
{
|
{
|
||||||
strcpy(motor_call->message, mr->init);
|
strcpy(motor_call->message, mr->init);
|
||||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||||
motor_call->type = MCB4B_table[command];
|
motor_call->type = MD90_table[command];
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
@@ -207,8 +207,8 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
{
|
{
|
||||||
strcpy(motor_call->message, mr->prem);
|
strcpy(motor_call->message, mr->prem);
|
||||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||||
motor_call->type = MCB4B_table[command];
|
motor_call->type = MD90_table[command];
|
||||||
}
|
}
|
||||||
if (strlen(mr->post) != 0)
|
if (strlen(mr->post) != 0)
|
||||||
motor_call->postmsgptr = (char *) &mr->post;
|
motor_call->postmsgptr = (char *) &mr->post;
|
||||||
@@ -238,7 +238,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
case SET_VEL_BASE:
|
case SET_VEL_BASE:
|
||||||
send=false;
|
send=false;
|
||||||
trans->state = IDLE_STATE;
|
trans->state = IDLE_STATE;
|
||||||
break; /* MCB4B does not use base velocity */
|
break; /* MD90 does not use base velocity */
|
||||||
case SET_VELOCITY:
|
case SET_VELOCITY:
|
||||||
ival = (int) (fabs(115200./dval) + 0.5);
|
ival = (int) (fabs(115200./dval) + 0.5);
|
||||||
if (ival < 2) ival=2;
|
if (ival < 2) ival=2;
|
||||||
@@ -247,7 +247,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
break;
|
break;
|
||||||
case SET_ACCEL:
|
case SET_ACCEL:
|
||||||
/* dval is acceleration in steps/sec/sec */
|
/* dval is acceleration in steps/sec/sec */
|
||||||
/* MCB is programmed with Ramp Index (R) where: */
|
/* MD-90 is programmed with Ramp Index (R) where: */
|
||||||
/* dval (steps/sec/sec) = 720,000/(256-R) */
|
/* dval (steps/sec/sec) = 720,000/(256-R) */
|
||||||
/* or R=256-(720,000/dval) */
|
/* or R=256-(720,000/dval) */
|
||||||
ival = (int) (256-(720000./dval)+0.5);
|
ival = (int) (256-(720000./dval)+0.5);
|
||||||
@@ -257,7 +257,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
break;
|
break;
|
||||||
case GO:
|
case GO:
|
||||||
/*
|
/*
|
||||||
* The MCB4B starts moving immediately on move commands, GO command
|
* The MD90 starts moving immediately on move commands, GO command
|
||||||
* does nothing
|
* does nothing
|
||||||
*/
|
*/
|
||||||
send=false;
|
send=false;
|
||||||
@@ -265,7 +265,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
break;
|
break;
|
||||||
case SET_ENC_RATIO:
|
case SET_ENC_RATIO:
|
||||||
/*
|
/*
|
||||||
* The MCB4B does not have the concept of encoder ratio, ignore this
|
* The MD90 does not have the concept of encoder ratio, ignore this
|
||||||
* command
|
* command
|
||||||
*/
|
*/
|
||||||
send=false;
|
send=false;
|
||||||
@@ -280,19 +280,19 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
sprintf(motor_call->message, "#%02dQ", axis);
|
sprintf(motor_call->message, "#%02dQ", axis);
|
||||||
break;
|
break;
|
||||||
case JOG:
|
case JOG:
|
||||||
/* MCB-4B does not have jog command. Move 1 million steps */
|
/* MD-90 does not have jog command. Move 1 million steps */
|
||||||
ival = (int) (fabs(115200./dval) + 0.5);
|
ival = (int) (fabs(115200./dval) + 0.5);
|
||||||
if (ival < 2) ival=2;
|
if (ival < 2) ival=2;
|
||||||
if (ival > 65535) ival = 65535;
|
if (ival > 65535) ival = 65535;
|
||||||
sprintf(motor_call->message, "#%02dC=%ld", axis, ival);
|
sprintf(motor_call->message, "#%02dC=%ld", axis, ival);
|
||||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||||
motor_call->type = MCB4B_table[command];
|
motor_call->type = MD90_table[command];
|
||||||
if (dval > 0.) {
|
if (dval > 0.) {
|
||||||
/* This is a positive move in MCB4B coordinates */
|
/* This is a positive move in MD90 coordinates */
|
||||||
sprintf(motor_call->message, "#%02dM+1000000", axis);
|
sprintf(motor_call->message, "#%02dM+1000000", axis);
|
||||||
} else {
|
} else {
|
||||||
/* This is a negative move in MCB4B coordinates */
|
/* This is a negative move in MD90 coordinates */
|
||||||
sprintf(motor_call->message, "#%02dM-1000000", axis);
|
sprintf(motor_call->message, "#%02dM-1000000", axis);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -325,7 +325,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
|||||||
return(rtnval);
|
return(rtnval);
|
||||||
else {
|
else {
|
||||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||||
Debug(5, "MCB4B_send_msg: motor_end_trans_com status=%d, exit\n", rtnval);
|
Debug(5, "MD90_send_msg: motor_end_trans_com status=%d, exit\n", rtnval);
|
||||||
return (rtnval);
|
return (rtnval);
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
/* File: drvMCB4B.cc */
|
/* File: drvMD90.cc */
|
||||||
|
|
||||||
/* Device Driver Support routines for motor */
|
/* Device Driver Support routines for motor */
|
||||||
/*
|
/*
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errlog.h>
|
#include <errlog.h>
|
||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
#include "AcsRegister.h"
|
#include "dsmRegister.h"
|
||||||
#include "drvMCB4B.h"
|
#include "drvMD90.h"
|
||||||
#include "asynOctetSyncIO.h"
|
#include "asynOctetSyncIO.h"
|
||||||
#include "epicsExport.h"
|
#include "epicsExport.h"
|
||||||
|
|
||||||
@@ -35,14 +35,14 @@
|
|||||||
|
|
||||||
#define TIMEOUT 2.0 /* Command timeout in sec */
|
#define TIMEOUT 2.0 /* Command timeout in sec */
|
||||||
|
|
||||||
#define BUFF_SIZE 100 /* Maximum length of string to/from MCB4B */
|
#define BUFF_SIZE 100 /* Maximum length of string to/from MD90 */
|
||||||
|
|
||||||
volatile int drvMCB4BDebug = 0;
|
volatile int drvMD90Debug = 0;
|
||||||
extern "C" {epicsExportAddress(int, drvMCB4BDebug);}
|
extern "C" {epicsExportAddress(int, drvMD90Debug);}
|
||||||
|
|
||||||
static inline void Debug(int level, const char *format, ...) {
|
static inline void Debug(int level, const char *format, ...) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (level < drvMCB4BDebug)
|
if (level < drvMD90Debug)
|
||||||
{
|
{
|
||||||
va_list pVar;
|
va_list pVar;
|
||||||
va_start(pVar, format);
|
va_start(pVar, format);
|
||||||
@@ -53,14 +53,14 @@ static inline void Debug(int level, const char *format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Debugging notes:
|
/* Debugging notes:
|
||||||
* drvMCB4BDebug == 0 No debugging information is printed
|
* drvMD90Debug == 0 No debugging information is printed
|
||||||
* drvMCB4BDebug >= 1 Warning information is printed
|
* drvMD90Debug >= 1 Warning information is printed
|
||||||
* drvMCB4BDebug >= 2 Time-stamped messages are printed for each string
|
* drvMD90Debug >= 2 Time-stamped messages are printed for each string
|
||||||
* sent to and received from the controller
|
* sent to and received from the controller
|
||||||
* drvMCB4BDebug >= 3 Additional debugging messages
|
* drvMD90Debug >= 3 Additional debugging messages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int MCB4B_num_cards = 0;
|
int MD90_num_cards = 0;
|
||||||
|
|
||||||
/* Local data required for every driver; see "motordrvComCode.h" */
|
/* Local data required for every driver; see "motordrvComCode.h" */
|
||||||
#include "motordrvComCode.h"
|
#include "motordrvComCode.h"
|
||||||
@@ -78,7 +78,7 @@ STATIC void query_done(int, int, struct mess_node *);
|
|||||||
|
|
||||||
/*----------------functions-----------------*/
|
/*----------------functions-----------------*/
|
||||||
|
|
||||||
struct driver_table MCB4B_access =
|
struct driver_table MD90_access =
|
||||||
{
|
{
|
||||||
motor_init,
|
motor_init,
|
||||||
motor_send,
|
motor_send,
|
||||||
@@ -102,16 +102,16 @@ struct driver_table MCB4B_access =
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drvMCB4B_drvet
|
struct drvMD90_drvet
|
||||||
{
|
{
|
||||||
long number;
|
long number;
|
||||||
long (*report) (int);
|
long (*report) (int);
|
||||||
long (*init) (void);
|
long (*init) (void);
|
||||||
} drvMCB4B = {2, report, init};
|
} drvMD90 = {2, report, init};
|
||||||
|
|
||||||
extern "C" {epicsExportAddress(drvet, drvMCB4B);}
|
extern "C" {epicsExportAddress(drvet, drvMD90);}
|
||||||
|
|
||||||
STATIC struct thread_args targs = {SCAN_RATE, &MCB4B_access, 0.0};
|
STATIC struct thread_args targs = {SCAN_RATE, &MD90_access, 0.0};
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************
|
/*********************************************************
|
||||||
@@ -120,16 +120,16 @@ STATIC struct thread_args targs = {SCAN_RATE, &MCB4B_access, 0.0};
|
|||||||
static long report(int level)
|
static long report(int level)
|
||||||
{
|
{
|
||||||
int card;
|
int card;
|
||||||
struct MCB4Bcontroller *cntrl;
|
struct MD90controller *cntrl;
|
||||||
|
|
||||||
if (MCB4B_num_cards <=0)
|
if (MD90_num_cards <=0)
|
||||||
printf(" NO MCB4B controllers found\n");
|
printf(" NO MD90 controllers found\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (card = 0; card < MCB4B_num_cards; card++) {
|
for (card = 0; card < MD90_num_cards; card++) {
|
||||||
if (motor_state[card]) {
|
if (motor_state[card]) {
|
||||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||||
printf(" MCB4B controller %d, port=%s, id: %s \n",
|
printf(" MD90 controller %d, port=%s, id: %s \n",
|
||||||
card, cntrl->port,
|
card, cntrl->port,
|
||||||
motor_state[card]->ident);
|
motor_state[card]->ident);
|
||||||
}
|
}
|
||||||
@@ -148,10 +148,10 @@ static long init()
|
|||||||
* support
|
* support
|
||||||
*/
|
*/
|
||||||
/* Check for setup */
|
/* Check for setup */
|
||||||
if (MCB4B_num_cards <= 0)
|
if (MD90_num_cards <= 0)
|
||||||
{
|
{
|
||||||
Debug(1, "init: *MCB4B driver disabled*\n");
|
Debug(1, "init: *MD90 driver disabled*\n");
|
||||||
Debug(1, "MCB4BSetup() is missing from startup script.\n");
|
Debug(1, "MD90Setup() is missing from startup script.\n");
|
||||||
return (ERROR);
|
return (ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ STATIC void query_done(int card, int axis, struct mess_node *nodeptr)
|
|||||||
*********************************************************/
|
*********************************************************/
|
||||||
STATIC void start_status(int card)
|
STATIC void start_status(int card)
|
||||||
{
|
{
|
||||||
/* The MCB4B cannot query status or positions of all axes with a
|
/* The MD90 cannot query status or positions of all axes with a
|
||||||
* single command. This needs to be done on an axis-by-axis basis,
|
* single command. This needs to be done on an axis-by-axis basis,
|
||||||
* so this function does nothing
|
* so this function does nothing
|
||||||
*/
|
*/
|
||||||
@@ -265,7 +265,7 @@ STATIC int set_status(int card, int signal)
|
|||||||
if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 && nodeptr->postmsgptr != 0)
|
if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 && nodeptr->postmsgptr != 0)
|
||||||
{
|
{
|
||||||
send_mess(card, nodeptr->postmsgptr, NULL);
|
send_mess(card, nodeptr->postmsgptr, NULL);
|
||||||
/* The MCB4B always sends back a response, read it and discard */
|
/* The MD90 always sends back a response, read it and discard */
|
||||||
recv_mess(card, buff, WAIT);
|
recv_mess(card, buff, WAIT);
|
||||||
nodeptr->postmsgptr = NULL;
|
nodeptr->postmsgptr = NULL;
|
||||||
}
|
}
|
||||||
@@ -276,12 +276,12 @@ STATIC int set_status(int card, int signal)
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
/* send a message to the MCB4B board */
|
/* send a message to the MD90 board */
|
||||||
/* send_mess() */
|
/* send_mess() */
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
||||||
{
|
{
|
||||||
struct MCB4Bcontroller *cntrl;
|
struct MD90controller *cntrl;
|
||||||
size_t nwrite;
|
size_t nwrite;
|
||||||
|
|
||||||
/* Check that card exists */
|
/* Check that card exists */
|
||||||
@@ -293,7 +293,7 @@ STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
|||||||
|
|
||||||
/* If the string is NULL just return */
|
/* If the string is NULL just return */
|
||||||
if (strlen(com) == 0) return(OK);
|
if (strlen(com) == 0) return(OK);
|
||||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||||
|
|
||||||
Debug(2, "send_mess: sending message to card %d, message=%s\n",\
|
Debug(2, "send_mess: sending message to card %d, message=%s\n",\
|
||||||
card, com);
|
card, com);
|
||||||
@@ -305,7 +305,7 @@ STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
/* Read a response string from the MCB4B board */
|
/* Read a response string from the MD90 board */
|
||||||
/* recv_mess() */
|
/* recv_mess() */
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
STATIC int recv_mess(int card, char *com, int flag)
|
STATIC int recv_mess(int card, char *com, int flag)
|
||||||
@@ -313,7 +313,7 @@ STATIC int recv_mess(int card, char *com, int flag)
|
|||||||
double timeout;
|
double timeout;
|
||||||
size_t nread=0;
|
size_t nread=0;
|
||||||
asynStatus status;
|
asynStatus status;
|
||||||
struct MCB4Bcontroller *cntrl;
|
struct MD90controller *cntrl;
|
||||||
int flush;
|
int flush;
|
||||||
int eomReason;
|
int eomReason;
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ STATIC int recv_mess(int card, char *com, int flag)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||||
|
|
||||||
Debug(3, "recv_mess entry: card %d, flag=%d\n",\
|
Debug(3, "recv_mess entry: card %d, flag=%d\n",\
|
||||||
card, flag);
|
card, flag);
|
||||||
@@ -363,18 +363,18 @@ STATIC int recv_mess(int card, char *com, int flag)
|
|||||||
|
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
/* Setup system configuration */
|
/* Setup system configuration */
|
||||||
/* MCB4BSetup() */
|
/* MD90Setup() */
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
RTN_STATUS
|
RTN_STATUS
|
||||||
MCB4BSetup(int num_cards, /* maximum number of controllers in system */
|
MD90Setup(int num_cards, /* maximum number of controllers in system */
|
||||||
int scan_rate) /* polling rate - 1/60 sec units */
|
int scan_rate) /* polling rate - 1/60 sec units */
|
||||||
{
|
{
|
||||||
int itera;
|
int itera;
|
||||||
|
|
||||||
if (num_cards < 1 || num_cards > MCB4B_NUM_CARDS)
|
if (num_cards < 1 || num_cards > MD90_NUM_CARDS)
|
||||||
MCB4B_num_cards = MCB4B_NUM_CARDS;
|
MD90_num_cards = MD90_NUM_CARDS;
|
||||||
else
|
else
|
||||||
MCB4B_num_cards = num_cards;
|
MD90_num_cards = num_cards;
|
||||||
|
|
||||||
/* Set motor polling task rate */
|
/* Set motor polling task rate */
|
||||||
if (scan_rate >= 1 && scan_rate <= 60)
|
if (scan_rate >= 1 && scan_rate <= 60)
|
||||||
@@ -384,15 +384,15 @@ MCB4BSetup(int num_cards, /* maximum number of controllers in system */
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate space for motor_state structure pointers. Note this must be done
|
* Allocate space for motor_state structure pointers. Note this must be done
|
||||||
* before MCB4BConfig is called, so it cannot be done in motor_init()
|
* before MD90Config is called, so it cannot be done in motor_init()
|
||||||
* This means that we must allocate space for a card without knowing
|
* This means that we must allocate space for a card without knowing
|
||||||
* if it really exists, which is not a serious problem since this is just
|
* if it really exists, which is not a serious problem since this is just
|
||||||
* an array of pointers.
|
* an array of pointers.
|
||||||
*/
|
*/
|
||||||
motor_state = (struct controller **) malloc(MCB4B_num_cards *
|
motor_state = (struct controller **) malloc(MD90_num_cards *
|
||||||
sizeof(struct controller *));
|
sizeof(struct controller *));
|
||||||
|
|
||||||
for (itera = 0; itera < MCB4B_num_cards; itera++)
|
for (itera = 0; itera < MD90_num_cards; itera++)
|
||||||
motor_state[itera] = (struct controller *) NULL;
|
motor_state[itera] = (struct controller *) NULL;
|
||||||
return (OK);
|
return (OK);
|
||||||
}
|
}
|
||||||
@@ -400,20 +400,20 @@ MCB4BSetup(int num_cards, /* maximum number of controllers in system */
|
|||||||
|
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
/* Configure a controller */
|
/* Configure a controller */
|
||||||
/* MCB4BConfig() */
|
/* MD90Config() */
|
||||||
/*****************************************************/
|
/*****************************************************/
|
||||||
RTN_STATUS
|
RTN_STATUS
|
||||||
MCB4BConfig(int card, /* card being configured */
|
MD90Config(int card, /* card being configured */
|
||||||
const char *name) /* port name for asyn */
|
const char *name) /* port name for asyn */
|
||||||
{
|
{
|
||||||
struct MCB4Bcontroller *cntrl;
|
struct MD90controller *cntrl;
|
||||||
|
|
||||||
if (card < 0 || card >= MCB4B_num_cards)
|
if (card < 0 || card >= MD90_num_cards)
|
||||||
return (ERROR);
|
return (ERROR);
|
||||||
|
|
||||||
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
|
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
|
||||||
motor_state[card]->DevicePrivate = malloc(sizeof(struct MCB4Bcontroller));
|
motor_state[card]->DevicePrivate = malloc(sizeof(struct MD90controller));
|
||||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||||
strcpy(cntrl->port, name);
|
strcpy(cntrl->port, name);
|
||||||
return (OK);
|
return (OK);
|
||||||
}
|
}
|
||||||
@@ -429,7 +429,7 @@ MCB4BConfig(int card, /* card being configured */
|
|||||||
STATIC int motor_init()
|
STATIC int motor_init()
|
||||||
{
|
{
|
||||||
struct controller *brdptr;
|
struct controller *brdptr;
|
||||||
struct MCB4Bcontroller *cntrl;
|
struct MD90controller *cntrl;
|
||||||
int card_index, motor_index;
|
int card_index, motor_index;
|
||||||
char buff[BUFF_SIZE];
|
char buff[BUFF_SIZE];
|
||||||
int total_axis = 0;
|
int total_axis = 0;
|
||||||
@@ -439,21 +439,21 @@ STATIC int motor_init()
|
|||||||
initialized = true; /* Indicate that driver is initialized. */
|
initialized = true; /* Indicate that driver is initialized. */
|
||||||
|
|
||||||
/* Check for setup */
|
/* Check for setup */
|
||||||
if (MCB4B_num_cards <= 0)
|
if (MD90_num_cards <= 0)
|
||||||
{
|
{
|
||||||
Debug(1, "motor_init: *MCB4B driver disabled*\n");
|
Debug(1, "motor_init: *MD90 driver disabled*\n");
|
||||||
Debug(1, "MCB4BSetup() is missing from startup script.\n");
|
Debug(1, "MD90Setup() is missing from startup script.\n");
|
||||||
return (ERROR);
|
return (ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (card_index = 0; card_index < MCB4B_num_cards; card_index++)
|
for (card_index = 0; card_index < MD90_num_cards; card_index++)
|
||||||
{
|
{
|
||||||
if (!motor_state[card_index])
|
if (!motor_state[card_index])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
brdptr = motor_state[card_index];
|
brdptr = motor_state[card_index];
|
||||||
total_cards = card_index + 1;
|
total_cards = card_index + 1;
|
||||||
cntrl = (struct MCB4Bcontroller *) brdptr->DevicePrivate;
|
cntrl = (struct MD90controller *) brdptr->DevicePrivate;
|
||||||
|
|
||||||
/* Initialize communications channel */
|
/* Initialize communications channel */
|
||||||
success_rtn = pasynOctetSyncIO->connect(cntrl->port, 0, &cntrl->pasynUser, NULL);
|
success_rtn = pasynOctetSyncIO->connect(cntrl->port, 0, &cntrl->pasynUser, NULL);
|
||||||
@@ -498,7 +498,7 @@ STATIC int motor_init()
|
|||||||
sprintf(buff,"#%02dQ", motor_index);
|
sprintf(buff,"#%02dQ", motor_index);
|
||||||
send_mess(card_index, buff, 0);
|
send_mess(card_index, buff, 0);
|
||||||
recv_mess(card_index, buff, WAIT); /* Throw away response */
|
recv_mess(card_index, buff, WAIT); /* Throw away response */
|
||||||
strcpy(brdptr->ident, "MCB-4B");
|
strcpy(brdptr->ident, "MD-90");
|
||||||
motor_info->status.All = 0;
|
motor_info->status.All = 0;
|
||||||
motor_info->no_motion_count = 0;
|
motor_info->no_motion_count = 0;
|
||||||
motor_info->encoder_position = 0;
|
motor_info->encoder_position = 0;
|
||||||
@@ -521,7 +521,7 @@ STATIC int motor_init()
|
|||||||
|
|
||||||
Debug(3, "motor_init: spawning motor task\n");
|
Debug(3, "motor_init: spawning motor task\n");
|
||||||
|
|
||||||
epicsThreadCreate((char *) "tMCB4B", epicsThreadPriorityMedium,
|
epicsThreadCreate((char *) "tMD90", epicsThreadPriorityMedium,
|
||||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||||
(EPICSTHREADFUNC) motor_task, (void *) &targs);
|
(EPICSTHREADFUNC) motor_task, (void *) &targs);
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
/* File: drvMCB4B.h */
|
/* File: drvMD90.h */
|
||||||
|
|
||||||
|
|
||||||
/* Device Driver Support definitions for motor */
|
/* Device Driver Support definitions for motor */
|
||||||
@@ -12,23 +12,23 @@
|
|||||||
* .01 02/24/2002 mlr initialized from drvPM304.h
|
* .01 02/24/2002 mlr initialized from drvPM304.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INCdrvMCB4Bh
|
#ifndef INCdrvMD90h
|
||||||
#define INCdrvMCB4Bh 1
|
#define INCdrvMD90h 1
|
||||||
|
|
||||||
#include "motordrvCom.h"
|
#include "motordrvCom.h"
|
||||||
#include "asynDriver.h"
|
#include "asynDriver.h"
|
||||||
|
|
||||||
/* MCB4B default profile. */
|
/* MD90 default profile. */
|
||||||
|
|
||||||
#define MCB4B_NUM_CARDS 4
|
#define MD90_NUM_CARDS 4
|
||||||
#define MCB4B_NUM_CHANNELS 4
|
#define MD90_NUM_CHANNELS 4
|
||||||
|
|
||||||
#define OUTPUT_TERMINATOR "\r"
|
#define OUTPUT_TERMINATOR "\r"
|
||||||
|
|
||||||
struct MCB4Bcontroller
|
struct MD90controller
|
||||||
{
|
{
|
||||||
asynUser *pasynUser; /* asynUser structure */
|
asynUser *pasynUser; /* asynUser structure */
|
||||||
char port[80]; /* asyn port name */
|
char port[80]; /* asyn port name */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCdrvMCB4Bh */
|
#endif /* INCdrvMD90h */
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
FILENAME... AcsRegister.cc
|
FILENAME... dsmRegister.cc
|
||||||
USAGE... Register ACS motor device driver shell commands.
|
USAGE... Register DSM motor device driver shell commands.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -16,40 +16,40 @@ of this distribution.
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
#include "AcsRegister.h"
|
#include "dsmRegister.h"
|
||||||
#include "epicsExport.h"
|
#include "epicsExport.h"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
||||||
// ACS Setup arguments
|
// DSM Setup arguments
|
||||||
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
|
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
|
||||||
static const iocshArg setupArg1 = {"Polling rate", iocshArgInt};
|
static const iocshArg setupArg1 = {"Polling rate", iocshArgInt};
|
||||||
// ACS Config arguments
|
// DSM Config arguments
|
||||||
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
|
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
|
||||||
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
|
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
|
||||||
|
|
||||||
static const iocshArg * const MCB4BSetupArgs[2] = {&setupArg0, &setupArg1};
|
static const iocshArg * const MD90SetupArgs[2] = {&setupArg0, &setupArg1};
|
||||||
static const iocshArg * const MCB4BConfigArgs[2] = {&configArg0, &configArg1};
|
static const iocshArg * const MD90ConfigArgs[2] = {&configArg0, &configArg1};
|
||||||
|
|
||||||
static const iocshFuncDef setupMCB4B = {"MCB4BSetup", 2, MCB4BSetupArgs};
|
static const iocshFuncDef setupMD90 = {"MD90Setup", 2, MD90SetupArgs};
|
||||||
static const iocshFuncDef configMCB4B = {"MCB4BConfig", 2, MCB4BConfigArgs};
|
static const iocshFuncDef configMD90 = {"MD90Config", 2, MD90ConfigArgs};
|
||||||
|
|
||||||
static void setupMCB4BCallFunc(const iocshArgBuf *args)
|
static void setupMD90CallFunc(const iocshArgBuf *args)
|
||||||
{
|
{
|
||||||
MCB4BSetup(args[0].ival, args[1].ival);
|
MD90Setup(args[0].ival, args[1].ival);
|
||||||
}
|
}
|
||||||
static void configMCB4BCallFunc(const iocshArgBuf *args)
|
static void configMD90CallFunc(const iocshArgBuf *args)
|
||||||
{
|
{
|
||||||
MCB4BConfig(args[0].ival, args[1].sval);
|
MD90Config(args[0].ival, args[1].sval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AcsRegister(void)
|
static void dsmRegister(void)
|
||||||
{
|
{
|
||||||
iocshRegister(&setupMCB4B, setupMCB4BCallFunc);
|
iocshRegister(&setupMD90, setupMD90CallFunc);
|
||||||
iocshRegister(&configMCB4B, configMCB4BCallFunc);
|
iocshRegister(&configMD90, configMD90CallFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
epicsExportRegistrar(AcsRegister);
|
epicsExportRegistrar(dsmRegister);
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
FILENAME... AcsRegister.h
|
FILENAME... dsmRegister.h
|
||||||
USAGE... This file contains function prototypes for ACS IOC shell commands.
|
USAGE... This file contains function prototypes for DSM IOC shell commands.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -37,6 +37,6 @@ USAGE... This file contains function prototypes for ACS IOC shell commands.
|
|||||||
#include "motordrvCom.h"
|
#include "motordrvCom.h"
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
extern RTN_STATUS MCB4BSetup(int, int);
|
extern RTN_STATUS MD90Setup(int, int);
|
||||||
extern RTN_STATUS MCB4BConfig(int, const char *);
|
extern RTN_STATUS MD90Config(int, const char *);
|
||||||
|
|
@@ -1,7 +1,7 @@
|
|||||||
TOP = ..
|
TOP = ..
|
||||||
include $(TOP)/configure/CONFIG
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
DIRS += acsIOC
|
DIRS += dsmIOC
|
||||||
|
|
||||||
include $(TOP)/configure/RULES_TOP
|
include $(TOP)/configure/RULES_TOP
|
||||||
|
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
# Use the following lines if motorAcs was built inside motor
|
|
||||||
MOTOR=
|
|
||||||
-include $(MOTOR)/configure/RELEASE
|
|
||||||
# Use the following lines if motorAcs was built outside motor
|
|
||||||
#!MOTOR_ACS=
|
|
||||||
#!-include $(MOTOR_ACS)/configure/RELEASE.local
|
|
@@ -1,9 +0,0 @@
|
|||||||
file "$(MOTOR)/db/basic_asyn_motor.db"
|
|
||||||
{
|
|
||||||
pattern
|
|
||||||
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
|
||||||
{IOC:, 1, "m$(N)", "asynMotor", MCB4B1, 0, "Bottom", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
|
||||||
{IOC:, 2, "m$(N)", "asynMotor", MCB4B1, 1, "Top", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
|
||||||
{IOC:, 3, "m$(N)", "asynMotor", MCB4B1, 2, "Inboard", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
|
||||||
{IOC:, 4, "m$(N)", "asynMotor", MCB4B1, 3, "Outboard", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
|
||||||
}
|
|
@@ -1,34 +0,0 @@
|
|||||||
#errlogInit(5000)
|
|
||||||
< envPaths
|
|
||||||
|
|
||||||
# Tell EPICS all about the record types, device-support modules, drivers, etc.
|
|
||||||
dbLoadDatabase("../../dbd/acs.dbd")
|
|
||||||
acs_registerRecordDeviceDriver(pdbbase)
|
|
||||||
|
|
||||||
# Port 2 on a Moxa
|
|
||||||
drvAsynIPPortConfigure("serial1", "192.168.1.16:4002",0,0,0)
|
|
||||||
# Local serial port
|
|
||||||
#!drvAsynSerialPortConfigure("serial1", "/dev/ttyS0", 0, 0, 0)
|
|
||||||
asynOctetSetInputEos("serial1",0,"\r")
|
|
||||||
asynOctetSetOutputEos("serial1",0,"\r")
|
|
||||||
asynSetTraceIOMask("serial1", 0, 2)
|
|
||||||
#asynSetTraceMask("serial1", 0, 255)
|
|
||||||
|
|
||||||
MCB4BCreateController("MCB4B1", "serial1", 4, 100, 5000)
|
|
||||||
|
|
||||||
### Motors
|
|
||||||
dbLoadTemplate "motor.substitutions.mcb4b"
|
|
||||||
|
|
||||||
dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=serial1,PORT=serial1,ADDR=0,OMAX=80,IMAX=80")
|
|
||||||
|
|
||||||
iocInit
|
|
||||||
|
|
||||||
# This IOC does not use save/restore, so set values of some PVs
|
|
||||||
dbpf("IOC:m1.RTRY", "0")
|
|
||||||
dbpf("IOC:m1.TWV", "0.1")
|
|
||||||
dbpf("IOC:m2.RTRY", "0")
|
|
||||||
dbpf("IOC:m2.TWV", "0.1")
|
|
||||||
dbpf("IOC:m3.RTRY", "0")
|
|
||||||
dbpf("IOC:m3.TWV", "0.1")
|
|
||||||
dbpf("IOC:m4.RTRY", "0")
|
|
||||||
dbpf("IOC:m4.TWV", "0.1")
|
|
@@ -37,8 +37,8 @@ CHECK_RELEASE = YES
|
|||||||
|
|
||||||
# Include motor's CONFIG_SITE.local when building inside motor
|
# Include motor's CONFIG_SITE.local when building inside motor
|
||||||
-include $(TOP)/../../../../configure/CONFIG_SITE.local
|
-include $(TOP)/../../../../configure/CONFIG_SITE.local
|
||||||
# Include motorAcs's CONFIG_SITE.local when building inside motorAcs
|
# Include motorDsm's CONFIG_SITE.local when building inside motorDsm
|
||||||
-include $(TOP)/../../configure/CONFIG_SITE.local
|
-include $(TOP)/../../configure/CONFIG_SITE.local
|
||||||
# Use acsIOC's CONFIG_SITE.local
|
# Use dsmIOC's CONFIG_SITE.local
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/configure/CONFIG_SITE.local
|
||||||
|
|
6
iocs/dsmIOC/configure/EXAMPLE_RELEASE.local
Normal file
6
iocs/dsmIOC/configure/EXAMPLE_RELEASE.local
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Use the following lines if motorDsm was built inside motor
|
||||||
|
MOTOR=
|
||||||
|
-include $(MOTOR)/configure/RELEASE
|
||||||
|
# Use the following lines if motorDsm was built outside motor
|
||||||
|
#!MOTOR_DSM=
|
||||||
|
#!-include $(MOTOR_DSM)/configure/RELEASE.local
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Use motor/module's generated release file when buidling inside motor
|
# Use motor/module's generated release file when buidling inside motor
|
||||||
-include $(TOP)/../../../RELEASE.$(EPICS_HOST_ARCH).local
|
-include $(TOP)/../../../RELEASE.$(EPICS_HOST_ARCH).local
|
||||||
# Use motorAcs's release file when building inside motorAcs, but outside motor
|
# Use motorDsm's release file when building inside motorDsm, but outside motor
|
||||||
-include $(TOP)/../../configure/RELEASE.local
|
-include $(TOP)/../../configure/RELEASE.local
|
||||||
# Use acsIOC's RELEASE.local when building outside motorAcs
|
# Use dsmIOC's RELEASE.local when building outside motorDsm
|
||||||
-include $(TOP)/configure/RELEASE.local
|
-include $(TOP)/configure/RELEASE.local
|
@@ -11,44 +11,44 @@ include $(TOP)/configure/CONFIG
|
|||||||
#=============================
|
#=============================
|
||||||
# Build the IOC application
|
# Build the IOC application
|
||||||
|
|
||||||
PROD_IOC = acs
|
PROD_IOC = dsm
|
||||||
# acs.dbd will be created and installed
|
# dsm.dbd will be created and installed
|
||||||
DBD += acs.dbd
|
DBD += dsm.dbd
|
||||||
|
|
||||||
# acs.dbd will be made up from these files:
|
# dsm.dbd will be made up from these files:
|
||||||
acs_DBD += base.dbd
|
dsm_DBD += base.dbd
|
||||||
|
|
||||||
# Include dbd files from all support applications:
|
# Include dbd files from all support applications:
|
||||||
#ifdef ASYN
|
#ifdef ASYN
|
||||||
acs_DBD += asyn.dbd
|
dsm_DBD += asyn.dbd
|
||||||
acs_DBD += drvAsynSerialPort.dbd
|
dsm_DBD += drvAsynSerialPort.dbd
|
||||||
acs_DBD += drvAsynIPPort.dbd
|
dsm_DBD += drvAsynIPPort.dbd
|
||||||
#endif
|
#endif
|
||||||
acs_DBD += motorSupport.dbd
|
dsm_DBD += motorSupport.dbd
|
||||||
acs_DBD += devAcsMotor.dbd
|
dsm_DBD += devDsmMotor.dbd
|
||||||
|
|
||||||
# Add all the support libraries needed by this IOC
|
# Add all the support libraries needed by this IOC
|
||||||
acs_LIBS += Acs
|
dsm_LIBS += dsm
|
||||||
acs_LIBS += motor
|
dsm_LIBS += motor
|
||||||
#ifdef ASYN
|
#ifdef ASYN
|
||||||
acs_LIBS += asyn
|
dsm_LIBS += asyn
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNCSEQ
|
#ifdef SNCSEQ
|
||||||
acs_LIBS += seq pv
|
dsm_LIBS += seq pv
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# acs_registerRecordDeviceDriver.cpp derives from acs.dbd
|
# dsm_registerRecordDeviceDriver.cpp derives from dsm.dbd
|
||||||
acs_SRCS += acs_registerRecordDeviceDriver.cpp
|
dsm_SRCS += dsm_registerRecordDeviceDriver.cpp
|
||||||
|
|
||||||
# Build the main IOC entry point on workstation OSs.
|
# Build the main IOC entry point on workstation OSs.
|
||||||
acs_SRCS_DEFAULT += acsMain.cpp
|
dsm_SRCS_DEFAULT += dsmMain.cpp
|
||||||
acs_SRCS_vxWorks += -nil-
|
dsm_SRCS_vxWorks += -nil-
|
||||||
|
|
||||||
# Add support from base/src/vxWorks if needed
|
# Add support from base/src/vxWorks if needed
|
||||||
#acs_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
#dsm_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
||||||
|
|
||||||
# Finally link to the EPICS Base libraries
|
# Finally link to the EPICS Base libraries
|
||||||
acs_LIBS += $(EPICS_BASE_IOC_LIBS)
|
dsm_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||||
|
|
||||||
#===========================
|
#===========================
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
/* acsMain.cpp */
|
/* dsmMain.cpp */
|
||||||
/* Author: Marty Kraimer Date: 17MAR2000 */
|
/* Author: Marty Kraimer Date: 17MAR2000 */
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
28
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90
Normal file
28
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
file "$(MOTOR)/db/basic_asyn_motor.db"
|
||||||
|
{
|
||||||
|
pattern
|
||||||
|
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, VMAX, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
||||||
|
{DSM:, 0, "m$(N)", "asynMotor", MD900, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
# P IOC prefix
|
||||||
|
# N Port number
|
||||||
|
# M Record name pattern
|
||||||
|
# DTYP Datatype
|
||||||
|
# PORT Port
|
||||||
|
# ADDR Address
|
||||||
|
# DESC Description
|
||||||
|
# EGU Engineering units
|
||||||
|
# DIR Direction
|
||||||
|
# VELO Velocity (EGU / s) (note: jog velocity set separately by JVEL)
|
||||||
|
# VBAS Minimum velocity (EGU / s)
|
||||||
|
# VMAX Maximum velocity (EGU / s) (note: not getting set here with basic_asyn_motor.db)
|
||||||
|
# ACCL Acceleration (time in seconds until VELO)
|
||||||
|
# BDST Backlash distance
|
||||||
|
# BVEL Backlash velocity
|
||||||
|
# BACC Backlash acceleration
|
||||||
|
# MRES Motor step size (EGU)
|
||||||
|
# PREC Display precision number of decimal places
|
||||||
|
# DHLM Dial high travel limit (EGU)
|
||||||
|
# DLLM Dial low travel limit (EGU)
|
||||||
|
# INIT Initialization string (seems to be unused/broken)
|
35
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90.multi
Normal file
35
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90.multi
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
file "$(MOTOR)/db/basic_asyn_motor.db"
|
||||||
|
{
|
||||||
|
pattern
|
||||||
|
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, VMAX, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
||||||
|
{DSM:, 0, "m$(N)", "asynMotor", MD900, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 1, "m$(N)", "asynMotor", MD901, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 2, "m$(N)", "asynMotor", MD902, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 3, "m$(N)", "asynMotor", MD903, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 4, "m$(N)", "asynMotor", MD904, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 5, "m$(N)", "asynMotor", MD905, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 6, "m$(N)", "asynMotor", MD906, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
{DSM:, 7, "m$(N)", "asynMotor", MD907, 0, "MD-90", mm, Pos, 1.0, 0.05, 1.0, 0, 0, 0.05, 0, .00001, 2, 20, -20, ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
# P IOC prefix
|
||||||
|
# N Port number
|
||||||
|
# M Record name pattern
|
||||||
|
# DTYP Datatype
|
||||||
|
# PORT Port
|
||||||
|
# ADDR Address
|
||||||
|
# DESC Description
|
||||||
|
# EGU Engineering units
|
||||||
|
# DIR Direction
|
||||||
|
# VELO Velocity (EGU / s) (note: jog velocity set separately by JVEL)
|
||||||
|
# VBAS Minimum velocity (EGU / s)
|
||||||
|
# VMAX Maximum velocity (EGU / s) (note: not getting set here with basic_asyn_motor.db)
|
||||||
|
# ACCL Acceleration (time in seconds until VELO)
|
||||||
|
# BDST Backlash distance
|
||||||
|
# BVEL Backlash velocity
|
||||||
|
# BACC Backlash acceleration
|
||||||
|
# MRES Motor step size (EGU)
|
||||||
|
# PREC Display precision number of decimal places
|
||||||
|
# DHLM Dial high travel limit (EGU)
|
||||||
|
# DLLM Dial low travel limit (EGU)
|
||||||
|
# INIT Initialization string (seems to be unused/broken)
|
@@ -1,24 +1,24 @@
|
|||||||
#!../../bin/linux-x86_64/acs
|
#!../../bin/linux-x86_64/dsm
|
||||||
|
|
||||||
< envPaths
|
< envPaths
|
||||||
|
|
||||||
cd "${TOP}"
|
cd "${TOP}"
|
||||||
|
|
||||||
## Register all support components
|
## Register all support components
|
||||||
dbLoadDatabase "dbd/acs.dbd"
|
dbLoadDatabase "dbd/dsm.dbd"
|
||||||
acs_registerRecordDeviceDriver pdbbase
|
dsm_registerRecordDeviceDriver pdbbase
|
||||||
|
|
||||||
cd "${TOP}/iocBoot/${IOC}"
|
cd "${TOP}/iocBoot/${IOC}"
|
||||||
|
|
||||||
|
|
||||||
## motorUtil (allstop & alldone)
|
## motorUtil (allstop & alldone)
|
||||||
dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=acs:")
|
dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=dsm:")
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
||||||
iocInit
|
iocInit
|
||||||
|
|
||||||
## motorUtil (allstop & alldone)
|
## motorUtil (allstop & alldone)
|
||||||
motorUtilInit("acs:")
|
motorUtilInit("dsm:")
|
||||||
|
|
||||||
# Boot complete
|
# Boot complete
|
39
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90
Normal file
39
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#errlogInit(5000)
|
||||||
|
< envPaths
|
||||||
|
|
||||||
|
# Tell EPICS all about the record types, device-support modules, drivers, etc.
|
||||||
|
dbLoadDatabase("../../dbd/dsm.dbd")
|
||||||
|
dsm_registerRecordDeviceDriver(pdbbase)
|
||||||
|
|
||||||
|
# Network device
|
||||||
|
#!drvAsynIPPortConfigure("serial0", "192.168.1.16:4002",0,0,0)
|
||||||
|
# Local serial port
|
||||||
|
drvAsynSerialPortConfigure("serial0", "/dev/ttyUSB0", 0, 0, 0)
|
||||||
|
asynSetOption("serial0", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial0", 0, "bits", "8")
|
||||||
|
asynSetOption("serial0", 0, "parity", "none")
|
||||||
|
asynSetOption("serial0", 0, "stop", "1")
|
||||||
|
|
||||||
|
asynOctetSetInputEos("serial0", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial0", 0, "\r")
|
||||||
|
asynSetTraceIOMask("serial0", 0, 2)
|
||||||
|
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial0", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
|
||||||
|
MD90CreateController("MD900", "serial0", 1, 100, 5000)
|
||||||
|
|
||||||
|
### Motors
|
||||||
|
dbLoadTemplate "motor.substitutions.md90"
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial0,PORT=serial0,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
|
||||||
|
iocInit
|
||||||
|
|
||||||
|
# This IOC does not use save/restore, so set values of some PVs
|
||||||
|
dbpf("DSM:m0.RTRY", "0")
|
||||||
|
dbpf("DSM:m0.TWV", "0.1")
|
||||||
|
dbpf("DSM:m0.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m0.HVEL", "1.0")
|
186
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90.multi
Normal file
186
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90.multi
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#errlogInit(5000)
|
||||||
|
< envPaths
|
||||||
|
|
||||||
|
# Tell EPICS all about the record types, device-support modules, drivers, etc.
|
||||||
|
dbLoadDatabase("../../dbd/dsm.dbd")
|
||||||
|
dsm_registerRecordDeviceDriver(pdbbase)
|
||||||
|
|
||||||
|
# Unfortunately, iocsh doesn't support looping...
|
||||||
|
|
||||||
|
# Local serial port
|
||||||
|
drvAsynSerialPortConfigure("serial0", "/dev/ttyUSB0", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial1", "/dev/ttyUSB1", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial2", "/dev/ttyUSB2", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial3", "/dev/ttyUSB3", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial4", "/dev/ttyUSB4", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial5", "/dev/ttyUSB5", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial6", "/dev/ttyUSB6", 0, 0, 0)
|
||||||
|
drvAsynSerialPortConfigure("serial7", "/dev/ttyUSB7", 0, 0, 0)
|
||||||
|
|
||||||
|
asynSetOption("serial0", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial1", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial2", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial3", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial4", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial5", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial6", 0, "baud", "115200")
|
||||||
|
asynSetOption("serial7", 0, "baud", "115200")
|
||||||
|
|
||||||
|
asynSetOption("serial0", 0, "bits", "8")
|
||||||
|
asynSetOption("serial1", 0, "bits", "8")
|
||||||
|
asynSetOption("serial2", 0, "bits", "8")
|
||||||
|
asynSetOption("serial3", 0, "bits", "8")
|
||||||
|
asynSetOption("serial4", 0, "bits", "8")
|
||||||
|
asynSetOption("serial5", 0, "bits", "8")
|
||||||
|
asynSetOption("serial6", 0, "bits", "8")
|
||||||
|
asynSetOption("serial7", 0, "bits", "8")
|
||||||
|
|
||||||
|
asynSetOption("serial0", 0, "parity", "none")
|
||||||
|
asynSetOption("serial1", 0, "parity", "none")
|
||||||
|
asynSetOption("serial2", 0, "parity", "none")
|
||||||
|
asynSetOption("serial3", 0, "parity", "none")
|
||||||
|
asynSetOption("serial4", 0, "parity", "none")
|
||||||
|
asynSetOption("serial5", 0, "parity", "none")
|
||||||
|
asynSetOption("serial6", 0, "parity", "none")
|
||||||
|
asynSetOption("serial7", 0, "parity", "none")
|
||||||
|
|
||||||
|
asynSetOption("serial0", 0, "stop", "1")
|
||||||
|
asynSetOption("serial1", 0, "stop", "1")
|
||||||
|
asynSetOption("serial2", 0, "stop", "1")
|
||||||
|
asynSetOption("serial3", 0, "stop", "1")
|
||||||
|
asynSetOption("serial4", 0, "stop", "1")
|
||||||
|
asynSetOption("serial5", 0, "stop", "1")
|
||||||
|
asynSetOption("serial6", 0, "stop", "1")
|
||||||
|
asynSetOption("serial7", 0, "stop", "1")
|
||||||
|
|
||||||
|
asynOctetSetInputEos("serial0", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial1", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial2", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial3", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial4", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial5", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial6", 0, "\r")
|
||||||
|
asynOctetSetInputEos("serial7", 0, "\r")
|
||||||
|
|
||||||
|
asynOctetSetOutputEos("serial0", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial1", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial2", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial3", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial4", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial5", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial6", 0, "\r")
|
||||||
|
asynOctetSetOutputEos("serial7", 0, "\r")
|
||||||
|
|
||||||
|
asynSetTraceIOMask("serial0", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial1", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial2", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial3", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial4", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial5", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial6", 0, 2)
|
||||||
|
asynSetTraceIOMask("serial7", 0, 2)
|
||||||
|
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial0", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial1", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial2", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial3", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial4", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial5", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial6", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
# Turn on the power supply and set the deadband
|
||||||
|
asynOctetConnect("initConnection", "serial7", 0)
|
||||||
|
asynOctetWrite("initConnection", "EPS")
|
||||||
|
asynOctetWrite("initConnection", "SDB 10")
|
||||||
|
asynOctetDisconnect('initConnection')
|
||||||
|
|
||||||
|
MD90CreateController("MD900", "serial0", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD901", "serial1", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD902", "serial2", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD903", "serial3", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD904", "serial4", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD905", "serial5", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD906", "serial6", 1, 100, 5000)
|
||||||
|
MD90CreateController("MD907", "serial7", 1, 100, 5000)
|
||||||
|
|
||||||
|
### Motors
|
||||||
|
dbLoadTemplate "motor.substitutions.md90.multi"
|
||||||
|
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial0,PORT=serial0,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial1,PORT=serial1,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial2,PORT=serial2,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial3,PORT=serial3,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial4,PORT=serial4,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial5,PORT=serial5,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial6,PORT=serial6,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial7,PORT=serial7,ADDR=0,OMAX=80,IMAX=80")
|
||||||
|
|
||||||
|
iocInit
|
||||||
|
|
||||||
|
# This IOC does not use save/restore, so set values of some PVs
|
||||||
|
dbpf("DSM:m0.RTRY", "0")
|
||||||
|
dbpf("DSM:m0.TWV", "0.1")
|
||||||
|
dbpf("DSM:m0.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m0.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m1.RTRY", "0")
|
||||||
|
dbpf("DSM:m1.TWV", "0.1")
|
||||||
|
dbpf("DSM:m1.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m1.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m2.RTRY", "0")
|
||||||
|
dbpf("DSM:m2.TWV", "0.1")
|
||||||
|
dbpf("DSM:m2.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m2.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m3.RTRY", "0")
|
||||||
|
dbpf("DSM:m3.TWV", "0.1")
|
||||||
|
dbpf("DSM:m3.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m3.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m4.RTRY", "0")
|
||||||
|
dbpf("DSM:m4.TWV", "0.1")
|
||||||
|
dbpf("DSM:m4.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m4.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m5.RTRY", "0")
|
||||||
|
dbpf("DSM:m5.TWV", "0.1")
|
||||||
|
dbpf("DSM:m5.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m5.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m6.RTRY", "0")
|
||||||
|
dbpf("DSM:m6.TWV", "0.1")
|
||||||
|
dbpf("DSM:m6.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m6.HVEL", "1.0")
|
||||||
|
|
||||||
|
dbpf("DSM:m7.RTRY", "0")
|
||||||
|
dbpf("DSM:m7.TWV", "0.1")
|
||||||
|
dbpf("DSM:m7.VMAX", "1.0")
|
||||||
|
dbpf("DSM:m7.HVEL", "1.0")
|
Reference in New Issue
Block a user