Data Lookup from ADC Data

Ok .. here is the scenario, and I am an Arduino newbie but I have been a coder guy for some time.

What I have is a device that I am getting data from (voltage data) to the Arduino Analog A0 port. So I get a value in the range of 0 to 1023 from the Arduino.

But here is my issue ... for each of those 1024 items I have a corresponding other value I need to look up. For example (and these are fake numbers) I just need to find the best way to code this lookup part.

So it would be something like this with 1024 items.

ADC, Raw Data

ADC 0, 7 ACD 1, 10 ADC 2, 14 ADC 3, 17

..

ADC 1022, 822 ADC 1023, 825

So I need to look up the Raw Data part for the corresponding ADC value ?

I do not have live true data for possibly a few days (likely at least Friday) but the concept is exactly the same as above. I am expecting the raw data values to be in the range from 20 to 140 but do not know yet.

So what is the best way .. Arduino wise to get the data ?

I should note that I only need to display the data to my LCD screen once a second. So I will get the ADC value once a second and look up the Raw Data at that time and display it.

Thanks Kevin

If the data is linear, consider using map()

output = map( ADCCount, 0, 1023, 20, 140 );

If it’s non-linear you could create a smaller table using a best-fit method and use linear interpolation, such as:

const int DataArray[64] = 
    {
        0, 10, 20, 30, 40, 50, 60, 70,
        80, 90, 100, 110, 120, 130, 140, 150,
        160, 170, 180, 190, 200, 210, 220, 230,
        240, 250, 260, 270, 280, 290, 300, 310,
        320, 330, 340, 350, 360, 370, 380, 390,
        400, 410, 420, 430, 440, 450, 460, 470,
        480, 490, 500, 510, 520, 530, 540, 550,
        560, 570, 580, 590, 600, 610, 620, 630        
    };


int
    ADCValue;

void setup()
{
    Serial.begin(9600);
    ADCValue = 0x0000;

}//setup

void loop()
{
    int
        nIdx,
        nFrac,
        nOutput;
    int
        tblVal1, tblVal2;
        
    nIdx = (ADCValue >> 4) & 0x3f;
    nFrac = ADCValue & 0xf;

    if( nIdx == 0x3f )
        nOutput = DataArray[nIdx];
    else
    {
        tblVal1 = DataArray[nIdx];
        tblVal2 = DataArray[nIdx+1];
        if( tblVal2 > tblVal1 )
            nOutput = tblVal1 + (((tblVal2-tblVal1)*nFrac)/0xf);
        else
            nOutput = tblVal1 - (((tblVal1-tblVal2)*nFrac)/0xf);
        
    }//else

    Serial.print( "ADC: " ); Serial.print( ADCValue );
    Serial.print( "  Table output: " );Serial.println( nOutput );
    
    delay(10);
    ADCValue = (ADCValue + 1) & 0x03ff;
        
}//loop

and yes, I know the data in my example is linear…

Thank you .. I will look into it once my new Arduino hardware comes and everything is ready. But for now .. I can probably use fake data to see how it works.

I am making progress … however I do need to convert from uV readings to dBm values.

For example the formula is as follows in Excel. I know … but I am having issues getting it to work in Arduino.

10LOG(((uV0.000001)^2)/50)+30

This is assuming that an input value for uV as 1776, which should give an answer of -42.

#include <math.h>

float uV = 1776;
float value = 0.0;

void setup() {
  // put your setup code here, to run once:


Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

value = pow(10*log10(uV*0.000001),2)/50;
int value2 = value + 30;

Serial.println(value2);

delay (2000);
}

Thanks
Kevin

edmscan:
What I have is a device that I am getting data from (voltage data) to the Arduino Analog A0 port. So I get a value in the range of 0 to 1023 from the Arduino.

edmscan:
I am making progress … however I do need to convert from uV readings to dBm values.

you do realise that if you are using A0 WITHOUT any external voltage reference the resolution of A0 is about 5mV

how do you intend to measure uV???

anyway this equation :

edmscan:
10LOG(((uV0.000001)^2)/50)+30

can be simplified (that will make it easier for your arduino to process)

so, if I right, the equation can be re-written as:

20LOG(uV) + 20LOG(0.000001) -10*LOG(50) + 30

// pre-calculate 20LOG(0.000001) -10LOG(50) + 30 and put the value in their place

and if you are using the ADC then is probably be something like this:

