Positive/negative value handling

edmunds

Senior Member
Dear all,

I'm trying to come up with a PID or at least PI controller here. I think I've got my head around the structure, but I don't know how to handle negative values. I mean, I could add, say 255 to everything if these would be byte values in word-sized variables and see if it is more than zero or less in the end, but is there a better way?


Thank you for your time,

Edmunds
 

erco

Senior Member
Can you offset "zero" to 125 or so, so that 0 is like -125, 125 is like 0 and 250 is like 125? That's somewhat like the servo command, which centers at 150 rather conveniently for a 1.5 ms pulse.
 

hippy

Technical Support
Staff member
Two's complement arithmetic is the usual technique. For bytes -

$80 = -128
$81 = -127
:
$FE = -2
$FF = -1
$00 = 0
$01 = +1
$02 = +2
:
$7F = +127

For words ...

$8000 = -32768
$8001 = -32767
:
$FFFE = -2
$FFFF = -1
$0000 = 0
$0001 = +1
$0002 = +2
:
$7FFF = +32767
 
Last edited by a moderator:

edmunds

Senior Member
Thanks, @erco,

I assume so, but since the equations are dependent on the sign of the value, I have to introduce if or case statements then. Which, I guess, is inevitable one way or another by now.

Edmunds
 

edmunds

Senior Member
Two's complement arithmetic is the usual technique. For bytes -

$80 = -128
$81 = -127
:
$FE = -2
$FF = -1
$00 = 0
$01 = +1
$02 = +2
:
$7F = +127

For words ...

$8000 = -32788
$8001 = -32767
:
$FFFE = -2
$FFFF = -1
$0000 = 0
$0001 = +1
$0002 = +2
:
$7FFF = +32767
Now this looks a lot like a solution, but that on top of the algorithms part is totally complicated :). Thanks for the hint, will try to process it tomorrow.

Edmunds
 

BESQUEUT

Senior Member
I assume so, but since the equations are dependent on the sign of the value, I have to introduce if or case statements then. Which, I guess, is inevitable one way or another by now.
You can use negatives numbers for add and substract.
Multiply and divide have restrictions but may be usable sometime.
For example :
Code:
[color=Purple]b0[/color][color=DarkCyan]=-[/color][color=Navy]1[/color]
[color=Purple]b1[/color][color=DarkCyan]=[/color][color=Navy]4[/color]
[color=Purple]b3[/color][color=DarkCyan]=[/color][color=Purple]b1[/color][color=DarkCyan]+[/color][color=Purple]b0
b4[/color][color=DarkCyan]=[/color][color=Purple]b1[/color][color=DarkCyan]-[/color][color=Purple]b0
b5[/color][color=DarkCyan]=[/color][color=Purple]b0[/color][color=DarkCyan]*[/color][color=Purple]b1[/color][color=DarkCyan]+[/color][color=Navy]10[/color]
[color=Purple]b6[/color][color=DarkCyan]=[/color][color=Purple]b0[/color][color=DarkCyan]*[/color][color=Purple]b0[/color]
[color=Blue]sertxd([/color][color=Red]"b3="[/color][color=Black],#[/color][color=Purple]b3[/color][color=Black],[/color][color=Red]" b4="[/color][color=Black],#[/color][color=Purple]b4[/color][color=Black],[/color][color=Red]" b5="[/color][color=Black],#[/color][color=Purple]b5[/color][color=Black],[/color][color=Red]" b6="[/color][color=Black],#[/color][color=Purple]b6[/color][color=Black],[/color][color=Navy]13[/color][color=Black],[/color][color=Navy]10[/color][color=Blue])[/color]
 
Last edited:

AllyCat

Senior Member
Hi,

Addition and Subtraction are pretty easy, generally just use the Most Significant Bit as the "sign" (1 = negative). You may need a "Sign Extension" routine if converting from bytes to words, etc..

It's when you get to Multiplication and Division that things get a little more tricky. ;)

Cheers, Alan.
 

edmunds

Senior Member
It's when you get to Multiplication and Division that things get a little more tricky. ;)
Cheers, Alan.
Since I got away with Proportional only (out of PID) for this case, then it was really one line where I had to worry about this and that definitely was not the most difficult part :). If I would have had to do the integration part with old and new error properly then multiplication is inevitable and I don't even want to think about it for now. I'm sure it can be done and with experience it probably becomes even easy, but this robots, navigation and micro controllers stuff is steep :).


Thank you for helping to keep the spirits up,

Edmunds
 

stan74

Senior Member
Hi all. Negative numbers in picaxe basic has kept me up late trying to convert this line draw to picaxe. It's for drawing lines on 128x64 oled. I can plot a pixel from x,y co-ordinates ok it's putting the plot routine in here. I was thinking of 2's compliment with 2 byte values because they are bigger than 127.
1500 REM === DRAW a LINE. Ported from C version
1510 REM Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
1520 DX = ABS(X2 - X1):SX = -1:IF X1 < X2 THEN SX = 1
1530 DY = ABS(Y2 - Y1):SY = -1:IF Y1 < Y2 THEN SY = 1
1540 ER = -DY:IF DX > DY THEN ER = DX
1550 ER = INT(ER / 2)
1560 PLOT X1,Y1:REM This command may differ depending ON BASIC dialect
1570 IF X1 = X2 AND Y1 = Y2 THEN RETURN
1580 E2 = ER
1590 IF E2 > -DX THEN ER = ER - DY:X1 = X1 + SX
1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY
1610 GOTO 1560
 

hippy

Technical Support
Staff member
It's when you get to Multiplication and Division that things get a little more tricky. ;)
But not too tricky -

Code:
Symbol lhs      = w2
Symbol rhs      = w3
Symbol result   = w4
Symbol tempWord = w5

lhs =  8 : rhs =  2 : Gosub Multiply
lhs =  8 : rhs = -2 : Gosub Multiply
lhs = -8 : rhs =  2 : Gosub Multiply
lhs = -8 : rhs = -2 : Gosub Multiply

lhs =  8 : rhs =  2 : Gosub Divide
lhs =  8 : rhs = -2 : Gosub Divide
lhs = -8 : rhs =  2 : Gosub Divide
lhs = -8 : rhs = -2 : Gosub Divide

End

Multiply:
  tempWord = lhs : Gosub ShowSigned : SerTxd( " * "  )
  tempWord = rhs : Gosub ShowSigned : SerTxd( " = "  )
  tempWord = lhs ^ rhs
  If lhs >= $8000 Then
    lhs = -lhs
  End If
  If rhs >= $8000 Then
    rhs = -rhs
  End If
  result = lhs * rhs
  If tempWord >= $8000 Then
    result = -result
  End If
  tempWord = result : Gosub ShowSigned : SerTxd( CR, LF )
  Return

Divide:
  tempWord = lhs : Gosub ShowSigned : SerTxd( " / "  )
  tempWord = rhs : Gosub ShowSigned : SerTxd( " = "  )
  tempWord = lhs ^ rhs
  If lhs >= $8000 Then
    lhs = -lhs
  End If
  If rhs >= $8000 Then
    rhs = -rhs
  End If
  result = lhs / rhs
  If tempWord >= $8000 Then
    result = -result
  End If
  tempWord = result : Gosub ShowSigned : SerTxd( CR, LF )
  Return

ShowSigned:
  If tempWord >= $8000 Then
    SerTxd("-")
    tempWord = -tempWord
  End If
  SerTxd( #tempWord )
  Return
 
Top