Searching \ for '[PIC] Convert ASCII string to variable for compari' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: massmind.org/techref/microchip/devices.htm?key=pic
Search entire site for: 'Convert ASCII string to variable for compari'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] Convert ASCII string to variable for compari'
2005\11\30@042620 by Jinx

face picon face
Can I get some suggestions from you clever lot please. I don't
use C, this will be in assembler

A PIC is connected to several analogue sensors. These sensors
have FSDs of 5V or 12V scaled down to 5V. A user inputs an
ASCII string so that the PIC will alert them when the sensor
meets the requirements of the string

For example, say the PIC was monitoring a 12V battery, the
ASCII sent might be L11, which means "alert me if the voltage
goes below (is "L"ess than) 11V". Similarly G (>) or E (=)

Right, here's the tricky bit

Taking the example above as a fairly simple implementation, I
know what the scale factor is (5:12) and that the highest result
from the A2D is 12V, so can work it out from there

What I really want to do is make a universal system so that any
ASCII string can be compared to any sensor voltage, so that the
user receives not only the alert but also a message in appropriate
terms and units

Another example, exaggerated but it shows what I'm after. A
temperature sensor has a 0-12V o/p, spanning the range 0C to
40C. The user sends the PIC "G20.58", meaning "alert me when
the temperature goes over 20.58 degrees"

Now there are two things to consider. First is the 5:12 scaling
of the input, second is converting the "20.58" to a variable that
can be compared to the A2D

I've tried a few things long-hand and wonder if there's a generic
way of doing it

First thing I tried was to search the string for a "." and then split
it. Working left from the "." I multiply by successive magnitudes
of 10, starting with a magnitude that depends on the position that
the number was sent to in an array. So "20" would be 0 x 1000
+ 2 * 10,000

But then realised I could maybe just pad either end with "0" and
convert the whole string to a number, then scale it in accordance
with the scale factor so that it could be compared. When sending
an ASCII message back, use inverse scaling. This would need to
be done (rather than simply echoing the original figure - eg "20.58
degrees reached) in case where the user is asking for an analogue
reading, in which instance the PIC would have to compose a
string from that reading in terms of the sensor's function and range

Strings (limited to 5 chars but all 5 not necessarily used) would be

y.xx
yy.xx
yyy.x

but if there's a simple way then covering .xxxx to yyyy would
be good (although they may be seldom, if ever, used)

I've spent a couple of days on this, and there still seems to be lot
of long-hand if...then, search this, search that coding ahead unless
I find a more elegant solution

TIA

===============================================
If you aren't part of the solution, you're part of the precipitate

2005\11\30@044523 by Richard Prosser

picon face
One thing that you need to do is figure out if the numeric part is
always to include 2 (or more, or less) decimals. For example is "G22"
likely to be input or is it always "G22.00". If decimal places ar
ealways present, the decimal point can  be ignored and the scaling
becomes much easier.

RP

On 30/11/05, Jinx <spam_OUTjoecolquittTakeThisOuTspamclear.net.nz> wrote:
{Quote hidden}

> -

2005\11\30@051831 by Jinx

face picon face


> One thing that you need to do is figure out if the numeric part is
> always to include 2 (or more, or less) decimals. For example is
> "G22" likely to be input or is it always "G22.00". If decimal places
> are always present, the decimal point can  be ignored and the
> scaling becomes much easier

I would like to cater for any format of i/p the user chooses, so
the only significant character is the "." (or lack thereof, implying
an integer). ie 0022, 022, 22, 22.0, 22.00 must all be interpreted
by the PIC as plain 22. I realise that the more latitude I give the
user, the more comprehensive the interpreter needs to be, but I'm
prepared to go the extra mile for the sake of user-friendliness

2005\11\30@053948 by Alan B. Pearce

face picon face
>> One thing that you need to do is figure out if the numeric part is
>> always to include 2 (or more, or less) decimals. For example is
>> "G22" likely to be input or is it always "G22.00". If decimal places
>> are always present, the decimal point can  be ignored and the
>> scaling becomes much easier
>
>I would like to cater for any format of i/p the user chooses, so
>the only significant character is the "." (or lack thereof, implying
>an integer). ie 0022, 022, 22, 22.0, 22.00 must all be interpreted
>by the PIC as plain 22. I realise that the more latitude I give the
>user, the more comprehensive the interpreter needs to be, but I'm
>prepared to go the extra mile for the sake of user-friendliness


Have you looked to see if Olins command line whatsit could be modified to do
what you want?

But I suspect the easiest way if you have to start from scratch may be to
get a demo C compiler for this bit, even if you then link in assembler code.
Of course the other way to deal with this is to do the translation if an HLL
(could even be GWBasic - shudder) in a PC, and send a suitable hex string to
the PIC. I have done this before.

2005\11\30@055429 by Jinx

face picon face
> Have you looked to see if Olins command line whatsit could be
> modified to do what you want?

No, I haven't

> But I suspect the easiest way if you have to start from scratch
> may be to get a demo C compiler for this bit

Hmmm, C has always been on the back burner (have HighTech),
and not sure if I want to face another learning curve just at the
moment. Good suggestion though, and C is maybe something I
should have gotten around to earlier, but you know how it is. You
look up, it's Xmas again and the to-do list isn't any shorter

> Of course the other way to deal with this is to do the translation in
> an HLL (could even be GWBasic - shudder) in a PC, and send a
> suitable hex string to the PIC. I have done this before

No PC involved unfortunately, this is completely stand-alone

2005\11\30@055719 by Andrew Warren

face
flavicon
face
Jinx <.....piclistKILLspamspam@spam@mit.edu> wrote:

> A temperature sensor has a 0-12V o/p, spanning the range 0C to 40C.
> The user sends the PIC "G20.58", meaning "alert me when the
> temperature goes over 20.58 degrees"
>
> Now there are two things to consider. First is the 5:12 scaling
> of the input, second is converting the "20.58" to a variable that can
> be compared to the A2D
>
> I've tried a few things long-hand and wonder if there's a generic way
> of doing it

