Triamec > Produkte > Software > Matlab

TAM mit Matlab ansprechen

Das TAM SDK ist so konzipiert, dass es auch aus der Matlab®-Umgebung von MathWorks benutzt werden kann. Mit dieser Möglichkeit kann mit einem Matlab Skript auf einfache Weise zum Beispiel ein Testablauf oder eine Messung realisiert werden. Alle Methoden, die das TAM SDK anbietet, können auch aus Matlab angesprochen werden. Weiter besteht die Möglichkeit, mittels Matlab Berechnungen und Analysen mit den Daten eines Triamec Servo-Drives oder I/O-Controllers durchzuführen oder die Daten zu visualisieren.

Auf ähnliche Weise wurden auch Integrationen in National Instruments LabVIEW durchgeführt.

Funktionen der Matlab Schnittstelle

Triamec TAM SDK
TAM Benutzung aus Matlab
  • Transparente Tria-Link-Kommunikation
  • Anwendungen in Matlab Skript Sprache
  • Zyklischer Datenaustausch mit Triggern
  • Zustandsbeobachtung und Events
  • Motion-Befehle (in Anlehnung an PLCopen)
  • Berechnungen und Visualisierung

Anwendungen

  • Test- und Prüfaufbauten.

Installation

Die Matlab Skripte und Beispiele sind zusammen mit dem TAM SDK als ZIP-Archiv hier herunterladbar.

Matlab Skript Beispiele

Einige Beispiele sind im folgenden aufgeführt, weitere werden zusammen mit dem TAM SDK installiert.

Reiter 1: DemoScript.m: Hauptprogramm
Reiter 2: LoadTam.m: Laden der TAM SDK Bibliothek
Reiter 3: SetupTam.m: Triamec Hardware initialisieren und konfigurieren
Reiter 4: DemonstrateTam.m: Zeigt oft verwendete Funktionalitäten

  • DemoScript
  • LoadTam
  • SetupTam
  • DemonstrateTam

Demo Script

% DemoScript
% Sequential version of GUI Demo

% $Id: DemoScript.m 16549 2014-02-06 07:48:48Z chm $
% Copyright © 2011 Triamec Motion AG, Switzerland

%% Load TAM .NET API.
LoadTam('C:\test\Tam4Matlab\SDK');

%% Setup the topology.
%topology = SetupTam('NB-T400.xml',false);
topology = SetupTam('C:\test\Tam4Matlab\SDK\eBergerLahr_SER3913_Bldc.TAMcfg',false);

%% Work with the explorer simultaneously (uncomment to use)
% explorer = Triamec.Tam.UI.TamExplorerForm;
% explorer.Topology = topology;
% explorer.Show;

try
%% Do something useful with it
    % The addresses need to relate to what is saved in the TAM
    % configuration file specified above.
%    DemonstrateTam(topology, 'tam://localhost/Adapter/Link/', 'Lastmotor/Drive/', 'TIOB/Drive');
    DemonstrateTam(topology, 'tam://localhost/TLC201/Link/', 'TS350/Device/');
catch ME
    ShowExceptionMessage(ME);
end

%% Dispose of the topology.
TeardownTam(topology);

LoadTam

function LoadTam(tamDir)
%LOADTAM    pre-loads the TAM SDK library.
%
%   LOADTAM(PATH) Pre-loads the TAM SDK library from directory PATH
%   such that its classes may be used in other functions.
%
%   If you try to import or use members from a .NET API from a library
%   which is not yet loaded, you will get an error. Trying to load the
%   right library in the same function as referencing types from it is not
%   possible.
%
%   Please consult the TAM API Class Library and the available
%   MATLAB samples for getting started.
%   Use the TAM System Explorer in order to create TAM configuration files
%   and to learn about existing registers.
%
%   CAUTION: The register layout libraries need to resist also in the
%   specified PATH which is *not* the case with the standard installation
%   of the TAM SDK.
%
%   See also SETUPTAM.

