Program To Split ADC Value - too long

TomMystery

New Member
I need a program to take an ADC value and split each of the numbers into seperate variables. Since I do not know of a specific command that will allow me to do that I wrote the following program. Unfortunately it is too long by 3 bytes. Any ideas as to what I could do to reduce the size of the program? Or whether there is another way to do it?

readchip:
readadc 1,b0

first:
if b0 >= 200 then th
th:
let b1 = 2
let b0 = b0 - 200
goto second

if b0 >= 100 then oh
oh:
let b1 = 1
let b0 = b0 - 100
goto second

if b0 > 100 then nh
nh:
let b1 = 0

second:
if b0 >= 90 then nit
nit:
let b2 = 9
let b0 = b0 - 90
goto third

if b0 >= 80 then eit
eit:
let b2 = 8
let b0 = b0 - 80
goto third

if b0 >= 70 then svt
svt:
let b2 = 7
let b0 = b0 - 70
goto third

if b0 >= 60 then sit
sit:
let b2 = 6
let b0 = b0 - 60
goto third

if b0 >= 50 then fit
fit:
let b2 = 5
let b0 = b0 - 50
goto third

if b0 >= 40 then fot
fot:
let b2 = 4
let b0 = b0 - 40
goto third

if b0 >= 30 then tht
tht:
let b2 = 3
let b0 = b0 - 30
goto third

if b0 >= 20 then twt
twt:
let b2 = 2
let b0 = b0 - 20
goto third

if b0 >= 10 then tet
tet:
let b2 = 1
let b0 = b0 - 10
goto third

if b0 > 10 then zet
zet:
let b2 = 0

third:
if b0 = 9 then ni
ni:
let b3 = 9
goto sendvalue

if b0 = 8 then ei
ei:
let b3 = 8
goto sendvalue

if b0 = 7 then se
se:
let b3 = 7
goto sendvalue

if b0 = 6 then si
si:
let b3 = 6
goto sendvalue

if b0 = 5 then fi
fi:
let b3 = 5
goto sendvalue

if b0 = 4 then fo
fo:
let b3 = 4
goto sendvalue

if b0 = 3 then thr
thr:
let b3 = 3
goto sendvalue

if b0 = 2 then two
two:
let b3 = 2
goto sendvalue

if b0 = 1 then one
one:
let b3 = 1
goto sendvalue

if b0 = 0 then ze
ze:
let b3 = 0

sendvalue:
serout 0,N2400, (b1)
serout 2,N2400, (b2)
serout 4,N2400, (b3)
goto readchip
 

Technical

Technical Support
Staff member
Label length makes no difference to program size.

Try this trick: Replace all your double lines

let b3=?
goto sendvalue

with the single line

goto addb3_x
(where ? = 1 to 9 as appropriate)

and then use this code instead

addb3_9: let b3 = b3 + 1
addb3_8: let b3 = b3 + 1
addb3_7: let b3 = b3 + 1
addb3_6: let b3 = b3 + 1
addb3_5: let b3 = b3 + 1
addb3_4: let b3 = b3 + 1
addb3_3: let b3 = b3 + 1
addb3_2: let b3 = b3 + 1
addb3_1: let b3 = b3 + 1
goto sendvalue


You need to make b3 = 0 before you start.


However your program won't work anyway. The lines such as

if b0 >= 200 then th
th:

are pointless - th will be executed whatever the value is. You need to jump to the next label, not the one adjacent.

Edited by - Technical on 2/4/2006 9:32:34 PM
 

Fowkc

Senior Member
From the look of this type if IF statement you have:
<code><pre><font size=2>
first:
if b0 &gt;= 200 then th
th:
let b1 = 2
let b0 = b0 - 200
goto second
</font></pre></code>

The program will always run the th label. If b0 is greater than or equal to 200, goto th, otherwise, it will just run the next line, which is where the th label is.

But as for getting seperate variables out, there's a much easier way. Just use division.
For example, consider an ADC value of b0 = 186. Divide by 100:

b1 = b0 /100 (so b1 = 1 in this case)

Then take away that many hundreds from b0:

b2 = b1 * 100 (=100 in this case)
b0 = b0 - b2 (186 - 100 = 86)

Repeat the division with tens:

b2 = b0 / 10 (= 86/10 = 8)

Take away that many tens from b0:
b3 = b2 * 10 (=80)
b0 = b0 - b3 (=86 - 80 = 6)

Micheal, I thought label names didn't contribute to code size (in terms of their length). The name itself isn't compiled to assembler is it? It's just to make programming easier?
 

Technical

Technical Support
Staff member
This works better

readchip:
readadc 1,b0

b1 = b0/100 'divide by 100 to get hundreds

b4 = b1*100
b2 = b0-b4/10 'orignal minus hundreds / 10

b4 = b1*100
b5 = b2*10
b3 = b0-b4-b5 'original - hundreds - tens

serout 0,N2400, (b1)
serout 2,N2400, (b2)
serout 4,N2400, (b3)
goto readchip
 

Michael 2727

Senior Member
Thank's, I was stuck also the other day.
Needed 2 extra bytes, ended up changing
pause times to get the space I needed.
 

BarryP

Senior Member
Or Perhaps Use The Modulus Operator.
Symbol ADCval = B0
Symbol Hundreds = B1
Symbol Tens = B2
Symbol Ones = B3
Hundreds = ADCval/100
Tens = ADCval//100/10
Ones = ADCval//100//10

BTW , Do you have 3 separate devices that receive the Hundreds,Tens,Ones on Pins 0,2,4 ? or is it a mistake.
 

manuka

Senior Member
David Lincoln's Vol.2 booklet 'Expts in Mechatronics' P.18-25 details number massaging insights. These are very lucidly explained &amp; are just the ticket for slicing off remainders etc. See an example from March 05 SiChip =&gt; www.picaxe.orcon.net.nz/uhfcbds.bas <A href='http://www.picaxe.orcon.net.nz/uhfcbds.bas ' Target=_Blank>External Web Link</a>
 

TomMystery

New Member
Thanks for your help technical, that really does simplify things. I also didn't know that the labels would be executed, I thought that it would just jump to the next if statement.

As for the question about devices, yes I have 3 different devices that will then act on the code recieved.
 

TomMystery

New Member
Actually, I just thought about the program.

Wouldn't b1 round to 1 if b0 was 98? Or does the chip always round down? Sorry, this is my first project using the picaxe microcontroller.
 

BarryP

Senior Member
Nope
It is Integer Math (No Fractions)
I.E.
10/3 = 3
To Get The Remainder &amp; Work With It Use Modulus Divide ( // )
10//3 = 1

Just To Clear .. The Fractional Part Is efectivly Chopped Off . NO rounding is done.



Edited by - barryp on 2/5/2006 2:51:52 AM
 
Top