Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/sensor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_subdirectory(microchip)
add_subdirectory(nordic)
add_subdirectory(nuvoton)
add_subdirectory(nxp)
add_subdirectory(omron)
add_subdirectory(pixart)
add_subdirectory(pni)
add_subdirectory(realtek)
Expand Down
1 change: 1 addition & 0 deletions drivers/sensor/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ source "drivers/sensor/microchip/Kconfig"
source "drivers/sensor/nordic/Kconfig"
source "drivers/sensor/nuvoton/Kconfig"
source "drivers/sensor/nxp/Kconfig"
source "drivers/sensor/omron/Kconfig"
source "drivers/sensor/pixart/Kconfig"
source "drivers/sensor/pni/Kconfig"
source "drivers/sensor/realtek/Kconfig"
Expand Down
6 changes: 6 additions & 0 deletions drivers/sensor/omron/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) 2025 Prevas A/S
# SPDX-License-Identifier: Apache-2.0

# zephyr-keep-sorted-start
add_subdirectory_ifdef(CONFIG_D6F d6f)
# zephyr-keep-sorted-stop
6 changes: 6 additions & 0 deletions drivers/sensor/omron/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) 2025 Prevas A/S
# SPDX-License-Identifier: Apache-2.0

# zephyr-keep-sorted-start
source "drivers/sensor/omron/d6f/Kconfig"
# zephyr-keep-sorted-stop
5 changes: 5 additions & 0 deletions drivers/sensor/omron/d6f/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) 2025 Prevas A/S
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_sources(d6f.c)
12 changes: 12 additions & 0 deletions drivers/sensor/omron/d6f/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2025 Prevas A/S
# SPDX-License-Identifier: Apache-2.0

config D6F
bool "D6F mass flow rate sensor"
default y
depends on DT_HAS_OMRON_D6F_P0001_ENABLED || DT_HAS_OMRON_D6F_P0010_ENABLED
select ADC
select FPU if CPU_HAS_FPU
help
Enable Omron D6F mass flow rate sensor driver. The sensor series
outputs an analogue voltage which is read using an ADC.
141 changes: 141 additions & 0 deletions drivers/sensor/omron/d6f/d6f.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright (c) 2025 Prevas A/S
* SPDX-License-Identifier: Apache-2.0
*/

#include <math.h>
#include <stdint.h>

#include <zephyr/drivers/adc.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(d6f, CONFIG_SENSOR_LOG_LEVEL);

struct d6f_config {
const struct adc_dt_spec *adc;
struct adc_sequence sequence;
const float *polynomial_coefficients;
uint8_t polynomial_degree;
};

struct d6f_data {
uint32_t adc_sample;
};

static int d6f_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
const struct d6f_config *config = dev->config;

switch (chan) {
case SENSOR_CHAN_ALL:
case SENSOR_CHAN_FLOW_RATE:
return adc_read_dt(config->adc, &config->sequence);
default:
return -ENOTSUP;
}
}

static int d6f_flow_rate(const struct d6f_config *config, struct d6f_data *data,
struct sensor_value *val)
{
float flow_rate = config->polynomial_coefficients[0];
int32_t uv = data->adc_sample;
float v;
int rc;

rc = adc_raw_to_microvolts_dt(config->adc, &uv);
if (rc != 0) {
return rc;
}
v = uv / 1000000.f;

for (uint8_t i = 1; i <= config->polynomial_degree; ++i) {
flow_rate += config->polynomial_coefficients[i] * powf(v, i);
}

rc = sensor_value_from_float(val, flow_rate);
if (rc != 0) {
return rc;
}

return 0;
}

static int d6f_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
const struct d6f_config *config = dev->config;
struct d6f_data *data = dev->data;

switch (chan) {
case SENSOR_CHAN_FLOW_RATE:
return d6f_flow_rate(config, data, val);
default:
return -ENOTSUP;
}

return 0;
}

