Converting a 1 volt input to different output

Hi, I'm sending a 0-1volt output from o2 sensor controller to an analog input into Arduino outputing to my 16x2 serial display. I'm having a problem figuring out how to formulate and write the conversion. The range is, 0 volts = 22.0 A/F ratio and 1 volt = 10.0 A/F ratio. I have started with the basic voltmeter code.

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  Serial.begin(19200);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0);
  // print out the value you read:
  Serial.println(voltage);
  Serial1.print(voltage);
}

Th range is, 0 volts = 22.0 A/F ratio and 1 volt = 10.0 A/F ratio

What is “Th range” and what does “A/F ratio” mean, please.

float voltage = sensorValue * (5.0 / 1023.0); It's a small thing, but I it is best to get things correct float voltage = sensorValue * (5.0 / 1024.0);

Thank you. Edited.

A/F ratio is a air to fuel ratio in an automotive exhaust. It really would just be a linear conversion of 0 volt input equaling a maximum value output of 22 through a 1 volt input equaling a minimum value output of 10 on my display. I seems like it should be fairly easy, but a 1 volt maximum on a 5 volt analog input and converting those to output a different value has me lost with coding.

Why not use the 1.1V internal reference, and get better resolution?
I now assume you meant O2 and “ratio” , not “ration”

AWOL:
Why not use the 1.1V internal reference, and get better resolution?

Take a look at these

http://www.ebay.co.uk/itm/Arduino-Uno-Mega2560-12-13bit-ADC-Shield-RTC-BLE-Bluetooth-Wifi-LAN-uSD-/191852458481?hash=item2cab4c31f1:g:iqkAAOSwyjBW8DRZ

Even better resolution and you can Bluetooth the data to your phone as well as to a 2X16/4X20 lcd display!

OK, its my product and I’m shameless so sue me!

Steve.

Sorry forgot to mention;

Once you have your voltage from

float voltage = sensorValue * (5.0 / 1024.0);

then you calculate the value as 22 - (voltage * 12)

ie if the voltage is 0 then 22-(0*12)=22

if the voltage is 1 then 22-(1*12) = 10

and if its 0.5, 22-(0.5*12) = 16

Hope that helps.

Steve

AWOL:
Why not use the 1.1V internal reference, and get better resolution?
I now assume you meant O2 and “ratio” , not “ration”

Yes, some auto-correct on ratio I guess…
Interesting, I didn’t know about this until now. Reading about this…

My head has been very cloudy from allergies, please let me know if my understanding is correct. If I use analogReference(INTERNAL1V1) in the Setup and and analogRead(a0) in the Loop, it will scale 0 to 1.1 volts on pin 0 from 0 to 1023. Then I can use a Map function to display the output to the display? int val = analogRead(a0); val = map(val, 0, 1023, 22, 10); Serial1.print(val);

The display output will need to float by at least 1 decimal, ex.. 10.5. Will the float be a problem using Map?

Map will not work with floats. I found the following function that will:

float fmap(long x, float in_min, float in_max, float out_min, float out_max)
 {
   return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
 }

You could convert to volts first then call, val = fmap(val, 0, 1.0, 22.0, 10.0);

And analogRead(a0) will probably cause an error (use A0).

AWOL: float voltage = sensorValue * (5.0 / 1023.0);

It's a small thing, but I it is best to get things correct

float voltage = sensorValue * (5.0 / 1024.0);

If you're going to be that fussy, at least get it correct:

float voltage = 5.0 * (sensorValue + 0.5) / 1024.0;

An ADC splits the input voltage range into 2^n buckets, the expression above gives the centre-voltage of each bucket which is the statistically unbiased value.

DACs are usually different and 1023 would be the correct factor for a 10 bit DAC.

Thank for everyone's responses.

Getting around to mess with this tonight, the following actually worked well with the float.

 analogReference(INTERNAL2V56);
  int sensorValue = analogRead(A0);
Serial1.print( map(sensorValue, 0,1023,2000,1000) / 100.0);

The coarse voltage output of the O2 sensor controller can actually output a maximum of 3.8 volts. I set voltage output to: 2.56 @ 10.00 A/F Ratio 0.00 @ 20.00 A/F Ratio and set the INTERNAL2V56 reference which seemed to provide a less jumpy output.

Then it came to me, I can use the 3.3 volt output pin into the AREF pin and change controller analog output setting range from 0 volts @ 20 A/F ratio - 3.3 volts @ 10 A/F ratio ouput and used the following:

analogReference(EXTERNAL);
  int sensorValue = analogRead(A0);
Serial1.print( map(sensorValue, 0,1023,2000,1000) / 100.0);

The display has even less jumpy output.

Jumpy meaning, A/F would jump around on display when Arduino showing 0.00 to 0.03 volts at input pin. A/F ratio would read like this at 0 volts:(roughly) 1.1 volt reference 19.85 A/F - 20.00 A/F 2.56 volt reference 19.92 A/F to 20.00 A/F External 3.3 volt reference 19.98 A/F to 20.00 A/F

My apologies if I'm not explaining this well, but I hope this helps someone. This seems to work very well!