Pages: [1] 2   Go Down
Author Topic: Urgent - Split Long into 2 Int using BitShift  (Read 5638 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi All,
I have this problem and I did not found a solution  :-/

I have a Signed Long variable that come from an encoder reading, I need to split it into 2 Signed Int to be able to send them to a PC using ModBus Slave over serial.

Actually I do this :

HighINT = ValueLong / 32767;
LowINT = ValueLong - (HighINT * 32767);

regs[MB_REG4] = HighINT;
regs[MB_REG5] = LowINT ;

It works good but it need a lot of time when ValueLong is big

I need to do the same operation using bitshift, something like:

HighINT = (ValueLong >> 16) & 0x0000ffffl;
LowINT  = ValueLong & 0x0000ffffl;

regs[MB_REG4] = HighINT;
regs[MB_REG5] = LowINT;

I'm not expert in bits operation, I hope that someone can correct this code for me.

Thanks in advanced !  smiley-wink

Matrix
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26312
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Dividing by 32767 'works good'?
That's where your problem is; your definition of 'good' is flawed.
« Last Edit: January 20, 2011, 10:14:04 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yes it works but increasing the long number will increase the loop time from 1 mS to more than 4 mS and it is not good for me. Anyway the conversion works.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26312
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It doesn't work.
It may do something, but it isn't correct.
It may help to see the problem if you write 32767 out in hex.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

EMH, I'm sure that it works.
 I test it comparing the value of original Long on Arduino and the rebuilded one on the PC side doing the inverse math ( Software on PC side is VB6)

rebuildLong = ( HighINT * 32767) + LowInt

I need the same exactly results.... but faster  smiley
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26312
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You've already posted a bitshift method that works, so why not use it?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13718
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks to me like the shift you posted is correct and should work.

Question: The highint and lowint are they signed or unsigned?
One of the things that may happen with shift operations is sign extension, so maybe a cast to unsigned long is needed to make the >> 16 work correctly.

---------

The first part is not correct:

HighINT = ValueLong / 32767;
LowINT = ValueLong - (HighINT * 32767);

should be

HighINT = ValueLong / 32768;
LowINT = ValueLong - (HighINT * 32768);

or

HighINT = ValueLong / 32768;
LowINT = ValueLong  % 32768;


[edit]Sorry: the magic number must be 65536L as stated below. Too eager to answer  :-[
« Last Edit: January 20, 2011, 12:19:56 pm by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26312
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Better still, use 65536.  See reply #1

 smiley-wink
« Last Edit: January 20, 2011, 11:09:31 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

New Hampshire
Offline Offline
God Member
*****
Karma: 17
Posts: 781
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just use:

HighINT = ValueLong >> 16;
LowINT  = ValueLong;

And be done with it.  The masking is unnecessary.  The results won't match your other method, but that is because, as AWOL has correctly pointed out, your other method is incorrect.
Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Both L & H int are signed and I need it because my Long must be Signed, Encoder can count + or - .

I dont know how BitShift works with sign  smiley-sad

The math of the first post  works even if you divide the long value by any number lower that 32767, on the worst case I cant reach the maximum Long extension  but it is a very remote possibility ( > 1 milion)
Anyway the problem is not the result but the speed of the loop.

I try with >> 16 as in the #1 post but did not work.

I try >>15 to leave 1 bit for sign and it works only for L value

I dont have the knowledge base to understand this bit operation.

Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 133
Posts: 6755
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
HighINT = (ValueLong >> 16) & 0x0000ffffl;
LowINT  = ValueLong & 0x0000ffffl;
Those look OK.  (better than the 32767 examples!)
There may be sign issues; Shift operation is not fully specified for signed numbers, but since you're masking things anyway you should get the correct results in any case.
Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 17
Posts: 781
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bitwise manipulation in general doesn't care one bit (no pun intended) about the sign or format of the variable they are operating on.

If you decompose a 4 byte variable into two 2 byte variables, and then later recompose them back into a 4 byte variable, the bit patterns will remain identical.

That's not to say there won't be any sign issues, but they will not be related in any way to the bitwise operations (for example, there may be endian problems if you are transferring the data between platforms with different endian'ness').
Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I try this code as test, maybe can help to find  mistakes

int H;
int L;
long ValueLong;

void loop(){
 
ValueLong = -1;

H = ( ValueLong >> 16) & 0x0000ffffl;

L = ValueLong & 0x0000ffffl;


Serial.print(H,DEC);
Serial.print("-");
Serial.println(L,DEC);

delay(500);

}

Results are H = -1 L = -1

if ValueLong = 32769  H = 0 L = -32766   smiley-sad

same results without masks

I'm counfused
« Last Edit: January 20, 2011, 11:51:03 am by MatrixGTI » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13718
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 try using print(..., BIN) to see the bit patterns ... thn you see what happens ..
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

With -1 as ValueLong I read on serial monitor:

L = 11111111111111111111111111111111
H = 11111111111111111111111111111111

both with mask or not


with 32769 I read:

H = 0
L= 11111111111111111000000000000001
« Last Edit: January 20, 2011, 12:03:19 pm by MatrixGTI » Logged

Pages: [1] 2   Go Up
Jump to: