Beispielprogramm Acquisition
using System;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using Triamec.Acquisitions;
using Triamec.Tam.Acquisitions;
using Triamec.Tam.Registers;
using Triamec.Tam.Samples.Properties;
using Triamec.Tam.UI;
using Triamec.TriaLink;
using Axis = Triamec.Tam.Rlid4.Axis;
namespace Triamec.Tam.Samples {
sealed partial class AcquisitionForm : Form {
#region Fields
TamTopology _topology;
ITamDrive _drive;
TamAxis _axis;
ITamAcquisition _acquisition;
ITamVariable<double> _positionVariable, _positionErrorVariable;
ITamTrigger _trigger;
#endregion Fields
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="AcquisitionForm"/> class.
/// </summary>
public AcquisitionForm() {
InitializeComponent();
}
#endregion Constructor
#region Acquisition demo code
/// <summary>
/// Prepares the TAM system.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item><description>Creates a TAM topology,</description></item>
/// <item><description>boots the Tria-Link,</description></item>
/// <item><description>searches for a TS151 servo-drive,</description></item>
/// <item><description>loads and applies a TAM configuration,</description></item>
/// <item><description>creates the acquisition.</description></item>
/// </list>
/// </remarks>
/// <exception cref="TamException">Startup failed.</exception>
void Startup() {
// Create the root object representing the topology of the TAM hardware.
// Note that we must dispose this object at the end in order to clean up resources.
_topology = new TamTopology("Tutorial");
// Add the local TAM system on this PC to the topology.
var system = _topology.AddLocalTamSystem(null);
// Get the (first) Tria-Link on the (first) PCI Adapter of the local TAM system.
var link = system[0][0];
// Boot the Tria-Link so that it learns about connected stations.
// Note that you may use the more robust Initialize() when the Tria-Link adapter isn't an observer
// (see link.Adapter.Role).
link.Identify();
// Find the (first) TS151 drive in the Tria-Link.
// Iterate over the stations one by one
// because the Tria-Link booting does not guarantee a particular order.
foreach (var station in link) {
if (station.HardwareIdDetails.ProductType == ProductType.FromName("TS151")) {
// found a drive to work with
_drive = station.Devices[0] as ITamDrive;
break; // out of foreach loop
}
}
if (_drive == null) throw new TamException("Drive not found.");
// Load a TAM configuration using a GUI.
// Alternatively, an instance of the Triamec.Tam.Configuration.Deserializer class can be
// instantiated, giving more possibilities.
LoadSurveyor.Load(Settings.Default.TamConfigurationPath, _topology, true, true, this);
// Get its first (and only) axis of the found drive.
_axis = _drive.Axes[0];
Axis axisRegister = (Axis)_drive.Axes[0].Register;
// Create two acquisition variables for position and position error.
// Specify 0 for the sampling time, which will be rounded to the lowest possible sampling time.
ITamReadonlyRegister posReg = axisRegister.Signals.PositionController.ActualPosition;
_positionVariable = posReg.CreateVariable(TimeSpan.FromSeconds(0));
ITamReadonlyRegister errorReg = axisRegister.Signals.PositionController.PositionError;
_positionErrorVariable = errorReg.CreateVariable(TimeSpan.FromSeconds(0));
// As soon as multiple variables are to be recorded synchronized, create an acquisition object.
// Otherwise, you may use the Acquire methods of the variable itself.
_acquisition = TamAcquisition.Create(_positionVariable, _positionErrorVariable);
}
/// <exception cref="TamException">Enabling failed.</exception>
void EnableDrive() {
// Prepare for the use of the WaitForTermination method.
_drive.AddStateObserver(this);
// Set the drive operational, i.e. switch the power section on.
_drive.SwitchOn().WaitForTermination();
// Enable the axis controller.
_axis.Control(AxisControlCommands.Enable).WaitForTermination();
}
/// <exception cref="TamException">Disabling failed.</exception>
void DisableDrive() {
// Disable the axis controller.
_axis.Control(AxisControlCommands.Disable).WaitForTermination();
// Switch the power section off.
_drive.SwitchOff().WaitForTermination();
// Counter part for AddStateObserver.
_drive.RemoveStateObserver(this);
}
/// <summary>
/// Plots one data series.
/// </summary>
static void Fill(Series series, ITamVariable<double> variable, double scaling) {
DataPointCollection points = series.Points;
points.SuspendUpdates();
points.Clear();
foreach (double value in variable) {
points.AddY(value * scaling);
}
points.ResumeUpdates();
}
/// <summary>
/// Called when an acquisition completes.
/// </summary>
/// <remarks>Must be called on the main thread.</remarks>
void OnAcquired(bool hasMore, AcquisitionException ex) {
// don't plot anymore if the form is already closed
if (!Visible) return;
if (ex == null) {
// plot
Fill(chart.Series["Position"], _positionVariable, 1);
Fill(chart.Series["Position Error"], _positionErrorVariable, 1E3);
// repeat recording
Acquire();
} else {
MessageBox.Show(ex.Message, "Failure during acquisition", MessageBoxButtons.OK,
MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0);
}
}
/// <summary>
/// Start an acquisition.
/// </summary>
/// <remarks>Must be called on the main thread.</remarks>
void Acquire() {
// Start asynchronously in order to not block the main thread.
// pass a delegate to the method OnAcquired called when acquire completes.
// The delegate will be called using the synchronization context of this thread.
_acquisition.AcquireAsync(TimeSpan.FromMilliseconds(trackBarDuration.Value), _trigger,
new AcquireFuture(OnAcquired));
}
/// <summary>
/// Recreates the trigger from a new value.
/// </summary>
/// <remarks>Must be called on the main thread.</remarks>
void RefreshTrigger() {
// Create a hardware trigger on velocity with raising edge on the level dictated by the trigger level
// track bar.
_trigger = new TamTrigger(((Axis)_axis.Register).Signals.PathPlanner.Velocity, PublicationCommand.RaisingEdge,
(float)trackBarTriggerLevel.Value);
}
/// <summary>
/// Does some work with a drive.
/// </summary>
void Worker() {
#region Preparation
// create topology, boot system, find drive
Startup();
if (_drive == null) return;
EnableDrive();
// Call the next two methods on the GUI thread as required.
// The ThreadStart delegate is set to an anonymous method constructed from a lambda expression.
BeginInvoke(new ThreadStart(() => { RefreshTrigger(); Acquire(); }));
#endregion Preparation
#region Work
// move forth and back
// stop moving when the form is closed
while (Visible) {
// command moves and wait until the moves are completed
_axis.MoveRelative(1).WaitForTermination();
_axis.MoveRelative(-1).WaitForTermination();
// ensure _terminate is fresh
Thread.MemoryBarrier();
}
#endregion Work
#region Tear down
DisableDrive();
_acquisition.Dispose();
_topology.Dispose();
#endregion Tear down
}
#endregion Acquisition demo code
// rest of application
}
}