Author Topic: ADC/DAC Conversion to "decimal", best practices....  (Read 14390 times)

0 Members and 1 Guest are viewing this topic.

Offline Brutte

  • Frequent Contributor
  • **
  • Posts: 614
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #25 on: June 09, 2016, 09:39:34 am »
This adc returns 2^12 values. If you want that scaled and the reference does not match then some kind of rounding must be involved. So the most logical choice would be to minimize the rounding error (rounding noise).
That could be made with decimation. So if you sum n consecutive ADC samples and divide the sum by m then the scaling can be easily performed even at fixed point.
Mind in C "y=a/b;" is called "divide with truncation" and it injects 1 bit noise. That noise can be easily cut in half if you "divide with rounding".
The decimation requires some dithering and antialiasing filter (it limits the bandwidth) but it also cuts the variance of ADC noise.
 

Offline Tomorokoshi

  • Super Contributor
  • ***
  • Posts: 1212
  • Country: us
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #26 on: June 10, 2016, 02:40:11 am »
Alternate solution:

Don't make your reference 10.000V; make it 10.2375V.

Then each count is 10.2375V / 4095 = 0.0025V.

Multiply the resulting number of counts by 25 to get the number of millivolts. Alternately divide by 400 to get volts.

This also gives you a little overhead to detect > 10.000 V conditions.
 

Offline bktemp

  • Super Contributor
  • ***
  • Posts: 1616
  • Country: de
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #27 on: June 10, 2016, 04:52:33 am »
Don't make your reference 10.000V; make it 10.2375V.

Then each count is 10.2375V / 4095 = 0.0025V.
Almost all ADCs and DACs can not reach the full positive reference voltage, there is one step missing. So the correct number is 4096, not 4095. Using a 10V reference voltage, the maximum measureable voltage is 4095/4096*10V=9.99756V
You often do not notice that, because the gain/offset error of most ADC/DACs is larger than 1 LSB.
Using 4096 you get a more common reference voltage of 10.24V. Most 10V references with a trimming pin can be adjusted to 10.24V.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #28 on: June 10, 2016, 10:34:48 am »
Quote
Alternate solution:

Don't make your reference 10.000V; make it 10.2375V.

Plenty of references come in at 2's powers: 1.024v, 2.048v, ...., exactly for that reason.
================================
https://dannyelectronics.wordpress.com/
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #29 on: June 11, 2016, 08:26:04 pm »
I benchmarked orin's approach to the typical mod + div approach on a few chips. I was converting a 24-bit type into the highest 8 digits.

PIC16F1936: orin's approach takes 4% of the time to execute vs. 100% for the mod + div approach
CM0: orin's approach takes 7% to execute
CM3: orin's approach takes 46% to execute
LM4F120: orin's approach takes 83% to execute.

So it seems that on a bigger chip, the advantage is smaller; on the smaller chips, it can take a lot of time.

Very impressive, indeed.
================================
https://dannyelectronics.wordpress.com/
 
The following users thanked this post: orin

Online voltsandjolts

  • Supporter
  • ****
  • Posts: 2297
  • Country: gb
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #30 on: December 02, 2022, 03:21:59 pm »
[sorry for waking the dead]

I think Orin's approach is quite common in bin to dec conversion, although in this case the initial scaling of the adc result is not needed, as he points out.

e.g. itoa kinda function...

Code: [Select]
/*
 * https://stackoverflow.com/questions/7890194/optimized-itoa-function
 * Convert an unsigned number in the range 0...99,000 to decimal 5 ascii digits using Q4.28 notation.
 * Terminating NULL is NOT provided.
 */
void utl_unsigned_to_5digit_ascii(char *buf, uint32_t val) {
    const uint32_t f1_10000 = ((1UL << 28) / 10000UL);

    /* 2^28 / 10000 is 26843.5456, but 26843.75 is sufficiently close */
    uint32_t tmp = val * (f1_10000 + 1) - (val / 4);

    for(uint32_t i = 0; i < 5; i++)
    {
        uint8_t digit = (uint8_t)(tmp >> 28);
        buf[i] = '0' + (uint8_t) digit;
        tmp = (tmp & 0x0fffffff) * 10;
    }
}
« Last Edit: December 02, 2022, 03:23:41 pm by voltsandjolts »
 

