Reading & Writing Registers
On this page :
Learn how to use Boolean, Float, and Integer registers on UR Cobots to communicate with Fieldbus or RTDE systems. Includes code examples, usage tips, and interface methods like Primary Interface and RTDE.
🚀 Introduction
Let’s dive into how you can use registers to communicate with external systems like Fieldbus or RTDE clients — it's simpler than it sounds, promise! 😉
🧠 What Are Registers?
UR Cobots offer access to several types of registers you can use to send and receive data between your robot and external systems. Think of them as little data mailboxes 📬 with three types of content:
- Boolean:
true
orfalse
- Float: 32-bit floating-point numbers
- Integer: 32-bit signed integers
Each data type comes in two flavors:
- Input Registers: Read-only 🔍 — used to receive data from external systems like Fieldbus or RTDE.
- Output Registers: Read/write ✍️ — used to send data to those systems.
⚠️ Note: You can only write to output registers using script. Input registers are strictly read-only from scripts!
🔍 Reading Registers with URScript
Data Type | Function | Address Range | Notes |
---|---|---|---|
Boolean (Input) | read_input_boolean_register(address: int) -> bool | 0–127 | 0–63 : Fieldbus/PLC64–127 : RTDE |
Boolean (Output) | read_output_boolean_register(address: int) -> bool | 0–127 | Same ranges as input |
Float (Input) | read_input_float_register(address: int) -> float | 0–47 | 0–23 : Fieldbus/PLC24–47 : RTDE |
Float (Output) | read_output_float_register(address: int) -> float | 0–47 | Same ranges as input |
Integer (Input) | read_input_integer_register(address: int) -> int | 0–47 | 0–23 : Fieldbus/PLC24–47 : RTDERange: [-2,147,483,648, 2,147,483,647] |
Integer (Output) | read_output_integer_register(address: int) -> int | 0–47 | Same as above |
✍️ Writing Registers with URScript
Data Type | Function | Address Range | Value |
---|---|---|---|
Boolean (Output) | write_output_boolean_register(address: int, value: bool) | 0–127 | True / False |
Float (Output) | write_output_float_register(address: int, value: float) | 0–47 | 32-bit float (e.g. 1.5 ) |
Integer (Output) | write_output_integer_register(address: int, value: int) | 0–47 | Signed 32-bit int |
🧪 Handling Registers with the Primary Interface
✍️ Writing Output Registers
The Primary Interface allows remote script execution with two key behaviors:
- If you send a raw script line, it will stop the current program and execute your line. ⛔➡️▶️
- If the script is sent within a secondary program (a
sec
block), it will run in parallel without stopping the main program. 🧵✨
Example: Writing the float register 0 with the value 1.5
:
using UnderAutomation.UniversalRobots;class PrimaryInterfaceWriteRegisters{static void Main(string[] args){var robot = new UR();robot.Connect("192.168.0.1");/**/// Pause main program and execute scriptrobot.PrimaryInterface.Script.Send("write_output_float_register(0, 1.5)");// Send Secondary program that does not stop the main programrobot.PrimaryInterface.Script.Send(@"sec secondaryProgram():write_output_float_register(0, 1.5)end");/**/}}
🕵️ Reading Registers
Technically, you can read registers via the Primary Interface... but it's a bit tricky 😅.
You’d need to execute something like:
global myRegister0 = read_input_float_register(0)
Then read myRegister0
via Primary Interface functions. The catch? You can’t write to a global variable from a secondary program. So this requires stopping the current program, which isn't ideal.
🚫 Not recommended — use RTDE instead for smoother operation.
⚡ Handling Registers with RTDE
RTDE (Real-Time Data Exchange) is the go-to method for reading and writing registers up to 500Hz 🔥⚡
To use it:
- Set up registers when configuring the RTDE connection
- Use OutputSetup for the data you want to read 📤
- Use InputSetup for the data you want to write 📥
💡 Boolean trick:
Booleans from 0–63
are accessed via two 32-bit unsigned integer packets.
From 64–127
, access them bit-by-bit.
✍️ Writing Input Registers
Only input-type registers (bool, int, float) can be written via RTDE. To write output-type registers, use Primary Interface. Here’s an example:
using UnderAutomation.UniversalRobots;using UnderAutomation.UniversalRobots.Common;using UnderAutomation.UniversalRobots.Rtde;using UnderAutomation.UniversalRobots.Rtde.Internal;class RtdeWriteRegisters{static void Main(){/**/var robot = new UR();var param = new ConnectParameters("192.168.0.1");// Enable RTDEparam.Rtde.Enable = true;// Exchange data at 500Hzparam.Rtde.Frequency = 500;// Select data you want to write in robot controllerparam.Rtde.InputSetup.Add(RtdeInputData.InputBtRegisters0To31);param.Rtde.InputSetup.Add(RtdeInputData.InputBtRegisters32To63);param.Rtde.InputSetup.Add(RtdeInputData.InputBitRegisters,64);param.Rtde.InputSetup.Add(RtdeInputData.InputIntRegisters, 0);param.Rtde.InputSetup.Add(RtdeInputData.InputDoubleRegisters, 0);// Connect to robotrobot.Connect(param);//...// Write input values in robotvar inputValues = new RtdeInputValues();inputValues.InputBtRegisters0To31 = 0xff;inputValues.InputBtRegisters32To63 = 0xCA;inputValues.InputBitRegisters.X64 = true;inputValues.InputIntRegisters.X0 = 2;inputValues.InputDoubleRegisters.X0 = 3.14;robot.Rtde.WriteInputs(inputValues);}}
🔍 Reading Registers
All registers are available for reading! Here’s how you can do it:
using UnderAutomation.UniversalRobots;using UnderAutomation.UniversalRobots.Rtde;class RtdeReadRegisters{static void Main(){/**/var robot = new UR();var param = new ConnectParameters("192.168.0.1");// Enable RTDEparam.Rtde.Enable = true;// Exchange data at 500Hzparam.Rtde.Frequency = 500;// Select data you want the robot to send// Read input registersparam.Rtde.OutputSetup.Add(RtdeOutputData.InputBitRegisters0To31); // 32 bits integerparam.Rtde.OutputSetup.Add(RtdeOutputData.InputBitRegisters32To63);// 32 bits integerparam.Rtde.OutputSetup.Add(RtdeOutputData.InputBitRegisters, 64); // one by one access of registers 64-127 from FW 3.9.0 / 5.3.0param.Rtde.OutputSetup.Add(RtdeOutputData.InputDoubleRegisters, 0); // floating pointparam.Rtde.OutputSetup.Add(RtdeOutputData.InputIntRegisters, 0); // integer// Read output registersparam.Rtde.OutputSetup.Add(RtdeOutputData.OutputBitRegisters0To31);param.Rtde.OutputSetup.Add(RtdeOutputData.OutputBitRegisters32To63);param.Rtde.OutputSetup.Add(RtdeOutputData.OutputBitRegisters, 64);param.Rtde.OutputSetup.Add(RtdeOutputData.OutputDoubleRegisters, 0);param.Rtde.OutputSetup.Add(RtdeOutputData.OutputIntRegisters, 0);// Connect to robotrobot.Connect(param);// Be notified at 500Hz when data is receivedrobot.Rtde.OutputDataReceived += Rtde_OutputDataReceived;/**/}/**/private static void Rtde_OutputDataReceived(object sender, RtdeDataPackageEventArgs e){// Read input registersbool bit0 = e.OutputDataValues.InputBitRegisters.X64;uint bit0To31 = e.OutputDataValues.InputBitRegisters0To31;uint bit32To63 = e.OutputDataValues.InputBitRegisters32To63;int int0 = e.OutputDataValues.InputIntRegisters.X0;double double0 = e.OutputDataValues.InputDoubleRegisters.X0;// Read output registersbool outputBit0 = e.OutputDataValues.OutputBitRegisters.X64;uint outputBit0To31 = e.OutputDataValues.OutputBitRegisters0To31;uint outputBit32To63 = e.OutputDataValues.OutputBitRegisters32To63;int outputInt0 = e.OutputDataValues.OutputIntRegisters.X0;double outputDouble0 = e.OutputDataValues.OutputDoubleRegisters.X0;}/**/}