% $Id: LoadTam.m 17389 2014-05-23 13:06:35Z chm $
% Copyright © 2011 Triamec Motion AG, Switzerland

%% Sanity checks
error(nargchk(1,1,nargin));

%% Imports
import System.IO.*

%% .NET 3.5 reference
% Only used for certain APIs, like Triamec.Tam.Acquisitions.
NET.addAssembly('System.Core');

%% Reference TAM SDK
% This works when tamDir is relative to the current working directory, or
% absolute.
try
    NET.addAssembly(char(Path.Combine(Directory.GetCurrentDirectory, Path.Combine(tamDir, 'Tam.dll'))));
    NET.addAssembly(char(Path.Combine(Directory.GetCurrentDirectory, Path.Combine(tamDir, 'Tam.UI.dll'))));
    NET.addAssembly(char(Path.Combine(Directory.GetCurrentDirectory, Path.Combine(tamDir, 'Tam.Simulation.dll'))));
    NET.addAssembly(char(Path.Combine(Directory.GetCurrentDirectory, Path.Combine(tamDir, 'ModuleCatalog.dll'))));
catch ex
    if ~isa(ex, 'NET.NetException') || ~isa(ex.ExceptionObject, 'System.Reflection.ReflectionTypeLoadException')
        rethrow(ex);
    else
        loaderExs = ex.ExceptionObject.LoaderExceptions;
        l = loaderExs.Length;
        msgs = cell(1,l);
        for i = 1:l, msgs{i} = char(loaderExs(i).Message); end
        msgs=unique(msgs);
        for i = 1:length(msgs), fprintf('%s\n', msgs{i}); end
        throw(MException('TAM:load', 'Provide the specified assemblies and RESTART MATLAB!'));
    end
end

SetupTam

function topo = SetupTam(configurationPath,simulated)
%SETUPTAM    initializes Triamec hardware and applies a TAM configuration.
%
%   Some behavior of the TAM library is configurable through .NET
%   application configuration. When needing to change some configuration, 
%   place it in a file MATLAB.exe.config beneath your MATLAB executable.
%   If it does not exist, default values are used.
%   In order to change defaults, you may copy the TAM System Explorer
%   configuration file (TamSystemExplorer.exe.config) from the TAM SDK
%   installation path for a good starting point.
%   CAUTION: There are different executables called MATLAB.exe. Use the
%   Windows task manager to find out which one is running.
%
%   Before calling this function the first time, LOADTAM has to be called.
%   Subsequent calls may be issued directly.
%    
%   T = SETUPTAM(PATH) returns the TAM topology T. All Tria-Link adapters
%   are booted, and the TAM configuration located at PATH has been
%   downloaded.
%   If PATH is omitted, no configuration is loaded.
%    
%   See also LOADTAM, TEARDOWNTAM.

% $Id: SetupTam.m 18916 2014-11-03 09:39:41Z chm $
% Copyright © 2011 Triamec Motion AG, Switzerland

% ----------------------------------------------------------------------------------------------------------------------
%% Imports
import System.*
import System.IO.*
import Triamec.Tam.*
import Triamec.Tam.Configuration.*
import Triamec.Tam.Periphery.*
import Triamec.TriaLink.*
import Triamec.TriaLink.Adapter.Simulation.*

simTypeName = 'Triamec.TriaLink.Adapter.ITriaLinkAdapter';

%% Create root of the TAM hierarchy.
% Note: The indexes might needed to be changed on your system
topo = Triamec.Tam.TamTopology('My topology');

