Comments (7)
Not sure how much help I can be without knowing how to decipher the bytes data but here's the retdata from the same above tags, which I am sure you can recreate on your setup but just in case. Let me know if you need any other data but I think the problem might be at the unpack_from, but that is a bit of a guess at this point:
I was trying to figure out if the value on retdata is losing precision before or after:
def _parseReply(self, tag, elements, data):
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x02\x00\xcc\x00\x00\x00\xca\x00!<Z;'
0.003329999977722764
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x03\x00\xcc\x00\x00\x00\xca\x00\xef\xff\x7f?'
0.9999989867210388
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x04\x00\xcc\x00\x00\x00\xca\x00\xcd\xcc\xcc='
0.10000000149011612
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x05\x00\xcc\x00\x00\x00\xca\x00\n\xd7#<'
0.009999999776482582
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x06\x00\xcc\x00\x00\x00\xca\x00!<Z;'
0.003329999977722764
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x07\x00\xcc\x00\x00\x00\xca\x00(knN'
1000000000.0
-------------------------------
status: 0
retdata: b'p\x00 \x00\x01\x00\x02H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa1\x00\x04\x00\x01\x00\x00 \xb1\x00\x0c\x00\x08\x00\xcc\x00\x00\x00\xca\x00\x00\x00\xa0@'
5.0
from pylogix.
Apologies for the delay.
The behavior you are seeing is the nature of floating point numbers. Not just with Rockwell or Python, in general. Rockwell is not showing you the exact representation of the number in memory. In believe they did in the early days of RSLogix, though I think it caused confusion when people would enter a value of 7.52 in the controller tags (See KB 8232), it would display 7.5199997. I’m guessing at some point they changed this to display the exact number they entered to save confusion. Or they added the “style” selection to display Exponent vs Float, I haven’t used the really old versions in many years so I cannot remember.
There are a couple of ways you can see this in action in Rockwell land. Create a new program, create a single tag that is a REAL, put the number 7.52 in it. Change the style field in the controller tags to exponent, you will see 7.52 change to the truer representation of 7.5199998e+000. Though it’s still not 100% accurate.
With that same program, save it as a L5K and check it out in your favorite text editor, it’ll probably look similar to above.
Now for fun, if you add the numbers 7.51 and 0.01, destination is the tag you created, you’ll see 7.5200005 as the result. Not 7.52.
Lastly, you can use a RTOS to convert the number 7.52 to a STRING, you will get “7.51999998”
from pylogix.
Yeah it was a bit strange. It makes sense, I will try to load the returned data into the PLC and see what happens. I guess it really doesn't matter how it looks as long as the plc knows how to handle those values.
By the way the same happens with EtherIP repo. Though it has multiple methods to retrieve data getInt, 7, getDouble creates the same scenario 7.5199997 and getFloat 7.52 so I figured something could be done in python as well. Nevertheless if the data loads correctly to the PLC then it should be OK.
from pylogix.
Interesting info on the EtherIP repo. "getFloat" seems like it would be a single precision floating point value, producing 7.5199997, "getDouble" would be double precision, producing more decimal points. Neither seems like it would product 7.52. Though maybe "getFloat" is special.
For fun:
https://www.exploringbinary.com/floating-point-converter/
from pylogix.
No worries on the delay, hope you had some good holidays! I was working until Sunday hence me working on a side project lol. Not sure how much useful wireshark data will be here, I did one tag read with etherip in the below example. After reading the tag the data goes to a buffer, all three intValue, doubleValue, and floatValue are abstract methods for Number which is an actual JDK class.
Below are implementations of those abstract methods in the JDK Float class:
/**
* Returns the value of this {@code Float} as an {@code int} (by
* casting to type {@code int}).
*
* @return the {@code float} value represented by this object
* converted to type {@code int}
*/
public int intValue() {
return (int)value;
}
/**
* Returns the {@code float} value of this {@code Float} object.
*
* @return the {@code float} value represented by this object
*/
public float floatValue() {
return value;
}
/**
* Returns the {@code double} value of this {@code Float} object.
*
* @return the {@code float} value represented by this
* object is converted to type {@code double} and the
* result of the conversion is returned.
*/
public double doubleValue() {
return (double)value;
}
Case "REAL" returns the data truncated or rounded depending on which method you call but the actual CIP data never changes.
final synchronized public Number getNumber(final int index)
throws Exception, IndexOutOfBoundsException
{
switch (this.type)
{
case BOOL:
case SINT:
return new Byte(this.data.get(this.type.element_size * index));
case INT:
return new Short(
this.data.getShort(this.type.element_size * index));
case DINT:
case BITS:
return new Integer(
this.data.getInt(this.type.element_size * index));
case REAL:
return new Float(
this.data.getFloat(this.type.element_size * index));
default:
throw new Exception("Cannot retrieve Number from " + this.type);
}
}
On another note I did read one real tag and wrote that same value to another online tag with pylogix and everything works as expected, so we probably shouldn't spend too much time on this one. I probably should have done that first.
from pylogix.
I could add a helper formatting function. I'll do some testing next week.
from pylogix.
Closing issue, since is not really an issue. 😄
from pylogix.
Related Issues (20)
- Unknown Error 255 on Multi-Write when including a string HOT 6
- read tag from 80 sets of plc HOT 22
- Double read packets? HOT 6
- cannot import name 'Adapter' from 'pylogix' HOT 23
- Tag Write falsely reports Success HOT 7
- "Forward open failed" when trying to read tags from Berghof PLC HOT 8
- .GetDeviceProperties always returns DeviceType of "None" HOT 5
- Issues connecting to emulate HOT 7
- micro850 connection HOT 5
- Return data gets jumbled up on a multi write when the tags don't exist. HOT 13
- The return value is different when using a multi write compared to a single write for a string. HOT 4
- cannot get a tag list HOT 3
- Is it possible to inhibit a periodic task? HOT 2
- pylogix - returning a tag list as a row of values HOT 7
- PLC REAL values HOT 5
- Pylogix - compare a previously acquired tag list with the current one HOT 5
- Discover does not work while running pylogix in docker HOT 10
- Invalid Continuation Byte HOT 5
- Abnormal code termination. HOT 8
- Do I need to use routing? HOT 20
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pylogix.