## how to perform calculations with an atmega?

21 posts / 0 new
Author
Message

hi,

right now i can receive and show a voltage on a lcd.

but i have to do some calculations with the input before showing them on the lcd now.

attached is a curve

x-axis is the input and the y-axis represents the data i want to show on the lcd

i added a line of best fit and the formula for that line is to the power of 4

"y = 0.00000000001661249863*pow(x,4)- 0.00000012009735767385*pow(x,3)+ 0.00033807921726585*pow(x,2)- 0.482076867931636*x+339.419792445089; "

now i am using the formula to calculate my output for the lcd.

-is it to complex for an atmega (324pa or others) to do the calculation? the result is getting inaccurate when x is getting higher!

-should i do linear approximation between my the points to get y?

or is there any other way how to solve this with an atmega?

-sl00k

## Attachment(s):

Wow, 2.5 Gigavolts! That's impressive. And/or measured with a 32-bit ADC.

Perhaps you ought to tell us...

1) What your input range really is.

2) What you output range is.

3) What precision you require.

4) What accuracy you require.

5) How long your calculation can take.

"This forum helps those that help themselves."

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Last Edited: Thu. Sep 21, 2017 - 04:06 PM

sl00k wrote:
-is it to complex for an atmega (324pa or others) to do the calculation? the result is getting inaccurate when x is getting higher!

An AVR8 is...an 8-bit processor.

That said, many/most calculators, historically, are based on 4-bit and 8-bit microprocessors.

You haven't said which language and toolchain you are using.  Some/many AVR8 toochains only have "single", not "double" float precision.

You haven't said what accuracy you need/desire.  For general microcontroller work, the blue circles on the graph don't look that bad.

Apparently, you have about half a dozen data points.  When you run them through your calculations in the spreadsheet, what is the real difference, say in percent error?  What is the source of the input reading?  If e.g. AVR8 10-bit ADC result, best-case is only 0.1%.  Typical depends on your skill in designing the analog subsystem.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Sep 21, 2017 - 04:28 PM

theusch wrote:
Typical depends on your skill in designing the analog subsystem.

and to get anywhere near that theoretical 0.1% best case would require quite a lot of skill ...

Unless I've made a mistake the OP is going to need to be using a maths package with 36 bits of precision.

"This forum helps those that help themselves."

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Brian Fairchild wrote:

Unless I've made a mistake the OP is going to need to be using a maths package with 36 bits of precision.

Scrub that. That's 36 bits after the decimal point.

"This forum helps those that help themselves."

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Brian Fairchild wrote:
Wow, 2.5 Gigavolts!

Or just in/with a locale where a comma is use as the decimal mark.. Among others, that would be more or less all of continental Europe (including the Nordic Countries).

Blue: point, Light/Bright Green: comma, Red: other, Grey: Data unavailable. Canada is "mixed": point when using the English language, comma when using the French.

Or, if you like...

Brian Fairchild wrote:
Wow, 2.5 Gigavolts!

Hey, your thousands marker is not making any sense there! ;-)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Sep 21, 2017 - 04:42 PM

the code is written in c and i use the native toolchain from atmel studio 7

the input is from a Distance Measuring Sensor Unit which is connected to a 12bit adc, connected over i2c to the atmega

the x-axis is in mV

input range is from x = 2640mV to 590mV

output range is from y= 20cm to 150cm

5% precision is already good enough for now (whats the difference to accuracy?)

the calculation can take up to 500ms

sl00k wrote:
5% precision is already good enough for now (whats the difference to accuracy?)
theusch wrote:
Apparently, you have about half a dozen data points. When you run them through your calculations in the spreadsheet, what is the real difference, say in percent error?

At a quick glance, Id say you are already almost done.

I'm a little rusty, and would need to do some noodling with pencil or spreadsheet.  Perhaps the "problem" terms are the first couple, with the high exponent values.  One could factor out some powers of ten to reduce the enormous dynamic range, and then apply after the multiplication.

E.g. isn't

sl00k wrote:
0.00000000001661249863*pow(x,4)

equivalent to

16.6125 times 10e-12 times (x / 10e-3) to the fourth power times 10e12

[I might have missed a power or two doing it in my head] Then the 10e-12 and 10e+12 turn into 1, right?  Now you have a lot less dynamic range.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

sl00k wrote:

Take your 12-bit value from the ADC, divide it by 16 (shift right 4 bits) to get a 8 bit result and use that as a lookup into a 256 entry table holding 8-bit values in the range 20 to 150. Job done.

"This forum helps those that help themselves."

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

5% precision is already good enough for now

There is nothing wrong with your approach, but it is perhaps better suited to working on a PC rather than an 8-bit micro.

An alternative approach, given the rather few data points, and the 5% range, would be to split the curve up into several segments, and do a simple linear approximation over the smaller, segmental, ranges.

Worst case, make every pair of data points a short segment, giving you 10 - 15 segments or so.

A lookup table holds the linear approx. variables for that segment.

JC

Brian Fairchild wrote:

Take your 12-bit value from the ADC, divide it by 16 (shift right 4 bits) to get a 8 bit result and use that as a lookup into a 256 entry table holding 8-bit values in the range 20 to 150. Job done.

Done this way, if my spreadsheet is correct, the maximum error is -2.5%.

"This forum helps those that help themselves."

"If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Brian Fairchild wrote:
Done this way, if my spreadsheet is correct, the maximum error is -2.5%.

When looking at the chart that OP posted, there are only a couple outliers.  The one higher on the chart has an asterisk, as the X value didn't seem to line up with the other test points.  The only other outlier is already within ~5%.  Thus, I said OP is "done" already.  If I had to guess, the outliers had to do with measurement error and not formula error.  But hey -- we are not allowed to see the raw data.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

i can make more datapoints, thats not a problem.

and more accurate, the ones i have now where done in a rush, just to see if it is possible that way.

thanks for the input. i can test 3 different ways now ... well, after the weekend :/

0.00000012009735767385

Just to note that most AVR C compilers only have 32 bit floats which offer about 7.5 significant decimal digits so a number like that will be interpreted as:

0.0000001200974

or similar.

DocJC wrote:

5% precision is already good enough for now

There is nothing wrong with your approach, but it is perhaps better suited to working on a PC rather than an 8-bit micro.

An alternative approach, given the rather few data points, and the 5% range, would be to split the curve up into several segments, and do a simple linear approximation over the smaller, segmental, ranges.

Worst case, make every pair of data points a short segment, giving you 10 - 15 segments or so.

A lookup table holds the linear approx. variables for that segment.

JC

Used this method with a 32 entry table to get well under 1% precision on a thermocouple application.  Pretty simple.  Wrote a little C program to calculate the table entries from the thermocouple equation.  After you generate the table entries you can then have the same program calculate the maximum error by calculating the error half way between each pair of table entries.

Given OP's output range, 5% accuracy could be done with a 42-entry table.

2% could be done with a 102-entry table.

Use binary search.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

Re-arrange your polynomial to Horner style -> Better conditioning, and no more insanely small constants, and no more pow() needed.

avrfreaks does not support Opera. Profile inactive.

Piecewise linear interpolation is probably the approach I would use... buy hey... I am old school.

Ross McKenzie ValuSoft Melbourne Australia

y = ax^4 + bx^3 + cx^2 + dx + e

y = (((ax + b)x + c)x + d)x + e

and much more computationally efficient.

Letting the smoke out since 1978