Offline mariush

  • Super Contributor
  • ***
  • Posts: 5012
  • Country: ro
  • .
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #31 on: December 02, 2022, 03:38:50 pm »
Some PIC microcontrollers  can have the internal voltage reference configurable to 1.024v , 2.048v and 4.096v  - your input voltage must be above the voltage reference, of course, so you could use 2.048v if you power your microcontroller with 3.3v, and 4.096v if you power it with 5v.

If you set the voltage reference to 4.096v you basically have 4 mV per step, so you can simply measure with your ADC and multiply by 4.  Change your voltage divider resistors so that you'd a 1:3 ratio or something like that... for example 4096mV on the AC pin  = 12v input.

Now, each adc step is 4mV x 3 = 12mV

If the voltage reference is not configurable or you rely on the input voltage to the PIC to be the reference,  I would still consider choosing the voltage dividing resistors so that you could simply do some bit shifting (divide by 2 , by 4 etc)
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #32 on: December 02, 2022, 04:26:08 pm »
One should also consider whether there is a need for accuracy.

I haven't read the whole thread but even 12 bits is 1/4096 i.e. 0.025%. I've been in "precision analog" since the 1970s (when "precision analog" was really expensive, with an AD504 costing 20 quid) and 0.025% accuracy is not gonna be cheap/easy to achieve in production.

I am doing a product now which has a 16 bit ADC and it all needs factory cal stored in FLASH, against a really carefully built test rig calibrated to < 0.01%.

Also most 12 bit ADCs are pretty fast and it can take a lot more time to get the data out via SPI or I2C. I once bit-banged I2C on a H8/300 to drive an ADS7828 and it took 600us to get the data out :) That probably compares to a floating point multiply on a very slow CPU...

And almost no on-chip 12 bit DAC/ADC yields a real 12 bit value. The last 2 bits tend to be random.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8166
  • Country: fi
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #33 on: December 02, 2022, 04:59:07 pm »
Generally: for a n-bit ADC, round n up to nearest 8 bits. Then use a multiplication factor of same width, and output 2n bits. Then divide the result by 2^m, which often can be just 2^n.

The multiplier server three purposes, all-in-one:
* transform the input to be large enough so that further division does not reduce resolution,
* work as unit conversion (for example, going from ADC count to microvolts, millivolts, fixed point volts, whatever)
* work as calibration factor: make the multiplier adjustable (fine-tunable)

Divider could be anything, but usually in instruction sets, especially in small MCUs, multiplying is fast but arbitrary division is slow. But dividing by 2^n is fast. So adjust the multiplier to be any arbitrary number and divide by 2^n.

Example with 12-bit ADC.
Say 12-bit range [0 .. 4096] corresponds to [0 ... 3.3V]. We want to output 0.1mV: [0 .. 33000] so that one can just add decimal point before the last digit when printing. So we want to multiply by 33000/4096 = 8.056640625.

1) Multiply by 33000
2) Divide the result by 4096

How about numerical ranges of types?
33000 fits in uint16
4095 fits in uint16
Hence, result should fit in uint32.
Double-check with maximum count: 4095 * 33000 = 135135000. UINT32_MAX is 2^32, way more than this.

In C:
static uint16_t calib = 33000;

uint16_t adc = read_from_adc();
uint16_t result = ((uint32_t)calib * (uint32_t)adc)/4096;

Adding the decimal point prior to printing is left as an exercise to the reader.


TLDR:
* multiplication is cheap
* division by 2^n is cheap
* large integer types are cheap (even a 64-bit type on a 8-bit microcontroller) compared to floats, use them for intermediate results.
« Last Edit: December 02, 2022, 05:24:59 pm by Siwastaja »
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26868
  • Country: nl
    • NCT Developments
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #34 on: December 02, 2022, 08:25:39 pm »
I used to use fixed point as well but the often 'odd' units (like decimeters, deciVolts, etc) didn't make the code much easier to read. Nowadays I just use floating point and be done with it. Realistically all the fixed point calculations in between add up to quite a few cycles and speed of soft floating point is more often than not fast enough anyway. Especially where it comes to displaying numbers. But I'm using soft floating point in applications with samplerates into several kHz as well.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3237
  • Country: gb
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #35 on: December 02, 2022, 09:33:21 pm »
Should be considerably faster (no divides), more accurate (as it uses the CORRECT 4095 value), and quicker to type (shorter).

A unipolar ADC or DAC hits it's full scale output at \$FS=V_{ref}{{2^N-1}\over{2^N}}\$ i.e. full scale is 1 LSB below the reference voltage which in this case is (4095/4096)*Vref.  To convert to voltage dividing by 4096 would be correct.
 

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #36 on: December 02, 2022, 10:00:41 pm »

 \$FS=V_{ref}{{2^N-1}\over{2^N}}\$

Where did you get that formula from?

If the reference is exactly 10.00000000000000000000 volts, and the maximum the ADC can read is $FFFF.

Then full scale (max) reading, for exactly 10.000000000 Volts input to the ADC, would be 4095 decimal ($FFFF).
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6227
  • Country: fi
    • My home page and email address
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #37 on: December 03, 2022, 02:49:02 am »
\$FS=V_{ref}{{2^N-1}\over{2^N}}\$
Where did you get that formula from?
It applies to all successive approximation ADCs (aka SAR ADCs).  The reason is that the reference voltage corresponds to code \$2^N\$, which cannot be reached by the successive approximation.  SAR ADCs work by starting with \$V_\min=0\$, \$V_\max=V_\text{REF}\$, applying the bisection method to halve the range, keeping \$V_\min \le V_\text{IN} \le V_\max\$.  It takes \$N\$ steps to resolve a \$2^N\$-bit code, using essentially a DAC and a comparator (that tells whether \$V_\text{IN}\$ is above or below \$V_\text{DAC} = \frac{V_\min + V_\max}{2}\$).  Because of this, the range of the conversion is between \$0\$ and \$2^N-1\$, inclusive, and the largest possible code \$2^N-1\$ refers to \$V_\text{REF}\frac{2^N-1}{2^N}\$.

This is typical of many similar algorithms both in electronics and computing.  You can find detailed descriptions of this at Wikipedia, the successive approximation ADC article, and the binary search and bisection method articles.
 
The following users thanked this post: MK14

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14430
  • Country: fr
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #38 on: December 03, 2022, 03:03:34 am »
Yep. But in the end it's down to the fact that you can't represent 2^N with N bits. Or, if you can, you can't represent 0. Or, alternatively, the scale is not linear.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #39 on: December 03, 2022, 03:17:41 am »
\$FS=V_{ref}{{2^N-1}\over{2^N}}\$
Where did you get that formula from?
It applies to all successive approximation ADCs (aka SAR ADCs).  The reason is that the reference voltage corresponds to code \$2^N\$, which cannot be reached by the successive approximation.  SAR ADCs work by starting with \$V_\min=0\$, \$V_\max=V_\text{REF}\$, applying the bisection method to halve the range, keeping \$V_\min \le V_\text{IN} \le V_\max\$.  It takes \$N\$ steps to resolve a \$2^N\$-bit code, using essentially a DAC and a comparator (that tells whether \$V_\text{IN}\$ is above or below \$V_\text{DAC} = \frac{V_\min + V_\max}{2}\$).  Because of this, the range of the conversion is between \$0\$ and \$2^N-1\$, inclusive, and the largest possible code \$2^N-1\$ refers to \$V_\text{REF}\frac{2^N-1}{2^N}\$.

This is typical of many similar algorithms both in electronics and computing.  You can find detailed descriptions of this at Wikipedia, the successive approximation ADC article, and the binary search and bisection method articles.

The DEFINITION, for this thread, seems to be given as:

My ADC result is 0-4095. I need to convert this to be 0-10V as a string.