Ok... If you just wanted to convert from ASCII to decimal (and if you
didn't have to check the string for conformance to your syntax), you
would:

1.  Point at the rightmost character.
2.  MULTIPLIER = 1.  TOTAL = 0.
3.  Grab the character at which we're pointing.  If it's a "G" (or
"E" or "L" or whatever), exit.
4.  Otherwise, if it's a decimal point, divide TOTAL by MULTIPLIER,
set MULTIPLIER = 1, and go to step 7.
5.  Otherwise, convert the character from ASCII to a decimal number,
multiply it by MULTIPLIER, and add it to TOTAL.
6.  MULTIPLIER = MULTIPLIER * 10.
7.  Move your pointer one character leftward, then go to step 3.

That process would convert your "G20.58" to the number 20.58 (in
whatever format you've chosen to represent non-integers)... But YOU
want to convert it to a number that takes into account the ADC
scaling, so for your particular case (temperature sensor reads 0-40C
and max ADC value is 255), you'd change step 5 to read:

   5.  Otherwise, convert the character from ASCII to a decimal
   number, multiply it by MULTIPLIER * 255/40, and add it to TOTAL.

With that change, you'd get:

CHARACTER   MULTIPLIER   TOTAL
               1         0
   8           1         8 * 1 * 255/40 = 51
   5           10        51 + 8 * 10 * 255/40 = 369.75
   .           100       369.75/100 = 3.6975
   0           1         3.6975 + 0 * 1 * 255/40 = 3.6975
   2           10        3.6975 + 2 * 10 * 255/40 = 131.1975
   G           100       131.1975

So your ADC threshold is 131 or so.  Is that what you wanted?

-Andrew

=== Andrew Warren - fastfwdspamKILLspamix.netcom.com

2005\11\30@064840 by Jan-Erik Soderholm

face picon face
Not answering your question, but...

Jinx wrote :

> No PC involved unfortunately, this is completely stand-alone

What input device is used that gives the user the
flexibility in input format that you described before ?

Maybe you can't change that, but must the user
have that flexibility ?

Jan-Erik



2005\11\30@072235 by Jinx

face picon face
> So your ADC threshold is 131 or so.  Is that what you wanted?

Hi Andrew, yes it is. You've done it in a slightly different way to
what I've been experimenting with. One approach I tried, and I
think I may have done a little too much thinking about this and
lost focus, was to think of all numbers in terms of millivolts. The
sensor interfaces I'll be using have their limits, so at least that part
of it isn't open-ended. So, taking the battery monitor as an example,
say I used a 3:1 divider, therefore 5V to the A2D represents
15V, which would be a reasonable limit for a 12V battery

If the user wants the PIC to send a message when the voltage
reaches 13.5V, this would need to be stored as a comparison
figure of 1023 / (13.5 /3)

I admit again, maybe my thinking has gone fuzzy. It seemed
simple enough to start with. I was hoping that trying to explain
it to someone else and then perhaps discussing it might help
me get a better grip on what seems so slippery. It could be
that I'm getting bogged down because I've over-complicated it

2005\11\30@072239 by Jinx

face picon face

> What input device is used that gives the user the
> flexibility in input format that you described before ?

SMS or GSM data

> Maybe you can't change that, but must the user
> have that flexibility ?

Well, people are people. As Josh says -

"A common mistake that people make when trying to design
something completely foolproof is to underestimate the ingenuity
of complete fools.
       -Douglas Adams"

I *could* make the input ASCII conform to a specified format,
but that wouldn't actually change the interpretation or actions
needed, as you have to allow for decimals. It would be unreasonable
to expect a user to enter a battery voltage in xxxxx mV for example

User-input flexibility is desirable (stopping short of "type whatever
you feel like, the PIC will know what you really meant"), interpretation
flexibility is pretty much essential

2005\11\30@072625 by Jinx

face picon face

> If the user wants the PIC to send a message when the voltage
> reaches 13.5V, this would need to be stored as a comparison
> figure of 1023 / (13.5 /3)

My mistake -

1023 * ( 13.5 / 15 )

2005\11\30@080133 by Jan-Erik Soderholm

face picon face
Jinx wrote :

> > What input device is used that gives the user the
> > flexibility in input format that you described before ?
>
> SMS or GSM data

Ah, that explains it. I've seen similar SMS-based
messaging system byt they had quite strickt
rules to how to write the messages to the "device".
In that case it was setting/clearing digital I/O lines,
but the principle was the same. more or less. You
could also query the status of the input lines. Anyway...

Maybe you could respond to an "unknown" message
with a short "usage" message ? With a couple of
formating exemples. Or implement a "help" command,
the user sends "help" in an SMS and gets a short help
text back.

Anyway, now it's much cleaer what environment the
PIC code operates in ! :-)

Finaly, I don't know if having an SMS "interface" still
counts as "stand alone"... :-)

Regards,
Jan-Erik.



2005\11\30@082930 by olin piclist

face picon face
Jinx wrote:
> What I really want to do is make a universal system so that any
> ASCII string can be compared to any sensor voltage, so that the
> user receives not only the alert but also a message in appropriate
> terms and units

Since you're dealing with verbose ASCII strings over a serial port, I'll
assume that compute cycles aren't critical.  If so, this sounds like a
natural application for floating point.  That way you don't have to worry
about the max range on one end and the min precision on the other.  For each
A/D channel, you keep two numbers that can be pre-computed at assembly time.
These are the scale factor and offset to go from the user values to the A/D
reading.  Using the same two numbers you do a subtract and a divide to go
the other way.

The remaining issue is converting a floating point value to its ASCII
representation.  Again I'm assuming cycles are available, so brute force it.
One general routine will be easier to write and maintain, even if it takes a
few more cycles.  By brute force it, I mean using multiple of 10 scale
factors, probably again using floating point because of the unknown range.

I use a 24 bit floating point format for this, which leaves 16 bits of
precision.  That's plenty good enough considering you're ultimately dealing
with 10 or 12 bit A/D readings, even allowing a few bits for roundoff
errors.  As for pre-computing the fixed scale factors and offsets at
assembly time, use my preprocessor.  It adds floating point as a native data
type to MPASM and does the assembly time calculations in the host floating
point format.  It also includes conversion functions to emit the hex values
in MPASM syntax for the resulting values in my PIC 24 bit floating point
format.  If you're not already using my PIC development environment and
relocatable mode and the preprocessor, maybe now's a good time to See the
Light and jump in.  I won't ask you to drink any grape coolaid.  It's really
not that hard and in a few weeks you'll wonder how you ever got along with
out it.

If you do that, I'll send you my 24 bit floating point routines privately.
I don't give these away on the web, but I don't mind you using them as long
as you don't give them out publicly.


******************************************************************
Embed Inc, Littleton Massachusetts, (978) 742-9014.  #1 PIC
consultant in 2004 program year.  http://www.embedinc.com/products

2005\11\30@084054 by olin piclist

face picon face
Jinx wrote:
> I would like to cater for any format of i/p the user chooses, so
> the only significant character is the "." (or lack thereof, implying
> an integer). ie 0022, 022, 22, 22.0, 22.00 must all be interpreted
> by the PIC as plain 22. I realise that the more latitude I give the
> user, the more comprehensive the interpreter needs to be, but I'm
> prepared to go the extra mile for the sake of user-friendliness

This is really not hard if you break it into two algorithms, one before the
point and one after.  Before the point initialize the value to 0.  For each
digit, multiply the current value by 10, then add the digit.  After the
point init a scale factor to .1.  For each digit, multiply the digit value
by the scale factor, add that into the accumulated value, then multiply the
scale factor by .1.


******************************************************************
Embed Inc, Littleton Massachusetts, (978) 742-9014.  #1 PIC
consultant in 2004 program year.  http://www.embedinc.com/products

2005\11\30@084740 by Alan B. Pearce

face picon face
>Jinx wrote:
>> What I really want to do is make a universal system so that any
>> ASCII string can be compared to any sensor voltage, so that the
>> user receives not only the alert but also a message in appropriate
>> terms and units
>
>Since you're dealing with verbose ASCII strings over
>a serial port, I'll assume that compute cycles aren't
>critical.  If so, this sounds like a natural
>application for floating point.

This also comes back to what I said earlier. It may be worth going to an HLL
demo compiler to do the parsing of the incoming strings, and then using the
arithmetic routines of the HLL. With C18 freely available it may be worth
looking at an 18F chip anyway for the memory size, if Jinx ends up having to
deal with umpteen formatting possibilities.

2005\11\30@085738 by Dave Lag

picon face
Jan-Erik Soderholm wrote:
> Jinx wrote :
>>SMS or GSM data
>
> Maybe you could respond to an "unknown" message
> with a short "usage" message ? With a couple of
> formating exemples. Or implement a "help" command,
> the user sends "help" in an SMS and gets a short help
> text back.
........
> Regards,
> Jan-Erik.

That would become "real" popular in a U$AGE based network.
:(

2005\11\30@090809 by Bob Ammerman

picon face
Here you go. Sorry for the pseudo-"C", but you can covert the algorithm
easily to ASM:




char        buf[?];            // buffer with ascii value

long        value = 0;        // will be value, scaled to include two
decimal places
int           dps = -1;        // number of decimal places seen
int           p = 0;            // pointer to current location in the buffer

// assemble the value
while (...p is still within the buffer...)
{
   if (buf[p] >= '0' && buf[p] <= '9')
   {
       value = value * 10 + buf[p] - '0';
       if (dps >= 0)
           ++dps;
       if (dps > 2)
           error();
   }
   else if (buf[p] == '.')
   {
       if (dps >= 0)
           error();
       dps = 0;
   }
   else
   {
           error();
   }
   ++p;
}

// handle numbers without a '.'
if (dps < 0)
   dps = 0;

// scale it to two decimals
while  (dps < 2)
{
   value *= 10;
   dps += 1;
}


Good luck,

Bob Ammerman

2005\11\30@091716 by Bob Ammerman

picon face

----- Original Message -----
From: "Olin Lathrop" <.....olin_piclistKILLspamspam.....embedinc.com>
To: "Microcontroller discussion list - Public." <EraseMEpiclistspam_OUTspamTakeThisOuTmit.edu>
Sent: Wednesday, November 30, 2005 8:30 AM
Subject: Re: [PIC] Convert ASCII string to variable for comparison


> Jinx wrote:
>> What I really want to do is make a universal system so that any
>> ASCII string can be compared to any sensor voltage, so that the
>> user receives not only the alert but also a message in appropriate
>> terms and units
>
> Since you're dealing with verbose ASCII strings over a serial port, I'll
> assume that compute cycles aren't critical.  If so, this sounds like a
> natural application for floating point.

I strongly disagree here. A 32-bit or even 24-bit integer should be more
than enough precision to store a value scaled to two decimal places since
9999 (the maximum value) would be stored as 999900.

Bob Ammerman


2005\11\30@091724 by Bob Ammerman

picon face
From: "Olin Lathrop" <olin_piclistspamspam_OUTembedinc.com>

> Jinx wrote:
>> I would like to cater for any format of i/p the user chooses, so
>> the only significant character is the "." (or lack thereof, implying
>> an integer). ie 0022, 022, 22, 22.0, 22.00 must all be interpreted
>> by the PIC as plain 22. I realise that the more latitude I give the
>> user, the more comprehensive the interpreter needs to be, but I'm
>> prepared to go the extra mile for the sake of user-friendliness
>
> This is really not hard if you break it into two algorithms, one before
> the
> point and one after.  Before the point initialize the value to 0.  For
> each
> digit, multiply the current value by 10, then add the digit.  After the
> point init a scale factor to .1.  For each digit, multiply the digit value
> by the scale factor, add that into the accumulated value, then multiply
> the
> scale factor by .1.

As shown by my previous post, this is really not necessary. You can just
scan the value from left to right, pretending it is an integer, but
remembering where the decimal point is. When you are done you simply
multiply by 10 as many times as needed to scale the final result to two
decimal places.

Bob Ammerman

2005\11\30@094116 by olin piclist

face picon face
Bob Ammerman wrote:
> As shown by my previous post, this is really not necessary. You can just
> scan the value from left to right, pretending it is an integer, but
> remembering where the decimal point is. When you are done you simply
> multiply by 10 as many times as needed to scale the final result to two
> decimal places.

That only works if the number of digits that could be sent it finite.  For
example sending 20.000000001 could cause the most significant part to be
shifted off the end, at least without checking.  I suppose you could look at
the high 4 bits of the 32 bit (or whatever) integer you are accumulating the
value into, and ignore new digits once that nibble gets too big.  When all
done, convert to floating point and multiply by the appropriate power of 10
to take the decimal point position into account.


******************************************************************
Embed Inc, Littleton Massachusetts, (978) 742-9014.  #1 PIC
consultant in 2004 program year.  http://www.embedinc.com/products

2005\11\30@094857 by William Chops Westfield

face picon face
On Nov 30, 2005, at 1:26 AM, Jinx wrote:

> What I really want to do is make a universal system so that any
> ASCII string can be compared to any sensor voltage, so that the
> user receives not only the alert but also a message in appropriate
> terms and units

It looks to me like everyone is focusing on the decimal input
(which ought to be relatively standard) rather than the automatic
scaling (which presumably has to happen at assembly time rather
than runtime; I don't think there's any way you can derive a
scale factor from a single input number...)

Essentially you need to input two points that define an
equation that gives you input values for A-D values.  For your
battery example you might have (0,0) and (12, 1023) and for the
temperature example you have (0,0) and (40, 1023) (or something
like that, if your A-D is 10 bits.)  ; the fact that the sensors
output 12V and there's HW scaling to 5V is an irrelevant red herring;
all you really care about is limits and A-D results.

So you'd want macros something  like:

compute_inputscale macro (admin, inmin, admax, inmax, inscale, outscale)
;; store inscale and outscale based on computations with values.

inputnumber macro (inscale)
;; input a number and convert to A-D value based on inscale computed
;;   earlier by compute_inscale

outputnumber macro (outscale)

inscale doesn't have to be a number that you do math with; it can be
code generated by the macro, which could give you multiple precision
capability.  For efficiency, it can be multiple pieces of code that
are called depending on the number of decimal places in the input.

Am I making any sense, or is it too early in the morning?

BillW

2005\11\30@105202 by Mike Hord

picon face
> A PIC is connected to several analogue sensors. These sensors
> have FSDs of 5V or 12V scaled down to 5V. A user inputs an
> ASCII string so that the PIC will alert them when the sensor
> meets the requirements of the string

What's your user entry method like?  12-key pad?  PC keyboard?
IIRC, in a later message you say "no PC involved"...

If it's a stand alone device, and your user punches in on a keypad,
why not remove the decimal?  Last night I deposited a $30.00
check in an ATM.  I punched in "3", the machine displayed
"$0.03", then I followed with three zeroes, which offset the "3" to
the proper value.  The machine just slid numbers to the left as I
put in new digits.  It displayed the decimal point, but I didn't put
it in, and for all I know, the machine ignored it in all of its math.

Of course, this only works if you control the entry of the ASCII
data.

I was also thinking that it might help if you can "re-scale" the
inputs, such that a 4.092V reference could be used.  That'd
make it a little easier to compare voltages in assembly, by
going from ASCII->BCD->binary.  ASCII->BCD is easy, just
a matter of the proper offset value, and BCD->binary (and
back) has well-established methodologies.  I suppose you
could also try running your PIC at 5.120V, and then not
need to rescale the inputs.

I may be missing the problem all together, but I've already
had a long day.

Mike H.

2005\11\30@153239 by Jinx

face picon face
> It looks to me like everyone is focusing on the decimal input
> (which ought to be relatively standard) rather than the automatic
> scaling (which presumably has to happen at assembly time rather
> than runtime; I don't think there's any way you can derive a
> scale factor from a single input number...)

When the user initially sets it up, the name, FSD, range and units of
each sensor is entered and stored in EEPROM. This is what is used
later for the comparison (and to check against for out-of-range
command numbers etc)

2005\11\30@160928 by Jinx

face picon face
> Here you go. Sorry for the pseudo-"C", but you can covert
> the algorithm easily to ASM:
> .........
> Good luck,

Bob, thanks. "luck" = "quite some time in a quiet room"

Olin, I'll be looking at your system in the New Year. This is the
last major project for the year and coding will be substantially
done by Xmas, so I'll finish it off as I started. The maths routines
I have already should suffice. As you said, 10-bit A2D, in this
application anyway, does not require extreme precision. Most
users will not be expecting 3 decimal place accuracy from a
general purpose sensor, eg if the system reacts at 12.01V instead
of 12V, BFD

2005\11\30@160936 by Jinx

face picon face
> As shown by my previous post, this is really not necessary. You
> can just scan the value from left to right, pretending it is an integer,
> but remembering where the decimal point is. When you are done
> you simply multiply by 10 as many times as needed to scale the
> final result to two decimal places

After I made a correction to a post

"My mistake -

1023 * ( 13.5 / 15 )"

I realised that some of what I was looking for is right there. Using
your method above, the 13.5 is converted to 13500 so it can be
compared to 15000. It looks like some magnitude detection is
going to be necessary, whichever method is used. I see now that
there is no "magic" way (fingers crossed for a table) to do this and
also to cover so many permutations, except for the brute force way
that Olin suggested. This is what I'd been trying up to now, partly
to test the system, partly to see code working in front of me in the
hope of an epiphany

It's helped to see that I wasn't too far off the mark, and I appreciate
everyone's ideas


2005\11\30@183640 by Jinx

face picon face
> Ah, that explains it. I've seen similar SMS-based
> messaging system byt they had quite strickt
> rules to how to write the messages to the "device".
> In that case it was setting/clearing digital I/O lines,
> but the principle was the same. more or less. You
> could also query the status of the input lines. Anyway...

I've looked around at what's available and added the
best features of those (when they actually have a feature
that's even worth considering) to my units, as well as
incorporating a much fuller command set and features that
all the others lack, whether it be in the h/w configuration,
ease-of-use etc.

Additionally this is being done with a patent holder and
mobile service provider, which should keep competing
products at bay


2005\11\30@201138 by Peter

picon face

You can think of your numbers as fixed point. This implies especially
that the precision is limited. So to convert, you can figure in a fixed
multiplier, eg:

xx.yy  = 0XXYY/100 -> you store 0XXYY 2
xxx.yy = XXXYY/100 -> you store XXXYY 2
xx     = 0XX00/100 -> you store 0XX00 0
x.y    = 00XY0/100 -> you store 00XY0 1

thus the decimal point 'disappears' for internal conversion and
comparison purposes (you store 0XXYY), but you store is away and use it
later for display. You have to store the requested precision (number of
digits after . entered) along with the encoded request. Then when you
display a number you do:

0XXYY 1 -> zXX.Y

z is a suppressed leading zero, XX are the integer part, you print a dot
iff the original string had a dot, and as many Y's as Y's were in the
original string after the dot (and suppress the others).

To store and compare data easily in internal form you can use the binary
form of XXXYY. Multiplying binary values by d'100' is easy (as long as
you do not ever need to divide). If you have enough storage you can use
the decimal form (f.ex. unpacked BCD) for arithmetics. This makes for
low cost conversion for display on multiplier-less micros.

I hope that this makes sense. It's 3AM here.

Peter




2005\11\30@201957 by Peter

picon face

On Wed, 30 Nov 2005, Jinx wrote:

>> Have you looked to see if Olins command line whatsit could be
>> modified to do what you want?
>
> No, I haven't
>
>> But I suspect the easiest way if you have to start from scratch
>> may be to get a demo C compiler for this bit
>
> Hmmm, C has always been on the back burner (have HighTech),
> and not sure if I want to face another learning curve just at the
> moment. Good suggestion though, and C is maybe something I
> should have gotten around to earlier, but you know how it is. You
> look up, it's Xmas again and the to-do list isn't any shorter

Just remeber C is a RISC language. It has fewer commands than the
smallest pic (26 vs. 32). There is a reason it is very popular.

Peter

2005\11\30@213333 by Jinx

face picon face
> xx.yy  = 0XXYY/100 -> you store 0XXYY 2
> xxx.yy = XXXYY/100 -> you store XXXYY 2
> xx     = 0XX00/100 -> you store 0XX00 0
> x.y    = 00XY0/100 -> you store 00XY0 1

> I hope that this makes sense. It's 3AM here

It does, and it's 3pm here

That's exactly the sort of thing I'll be doing. Worry about the
DP after the ASCII -> integer conversion. Will be a lot simpler
than how I'd started it, coping with the DP during conversion

I've also belatedly realised that each sensor can be dealt with
using its own range, rather than trying to devise a system that
covers everything from 99999 to 0.001. No individual sensor
actually needs that bit width / precision. In fact 1% would be
close enough most of the time, given the analogue nature of
the sensors, A2D resolution etc

2005\11\30@225553 by Dmitriy Kiryashov

picon face
Hi Peter.

Peter wrote:
>
> You can think of your numbers as fixed point. This implies especially
> that the precision is limited. So to convert, you can figure in a fixed
> multiplier, eg:
>
> xx.yy  = 0XXYY/100 -> you store 0XXYY 2
> xxx.yy = XXXYY/100 -> you store XXXYY 2
> xx     = 0XX00/100 -> you store 0XX00 0
> x.y    = 00XY0/100 -> you store 00XY0 1

Isn't that supposed to be ( last two )

xx     = 000XX/100 -> you store 000XX 0
x.y    = 000XY/100 -> you store 000XY 1

Or in your terms

xx     = 0XX00/100 -> you store 0XX00 2
x.y    = 00XY0/100 -> you store 00XY0 2


Dmitriy.



{Quote hidden}

2005\11\30@231002 by Bill & Pookie

picon face
Maybe your going the wrong way.  You could convert the a/d reading to a
ASCII string and then compare with the user's string.

One way would be to have 6 bytes to calculate the a/d value (work bytes).
The high order work byte will contain the 100's digit from the a/d.  Second
byte 10's, third byte units.  The forth byte tenth's, fifth hundredths and
sixth byte thousand's.  You will not compare  the thousand's digit but it
will keep from having too great of round off errors.

Then test each bit in a/d reading.  If bit set, add the 6 decimal values to
the 6 work bytes.  They will accumulate a value for each digit.  This value
will not overflow into higher order byte as you will be adding at most the
value of 9 each time and you will be doing it at most 10 times.  So maximum
value is 90 or less.

After checking each of the 10 or 8 bits of the a/d and adding the  correct
values to each byte of the work bytes, go through each testing for greater
than 9.  If it is, subtract 10 from it, increment the next higher byte and
test the same byte again.  When done all six bytes, just ignore the sixth or
thousand's byte, it's served it's purpose and set a couple of bits to
convert each byte to ASCII digit.  Or convert the user ASCII character
string to 5 decimal bytes for comparison.

You will need to calculate the conversions for each a/d bit to use in the
pic program, but a pc program or spread sheet could do this.  If you wanted
to get fancy, write a pc program to write that part of the code for you.

Bill

{Original Message removed}


'[PIC] Convert ASCII string to variable for compari'
2005\12\01@043519 by Alan B. Pearce
face picon face
>Just remeber C is a RISC language. It has fewer commands
>than the smallest pic (26 vs. 32). There is a reason it
>is very popular.

My response would be "so what" - but I am not setting out to put you down
here.

My reason for suggesting doing the parsing of the incoming ASCII in C is
that it is probably easier to write such a parser in an HLL than in
assembler, because of the language constructs available - e.g. the pseudo C
code someone else gave in this same thread.

2005\12\01@125420 by Peter
picon face

On Wed, 30 Nov 2005, Dmitriy Kiryashov wrote:

>> xx.yy  = 0XXYY/100 -> you store 0XXYY 2
>> xxx.yy = XXXYY/100 -> you store XXXYY 2
>> xx     = 0XX00/100 -> you store 0XX00 0
>> x.y    = 00XY0/100 -> you store 00XY0 1
>
> Isn't that supposed to be ( last two )
>
> xx     = 000XX/100 -> you store 000XX 0
> x.y    = 000XY/100 -> you store 000XY 1

No, the second number stores the number of significant fractional digits
for conversion and comparison, it is not an exponent of a normalized
mantissa. I meant to write it the way I wrote it.

Jinx said that he needs to cover numbers to 10^5. I do not address this
here but one could store another number for exponent *without* implying
switching to fp.

Peter

2005\12\01@142438 by Dmitriy Kiryashov

picon face
Hi Peter.

Ok. But format is kind of strange.
Not sort of right align it and point where the point is located
from the right edge but rather assume that two rightmost positions
are always occupied by fractional part and second number displays
how may digits are actually used starting from the left edge
of that reservation. Fixed placement I would say. :)
( still good since separate byte is used for fractions )

WBR Dmitriy.



Peter wrote:
{Quote hidden}

> -

2005\12\02@052224 by Howard Winter

face
flavicon
picon face
Mike,

On Wed, 30 Nov 2005 09:52:01 -0600, Mike Hord wrote:

>...
> If it's a stand alone device, and your user punches in on a keypad,
> why not remove the decimal?  Last night I deposited a $30.00
> check in an ATM.  I punched in "3", the machine displayed
> "$0.03", then I followed with three zeroes, which offset the "3" to
> the proper value.

Oooh, User-Unfriendly!  On one occasion when I was in a hurry paying-in a cheque at an ATM I typed in 5 0 <enter> which of course is £0.50, when I meant £50.  I had to cancel the transaction and start again because I noticed it on the screen, but I bet they get a few every day where the typed amount is 1/100th of the amount on the cheque because the punter didn't notice.  For paying in you need the above precision, but I've found some ATMs which expect the whole pounds/pence thing on paying out cash (other than a pre-displayed amount), when the smallest denomination they have is £10 notes, and that's just daft.

As Jinx has said that the interface is from SMS, there's no feedback to the user on what they have typed, so you have to be very lenient interpreting what they type because their entry is "open loop".

Cheers,


Howard Winter
St.Albans, England

2005\12\04@073951 by Jinx

face picon face
I've come up with this. Perhaps not as elegant as it could be
but it's working (and best of all, it's out of my head \O/ yay
and something to build on). Appears so far to convert any
ASCII number between 0.000 and 65.535, which is fine for
this application as all sensor i/ps are reduced to 5000mV for
the ADC anyway. The result is in a form that can be compared
to the sensor's FSD, as stored in EEPROM, and used to set a
trigger point. In the example below, perhaps a battery tester,
FSD is set at 15,000. So the ADC value to look for is (13400/
15000) * 1024. 1024 keeps the maths simple

============================

;ASCII string example, E13.4 <parameter> <parameter>^, stored at 0x20+
;find/record position of any DP
;store stripped copy of digits at 0x30+
;get number of digit chars before DP, compare with allowable number
;start multiplication at FSR-offset
;value of digits in cmph:l
;(divide by sensor FSD) *1024 -> ADC threshold

;b4dp1   number of digits allowed left of DP
;ab4dp1  number of digits found left of DP
;dpf     flags,1 -> set if DP found in string

movff    macro   file1,file2  ;note !!! destroys W !!!
        movfw   file1
        movwf   file2
        endm

eval     clrf    temp0        ;clear work area
        clrf    temp1
        clrf    temp2
        clrf    temp3
        clrf    temp4
        clrf    cmpl         ;result, 0 - 65535mV
        clrf    cmph
        bcf     dpf          ;DP found flag
        movlw   temp4        ;work arrary FSR
        movwf   temp5
        movff   fsr,temp7    ;save for swap

;at this point FSR = 0x30, INDF = "E"

        incf    temp7        ;inc FSR past letter to 1st digit
        movlw   temp0
        movwf   temp6        ;temp6 = address of temp0 array
        movff   temp7,fsr    ;temp7 = start of digit characters
        clrf    out          ;position of any DP in string
get_chr  movfw   indf         ;get digit
        xorlw   " "          ;test for space (end of part)
        bz      testb4
        xorlw   " " ^ "."    ;test for DP
        bnz     tst_eos
        movff   out,ab4dp1   ;actual number of chars before DP
        bsf     dpf          ;DP found
        incf    temp7
        goto    bump         ;do not copy "."
tst_eos  xorlw   " " ^ "^"    ;test for end-of-string terminator
        bz      testb4
        movfw   indf
        andlw   0x0f         ;strip ASCII
        movwf   temp8        ;hold
        movff   fsr,temp7    ;swap
        movff   temp6,fsr
        movff   temp8,indf   ;store stripped data at temp0+
        incf    temp6
bump     movff   temp7,fsr
        incf    out
        incf    fsr
        goto    get_chr

testb4   btfsc   dpf          ;was actual DP found ?
        goto    dp_diff      ;yes
        movff   out,ab4dp1   ;no, use number of digit characters
dp_diff  movfw   ab4dp1       ;compare # chars before DP with allowable
        subwf   b4dp1,w
        movwf   temp8        ;difference
        bc      x1           ;OK

        goto    n_error      ;number error (ASCII > than FSD)

x1       movlw   temp4        ;adjust FSR with difference
        movwf   fsr
        movfw   temp8
        subwf   fsr

        movfw   indf
        bz      x10          ;move on if 0
        clrc
        movff   indf,cmpl    ;add digit x 1

x10      decf    fsr          ;work from LSchar to MSchar
        movfw   indf
        bz      x100
add10    clrc
        movlw   .10          ;add digit x 10
        addwf   cmpl
        decfsz  indf         ;loop until 0
        goto    add10

x100     decf    fsr
        movfw   indf
        bz      x103
add100   clrc
        movlw   .100         ;add digit x 100
        addwf   cmpl
        skpnc
        incf    cmph
        decfsz  indf
        goto    add100

x103     decf    fsr
        movfw   indf
        bz      x104
add103   clrc
        movlw   0xe8         ;add digit x 1,000
        addwf   cmpl
        skpnc
        incf    cmph
        clrc
        movlw   0x03
        addwf   cmph
        decfsz  indf
        goto    add103

x104     decf    fsr
        movfw   indf
        bz      done
add104   clrc
        movlw   0x10         ;add digit x 10,000
        addwf   cmpl
        skpnc
        incf    cmph
        clrc
        movlw   0x27
        addwf   cmph
        decfsz  indf
        goto    add104

done     goto    done         ;(example) cmph:l = 13,400

;then divide by FSD and * 1024

n_error  goto    n_error

2005\12\04@091225 by olin piclist

face picon face
Jinx wrote:
> ;ASCII string example, E13.4 <parameter> <parameter>^, stored at 0x20+
> ...
> ;store stripped copy of digits at 0x30+

Really now!  You should know better than to use literal constants for the
addresses of variables.  You did it right and used symbols in the code, so
it's doubly strange that you used fixed constants in the comments,
especially since the mapping of these constants to the symbols is not
available in this code fragment.

> movff    macro   file1, file2 ;note !!! destroys W !!!

And requires both FILE1 and FILE2 to be accessible with the current bank
setting.

{Quote hidden}

With all these TEMP0 - TEMPn variables, there should be a block comment
explaining their usage.  Some of these are apparently used for more than
just a buffer since you loaded the address of TEMP4 into TEMP5, although we
have no idea why.

>          movff   fsr, temp7  ;save for swap

This is a bug since FSR is uninitialized.  It's either a bug in the code
here or a bug in the comments that forget to mention that the state of FSR
is important on entry to this routine.

> ;at this point FSR = 0x30, INDF = "E"

Oh?  I don't see how 30h got into FSR, nor what the significance of 30h is.
I also have no clue what is meant by INDF = "E".  Apparently ASCII "E" is
stored at 30h since that's where FSR is supposedly pointing, but what the
%$&*@# is the significance of that?

>          incf    temp7       ;inc FSR past letter to 1st digit

Um, your incrementing TEMP7 not FSR.

I was curious how your algorithm works, but this is too painful.  I'm giving
up here.


******************************************************************
Embed Inc, Littleton Massachusetts, (978) 742-9014.  #1 PIC
consultant in 2004 program year.  http://www.embedinc.com/products

2005\12\04@234444 by Jinx

face picon face
Olin, hopefully this will answer your questions

> > ;ASCII string example, E13.4 <parameter> <parameter>^, stored at 0x20+
> > ...
> > ;store stripped copy of digits at 0x30+

> Really now!  You should know better than to use literal constants
> for the addresses of variables

That's just where I put them, so I can see what's going on. The
ASCII to examine is at 20-2f, the work area is at 30-34. The
variables occupying 30-34 are called temp0 to temp4

> > movff    macro   file1, file2 ;note !!! destroys W !!!
>
> And requires both FILE1 and FILE2 to be accessible with the
> current bank setting

As this is a 16F, not an 18F, that has to be assumed, as would
be the case for any file copying

{Quote hidden}

Fair enough. There is a contiguous block of TEMPn variables. Just
think of it as a scratch array

> Some of these are apparently used for more than just a buffer since

That's true. In this part of the program, temp0-temp4 are the
ASCII-less digits (corresponding to the number in the ASCII
string). These variables are also used in other parts of the program
as general purpose variables, so they don't have specific names

> you loaded the address of TEMP4 into TEMP5, although we
> have no idea why

I see now that was unnecessary, as no use is made of temp5. The
intention is for FSR to switch back and forth between the ASCII
and the temp0-temp4 digit store, but usage of temp5 was
superceded by the code following being re-written

> > ;at this point FSR = 0x30, INDF = "E"
>
> Oh?  I don't see how 30h got into FSR, nor what the significance of
> 30h is

Typo - should have been 0x20, the start of the ASCII, which is the
letter "E", sorry about that

> >          incf    temp7       ;inc FSR past letter to 1st digit
>
> Um, your incrementing TEMP7 not FSR.

Yes and no. temp7 and temp6 are used to switch FSR between
the 0x20 ASCII array and the 0x30 digit array

> I was curious how your algorithm works, but this is too painful.  I'm
> giving up here

Let me ease your pain......................and by explaining it to you,
I'll probably see more myself. And of course I need to document
it and make sure it works properly as I'll be using it extensively

This ASCII string is at 0x20

E13.5^

Now, this 13.5 has to be meaningful in the context of what the
sensor FSD is. In this case, a battery monitor, I've said limit
variable = 15000 (for use in magnitude testing later)and assigned
the notional units "mV". So, the text says "alert me when the
battery equals 13500mV". I've also set the variable b4dp1 to 2,
which is the maximum number of digits allowable before the
decimal point. > 2 digits is an error. It is also used to determine
where multiplication starts

Now, what the routine does is to work through the string

eval     clrf    temp0        ;clear work area
        clrf    temp1
        clrf    temp2
        clrf    temp3
        clrf    temp4

; temp0 - temp4 need to be all 0 before work starts

        clrf    cmpl         ;result, 0 - 65535mV
        clrf    cmph
        bcf     dpf          ;DP found flag

dpf is set if an actual 0x2e "." is found. In the case of "13.5" it
will be, in the case of "13" it won't

        movff   fsr,temp7    ;save for swap

;at this point FSR = 0x20, INDF = "E"

        incf    temp7        ;inc FSR past letter to 1st digit

;ie move FSR past "E", onto "1"

        movlw   temp0
        movwf   temp6        ;temp6 = start of temp0 array
        movff   temp7,fsr    ;temp7 = start of ASCII characters

        clrf    out          ;position of any DP in string

;if dpf gets set, the value of out at that time gets copied to ab4dp1
;= "actual number of digits before decimal point". If dpf does not
;get set (no 0x2e "." in the string), then "out" will be the number of
;digits (ie the number is a simple integer)

get_chr  movfw   indf         ;get character
        xorlw   " "          ;test for end of part
        bz      testb4

;parameters are separated by a space, string is terminated by
;a caret ^. Finding either will end the rroutine

        xorlw   " " ^ "."    ;test for DP
        bnz     tst_eos      ;not DP, test for terminator

;xorlw " " ^ "." restores W after previous xorlw " " and xors with "."

;DP found, record number of characters before it (ie how many
;times routine has looped up until now)

        movff   out,ab4dp1   ;actual number of chars before DP
        bsf     dpf          ;record that DP found
        incf    temp7        ;increment the FSR swap register
        goto    bump         ;do not copy "." to number store

tst_eos  xorlw   " " ^ "^"    ;test for end-of-string terminator
        bz      testb4       ;found, exit

        movfw   indf         ;reload character into W, test for non-number
        addlw   .255-"9"
        addlw   ("9"-"0")+1
        skpc                 ;is ASCII number, carry on
        goto    n_error      ;is not, number error

        movfw   indf         ;get character from ASCII text
        andlw   0x0f         ;strip ASCII
        movwf   temp8        ;hold
        movff   fsr,temp7    ;swap FSR to point at temp0 digit store
        movff   temp6,fsr
        movff   temp8,indf   ;store stripped data
        incf    temp6

bump     movff   temp7,fsr    ;swap FSR to point at ASCII
        incf    out          ;character counter
        incf    fsr          ;ASCII array pointer
        goto    get_chr      ;loop until " " or "^" found

After this loop has completed, what will be seen at 0x30 (the digit
store) onward is 01 03 05 00 00

dpf is set, because a DP was found
ab4dp1 = 2, (the "1" and the "3" are before the DP)

testb4   btfsc   dpf          ;was actual DP found ?
        goto    dp_diff      ;yes
        movff   out,ab4dp1   ;no, use number of digit characters

dp_diff  movfw   ab4dp1       ;compare # of chars before DP with allowable
        subwf   b4dp1,w
        movwf   temp8        ;difference
        bc      x1           ;OK, number is = or < allowable

        goto    n_error      ;number error
;if text had been "135" this would obviously be more than 2 digits

;temp4 is the LSdigit of the digit array (address 0x34)
;Where you start multiplying depends on how many digits
;are before the DP

; 01 03 05 00 00

x1       movlw   temp4        ;adjust FSR with difference
        movwf   fsr
        movfw   temp8
        subwf   fsr

;difference is 0 (two digits pre-DP allowable, two found)
;so FSR points at temp4
;Multiply, starting at temp4

        movfw   indf
        bz      x10          ;exit if 0
        clrc
        movff   indf,cmpl    ;add digit x 1

x10      decf    fsr          ;work from LSchar to MSchar
        movfw   indf
        bz      x100         ;exit if 0

etc

result is 13500 (00 00 in array are coincidence) or

(0 x 1) + (0 x 10) + (5 x 100) + (3 x 1000) + (1 x 10000)

Following this, do the calculation

(13500 * 1024) / 15000 = 921.6, the 10-bit ADC value to test
for. It would have been 920.7 if 1023, but adding a 00 byte and
a couple of shifts is quick and easy, and the error is insignificant
in this application

If the string had been 1.35, then the difference would have been
1 (two allowable - one found), and so the multiplication would
have started at temp3 (FSR = temp4-1), giving a result of 1350

In my previous post I said that the conversion covers 0.000 to
65.536. It is actually limited to 65.53 -> result of 65530 because
the ASCII is limited to 5 characters and if one of those is a DP
then that leaves 4 as digits

Say if you had a temperature sensor with a range of 0 - 200deg,
(presented to the PIC as 0-5000mV)

limit = 20000
b4dp1 = 3 (number of digits allowed before DP is 3)

Text might be E125^ (tell me when temperature = 125 degrees)

After running the routine, result is 12500. ADC value is
(12500 * 1024) / 20000 = 640

You have to set the two constants "limit" and "b4dp1" to suit
each input. It's not just figures, you have to consider the context
too

2005\12\05@075217 by Bill & Pookie

picon face
part 1 12698 bytes content-type:text/plain; (decoded 7bit)

I have written and used a basic program on the pc to make asm data
statements for another processor.  Was easier then copying a bunch of
numbers into data statements.  Have done something similar for your example
of a full scale a/d reading of 200.

The program outputs a file containing the important parts of code to convert
reading to six decimal digits.  Three digits to left of decimal point and
three to right of decimal point.  Each bit of a/d is tested and if set then
the code for that bit is executed.  Afterwards each byte (low order byte
first) is tested for less than 10.  If 10 or greater then 10 is subtracted
from it and the next higher order digit (byte) is incremented.  This is done
to each byte until it is less than 10.  Then the ASCII digits could be
compared with the a/d values.

The qbasic program can output conversion for most values by changing one
variable 'ref' from 200 to the wanted value.  The qbasic program could be
modified to convert one hex a/d value to another hex value.  As in
converting the example from the a/d  Celsius  reading to the hex value for
Fahrenheit.

Also the concept of having a pc program generate asm data code for a
nonlinear function  is useful.

Bill

Included the output file with code as it seems the mail program lost the
tabs.

******* code generated by program follows *********

;  for bit 9   100

movlw D'1'
addwf CVD0,F


;  for bit 8   50

movlw D'5'
addwf CVD1,F


;  for bit 7   25

movlw D'2'
addwf CVD1,F
movlw D'5'
addwf CVD2,F


;  for bit 6   12.5

movlw D'1'
addwf CVD1,F
movlw D'2'
addwf CVD2,F
movlw D'5'
addwf CVD3,F


;  for bit 5   6.25

movlw D'6'
addwf CVD2,F
movlw D'2'
addwf CVD3,F
movlw D'5'
addwf CVD4,F


;  for bit 4   3.125

movlw D'3'
addwf CVD2,F
movlw D'1'
addwf CVD3,F
movlw D'2'
addwf CVD4,F
movlw D'5'
addwf CVD5,F


;  for bit 3   1.5625

movlw D'1'
addwf CVD2,F
movlw D'5'
addwf CVD3,F
movlw D'6'
addwf CVD4,F
movlw D'3'
addwf CVD5,F


;  for bit 2   .78125

movlw D'7'
addwf CVD3,F
movlw D'8'
addwf CVD4,F
movlw D'1'
addwf CVD5,F


;  for bit 1   .390625

movlw D'3'
addwf CVD3,F
movlw D'9'
addwf CVD4,F
movlw D'1'
addwf CVD5,F


;  for bit 0   .1953125

movlw D'1'
addwf CVD3,F
movlw D'9'
addwf CVD4,F
movlw D'5'
addwf CVD5,F


; max value a/d is   199.805

********  end of code  **********
'.

{Original Message removed}
part 2 1633 bytes content-type:text/plain;
(decoded quoted-printable)

 REM     a/d values
 CLS

 tab$ = CHR$(9)
 movlw$ = tab$ + "movlw" + tab$ + "D'"
 addwf$ = tab$ + "addwf" + tab$ + "CVD"

 OPEN "a2dcode.txt" FOR OUTPUT AS #1

 max = (2 ^ 10): REM full scale for 10 bits
          ref = 200: REM the reference voltage for full count

 REM  calculate each bit value in decimal
 REM  3 to left of decimal point and three to right

 FOR bit = 9 TO 0 STEP -1
       qx = (ref / max) * 2 ^ bit: REM full scale for a/d reference voltage
   qx = qx + .00051: REM round up
   qx = INT(1000 * qx) + 1000000: REM round off and make sure 7 charaters long
   a$ = STR$(qx): REM in " 1dddddd" format, just use the 6 d's
    PRINT ";  for bit"; STR$(bit), (ref / max) * 2 ^ bit
   PRINT

   PRINT #1, ""
   PRINT #1, ";  for bit"; STR$(bit), (ref / max) * 2 ^ bit
   PRINT #1, ""

   REM  pull each digit for the bit, characters 3 through 8

   FOR digit = 0 TO 5
       vvv = 3 + digit: REM skip first two characters " 1"
       b$ = MID$(a$, vvv, 1)
       IF b$ <> "0" THEN
         PRINT #1, movlw$; b$; "'  "
         PRINT #1, addwf$; RIGHT$(STR$(digit), 1); ",F"
       END IF

   NEXT digit

   PRINT #1, ""

   PRINT qx
   allbits = allbits + (qx - 1000000): REM get value of H'1111111111'

 NEXT bit

 PRINT allbits / 1000, "all bits set"
 PRINT #1, ""
 PRINT #1, ";"; tab$; "max value a/d is  "; allbits / 1000
 CLOSE #1



part 3 1070 bytes content-type:text/plain;
(decoded 7bit)


;  for bit 9   100

       movlw        D'1'  
       addwf        CVD0,F


;  for bit 8   50

       movlw        D'5'  
       addwf        CVD1,F


;  for bit 7   25

       movlw        D'2'  
       addwf        CVD1,F
       movlw        D'5'  
       addwf        CVD2,F


;  for bit 6   12.5

       movlw        D'1'  
       addwf        CVD1,F
       movlw        D'2'  
       addwf        CVD2,F
       movlw        D'5'  
       addwf        CVD3,F


;  for bit 5   6.25

       movlw        D'6'  
       addwf        CVD2,F
       movlw        D'2'  
       addwf        CVD3,F
       movlw        D'5'  
       addwf        CVD4,F


;  for bit 4   3.125

       movlw        D'3'  
       addwf        CVD2,F
       movlw        D'1'  
       addwf        CVD3,F
       movlw        D'2'  
       addwf        CVD4,F
       movlw        D'5'  
       addwf        CVD5,F


;  for bit 3   1.5625

       movlw        D'1'  
       addwf        CVD2,F
       movlw        D'5'  
       addwf        CVD3,F
       movlw        D'6'  
       addwf        CVD4,F
       movlw        D'3'  
       addwf        CVD5,F


;  for bit 2   .78125

       movlw        D'7'  
       addwf        CVD3,F
       movlw        D'8'  
       addwf        CVD4,F
       movlw        D'1'  
       addwf        CVD5,F


;  for bit 1   .390625

       movlw        D'3'  
       addwf        CVD3,F
       movlw        D'9'  
       addwf        CVD4,F
       movlw        D'1'  
       addwf        CVD5,F


;  for bit 0   .1953125

       movlw        D'1'  
       addwf        CVD3,F
       movlw        D'9'  
       addwf        CVD4,F
       movlw        D'5'  
       addwf        CVD5,F


;        max value a/d is   199.805


part 4 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2005\12\06@072829 by Jinx

face picon face
> As Jinx has said that the interface is from SMS, there's no
> feedback to the user on what they have typed, so you have
> to be very lenient interpreting what they type because their
> entry is "open loop"

That's true. Lenient with legal entries (some SMS controllers I've
looked at have ghastly long strings you need to enter verbatim-
wherever possible my system will allow short-hand entries) and
providing good error messages if they get it wrong. eg echoing
the text back to them with an explanation. The ASCII-variable
routine seems to be working very well so far. I can TXT the
PIC with any number (plus other parameters) in any sensor's
range and it handles them all perfectly, calculating the correct
ADC value and action to take. The idiot-proofing is also doing
its job well, catching out-of-range numbers, illegal characters,
malformed strings etc. Nothing worse for a user than "hmmm,
now why didn't *that* work ?"

2005\12\06@203159 by James Newton, Host

face picon face
This looks neat, but I'm not really sure I understand it.

> The program outputs a file containing the important parts of
> code to convert reading to six decimal digits.  Three digits
> to left of decimal point and three to right of decimal point.
>  Each bit of a/d is tested and if set then the code for that
> bit is executed.  

So there are a series of bit test and jmps somewhere that call the code in
the generated listing? Don't there need to be labels? E.g. bit9:

> Afterwards each byte (low order byte
> first) is tested for less than 10.  If 10 or greater then 10
> is subtracted from it and the next higher order digit (byte)
> is incremented.  This is done to each byte until it is less
> than 10.  Then the ASCII digits could be compared with the a/d values.

Could you post a sample of that code?

> The qbasic program can output conversion for most values by
> changing one variable 'ref' from 200 to the wanted value.  
> The qbasic program could be modified to convert one hex a/d
> value to another hex value.  As in converting the example
> from the a/d  Celsius  reading to the hex value for Fahrenheit.
>
> Also the concept of having a pc program generate asm data
> code for a nonlinear function  is useful.

Code generators are my favorite thing in the world.
http://www.massmind.org

---
James Newton: PICList webmaster/Admin
@spam@jamesnewtonKILLspamspampiclist.com  1-619-652-0593 phone
http://www.piclist.com/member/JMN-EFP-786
PIC/PICList FAQ: http://www.piclist.com



{Quote hidden}

2005\12\07@043415 by Bill Cornutt

picon face
Yes, the code is not complete.  There is a series of instructions to be run
if the bit is set in the a/d reading. and these instructions are the ones
the program outputted.  This removes the tedium and error proness of doing
each calculation and writing the code by hand.

It is early and no coffee yet,  This post is short.

Bill

;      for bit 9   100
test9  bftss     adhigh;1    ***** inserted by jand
         goto    test8            *****

       movlw D'1'
      addwf CVD0,F

        for bit 8   50

test8  bftss     adhigh;0  ****
         goto    test7         *****

Bill

{Original Message removed}

2005\12\07@131547 by James Newton, Host

face picon face
{Quote hidden}

Ahh... Excellent, thank you. So in your BASIC program, something like the
following could be added after the PRINT "; for bit" line...

   if bit>8 then ad="adhigh;" & cstr(bit-8) else ad="adlow;" & cstr(bit)
   PRINT "test" & CSTR(bit) &"  bftss" & vbTab & ad
   PRINT vbTab & "goto    test" & cstr(bit-1)

Now, there is also some "fix up" code at the end that corrects for registers
that may have accumulated more than 10? May I impose on you to also share
that code?

---
James Newton: PICList webmaster/Admin
KILLspamjamesnewtonKILLspamspampiclist.com  1-619-652-0593 phone
http://www.piclist.com/member/JMN-EFP-786
PIC/PICList FAQ: http://www.piclist.com


