UnderAutomation
Une question ?

[email protected]

Contactez-nous
UnderAutomation
⌘Q
ABB SDK documentation
Start & stop a RAPID program
Documentation home

Read & write I/O signals

Read and write digital, analog and group I/O signals of an ABB controller, pulse a signal and simulate one during tests.

Reading an I/O signal of an ABB controller is robot.Rws.Io.GetSignal(network, device, signal), and writing one is robot.Rws.Io.SetSignalValue(network, device, signal, value). Digital, analog and group signals all go through the same two methods, only the value changes. I/O needs no mastership, it needs a user account with the write grant.

AVAILABLE ON
RWS 1.0
RWS 2.0

How a signal is identified

A signal has three parts: the network it belongs to, the device it is connected to, and its name. Local is the internal network of the controller, and the signals of the robot itself are usually on it.

IoSignalItem.Path gives the three parts joined, for example Local/Board10/DO_Gripper. If you only know the name of a signal, find its network and its device with GetSignals() or with a search.

Read a signal

// A signal is identified by its network, its device and its name
IoSignalItem signal = robot.Rws.Io.GetSignal("Local", "Board10", "DO_Gripper");
Console.WriteLine(signal.Path); // Local/Board10/DO_Gripper
Console.WriteLine(signal.Type); // DigitalOutput
Console.WriteLine(signal.LogicalValue); // 1
Console.WriteLine(signal.LogicalState); // NotSimulated
Console.WriteLine(signal.PhysicalValue); // 1
Console.WriteLine(signal.PhysicalState); // Valid
// Every signal of the controller, in one call
IoSignalItem[] signals = robot.Rws.Io.GetSignals();
foreach (IoSignalItem item in signals)
{
Console.WriteLine($"{item.Path} = {item.LogicalValue} ({item.Type})");
}

A signal has two values. LogicalValue is what the program and the network see. PhysicalValue is what the device really carries. They differ when the signal is simulated, or inverted in the configuration. LogicalState says whether the signal is simulated, PhysicalState whether the value can be trusted.

GetSignals() returns every signal of the controller in one request. It is the fast way to build a table, but it carries only the name, the type, the category, the logical value and the logical state. Call GetSignal on one signal to get everything.

Digital, analog and group

IoSignalTypeValueWritten with
DigitalInput, DigitalOutput0 or 1SetSignalValue(..., 1)
AnalogInput, AnalogOutputany value inside the configured rangeSetSignalValue(..., 12.5f)
GroupInput, GroupOutputthe integer made of the bits of the groupSetSignalValue(..., 5)

LogicalValue is a float?, and SetSignalValue takes a float. A group of 4 bits written with the value 5 sets the bits 1 and 3. IoSignalConfiguration.SignalBits gives the width of a group.

Write a signal

Only an output can be written, unless the input is simulated. Writing a read only signal fails with an RwsException.

// A digital signal takes 0 or 1
robot.Rws.Io.SetSignalValue("Local", "Board10", "DO_Gripper", 1);
// An analog or a group signal takes any value inside its range
robot.Rws.Io.SetSignalValue("Local", "Board10", "AO_Speed", 12.5f);
// The last argument writes the change in the event log of the controller
robot.Rws.Io.SetSignalValue("Local", "Board10", "DO_Gripper", 0, true);
// The controller applies the value 500 ms later, and answers immediately
robot.Rws.Io.SetSignalValueDelayed("Local", "Board10", "DO_Gripper", 1, 500);

Pulse, toggle and invert

A pulse is done by the controller, which is more precise than two writes separated by a Thread.Sleep in your application.

// Three pulses to 1, 200 ms active and 200 ms passive
robot.Rws.Io.PulseSignal("Local", "Board10", "DO_Gripper", 1, 3, 200, 200);
// Same, with the pulse lengths configured on the controller
robot.Rws.Io.PulseSignal("Local", "Board10", "DO_Gripper", 1, 1);
// Toggle pulses the signal by starting from the opposite of its current value
robot.Rws.Io.ToggleSignal("Local", "Board10", "DO_Gripper", 1, 2, 200, 200);
// Invert writes the opposite of the current value, once
robot.Rws.Io.InvertSignal("Local", "Board10", "DO_Gripper", 1);