So, 4095 is DEFINED to be EXACTLY 10.00000000000000000... Volts.

It may or may not be successive approximation, or another type.  It may or may not have a 10 volt reference, etc.
 
The following users thanked this post: Nominal Animal

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #40 on: December 03, 2022, 03:36:12 am »
Also note.  The thread seems to be from around 6.5 years ago, and the OP, doesn't seem to have logged in here, for around 4.5 years.
 
The following users thanked this post: Siwastaja, newbrain

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6227
  • Country: fi
    • My home page and email address
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #41 on: December 03, 2022, 04:32:46 am »
Sure.  And you're right, MK14; I didn't mean to imply it applies here, just wanted to describe where it comes from.  :-+

Let's delve into the math a bit, though, because even the integer form of the Arduino map() gets this stuff wrong (it does not yield the same results as the float form one does!).



When you want to convert \$V\$ to \$R\$, with \$V_\min \le V \le V_\max\$, and \$R = R_0\$ when \$V = V_\min\$ and \$R = R_1\$ when \$V = V_\max\$, the exact mathematical formula is
$$R = R_0 + \left(V - V_\min\right) \frac{R_1 - R_0}{V_\max - V_\min}$$

When we use integers and integer arithmetic (\$V, R \in \mathbb{Z}\$), the situation is somewhat more interesting, especially when uses SAR ADCs, because then \$V_\min \le V \lt V_\max\$, and \$V_\max = V_\min + 2^N\$.  In other words, \$V_\max\$ is exclusive.  Nothing else in the formula changes, though.  To apply correct rounding, i.e.
$$R = R_0 + \left\lfloor \left(V - V_\min\right) \frac{R_1 - R_0}{V_\max - V_\min} \right\rceil$$
we do
$$R = R_0 + \left\lfloor \frac{ (V - V_\min) (R_1 - R_0) + C}{V_\max - V_\min} \right\rceil, \quad C = \operatorname{sgn}(R_1 - R_0) \frac{V_\max - V_\min}{2}$$
i.e. \$C\$ is half the divisor with the same sign as \$R_1 - R_0\$, and picking \$\lfloor \rfloor\$ when \$C\$ is positive, and \$\lceil \rceil\$ when \$C\$ is negative.

In C, we can write this using correct rounding as for example
Code: [Select]
int32_t  map(const int32_t in, const int32_t inmin, const int32_t inlimit, const int32_t outmin, const int32_t outlimit)
{
    const uint32_t  i = (in >= inmin) ? in - inmin : 0;
    const uint32_t  im = (inlimit > inmin) ? inlimit - inmin : 1;
    if (outlimit > outmin) {
        const uint32_t  om = outlimit - outmin;
        return outmin + (int32_t)((i * om + (im >> 1)) / im);
    } else
    if (outmin > outlimit) {
        const uint32_t  om = outmin - outlimit;
        return outmin - (int32_t)((i * om + (im >> 1)) / im);
    } else
        return outmin;
}
When outlimit - outmin is a power of two, the division simplifies to a bit shift.   The above only works correctly when im*om ≤ 232, and inmin ≤ in < inlimit.  Then, if outmin < outlimit, outmin ≤ result < outlimit.  If outmin > outlimit, then outlimit < result ≤ outmin, and result is correctly rounded, halfway towards outlimit.  However, if im ≥ 2 om, i.e. the output range is half of the input range or less, then result can reach outlimit due to rounding.  When the output range is smaller than the input range, I recommend omitting the rounding.  Whenever output range is more than half the input range, result won't reach outlimit unless in ≥ inlimit.

(We could do the above for short, int and long types in Arduino, using __builtin_clz() or __builtin_clzl() to find the size of im and om in bits and using a larger cast (long or long long) when necessary, getting fast but accurate integer map() whose behaviour matches that of the one with float parameters.  Details like this bug me, because they are often the cause of weird behavioural differences due to tiny changes in the code that should not affect arithmetic results that much.)

When inmin, inlimit, outmin, and outlimit are fixed, it makes sense to precalculate om and im, and divide both with their greatest common denominators (which for a power of two om means shifting both right until im becomes odd).

