Jump to content

Recommended Posts

Posted

I am getting variables from an arduino. I now have it so I can send or receive bytes with which I can control the arduino. I am now to the point where the arduino is sending me a signed int as two bytes. (high and low byte). I can view the two bytes as a number 0-255. How would I go about taking those two numbers and getting a number that would be the same as the signed int the Arduino put into it?

Posted

This is something of a work around but seems to work. Leaving this here for other people who may have such a problem. It does require the baseconv.au3 lib found on this site to turn the bytes into readable 1s and 0s. If someone has a simpler answer I would be interested.

#include <BaseConv.au3>
$HighByte=255
$LowByte=255

ConsoleWrite('Int from byte: '&byte_to_int($HighByte,$LowByte)& @CRLF)



Func byte_to_int($r,$r2)
   Local $countArray[]=[32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1]

;~ High Bite
   if $r <>0  Then $r=_ToBase($r,2)
   ConsoleWrite('$r '&$r & @CRLF)
   While  StringLen($r) <8
      $r="0"&$r
   WEnd
   Local $aArray =StringToASCIIArray($r)


;~ Low Bite
   if $r2 <>0  Then $r2=_ToBase($r2,2)
   ConsoleWrite('$r2 '&$r2 & @CRLF)
   While  StringLen($r2) <8
      $r2="0"&$r2
   WEnd
   Local $bArray =StringToASCIIArray($r2)

;~ We now have two arrays that are holding our bytes 48=0 and 49=1
;~ Now how to turn the bits into an int?

   Local $count=0
   For $i=1 to 15 Step 1 ;start at one, we will need to do place 0 later as this is a signed int.
      If $i<8 Then
         if $aArray[$i]=49 Then
            $count= $count+$countArray[$i]
         EndIf
      Else
         if $bArray[$i-8]=49 Then
            $count= $count+$countArray[$i]
         EndIf
      EndIf
      ConsoleWrite('$aArray '&$i&' and ' & $countArray[$i]& " $count="& $count& @CRLF)
   Next
   if $aArray[0]=49 Then
      $count=$count+1
      $count=$count*-1
   EndIf
   return ($count)
EndFunc

 

Posted

I use the following function in my AD UDF:

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: __AD_LargeInt2Double
; Description ...: Converts a large Integer value to an Integer (Double Word) value.
; Syntax.........: __AD_LargeInt2Double($iLow, $iHigh)
; Parameters ....: $iLow - Lower Part of the Large Integer
;                  $iHigh - Higher Part of the Large Integer
; Return values .: Integer (Double Word) value
; Author ........: Sundance
; Modified.......: water
; Remarks .......: This function is used internally
; Related .......:
; Link ..........: http://www.autoitscript.com/forum/index.php?showtopic=49627&view=findpost&p=422402
; Example .......:
; ===============================================================================================================================
Func __AD_LargeInt2Double($iLow, $iHigh)

    Local $iResultLow, $iResultHigh
    If $iLow < 0 Then
        $iResultLow = 2 ^ 32 + $iLow
    Else
        $iResultLow = $iLow
    EndIf
    If $iHigh < 0 Then
        $iResultHigh = 2 ^ 32 + $iHigh
    Else
        $iResultHigh = $iHigh
    EndIf
    Return $iResultLow + $iResultHigh * 2 ^ 32

EndFunc   ;==>__AD_LargeInt2Double

 

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted (edited)

Either I'm missing something, or you're missing something;:D What's wrong with this?

Global $twobytes=DllStructCreate("align 1; byte[2]")
Global $short=DllStructCreate("align 1; ushort", DllStructGetPtr($twobytes))

$Low=123
$High=1
ConsoleWrite(_LowHighByte2Short($Low, $High) & @CRLF)
ConsoleWrite(__AD_LargeInt2Short($Low, $High) & @CRLF)


Func _LowHighByte2Short($lo,$hi)
    DllStructSetData($twobytes,1,$lo,1)
    DllStructSetData($twobytes,1,$hi,2)
    Return DllStructGetData($short,1)
EndFunc


