Cast "arduino" long via modbus (two 16 bit uints) in int32_t.

More
05 Jun 2021 16:58 #211232 by gesamtplan
Hello,

I am new with linuxcnc and I didn't find an answer to my question. Maybe here is some help.

I build a MPG which is working with an Arduino Nano putting all data via Modbus TCP to LinuxCNC. It works good with mb2hal but i found a problem while setting up the encoder.

When I write the Encoder long from the arudino to modbus the Encoder Signal is cause of ModbusTCP converted to a word (uint16) and mb2hal converts it back to a s32 with the Uint16 variable input.

When I give this Signal to an encoder input it works but when the value jumps from 65535 to 0 and back I have a fast movement on the axis which is jogging. This is not a good solution but I have actually now clue to solve it.

One option would be to cast the variable on the arduino but I didn't find any solution to cast it back in HAL.

Is there any chance to do this or is it posible to change some things on the encoder site to avoid the jump von 65535 to 0 and the movement of my axis?

It would be glad if someone could give me a hint where i should start searching. :-)

Please Log in or Create an account to join the conversation.

More
05 Jun 2021 17:30 - 05 Jun 2021 17:30 #211235 by PCW
If you are sending 32 bits is should be easy to fix but if you are only sending 16 bits
the wrap needs to be handled by the driver or hal code.
This cannot be done with a cast since it requires a simple state machine
(looking at the current and previous count) to detect overflows and
underflows and extend the count range to 32 or 64 bits.
A simple hal component could do this however
Last edit: 05 Jun 2021 17:30 by PCW.
The following user(s) said Thank You: gesamtplan

Please Log in or Create an account to join the conversation.

More
05 Jun 2021 18:38 #211239 by gesamtplan
I don't unterstand fully. Like I said I am relativly new to this topic. How could I do this in HAL. Didn't find such things in documentation.

In my knowledge Modbus can only send 16 Bit data in a Register. I can put the Value from the Arduino in two registers. But how can I put them together. MB2HAL puts everything in s32 oder float. I have to put 16 bit of the first value and 16 bit of the second value to get a 32 Bit. Is this possible in HAL and if the answer is yes. How can I do this. Are there any examples in the documentation?

Please Log in or Create an account to join the conversation.

More
05 Jun 2021 19:28 - 05 Jun 2021 19:29 #211244 by BigJohnT
PCW is suggesting you write a HAL Component and use that. Maybe the examples will suggest a way to do what you need.

linuxcnc.org/docs/2.8/html/hal/comp.html

This page may help as well.
stackoverflow.com/questions/59071750/how...ue-when-either-one-i

JT
Last edit: 05 Jun 2021 19:29 by BigJohnT.
The following user(s) said Thank You: gesamtplan

Please Log in or Create an account to join the conversation.

More
05 Jun 2021 20:02 #211245 by gesamtplan
Hello JT,

thanks for the information. I think i need a few days to understand that. :-) The documentation looks good. Even vor Noobs like me.I will try to shift it right.

Thank you very much.

Please Log in or Create an account to join the conversation.

More
06 Jun 2021 09:57 #211284 by gesamtplan
Hello

found out that I can use Python for building components as well. This is working fine for my purpose. But I don't find, how S32 in linuxcnc is defiined.

Actually i can't write 0xFFFFFFFF into an s32 input because of overflow. When I print the values in Python I get as output a minus in hex and in bin, which is confusing me a little.

-h7FFFFFFFF or +h7FFFFFFF for -2147483648 to 2147483647

Is there any chance to push a hFFFFFFFF into s32?

Please Log in or Create an account to join the conversation.

More
06 Jun 2021 11:54 #211288 by BigJohnT
I was going to suggest looking at some of the convert components but they are built by some black magic in the submakefile.

github.com/LinuxCNC/linuxcnc/blob/master...mponents/Submakefile

github.com/LinuxCNC/linuxcnc/blob/master...ponents/conv.comp.in

JT

Please Log in or Create an account to join the conversation.

More
06 Jun 2021 17:28 - 06 Jun 2021 17:44 #211309 by gesamtplan
I found a solution for my problem.

First long on arduino IDE is no int32_t.
"s32" on linuxcnc uses 2's complement bit and the arduino "long" doesn't.
If u wanna transfer it via modbus u have to split the long in half and shift it together again.
mb2hal writes holding registers (fnct03) always in s32 and float, which r used as input.
After that u have to convert it to get used in HAL.

I am sure it can be done with a c HAL component too.
#!/usr/bin/env python
import hal, time
h = hal.component("MB_shift")
h.newpin("in1", hal.HAL_S32, hal.HAL_IN)
h.newpin("in2", hal.HAL_S32, hal.HAL_IN)
h.newpin("out", hal.HAL_S32, hal.HAL_OUT)
h.ready()

def twos_comp(val, bits):
	"""compute the 2's complement of int value val"""
	if (val & (1 << (bits - 1))) !=0:
		val = val - (1 <<bits)
	return val

try:
    while 1:
        huli = h['in1'] << 16 | h['in2']
        #hex_string_test = '0xFFFFFFFF'
        h['out'] = twos_comp(int(hex(huli),16), 32)/4 

except KeyboardInterrupt:
    raise SystemExit
Take a look here:
linuxcnc.org/docs/2.8/html/hal/halmodule.html
For doing the conversion this helps:
izziswift.com/twos-complement-in-python/
Last edit: 06 Jun 2021 17:44 by gesamtplan.

Please Log in or Create an account to join the conversation.

More
08 Jun 2021 23:03 #211557 by andypugh
There is code in the smart-serial driver which converts encoder counts of arbitrary bit-length in to a 64-bit signed buffer.

Here is that code:
github.com/LinuxCNC/linuxcnc/blob/master...mot2/sserial.c#L2003

What it does is convert the current counts to a 64-bit number, it then subtracts the previous counts from the current counts, and adds that difference to the 64-bit accumulator.
There is explicit testing that checks for a jump of more than 1/4 of the total possible counts in the input buffer. If that happens then wrap is assumed.

Note that the sign-extension that is done there, with 1U << bitlength and an XOR is not necessary if the input value is a known type. But the code in sserial.c is set up to cope with bitstream data that can be literally any number of bits.

Please Log in or Create an account to join the conversation.

Time to create page: 0.095 seconds
Powered by Kunena Forum