Wait for a signal

There is no subscription in this SDK, a value is read by asking for it. To wait for an input, poll it with a period and a timeout. 200 ms is a reasonable period, a shorter one loads the controller for nothing.

// Ask the robot to work, then wait for its answer
robot.Rws.Io.SetSignalValue("Local", "Board10", "DO_Start", 1);
if (!WaitValue(robot, "Local", "Board10", "DI_Done", 1, 10000))
throw new Exception("The robot did not answer in 10 seconds");
robot.Rws.Io.SetSignalValue("Local", "Board10", "DO_Start", 0);
// Polls one signal until it reaches the expected value, or the timeout expires.
// 200 ms is a reasonable period : a shorter one loads the controller for nothing.
static bool WaitValue(AbbController robot, string network, string device, string signal,
float expected, int timeoutMs)
{
DateTime limit = DateTime.UtcNow.AddMilliseconds(timeoutMs);
while (DateTime.UtcNow < limit)
{
IoSignalItem item = robot.Rws.Io.GetSignal(network, device, signal);
if (item.LogicalValue == expected)
return true;
Thread.Sleep(200);
}
return false;
}

When the reaction has to be faster than that, do the waiting in RAPID with a WaitDI, and use the SDK to give the program the order to start.

Simulate a signal during a test

A simulated signal keeps the value written by the client and stops following its device. This is how an input is forced from a test bench, on a real controller as well as on a virtual one.

// Simulate an input: it keeps the value written by the client
robot.Rws.Io.SetSignalState("Local", "Board10", "DI_PartPresent", true);
robot.Rws.Io.SetSignalValue("Local", "Board10", "DI_PartPresent", 1);
IoSignalItem signal = robot.Rws.Io.GetSignal("Local", "Board10", "DI_PartPresent");
Console.WriteLine(signal.LogicalState); // Simulated
// Give the signal back to its device
robot.Rws.Io.SetSignalState("Local", "Board10", "DI_PartPresent", false);
// Or stop simulating every simulated signal of the controller at once
robot.Rws.Io.UnblockSignals();

Do not leave a signal simulated at the end of a test. UnblockSignals() stops the simulation of every simulated signal of the controller at once.

Who is allowed to write a signal

A signal can be write protected depending on who writes it and in which operation mode. When a write is refused and the mastership is not the reason, read the configuration of the signal.

IoSignalConfiguration config = robot.Rws.Io.GetSignalConfiguration("Local", "Board10", "DO_Gripper");
Console.WriteLine(config.SignalName); // DO_Gripper
Console.WriteLine(config.SignalBits); // 1
// Who is allowed to write the signal, and in which operation mode
Console.WriteLine(config.Rapid); // a RAPID program
Console.WriteLine(config.LocalManual); // the teach pendant, in manual mode
Console.WriteLine(config.LocalAuto); // the teach pendant, in auto mode
Console.WriteLine(config.RemoteManual); // a remote client, in manual mode
Console.WriteLine(config.RemoteAuto); // a remote client, in auto mode

Find the signals you need

SearchSignals filters on the name, the device, the network, the type and the category. A second criteria can be inverted to exclude what it matches, which is how the safety signals are left out of a list.

// Every digital output of one device
IoSignalSearchCriteria criteria = new IoSignalSearchCriteria();
criteria.DeviceName = "Board10";
criteria.Type = IoSignalType.DigitalOutput;
IoSignalItem[] outputs = robot.Rws.Io.SearchSignals(criteria);
foreach (IoSignalItem signal in outputs)
{
Console.WriteLine($"{signal.Name} = {signal.LogicalValue}");
}
// The extended search also reports the physical value and the write access level
IoSignalItem[] extended = robot.Rws.Io.SearchSignalsExtended(criteria, null, 0, 50);
Console.WriteLine(extended[0].PhysicalValue);
Console.WriteLine(extended[0].Quality);
Console.WriteLine(extended[0].WriteAccessLevel);
// A second inverted criteria excludes what it matches, here the safety signals
IoSignalSearchCriteria exclude = new IoSignalSearchCriteria();
exclude.Category = "safety";
exclude.Invert = true;
IoSignalItem[] withoutSafety = robot.Rws.Io.SearchSignals(criteria, exclude);

