ASCII in Concept IEC


Thread Starter

Santosh David

My quandry is this. I have a Quantum 534 PLC and I'm using a RTXMIT block to read ASCII information from a sensor. The information is coming back to the PLC, but I'm having a problem taking the data (which is a floating point number in Hex ASCII) and putting it into a register (Real Datatype). Structured text seems to be the only option. I just wanted to know if anyone else out there has had a similar issue with ascii sensors and Concept IEC.

Best Regards,
Santosh David
I do not know the exactly meaning of HEX ASCII, just like '8a4f'? maybe 'word as real'(Not word to real') can help you. I am in China, you can e-mail me for more help.

I am write a program about esi06210, would you be so kind to share your code with me ?
"[email protected]", mailto:[email protected]

Chad Markovich

Let's assume the data from the ASCII device is 123.456 as an ASCII string. The 'raw' data from the ASCII device into the PLC should look something like this in the PLC's registers:
40001 = 12 (ASCII) -> 3132 (HEX)
40002 = 3. (ASCII) -> 332E (HEX)
40003 = 45 (ASCII) -> 3435 (HEX)
40004 = 6 (ASCII) -> 3600 (HEX)

Note: This may not be exactly what appears in the registers, as most ASCII strings have some sort of header and trailer attached to the data. What you will need to do is to locate the start of the actual numeric data in the string. Notice that each register contains two ASCII characters, the first character (in this example) represented in the upper byte. You'll need to identify the first and second characters individually and store them into separate registers. To get the upper byte (the ASCII '1') from 40001, divide 40001 by 256. The result should be 31 hex or 49 decimal. You'll then need to subtract 30 hex (or 48 decimal) from the result of the division, which converts the ASCII '1' in this case to decimal '1'. By the way, the divide does the same thing as shifts the bit pattern to the right 8 bits. Next, we need to get the lower byte, the '2' value, by clearing the upper byte of the 40001 register. This can be done by ANDing the 40001 register with 00FF hex, or 256 decimal. You then need to look at the result of the AND, which should be 32 hex (or 50 decimal,) and subtract 30 hex (48 decimal) to convert the ASCII '2' into the decimal '2'. That's one way to convert the individual ASCII characters into individual decimal values. You'll also need to check for the decimal point in the above routine. When you find the decimal point, use the digits converted before the decimal point as the whole number (abcissa?) and the digits after the decimal point as the fractional part (mantissa?) To convert the individual digits into one floating point value (2 consecutive 4x registers,) you need to "sum" the individual digits. This can be done as you determine each ASCII character's decimal value. For example, when you convert the ASCII '12' into decimal 1 and decimal 2, you can use another register(s), let's say 40100 as a float (which also uses 40101), to hold this running sum of the numbers we have already converted. If we multiply 40100F by 10, and then add the number we just converted, we can "build" our converted number. So, initially, 40100F will be equal to 0. If we multiply by 10 (which initially gives us 0) and then add '1' our result will be '1'. After we convert the next digit, '2', we multiply 40100F (at this point it's 1) by 10 (which will equal 10)and add the converted digit. This makes our sum register equal to '12'. We continue to use this multiply & add routine until we come across our decimal point. Once we find our decimal point, we want to modify this routine to count the number of fractional characters we have in our ASCII string. We can use the same multiply & add routine, but in the end, we need to divide by 10 for each fractional character we counted. We also want to use a different "sum" register for the fractional part. Once we get to the end of our ASCII string and have the complete whole number converted in a "sum" register and the fractional part in another "sum" register, we want to add the two sum registers together. Finally, this sum will be the floating point equivalent of the ASCII string. Of course, you'll want to thoroughly test different combinations of ASCII data coming back in, such as 1.023 to make sure you do not end up with 1.23, where the "leading zeros" after the decimal point are lost.

Some other ideas to consider: will you be getting negative numbers? What about data in an exponential data format, such as 1.234e-3? I don't think Concept's built-in libraries convert ASCII to decimal. The XMIT block in 984LL could do this, but I do not know if it handled floating point values. I do not think the XXMIT does ASCII conversion - check the help pages/pdf's, because it might. It will be a fair amount of code to write. It may be worthwhile creating a DFB to do this to make future maintenance on the rest of the program easier, since you won't need to muddle through the ASCII conversion code and make the overall program easier to understand. This also allows you to re-use the conversion function block in other programs if necessary, or re-use it in the same program if you have multiple ASCII devices. If you know C++, Concept has an EFB toolkit that allows you to create your own function blocks that are highly optimized (not really an issue with the Quantum 534.) The EFB Toolkit also allows you to hide your source code, just like you cannot see the code for the RTXMIT or a TON, or any other EFB.

I did a similar conversion a few weeks ago, but in 984 ladder logic. Using Concept should be a lot easier. As you suggested, I would probably use Structured Text, since the process is mainly math and loops.

Good luck!

Chad Markovich
Application Engineer
Northwest Controls
[email protected]