For the 0,4096 → 0,10000 conversion (assuming exclusive limits, like on SAR ADCs), 10000/4096 = 625/256, exactly, and the result of the multiplication fits in 22 bits.  The function is then simply
Code: [Select]
uint_fast16_t  adc_to_millivolts(uint_fast16_t i) { return ((uint_fast32_t)i * 625 + 128) >> 8); }and adc_to_millivolts(4095) == 9998 , as expected. (40950000/4096 = 9997.55859375, which rounds to 9998.)
In fact, this routine returns the exact same results as (uint_fast16_t)floor(0.5 + i * 10000.0 / 4096.0); and, if using round away from zero, with (uint_fast16_t)round(i * 10000.0 / 4096.0).  The latter differs from the former for i=128,640,1152,1664,2176,2688,3200,3712 because the standard rule for IEEE 754 floating-point math is to round halfway towards odd, not away from zero, and these values of i are at exact half-millivolt boundaries.

With inclusive limits 0,4095 → 0,10000 conversion requires a division by 4095, or a fractional multiplication by 10000/4095 = 2000/819 ≃ 2.44200244200... which we can approximate with 160039/65536, compensating a bit with the rounding constant (32951 instead of 32768):
Code: [Select]
uint_fast16_t  adc_to_millivolts(uint_fast16_t i) { return ((uint_fast32_t)i * 160039 + 32951) >> 16; }which yields 169 instead of 168 for i=69; 1390 instead of 1389 for i=569; 3390 instead of 3389 for i=1388, and 8610 instead of 8611 for i=3526; and the exact same results as (uint_fast16_t)floor(0.5 + i * 10000.0 / 4095.0) for the rest of i=0..4095, inclusive.
« Last Edit: December 03, 2022, 04:45:17 am by Nominal Animal »
 
The following users thanked this post: helius, MK14

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8166
  • Country: fi
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #42 on: December 03, 2022, 07:34:05 am »
The DEFINITION, for this thread, seems to be given as:

My ADC result is 0-4095. I need to convert this to be 0-10V as a string.

So, 4095 is DEFINED to be EXACTLY 10.00000000000000000... Volts.

Technically correct (that OP said so), but it's very likely OP made a mistake here, and meant 4096 is defined as exactly 10.0V. This is a common mistake to make (assuming that maximum count of SAR ADC represents the reference voltage, when in reality (maximum count + 1) represents the reference).
 
The following users thanked this post: mikerj, Ian.M, MK14

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 3455
  • Country: us
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #43 on: December 03, 2022, 10:30:23 am »
One "trick" is to use a reference voltage that is a power of 2, e.g., 4.096 V or 2.048 V.  Then each count is a power of 2 in millivolts.  After that, it is just a matter of converting the binary files to BCD (or whatever) for printing.  Example: 10 bit ADC with 4.096 Vref gives 4 mV per count, which is just a couple of left shifts.
 
The following users thanked this post: MK14

Offline wek

  • Frequent Contributor
  • **
  • Posts: 494
  • Country: sk
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #44 on: December 03, 2022, 01:23:36 pm »
Consider a perfect 1-bit ADC, which is a perfect comparator with VREF/2. The result of conversion is 0 or 1, corresponding to intervals 0..VREF/2 and VREF/2..VREF.

See the point? The converted digital value does not correspond to a single voltage but to an interval of voltages. You can consider the middle of the interval to be the "true value", with giving symmetrical error. Or you can consider the lower end of the interval (upper would be... strange), that's the equivalent of simply multiplying the conversion result with VREF/2^N (and "never reaching VREF").

Further discussion of this notion in footnote 3 here.

JW
« Last Edit: December 03, 2022, 01:26:30 pm by wek »
 
The following users thanked this post: mikerj, MK14