Going further

  • I/O signals, devices & networks, the complete reference
  • Start & stop a RAPID program, to trigger a program that reacts to your signals
  • Read & write RAPID variables, the other way of exchanging data with a program
Methods of IoService :
// Gets a single I/O signal, including its physical value and time stamps (synchronous)
IoSignalItem GetSignal(string network, string device, string signal);
// Gets the runtime configuration properties of an I/O signal (synchronous)
IoSignalConfiguration GetSignalConfiguration(string network, string device, string signal);
// Gets every I/O signal defined in the controller (synchronous) A controller usually exposes several hundreds of signals. Use Nullable%7bSystem.Int32%7d) to narrow the result down to a network, a device, a category or a signal type.
IoSignalItem[] GetSignals();
// Inverts the value of an I/O signal (synchronous) Only digital and group signals can be inverted.
void InvertSignal(string network, string device, string signal, float value, bool logToEventLog = false);
// Pulses the value of an I/O signal (synchronous) Only digital and group signals can be pulsed.
void PulseSignal(string network, string device, string signal, float value, int pulses, int? activePulseLength = null, int? passivePulseLength = null, bool logToEventLog = false);
// Searches the I/O signals matching the given criteria (synchronous) The returned signals carry their name, type, category, logical value and logical state. Use Nullable%7bSystem.Int32%7d) to also get their physical value, time stamps and write access level.
IoSignalItem[] SearchSignals(IoSignalSearchCriteria criteria = null, IoSignalSearchCriteria secondCriteria = null, int? start = null, int? limit = null);
// Searches the I/O signals matching the given criteria and returns their extended properties (synchronous) In addition to Nullable%7bSystem.Int32%7d), the returned signals carry their physical value, quality, time stamps and write access level.
IoSignalItem[] SearchSignalsExtended(IoSignalSearchCriteria criteria = null, IoSignalSearchCriteria secondCriteria = null, int? start = null, int? limit = null);
// Simulates or stops simulating an I/O signal (synchronous) A simulated signal keeps the logical value written by the client and no longer follows its physical value.
void SetSignalState(string network, string device, string signal, bool simulated);
// Writes the value of an I/O signal (synchronous)
void SetSignalValue(string network, string device, string signal, float value, bool logToEventLog = false);
// Writes the value of an I/O signal in "queued delayed" mode (synchronous) The controller queues the write and applies it once the delay has elapsed.
void SetSignalValueDelayed(string network, string device, string signal, float value, int delay, bool logToEventLog = false);
// Pulses an I/O signal by toggling its current value (synchronous) Only digital and group signals can be toggled.
void ToggleSignal(string network, string device, string signal, float value, int pulses, int? activePulseLength = null, int? passivePulseLength = null, bool logToEventLog = false);
// Removes the simulation of every simulated I/O signal of the controller (synchronous)
void UnblockSignals();

Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.