Func __AD_LargeInt2Short($iLow, $iHigh) ; corrected version

    Local $iResultLow, $iResultHigh
    If $iLow < 0 Then
        $iResultLow = 2 ^ 8 + $iLow
    Else
        $iResultLow = $iLow
    EndIf
    If $iHigh < 0 Then
        $iResultHigh = 2 ^ 8 + $iHigh
    Else
        $iResultHigh = $iHigh
    EndIf
    Return $iResultLow + $iResultHigh * 2 ^ 8

EndFunc

and @water, the OP asked for short from two-byte input, so power should be 8 everywhere, not 32, I would think.

NB I'm assuming ushort here (i.e., unsigned = range 0-pos) replace with "short" if a signed interpretation is needed.

Edited by RTFC
Posted

This is what I like about a good coding forum there is almost always a different and often better way to do something than I can think of. I played with everyone's code and, you all have better answers than I did to get a unsigned short. I took a few minutes and ran a test script and was surprised that the performance was almost the same. Just calling the function 10k times each and all of these examples were around 2.1 seconds.

@water

I was trying to find the exponent command, for what ever reason I could not find it before, that makes a big improvement. I changed yours to work with bytes and it works as expected for unsigned.

@RFTC

I had not come across that before. I will have to look into it more. I did try to get it to give me a short by changing ushort to short on the second line, that seems to cause an error.

 

@Nine Very nice code, gives me the wrong answer half the time but very nice. Yours is perfect for unsigned short. Mine is signed, have a clever way to add that feature? The best I have is.

 

$HighByte=255
$LowByte=255

ConsoleWrite(HighLowByte2Short1($HighByte,$LowByte)& @CRLF)

Func HighLowByte2Short1($hi,$lo)
   $hold=Dec(hex($hi,2) & hex($lo,2))
   if $hold >32767 Then $hold=($hold-32767)*(-1)
  Return $hold
EndFunc

 

 

 

Posted (edited)
Posted (edited)
$Low=1
$High=128
ConsoleWrite(_LowHighByte2Int($Low, $High, True) & @CRLF)
ConsoleWrite(_LowHighByte2Int($Low, $High, False) & @CRLF)


Func _LowHighByte2Int($lo,$hi, $signed=False)

    Local $twobytes=DllStructCreate("align 1; byte[2]")
    Local $short=DllStructCreate("align 1; "&(($signed)?(""):("u"))&"short", DllStructGetPtr($twobytes))

    DllStructSetData($twobytes,1,$lo,1)
    DllStructSetData($twobytes,1,$hi,2)
    Return DllStructGetData($short,1)
EndFunc

And because I really don't like ad-hoc solutions, the one below handles all possible cases:

$Low=1
$High=128

ConsoleWrite(_ConvertRawBytes2Type("short", $low, $high) & @CRLF)
ConsoleWrite(_ConvertRawBytes2Type("ushort", $low, $high) & @CRLF)

Func _ConvertRawBytes2Type($type, $b1=0, $b2=0, $b3=0, $b4=0, $b5=0, $b6=0, $b7=0, $b8=0)

    Local $bytes, $bytebuffer=DllStructCreate("align 1; byte[8]")

    Switch StringUpper($type)
        Case "BYTE","BOOLEAN","CHAR"
            $bytes=1
        Case "WCHAR","SHORT","USHORT","WORD"
            $bytes=2
        Case "INT","LONG","BOOL","UINT","ULONG","DWORD","FLOAT"
            $bytes=4
        Case "INT64","UINT64","DOUBLE"
            $bytes=8
        Case "PTR","HWND","HANDLE","INT_PTR","LONG_PTR","LRESULT","LPARAM", _
                "UINT_PTR","ULONG_PTR","DWORD_PTR","WPARAM"
            $bytes=((@AutoItX64)?(8):(4))
        Case Else
            Return SetError(1,0,"")
    EndSwitch

    Local $result=DllStructCreate("align 1; "&$type, DllStructGetPtr($bytebuffer))
    For $bc=1 to $bytes
        DllStructSetData($bytebuffer,1,Eval("b"&$bc),$bc)
    Next

    Return DllStructGetData($result,1)
EndFunc

 

Edited by RTFC

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...