Omron PLC Counter Timer: BCD Binary Mode and Double Word

James Nishida17 min read
HMI ProgrammingOmronTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview: Why Omron Counters and Timers Count Downward

New Omron PLC programmers frequently encounter a counterintuitive behaviour: when a TIM (timer) or CNT (counter) instruction is energised, the present value (PV) does not climb from 0 toward the set value (SV). Instead, the PV starts at the SV and decrements toward 0, at which point the instruction's own contact closes. This is the legacy BCD presentation that Omron inherited from its earlier C-series and P-type controllers, and it remains the default behaviour on the CPM1A, CPM2A, CPM2C, and SRM1 PLCs and on CS1/CJ1/CJ2 controllers when the project is configured for BCD instruction mode. For machine builders who display the PV directly on an HMI or text panel, the descending readback is confusing because the operator intuitively expects to see "0 … 99 … 500 … 1000" rather than "1000 … 999 … 500 … 0".

Two separate problems are bundled into the typical counter-and-timer support question. The first is the descending readback itself, which is solved either by enabling binary mode (when the CPU supports it) or by subtracting the PV from the SV inside the HMI. The second is the requirement to record a daily production figure that may climb into the millions, which exceeds the 0–9999 BCD range of a single CNT or the 0–65535 binary range of a single CNTX. That second problem requires either a cascade of counters or a 32-bit (double-word) variable maintained in ladder, with a matching data type on the HMI.

This article addresses both problems on the CPM2A (the platform named in the source material) and on the CJ1M, CS/CJ-H, CP1H, CP1L, and CP2E families where binary mode and full double-word arithmetic are available. Throughout, the article assumes CX-Programmer version 5.0 or later; on Sysmac Studio (NJ/NX, CP2E) the same mnemonics appear with identical semantics. Refer to the Omron Industrial Automation support portal for the latest CX-Programmer and Sysmac Studio downloads and documentation sets.

Important. On CPM2A, SRM1, and CPM1A the binary-mode switch in CX-Programmer PLC properties is honoured by the offline documentation but not by the firmware; these CPUs execute TIM/CNT/CNTR in BCD unconditionally. To get ascending behaviour on those families you must either invert in the HMI or maintain your own up-counter using +B or ++ instructions in a DM word.

CPM2A Counter and Timer Architecture

The CPM2A CPU units (CPM2A-20CDR-A, CPM2A-30CDR-D, CPM2A-40CDR-A, CPM2A-60CDR-A and the -D, -1 and -ESS variants) share the instruction set defined in the CPM1/CPM2A/CPM2C/SRM1 Programming Manual (Omron document number W352). Counters and timers are bit-instanced instructions:

Mnemonic Function code PV units SV range Auto-reset
TIM 0.1 s 0–9999 (BCD) Yes, on input OFF
TIMH(15) 15 10 ms 0–9999 (BCD) Yes, on input OFF
TMHH 1 ms 0–9999 (BCD) Yes, on input OFF
CNT events 0–9999 (BCD) No, requires reset input
CNTR(12) 12 events 0–9999 (BCD) No, reversible
TTIM(87) 87 0.1 s 0–9999 (BCD) Yes, totalising

Each instance occupies one word in the timer/counter area (TIM/CNT words 000–511 on a 20-point CPM2A; up to 1023 on larger units). The instruction is the address — there is no separate tag for SV versus PV. The same TC number carries the SV at programming time and the live PV at runtime. To read the PV in ladder or from the HMI you address the TC word as a normal operand; the radix is BCD and the value reads 4-digit hex when watched in BCD mode but interprets as decimal when displayed with the radix set to DEC.

Because the PV is stored BCD, attempting to use it directly in BIN arithmetic without conversion will yield nonsense. Any math instruction that consumes an operand in the TC area must use the BCD family: ADB(50), SBB(51), MLB(52), and DVB(53). CPM2A does not support signed BCD math, so negative results must be handled as separate decrement logic.

Why the PV Appears Descending on an HMI

The descending readback is purely a presentational convention, not a functional difference. Internally the firmware of a TIM instruction computes elapsed = (SV − PV), and the instruction's Done bit closes when elapsed ≥ SV. The PV that the programmer reads from the TC word is therefore SV minus elapsed, which naturally starts at SV and falls to 0.

