One BCD-to-REAL conversion box takes 53 program words, so 96 registers take 5,088 of 7,680 ladder words. One conversion sequence in a FOR/NEXT loop with two pointers converts the whole block in a few rungs and reclaims about 5,000 words.
Ninety-six BCD registers need to become REAL values before the panel's graph can store decimal numbers, and one conversion box per register is what blows the memory budget. The fix is a single conversion sequence run in a FOR/NEXT loop through two pointers: load the BCD word through the first pointer, convert it to binary and then to REAL, scale it with a REAL divide, store it through the second pointer, bump both pointers, repeat. The whole table converts in a few rungs, the ladder gives back roughly 5,000 words, and the graph receives the REAL block it requires. This page shows where the words go, which symptoms point at memory, the loop itself, and the checks that keep a pointer from walking into data it must not touch.
Symptoms and what each points to
- Ladder memory full when the conversion rungs go in. At 53 words per conversion box, 96 boxes need 5,088 words; with about 3,500 words already in use, the total passes the 7,680 ladder words this CPU family documents. That is the case this page fixes.
- Whole numbers on the graph, or every value 100 times too large. The block is still BCD or integer in memory, or the divisor register is empty. A magnitude wrong by exactly the scale factor points at the divisor.
- Nonsense on the panel for values that look right in a data view. That is a data type mismatch between register and tag, a different fault; HMI panel shows nonsense numbers from a PLC BCD analog register covers it.
- The graph object takes no decimal values. The graphing path stores decimal data only as REAL, which is the requirement that starts this job.
Where the words go
The conversion box, BCDTOR in this family, takes 53 program words per copy. The CPU specifications document 7.6K words of ladder memory for it, which is 7,680 words.
96 boxes x 53 words = 5,088 words
5,088 + 3,500 in use = 8,588 words
8,588 - 7,680 available = 908 words short
The boxes run word-hungry across the board in this family: an on-delay timer box takes 26 words where 5 words of standard logic does the same job. So the per-register layout loses before a rung is written, and the alternative is to execute one conversion sequence 96 times.
Checks before you build the loop
- Contiguity. All source words must sit in one unbroken run of V-memory and the REAL results in a second unbroken run, separate from the first. The loop addresses nothing individually, so scattered data rules it out.
- Pointer storage. Pick two unused V-memory locations outside both blocks. The sample uses V2200 and V2201; pick your own from your memory map.
- Data width. The single-word conversion path covers BCD values from 0 to 9999, the range the instruction's help documents. Wider BCD numbers need the double load, because the binary conversion acts on the whole accumulator.
- Scale. Two implied decimals means the divisor register holds 100.0 as a REAL. Decide it now; the FAQ below lists the factors for one and three decimal places.
- What you are replacing. Export one conversion-box rung with File->Export->Program and tick the "Expand IBoxes" checkbox in the Options group box. The export shows the logic the box actually generates, so you can weigh its word count against the loop.
The loop that replaces the boxes
Two rungs do the job. The first runs once and loads the block starting addresses into pointer storage:
LDA O2000
OUT V2200
LDA O3000
OUT V2201
LDA O2000 loads the address of V2000 and OUT V2200 parks it in the first pointer; the second pair does the same for V3000. Inside the loop, LD P2200 reads through that pointer, so one rung serves every source word in the table.
The second rung converts and advances:
STR SP1
FOR K96
LD P2200
BIN
BTOR
DIVR R100
OUTD P2201
INCB V2200
INCB V2201
INCB V2201
NEXT
- LD P2200 loads the BCD word the first pointer aims at. BIN converts BCD to binary, BTOR turns the binary into a REAL, and DIVR R100 divides by the REAL held in R100. Load 100.0 into R100 before the loop first runs and confirm it in a data view.
- OUTD P2201 stores the result as double data through the second pointer. A REAL occupies two V-memory words, the same layout behind displaying a PLC float stored in two word registers on an HMI, so the destination pointer bumps twice per value (two INCB V2201) and the single-word source bumps once (one INCB V2200).
- STR SP1 is the sample's rung condition; it decides when the table converts. Use the condition the application needs, such as a one-shot that converts once at startup or a permissive bit that refreshes the table while the line runs.
- The count matches the table length. The sample shipped with FOR K64 for a 64-value table; a 96-value table is FOR K96. Raise a count only after the span check in the example below passes.
- For double BCD sources, change the load to LDD P2200 and add a second INCB V2200 so the source pointer crosses both input words per value.
Example: 96 values with two implied decimals
The table holds 96 single-word BCD values with two implied decimals at V2000; results go to V3000; pointer storage sits at V2200 and V2201; the program already carries about 3,500 of the 7,680 ladder words.
Source span: 96 values at one word each is 96 words, V2000 through V2095. Pointer storage begins at V2200, 104 words above the last source word, so the source pointer stops clear of it.
Destination span: 96 REALs at two words each is 192 words, V3000 through V3191. Nothing else may live in that run.
Value check: a source of 1234 becomes binary 1234, REAL 1234.0, and 1234.0 / 100.0 = 12.34. A source of 9999 lands at 99.99. Read source BCD, converted REAL and expected value in a data view for a mid-range and a top-of-range value before trusting the block.
Memory check: 96 boxes would use 5,088 words against 4,180 free (7,680 - 3,500), 908 words short. The loop replaces them with two init rungs and one loop rung; for scale, this family runs a 26-word timer box in 5 words of standard logic. The saving is roughly 5,000 words.
Pointer check: after 96 iterations the source pointer holds the address of V2096 and the destination V3192, one step past each block. Watching both stop there on the first run confirms the count and the increments. When the REAL block reaches the panel, give the graph limits to match; setting trend graph limits for implied decimal PLC values covers that half.
When the loop is the wrong tool
If the source words are scattered, no free 192-word run exists for the results, or the only free pointer locations sit inside either span, the loop would walk through data it must not touch. A wrong span throws no error: the loop writes to whatever addresses the pointers reach. Bring the first download in with the process stopped or the outputs disabled, watch the pointers land on V2096 and V3192, and only then let the line run.
Recommendation: When a BCD table needs REAL conversion and both blocks are contiguous, replace the per-register conversion boxes with the pointer loop: initialize two pointers, load through the first (LDD for double BCD), BIN, BTOR, DIVR with the scale loaded as a REAL, OUTD through the second, bump the source pointer once per value (twice for double BCD) and the destination twice, and set the count to the number of values. On a 96-value table that reclaims roughly 5,000 ladder words against 5,088 for the boxes. If either block is scattered or a span would collide with pointer storage, keep individually addressed logic and free memory some other way.
If the same floor also needs a notice or status screen, that is the job of our shop-floor signage displays.
Questions
Can the panel's decimal-place setting replace the conversion?
Only for a numeric readout. A numeric display can show a chosen number of decimal places on raw BCD data, but that formatting lives in the panel and changes nothing in PLC memory. A graphing object that stores decimal values reads REAL data, so the PLC has to hold the converted block. Use the display setting for operator readouts and the conversion loop for anything the panel must store or graph.
What divisor matches one or three implied decimals?
The divisor register holds the scale as a REAL value: 10 for one implied decimal place, 100 for two, 1,000 for three. Load the factor before the loop runs and confirm it in a data view, because a clean conversion with the wrong divisor still puts the decimal point in the wrong place. Match the factor to the source data's actual decimal convention.
Does this loop structure transfer to other PLC families?
The structure transfers, the mnemonics do not. Any PLC with pointer or indirect addressing, a FOR/NEXT loop, BCD-to-binary and binary-to-REAL conversions and a REAL divide runs the same sequence: load through the pointer, convert, scale, store through the second pointer, bump both. Match each step against your manual's conversion and loop instructions and check the documented range of the single-word BCD load before widening it.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.