Converting BMW temperature sensor resistance to degrees Celsius with an IC
The BMW E36 on-board computer uses a temperature sensor mounted in the front bumper.
The temperature sensor is actually a thermistor with a negative thermal coefficient (NTC thermistor = negistor), meaning that as the temperature rises, its resistance falls.
The sensor was found to be equal to a K164NK004.7 thermistor. The resistances of this thermistor for different temperatures according to the datasheet are:
When using an IC such as the Atmega168 on Arduino, you cannot measure resistance directly. You add a pull-up resistor to the temperature sensor, which creates a voltage divider and then use the IC to measure the resultant voltage.
The value dependence between the thermistor resistance and the resulting voltage is not linear and neither is the dependence between the resistance and the actual ambient temperature in degrees Celsius.
My goal was to determine the best value of the pull-up resistor to create a linear (or at least uniform) dependency between the ambient temperature and the output of the voltage divider.
I picked several common resistor values and calculated the voltages for different temperatures.
Let's put the values on a graph and see which resistor gives the most linear output
The graphs seem very similar, so let's graph the relation between a temperature change and a voltage change.
This graph clearly shows that no matter what resistance we use, we will never get a flat line. The next best thing is the 12K resistor - it is flat around zero degrees and uniform on both sides.
So let's use a 12K resistor and see how closely we can approximate its graph with a linear function. We want to calculate the temperature from the voltage, so the graph will be reversed. It is not hard to see that a good approximation function is
temperature = 20 * voltage - 45
That's not bad for such a simple function, but it still needs some fine-tuning - the biggest difference is almost 5 degrees Celsius.
After some test and error time, I came up with
temperature = (400 * voltage - 888) * (140 + |voltage|) / 3500
which gives acceptable results.
So let's sum up - if you connect the BMW E36 ambient temperature sensor to an IC and pull it up to 5V with a 12K resistor, you can then convert the voltage measured by the IC to actual temperature using the formula stated above.
The temperature sensor is actually a thermistor with a negative thermal coefficient (NTC thermistor = negistor), meaning that as the temperature rises, its resistance falls.
The sensor was found to be equal to a K164NK004.7 thermistor. The resistances of this thermistor for different temperatures according to the datasheet are:
When using an IC such as the Atmega168 on Arduino, you cannot measure resistance directly. You add a pull-up resistor to the temperature sensor, which creates a voltage divider and then use the IC to measure the resultant voltage.
The value dependence between the thermistor resistance and the resulting voltage is not linear and neither is the dependence between the resistance and the actual ambient temperature in degrees Celsius.
My goal was to determine the best value of the pull-up resistor to create a linear (or at least uniform) dependency between the ambient temperature and the output of the voltage divider.
I picked several common resistor values and calculated the voltages for different temperatures.
Let's put the values on a graph and see which resistor gives the most linear output
The graphs seem very similar, so let's graph the relation between a temperature change and a voltage change.
This graph clearly shows that no matter what resistance we use, we will never get a flat line. The next best thing is the 12K resistor - it is flat around zero degrees and uniform on both sides.
So let's use a 12K resistor and see how closely we can approximate its graph with a linear function. We want to calculate the temperature from the voltage, so the graph will be reversed. It is not hard to see that a good approximation function is
temperature = 20 * voltage - 45
That's not bad for such a simple function, but it still needs some fine-tuning - the biggest difference is almost 5 degrees Celsius.
After some test and error time, I came up with
temperature = (400 * voltage - 888) * (140 + |voltage|) / 3500
which gives acceptable results.
So let's sum up - if you connect the BMW E36 ambient temperature sensor to an IC and pull it up to 5V with a 12K resistor, you can then convert the voltage measured by the IC to actual temperature using the formula stated above.
Labels: arduino, bmw e36, thermistor, voltage divider