sensors: grove_light: convert to devicetree bindings

Replace Kconfig configuration data with devicetree bindings using
(ADC) io channels.  Rework the sample to document expectations about
the relationship between the reference voltage and the divider input
voltage, and update the sensor configuration to support Nordic SAADC.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2019-12-27 07:03:37 -06:00 committed by Kumar Gala
parent bc60245787
commit a8d15c1279
8 changed files with 86 additions and 58 deletions

View file

@ -10,28 +10,6 @@ config GROVE_LIGHT_SENSOR
Setting this value will enable driver support for the Grove Light
Sensor.
if GROVE_LIGHT_SENSOR
config GROVE_LIGHT_SENSOR_NAME
string "Driver name"
default "GROVE_LIGHT_SENSOR"
help
Specify the device name with which the sensor is identified.
config GROVE_LIGHT_SENSOR_ADC_DEV_NAME
string "ADC where Grove Light Sensor is connected"
default "ADC_0"
help
Specify the device name of the ADC to which the Grove Light Sensor
is connected.
config GROVE_LIGHT_SENSOR_ADC_CHANNEL
int "ADC channel used by Grove Light Sensor"
default 10
help
Specify the channel of the ADC to which the Grove Light Sensor is
connected.
endif
config GROVE_TEMPERATURE_SENSOR
bool "Enable the Seeed Grove Temperature Sensor"
depends on ADC && !MINIMAL_LIBC

View file

