Simple Code

Been experimenting with a resistor reader and have the following:

int analogPin = 0;
int raw = 0;
int Vin = 4.94;
float Vout = 0;
float R1 = 1010.86;
float R2 = 0;
float buffer = 0;

void setup()
{
  Serial.begin(9600);
  
}

void loop()
{
  raw = analogRead(analogPin);
  if(raw)
    {
        buffer = raw * Vin;
        Vout = buffer /1024.0;
        buffer = (Vin / Vout) - 1;
        R2 = R1 / buffer;
        Serial.print("Resistance Value: ");
        Serial.println(R2);
        delay(900);
        
    }
}

All is well but I would like it to say the word "Ohms" after the given reading on the same line. For example as it sits now it displays, "Resistance Vaule: 470.00" I would like to read, "Resistance Value: 470 Ohms." I have been trying different ways but no success. Any help much appreciated.

int Vin = 4.94;

Don't know much about ints, do you?

  raw = analogRead(analogPin);
  if(raw)
    {

The analogRead() function doesn't return a boolean. Don't treat the return value as boolean.

All is well but I would like it to say the word "Ohms" after the given reading on the same line. For example as it sits now it displays, "Resistance Vaule: 470.00" I would like to read, "Resistance Value: 470 Ohms."

And you can't see the difference between the print() and println() functions?

Yeah I see it but I don't understand it. Sorry. I just needed to know how I would change the code. :blush:

Don't use float. Your almost there: Serial.print("Resistance Value: "); Serial.print(R2); Serial.println(" Ohms");

I do kind of wonder how much of that code is copy&paste which is no problem but coupled with your question versus the ones you should be asking I'm not sure what advice to give but I am pretty sure that just fixing that code will not help you learn anything useful.

Your variables and your use of them have issues. Sure you'll get values out but not correct ones.

Analog read returns an int 0 to 1023. Dividing buffer by 1024.0 is one error. Divide by 1023.0 to get the proper range. 1024 while "intuitive" is wrong. Don't feel so bad, I did that too.

When you mix variable types and don't want the compiler to screw it up, use casts like this:

int myRead = 234; float myResult, myScale = 10.9;

myResult = (float) myRead / myScale;

The (float) makes sure that myRead is cast into a float for the division and myScale is not made into an int.

Serial.println( myResult ) adds a newline after the number is printed where Serial.print( myResult ) does not which would let me add more text with a print on the next line.

Your code:

        Serial.print("Resistance Value: ");
        Serial.println(R2);

should show you how to print 2 things on the same line so really, how hard can adding 1 more be?

And that's why "I do kind of wonder how much of that code is copy&paste." Copying code is NOT a problem unless you don't understand what you copied.

Do you need some links into the Arduino site where the basics are explained, the standard commands/functions are referenced, the examples included in your IDE are gone over and such? Because really, you need more background just to save yourself time getting up to speed. Just poking at what you mainly don't know how to read is not going to help much. You need to refer to references for every command/function in the code that you are not SOLID with. You want nothing in there you don't know about doing you don't know what. Look things up, the machine won't "know what you really mean".

Hi, Serial.print(R2); means print the value of variable R2, the [u]print[/u] means keep the cursor on the next character positon after printing R2 value.

Serial.println(" Ohms"); means print Ohms (the text), [u]println[/u] means perform a carriage return after "Ohms". That is move down to start of next line , if possible.

Basically; If you don't use " " around what you need to print, what you have put between the ( ) will be treated as a variable. If you do use " " around what you need to print, what you have put between the ( ) will be treated as a text.

Tom...Hope this helps.... :)

Very cool thank you guys for the help.

You have no questions?

I for one wonder how you have that wired.

Here you go:

Untitled-1.jpg

A voltage divider. Cool. And I see that you determined the reference resistor to 6 places ( 1010.86 ).

There is a code step you can take to get more accurate math to your answer. Do the math as fixed-point with 64-bit integers ( 19 places ) and you shouldn't lose anything. Whereas with Arduino 32-bit floats ( 6 places, 7 if the high digit is 3 or less) and 5 operations you do.

        buffer = raw * Vin;            // 1 mult
        Vout = buffer /1024.0;      // 1 div
        buffer = (Vin / Vout) - 1;    // 1 div and 1 add
        R2 = R1 / buffer;                 // 1 div

But of course that fixed-point accuracy will be false to some margin due to the extent of physical error (wires and plugging the test resistor) while the error in using floats may either counter the physical error or add to it.

Sometimes you just gotta either love of hate tolerances!

GoForSmoke: Analog read returns an int 0 to 1023. Dividing buffer by 1024.0 is one error. Divide by 1023.0 to get the proper range. 1024 while "intuitive" is wrong.

As far as I know there are 1024 steps. The bottom one is 0 and the top one is 1023.

...R

Just in case there is any misunderstanding about Robin2's post...

GoForSmoke: Analog read returns an int 0 to 1023.

Yup.

Dividing buffer by 1024.0 is one error.

Nope.

Divide by 1023.0 to get the proper range.

Nope.

1024 while "intuitive" is wrong.

Nope.

Don't feel so bad...

Yup.

...I did that too.

You need to keep doing it.

Have any doubts? Check the datasheet.

The value returned from analogRead is divided by 1024. And, yes, that means it is impossible to reach the reference voltage. That's the way successive approximation converters work.

So you've got 0 to 1023 for 0V to 5V. And you read 1023

5 x 1023 / 1024 = 4.995

Hmmmm, gotta fix that so how about

5 x (1023 + 1) / 1024 = 5

And you read 0

5 x (0 + 1) / 1024 = .040

Whereas

5 x 1023 / 1023 = 5 5 x 0 / 1023 = 0

You do it your way then

Hi. 1024 levels, but only 1023 level to level gaps (steps).

Tom...... :)

If you're going to calculate with it, you might as well get what you put in.

ADC doesn't go all the way up, that's how the hardware works. Put in 5 V, get a converted value of 4.9951171875 V. Does it change the input voltage which is what you actually want to know?

TomGeorge: Hi. 1024 levels, but only 1023 level to level gaps (steps).

Tom...... :)

I suspect this is the answer. Sorry for starting a controversy.

...R

So you’ve got 0 to 1023 for 0V to 5V.
And you read 1023

5 x 1023 / 1024 = 4.995

Hmmmm, gotta fix that

No, you’ve got to accept that.

Imagine a one bit ADC, with a one volt reference.
You apply 750mV.
What’s the voltage on the pin?

Answer: the voltage is at least 500mV

GoForSmoke: So you've got 0 to 1023 for 0V to 5V.

The converter cannot differentiate between the reference voltage and one quanta less than the reference voltage. In your example that is 5 - 0.0048828125 = 4.9951171875 volts. The last step available to the converter is 4.9951171875 volts to 5 volts. A value of 1023 means the sampled voltage is between 4.9951171875 volts and 5 volts. Your comparison between the two ranges is incomplete because it disregards the fact that one side is discrete (0-1023) and the other side is continuous.

5 x 1023 / 1024 = 4.995

Correct (disregarding the lack of significant digits).

Hmmmm, gotta fix that so how about

There is nothing to fix because dividing by 1024 is not "broken".

You do it your way then

The way the folks at Atmel described it should be done? Of course I'm going to do it that way. They designed the hardware. They spent significantly more time than you and I studying the issues. I am not so arrogant to believe that I posses some hidden wisdom.

If I thought that the circuit and ADC combined are going to be up to the difference between 1/1024 and 1/1023 then I might take more care in making the shortcut abstraction.

Jack joggled me in a PM with a section of the datasheet that made me think hey, one solution would be to never feed the ADC the full AREF range. If AREF is 5V then what extra circuit would be best to limit that to 4.8V without more trouble and current drain than the difference is worth?

FWIW Robin, I'm sorry I stepped into it too.

Excellent thread subject... A Most Excellent topic for "n00b's" and those of us that have been using or designing with microcontrollers for years... And, Yes I got bit with that one too.. except I made 300 copies of the mistake.. I had a deal with my employer... He or the assemblers made a mistake, they or the Boss fixed them.. I made a design mistake, I fixed it... I fixed my share... and then some... Kinda sux BUT it [u]does[/u] wonders for making mistakes in basic circuit design.... Especially with solar powered, Very low power devices..

Doc