20LOG(ADC) + 20LOG(ADC_Vref/ADC_resolution) + 20LOG(0.000001) -10LOG(50) + 30

//again ‘ADC_Vref’ and ‘ADC_resolution’ would be constants and can therefore be pre-calculated

Floats have about 6 decimals accuracy.

0.000001 is at the limits

demkat1:
Floats have about 6 decimals accuracy.

0.000001 is at the limits

The limit of 6 to 7 digits (in the decimal domain) is about significant digits.
The 0.000001 has only one significant digit (in the decimal domain).

Huge thanks for the reply …

I have a lab grade signal generator right beside me. It is really just about being able to display the dBm reading on the screen.

So this is a photo of the project right now. I actually just used the Excel spreadsheet and just got the dBm readings from the uV readings. I did have to generate signals to determine the ADC value for a given signal.

I get ADC values from about 106 at the low end and 315 on the high end. The bar graph is a bit compressed on the high end as those really strong signals are very rare and really it is just about a graphical representation.

I only really need to do this once … so I just did it. I hard coded the values in an array and just look them up.

For example … a 50 uV signal is about 293 on the ADC or -73 dBm. I know that due to rounding etc … that my dBm is +/- about 1 dBm.

You may be wondering why there are 2 S-Unit numbers. Well the one on the right is IARU recommendation. The one on the left is more old school (this is due to the fact that my receiver cannot receive anything weaker than about -122 dBm and that is an S4 signal on the IARU recommendation. That is just weird for me … as that is a weak signal. As long as 6 dBm is one s-unit <= S9 and 10 dBm for > S9 then I will be fine.

Because the only thing I can get from the radio is the ADC data … I just have to be as precise as I can.

I am using it for a number of things from antenna testing to repeater / signal testing. Of course the higher the ADC value the stronger the signal. That will always be constant.

I am tapped off the squelch circuit to be able to tell if the squelch is broken … and if it is not, I display a no signal screen. I only update the data if the data is changing so that there is less flicker.

Oh … I do not know what the ADC resolution etc is … so over my head right now but that does not mean that it could not be useful in the future of this project.

Take care …
Kevin

edmscan: So it would be something like this with 1024 items.

ADC, Raw Data

ADC 0, 7 ACD 1, 10 ADC 2, 14 ADC 3, 17

I'm a bit confused.

A lookup table is usually used when it is not possible to calculate the corresponding values yet a lot of the subsequent discussion is about calculating values.

There is not enough SRAM in an Uno for a lookup table of that size. You may be able to put it in program memory if the values never need to change.

HOWEVER, I would not normally expect the ADC to give such precise values that you could clearly distinguish between two adjacent values - in many cases the actual voltage presented to the ADC will be teetering between two discrete values.

...R

The ADC data as you stated .. is a bit hit and miss due to tiny fluctuations.

For example ... if you give it a signal it may alternate +/- a couple of ADC digits for example but sometimes it is rock solid.

This is not a lab grade project .. I know it won't be. When you consider that on most radios unless you get the new Uniden SDS100 or Uniden SDS200 radios (these have dBm displays) you get 1-5 bars at best.

The thing .. is that I only displaying data on the screen if it changes and only reading from the radio once every .75 seconds. So the Arduino is not breaking a sweat as it sits there for the most part.

The one issue .. the given formula I do not know what ADC_Vref and ADC_resolution are .. so hard for me to use a formula. I know .. I am a newbie to Arduino.

20*LOG(ADC) + 20*LOG(ADC_Vref/ADC_resolution) + 20*LOG(0.000001) -10*LOG(50) + 30

For right now .. it works but it is a work in progress and yes if I could code a better solution rather than using a look up method as I have now I could do that instead.

I am absolutely not disregarding what has been said .. but have to live within my knowledge limitations. That is in regards to coding and the Arduino.

Thanks Kevin

edmscan: The one issue .. the given formula I do not know what ADC_Vref and ADC_resolution are .. so hard for me to use a formula. I know .. I am a newbie to Arduino.

FYI... nothing to do with arduino... its purely ADC stuff!!!!

ADC_Vref is the ADC voltage-reference (internal or external). depending on the hardware you have some options there. ADC_resolution is, as the variable name states, the resolution of your ADC. (for arduino, can look up here: https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/)

start GOOGLING to expand your knowledge.

Thank you .. ;-)