On a BCD-aware HMI element this is fine — the operator sees a count-down timer and understands "1000, 900, 800 … 0 means 100 s remaining". The confusion arises only when the operator expects an up-counter or when the HMI is configured to render the TC word as a BIN (hex) value, because the radix override on the HMI side reinterprets the same BCD nibbles as a hex number that may not be meaningful. Always configure the HMI data type as BCD or DEC depending on whether you want to honour the BCD nibble grouping or the decimal reading.

Three practical fixes exist, in increasing order of cleanliness:

  1. Re-scale in the HMI by displaying (SV) − (PV). Most Omron NS, NB, and NA panels support an expression element or a numeric display with a formula. The TC word for the PV is the same address you typed as the operand in the TIM/CNT instruction.
  2. Maintain a separate DM up-counter in ladder. On every count event, execute ADB(50) D100 #0001 D100 (or on a binary-capable CPU, +(400) D100 #0001 D100) and display D100 on the HMI.
  3. Switch to a binary-mode CPU and use TIMX, CNTX, and CNTRX so the PV starts at 0 and increments to SV.

Display Conversion on Touchscreen Panels

For the NB3Q, NB5Q, NB7W, and NB10W series, open the project in NB-Designer, drag a Numeric Display onto the screen, set the address to the TC word, and switch the data type to BCD 16-bit. To show an ascending value, insert a Numeric Input/Display with the same address but with the formula SV − PV. The constant SV can be entered directly, or you can read it from a DM word you have written at startup using MOV(21) #01000 D200 (BCD 1000).

On the NS-series PT (CX-Designer), use a numeric display element with the Expression option. The expression syntax is @/TC000 − @/D0100 where the leading @ denotes an indirect reference and the second operand is the live PV from the TC word. Do not forget to set the display radix to DEC so the BCD nibble group is not re-rendered as hex.

For third-party panels (Pro-face GP, Weintek cMT, Red Lion Crimson), the TC word is read through a Modbus TCP or EtherNet/IP gateway. Configure the source register as a 16-bit holding register (function code 03) and set the format to 4-digit BCD, which most SCADA drivers handle as unsigned decimal 0–9999.

Enabling Binary Mode on CJ1M, CS/CJ-H, and CP1H

On the CJ1M, CS1H, CS1D, CJ1H, CJ2H, CJ2M, CP1H, CP1L, and CP1E PLCs, the choice between BCD-mode timers/counters (TIM/CNT/CNTR) and binary-mode timers/counters (TIMX/CNTX/CNTRX) is a per-CPU switch, not a per-instruction switch. It is set in CX-Programmer under PLC | Properties on the Binary tab of the CPU configuration dialog. The exact path is described in the CX-Programmer Operation Manual (W437).

  1. Open the project tree in CX-Programmer, right-click the PLC icon (for example NewPLC or CJ1M-CPU13) and choose Properties.
  2. In the CPU Type tab, set Timer/Counter PV update method to Binary (BIN). The default is BCD. The setting is written to the CPU's user memory at transfer and survives a power cycle.
  3. Click Transfer to PLC and confirm the prompt that warns the new setting requires the PLC to be in PROGRAM mode.
  4. Cycle power if the transfer dialog requires it (older CJ1M firmware prior to unit version 3.0 may need a power cycle).
  5. Open the global timer/counter table (View | Window | TC Table) and confirm the PV column now reads as BIN. The TC words themselves are still allocated in the same area but the display radix in the table changes.

After this change, all TIM, CNT, and CNTR instructions remain legal and behave exactly as before for backward compatibility, but you should use the X-suffixed variants in new code. TIMX, CNTX, and CNTRX are unconditionally binary regardless of the CPU switch, which is the recommended practice for any project that must scale across firmware revisions.

TIMX, CNTX, and CNTRX Instructions

With binary mode enabled (or when using the X-suffixed mnemonics), the SV range extends from 0–9999 (BCD) to 0–65535 (BIN, 16-bit unsigned). The full instruction family is documented in the CS/CJ/CP Series Instructions Reference Manual (W474):

Mnemonic FC PV units SV range Direction
TIMX 548 0.1 s 0–65535 Down display, internal up counter
TIMHX 549 10 ms 0–65535 Down display, internal up counter
TMHHX 550 1 ms 0–65535 Down display, internal up counter
CNT (BCD) events 0–9999 Down display, increment input
CNTX 546 events 0–65535 Down display, increment input
CNTRX binary rev. counter events 0–65535 Up display, II/DI inputs
TTIMX 555 0.1 s 0–65535 Totalising timer, up
MTIMX 553 0.1 s 0–65535 Multi-input, up

Function code for CNTRX varies by manual revision; verify against W474 §5 before deployment.

Note that the standard TIMX still shows a descending PV to the HMI — only CNTRX (and CNTR) count upward naturally. The binary-mode change does not flip the display; it widens the SV range. To get an ascending readback on a one-shot timer, the cleanest pattern is to feed a CNTR from a 0.1 s or 10 ms clock pulse and then compare CNTR's PV against the desired timeout in ladder.

Reversible Counting with CNTR and CNTRX

CNTR(12) is the reversible counter. It has two execution inputs: the Increment Input (II) and the Decrement Input (DI). Each pulse on II adds one to the PV; each pulse on DI subtracts one. The PV starts at 0 and increments up to the SV; on the next II pulse beyond SV, the PV wraps to 0 and the completion output closes for one scan. Conversely, decrementing past 0 wraps to SV. CNTR therefore naturally gives an ascending readback.

On the CJ1M, the binary variant is CNTRX. Its SV range is 0–65535. Common ladder pattern for a part counter that can be both added (parts produced) and subtracted (parts rejected):

| | II (parts_produced_pulse)  DI (parts_rejected_pulse)  Reset |
| |-------| |-----------------------| |-----------------| |--|
| |                          CNTRX                                |
| |                          0000                                 |
| |                          #01000                               |
| |                          CIO 2000.00  (Done at 1000)          |

The Done bit on CNTR is one-shot: it closes for one scan at SV then reopens. To latch "reached setpoint", follow the CNTR contact with a KEEP(11) instruction or with a self-holding rung.

Note. The PV of CNTR is the live up-count, but CNTR does not retain across power loss unless its TC word is in a retentive area. On CPM2A the timer/counter area is retentive by default (the HR area is not used; TC area is battery-backed). On CJ1M, mark the TC range as retentive in the PLC Properties | Memory tab; otherwise a power cycle resets the PV to 0.

Counting Above 9999: Cascading on CPM2A

