Exact match. Not showing close matches.
PICList
Thread
'[PIC] Convert ASCII string to variable for compari'
2005\11\30@042620
by
Jinx
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
|
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_OUTjoecolquittTakeThisOuT
clear.net.nz> wrote:
{Quote hidden}> 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@051831
by
Jinx
> 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
>> 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
> 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
|
Jinx <.....piclistKILLspam
@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 - fastfwd
KILLspamix.netcom.com
2005\11\30@064840
by
Jan-Erik Soderholm
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
> 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
> 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
> 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
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
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
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
>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
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
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
----- Original Message -----
From: "Olin Lathrop" <.....olin_piclistKILLspam
.....embedinc.com>
To: "Microcontroller discussion list - Public." <EraseMEpiclistspam_OUT
TakeThisOuTmit.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
|
From: "Olin Lathrop" <olin_piclist
spam_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
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
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
|
> 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
> 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
> 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
> 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
> 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
|
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
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
> 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
|
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}> 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@231002
by
Bill & Pookie
|
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
>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
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
|
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}>
> 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\02@052224
by
Howard Winter
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
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
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}> 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
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
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}> > 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
>
> With all these TEMP0 - TEMPn variables, there should be a block
> comment explaining their usage
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
|
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
> 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
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@jamesnewtonKILLspam
piclist.com 1-619-652-0593 phone
http://www.piclist.com/member/JMN-EFP-786
PIC/PICList FAQ: http://www.piclist.com
{Quote hidden}> 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 **********
> '.
2005\12\07@043415
by
Bill Cornutt
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
{Quote hidden}> 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
>
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
KILLspamjamesnewtonKILLspam
piclist.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
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
{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?
>
> 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)
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
RemoveMEjamesnewtonTakeThisOuT
piclist.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...