drivers: sensors: Add support for ds18s20

Added support for the older ds18s20 inside the (newer) ds18b20.

Signed-off-by: Fredrik Gihl <fgihl@hotmail.com>
This commit is contained in:
Fredrik Gihl 2024-04-27 12:51:40 +02:00 committed by Anas Nashif
commit 2d31d45429
6 changed files with 83 additions and 27 deletions

View file

@ -229,6 +229,7 @@ Drivers and Sensors
* Sensor
* Added TMP114 driver
* Added DS18S20 1-wire temperature sensor driver.
* Serial

View file

@ -6,7 +6,7 @@
config DS18B20
bool "DS18B20 Temperature Sensor"
default y
depends on DT_HAS_MAXIM_DS18B20_ENABLED
depends on DT_HAS_MAXIM_DS18B20_ENABLED || DT_HAS_MAXIM_DS18S20_ENABLED
depends on W1_NET
help
Enable driver for DS18B20 1-Wire temperature sensors.

View file

@ -9,9 +9,11 @@
* A datasheet is available at:
* https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
*
* Driver also support the older DS18S20 1-Wire temperature sensors.
* https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf
*
* Parasite power configuration is not supported by the driver.
*/
#define DT_DRV_COMPAT maxim_ds18b20
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor/w1_sensor.h>
@ -25,15 +27,25 @@ LOG_MODULE_REGISTER(DS18B20, CONFIG_SENSOR_LOG_LEVEL);
static int ds18b20_configure(const struct device *dev);
/* measure wait time for 9-bit, 10-bit, 11-bit, 12-bit resolution respectively */
static const uint16_t measure_wait_ms[4] = { 94, 188, 376, 750 };
static const uint16_t measure_wait_ds18b20_ms[4] = { 94, 188, 376, 750 };
static inline void ds18b20_temperature_from_raw(uint8_t *temp_raw,
/* ds18s20 always needs 750ms */
static const uint16_t measure_wait_ds18s20_ms = { 750 };
static inline void ds18b20_temperature_from_raw(const struct device *dev,
uint8_t *temp_raw,
struct sensor_value *val)
{
int16_t temp = sys_get_le16(temp_raw);
const struct ds18b20_config *cfg = dev->config;
int16_t temp = sys_get_le16 (temp_raw);
val->val1 = temp / 16;
val->val2 = (temp % 16) * 1000000 / 16;
if (cfg->chip == type_ds18s20) {
val->val1 = temp / 2;
val->val2 = (temp % 2) * 5000000;
} else {
val->val1 = temp / 16;
val->val2 = (temp % 16) * 1000000 / 16;
}
}
/*
@ -95,10 +107,20 @@ static void ds18b20_set_resolution(const struct device *dev, uint8_t resolution)
data->scratchpad.config |= DS18B20_RESOLUTION(resolution);
}
static uint16_t measure_wait_ms(const struct device *dev)
{
const struct ds18b20_config *cfg = dev->config;
if (cfg->chip == type_ds18s20) {
return measure_wait_ds18s20_ms;
}
return measure_wait_ds18b20_ms[DS18B20_RESOLUTION_INDEX(cfg->resolution)];
}
static int ds18b20_sample_fetch(const struct device *dev,
enum sensor_channel chan)
{
const struct ds18b20_config *cfg = dev->config;
struct ds18b20_data *data = dev->data;
int status;
@ -118,7 +140,7 @@ static int ds18b20_sample_fetch(const struct device *dev,
LOG_DBG("W1 fetch error");
return status;
}
k_msleep(measure_wait_ms[DS18B20_RESOLUTION_INDEX(cfg->resolution)]);
k_msleep(measure_wait_ms(dev));
return ds18b20_read_scratchpad(dev, &data->scratchpad);
}
@ -132,7 +154,7 @@ static int ds18b20_channel_get(const struct device *dev,
return -ENOTSUP;
}
ds18b20_temperature_from_raw((uint8_t *)&data->scratchpad.temp, val);
ds18b20_temperature_from_raw(dev, (uint8_t *)&data->scratchpad.temp, val);
return 0;
}
@ -159,17 +181,19 @@ static int ds18b20_configure(const struct device *dev)
}
if ((cfg->family != 0) && (cfg->family != data->config.rom.family)) {
LOG_ERR("Found 1-Wire slave is not a DS18B20");
LOG_ERR("Found 1-Wire slave is not a %s", dev->name);
return -EINVAL;
}
/* write default configuration */
ds18b20_set_resolution(dev, cfg->resolution);
ret = ds18b20_write_scratchpad(dev, data->scratchpad);
if (ret < 0) {
return ret;
if (cfg->chip == type_ds18b20) {
ds18b20_set_resolution(dev, cfg->resolution);
ret = ds18b20_write_scratchpad(dev, data->scratchpad);
if (ret < 0) {
return ret;
}
}
LOG_DBG("Init DS18B20: ROM=%016llx\n",
LOG_DBG("Init %s: ROM=%016llx\n", dev->name,
w1_rom_to_uint64(&data->config.rom));
return 0;
@ -214,24 +238,35 @@ static int ds18b20_init(const struct device *dev)
return 0;
}
#define DS18B20_CONFIG_INIT(inst) \
{ \
#define DS18B20_CONFIG_INIT(inst, default_family_code, chip_type) \
{ \
.bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \
.family = (uint8_t)DT_INST_PROP_OR(inst, family_code, 0x28), \
.resolution = DT_INST_PROP(inst, resolution), \
.family = (uint8_t)DT_INST_PROP_OR(inst, family_code, default_family_code), \
.resolution = DT_INST_PROP_OR(inst, resolution, 12), \
.chip = chip_type, \
}
#define DS18B20_DEFINE(inst) \
static struct ds18b20_data ds18b20_data_##inst; \
static const struct ds18b20_config ds18b20_config_##inst = \
DS18B20_CONFIG_INIT(inst); \
#define DS18B20_DEFINE(inst, name, family_code, chip_type) \
static struct ds18b20_data data_##name##_##inst; \
static const struct ds18b20_config config_##name##_##inst = \
DS18B20_CONFIG_INIT(inst, family_code, chip_type); \
SENSOR_DEVICE_DT_INST_DEFINE(inst, \
ds18b20_init, \
NULL, \
&ds18b20_data_##inst, \
&ds18b20_config_##inst, \
&data_##name##_##inst, \
&config_##name##_##inst, \
POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, \
&ds18b20_driver_api);
DT_INST_FOREACH_STATUS_OKAY(DS18B20_DEFINE)
#define DT_DRV_COMPAT maxim_ds18b20
DT_INST_FOREACH_STATUS_OKAY_VARGS(DS18B20_DEFINE, DT_DRV_COMPAT,
DS18B20_FAMILYCODE,
type_ds18b20)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT maxim_ds18s20
DT_INST_FOREACH_STATUS_OKAY_VARGS(DS18B20_DEFINE, DT_DRV_COMPAT,
DS18S20_FAMILYCODE,
type_ds18s20)
#undef DT_DRV_COMPAT

View file

@ -31,6 +31,11 @@
/* convert resolution in bits to array index (for resolution specific elements) */
#define DS18B20_RESOLUTION_INDEX(res) (res - 9)
#define DS18B20_FAMILYCODE 0x28
#define DS18S20_FAMILYCODE 0x10
enum chip_type {type_ds18b20, type_ds18s20};
struct ds18b20_scratchpad {
int16_t temp;
uint8_t alarm_temp_high;
@ -44,6 +49,7 @@ struct ds18b20_config {
const struct device *bus;
uint8_t family;
uint8_t resolution;
enum chip_type chip;
};
struct ds18b20_data {

View file

@ -0,0 +1,8 @@
# Copyright (c) 2024, Fredrik Gihl
# SPDX-License-Identifier: Apache-2.0
description: Maxim 1-Wire ds18s20 temperature sensor
compatible: "maxim,ds18s20"
include: [sensor-device.yaml, w1-slave.yaml]

View file

@ -12,3 +12,9 @@ test_w1_ds18b20: ds18b20 {
resolution = <12>;
status = "okay";
};
test_w1_ds18s20: ds18s20 {
compatible = "maxim,ds18s20";
family-code = <0x10>;
status = "okay";
};