static int d6f_init(const struct device *dev)
{
const struct d6f_config *config = dev->config;
int rc;

LOG_DBG("Initializing %s", dev->name);

if (!adc_is_ready_dt(config->adc)) {
LOG_ERR("%s not ready", dev->name);
return -ENODEV;
}

rc = adc_channel_setup_dt(config->adc);
if (rc != 0) {
LOG_ERR("%s setup failed: %d", config->adc->dev->name, rc);
return -ENODEV;
}

return 0;
}

static DEVICE_API(sensor, d6f_driver_api) = {
.sample_fetch = d6f_sample_fetch,
.channel_get = d6f_channel_get,
};

#define D6F_INIT(n, c, p) \
static struct d6f_data d6f_data_##c##_##n; \
static const struct adc_dt_spec d6f_adc_##c##_##n = ADC_DT_SPEC_INST_GET(n); \
static const struct d6f_config d6f_config_##c##_##n = { \
.adc = &d6f_adc_##c##_##n, \
.sequence = \
{ \
.options = NULL, \
.channels = BIT(d6f_adc_##c##_##n.channel_id), \
.buffer = &d6f_data_##c##_##n.adc_sample, \
.buffer_size = sizeof(d6f_data_##c##_##n.adc_sample), \
.resolution = d6f_adc_##c##_##n.resolution, \
.oversampling = d6f_adc_##c##_##n.oversampling, \
.calibrate = false, \
}, \
.polynomial_coefficients = (p), \
.polynomial_degree = (ARRAY_SIZE(p) - 1), \
}; \
\
SENSOR_DEVICE_DT_INST_DEFINE(n, d6f_init, NULL, &d6f_data_##c##_##n, \
&d6f_config_##c##_##n, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &d6f_driver_api);

#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT omron_d6f_p0001
static __maybe_unused const float d6f_p0001_polynomial_coefficients[] = {-0.024864, 0.049944};
DT_INST_FOREACH_STATUS_OKAY_VARGS(D6F_INIT, DT_DRV_COMPAT, d6f_p0001_polynomial_coefficients)

#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT omron_d6f_p0010
static __maybe_unused const float d6f_p0010_polynomial_coefficients[] = {
-0.269996, 1.060657, -1.601495, 1.374705, 1.374705, -0.564312, 0.094003};
DT_INST_FOREACH_STATUS_OKAY_VARGS(D6F_INIT, DT_DRV_COMPAT, d6f_p0010_polynomial_coefficients)
1 change: 1 addition & 0 deletions drivers/sensor/sensor_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static const char *const sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = {
[SENSOR_CHAN_O2] = "o2",
[SENSOR_CHAN_VOC] = "voc",
[SENSOR_CHAN_GAS_RES] = "gas_resistance",
[SENSOR_CHAN_FLOW_RATE] = "flow_rate",
[SENSOR_CHAN_VOLTAGE] = "voltage",
[SENSOR_CHAN_VSHUNT] = "vshunt",
[SENSOR_CHAN_CURRENT] = "current",
Expand Down
14 changes: 14 additions & 0 deletions dts/bindings/sensor/omron,d6f-analog.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2025, Prevas A/S
# SPDX-License-Identifier: Apache-2.0

title: Omron D6F mass flow rate sensor.

include: sensor-device.yaml

properties:
io-channels:
type: phandle-array
required: true
description: |
ADC used to measure the mass flow rate:
<&adc_node channel>
8 changes: 8 additions & 0 deletions dts/bindings/sensor/omron,d6f-p0001.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2025, Prevas A/S
# SPDX-License-Identifier: Apache-2.0

title: Omron D6F-P0001A1 0.1 L/min flow rate sensor.

compatible: "omron,d6f-p0001"

include: omron,d6f-analog.yaml
8 changes: 8 additions & 0 deletions dts/bindings/sensor/omron,d6f-p0010.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2025, Prevas A/S
# SPDX-License-Identifier: Apache-2.0

title: Omron D6F-P0010 1 L/min flow rate sensor.

compatible: "omron,d6f-p0010"

include: omron,d6f-analog.yaml
1 change: 1 addition & 0 deletions dts/bindings/vendor-prefixes.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Device tree binding vendor prefix registry. Keep this list in

Check warning on line 1 in dts/bindings/vendor-prefixes.txt

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

Copyright missing

dts/bindings/vendor-prefixes.txt:1 File has no SPDX-FileCopyrightText header, consider adding one.

Check warning on line 1 in dts/bindings/vendor-prefixes.txt

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

License missing

dts/bindings/vendor-prefixes.txt:1 File has no SPDX-License-Identifier header, consider adding one.

Check warning on line 1 in dts/bindings/vendor-prefixes.txt

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

Copyright missing

dts/bindings/vendor-prefixes.txt:1 File has no SPDX-FileCopyrightText header, consider adding one.

Check warning on line 1 in dts/bindings/vendor-prefixes.txt

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

License missing

dts/bindings/vendor-prefixes.txt:1 File has no SPDX-License-Identifier header, consider adding one.
# alphabetical order.
#
# This isn't an exhaustive list, but you should add new prefixes to it
Expand Down Expand Up @@ -492,6 +492,7 @@
oki Oki Electric Industry Co., Ltd.
olimex OLIMEX Ltd.
olpc One Laptop Per Child
omron OMRON Corporation
onion Onion Corporation
onnn ON Semiconductor Corp.
ontat On Tat Industrial Company
Expand Down
2 changes: 2 additions & 0 deletions include/zephyr/drivers/sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ enum sensor_channel {
SENSOR_CHAN_VOC,
/** Gas sensor resistance in ohms. */
SENSOR_CHAN_GAS_RES,
/** Flow rate in litres per minute */
SENSOR_CHAN_FLOW_RATE,

/** Voltage, in volts **/
SENSOR_CHAN_VOLTAGE,
Expand Down
4 changes: 2 additions & 2 deletions samples/sensor/sensor_shell/pytest/test_sensor_shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_sensor_shell_attr_get(shell: Shell):
assert any(['sensor@0(channel=co2, attr=sampling_frequency)' in line for line in lines]), 'expected response not found'

shell.wait_for_prompt()
lines = shell.exec_command('sensor attr_get sensor@1 54 3')
lines = shell.exec_command('sensor attr_get sensor@1 55 3')
assert any(['sensor@1(channel=gauge_state_of_health, attr=slope_th)' in line for line in lines]), 'expected response not found'

logger.info('response is valid')
Expand All @@ -56,7 +56,7 @@ def test_sensor_shell_attr_set(shell: Shell):
assert any([expected_line in line for line in lines]), 'expected response not found'

shell.wait_for_prompt()
lines = shell.exec_command('sensor attr_set sensor@1 54 3 1')
lines = shell.exec_command('sensor attr_set sensor@1 55 3 1')
expected_line = 'sensor@1 channel=gauge_state_of_health, attr=slope_th set to value=1'
assert any([expected_line in line for line in lines]), 'expected response not found'

Expand Down
12 changes: 12 additions & 0 deletions tests/drivers/build_all/sensor/adc.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ test_murata_ncp15wb473: murata-ncp15wb473 {
connected-positive;
};

test_omron_d6f_p0001: test-omron-d6f-p0001 {
status = "okay";
compatible = "omron,d6f-p0001";
io-channels = <&test_adc 0>;
};

test_omron_d6f_p0010: test-omron-d6f-p0010 {
status = "okay";
compatible = "omron,d6f-p0010";
io-channels = <&test_adc 0>;
};

test_tdk_ntcg163jf103ft1: tdk-ntcg163jf103ft1 {
compatible = "tdk,ntcg163jf103ft1";
io-channels = <&test_adc 0>;
Expand Down
Loading