%% Initialize and load configuration
try
    %% Set up simulation
    if nargin > 1 && simulated
        deserializer = Deserializer;
        loadResult = deserializer.Load(configurationPath);
        if isempty(loadResult.Errors)
            
            % CreateSimulatedTriaLinkAdapters returns
            % SimulatedTriaLinkAdapter[], where AddLocalTamSystem requires
            % ISimulatedTriaLinkAdapters[]. Unlike in .NET, MATLAB does not
            % recognize that the former is assignment compatible to the
            % latter type. So we must do it manually, and we only pass the
            % first adapter found in the TAM configuration.
            simulatedAdapters = NET.createArray(simTypeName, 1);
            concreteSimulatedAdapters = ...
                SimulationFactory.CreateSimulatedTriaLinkAdapters( ...
                deserializer.Configuration, []);
            simulatedAdapters.SetValue( ...
                concreteSimulatedAdapters.GetValue(0), 0);
        else
            simulatedAdapters = NET.createArray(simTypeName, 0);
        end
        deserializer.Dispose
    else
        simulatedAdapters = NET.createArray(simTypeName, 0);
    end
    
    %% Find and initialize TAM adapter(s)
    % Find the TAM adapter(s) installed on the local computer.
    % Note: [] is used to pass a null reference
    system = topo.AddLocalTamSystem('My system', simulatedAdapters);

    % Boot TAM system, that is, find all stations in the Tria-Link.
    display('Initialize TAM system.');
    system.Initialize;
    
    %% Load a TAM configuration.
    if nargin > 0
        disp(['Load TAM configuration from ' configurationPath '.']);
        try
            topo.Load(configurationPath);
        catch ex
            ShowExceptionMessage(ex);    
            return
        end
    else
        display('No TAM configuration is loaded.');
    end
catch ME
    % If an unhandled exception occurred, always call this method in order to cleanup the TAM system
    topo.Dispose;
    
    ShowExceptionMessage(ME);
    
    rethrow(ME);
end

DemonstrateTam

function DemonstrateTam(topo,linkAddress,driveAddress,tiobAddress)
%DEMONSTRATETAM    shows some of the most often used functionality.
%
%   DEMONSTRATETAM
%   - reads and writes registers.
%   - does some motion.
%   - acquires and plots some data.
%   - accesses the FPGA local-bus (advanced).
%
%   DEMONSTRATETAM does not
%   - check for errors in general.
%
%   DEMONSTRATETAM(T,LADR,DADR,TADR) shows the demo using the TAM topology
%   T. Within the topology, it uses the Tria-Link with address LADR. Within
%   the Tria-Link, it uses the drive with address DADR, and the I/O board
%   with address TADR.
%   LADR, DADR and optionally TADR are to be passed as strings.
%   LADR must be absolute while DADR and TADR may be specified relatively
%   to LADR.
%
%   See also SETUPTAM, LOADTAM.

% $Id: DemonstrateTam.m 18279 2014-08-26 07:19:27Z chm $
% Copyright © 2011 Triamec Motion AG, Switzerland

%% Register some packages
import System.*
import System.IO.*
import Triamec.Tam.*
import Triamec.Tam.Configuration.*
import Triamec.Tam.Periphery.*
import Triamec.TriaLink.*
import Triamec.Tam.Modules.*
import Triamec.Tam.Requests.*

%% Find TAM nodes to work with
linkUri = Uri(linkAddress);
driveUri = Uri(linkUri, driveAddress);
if nargin > 3
    tiobUri = Uri(linkUri, tiobAddress);
end

% Navigate down the hierarchy. .NET indexers are available as Item
% function.
%adapter = system.Item(0);
%link = adapter.Item(0);
%station = link.Item(0);
%device = station.Item(0);

% Alternative: navigate to an address as defined in the TAM
% configuration file.
device = topo.FindTamNode(driveUri);
if nargin > 3
    tiob = topo.FindTamNode(tiobUri);
end
station = device.Station;
axis = device.Axes.Item(0);
axisReg = device.Register.Axes.Item(0);

%% Register a state observer to the device.
% This enables the usage of the WaitForTermination methods below
observer = System.Object;
device.AddStateObserver(observer);

