News:

Let's find out together what makes a PIC Tick!

Main Menu

Signed Comparison on an Unsigned Variable?

Started by Craig, Oct 05, 2022, 08:01 AM

Previous topic - Next topic

Craig

Hi All

I Have been using a piece of code on a Pic24FJ64GA004 with Positron 16 Version 1.1.0.4 which has worked fine but, if I recompile with the latest version 1.1.1.2 then I get a problem with a certain piece of code.
In both versions of the compiler, on compilation it will give a HINT:> Signed Comparison on an Unsigned Variable Two's compliment values will be operated on

Include "SPI_24.inc"
Include "SPI_DOG.inc"
Include "convert24.inc"

Dim anRxBuf[35] As Byte
Dim VLHold      As Byte
Dim VLRead      As SWord

----------------------------------------------------------------------------
Code in Question:
----------------------------------------------------------------------------
If anRxBuf[7] <= -128 Then               ' (-128 to +127 SByte Range)
    VLHold = anRxBuf[7]                                                                           
    VLRead = VLHold
    VLRead = (VLRead * 10)               ' Add Back *10 to go from "cm" Back to "mm"
    DelayMS 5
    string2Hold = " mm "                 
    string2Print = " VL " + Str$(SDec VLRead) + string2Hold       
    Print_At(arialn8,2,5,Str string2Print + "     ",0) 
EndIf
----------------------------------------------------------------------------

The issue is with:
If anRxBuf[7] <= -128 Then
If I change anRXBuf to a SByte type variable it does not work, the problem is that it is being received from a data Radio Tranceiver.   


JonW

Quote from: Craig on Oct 05, 2022, 08:01 AMIf I change anRXBuf to a SByte type variable it does not work, the problem is that it is being received from a data Radio Tranceiver.   


It doesn't compile if you change the array to SBYTE?

Cant you just declare a STEMP as BYTE and copy  anRxBuf[7]   to it for comparison



Include "SPI_24.inc"
Include "SPI_DOG.inc"
Include "convert24.inc"

Dim anRxBuf[35] As Byte
Dim VLHold      As Byte
Dim VLRead      As SWord
dim STEMP       As SBYTE

----------------------------------------------------------------------------
Code in Question:
----------------------------------------------------------------------------
STEMP = anRxBuf[7]
If STEMP <= -128 Then               ' (-128 to +127 SByte Range)
    VLHold = anRxBuf[7]                                                                           
    VLRead = VLHold
    VLRead = (VLRead * 10)               ' Add Back *10 to go from "cm" Back to "mm"
    DelayMS 5
    string2Hold = " mm "                 
    string2Print = " VL " + Str$(SDec VLRead) + string2Hold       
    Print_At(arialn8,2,5,Str string2Print + "     ",0)
EndIf
----------------------------------------------------------------------------

tumbleweed

How exactly do you want this to work?

For an 8-bit variable, -128 = 0x80 in 2's compliment form.
That's the lowest value that can be represented in 8 bits, so the signed comparison "<= -128" would be true only for a value of -128 and no other value.

If you're using an unsigned byte for the comparison then the statement would be true for values from 0 to 0x80 (128).

Craig

#3
Thank you  for the reply's, Jonw & Tumbleweed! I Couldn't complete my previous thread as Our Country is being Plagued Currently with rolling Power Blackouts where you have No Electricity For Hours, so I couldn't complete my original post correctly.

Getting back to my original thread: The new compiler version does compile correctly and also gives the Hint about Two's compliment but, when I execute that piece of code it Doesn't operate correctly as per the Older version of the compiler.

The Older Version of the Compiler Positron 16 on the Receiver side (PIC24) would print out the Signed Byte value Correctly but, With the Latest version of the Compiler it does not display the signed value correctly if it is a "-" it will print "2200mm" instead of giving the correct value namely "-220mm" where the "+" Value is correct.

{The problem is on Positron 16 with the Pic24FJ64GA004}

The problem is that I can only send a Byte in each Element of the Array anTxBuf[17] Via the Transmitter, so what I did was to Divide the number by 10 on the transmitter side and then Multiply it by 10 on the Receiver side, this has worked perfectly on the older version of the Positron 16 Compiler Version:1.1.0.4 but, as explained I am having issues with this in version 1.1.1.2 on Positron 16.

If I tried this "If anRxBuf[7] > 0 Then" it would only pick up if a Value was "+" and would obviously not detect anything Smaller than "0" so, any "-" would Not be detected so I then changed to using this " If anRxBuf[7] <= -128 Then"     

It is now Not meeting this criteria to see if there is something in position 7 of the array:
If anRxBuf[7] <= -128 Then  ' (-128 to +127 SByte Range)
** See Full code below in the Receiver Section **
I have tried many iterations of this and have also tried making the anTxBuf[17] an SByte and the Same with the anRxBuf[35] but, this seems to still have and issue?
so Not sure what has changed in the newer update of the compiler to cause this to become an issue?

Thank you for your help!
Regards
Craig


'--------------------------------------------------------------
------  Transmitter Side: --------
------- PIC 18F47K40      --------
'--------------------------------------------------------------
Dim anTxBuf[17] As Byte
Dim DHold       As Word
Dim OffsetT     As SWord
Dim SCon        As Word = 533
Dim DistanceTR  As SByte
Dim SRest       As SWord


Main:
GoSub S_Rout
Clear anTxBuf[7]
SRest = OffsetT
DistanceTR = SRest/10        ' Divided By 10 to Be Able to Send as Byte, Must * 10 on Receiver Side to get back to Correct Value     
DelayMS 5
anTxBuf[7] = DistanceTR      ' Load the New Value into the Transmitter Byte Buffer and get ready to Send Via the Transmitter
DelayMS 5
GoSub To_TX_Mode             ' Send the TX Values
Goto Main

