Sign in to follow this  
Followers 0
Michael Lloyd

I need to move some data around in a CLX

20 posts in this topic

I'm sitting here laughing at myself because I'm pretty sure what I want to do isn't particularly difficult but my brain cell is just not kicking in tonight... Here's the situation. We are delivering oil to a refinery. They want the data listed below as well as a valve status word in integer format from the PLC. I have installed a Red Lion Data Station Plus to isolate them from our measurement device and the Control Logix PLC. The DSP is a pretty slick little protocol manager that I've used in this application many times. It's rock solid. I am using an OMNI Flow Computer for flow measurement. It's probably as friendly as they come when it comes to transferring MODBUS data to / from so the hitch isn't there. Here's a list of the data that I need to move from the Omni and it's format Address Point Description 40001 3869 Clock Seconds INT 40002 7106 Meter Run #1 Pressure FLOAT 40004 7105 Meter Run #1 Temperature FLOAT 40006 7101 Meter Run #1 Gross Flow Rate FLOAT 40008 5109 Meter Run #1 Today's Gross Totalizer 32 BIT INT 40010 5110 Meter Run #1 Today's Net Totalizer 32 BIT INT 40012 5111 Meter Run #1 Today's Mass Totalizer 32 BIT INT 40014 7112 Meter Run #1 API Gravity FLOAT 40016 7809 Meter Run #1 BS&W FLOAT So far so good. The data types are in the order that I need to move them and they are the data type that the Omni supplies so no changes there. I have one integer register to pull from a CLX PLC as well as the modbus data in the Omni. This is what the refinery wants their data to look like: DESCRIPTION DATA TYPE REGISTER ADDRESS MOV STATUS (0=OPEN,1=CLOSE, 2=TRAVELLING, 3=FAIL) INTEGER (16 BITS) 40001 TIME OF DAY (SECONDS) INTEGER (16 BITS) 40002 PRESSURE (PSIG) INTEGER (16 BITS) 40003 TEMPERATURE (F) INTEGER (16 BITS) 40004 FLOW RATE (BBL/HR) INTEGER (16 BITS) 40005 GROSS TOTAL (BBL) INTEGER (LOWER 16 BITS) 40006 INTEGER (UPPER 16 BITS) 40007 NET TOTAL (BBL) INTEGER (LOWER 16 BITS) 40008 INTEGER (UPPER 16 BITS) 40009 MASS TOTAL (KLBS) INTEGER (LOWER 16 BITS) 40010 INTEGER (UPPER 16 BITS) 40011 DENSITY (API) FLOAT (LOWER 16 BITS) 40012 FLOAT (UPPER 16 BITS) 40013 BSW (%) FLOAT (LOWER 16 BITS) 40014 FLOAT (UPPER 16 BITS) 40015 They want pressure, temperature, and flow in Integer format. Their 40001 comes from the PLC. I've got that covered in the Red Lion with a direct poll of the CLX. The registers above this sentence are read registers in the Red Lion. Ie this is what they are going to read. This is getting confusing Ok- I am polling the Omni with a Prosoft MVI56E_MNETC. I am putting everything that I receive from the Omni in consecutive integers. The Pressure / Temperature / Flow variable are going to come in as two integer values. I need them to be one integer. Ie I need to convert a DINT to an INT and I want to do it without a bunch of steps. This is the problem in a nutshell... The DINT's are not an issue because I can move them as a group. I've got an array tag built that is set up like the data packet above. Once I have the array populated I'll point the Red Lion at it (Red Lions let you import L5K tags and drag/drop them on modbus registers in the device). I should add that I also have the option of polling the Omni with the Red Lion DSP but it's not so hot at DINT or REAL to INT conversion so I decided to use the Prosoft card. Both the DSP and Prosoft card are surplus from another job so no cost impact to this job.

Share this post


Link to post
Share on other sites
From my reading of your post, this sounds like the classic "transport a 32-bit Floating Point value over Modbus as two holding registers" challenge. The two Holding Registers shouldn't be treated as Integers, but rather as "two hex bytes" each. I think all you need is one COP instruction to move the four bytes represented as 40002/40003 into a REAL (call it Meter_1_Pressure_REAL), then a MOV to convert that REAL value into an INT value. Repeat three times for the sake of the next guy who has to read the code. The COP and CPS instructions are unaware of the format of the data they are copying; it's all just bytes. The MOV instruction, by contrast, automatically converts data types to and from DINT, INT, SINT and REAL. An example: "123.456" is encoded as a IEEE 754 Single-Precision Floating Point value as 0x42F6E979 (hex). That would show up in Modbus registers as 0x42F6 and 0xE979. When you COP the two Modbus registers to a REAL, the value is "123.456". When you then MOV that value to an INT, the value is "123". Edited by Ken Roach

Share this post


Link to post
Share on other sites
That's it in a nut shell. I was looking for something a little "slicker" but I guess it's not available. I mapped all of my registers in the Red Lion, with the exception of the three "evil" floating point registers. I came back here to see there was a reply that would save me from COP and MOV x 3 The structure is COP(Source,Destination,Length) where length is the number of DESTINATION elements to copy. If my source is 2 integers / 4 bytes and my destination is 1 real / 4 bytes then the length is 1 correct? For the life of me I can't figure out why they singled out those three for integer values when everything below them is a DINT or FLOAT.

Share this post


Link to post
Share on other sites
You are correct about the Length of the COP instruction: it's the number of destination elements, so COP from INT[2] to a single REAL would be Length = 1. In this case you don't have to use CPS because the data is arriving in the ControlLogix tag database via ladder logic, not asynchronously via the I/O structure. Three rungs, with a COP and a MOV on each one will make the data transformation clear to somebody who looks at this later. That's a fine investment of three rungs :).

Share this post


Link to post
Share on other sites
Ken or Michael, Can you post the rungs of this? Just wondering and wanting to see it... John

Share this post


Link to post
Share on other sites
I use structured text for these kinds of operations but I'll be happy to post it here: COP(MNETC.DATA.ReadData[1],M_PSIG,1); COP(MNETC.DATA.ReadData[3],M_DEGF,1); COP(MNETC.DATA.ReadData[5],M_FLOW,1); Valero.CS := MNETC.DATA.ReadData[0]; Valero.P := M_PSIG; Valero.T := M_DEGF; Valero.GF := M_FLOW; Bob[0]:= BSW; COP(BSW,Bob[0],4); The above is not as clean as it's going to be. The "master" (as it pertains to Modbus) programmer on the other end changed everything up yesterday. He actually made it a lot simpler for me so I'm not going to complain. The first two writes from him will be INT and then everything else will be DINT or REAL. The first three COP commands put the two integer values in MNETC.DATA.ReadData[3] and [4] into the REAL register M_PSIG. I have an MNETC card reading data from an Omni Flow computer. This data is stored as integers in the MNETC's read array tags. If you scroll down a little you'll see that I used an assignment operator (:=) to put the value in M_PSIG (REAL) into Valero.P (INT). The result is a value like 100.1232526 in M_PSIG will be 100 in Valero.P. I did this because the "master" wanted these values as integers and the Omni that I'm polling from stores them as REAL's. My task today is to rewrite all that crap since they've tripled the variable count, rearranged it, and changed it to the data type that the Omni uses. It's actually going to be a lot easier The Bob tag was a dummy tag that allowed me to give the other programmer a fake floating point value to read so he could be sure his register alignment was correct. An observant person might ask what the Valero.P tag is for. I am delivering data to the master with a Red Lion Data Station Plus via RS485. I don't want to give the "master" access to the PLC so I am firewalling the connection with the DSP. The DSP lets me import an L5K tag and use tag assignments to map modbus registers that I then assign to the slave poll list. So all I have to do in my world is build and populate an array of variables in the PLC that lines up with the variable order that the master device wants to see, export the AB program to L5K, import it into the Red Lion, drag and drop, save, download, and I'm done. The ONLY reason that I map the variables in the PLC in the order that the master wants them is so when he's asking about 40002 I know to look at my second variable I attached a couple of screenshots that might help explain the reason for all of this Valero array used to convert REAL to INT MNETC tags Data Station Plus setup. Crimson 3.0 (config software) is free. You can do some pretty slick things with the DSP+ including logical data moves. For instance If Tag = 1 then put Tag 2 in 40001 Else_If Tag = 2 then put Tag 2 in 40002. This isn't the exact structure you would use. 40001 and 40002 would be a tag that would be mapped to those values Have fun

Share this post


Link to post
Share on other sites
I've tried the COP command 3 different ways and the data is scrambled every time. There are quite a few variables. Here's the structure of the command(s). I also tried 2 and 4 elements. None of the data made sense. COP(MNET.DATA.ReadData[1],Valero.X5105,1; The MNET data is DINT data spread across two INT registers. Valero.X5105 is a DINT (I built a UDT to mimic the data coming in via Modbus) COP(MNET.DATA.ReadData[19],Valero.X7101,1; The MNET data is REAL data spread across two INT registers. Valero.X5105 is a REAL (I built a UDT to mimic the data coming in via Modbus) For testing purposes I'm connected through a cell modem that has horrific bandwidth. I have 20 lines of code that I've modified 4 times and I started at 7pm. It's 10:42 and I just decided to quite for the evening. When I say horrific, I mean horrific. It takes about 30-45 minutes to make an edit on 20 lines of structured text, save it, and then see what the result is. Needless to say I'll finish testing when I'm on site. Half of the registers, give or take are (2) INT registers to DINT transfers and the other half are (2) INT to REAL. So far I've made all of my command lines the same as it pertains to number of elements. I think that's where I'm messing up. At almost 11pm I have about 2 neurons firing and it takes most of those for breathing... So... if you could give me some insight into why this isn't working I would appreciate it. When I get to the site I'll brute force the heck out of it and something will end up working but I would rather just do it once. Edited by Michael Lloyd

Share this post


Link to post
Share on other sites
Any hope???

Share this post


Link to post
Share on other sites
There's always hope. I have yet to make it back to the site to play in real time. We're kind of busy these days (and all days before it) but I'll swing by there soon. For instance, yesterday, I did a FAT on (1) CLX PLC with a full 17 slot rack and a full 13 slot remote rack. The odds are pretty high that I'll add another 13 slot rack in the next week or two. (4) Micrologix 1100 LACT panels and (1) SCADAPack 350 panel Coming down the pipe in the next couple of weeks I have (at least 6 ) SCADAPack 350 panels, (2) CLX panels with 13 - 17 slot racks. (1) CLX panel with a 17 slot rack and a 13 slot rack. (1) CLX with 17 slot rack and a 17 slot remote rack. All of the CLX boxes will have MNETC cards. It sounds like more than it is. It only takes a day to flesh out the program for the largest panel (almost 200 analog points and 400 or so digital points. A panel this size will have 128 alarm registers and at least 128 shutdown registers) and another day to fine tune the docs. I document every single register so docs are a big deal to me. It's important to have some level of standardization if you are going to put out a high volume of good programs. I have standardized alarm logic, analog scaling, pump logic, shutdown logic, etc. Doing so helps me to be efficient with my time and it helps the guy doing the HMI work to b e efficient with his time

Share this post


Link to post
Share on other sites
Which processor are you using? Any tank gauging involved? LACT units are good! (Err, work is good?) Standardization is ALWAYS good. J

Share this post


Link to post
Share on other sites
I use an L61 for everything. Keeps my spare inventory at 1 processor. I have a little add-on that I wrote that calcs tank level (and barrels and pounds and gallons) based on a 0-100% input from the LT. I just have to input the diameter and height for each tank. LACT's are easy. We put a little extra on ours. I use a little Nematron display so we know what shut it down, what the level is, what the flow rate is (calculated from a pulse input and some logic). I'm pretty sure I'm going to have to swap words on the values to get them to come in right. I played with a BTD instruction a little but I apparently didn't have it built right. I created more garbage <edit> BTD or BTDT either one doesn't like floats. 1/2 of the registers that I need are floats... so it's try it with all DINT's then move to floats or ??? This would be real easy to fix in the MNET card. All I would have to do is set swap to 1. But... the customer is getting the same data and they take priority. If I swap the words in the poll then their data will be trash and mine will be good. I hope that some day the little endian kicks the big endians butt... Edited by Michael Lloyd

Share this post


Link to post
Share on other sites
I decided to brave the interminably slow connection through a cell modem and test some changes to the logic to see if I could get this thing finished. Winner winner chicken dinner... The solution isn't elegant but it works. I used the BTD (Bit Field Distribute) command in ladder to word swap the DINT registers that held the data from the Omni that I wanted in an array (used a UDT) that I built. About 1/2 of the array was comprised of DINT's and the other half were REAL's. The Reals required an extra step. I had to create a DINT array, used the BTD to swap the words of the MNET registers and put them in the DINT array. Then I copied the DINT values to the REAL values. It sounds clunky but in practice it wasn't too bad. Here's a screenshot of the DINT to DINT and DINT to REAL logic. If I would have set the MNET card poll groups up with word swapping this would have been a problem for someone else...

Share this post


Link to post
Share on other sites
Are you mapping those tags through the Red Lion? If so, couldn't you set it up there to do all your bit manipulations?

Share this post


Link to post
Share on other sites
I'm using the L61 for the tankage gauging too. The layout I use is very taxing to the Processor. I am currently wondering if I slowed some of the tasks scan rate what that would get me. Right now the inherited layouts are running all the same speed. Installation is ina generic package so the integrator before me wasn't too worried about the processor constantly running in the yellow. I would suspect a huge amount of unloading if I ran a couple of the not-so-needy task at like 250 mS. I'll keep the forum posted. As always thanks for the help. I am very new to PB32, think FT Studio isn't much better. Wonderware, or FactoryLink is kinda my forte'. Good to see OkiePC is alive and well! John Edited by a062549

Share this post


Link to post
Share on other sites
SWEET, brutal but very nice. The OMNI's can be pretty cantankerous for the integration to a not MODBUS friendly PLC. John

Share this post


Link to post
Share on other sites
The MNET reads an Omni flow computer. The Red Lion reads the MNET tags in the PLC. I could have set up a read back from the RL but I wanted a set of registers that would tell me what the MNET card registers were doing. If the MNET registers are right then the problem is theirs not mine. Unless the RL is hosed up...

Share this post


Link to post
Share on other sites
How many tanks are you reading? I haven't come close to taxing an L61. Ever. I've put entire gas processing plants on them with 20 or 30 loops. The latest pump station program has 133 analog points (not all are used but they function, I map every point on a card). Each analog array has 8 reals, two strings, and 8 booleans so in my world analogs make for a lot of tags. Granted... we usually only have 2 to 10 tanks so compared to a large tank farm we aren't doing much and the level calc block that I wrote doesn't take up much time. I put my PIDE loops in a Task set to 250ms or so. They don't eat up much time.

Share this post


Link to post
Share on other sites
The thing that got me on this one was the MNET card. If I had swapped words when I set the MNET card up then everything would have lined up. I could have swapped the word the other way in the Red Lion and the customer wouldn't have seen any difference. I had to go the route that I did here because (A) the data that I am monitoring is for troubleshooting only and (B) I don't know what they are doing with the data that they requested so I can't risk screwing up their data by switching everything now. I know it would work but I don't KNOW that it would work Edited by Michael Lloyd

Share this post


Link to post
Share on other sites
I can certainly see the usefulness of keeping it all in the PLC, especially as a modification to existing code done by others. I was just curious. I have been having a wonderful time with Crimson 3.0. I am building a template for a 1000 step Click Sequencer with sequenced inputs and outputs, fully configurable from the HMI (hopefully it will work with the emulator too.) I have just recently gotten into writing functions and doing advanced data manipulations in Crimson. It has been rock solid so far. I have a pretty strong trust of Red Lions' stuff as a bridge device, but keeping it in the PLC does remove one potential loss of data integrity, and provide easier access to those who're Logix savvy for the future. Paul

Share this post


Link to post
Share on other sites
I put it in the PLC because of being able to import L5K files into the Red Lion and then using the AB tags to address the registers that the customer wanted to see and because I DID NOT, for this reason, want the customer to have access to the PLC or the Omni directly. I used the RL as a firewall. I haven't seen code by others in so long... I kind of miss it. I learned a lot from tearing apart other peoples programs. I kind of miss the S7, TI505, and Direct Logic PLC's but for pure simplicity of implementation I prefer the the CLX box. AB hit a home run with it... The RL and Crimson software are a very well thought out and implemented solution to a lot of control "things". The only thing that I would call advanced that I've done with a RL is use it to share chromatograph data with 3 measurement runs. If the stream number is 1 then the data is placed in Meter Run 1s registers, if 2 then MR2, etc. Everything was done over Modbus TCP and serial. Most of the time I use it as a firewall or cheap modbus card

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0