drivers: sensor: ntc-thermistor: Fix voltage & resistance calculation

The pullup resistance was assumed to be the maximum ADC value. This is
incorrect when the reference ADC voltage and the thermistor pullup
voltage differ. Use the pullup_uv property from DT instead.

The equations for the thermistor resistance are also wrong. The correct
equations are (see https://en.wikipedia.org/wiki/Voltage_divider):
R1 = R2 * (Vin / Vout - 1)
for the positive-connected resistor, and
R2 = R1 * (Vin / Vout - 1)^-1
for the negative-connected resistor. These were transformed so that
they can be computed using integer math.

Signed-off-by: Paweł Anikiel <pan@semihalf.com>
This commit is contained in:
Paweł Anikiel 2023-08-04 10:36:07 +00:00 committed by Maureen Helm
commit 883a0c46a8
3 changed files with 19 additions and 12 deletions

View file

@ -55,13 +55,12 @@ static int ntc_thermistor_channel_get(const struct device *dev, enum sensor_chan
{
struct ntc_thermistor_data *data = dev->data;
const struct ntc_thermistor_config *cfg = dev->config;
uint32_t ohm, max_adc;
uint32_t ohm;
int32_t temp;
switch (chan) {
case SENSOR_CHAN_AMBIENT_TEMP:
max_adc = (1 << (cfg->adc_channel.resolution - 1)) - 1;
ohm = ntc_get_ohm_of_thermistor(&cfg->ntc_cfg, max_adc, data->raw);
ohm = ntc_get_ohm_of_thermistor(&cfg->ntc_cfg, data->sample_val);
temp = ntc_get_temp_mc(&cfg->ntc_cfg.type, ohm);
val->val1 = temp / 1000;
val->val2 = (temp % 1000) * 1000;

View file

@ -56,11 +56,10 @@ int32_t ntc_get_temp_mc(const struct ntc_type *type, unsigned int ohm);
* @brief Calculate the resistance read from NTC Thermistor
*
* @param cfg: NTC Thermistor configuration
* @param max_adc: Max ADC value
* @param raw_adc: Raw ADC value read
* @sample_mv: Measured voltage in mV
*
* @return resistance from raw ADC value
* @return Thermistor resistance
*/
uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, uint32_t max_adc, int16_t raw_adc);
uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, int sample_mv);
#endif /* NTC_THERMISTOR_H */

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <limits.h>
#include <stdlib.h>
#include <zephyr/devicetree.h>
#include "ntc_thermistor.h"
@ -97,17 +98,25 @@ static void ntc_lookup_comp(const struct ntc_type *type, unsigned int ohm, int *
* ntc_get_ohm_of_thermistor() - Calculate the resistance read from NTC Thermistor
*
* @cfg: NTC Thermistor configuration
* @max_adc: Max ADC value
* @raw_adc: Raw ADC value read
* @sample_mv: Measured voltage in mV
*/
uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, uint32_t max_adc, int16_t raw_adc)
uint32_t ntc_get_ohm_of_thermistor(const struct ntc_config *cfg, int sample_mv)
{
int pullup_mv = cfg->pullup_uv / 1000;
uint32_t ohm;
if (sample_mv <= 0) {
return cfg->connected_positive ? INT_MAX : 0;
}
if (sample_mv >= pullup_mv) {
return cfg->connected_positive ? 0 : INT_MAX;
}
if (cfg->connected_positive) {
ohm = cfg->pulldown_ohm * max_adc / (raw_adc - 1);
ohm = cfg->pulldown_ohm * (pullup_mv - sample_mv) / sample_mv;
} else {
ohm = cfg->pullup_ohm * (raw_adc - 1) / max_adc;
ohm = cfg->pullup_ohm * sample_mv / (pullup_mv - sample_mv);
}
return ohm;