| /* |
| * Copyright (c) 2016 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #define DT_DRV_COMPAT seeed_grove_temperature |
| |
| #include <zephyr/drivers/adc.h> |
| #include <zephyr/device.h> |
| #include <zephyr/devicetree.h> |
| #include <math.h> |
| #include <zephyr/drivers/sensor.h> |
| #include <zephyr/zephyr.h> |
| #include <zephyr/logging/log.h> |
| |
| LOG_MODULE_REGISTER(grove_temp, CONFIG_SENSOR_LOG_LEVEL); |
| |
| /* The effect of gain and reference voltage must cancel. */ |
| #ifdef CONFIG_ADC_NRFX_SAADC |
| #define GROVE_GAIN ADC_GAIN_1_4 |
| #define GROVE_REF ADC_REF_VDD_1_4 |
| #define GROVE_RESOLUTION 12 |
| #else |
| #define GROVE_GAIN ADC_GAIN_1 |
| #define GROVE_REF ADC_REF_VDD_1 |
| #define GROVE_RESOLUTION 12 |
| #endif |
| |
| struct gts_data { |
| struct adc_channel_cfg ch_cfg; |
| uint16_t raw; |
| }; |
| |
| struct gts_config { |
| const struct device *adc; |
| int16_t b_const; |
| uint8_t adc_channel; |
| }; |
| |
| static struct adc_sequence_options options = { |
| .extra_samplings = 0, |
| .interval_us = 15, |
| }; |
| |
| static struct adc_sequence adc_table = { |
| .options = &options, |
| }; |
| |
| static int gts_sample_fetch(const struct device *dev, |
| enum sensor_channel chan) |
| { |
| const struct gts_config *cfg = dev->config; |
| |
| return adc_read(cfg->adc, &adc_table); |
| } |
| |
| static int gts_channel_get(const struct device *dev, |
| enum sensor_channel chan, |
| struct sensor_value *val) |
| { |
| struct gts_data *drv_data = dev->data; |
| const struct gts_config *cfg = dev->config; |
| double dval; |
| |
| /* |
| * The formula for converting the analog value to degrees Celsius |
| * is taken from the sensor reference page: |
| * http://www.seeedstudio.com/wiki/Grove_-_Temperature_Sensor |
| */ |
| dval = (1 / (log((BIT(GROVE_RESOLUTION) - 1.0) |
| / drv_data->raw |
| - 1.0) |
| / cfg->b_const |
| + (1 / 298.15))) |
| - 273.15; |
| val->val1 = (int32_t)dval; |
| val->val2 = ((int32_t)(dval * 1000000)) % 1000000; |
| |
| return 0; |
| } |
| |
| static const struct sensor_driver_api gts_api = { |
| .sample_fetch = >s_sample_fetch, |
| .channel_get = >s_channel_get, |
| }; |
| |
| static int gts_init(const struct device *dev) |
| { |
| struct gts_data *drv_data = dev->data; |
| const struct gts_config *cfg = dev->config; |
| |
| if (!device_is_ready(cfg->adc)) { |
| LOG_ERR("ADC device is not ready."); |
| return -EINVAL; |
| } |
| |
| /*Change following parameters according to board if necessary*/ |
| drv_data->ch_cfg = (struct adc_channel_cfg){ |
| .gain = GROVE_GAIN, |
| .reference = GROVE_REF, |
| .acquisition_time = ADC_ACQ_TIME_DEFAULT, |
| .channel_id = cfg->adc_channel, |
| #ifdef CONFIG_ADC_NRFX_SAADC |
| .input_positive = SAADC_CH_PSELP_PSELP_AnalogInput0 + cfg->adc_channel, |
| #endif |
| }; |
| adc_table.buffer = &drv_data->raw; |
| adc_table.buffer_size = sizeof(drv_data->raw); |
| adc_table.resolution = GROVE_RESOLUTION; |
| adc_table.channels = BIT(cfg->adc_channel); |
| |
| adc_channel_setup(cfg->adc, &drv_data->ch_cfg); |
| |
| return 0; |
| } |
| |
| #define GTS_DEFINE(inst) \ |
| static struct gts_data gts_data_##inst; \ |
| \ |
| static const struct gts_config gts_cfg_##inst = { \ |
| .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ |
| .b_const = (IS_ENABLED(DT_INST_PROP(inst, v1p0)) \ |
| ? 3975 \ |
| : 4250), \ |
| .adc_channel = DT_INST_IO_CHANNELS_INPUT(inst), \ |
| }; \ |
| \ |
| DEVICE_DT_INST_DEFINE(inst, >s_init, NULL, \ |
| >s_data_##inst, >s_cfg_##inst, POST_KERNEL, \ |
| CONFIG_SENSOR_INIT_PRIORITY, >s_api); \ |
| |
| DT_INST_FOREACH_STATUS_OKAY(GTS_DEFINE) |