Van

MrPLC Member
  • Content count

    33
  • Joined

  • Last visited

Everything posted by Van

  1. Moving Literals

    Is it possible to move literal text/string into memory? For example, to move a literal hex value one does this: MOV #41 H150 and that moves hex 0x41 ("A") into memory location H150. but I would like to do something like this: MOV$ "TEST" H150 How would one go about this? I am trying to avoid having to have four MOV commands using hex.
  2. Question 1: How do you address just one-half (i.e. one byte) of a word? For example, D100 addresses an entire WORD (i.e. 16 bits or two bytes). What if I wanted to access just ONE-HALF of that address? I know I can address it in BIT form (i.e. D100.0, D100.1, etc). Can you do it in byte form? Question 2: How does one move/copy/distribute just one BYTE from one address to another? The MOV command moves a WORD (i.e. two-bytes). I want to move just one-half of a word (i.e. one byte). Here is what I am trying to do: I want to create a contiguous memory space of data that will be composed of data from other non-contiguous memory locations. For example, lets say my contiguous memory space is D1000-D1007 (i.e. 8 words, 16 bytes). I want to assign the first byte at address D50 to the first byte at address D1000 and the second byte at address D59 to the second byte at address D1000: D1000 = (D50.0-7) + D59.(8-15) How does one accomplish this?
  3. I have posted before that I am PC programmer with some PLC experience. I am reading the programming manual but have not seen anything that could answer my question (probably not looking in the right place). Is it possible to address memory using mathematics instead of hard coding it? Let me provide and example of what I would like to do. I have an output module (ex. OC211). This module has 16 bits (ex. 0.00 - 0.15). Through some other means the PLC receives information. Based on the data received by the PLC we would like to use mathematics to address certain memory locations. For example, lets say that I received the number six (6) in a memory location (say D1000). Would it be possible in ladder logic to address point "six" (0.06) using a mathematical expression versus hard coding? Here it is in suedo code: bit to set ( 0.00 + ( D2000 * 0.01 ) )
  4. In CX-Programer, RIGHT-CLICK on the program section and there is an option to view it in mnemonic.
  5. I have two PLCS: CJ1M-CPU12-ETN (built in Ethernet) and a CJ1M-CPU11 + CJ1W-ETN21 According to the manual, the ethernet modules are the same (ENT21). The version codes are the same (V1.4). I have configured both Ethernet modules (CPU built-in and the CJ1W) with the same UNIT NO so that our PLC code is portable between both units. However, the socket TCP function block code DOES work on the CPU11 + CJ1W-ENT21 but will NOT work on the CJ1M-CPU12-ETN. Am I missing something?
  6. A big thanks to everyone for their help. I wrote a test application and used the PLC simulator (CXL-Programmer 7.2) to try and understand just what was actually happening. I didn't just want to know WHAT DIFU does but HOW it actually worked. My suspicions were correct. Using Multiple DIFUs for the same memory address is detrimental. Although it doesn't say it in the manual, in reality you should only use DIFU once per memory address. This may be common knowledge to you PLC folk. Attached are two little application I wrote. DIFU_TEST_GOOD - shows a typical application using a DIFUs with each having it's own memory address. DIFU_TEST_BAD - shows an application using two DIFUs using the same memory location (W0.00). Note RUNG 2. If you run DIFU_TEST_BAD in the simulator the PLC simulator behaves unpredictably (exactly what is happening in my real PLC). I noticed a couple of scenarios happening: 1) Stepping through the code (SET W0.00 ON) you will notice that in just the same scan DIFU will change states twice. If W0.00 is ON, W0.01 will go ON in RUNG 1 however, in RUNG 2 if W0.02 is OFF, W0.01 will go OFF. 2) OR; Stepping through the code (SET W0.00 ON) you will notice that the DIFU in RUNG 1 does nothing to W0.01. If in RUNG 2: 2A) W0.02 is ON, W0.01 will go ON. 2B) W0.02 is OFF, W0.01 will stay OFF. It would appear that a DIFU instruction is always evaluated at every occurrence irregardless of the logic in front of the instruction. In other words, every DIFU instruction is processed using some logic similar to the following: IF DIFU = TRUE THEN DIFU = FALSE ELSE IF LOGIC=TRUE THEN DIFU = TRUE Also note. The DIFU'd bit changes state at a every scan. For a DIFU, a scan appears to be a loop FROM the DIFU location back to the DIFU. Again, that may be common knowledge to you PLC folk but in the PLC programmers manual I read, a scan was defined to be from TOP of PLC code to BOTTOM of PLC code. That made it confusing to me. DIFU_TEST_BAD.cxp DIFU_TEST_GOOD.cxp
  7. Equipment: CJ1M-CPU12 I have mentioned before that I am a PC programmer learning how to program PLCs so please keep this in mind. I think like a PC programmer. I read about DIFU (and DIFD) and thought this was the neatest tool. So, I used it all over my programs. However, I starting to think this is also part of my problem. I suspect DIFU is a two-edged sword. My program behaves irrationally. It sometimes works and sometimes doesn't. I can't figure it out. I am using the DIFU for the same bit in multiple rungs of a task and in multiple tasks. I suspect this might be my problem. I just realized that, although only one task/rung may execute the DIFU instruction on the bit - I don't know when the bit truly gets set and reset. Is the bit reset when the same DIFU that flipped the bit is encountered on the next scan? Or is the bit reset on the very next encounter of a DIFU instruction? Or is the bit reset at the very end of the current scan or the beginning of the next scan? Am I guaranteed that the bit will survive a complete scan before it's reset (i.e. every rung of every task will have access to the high signal?)? If so, then What is a complete scan to DIFU? Also, does it matter where DIFU you is in the program? Can I DIFU on TASK 30 and TASK 2 still get the signal? Here is an example of logic in pseudo code: BEGIN SCAN **** TASK A **** RUNG 1: if BIT-AA then DO STUFF RUNG 2: if BIT-A then DIFU BIT-ZZ **** TASK A **** **** TASK B **** RUNG 1: if BIT-BA then DO STUFF RUNG 2: if BIT-B then DIFU BIT-ZZ RUNG 3: if BIT-BB then DIFU BIT-AA **** TASK B **** **** TASK ZZ **** RUNG 1: IF BIT-ZZ then DO STUFF RUNG 2: IF BIT-ZA then DIFU BIT-AA RUNG 3: IF BIT-ZB then DIFU BIT-BA **** TASK ZZ **** END SCAN Is the above logic valid for DIFU? I suspect that there is something wrong with my logic here.
  8. It's up to the programmer. The programmer can do it: 1) at the top of every loop (scan) 2) at the bottom of every loop (scan) 3) at the next pass of the function/command/method that is responsible for the bit. Could be in the middle of the loop. This is why I ask the question: At what point does the signal actually rise and fall. If I DIFU a bit in the middle of the curent scan, is the bit ON for the rest of the current scan or, does he bit remain off until the start of the NEXT scan?
  9. I would like to better understand the above statement: BEGIN SCAN ONE *** TASK A *** RUNG 1: IF AA then Do Stuff (<---- AA False) RUNG 2: Do Stuff *** TASK A *** *** TASK B *** RUNG 1: IF BB then DIFU AA (<--- BB is TRUE this scan so AA goes from False to True) RUNG 2: Do Stuff *** TASK B *** *** TASK C *** RUNG 1: IF AA then Do Stuff (<---- Is AA True of False?) RUNG 2: Do Stuff *** TASK C *** END SCAN ONE BEGIN SCAN TWO *** TASK A *** RUNG 1: IF AA then Do Stuff (<---- Is AA True or False?) RUNG 2: Do Stuff *** TASK A *** *** TASK B *** RUNG 1: IF BB then DIFU AA (<--- Is this where AA is reset to false again? (BB is FALSE this scan) ) RUNG 2: Do Stuff *** TASK B *** *** TASK C *** RUNG 1: IF AA then Do Stuff (<---- Is AA True or False?) RUNG 2: Do Stuff *** TASK C *** END SCAN TWO
  10. Equipment: CJ1M-CPU12 ETN (ETN21) Using the CPU's ENT21 and the CPU's RS232 I have programmed three tasks: 1. XMT - Transmit data to my FUJI inverters via RS232. 2. RCV - Receive data from my FUJI inverters via RS232. 3. NET - Network send/recv via ETN21. If I enable the NETWORK task, the RCV task will no longer receive RS232 traffic. However, if I disable the NETWORK task, the RCV task works just fine. I have poured over and over and over my Symbols and memory assignments to make sure nothing is stepping on one another. I have run the Validate Symbols, etc. I went back to the manuals to find if I could not use both I/O devices at the same time. I can't seem to find anything mentioned like that (nor did I expect too). I am at a loss as to why that when the NETWORK is enabled (using Omron TCP function blocks OPEN, CLOSE, SEND, and RECV) the RS232 WILL TRANSMIT data but WILL NOT RECEIVE data. I know data is being sent back (used a sniffer and I can see it) and, like I said, if I disable the NETWORK task it works fine. Anyone have any idea why this is occurring?
  11. OK, I found it. My Bad. I was looking in the wrong manual. The Ethernet Units Construction of Applications (not Networks) section 6-6 has my answer.
  12. Equipment: CJ1M-CPU12 with CJ1W-ENT21 I have successfully programmed the PLC to accept a TCP socket connection (Passive TCP) and write data to and from the PC. However, I noticed that when I disconnect the TCP port (simulating a closed/lost connection) the PLC keeps the port open and will not accept another connection. I want to monitor for a lost or closed connection so I can reset (close and reopen) the port. I know that I need to do this but I can't seem to trap the lost connection. There doesn't seem to be any documentation on lost connectivity. How do I trap for a lost or closed TCP socket connection?
  13. Is there a way to add entries to the PLCs error log? I dont' see an instruction in the help that appears to permit this.
  14. More TKON - Interrupt Tasks

    What you have described is exactly what is happening. I will look into "subroutines". Thank you.
  15. Equipment: Omron CJ1M-CPU11 I read the programming manual and the instruction manual. Either the manual is missing something (doubt it) or I am overlooking something obvious (more likely)... I am attempting to use an interrupt task as a subroutine/function to be called from the main code (cyclical tasks) to populate memory space. According to the manual, when an interrupt task is called (via. TKON) from a cyclical task the execution is immediate: branches at TKON; executes the interrupt task; returns to the TKON interrupt point. I see this working however if I make multiple calls to my interrupt task from the same cyclical task (but separate rungs) in the same pass only the last called TKON is executed (i.e. last condition set for the TKON routeine to work from). I can see this by monitoring the memory space the interrupt task is writing too (a circular buffer). There should be TWO buffer (memory) writes but only the last call is writing to the buffer memory space. The PLC appears to be acting as if the changes to the memory space have not been committed at the end of the interrupt task. That is, only the last "push to stack" is being executed. Now, If I disable either rung it works properly. I did see this little blurb in the instruction manual: Immediate Refreshing Specification Not supported. I have a sneaky suspension I am about to learn what this really means. Do I have to wait for the cycle to finish before making the next TKON call? pseudo code: === BEGIN PASS === *** Cyclical Task 00 START -- SECTION 01 BEGIN RUNG 1: Set Data for TKON RUNG 2: CONDITION TRUE--->TKON(8011) RUNG 3: Set Data for TKON RUNG 4: CONDITION TRUE--->TKON(8011) -- SECTION 01 END *** Cyclical Task 00 END === END PASS === *** Interrupt Task 8011 START (do stuff here) *** Interrupt Task 8011 END
  16. Overview Want to contract and experienced Omron PLC programmer to write FB's to communicate to Fuji FRENIC motor inverters via Modbus RTU. Equipment: * Omron CJ1M-CPU11 (or 12 if needed) * Omron SCU21-V1 * Fuji FRENIC Inverters (MINI and 5000G11S) Scope of Work The desired result is to have a set of FBs (Function Blocks) to simplify sending command data and reading monitoring data via Modbus RTU with Fuji motor inverters. The following functions must be implemented: * Set the inverters current frequency (S01) * Read the inverters current frequency (M06) * Set motor direction (S06) * Read output current (M11) and voltage (M12) * Read ALARM value * Reset ALARM Absolutely no blind command data communications. In other words, it is expected that the function block will confirm all command data communications with the inverter (i.e. check the inverters response to command data). The FB should return an error if the inverter doesn't respond within a reasonable time frame or returns and error code. As for monitor data communications, the FB should return an error if the inverter doesn't respond within a reasonable time frame . We are open to suggestions, recommendation and solutions. The end result is to have a simplified method of injecting code into ladder logic to control and monitor the inverters. What we are looking for is something similar to the Omron supplied inverter FB's for the 3G3MV and 3G3RV series inverters. We understand that the candidate will most likely not have a Fuji inverter to test with. We will have a PC configured for you to remote terminal into via the internet and run CX-Programmer to test your code. The PC will be connected to the PLC that will be connected to an inverter with a motor. Time Frame As usual we needed it yesterday - ASAP. Reference Documentation * Fuji FRENIC Mini RS485 MEH448 (best resource for Modbus communications) * Fuji FRENIC-5000G11S : Technical Information Manual MEHT544 (has more info on communications) * Fuji FRENIC-MINI : Instruction Manual INR-S147-0791C-e * Fuji Website: http://www.fujielectric.co.jp/fcs/fdm/eng/index.html Terms * We want a fixed price for this project. No hourly rates. * 50% will be forwarded upon receiving partial working code (i.e. submit ONE working function block, like read inverter frequency, to show your viable progress.). * Final 50% upon project completion. * Additional work will most certainly follow. * We can pay via direct deposit or paypal. This is real work. Please do not waste our time if this is not truly in your skill set. Please PM me here or contact me via email.
  17. @Sergei Troizky: You were right, there was nothing truly wrong with the math when viewed in decimal. Thank you for that hint. I did find that I was using the wrong indirect addressing operand. I was using "*" and should have been using "@". That made the difference and now it's working. I have two PLCs: development and production. Dev: is a CJ1M CPU11 Prod: is a CJ1M CPU12 The difference, from what I was told, is addressable space. The CPU12 has more memory than the CPU11. But don't take my word for it. I'm not an expert. I'm only repeating what the Omron dealer told me.
  18. Thank you. I will double check my view (i.e. HEX vs DEC). I am using a CJ1M - CPU11 (and CPU12).
  19. OK. I'm having trouble understanding how to properly perform the math to do Indirect Addressing. Here is my setup: I have allocate some memory space to use as a circular buffer: D5900-D5999. Each buffer segment size is nine (9) continuous words. I have a FOR/NEXT loop that loops through each buffer segment and evaluates the first element (word) of each buffer segment to see if that buffer segment is available for use. For right now, there are only nine buffer segments. I am having trouble doing the multiplication and addition. I keep coming up with invalid memory addresses like 596A (i.e. HEX addresses) instead of it properly rolling over after 9 to next memory word location. In the FOR/NEXT I increment a multiplier starting at zero (0). I then take that multiplier and multiply it by nine (9) (the buffer segment size) and then add it to the starting memory location (D5900). Once I establish the base, I then attempt to create the remaining eight (8) element addresses by adding one (1) to the previous memory address. 0 (multiplier) X 9 (buffer segment size) = 0 (memory offset) 5900 (base memory address) + 0 (memory offset) = 5900 (first buffer element (word) ) 5900 + 1 = 5901 (second buffer element (word) ) 5901 + 1 = 5902 (third buffer element (word) ) ... and so forth to nine (5909). now, ZERO works great, however I have a problem when I want to use a multiplier greater than zero (0). Here is the mnemonic code: ' Circular Buffer.\nLocate an available memory space. FOR(512) XMT_SF_QUEUE_SIZE ' Check for invalid state. LDNOT XMT_SF BREAK(514) ' Increment Data Buffer Offset. LD XMT_SF ++(590) XMT_SF_DB_ADDR_MULT ' Compute and set memory offsets.\nThis is for use with indirect addressing. LD XMT_SF *(420) XMT_SF_DB_ADDR_MULT XMIT_SF_DB_SIZE XMT_SF_DB_ADDR_OFFSET +(400) XMT_SF_DB_ADDR_OFFSET XMT_SF_DB_BASE_MEM XMT_SF_DB_ADDR_STATE +(400) XMT_SF_DB_ADDR_STATE &1 XMT_SF_DB_ADDR_W01 +(400) XMT_SF_DB_ADDR_W01 &1 XMT_SF_DB_ADDR_W02 +(400) XMT_SF_DB_ADDR_W02 &1 XMT_SF_DB_ADDR_W03 +(400) XMT_SF_DB_ADDR_W03 &1 XMT_SF_DB_ADDR_W04 +(400) XMT_SF_DB_ADDR_W04 &1 XMT_SF_DB_ADDR_W05 +(400) XMT_SF_DB_ADDR_W05 &1 XMT_SF_DB_ADDR_W06 +(400) XMT_SF_DB_ADDR_W06 &1 XMT_SF_DB_ADDR_W07 +(400) XMT_SF_DB_ADDR_W07 &1 XMT_SF_DB_ADDR_CS ' Is this buffer (memory) space available for use? LD XMT_SF LD=(300) *XMT_SF_DB_ADDR_STATE XMT_SF_DB_STATE_AVAIL OR=(300) *XMT_SF_DB_ADDR_STATE #0000 ANDLD SET XMT_SF_DB_AVAIL BREAK(514) NEXT(513) LD XMT_SF ANDNOT XMT_SF_DB_AVAIL MOV(021) EC_XMT_SF_DB_FULL XMT_SF_ERROR_CODE Where am I going wrong?
  20. *sigh* Of coarse, how obvious (now). I was making a mountain out of a mole hill. Thank You!
  21. I thought I understood the ASC command but it seems I don't and I have been pulling my hair out trying to figure this out... (I'm a rookie PLC programmer). I have the math done. I see my word (D500) and it contains 0FA0 (i.e. 4000). What is stumping me is converting the WORD containing 0FA0 to it's true ASCII equivalent of "0FA0" (i.e. four bytes / two words). I think I am missing a step/command and I'm not to sure where to turn and read.
  22. Thank You! It is very similar to C/C++. '*' is something I understand very well!
  23. Do you need to call TKOF at the end of an interrupt task? In my cyclical (main) task I use the TKON instruction to execute an interrupt task. Do I need to call TKOF within (i.e. the end of) the interrupt task? Or, because the task is defined in CX-Programmer as an interrupt task, once it reaches the END statement the PLC automatically turns the task off?
  24. Well, I add that instruction to the final RUNG in the task just above the END rung and my code STOPPED working. I removed it and it worked. Is this model dependent? I'm running a CJ1M.
  25. BTW, for those who find this thread later, I found that MOVD(083) worked perfectly for me. A digit is four bits therefore you would issue a MOVD command to move two digits (i.e. one byte).