Data Types
Reference for tag data types in rungs.dev — BOOL, SINT, INT, DINT, REAL, TIMER, COUNTER, CONTROL, FBD_TIMER, FBD_COUNTER, FBD_ONESHOT — what each holds and which instructions read or write it.
Every tag has a data type. The type decides what values the tag can hold, how much memory it uses, and which instructions can read or write it.
Summary
| Type | Used For |
|---|---|
BOOL | Contacts, coils, one-shots, timer/counter status bits |
SINT | Bytes: packed status, serial data, -128 to 127 |
INT | Device registers and drive words, -32768 to 32767 |
DINT | Counts, presets, numeric values |
REAL | Analog values, setpoints, calculations |
TIMER | Ladder timer tags — used by TON, TOF, RTO |
COUNTER | Ladder counter tags — used by CTU, CTD |
CONTROL | Ladder array tags — used by BSL, FFL, FAL and the rest of the Array tab |
FBD_TIMER | Structured Text timer function block — TONR, TOFR, RTOR |
FBD_COUNTER | Structured Text counter function block — CTUD |
FBD_ONESHOT | Structured Text one-shot function block — OSRI, OSFI |
BOOL
A single bit — 0 or 1. The most common type in ladder logic — every contact and coil operates on a BOOL.
Use BOOL for:
- Pushbuttons, limit switches, and other digital inputs
- Motors, pilot lights, alarms, and other digital outputs
- Internal flags — running, fault, ready, enabled
- Status bits on structured tags (
.DN,.EN,.TT, etc.)
Write BOOL values as 0 or 1. Do not use the strings "true" or "false".
DINT
A 32-bit signed integer. Range: -2,147,483,648 to 2,147,483,647.
Use DINT for:
- Counts and totals
- Timer and counter presets (in milliseconds / steps)
- Numeric comparisons
- Array indices
Example: PartsToday counts pieces produced; CycleTime.PRE sets a timer to 5000 ms.
Writing DINT literals
A plain number without a decimal point is a DINT literal: 42, -42, 0.
You can also write a DINT as a radix literal — a bit pattern in hexadecimal, binary,
or octal. This is the natural way to write masks, where which bits are set matters more
than the decimal value:
16#00FF— hexadecimal (base 16), digits0-9andA-F. Same value as255.2#0000_1111— binary (base 2), digits0and1. Same value as15.8#377— octal (base 8), digits0-7. Same value as255.
Underscores may group digits for readability — in radix literals (2#1010_1010) and in
plain decimals (1_000_000) alike — and hex digits are case-insensitive (16#ff equals
16#FF).
A radix literal describes all 32 bits of the DINT, so it can name values a decimal
literal writes with a minus sign: 16#FFFFFFFF is every bit set, which as a signed
DINT is -1. The widest patterns are 16#FFFFFFFF, 2#1111_1111_1111_1111_1111_1111_1111_1111,
and 8#37777777777 — anything wider than 32 bits is a compile error. Radix literals
never take a sign: write the pattern itself, or use a decimal number.
SINT and INT
Narrower whole numbers, for data that arrives already sized by a device.
| Type | Bits | Range | Where you meet it |
|---|---|---|---|
SINT | 8 | -128 to 127 | A byte: packed status bits, serial data, a barcode character |
INT | 16 | -32,768 to 32,767 | A device register: a drive speed word, a Modbus register, a raw analog count |
Use them when the equipment you are talking to uses them. A drive that wants a speed
reference from 0 to 32767 is describing an INT; a protocol that hands you bytes is
describing SINT. For your own counters, totals and presets, use DINT.
Arithmetic is 32-bit, and overflow wraps
Arithmetic happens in 32 bits, and only the result is narrowed. In_A * In_B on two
SINT tags is worked out in full and then cut down to fit when it is stored. So the answer
can be right in the middle of a calculation and still not fit at the end.
A value that does not fit is not clipped — it wraps. Storing 300 in a SINT gives
44, not 127. Storing -129 gives 127. The controller keeps the low 8 bits (or 16 for
an INT) and reads them back as a signed number:
Out_Byte := 300; // Out_Byte is 44
Out_Byte := -129; // Out_Byte is 127
Out_Reg := 40000; // Out_Reg is -25536This is not an error — it is exactly what a real controller does, and the program still runs.
The top bit is the sign bit
Bits are numbered from 0, and the highest bit of a signed type carries the sign. Setting
bit 7 of a SINT gives -128, and setting bit 15 of an INT gives -32768:
Out_Byte := 0;
Out_Byte.7 := 1; // Out_Byte is -128For the same reason there is no bit 8 on a SINT or bit 16 on an INT — the type has no
such bit, and naming one is a compile error. A DINT has bits 0 to 31.
Hexadecimal is often the clearer way to write these values: 16#FF in a SINT is -1,
and reads as "all eight bits set" rather than as a negative number.
REAL
A 32-bit floating-point number with decimal precision.
Use REAL for:
- Temperatures, pressures, flow rates
- Sensor readings that need decimal values
- Engineering-unit calculations
Mixing REAL and DINT:
DINT / DINTinto aDINTdestination truncates toward zero (7 / 2 = 3).DINT / DINTinto aREALdestination keeps the fraction (7 / 2 = 3.5).- Any
REALoperand into aDINTdestination uses banker rounding (ties-to-even):2.5 → 2,3.5 → 4,−1.5 → −2.
Writing REAL literals
A REAL literal must contain a decimal point. Scientific notation needs a digit on both sides of the decimal point, and a leading + sign is not allowed.
- Accepted:
3.14,-0.5,-.5,1.0e3,-1.5e1,-2.5e2. - Rejected:
1e3(no decimal),.5e2(no digit before the decimal),+1.5e0(unary+not allowed on literals).
To write a positive REAL literal, just omit the sign — 1.5e0, not +1.5e0. This matches the rule used by the current generation of Rockwell tooling.
See Arithmetic and Comparison Operators for the full division and rounding matrix, or the MOVE instruction for type conversion in ladder logic.
Structured types
TIMER, COUNTER, CONTROL, FBD_TIMER, FBD_COUNTER, and FBD_ONESHOT are structures, not single values. They expose named members (.PRE, .ACC, .DN, …) that your logic reads and writes on a rung.
Each instruction that uses a structured tag documents its members in the instruction reference — see the Ladder Logic and Structured Text instruction pages.
CONTROL
The array instructions keep their state in a CONTROL tag. Where a timer counts milliseconds,
a control counts elements: .LEN is how many to work through and .POS is which one the
instruction is on. .LEN and .POS are ordinary numbers your logic can read and write, and
every array instruction reads them from the tag on every scan.
See Array Instructions for the full member list.
A structured tag can be Local — private to the instruction — or InOut, when the timer or counter belongs to the caller. It can never be an Input or an Output, which carry single values only. See Tag Usage.
Practice
Try data types in the Count Up exercise — a DINT counter that raises a BOOL Done flag when it reaches its target.
Relay AI Assistant
Relay is the AI assistant built into Rungs Studio. It explains PLC code, debugs Ladder Logic, and walks you through compiler errors and failing tests — using the rungs, tags, and test results from your active project.
Tag Usage
Every rungs.dev tag has a usage — Input, Output, InOut, or Local — that controls where its value comes from, where it appears in the editor, and whether logic can write to it.