The CPM2A cannot natively address a 32-bit counter in its base instruction set. To total production in the millions you must cascade two or three CNT or CNTR instructions. The standard cascade uses one counter per decimal digit:

  • CN1 (CNT #1000) — units, increments every part.
  • CN2 (CNT #1000) — thousands, increments when CN1 reaches SV.
  • CN3 (CNT #1000) — millions, increments when CN2 reaches SV.

The carry logic is a single NC contact of the lower counter's output driving the count input of the next higher counter. For a full daily total that can reach 9,999,999, three CNT instances are sufficient. For 99 million or higher, use four. The combined PV must be reconstructed in a separate DM region using BCD multiplications:

| | CN1_Done  CN2_Done   CN3_Done |
| |--------| |--------| |----------|
| |                              MOV(21) #0000 D100  (clear)       |
| |                              MLB(52)  D101  D100  D103         |
| |                              ADB(50)  D100  D103  D100         |
| |                              MLB(52)  D102  D100  D104         |
| |                              ADB(50)  D104  D100  D100         |

This is fragile and slow. It is also unnecessary on any CPU that supports 32-bit instructions. Migrate the production total to a double-word DM word (D100:D101 or D100L on CX-Programmer 9.x) and use the dedicated 32-bit instructions shown in the next section.

Double-Word (32-bit) Data on CJ1M, CS/CJ-H, and CP1H

The CJ-series instruction set distinguishes 16-bit and 32-bit operations by the absence or presence of the L suffix. The base mnemonics (+, , *, /, MOV, CMP, INC, DEC) operate on 4-digit BCD; appending L switches them to 8-digit BCD on two adjacent words. To get 32-bit signed binary math instead, append BL (e.g., +BL, −BL, *BL, /BL, INCBL, DECBL). The data type radix is the only difference — both L and BL variants share the same two-word storage layout: the low word at the base address, the high word at base+1.

Operation 16-bit BCD 32-bit BCD 32-bit BIN
Move MOV(21) MOVL(498) MOVL(498)*
Add +(400) +L(401) +BL(405)
Subtract −(410) −L(411) −BL(415)
Multiply *(420) *L(421) *BL(425)
Divide /(430) /L(431) /BL(435)
Increment ++(590) ++L(591) ++BL(593)
Decrement −−(592) −−L(593) −−BL(595)
Compare CMP(20) CMPL(610) CMPL(610)*
BCD→BIN BIN(23) BINL(621)
BIN→BCD BCD(24) BCDL(623)

*MOVL performs a raw 32-bit copy; the interpretation (BCD or BIN) is determined by the consumer instruction, not by MOVL itself.

The double-word tag in CX-Programmer is created by appending L to the address (D100L) or by entering the address as a 32-bit symbol. The Data Type field in the Symbol editor should be set to DWORD (or UDINT on Sysmac Studio). On the HMI side, configure the address as a 32-bit unsigned integer. For numbers up to 4,294,967,295 (2^32 − 1) use unsigned; for a counter that should saturate at, say, 999,999 and then alarm, prefer signed and clamp with a compare.

32-bit Ladder Pattern for a Daily Production Total

Reserve D200:D201 (or D200L) as the daily production counter. Initialise at first scan with MOVL #0 D200. On every part-produced pulse, execute +L #1 D200 D200 (BCD) or +BL #1 D200 D200 (BIN). At the end-of-day trigger (a CIO bit from the HMI, or a daily scheduler), move the total to an archive area (D300:D301) and reset D200:D201.

| | First_Scan_Pulse                EndOfDay_Pulse |
| |----| |---------------------------| |-----------|
| |                              +L(401) #00000001 D200 D200 |
| |                              MOVL(498) D200 D300        |
| |                              MOVL(498) #0 D200          |

To display the result on an NB or NA panel without overflow, format the numeric display as Decimal, 32-bit unsigned. On CX-Designer, use the same approach; the expression @/D200L dereferences the 32-bit tag. On third-party panels, expose D200 and D201 as separate holding registers (400200 and 400201) and configure the device as a 32-bit word with low-word-first byte order (Modicon convention); this is what EtherNet/IP, Modbus TCP, and FINS all use natively.

CX-Programmer Configuration Reference

Setting Path Default Recommended
Binary mode PLC Properties | CPU Type | Timer/Counter PV update method BCD BIN
TC area retention PLC Properties | Memory | TC area retention Off (CJ1M) On if PV must survive power cycle
DM area retention PLC Properties | Memory | DM area retention D00000–D00127 Expand to cover production region (D200–D301)
Cold start / Hot start PLC Properties | Startup Hot start (CJ1M) Cold start for counter resets on power-up
Cycle time PLC Properties | CPU Type | Cycle time Auto Fixed 10 ms for deterministic counting

Verification, Commissioning, and Common Faults

Symptom Likely cause Verification Fix
PV always reads 0 on HMI HMI radix set to BIN while TC word is BCD Online watch TC word in BIN and BCD Set HMI element to BCD or DEC
PV overflows at 9999 Single CNT used where total exceeds range Compute expected peak count Cascade or migrate to 32-bit D200L
Counter resets on power cycle TC area not marked retentive Watch TC word through power cycle Enable retention in PLC properties, or move production total to retentive DM
CNTR never reaches SV Decrement input pulsing simultaneously with increment Trace II and DI contacts over time Interlock II/DI with mutually-exclusive conditions
32-bit HMI shows garbage Byte-order mismatch (big-endian vs little-endian) Write a known pattern and compare on HMI Swap high/low word on HMI driver, or use MOVL into a swapped staging word
TIM counts down instead of up Binary mode not enabled and X-suffix not used Check PLC Properties and instruction mnemonic Switch to TIMX/CNTX, or compute SV−PV in HMI
CPM2A shows SV−PV that wraps at 0 to 9999 unexpectedly Subtraction in HMI not done in unsigned context Watch raw TC word Use DEC or subtraction with clamping in ladder, not in HMI
+L corrupts upper DM word Source operand overlaps destination Online monitor both halves of the 32-bit pair Use a separate staging word pair for each operand

Field Notes and Migration Tips

When migrating a CPM2A program to a CP1L or CP1H, replace the old TIM/CNT ladder rung-by-rung with TIMX/CNTX equivalents. CX-Programmer's Find/Replace tool supports mnemonic substitution and will preserve the TC addresses. Verify that any DM-based math that consumed the TC PV is updated to expect binary, not BCD — many engineers forget this and end up with a counter that appears correct until the moment a BCD nibble (such as 0x0A) is generated by the BIN value, after which additions begin producing nonsense.

On NJ/NX controllers (Sysmac Studio), the legacy TIM/CNT/TIMX/CNTX instructions are not present. Instead, use the standard TON, TOF, TP, CTU, CTD, and CTUD function blocks from the IEC 61131-3 library. These are inherently binary, inherently up-counting, and naturally support 32-bit PVs through the LINT data type. For a smooth migration path, write a wrapper function block that emulates the Omron TC area so the rest of the program does not need to change.

On CP2E (the economical CJ successor), the same TIMX/CNTX/CNTRX instructions are available with the same function codes, but the DM area is reduced (D0–D9999). Plan your production-counter D-allocations accordingly. Battery-backed retention for DM on CP2E requires the optional battery cartridge CP2W-BAT02.

Safety consideration. A production counter that silently resets on power loss creates a regulatory gap in batch-record traceability (21 CFR Part 11, EU GMP Annex 11). Always keep the daily total in a retentive DM region with battery backup, write the snapshot to an archive area at the shift change, and validate that the archive write succeeded before allowing the reset. Use a different DM range than the live total so a power loss between reset and archive cannot destroy both copies.

Frequently Asked Questions

Why does my CPM2A TIM count down rather than up?

The CPM2A executes all timer/counter instructions in BCD regardless of the CX-Programmer PLC property setting; the PV is stored as SV minus elapsed, so it starts at SV and decrements toward 0. To show an ascending value, either subtract the PV from the SV in the HMI numeric display formula, or maintain your own up-counter in a DM word using ADB(50).

How do I enable binary mode on a CJ1M?

Right-click the PLC icon in the CX-Programmer project tree, choose Properties, open the CPU Type tab, and set Timer/Counter PV update method to Binary. Transfer to PLC in PROGRAM mode. After this, TIM, CNT, and CNTR continue to work but the SV range widens to 0–65535 and the PV is stored in binary.

What is the difference between TIMX and TIM?

TIMX (function code 548) is the binary variant of the standard TIM instruction. Its PV is stored as an unsigned 16-bit binary value (0–65535) instead of BCD (0–9999), and its mnemonic is independent of the CPU's binary/BCD switch — using TIMX guarantees binary regardless of PLC properties. Use TIMX in new code on CJ1M, CS/CJ-H, CP1H, and CP1L.

How do I create a 32-bit counter that holds millions?

Reserve two adjacent DM words (D200:D201, or D200L in CX-Programmer 9.x) and use +L(401) for BCD double add or +BL(405) for binary double add on each count pulse. On the HMI, address the same tag as a 32-bit unsigned integer. On CPM2A, which lacks 32-bit add in its base set, cascade three or four CNT instructions and reconstruct the total with ADB and MLB.

Can I read a TC word directly from the HMI?

Yes. Configure the HMI numeric display with the TC address as its tag, set the data type to BCD 16-bit (or DEC), and the PV will appear. To convert the descending readback into ascending, either enable an expression element that computes SV−PV or maintain a parallel up-counter in a DM word.

Why does my counter reset after a power cycle on CJ1M?

The default CJ1M setup does not retain the TC area across power loss. Open PLC Properties, Memory tab, and enable retention for the relevant TC range, or move your production total to a retentive DM region and use 32-bit instructions there instead.

Is CNTRX the same function code as TIMX?

Both instructions appear in the 540–555 range of the CS/CJ/CP instruction set, but CNTRX has its own distinct function code that varies between manual revisions. Always confirm the FC against the CS/CJ/CP Series Instructions Reference Manual (W474) before entering it in CX-Programmer, or simply drag the instruction from the Instruction Bar which inserts the correct FC automatically.

Back to blog