PDA

View Full Version : Working code but my layman approach uses too much code space



Christopher4187
- 12th December 2012, 18:15
Trial and error led me to this code after my description just below. It works just like I need it to but there has to be a better way. The formula provided is this:
0.125*(M1*256+M2-0x0FA0)Seems simple, right? Not for me.....

So if M1=15 and M2=160 the result is 0. Both are byte variables so a rollover from M2 will increase M1 by 1. Increasing this number will provide a positive number and decreasing it will provide a negative number. In addition to the difficulty I was having with the formula, I had to account for formatting on my screen so triple digit numbers needed to be formatted differently than double digit numbers. Any comments are appreciated!

B1=256
B2=4000
MULT=125
G3T and G4T are byte sized variables

SELECT CASE G3T
CASE 15
SELECT CASE G4T
CASE IS < 160
DUMMY =MULT*((G3T*B1)+(G4T+B2))
MG2_NM = DIV32 100
MG2_NM=10000-MG2_NM
IF MG2_NM > 999 THEN
LCDOUT $FE, POS4-1,"-",DEC MG2_NM/10,".",DEC MG2_NM DIG 0
ELSE
LCDOUT $FE, POS4-1,"-",DEC MG2_NM/10,".",DEC MG2_NM DIG 0," "
ENDIF
CASE IS >= 160
MG2_NM=(G4T*125)-20000
IF MG2_NM > 9999 THEN
LCDOUT $FE,POS4-1," ",DEC MG2_NM/100,".",DEC MG2_NM DIG 0
ELSE
LCDOUT $FE,POS4-1," ",DEC MG2_NM/100,".",DEC MG2_NM DIG 0," "
ENDIF
END SELECT
CASE IS < 15
DUMMY =MULT*((G3T*B1)+(G4T+B2))' GOOD FOR NEGATIVE NM, INCLUDING ZERO
MG2_NM = DIV32 100
MG2_NM=10000-MG2_NM
IF MG2_NM > 999 THEN
LCDOUT $FE, POS4-1,"-",DEC MG2_NM/10,".",DEC MG2_NM DIG 0
ELSE
LCDOUT $FE, POS4-1,"-",DEC MG2_NM/10,".",DEC MG2_NM DIG 0," "
ENDIF
CASE ELSE
DUMMY = MULT*((G3T*B1)+(G4T-B2))
MG2_NM = DIV32 100
IF MG2_NM > 999 THEN
LCDOUT $FE,POS4-1," ",DEC MG2_NM/10,".",DEC MG2_NM//10
ELSE
LCDOUT $FE,POS4-1," ",DEC MG2_NM/10,".",DEC MG2_NM//10," "
ENDIF
END SELECT

If someone comes up with a one-line code I'm going to slit my wrists.....

I have another issue that I'm having difficulty solving. I'm viewing data that comes at a very fast rate. The number is very jumpy because it changes quickly. I know I can average it but if I average say 5 measurements, it would seem good for those five measurements but when compared with the next five measurements I would think the number would still appear jumpy. What is a good way to make a measurement look smooth? It looks like the data is sent about 90 times a second.

HenrikOlsson
- 12th December 2012, 19:50
Hi,
I don't follow your code that well but the formula...

0.125*(M1*256+M2-0x0FA0)
As far as I can see you're combining two bytes into a word where M1 is the high byte anf M2 the low byte. Then you subtract 4000 from that value and multiply 0.125. You can combine the two bytes into a word simply by creating a word variable and aliasing the high and low bytes. Subtracting 4000 is a no brainer and multiplying by 0.125 is the same as dividing by 8, dividing by 8 is the same as shifting the value 3 places to the right, right?


Result VAR WORD ' This is the "output" value.
Value VAR WORD ' This is the "input" variable consisting of two bytes, namely...
M1 VAR Value.HighByte ' ...M1,m which is the high byte and...
M2 VAR Value.LowByte ' ...M2, qhich is the low byte

' Now, if M1 is 15 ($0F) and M2 is 160 ($A0) Value is $0FA0 so the result, after subtracting 4000 ($0FA0) will be 0.

Sign VAR BIT

Result = (Value - 4000) ' Subtract 4000
Sign = Result.15 ' Remember if the value is negative.
Result = ABS(Result) ' Take the absolute value of Result.
Result = Result >> 3 ' Divide that by 8
If Sign THEN Result = -Result ' If the original value (before dividing by 8) was negative, so is the result.

Now, Result will be a signed two-complements number, if the high bit is set the value is negative, else it's positive. To display it on the LCD you can use the SDEC modifier, it will print it correctly with a negative sign in front (if negative of course). To display a fixed number of digits you can use for example SDEC3 which will display 3 digits (012 or -123 for example).

Just be aware that incrementing M2 so it rolls over will not automatically increment M1, for that to happen you must increment Value.

Not sure that's what you're really asking but I tried... :-)

/Henrik.

HenrikOlsson
- 12th December 2012, 20:14
Hi again,
I forgot the second part. You need what's called a rolling average or moving average (http://en.wikipedia.org/wiki/Moving_average). Darrel has a piece of code on his site, here (http://www.pbpgroup.com/modules/wfsection/article.php?articleid=7) and for more great info on integer math, including filters etc, take a close look at Tracy Allens BS2 math notes (http://www.emesystems.com/BS2math.htm).

/Henrik.

SteveB
- 12th December 2012, 20:22
Like Henrik said, the formula is really subtracting 4000 from a WORD. So here's the way I tackled it:



wCalc VAR WORD
G3T VAR wCalc[0]
G4T VAR wCalc[1]
IF wCalc <4000 THEN 'Number will be negative
DUMMY =MULT*(wCalc+B2)
MG2_NM = DIV32 100
MG2_NM=10000-MG2_NM
LCDOUT $FE, POS4-1,"-"
ELSE 'Number will be positive or 0
Dummy = MULT*(wCalc-B2)
MG2_NM = DIV32 100
LCDOUT $FE,POS4-1," "
ENDIF
IF MG2_NM < 100 THEN
LCDOUT " "
ELSEIF MG2_NM < 1000 THEN
LCDOUT " "
ENDIF
LCDOUT DEC MG2_NM/10,".",DEC MG2_NM//10

Christopher4187
- 14th December 2012, 20:44
Thanks for the help guys. Your posts helped out a lot.