3/13/2008 7:14 PM | |
Posts: 30 Rating: (6) |
After "googling" a lot, I was able to do what I want. For record, here is the code: The raw data tag stores all the DB, composed by 32-bit float values. [code] float function_GetRawFloat(char tag[], int Offset) // Some button calls the function with the tag and offset (0, 4, 8, 12,...,102) { #define DATA_SIZE 416 int i; int FloatValue; int aux_s, aux_e, aux_f; float FloatValue2; BYTE byData[DATA_SIZE]; //Actual value of the tag GetTagRaw(tag,byData,DATA_SIZE); //concatenate the bytes in a 32-bit word. FloatValue = byData[Offset]*16777216 + byData[Offset+1]*65536 + byData[Offset+2]*256 + byData[Offset+3]; //Separate the bytes like the IEEE-754 standard. //SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF aux_s = (2147483648 & FloatValue ) / 2147483648; //Signal aux_e = (2139095040 & FloatValue ) / 8388608; //Expoente aux_f = (8388607 & FloatValue ); //Fraction //Convert for float IEEE-754 FloatValue2 = (1 - 2*aux_s) * pow(2,aux_e - 127) * (aux_f / pow(2,23) + 1); return FloatValue2; }[/code] I found the formula in http://handyscript.wz.cz/files/ieee754.htm |
4/23/2008 10:42 PM | |
Posts: 30 Rating: (6) |
You want to find a way to read the floating point number without doing this "bit manipulation"? I think that when you read the raw data, you will get all the bits together. If you have 2 double words in PLC and use the raw data tag, what you'll get is these two 32bits words together. You will get a 64bits word. When you use the GetTagRaw, you need to transfer the information to an array of bytes. I don't know why, but only works witha a BYTE array. So, if you need to read bits, you need to separate de bits from the tag, with you need to read 16bits, 32bits, you need to merge the bytes. When I get the data from PLC, it will be something like this 010101010101010101010101010101001010101... Using GetTagRaw, I'll have a vector like this: [01010101, 01010101, 01010101, ...] So, the IEEE-754standard is this: SEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFF (S = Signal, E = Expoent, F = Fraction) To read the first float number, I read the firsts 4 bytes of the byte array, manipulate then (like the code I posted) and get 3 different words: 1-bit word S 8-bit word E 23-bit word F And using the formula found in http://handyscript.wz.cz/files/ieee754.htm I get the float number. But you want to read the data directly from the buffer, so you don't need to store the data with the byte array? |
4/24/2008 3:59 PM | |
Posts: 10 Rating: (0) |
you are correct of course, the GetTagRaw requires 3 arguments. My other mistake is "FloatValue1"= byData.float[44], should read "FloatValue1"=byData.data[44] // where "FloatValue1" is a WinCC internal tag, set to the value of the 4 bytes starting at offset 44 (x32 bit words) in the array (176 bytes offset into the array). The "." between byData and data tells the code to grab 4 bytes from the array, at 4 byte increments, and interpret the 32 bits as an IEEE754 floating point number. That as defined earlier, "float" data[220]; in the declaration section. If I switch to "ByteValue1"=byData.raw[44], then I get the 44th byte in the array. I compiled a version of this code in my WinCC C language actions, and it did compile with no errors. Of course, it may still yield garbage for results. My OPC link is down (I am hoping the sending end is the problem), so I cannot test this. The "union" provides different ways of defining the same memory space, so once you have loaded the data in under one type, such as loading a bunch of bytes, you may then choose to read that same data, before over-writing it, as a different type of data. Wikipedia (now back on line in China!) has an interesting note on Type_Punning (http://en.wikipedia.org/wiki/Type_punning), if you want to see examples on how to abuse thisfeature of the C language. The byData.raw data type is defined as type "BYTE". The byData.data data type is defined as type "float". (That was confusing, I had to read that again to make sure I do not stutter, next time maybe I make my data type "byData.process" name) My original OPC stream is already coded as floating point, in 4 byte chunks. If I define a data type float, which uses 4 bytes at a time, then my 880 byte array becomes a 220 floating point word array. The union was, according to some history that I read, designed to allow sharing of memory space, when all we had to work with was 64kB. There was some pretty funky code written for those machines. You had, or have, to be careful to only read back the same data type as you wrote, or you get garbage, like the byte information that you get from an array of floating point numbers. The "structure" allocates separate memory space for every element of the structure, the "union" allocates only enough space for the largest defined element, and pads the remaining space so that you always get back the same number you put in. If I ever get my OPC back, and this code actually works, I will post it on this thread. I put C keywords in "quotes" where it might not be obvious. My HTML color coding skills are non-existent. Also I find this handy reference http://users.ece.utexas.edu/~adnan/c-refcard.pdf which is 2 pages of C code reference data, like the plastic printed card we used to get when programming assembly code for old dinosaurs the Digital Equipment PDP11 processors! (From the '80s) All the C++ etc.references are not helpful on the WinCC platform. |
4/25/2008 4:54 AM | |
Posts: 10 Rating: (0) |
Your Research & Development work is very encouraging for me. It is one thing to have a theory, and yet quite another to test it out. You have solved my particular problem, as I only (selfishly) care about data flow in one direction, at this one time. My application is the feedback for a control loop, where the sensor is an OPC device, and the PID controls are within the WinCC - PCS7 system. The operator makes a zone setpoint change, one of 40, the S7-400 controller sends a new output to a control valve, and we wait some time to see the effect of the change in maybe several of the 40 zones, waiting for the transport time of the machine. In your very thorough testing, you have also uncovered something that I find mentioned in the various sources as whether the data is "little endian" or "big endian". This is a humorous English term, to say the least, and I find in this link I did miss something by not reading "Gulliver's Travels" in my high school English classes. See this link for some pretty funny stuff, if you're a geek like me, anyway. http://en.wikipedia.org/wiki/Endianness#Floating-point_and_endianness So, you have already found the problem in communication, so that is more than half of the solution. When you send your data, you can manipulate the order of the bytes with a small sub-routine, within the array packing routine. If it is a floating point number, place the number in the array as received. Then calculate the byte offset of each of the elements of the float number, using as your base, the array element subscript number you just wrote. i.e. byData.value[56]="WinCCFloatOutputTag1" Read back the bytes into a new temporary 4 byte array, using the "BYTE" definition of the "union", such as byData.raw. i.e. tempBYTEarray[0]=byData.raw[56*4]; tempBYTEarray[1]=byData.raw[(56*4)+1]; tempBYTEarray[2]=byData.raw[(56*4)+2]; // etc. of course, you would make this into a "for" loop, with variables for the integers, to save typing, if nothing else. Then, you can justwrite the bytes back in the order that the receiving system likes, by reversing the operation, with different subcripts. i.e. byData.raw[56*4]=tempBYTEarray[3]; Or you could do it all at the end, cycle through the array, swapping bytes as you go, just before executing the SetTagRaw("S7400floatarray", byData.raw,416); //maybe? The same union definition, byte & float, will allow you to place the bytes in the correct order for the receiving system. My method for designing the mathematics for this transform is very crude, but I understand it. I draw many boxes, each with its subscript, see attached, my template in Microsoft Word to explain to the Chinese developers my theory for how to transform 220 element into 40. AttachmentOPC get array.pas.zip (530 Downloads) |
Follow us on