2005\12\08@010238 by Bill & Pookie

picon face
Yes.  With exception that should test for greater than bit 7 and still print
"cstr(bit-8)"  in

>   if bit>8 then ad="adhigh;" & cstr(bit-8) else ad="adlow;" & cstr(bit)

I am working on this program to add the "rest of the stuff" and to have it
convert to hex nibbles (hex digits?)..  This feature could be used for
scaling up or down a hex value.  A divide with a fixed "divided by".

And started working on a pc basic program to generate a lookup table for
converting a/d readings to decibels.

Bill


{Original Message removed}

2005\12\08@124822 by James Newton, Host

face picon face
{Quote hidden}

Ah yes. Bit>7 does work better.

> I am working on this program to add the "rest of the stuff"
> and to have it convert to hex nibbles (hex digits?)..  This
> feature could be used for scaling up or down a hex value.  A
> divide with a fixed "divided by".

Excellent! Feel free to share pre-release versions as I will be interested
in debugging and suggesting things.

> And started working on a pc basic program to generate a
> lookup table for converting a/d readings to decibels.

Cool! I love this sort of thing...

---
James Newton: PICList webmaster/Admin
RemoveMEjamesnewtonTakeThisOuTspampiclist.com  1-619-652-0593 phone
http://www.piclist.com/member/JMN-EFP-786
PIC/PICList FAQ: http://www.piclist.com



More... (looser matching)
- Last day of these posts
- In 2005 , 2006 only
- Today
- New search...