MP STUDIO 2 · Memory · V1.3.0 and later ====== MP STUDIO 2 · Indexed Addresses (Pointers) ====== An indexed address, such as ''D100[D0]'', lets an instruction read and write the cell found by adding an index value to a base address (V1.3.0 and later). If ''D0'' is 3, the instruction uses ''D103''. By changing only the index value, you can step through data laid out like a table, such as recipe setpoints or a log buffer. [[#examples|View examples]] [[#writing_an_indexed_address|How to write one]] {{ :en-us_products:mp_studio:ix-hero.png?1600 |The whole MP STUDIO 2 window while an example program runs in simulation, with indexed cells showing their values and the cells they point to }} ^ Notation ^ Base area ^ Index ^ Version ^ | ''D100[D0]'' | D, DD, C, DC, R | D or C word, ''##name'' | V1.3.0 and later | * **Counts like an array**\\ The index counts in elements. For ''DD'' and ''DC'', one element takes two numbers. * **Out of range is skipped**\\ If the cell pointed to is outside the area, only that instruction is skipped and ''@IXERR'' turns on. No other memory is overwritten. * **Shows the cell pointed to**\\ During monitoring and simulation, an indexed cell shows its value together with the cell it points to, as in "2000 (→D103)". * **No change if unused**\\ A program that does not use indexed addresses uses the same memory and execution time as before. **On this page** * [[#writing_an_indexed_address|Writing an Indexed Address]] * [[#base_areas_and_indexes|Base Areas and Indexes]] * [[#cells_that_accept_an_indexed_address|Cells That Accept an Indexed Address]] * [[#cells_that_cannot_take_an_indexed_address|Cells That Cannot Take an Indexed Address]] * [[#out_of_range_and_ixerr|Out of Range and @IXERR]] * [[#input_assistance|Input Assistance]] * [[#monitoring_and_simulation|Monitoring and Simulation]] * [[#examples|Examples]] * [[#things_to_check|Things to Check]] ~~NOTOC~~ ===== Writing an Indexed Address ===== An indexed address takes the form ''base[index]''. C-style pointer forms such as ''*D0'' and ''&D100'' cannot be used. - In the ladder, select a value cell of an instruction (for example IN of ''MOVE'') and enter ''D100[D0]''. You can also type the whole instruction on one line in the Insert Function window (''Ctrl+E''), as in ''MOVE D100[D0] D200''. - Press ''Enter'' to confirm the cell. Lowercase letters and spaces inside and around the brackets are tidied up when you confirm (''d100[ d0 ]'' → ''D100[D0]''). As with an array in C, the index counts in elements. For ''D'', ''C'' and ''R'', the address points to the cell that is the index away from the base. For ''DD'' and ''DC'', where one element takes two numbers, it points to the cell that is twice the index away, so elements never overlap. ^ Address in the cell ^ Index value ^ Cell the instruction uses ^ | ''D100[D0]'' | ''D0'' = 3 | ''D103'' | | ''C10[D1]'' | ''D1'' = 5 | ''C15'' | | ''DD100[D0]'' | ''D0'' = 1 | ''DD102'' (''D102'' and ''D103'') | | ''R5[D0]'' | ''D0'' = 2 | ''R7'' | If you write a number as the index, the address becomes a fixed address. ''D100[3]'' is written as ''D103'', ''DD100[3]'' as ''DD106'' and ''R5[2]'' as ''R7'', and a notice such as "Wrote D100[3] as D103." is shown. {{ :en-us_products:mp_studio:ix-fold.png?900 |Figure 1. D100[3] entered in IN of MOVE, changed to D103, and the notice }} ===== Base Areas and Indexes ===== ^ Part ^ Can be used ^ Cannot be used ^ | Base address (area pointed into) | ''D'' word, ''DD'' double word, ''C'' word, ''DC'' double word, ''R'' real | ''P'', ''M'', ''T'', ''BD'', ''WM'', user variables and so on | | Index (inside the brackets) | ''D'' or ''C'' word address, ''##name'' user word (for example ''D100[##IDX]'') | ''DD'', ''DC'', ''R'', ''###name'', ''#name'' | Nested brackets (''D100[D0[D1]]''), a bit suffix (''D100[D0].3'') and two addresses inside the brackets cannot be used either. If you write something that cannot be used, if the base address has a negative number, or if the index is a number outside the data memory area (for example ''D100[D9999]''), the cell turns red and the program cannot be compiled. The index value is read as a signed 16-bit number (-32768 to 32767), so a negative index can point to cells before the base address. The range you can point to is the size of that area set in [[:en-us_products:mp_studio:memory_symbols#data_memory|Data Memory]]. What happens outside that range is described in [[#out_of_range_and_ixerr|Out of Range and @IXERR]]. The index value is read once, when the instruction starts. Even if the same instruction changes the index, the result goes to the cell the index pointed to at the start. For example, ''DIV 7 2 D100[D0] D0'' writes the remainder to ''D0'' and the quotient to the cell that ''D0'' pointed to when the instruction started. ===== Cells That Accept an Indexed Address ===== Indexed addresses can be used in the value cells of instructions and in compare contacts. They work as if you had written the address of the cell pointed to in that place, and orange warnings appear under the same conditions. ^ Category ^ Cells that accept an indexed address ^ | Comparison | IN1 and IN2 of comparison functions · comparisons written in contact cells (for example ''D100[D0]>D9'') | | Conversion | IN and OUT of ''H2D'', ''D2H'', ''INV'' and ''NEG'' | | Math | All cells of ''ADD'', ''SUB'', ''MUL'' and ''DIV'' · ''INC'' and ''DEC'' · the six cells of ''SCALE'' · ''FLOOR'' and ''SQRT'' | | Counter | SET VALUE of ''CTU'', ''CTD'' and ''CTUD'' · ''HCNT'', ''ENCODER'', ''ENMOV'' and ''HRST'' | | Timer | SET VALUE of ''TON'', ''TOFF'', ''TPL'', ''TMON'' and ''TMR'' | | Word Logic | All cells of ''WAND'', ''WOR'', ''WXOR'', ''SHL'', ''SHR'' and ''SWAP'' | | Analog | All cells of ''ADC'', ''ADC2'' and ''DAC'' · ''AFILTER'' · ''NTEMP'' and ''PTEMP'' · ''PWM'', ''FPWM'', ''FDPWM'', ''NPWM'', ''POFF'' and ''PSR'' · all cells of ''PID'' · ''PID_PWM'' (except PORT) | | MOVE | All cells of ''MOVE'', ''GMOVE'' and ''FMOVE'' | | Data Processing | All cells of ''MAX'', ''MIN'', ''SUM'', ''AVE'', ''MUX'', ''ENCO'' and ''DECO'' | | Serial Port | CHANNEL, DATA and LENGTH of ''PUT'' · CHANNEL, LENGTH and OUT of ''GET'' · ''PUT_LEN'' and ''GET_LEN'' · ''SERID'' and ''SERRATE'' · ''MNET'' and ''MNET_READ'' | | I2C | ADDRESS of ''ISTA'' · ''IWR'' · OUT of ''IRD'' · ''ISR'' · ''IBR'' | | CLCD (Character LCD) | ADR and the value cells of ''CINI'', ''CLOC'', ''CSTR'', ''CINT'', ''CREAL'', ''CHEX'', ''CCLS'', ''CCON'', ''CCOF'', ''CPUT'' and ''CGET'' (except the cells listed below) · PAGE of ''CSCR'' | | 7-Segment | IN, POSITION, LENGTH and DOT of ''FINT'' · ''FDATA'' · PAGE of ''FSCR'' | | DS3231 (RTC) | All cells of ''DS3231_WR'' and ''DS3231_RD'' | In instructions that work through several cells in order, such as ''GMOVE'', ''FMOVE'', ''MAX'', ''MIN'', ''SUM'', ''AVE'', ''MUX'', ''PUT'' and ''GET'', the indexed address becomes the start cell. > **A block instruction does not run if its last cell is outside the area** > Every element from the start element to the last cell the instruction reaches must be inside the area. The instruction reaches N elements for ''GMOVE'', ''FMOVE'', ''MAX'' and the like, the Nth element for ''MUX'', and LENGTH bytes for ''PUT'' and ''GET''. For example, if the D area is ''D0'' to ''D255'' and ''D0'' is 152, IN of ''GMOVE D100[D0] D200 5'' covers ''D252'' to ''D256'' and is out of range. Except for ''MUX'', if N is 0 (for ''MAX'', ''MIN'', ''SUM'' and ''AVE'', if N is 0 or less), the instruction does nothing and the range is not checked. For ''MUX'', an N of 0 selects the start element. ===== Cells That Cannot Take an Indexed Address ===== If you write an indexed address in the cells below, the cell turns red and the program cannot be compiled. Select the cell to see the reason in the Inspector, or hover over it to see the reason in a tooltip. ^ Type ^ Cells ^ Reason shown ^ | Cells that take only a fixed address | Contact, coil and edge cells · TIMER of timers (''T0'') and COUNT of counters (''C0'') · RESET of ''CTU'', SET of ''CTD'', and CU, CD and RESET of ''CTUD'' · ''JMP'', ''JMPN'' and ''LABEL'' · READ of ''ISTA'' · ACK of ''IRD'' · TYPE of ''CINI'' · DEFINE of ''CPUT'' · STRING of ''CSTR'' · ZERO and SIGN of ''CINT'', ''CREAL'' and ''FINT'' · ZERO of ''CHEX'' · PORT of ''PID_PWM'' | "D100[D0] is an indexed address, which this cell cannot take, so the program does not compile. Indexed addresses are only for an instruction's value fields (e.g. IN and OUT of MOV) and comparison contacts — write a fixed address such as D100 here." | | Cells that take only a constant | ADR of ''CSCR'' · DSP of ''FSCR'' · NUM of ''MCS'' and ''MCSCLR'' · CLK and DIO of ''FINI'' · NO of ''MBTRIG'' and ''UPTRIG'' · DIGIT of ''CREAL'' | "The ADR field of CSCR takes only a constant, so it cannot take an indexed address (D100[D0]) and the program does not compile. Write a constant (a number) in this field." | {{ :en-us_products:mp_studio:ix-red-reason.png?1000 |Figure 2. An indexed address written in the TIMER cell of a timer, shown in red, and the reason in the Inspector }} ===== Out of Range and @IXERR ===== If the element an index points to is outside its area (the size set in Data Memory) while the program runs, the PLC does the following. * It skips only that instruction. No other memory is overwritten. * The power output of that instruction turns off. A compare contact becomes false, so the coil after it turns off. * The system bit ''@IXERR'' turns on. The SET VALUE of timers and counters is range-checked even while the rung is off, so ''@IXERR'' can turn on then too. During monitoring and simulation, a notice appears the moment ''@IXERR'' turns on, together with the row of the last instruction the PLC skipped (and the tab name if there are two or more tabs). The notice appears even if the ladder has no ''@IXERR'' contact. {{ :en-us_products:mp_studio:ix-out-sim-marked.svg?1000 |Figure 3. An index out of range in simulation }} * **① Out-of-range cell:** ''D0'' is -200, so the address points outside the area before ''D100'' and is shown in red as "Out of range (D0 = -200)". ''MOVE'' is skipped, so ''D200'' keeps its previous value. * **② ''@IXERR'' rung:** ''@IXERR'' is on, so the coil after it is on. * **③ Notice:** "An index went out of range — @IXERR is on and that instruction was skipped. (last: row 0)" > **@IXERR does not turn off by itself** > ''@IXERR'' stays on even after the index comes back into range. Turn it off with a RESET coil (''@IXERR'') in the ladder, or by writing 0 to it in the Data Table during monitoring or simulation. Unlike the other ''@'' system bits, ''@IXERR'' accepts a written 0. After a download, it starts off. ''@IXERR'' also turns on when ''BSFT'', ''BRST'' or ''BSETN'' of the [[:en-us_products:mp_studio:bit_control|bit control functions]] goes outside its area while running, or when one cycle of ''TFLK'' does not fit in its timer (V1.4.0 and later). In a program that does not use indexed addresses, the notice appears only when ''@IXERR'' is on the ladder screen or in the Data Table, so check it with an ''@IXERR'' contact in the ladder. ===== Input Assistance ===== ==== Index Candidate List ==== When you type up to ''D100['' in a cell input box (contact editing, a function argument cell, or the Insert Function or Edit Function window), a list shows only what can be used as an index. **Index candidates — addresses used in this program** lists the ''D'' and ''C'' word addresses and ''##name'' user words used in the current tab that can serve as an index, and **Registered symbols** lists the symbols of those addresses, up to 8 in each group. {{ :en-us_products:mp_studio:ix-complete.png?470 |Figure 4. Index candidates shown after typing MOV D100[ in the Insert Function window }} Choose a candidate with ''↑'' and ''↓'' and press ''Tab'' or ''Enter'' to insert it (''Tab'' without a choice inserts the first candidate), or click it. Only the part after ''['' is replaced, and '']'' is added (unless it is already there). If the letters before ''['' are not ''D'', ''DD'', ''C'', ''DC'' or ''R'', or if the cell does not accept an indexed address, the usual autocomplete appears. ==== Using Symbols ==== You can use symbols for the base address and the index. If ''RECIPE'' is the symbol of ''D100'' and ''IDX'' the symbol of ''D0'', entering ''RECIPE[IDX]'' in a cell is saved as ''D100[D0]''. With **View → Show Symbols** on, the cell shows "RECIPE[IDX]", and the comment shown is that of the base address. You cannot register an indexed address as a symbol in the symbol table. {{ :en-us_products:mp_studio:ix-symbol.png?1000 |Figure 5. A RECIPE[IDX] cell in the ladder with symbols shown }} ==== Same-Address Highlighting and Line Breaks ==== When the cursor is on a ''D0'' cell, cells that use ''D0'' as an index get a dotted border. When the cursor is on a ''D100[D0]'' cell, the ''D100'' and ''D0'' cells are highlighted too. In a cell, a long address breaks onto a new line before ''['' (''DD1000'' / ''[D10]''). Printing works the same way. ===== Monitoring and Simulation ===== During monitoring and simulation, an indexed cell shows its value together with the cell it points to now. In simulation, the range check, ''@IXERR'' and the last row in the notice work the same as on the PLC. The range check and ''@IXERR'' also work in functions that are not simulated (such as ''PUT''). {{ :en-us_products:mp_studio:ix-monitor-marked.svg?1000 |Figure 6. Values and the cells pointed to, shown in indexed cells during simulation }} * **① Indexed cell:** shows the value and the cell it points to now, as in "2000 (→D103)". * **② Index ''D0'':** the value of the index register (3). * **③ Result ''D200'':** the value that ''MOVE'' copied (2000). ^ Shown as ^ Meaning ^ | "2000 (→D103)" | The value and the cell pointed to. A double word is shown as, for example, "70000 (→DD102)". | | "— (→?)" (dimmed text) | The instruction has not run yet, so the cell pointed to and its value are unknown (shown only on the canvas and in the Inspector). | | "Out of range (D0 = -200)" (red text) | The index is out of range now. | The canvas and the **Current value** in the Inspector show the cell the instruction pointed to when it last ran, while the Watch card and the Data Table show the cell the index points to now, in the same form. If you change the index while the rung is off and the instruction does not run, the two can show different cells. A block cell such as IN of ''GMOVE'' shows only the start cell, as in "(→D252)". The power flow of a compare contact is drawn from the result the PLC actually compared; a cell that is out of range or has not run yet is false. Right after the index value changes, the cell shown follows one read later. ==== Writing Values ==== Select an indexed cell and open **Write Value to Memory** (''Alt+Enter''). **Address** shows the cell it points to now, as in "D100[D0] → writes to D103", and the value is written to that cell. You cannot write to a cell that has not run yet. {{ :en-us_products:mp_studio:ix-write.png?440 |Figure 7. The Write Value to Memory window opened from an indexed cell }} ==== Data Table ==== If you add ''D100[D0]'' as a row of the Data Table, its value is shown as "2000 (→D103)", and a value you write goes to the cell it points to now. If the index is out of range or the cell pointed to is not known yet, the value is not sent and the reason is shown. The **Symbol** column shows "RECIPE[IDX]", and if you enter, for example, ''RECIPE[D7]'' there, the address becomes ''D100[D7]''. {{ :en-us_products:mp_studio:ix-datatable.png?780 |Figure 8. The Data Table with an indexed address row }} ==== Used Data ==== In **Run → Used Data**, the base element and the index register are painted as used, and the cells from the base element to the end of the area are hatched as cells the index can reach. If the index is a ''##name'' user word, that index is not shown in this window. {{ :en-us_products:mp_studio:ix-usedata-marked.svg?425 |Figure 9. Cells after D100 that the index can reach, in the Used Data window (D Memory) }} * **① Used cells:** the base element (''D100'' in the figure) and the index register are painted. * **② Hatching:** cells the index can reach. Hover over one to see "D100[D0] can reach this far · with a negative index it also reaches the addresses before it". * **③ Legend:** **Reachable by index** ===== Examples ===== You can write both examples in order in a new ''MPA-8A8R(T)'' project (default data memory) and check them in simulation. ==== Example 1. Choosing a Setpoint by Recipe Number ==== In this example, ''D100'' to ''D109'' hold the setpoints of 10 recipes, and each press of ''P0'' copies the value of the next recipe to ''D200''. - In **Settings → Symbol**, register RECIPE for ''D100'', IDX for ''D0'', NOW_SV for ''D200'', NEXT_BTN for ''P0'' and IXERR_LAMP for ''M0''. - Write the rungs below. ^ Rung ^ Input ^ Function or coil ^ What it does ^ | 0 | ''@ON'' | ''MOVE D100[D0] D200'' | Copies the value of the selected recipe to ''D200''. | | 1 | ''P0'' → rising edge | ''INC D0'' | Selects the next recipe each time ''P0'' is pressed. | | 2 | ''D0>=10'' (compare contact) | ''MOVE 0 D0'' | Returns to the first recipe after the tenth. | | 3 | ''@IXERR'' | Coil ''M0'' | Turns on when the index goes out of range. | Start **Run → Simulation**, write 1200, 1500, 1800, 2000 and 2500 to ''D100'' to ''D104'' in the Data Table, and then turn ''P0'' on and off three times. When ''D0'' becomes 3, the IN cell of rung 0 shows "2000 (→D103)" and ''D200'' becomes 2000 (Figure 6). If you write -200 to ''D0'' in the Data Table, rung 0 goes out of range and is skipped, and ''@IXERR'' and ''M0'' turn on (Figure 3). ''@IXERR'' stays on even after you set ''D0'' back to 0. ==== Example 2. Logging Measurements in a Ring Buffer ==== In this example, the value of ''D10'' is logged every second into the 20 cells ''D150'' to ''D169'' in turn, and logging starts over from the first cell after the last one. - In **Settings → Symbol**, register TEMP for ''D10'', POS for ''D1'' and LOG for ''D150''. - Write the rungs below after the rungs of Example 1. ^ Rung ^ Input ^ Function ^ What it does ^ | 4 | ''@100'' | ''MOVE D10 D150[D1]'' | Every second, writes the value of ''D10'' to the cell that is ''D1'' away from ''D150''. | | 5 | ''@100'' | ''INC D1'' | Moves on to the next cell. | | 6 | ''D1>=20'' (compare contact) | ''MOVE 0 D1'' | Returns to the first cell after all 20 cells are used. | During simulation, write 25 to ''D10'' in the Data Table and wait a few seconds. The OUT cell of rung 4 shows the cell being written now, as in "25 (→D157)". In **D Memory** of **Used Data**, ''D150'' is shown as used, and the cells after it up to the end of the area are shown as cells the index can reach. ''@100'' means 1 second when the timer base is 10 ms. In a project whose [[:en-us_products:mp_studio:menus_settings#timer_base|timer base]] is set to 1 ms, use ''@1000'' instead. ===== Things to Check ===== * Indexed addresses use the user memory (USER MEMORY). Each different indexed address takes 6 bytes (an address used in several cells counts once), plus 2 bytes for the whole program. If there is not enough, "(including M bytes of hidden area used by N indexed address(es))" is added to the end of the compile error, so increase **USER MEMORY** in **Settings → Data Memory**. * Each indexed cell adds a little to the execution time. * Indexed addresses are used in ladder cells and in the Data Table. They cannot be used in the bindings of the Modbus device table or in the value fields of the CLCD Screen Editor. * If the text of a cell starts with ''['', it is read as a bookmark, not an indexed address. * The project file (''.mpx'') saves the address as written in the cell (''D100[D0]''). ===== Related Pages ===== * [[:en-us_products:mp_studio:memory_symbols|Phase 5 · Memory and Symbols]] * [[:en-us_products:mp_studio:ladder_editing|Phase 3 · Ladder Editing]] * [[:en-us_products:mp_studio:functions|Phase 4 · Functions]] * [[:en-us_products:mp_studio:monitoring|Phase 7 · Monitoring and the Data Table]] * [[:en-us_products:mp_studio:simulation|Phase 8 · Simulation]] [[:en-us_products:mp_studio|← Back to the MP STUDIO 2 User Manual]]