%%
try
    %% Enable Endat
    % endatControl = EndatControl(axis);
    % endatControl.SetToPositionControlModeUsingEndat;
    
    %% Work with drive     
    % Set drive operational
    % and wait until the request has terminated.
    WaitForTermination(device,device.SwitchBridgePower(BridgePowerSwitch.On),'Bridge enable failed');

    % Enable axis
    WaitForTermination(device,axis.Control(AxisControlCommands.ResetErrorAndEnable),'Axis enable failed');

    % Move and wait until the move has terminated
    WaitForTermination(device,axis.MoveRelative(Float40.FromDouble(45)),'Move failed');

    %% Work with registers
    % Write velocity
    axisReg.Parameters.PathPlanner.VelocityMaximum.Write(20);

    % Need to commit changed parameters
    axisReg.Parameters.PathPlanner.Commit;

    % Read Float40 register (only position registers are typically Float40)
    display(['Actual position: ', num2str(Float40.ToDouble(axisReg.Signals.PositionController.ActualPosition.Read))]);
    
    % Read float register
    if nargin > 3
        display(['TIOB Analog input 1: ', num2str(tiob.Register.General.Signals.AnalogInput1.Read), 'V']);
    end

    %% Acquire some signals
    % import all classes from the Acquisition namespace
    import Triamec.Tam.Acquisitions.*

    % create acquisition parameters without trigger and fastest possible sampling rate
    samplingTime = TimeSpan(double(TimeSpan.TicksPerSecond)/50000);
    sampleCount = 500000;
    samplingDuration = samplingTime.TotalSeconds * sampleCount;

    % create the variable to acquire
    variable = CreateVariable(axisReg.Signals.General.ActualCurrentA, samplingTime);

    % create a trigger signal (only when not acquiring unconditionally)
    % trigger = TamTrigger(axisReg.Signals.PathPlanner.Done, ...
    %    PublicationCommand.FallingEdge, TamValue32.FromBool(true));

    % alternative: subscribe a stimulus in order to start the acquisition 
    % (requires MATLAB R2010b)
    % trigger = TamTrigger(axisReg.Signals.PathPlanner.Done, ...
    %    PublicationCommand.FallingEdge, TamValue32.FromBool(true), ...
    %    Stimulus(@() MoveRelative(axis, 20)), ...
    %    TimeSpan.FromSeconds(1));

    % do acquiring
    Acquire(variable, samplingDuration);
    
    % alternative: with trigger:
    % Acquire(variable, samplingDuration, trigger);
    
    % alternative to acquire multiple variables synchronized
    % twoVars = NET.createArray('Triamec.Tam.Acquisitions.ITamVariable', 2);
    % twoVars(1) = variable1;
    % twoVars(2) = variable2;
    % acquisition = TamAcquisition.Create(twoVars);
    % acquisition.Acquire(samplingDuration, trigger);
    % acquisition.Dispose;

    % copy result
    data = GetDataFromVariable(variable);

    % get actual sample time (should equal the samplingTime variable)
    d = variable.SamplingTime.TotalSeconds;

    % plot
    t = 0:d:d*(sampleCount-1);
    plot(t, data);
    xlabel('t [s]');

    %% Access periphery (FPGA local-bus)
    % Make sure the specific local-bus device exists on the adapter
    if station.Periphery.Contains(PeripheryDeviceIdentification.Pwm)
        pwmDevice = station.Periphery.GetDevice(PeripheryDeviceIdentification.Pwm);
        
        % create a periphery register on the fly, using information from
        % the FPGA data sheet. PWM, address 3 = whether economic mode is
        % enabled.
        % Other Types: Periphery-UInt,-MInt,-SInt,-Float
        reg = PeripheryBool(pwmDevice,'Economic Mode','',PeripheryAccess.ReadWrite,3,0);
        if(reg.ReadValue)
            disp('Economic PWM mode enabled.');
        else
            disp('Economic PWM mode not enabled.');
        end        
    else
        disp('No PWM local-bus device found this station -> cannot demonstrate periphery.');
    end
    
    DisplayDriveState(device);
    
    %% Power off
    axis.Control(AxisControlCommands.Disable).WaitForTermination;
    device.SwitchBridgePower(BridgePowerSwitch.Off).WaitForTermination;
catch ME
    device.RemoveStateObserver(observer);
    rethrow(ME);
end

% give back resources
device.RemoveStateObserver(observer);