PDA

View Full Version : How to prevent variable going below zero?



CuriousOne
- 21st June 2020, 11:32
reader:
adcin 0,Z
pause 100
IF Z>100 AND Z<130 THEN I=I+5
IF Z<100 THEN I=I-5
if i>255 then i=255
if i<5 then i=0
HPWM 2,I,10000
XY=I
gosub decoder
goto reader


Here is the simple code, the part if i>255 then i=255 works fine, but the part if i<5 then i=0 does not, because when i value goes below 0, it does not go below zero, it goes to 65535 and so on, completely messing whole code. Any ideas?

Charlie
- 21st June 2020, 13:59
The convention used by most software is that if the most significant bit is set, then the number is negative.

CuriousOne
- 21st June 2020, 15:59
Picbasic has no idea about negative numbers, anything goes below 0 gets deducted from 65535.

mpgmike
- 22nd June 2020, 01:47
First, you didn't include what size your "z" & "i" variables are; var BYTE or WORD? If you declared them as BYTEs then 256 becomes your roll-over value, not 65536. If you are adding and want to check to see if your variable went over 255 and rolled over, the STATUS Register will show "STATUS.C = 1". If subtracting and want to see if it rolled from 0 to 255, "STATUS.C = 0". Look in your data sheet for the STATUS Register and how it works.

richard
- 22nd June 2020, 02:47
mike would you like to provide some pbp code that demonstrates use of status register following pbp addition or subtraction


the status reg here is not in any way influenced by the subtraction result

i = byte



j=8
i=6
while j
status=1
i=i-1
s=status
debug 13,10,"status ",bin8 s ," i ", dec i
j=j-1
wend



result


status 00011001 i 5
status 00011001 i 4
status 00011001 i 3
status 00011001 i 2
status 00011001 i 1
status 00011101 i 0
status 00011001 i 255
status 00011001 i 254

CuriousOne
- 22nd June 2020, 07:16
Yes variable is WORD, because if use BYTE, IF I>255 statement also wont work :D

mpgmike
- 22nd June 2020, 07:36
mike would you like to provide some pbp code that demonstrates use of status register following pbp addition or subtraction


the status reg here is not in any way influenced by the subtraction result

i = byte



j=8
i=6
while j
status=1
i=i-1
s=status
debug 13,10,"status ",bin8 s ," i ", dec i
j=j-1
wend


result

status 00011001 i 5
status 00011001 i 4
status 00011001 i 3
status 00011001 i 2
status 00011001 i 1
status 00011101 i 0
status 00011001 i 255
status 00011001 i 254
You don't state what PIC this is for, so I randomly grabbed the data sheet for a PIC16F1824; STATUS Register 3-1, page 24.

STATUS <7:5> = Unimplemented, read as 0
STATUS.4 = TO: Time-Out bit
STATUS.3 = PD: Power-Down bit
STATUS.2 = Z: Zero bit
STATUS.1 = DC: Digit Carry
STATUS.0 = C: Carry

You can see when you reached zero the STATUS.Z reflected that. However, you alter the STATUS Register in your code. About the only thing you can change is the C bit. Delete the "status=1" line and try again.

richard
- 22nd June 2020, 07:56
You can see when you reached zero the STATUS.Z reflected that. However, you alter the STATUS Register in your code. About the only thing you can change is the C bit. Delete the "status=1" line and try again.

your assertion is

If subtracting and want to see if it rolled from 0 to 255, "STATUS.C = 0". Look in your data sheet for the STATUS Register and how it works.



You don't state what PIC this is for, so I randomly grabbed the data sheet for a PIC16F1824; STATUS Register 3-1, page 24.

if your assertion was correct it would not matter but its a12f1840

i repeat
mike would you like to provide some pbp code that demonstrates use of status register following pbp addition or subtraction
for any chip

richard
- 22nd June 2020, 08:31
a look at the lst file yields the reasons .
the status reg is not useful when you add or subtract a const 1
if you use a number greater than 1 or another var then the code does a proper addition/subtraction rather than inc/dec and sets status reg correctly

caveat emptor

Charlie
- 22nd June 2020, 13:29
Picbasic has no idea about negative numbers, anything goes below 0 gets deducted from 65535.
Re-read the single line I sent. I was not talking about PBP. I'm talking about representation of integers in a binary system. Read this article: https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html What most software developers do when they want to know when the variable goes "below zero", is look at the most significant bit. If it is high, the number is negative, if it is low, the number is positive. Since you are using a word, then your largest positive number will be 32768.

CuriousOne
- 22nd June 2020, 15:46
And since here is PBP forum, not general representation forum, I'm asking how to deal with this in PBP :)

peterdeco1
- 22nd June 2020, 17:29
Will this work for you?

iflag var bit
let iflag =0

reader:
adcin 0,Z
pause 100
IF Z>100 AND Z<130 THEN I=I+5
IF Z<100 and iflag = 0 THEN I=I-5 'only if iflag = 0 it's OK to substract
if i>255 then i=255
if i<5 then i=0
if i = 0 then let iflag = 1 'if i hits 0 put up a flag
if i >= 5 then let iflag = 0 'once i hits 5 or more, reset the flag
HPWM 2,I,10000
XY=I
gosub decoder
goto reader

tumbleweed
- 22nd June 2020, 20:02
In your original code, change
IF Z<100 THEN I=I-5 to this
IF Z<100 AND I>=5 THEN I=I-5

Dick Ivers
- 22nd June 2020, 20:07
Try this:

if Z.15 = 1 then
Z = 0
endif

Ioannis
- 23rd June 2020, 07:47
reader:
adcin 0,Z
pause 100
IF Z>100 AND Z<130 THEN I=I+5
IF Z<100 THEN I=I-5
if i>255 then i=255
if i<5 then i=0
HPWM 2,I,10000
XY=I
gosub decoder
goto reader



1. tumbleweed caught one problem in your code.

2. The variable I is altered some where? What check are you making ensuring it will not get a value to lead in negative results doing a -5 subtraction inside the reader routine?

Ioannis

peterdeco1
- 23rd June 2020, 08:35
I like Tumbleweed's code. Shorter and more to the point.

richard
- 23rd June 2020, 09:20
With a few proviso's mikes way beats it hands down




IF Z<100 THEN I=I-5
asm
BTFSS STATUS,C
CLRF _I
ENDASM



if i attempts to underflow its set to 0

Ioannis
- 23rd June 2020, 10:50
I like it how a simple logic problem CuriousOne had, lead to another topic with negative numbers and STATUS register!

Quite interesting!

Ioannis

richard
- 23rd June 2020, 11:01
anyone familiar with assembly programming will be well aware of the status reg and its use. what surprised me is that
the value of the status reg was/is preserved even after the completion of the transaction. because the result is transferred from the
working regs back into the result variable during the process i expected the status to be no longer representative of the calculation.
surprised yet again !

Ioannis
- 23rd June 2020, 12:17
You are absolutely right! I do not trust that this may be the case for any PIC though.

Ioannis

richard
- 23rd June 2020, 13:30
I do not trust that this may be the case for any PIC though.

its a quick easy test to check, it works on all chips that i tried just make sure the compiler dosn't compress the subtract into a decrement
i var can be byte or word



j=8
i=6
while j
status=1
i=i-2 ;subtractant cannot be 1
s=status
debug 13,10,"status ",bin8 s ," i ", dec i
j=j-1
wend

Ioannis
- 23rd June 2020, 16:31
Well, thanks for checking out. Wow!

Ioannis

Acetronics2
- 24th June 2020, 08:20
reader:
adcin 0,Z
pause 100
IF Z>100 AND Z<130 THEN I=I+5
IF Z<100 THEN I=I-5
if i>255 then i=255
if i<5 then i=0
HPWM 2,I,10000
XY=I
gosub decoder
goto reader


Here is the simple code, the part if i>255 then i=255 works fine, but the part if i<5 then i=0 does not, because when i value goes below 0, it does not go below zero, it goes to 65535 and so on, completely messing whole code. Any ideas?

Using MAX and MIN operators provided by the compiler ????

4 times IF-THEN in a row, ... Time to have a look to SELECT CASE ...

BTW ... if you want your number staying between 0 and 255 ... use a BYTE, instead of a WORD ... :rolleyes:

I'm just curious about what you try to do ( in the real world, of course ) with such a piece of code !!!

Alain

tumbleweed
- 24th June 2020, 11:45
if you want your number staying between 0 and 255 ... use a BYTE, instead of a WORD
That's his problem... he DOES want to use a byte but as he adds or subtracts to the byte value it wraps and gives false operation.

The way I usually handle this sort of thing is to have a routine that does the addition or subtraction with a temp copy of the variable, and only update the variable if the operation is valid.

You don't have to detect a negative number... what you want to know is if you add X to Y will it be < Y (wrapped 255) and if you subtract X from Y will it be > Y (wrapped 0). Don't modify Y until you know the answer. You can have the routine limit the results to 255 or 0 if that's how you want it to work, or ignore the operation.

CuriousOne
- 25th June 2020, 06:20
So this "wrapping" is compiler related issue and can't be fixed, as I understand?

CuriousOne
- 25th June 2020, 07:18
Technically, I solved this problem by making I change between 5 and 260, and outputting HPWM 2,I-5,10000.

Ioannis
- 25th June 2020, 07:20
If you mean a compiler problem, no. It is not.

If you mean how binary arithmetic works, yes. That is how you count, add or subtract in binary having byte, word or other size variables. In any case that is how you do it in decimal also but do not give it much attention.

The "fix" is in the answers given already to you. SELECT CASE, test before updating for valid result, etc...

Ioannis

richard
- 25th June 2020, 07:49
the mind boggles