Code Monkey home page Code Monkey logo

Comments (7)

TheFern2 avatar TheFern2 commented on July 18, 2024

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.

dmroeder avatar dmroeder commented on July 18, 2024

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.

TheFern2 avatar TheFern2 commented on July 18, 2024

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.

dmroeder avatar dmroeder commented on July 18, 2024

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.

TheFern2 avatar TheFern2 commented on July 18, 2024

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);
        }
    }

image

image

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.

TheFern2 avatar TheFern2 commented on July 18, 2024

I could add a helper formatting function. I'll do some testing next week.

from pylogix.

TheFern2 avatar TheFern2 commented on July 18, 2024

Closing issue, since is not really an issue. 😄

from pylogix.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.