Cast "arduino" long via modbus (two 16 bit uints) in int32_t.
- gesamtplan
- Offline
- New Member
Less
More
- Posts: 5
- Thank you received: 0
05 Jun 2021 16:58 #211232
by gesamtplan
Cast two 16 bit uints in 32 bit sint was created 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.
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.
05 Jun 2021 17:30 - 05 Jun 2021 17:30 #211235
by PCW
Replied by PCW on topic Cast two 16 bit uints in 32 bit sint
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
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.
- gesamtplan
- Offline
- New Member
Less
More
- Posts: 5
- Thank you received: 0
05 Jun 2021 18:38 #211239
by gesamtplan
Replied by gesamtplan on topic Cast two 16 bit uints in 32 bit sint
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?
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.
05 Jun 2021 19:28 - 05 Jun 2021 19:29 #211244
by BigJohnT
Replied by BigJohnT on topic Cast two 16 bit uints in 32 bit sint
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
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.
- gesamtplan
- Offline
- New Member
Less
More
- Posts: 5
- Thank you received: 0
05 Jun 2021 20:02 #211245
by gesamtplan
Replied by gesamtplan on topic Cast two 16 bit uints in 32 bit sint
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.
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.
- gesamtplan
- Offline
- New Member
Less
More
- Posts: 5
- Thank you received: 0
06 Jun 2021 09:57 #211284
by gesamtplan
Replied by gesamtplan on topic Cast two 16 bit uints in 32 bit sint
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?
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.
06 Jun 2021 11:54 #211288
by BigJohnT
Replied by BigJohnT on topic Cast two 16 bit uints in 32 bit sint
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
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.
- gesamtplan
- Offline
- New Member
Less
More
- Posts: 5
- Thank you received: 0
06 Jun 2021 17:28 - 06 Jun 2021 17:44 #211309
by gesamtplan
Replied by gesamtplan on topic Cast "arduino" long via modbus (two 16 bit uints) in int32_t.
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.
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/
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
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.
08 Jun 2021 23:03 #211557
by andypugh
Replied by andypugh on topic Cast "arduino" long via modbus (two 16 bit uints) in int32_t.
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.
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