Members of Rws.Data.IoSignalItem :
public class IoSignalItem {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.IoSignalItem" data-throw-if-not-resolved="false"></xref> class
public IoSignalItem()
// Category the signal belongs to, for example "safety"
public string Category { get; set; }
// Name of the device the signal is connected to, for example "DRV_1"
public string DeviceName { get; set; }
// Logical state of the signal (simulated or not)
public IoSignalLogicalState LogicalState { get; set; }
// Microseconds part of the global time at which the logical value was updated, null when not reported
public long? LogicalTimeMicroseconds { get; set; }
// Seconds part of the global time at which the logical value was updated, null when not reported
public long? LogicalTimeSeconds { get; set; }
// Logical value of the signal, null when the controller did not report it
public float? LogicalValue { get; set; }
// Name of the signal, for example "DRV1BRAKE"
public string Name { get; set; }
// Name of the network the signal belongs to, for example "Local"
public string NetworkName { get; set; }
// Full path of the signal, "{network}/{device}/{signal}" (for example "Local/DRV_1/DRV1BRAKE")
public string Path { get; set; }
// Physical state of the signal.
//
// <p>Only reported when reading a single signal with <code>IoService.GetSignal()</code>.</p>
public IoSignalPhysicalState PhysicalState { get; set; }
// Microseconds part of the global time at which the physical value was updated, null when not reported
public long? PhysicalTimeMicroseconds { get; set; }
// Seconds part of the global time at which the physical value was updated, null when not reported
public long? PhysicalTimeSeconds { get; set; }
// Physical value of the signal, null when the controller did not report it.
//
// <p>Only reported by <code>IoService.GetSignal()</code> and <code>IoService.SearchSignalsExtended()</code>.</p>
public float? PhysicalValue { get; set; }
// Quality of the signal, reported as a numeric code by <code>IoService.GetSignal()</code> and as a
// textual value (for example "good") by <code>IoService.SearchSignalsExtended()</code>
public string Quality { get; set; }
// Returns a string representation of this signal
public override string ToString()
// Type of the signal
public IoSignalType Type { get; set; }
// Access level required to write the signal, for example "None".
//
// <p>Only reported by <code>IoService.SearchSignalsExtended()</code>.</p>
public string WriteAccessLevel { get; set; }
}
Members of Rws.Data.IoSignalType :
public enum IoSignalType {
// Analog input
AnalogInput = 4
// Analog output
AnalogOutput = 3
// Digital input
DigitalInput = 2
// Digital output
DigitalOutput = 1
// Group input
GroupInput = 5
// Group output
GroupOutput = 6
// The signal type could not be determined
Unknown = 0
}
Members of Rws.Data.IoSignalConfiguration :
public class IoSignalConfiguration {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.IoSignalConfiguration" data-throw-if-not-resolved="false"></xref> class
public IoSignalConfiguration()
// Whether a local client can write the signal in auto mode
public bool? LocalAuto { get; set; }
// Whether a local client can write the signal in manual mode
public bool? LocalManual { get; set; }
// Whether a RAPID client can write the signal in both manual and auto mode
public bool? Rapid { get; set; }
// Whether a remote client can write the signal in auto mode
public bool? RemoteAuto { get; set; }
// Whether a remote client can write the signal in manual mode
public bool? RemoteManual { get; set; }
// Whether the bits of this signal are set by a device transfer operation.
//
// <p>Not reported by every controller, null when absent from the response.</p>
public bool? SetByDeviceTransfer { get; set; }
// Number of bits of the signal, null when not reported
public int? SignalBits { get; set; }
// Name of the signal, for example "DRV1CHAIN2"
public string SignalName { get; set; }
// Returns a string representation of this signal configuration
public override string ToString()
}
Members of Rws.Data.IoSignalSearchCriteria :
public class IoSignalSearchCriteria {
// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.IoSignalSearchCriteria" data-throw-if-not-resolved="false"></xref> class
public IoSignalSearchCriteria()
// Whether only the blocked (simulated) signals are searched
public bool? Blocked { get; set; }
// Category of the searched signals, for example "safety"
public string Category { get; set; }
// Category prefix of the searched signals
public string CategoryPrefix { get; set; }
// Name of the device the searched signals are connected to
public string DeviceName { get; set; }
// Whether the criteria is inverted: the signals matching it are excluded from the result
public bool? Invert { get; set; }
// Name of the searched signals
public string Name { get; set; }
// Name of the network the searched signals belong to
public string NetworkName { get; set; }
// Returns a string representation of this search criteria
public override string ToString()
// Type of the searched signals, null to search every type
public IoSignalType? Type { get; set; }
}
View as Markdown

Intégrez facilement les robots Universal Robots, Fanuc, Yaskawa, ABB ou Staubli dans vos applications .NET, Python, LabVIEW ou Matlab

UnderAutomation
Contactez-nousLegal

© All rights reserved.