Online Siwastaja

  • Super Contributor
  • ***
  • Posts: 8166
  • Country: fi
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #45 on: December 03, 2022, 03:19:25 pm »
One "trick" is to use a reference voltage that is a power of 2, e.g., 4.096 V or 2.048 V.  Then each count is a power of 2 in millivolts.  After that, it is just a matter of converting the binary files to BCD (or whatever) for printing.  Example: 10 bit ADC with 4.096 Vref gives 4 mV per count, which is just a couple of left shifts.

That's nice in theory but practical circuits usually have some kind of calculation anyway - resistor dividers, unit conversions, etc. Single multiplication wraps all (linear) calculations in one operation. Further, the multiplication and division are nearly free operations, especially on 32-bit micros but not bad on 8-bitters, either.

Binary to decimal conversion during printing is an order of magnitude slower.

This is why I have never seen the point in 2.048V etc. references - I pick the best reference based on all other specifications except that.
 
The following users thanked this post: MK14

Offline MK14

  • Super Contributor
  • ***
  • Posts: 4527
  • Country: gb
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #46 on: December 03, 2022, 05:10:10 pm »
Ok, well I'll replace some peoples speculation, with my own WILD speculation.
Some of the OPs posts, seem to also describe a particular ADC, which MIGHT be the same as the one in this thread.  It seems so, but is only an ASSUMPTION.

https://www.eevblog.com/forum/beginners/i2c-multiple-chips-not-working/msg608117/#msg608117

Bold in quote, added by me.
A DAC, and ADC and an IO expander. The DAC and IO expander work OK, I can access the registers fine. The ADC (Linear LTC2990) does not like me.

https://www.analog.com/media/en/technical-documentation/data-sheets/ltc2990.pdf

But we would also probably need to know what external components were used (schematic), and what settings they used, to really get to the bottom of it.

The datasheet doesn't seem to make it clear, what technology(s), are used for the ADC, or precise internal details, of its operations.
 

Offline Doctorandus_P

  • Super Contributor
  • ***
  • Posts: 3340
  • Country: nl
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #47 on: December 03, 2022, 09:50:36 pm »
I do not want to use Floating points, for obvious reasons.

Please explain.
It's not so obvious to me.
There are plenty of uC's these days with built in multiplication instructions, and floating point libraries are (or at least should be) heavily optimized.
You can do manual fixed point math or other routines but it takes a lot more effort to fine tune these compared to a single floating point multiplication with a calibration value.

Floating point is not as "heavy" as it's perceived to be on a lot of microcontrollers these days.

Edit:
 :-DD OP has not posted in this thread after 2016
« Last Edit: December 03, 2022, 09:53:17 pm by Doctorandus_P »
 
The following users thanked this post: nctnico, MK14

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 3455
  • Country: us
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #48 on: December 03, 2022, 10:00:42 pm »
That's nice in theory but practical circuits usually have some kind of calculation anyway - resistor dividers, unit conversions, etc. Single multiplication wraps all (linear) calculations in one operation. Further, the multiplication and division are nearly free operations, especially on 32-bit micros but not bad on 8-bitters, either.

Binary to decimal conversion during printing is an order of magnitude slower.

This is why I have never seen the point in 2.048V etc. references - I pick the best reference based on all other specifications except that.

The question asked was how to convert ADC binary to decimal.  That was answered.  As for further calculations, I agree, generally do that last.  BUT, that was not the question.  As for binary to BCD, I have no clue how those C wizards do it.  In Assembly, there are several ways.  Double Dabble is among the slowest.  Up to 17-bit, there are several polynomial methods on PICList that are quite fast compared to division with 16-bits on 8-bit horse carts.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26868
  • Country: nl
    • NCT Developments
Re: ADC/DAC Conversion to "decimal", best practices....
« Reply #49 on: December 04, 2022, 12:43:59 am »
As for binary to BCD, I have no clue how those C wizards do it.
printf("%f", my_float_here);

I know this is a bit tongue in cheek but the C libraries that come with good C compilers are pretty well optimised. There likely isn't much improvement you can achieve by writing your own unless your application is a rare corner case.

Not using floating point is one of the many ill advised dogmas that surround embedded programming.
« Last Edit: December 04, 2022, 02:03:41 am by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf