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:
parent
97e15f2923
commit
883a0c46a8
3 changed files with 19 additions and 12 deletions
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue