harmsm / PyCmdMessenger

Python interface for CmdMessenger arduino serial communication library
MIT License
80 stars 32 forks source link

Endian mismatch #19

Closed sphh closed 7 years ago

sphh commented 7 years ago

Hi Mike,

Finally I got my Yún working with PyCmdMessenger (see #15). The last stumbling block was that the integer value of 1 became 256 on the Yún (and 2 became 512 – you get the picture). It looks like the Yún is big endian!

I put a < in front of all the INTEGER_TYPE, UNSIGNED_INTEGER_TYPE and FLOAT_TYPE definitions as mentioned in https://docs.python.org/2/library/struct.html#byte-order-size-and-alignment. The relevant part in arduino.py becomes now:

        INTEGER_TYPE = {2:"<h",4:"<i",8:"<l"}
        UNSIGNED_INTEGER_TYPE = {2:"<H",4:"<I",8:"<L"}
        FLOAT_TYPE = {4:"<f",8:"<d"}

I hope it does not have negative side-effects on PCs.

Cheers, Stephan

harmsm commented 7 years ago

Thanks for the report. I think we can fix this by adding an "endian" argument to the ArduinoBoard.__init__ function, and then using that to construct the proper INTEGER_TYPE etc. dicts. This should have no impact on the PC side, as PyCmdMessenger uses pack and unpack, which are aware of the native endian-ness of the python program. All these strings specify is the endian-ness of the arduino.

One quick clarification on the problem, just to make sure I fully understand. Your problem is that the python part of the Yun is big-endian the arduino part is little-endian. Since no endian-ness is specified in the pack calls, PyCmdMessenger blithely creates a native (big-endian) binary string that the arduino treats as a little-endian binary string. If this is what is happening, an explicit declaration of the arduino endian-ness is a much better design than relying on whatever is native to the python platform.

I can roll out a patch and test it on my UNO tonight. It would be helpful if you could then test it on the Yun.

Thanks for your help with the library!

Mike

sphh commented 7 years ago

Hi Mike,

You understood the problem correctly: The Arduino uses little-endian, but the Yún sends them natively in big-endian. PyCmdMessenger works on PCs, because they are little-endian.

If all Arduinos are little-endian, I thought it's enough to hard-code the endian-ness into the PyCmdMessenger. If you want to keep it really flexible, and "endian=" keyword argument for the ArduinoBoard.__init__ function would be great.

Do you know, if CmdMessenger enforces little-endian-ness? In that case, the endian-ness does not depend on the Arduino, but on the CmdMessenger...

I am happy to test.

Stephan

harmsm commented 7 years ago

Thought about it more. I'm going to apply your fix. Works fine on my UNO and the (apparently) the Yun.
Flexibility here (with the endian arg) would suggest that setting it to "big" might actually work. It may not (and I can't really test it). Poking around, I could not find any evidence of a big-endian arduino in the wild.

I'm going to merge and create a new pypi release incorporating this and a few other small changes

Thanks again for your feedback on the library. I'm happy to help if anything else comes up.