S_Rout:
    Select DHold                     ' Right ( + Positive Reading )
      Case 0 To 532         
      OffsetT =  DHold - SCon                     
   '  HRSOut "CASE < 532: "          ' PC TESTING Purposes

       Case 533 To 1065              ' LEFT  ( - Negative Reading  )
       OffsetT =  DHold - SCon                   
   '   HRSOut "CASE > 533: "         ' PC TESTING Purposes
 EndSelect
Return



'--------------------------------------------------------------
------    Receiver Side:    --------
------   PIC 24FJ64GA004    --------
'--------------------------------------------------------------

Include "SPI_24.inc"
Include "SPI_DOG.inc"
Include "convert24.inc"

Dim anRxBuf[35] As Byte
Dim VLHold      As Byte
Dim VLRead      As SWord

----------------------------------------------------------------------------
Code in Question:
----------------------------------------------------------------------------
If anRxBuf[7] <= -128 Then               ' (-128 to +127 SByte Range)
    VLHold = anRxBuf[7]                                                                           
    VLRead = VLHold
    VLRead = (VLRead * 10)               ' Add Back *10 to go from "cm" Back to "mm"
    DelayMS 5
    string2Hold = " mm "                 
    string2Print = " VL " + Str$(SDec VLRead) + string2Hold       
    Print_At(arialn8,2,5,Str string2Print + "     ",0)
EndIf
----------------------------------------------------------------------------

 

Gabi

#4
updated to latest and seems ok now.



 
GL & 73
YO4WM

Craig

Thanks for the Help Guys works now as expected on the latest version of the compiler.
I change the compare statement to:

Dim STEMP As SBYTE
STEMP = anRxBuf[7]
If STEMP >= 0 Or STEMP <= 0 Then   ' Reads (-128 To +127 SByte Range)
 "
 "
Endif

tumbleweed

That IF statement doesn't make sense.
What other value for STEMP would make that statement false?

Craig

Hi Tumbleweed

I am Clearing the anRxBuf[7] every time before a new transmission is sent and then waiting for various sensors to complete their task and then checking anRxBuf[7] too see if there is any reading including 0 in it in the whole SByte Range (-128 To +127).

If I try various formats of the IF statement then it will always give me the Positive side of the SByte Range but, either gives a Wrong Reading on the Negative Side of the SByte Range or won't see the Negative side Correctly.

However if I use the ( If STEMP >= 0 Or STEMP <= 0 Then   ' Reads (-128 To +127 SByte Range) ) then it detects the correct Values each time Whether they are Positive or Negative, I do understand what you are saying Tumbleweed that there can never be a False State Because 0 is always Present.

The system under test does work because it uses a different sensor to check for target acquisition and then it reads this sensor Value held in the  anRxBuf[7] array which should always have a value present including Zero. {The sensor in question passes through [-550......0.......+550] this range as it takes it's readings}

There must be a Better way of checking the SByte Range more accurately and I will be very grateful for suggestions of how to better check and catch these readings in the If statement.

Kind Regards

Craig

 

tumbleweed

A signed byte (SBYTE) has a range of -128 to +127.

The comparison ">=0" would be true for values 0 to +127, and "<=0" would be true for values -128 to 0.
So, the IF statement is true for all values from -128 to +127, which is the entire range of an SBYTE.

In other words, it's always true.

If your sensor has a range of -550 to +550 then you need a larger variable than an SBYTE, like a 16-bit SWORD. That would require you to read two bytes from the serial stream.
 

Craig

Thanks Tumbleweed then my IF statement is correct and doing exactly what I need.
I have divided the Number by 10 so I can fit it into the SByte and then Multiplied it back by 10 afterwards so it is fine for now but, will look at updating it as you have suggested to an SWord.
Thanks for your help Tumbleweed Very much appreciated!
Kind Regards
Craig

tumbleweed

#10
You missed my point.

Since the IF statement is always true you can drop the tests entirely and just always do whatever is inside the IF THEN-ENDIF block with exactly the same results, but with less code.

Dim STEMP As SBYTE
STEMP = anRxBuf[7]
" do whatever you want with STEMP... no need to test ">= 0" or "<= 0" since that's always true

If you're dividing the sensor number -550 ... +550 by 10 to fit into a single byte -55...+55 then you're dropping the least significant digit, if that matters. You can't get it back by multiplying by 10.

atomix

This makes no sense and is always executed regardless of any STEMP value

If STEMP >= 0 Or STEMP <= 0 Then
Here is a picture explaining all the meanings of SByte:


DataRep_TwoComplement.png

John Drew


Craig
I notice in your RX code you are dimensioning AnRxBuff as byte which is 0 to 255.
You are then testing AnRxBuff[7] against -128 which will fail. You should only test for 0 to 255.

To help readers it's a good idea to use a naming convention.
For example
bAnRxBuff as byte
sbAnRxBuff as sbyte
So the prefix tells what kind of variable etc. Helps avoiding slips when programming.
Common prefixes you might think about:
sbTemp signed byte
bTemp as byte
wTemp as word
swTemp signed word
fTemp float
bitTemp as Bit
etc

Different people use other prefixes especially for bit as it clashes with byte. It doesn't matter as long as you have a system.
Cheers
John


JohnB

This is a very simple algorithm that requires minimal RAM

avg_accum = new_sample + avg_accum
avg_accum = sample_average
sample_average = avg_accum >> x

The value of X determines the level of damping.

JohnB

Craig

#14
Thank you Atomix for your detailed Definition and Thank yoiu John That is an Excellent Idea and makes coding much easier to follow at a glance.
Kind Regards
Craig