@ -13,10 +13,27 @@
LOG_MODULE_REGISTER(grove_light, 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 gls_data {
struct device *adc;
struct adc_channel_cfg ch10_cfg;
u8_t adc_buffer[4];
struct adc_channel_cfg ch_cfg;
u16_t raw;
};
struct gls_config {
const char *adc_label;
u8_t adc_channel;
};
static struct adc_sequence_options options = {
@ -28,8 +45,6 @@ static struct adc_sequence adc_table = {
.options = &options,
};
#define ADC_RESOLUTION 12
static int gls_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct gls_data *drv_data = dev->driver_data;
@ -42,20 +57,15 @@ static int gls_channel_get(struct device *dev,
struct sensor_value *val)
{
struct gls_data *drv_data = dev->driver_data;
u16_t analog_val;
u16_t analog_val = drv_data->raw;
double ldr_val, dval;
/* rescale sample from 12bit (Zephyr) to 10bit (Grove) */
analog_val = ((u16_t)drv_data->adc_buffer[1] << 8) |
drv_data->adc_buffer[0];
analog_val = analog_val >> 2;
/*
* The formula for converting the analog value to lux is taken from
* the UPM project:
* https://github.com/intel-iot-devkit/upm/blob/master/src/grove/grove.cxx#L161
*/
ldr_val = (1023.0 - analog_val) * 10.0 / analog_val;
ldr_val = (BIT(GROVE_RESOLUTION) - 1.0 - analog_val) * 10.0 / analog_val;
dval = 10000.0 / pow(ldr_val * 15.0, 4.0/3.0);
val->val1 = (s32_t)dval;
@ -72,32 +82,41 @@ static const struct sensor_driver_api gls_api = {
static int gls_init(struct device *dev)
{
struct gls_data *drv_data = dev->driver_data;
const struct gls_config *cfg = dev->config->config_info;
drv_data->adc = device_get_binding(cfg->adc_label);
drv_data->adc =
device_get_binding(CONFIG_GROVE_LIGHT_SENSOR_ADC_DEV_NAME);
if (drv_data->adc == NULL) {
LOG_ERR("Failed to get ADC device.");
return -EINVAL;
}
/*Change following parameters according to board if necessary*/
drv_data->ch10_cfg.channel_id = CONFIG_GROVE_LIGHT_SENSOR_ADC_CHANNEL;
drv_data->ch10_cfg.differential = false;
drv_data->ch10_cfg.gain = ADC_GAIN_1,
drv_data->ch10_cfg.reference = ADC_REF_INTERNAL;
drv_data->ch10_cfg.acquisition_time = ADC_ACQ_TIME_DEFAULT;
adc_table.buffer = drv_data->adc_buffer;
adc_table.channels = BIT(CONFIG_GROVE_LIGHT_SENSOR_ADC_CHANNEL);
adc_table.resolution = ADC_RESOLUTION;
adc_table.buffer_size = 4;
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(drv_data->adc, &drv_data->ch10_cfg);
adc_channel_setup(drv_data->adc, &drv_data->ch_cfg);
return 0;
}
static struct gls_data gls_data;
static const struct gls_config gls_cfg = {
.adc_label = DT_INST_0_GROVE_LIGHT_IO_CHANNELS_CONTROLLER,
.adc_channel = DT_INST_0_GROVE_LIGHT_IO_CHANNELS_INPUT,
};
DEVICE_AND_API_INIT(gls_dev, CONFIG_GROVE_LIGHT_SENSOR_NAME, &gls_init,
&gls_data, NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
DEVICE_AND_API_INIT(gls_dev, DT_INST_0_GROVE_LIGHT_LABEL, &gls_init,
&gls_data, &gls_cfg, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
&gls_api);

View file

@ -0,0 +1,15 @@
# Copyright (c) 2019 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
description: Grove Photo-Resistor Light Sensor
compatible: "grove,light"
include: base.yaml
properties:
io-channels:
type: phandle-array
required: true
description: |
IO channel associated with the resistor voltage divider.

View file

@ -0,0 +1,13 @@
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
ntc {
label = "GLS";
compatible = "grove,light";
io-channels = <&arduino_adc 0>;
};
};

View file

@ -1,5 +1,5 @@
CONFIG_ADC=y
CONFIG_GROVE_LIGHT_SENSOR=y
CONFIG_SENSOR=y
CONFIG_GROVE_LIGHT_SENSOR=y
CONFIG_NEWLIB_LIBC=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

View file

@ -3,5 +3,6 @@ sample:
tests:
sample.sensor.grove_light:
tags: drivers sensor grove light
platform_whitelist: nrf52_pca10040
harness: grove
depends_on: adc

View file

@ -6,7 +6,6 @@
#include <zephyr.h>
#include <init.h>
#include <sys/printk.h>
#include <stdio.h>
#include <drivers/sensor.h>
@ -14,10 +13,10 @@
void main(void)
{
struct device *dev = device_get_binding(CONFIG_GROVE_LIGHT_SENSOR_NAME);
struct device *dev = device_get_binding(DT_INST_0_GROVE_LIGHT_LABEL);
if (dev == NULL) {
printk("device not found. aborting test.\n");
printf("device not found. aborting test.\n");
return;
}
while (1) {
@ -26,17 +25,14 @@ void main(void)
read = sensor_sample_fetch(dev);
if (read) {
printk("sample fetch error %d\n", read);
printf("sample fetch error %d\n", read);
continue;
}
sensor_channel_get(dev, SENSOR_CHAN_LIGHT, &lux);
#ifdef CONFIG_NEWLIB_LIBC_FLOAT_PRINTF
printk("lux: %d\n", sensor_value_to_double(&lux));
#else
printk("lux: %d\n", lux.val1);
#endif
printf("lux: %f\n", sensor_value_to_double(&lux));
k_sleep(SLEEP_TIME);
}
}

View file

@ -402,6 +402,12 @@
#define DT_INST_0_INVENSENSE_MPU6050_INT_GPIOS_PIN 0
#endif
#ifndef DT_INST_0_GROVE_LIGHT_LABEL
#define DT_INST_0_GROVE_LIGHT_LABEL ""
#define DT_INST_0_GROVE_LIGHT_IO_CHANNELS_CONTROLLER ""
#define DT_INST_0_GROVE_LIGHT_IO_CHANNELS_INPUT 0
#endif
#ifndef DT_INST_0_GROVE_TEMPERATURE_LABEL
#define DT_INST_0_GROVE_TEMPERATURE_LABEL ""
#define DT_INST_0_GROVE_TEMPERATURE_IO_CHANNELS_CONTROLLER ""