zephyr/drivers/sensor/everlight/als_pt19/als_pt19.c
Dipak Shetty eb0050f7c9 drivers: sensor: add everlight light sensor
Adds driver for Everlight ALS-PT19 Ambient Light Sensor.

Signed-off-by: Dipak Shetty <shetty.dipak@gmx.com>
2025-04-01 22:12:13 +02:00

132 lines
3.6 KiB
C

/*
* Copyright (c) 2025 Dipak Shetty <shetty.dipak@gmx.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT everlight_als_pt19
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ALS_PT19, CONFIG_SENSOR_LOG_LEVEL);
struct als_pt19_data {
struct adc_sequence sequence;
uint16_t raw;
};
struct als_pt19_config {
struct adc_dt_spec adc;
uint32_t load_resistor;
};
static int als_pt19_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
const struct als_pt19_config *config = dev->config;
struct als_pt19_data *data = dev->data;
int ret;
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_LIGHT) {
LOG_ERR("Unsupported sensor channel");
return -ENOTSUP;
}
ret = adc_read_dt(&config->adc, &data->sequence);
if (ret != 0) {
LOG_ERR("adc_read: %d", ret);
}
return ret;
}
static int als_pt19_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
const struct als_pt19_config *config = dev->config;
struct als_pt19_data *data = dev->data;
int32_t raw_val = data->raw;
int ret;
__ASSERT_NO_MSG(val != NULL);
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_LIGHT) {
LOG_ERR("Unsupported sensor channel");
return -ENOTSUP;
}
ret = adc_raw_to_millivolts_dt(&config->adc, &raw_val);
if (ret != 0) {
LOG_ERR("to_mv: %d", ret);
return ret;
}
LOG_DBG("Raw voltage: %d mV", raw_val);
/* Calculate current through the load resistor (in microamps) */
const int32_t current_ua = (raw_val * 1000) / config->load_resistor;
/* Convert current to Lux (200µA = 1000 Lux) */
const int32_t lux = (current_ua * 1000) / 200;
/* Convert to sensor_value format */
val->val1 = lux;
val->val2 = 0;
LOG_DBG("ADC: %d/%dmV, Current: %duA, Lux: %d", raw_val, config->adc.vref_mv, current_ua,
val->val1);
return 0;
}
static DEVICE_API(sensor, als_pt19_driver_api) = {
.sample_fetch = als_pt19_sample_fetch,
.channel_get = als_pt19_channel_get,
};
static int als_pt19_init(const struct device *dev)
{
const struct als_pt19_config *config = dev->config;
struct als_pt19_data *data = dev->data;
int ret;
if (!adc_is_ready_dt(&config->adc)) {
LOG_ERR("ADC is not ready");
return -ENODEV;
}
ret = adc_channel_setup_dt(&config->adc);
if (ret != 0) {
LOG_ERR("ADC channel setup: %d", ret);
return ret;
}
ret = adc_sequence_init_dt(&config->adc, &data->sequence);
if (ret != 0) {
LOG_ERR("ADC sequence: %d", ret);
return ret;
}
data->sequence.buffer = &data->raw;
data->sequence.buffer_size = sizeof(data->raw);
return 0;
}
#define ALS_PT19_INST(inst) \
static struct als_pt19_data als_pt19_data_##inst; \
\
static const struct als_pt19_config als_pt19_cfg_##inst = { \
.adc = ADC_DT_SPEC_INST_GET(inst), \
.load_resistor = DT_INST_PROP(inst, load_resistor)}; \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, &als_pt19_init, NULL, &als_pt19_data_##inst, \
&als_pt19_cfg_##inst, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &als_pt19_driver_api);
DT_INST_FOREACH_STATUS_OKAY(ALS_PT19_INST)