From 503abb4415fbd538922051dadc4338bceab1ece3 Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Tue, 12 Jan 2016 01:04:21 +0100 Subject: [PATCH] ADC wrapper for the Zoul-based platforms, allows to add analogue sensors over the existing adc interface --- examples/zolertia/zoul/Makefile | 4 +- .../zolertia/zoul/test-grove-light-sensor.c | 91 ++++++++ .../zoul/test-grove-loudness-sensor.c | 110 +++++++++ examples/zolertia/zoul/test-rotation-sensor.c | 110 +++++++++ examples/zolertia/zoul/zoul-demo.c | 1 + platform/zoul/dev/adc-sensors.c | 37 ++- platform/zoul/dev/adc-sensors.h | 34 ++- platform/zoul/dev/adc-wrapper.c | 215 ++++++++++++++++++ platform/zoul/dev/adc-wrapper.h | 85 +++++++ platform/zoul/dev/zoul-sensors.c | 3 +- platform/zoul/dev/zoul-sensors.h | 1 - platform/zoul/firefly/board.h | 3 + platform/zoul/remote/board.h | 3 + 13 files changed, 678 insertions(+), 19 deletions(-) create mode 100644 examples/zolertia/zoul/test-grove-light-sensor.c create mode 100644 examples/zolertia/zoul/test-grove-loudness-sensor.c create mode 100644 examples/zolertia/zoul/test-rotation-sensor.c create mode 100644 platform/zoul/dev/adc-wrapper.c create mode 100644 platform/zoul/dev/adc-wrapper.h diff --git a/examples/zolertia/zoul/Makefile b/examples/zolertia/zoul/Makefile index dcda7321d..8c1422549 100644 --- a/examples/zolertia/zoul/Makefile +++ b/examples/zolertia/zoul/Makefile @@ -1,7 +1,9 @@ DEFINES+=PROJECT_CONF_H=\"project-conf.h\" CONTIKI_PROJECT = zoul-demo test-tsl2563 test-sht25 test-pwm test-power-mgmt -CONTIKI_PROJECT += test-bmp085 test-motion +CONTIKI_PROJECT += test-bmp085 test-motion test-rotation-sensor +CONTIKI_PROJECT += test-grove-light-sensor test-grove-loudness-sensor CONTIKI_TARGET_SOURCEFILES += tsl2563.c sht25.c bmp085.c motion-sensor.c +CONTIKI_TARGET_SOURCEFILES += adc-wrapper.c all: $(CONTIKI_PROJECT) diff --git a/examples/zolertia/zoul/test-grove-light-sensor.c b/examples/zolertia/zoul/test-grove-light-sensor.c new file mode 100644 index 000000000..c81f7b931 --- /dev/null +++ b/examples/zolertia/zoul/test-grove-light-sensor.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-examples + * @{ + * + * \defgroup zoul-grove-light-sensor-test Grove's LDR sensor v.1.0 test + * + * Demonstrates the operation of the Grove's analog LDR + * @{ + * + * \file + * Grove's LDR sensor example using the ADC wrapper + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/leds.h" +#include "dev/adc-wrapper.h" +/*---------------------------------------------------------------------------*/ +#define ADC_PIN 5 +#define SENSOR_READ_INTERVAL (CLOCK_SECOND / 4) +/*---------------------------------------------------------------------------*/ +PROCESS(remote_grove_light_process, "Grove LDR test process"); +AUTOSTART_PROCESSES(&remote_grove_light_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(remote_grove_light_process, ev, data) +{ + PROCESS_BEGIN(); + + uint16_t ldr; + + /* Use pin number not mask, for example if using the PA5 pin then use 5 */ + adc_wrapper.configure(ANALOG_GROVE_LIGHT, 5); + + /* And periodically poll the sensor */ + + while(1) { + etimer_set(&et, SENSOR_READ_INTERVAL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + ldr = adc_wrapper.value(ANALOG_GROVE_LIGHT); + + if(ldr != ADC_WRAPPER_ERROR) { + printf("LDR (resistor) = %u\n", ldr); + } else { + printf("Error, enable the DEBUG flag in adc-wrapper.c for info\n"); + PROCESS_EXIT(); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ + diff --git a/examples/zolertia/zoul/test-grove-loudness-sensor.c b/examples/zolertia/zoul/test-grove-loudness-sensor.c new file mode 100644 index 000000000..85907e3e3 --- /dev/null +++ b/examples/zolertia/zoul/test-grove-loudness-sensor.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-examples + * @{ + * + * \defgroup zoul-grove-loudness-sensor-test Grove's loudness sensor + * + * Demonstrates the operation of the Grove's analog loudness sensor + * @{ + * + * \file + * Grove's loudness sensor example using the ADC wrapper + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/leds.h" +#include "dev/adc-wrapper.h" +/*---------------------------------------------------------------------------*/ +#define ADC_PIN 5 +#define SENSOR_READ_INTERVAL (CLOCK_SECOND / 8) +/*---------------------------------------------------------------------------*/ +PROCESS(remote_grove_loudness_process, "Grove loudness test process"); +AUTOSTART_PROCESSES(&remote_grove_loudness_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(remote_grove_loudness_process, ev, data) +{ + PROCESS_BEGIN(); + + uint16_t loudness; + + /* Use pin number not mask, for example if using the PA5 pin then use 5 */ + adc_wrapper.configure(ANALOG_GROVE_LOUDNESS, ADC_PIN); + + /* And periodically poll the sensor */ + + while(1) { + etimer_set(&et, SENSOR_READ_INTERVAL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + loudness = adc_wrapper.value(ANALOG_GROVE_LOUDNESS); + + if(loudness != ADC_WRAPPER_ERROR) { + printf("%u\n", loudness); + } else { + printf("Error, enable the DEBUG flag in adc-wrapper.c for info\n"); + PROCESS_EXIT(); + } + + if(loudness < 100) { + leds_off(LEDS_ALL); + } + + if((loudness >= 100) && (loudness < 500)) { + leds_on(LEDS_BLUE); + leds_off(LEDS_GREEN | LEDS_RED); + } + + if((loudness >= 500) && (loudness < 1000)) { + leds_on(LEDS_GREEN); + leds_off(LEDS_BLUE | LEDS_RED); + } + + if(loudness >= 1000) { + leds_on(LEDS_RED); + leds_off(LEDS_BLUE | LEDS_GREEN); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ + diff --git a/examples/zolertia/zoul/test-rotation-sensor.c b/examples/zolertia/zoul/test-rotation-sensor.c new file mode 100644 index 000000000..220d86fca --- /dev/null +++ b/examples/zolertia/zoul/test-rotation-sensor.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-examples + * @{ + * + * \defgroup zoul-rotation-sensor-test Phidget 1109 rotation sensor example + * + * Demonstrates the operation of the analog phidget 1109 rotation sensor + * @{ + * + * \file + * Phidget analog rotation sensor example using the ADC wrapper + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/leds.h" +#include "dev/adc-wrapper.h" +/*---------------------------------------------------------------------------*/ +#define ADC_PIN 5 +#define SENSOR_READ_INTERVAL (CLOCK_SECOND / 4) +/*---------------------------------------------------------------------------*/ +PROCESS(remote_rotation_process, "Phidget rotation test process"); +AUTOSTART_PROCESSES(&remote_rotation_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(remote_rotation_process, ev, data) +{ + PROCESS_BEGIN(); + + uint16_t rotation; + + /* Use pin number not mask, for example if using the PA5 pin then use 5 */ + adc_wrapper.configure(ANALOG_PHIDGET_ROTATION_1109, 5); + + /* And periodically poll the sensor */ + + while(1) { + etimer_set(&et, SENSOR_READ_INTERVAL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + rotation = adc_wrapper.value(ANALOG_PHIDGET_ROTATION_1109); + + if(rotation != ADC_WRAPPER_ERROR) { + printf("Rotation = %u\n", rotation); + } else { + printf("Error, enable the DEBUG flag in adc-wrapper.c for info\n"); + PROCESS_EXIT(); + } + + if(rotation <= 45) { + leds_off(LEDS_ALL); + } + + if((rotation > 45) && (rotation < 150)) { + leds_on(LEDS_GREEN); + leds_off(LEDS_BLUE | LEDS_RED); + } + + if((rotation > 150) && (rotation < 250)) { + leds_on(LEDS_RED | LEDS_GREEN); + leds_off(LEDS_BLUE); + } + + if(rotation >= 250) { + leds_on(LEDS_RED); + leds_off(LEDS_BLUE | LEDS_GREEN); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ + diff --git a/examples/zolertia/zoul/zoul-demo.c b/examples/zolertia/zoul/zoul-demo.c index ff31d5ef9..25e49235f 100644 --- a/examples/zolertia/zoul/zoul-demo.c +++ b/examples/zolertia/zoul/zoul-demo.c @@ -69,6 +69,7 @@ #include "dev/leds.h" #include "dev/uart.h" #include "dev/button-sensor.h" +#include "dev/adc-sensors.h" #include "dev/zoul-sensors.h" #include "dev/watchdog.h" #include "dev/serial-line.h" diff --git a/platform/zoul/dev/adc-sensors.c b/platform/zoul/dev/adc-sensors.c index 4c88ed92f..da1ca844d 100644 --- a/platform/zoul/dev/adc-sensors.c +++ b/platform/zoul/dev/adc-sensors.c @@ -45,9 +45,16 @@ #include "dev/adc.h" #include "adc-sensors.h" #include "zoul-sensors.h" - +#include #include /*---------------------------------------------------------------------------*/ +#define DEBUG 1 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ static uint8_t decimation_rate; static uint8_t enabled_channels; /*---------------------------------------------------------------------------*/ @@ -80,6 +87,12 @@ get_channel_pin(int type) if((ZOUL_SENSORS_ADC3) && (type == ZOUL_SENSORS_ADC3)) { return SOC_ADC_ADCCON_CH_AIN0 + ADC_SENSORS_ADC3_PIN; } + if((ZOUL_SENSORS_ADC4) && (type == ZOUL_SENSORS_ADC4)) { + return SOC_ADC_ADCCON_CH_AIN0 + ADC_SENSORS_ADC4_PIN; + } + if((ZOUL_SENSORS_ADC5) && (type == ZOUL_SENSORS_ADC5)) { + return SOC_ADC_ADCCON_CH_AIN0 + ADC_SENSORS_ADC5_PIN; + } return ZOUL_SENSORS_ERROR; } /*---------------------------------------------------------------------------*/ @@ -90,16 +103,24 @@ value(int type) int16_t res; if(!(type & enabled_channels)) { + PRINTF("ADC: channel not enabled\n"); return ZOUL_SENSORS_ERROR; } channel = get_channel_pin(type); if(channel == ZOUL_SENSORS_ERROR) { + PRINTF("ADC: pin not active\n"); return ZOUL_SENSORS_ERROR; } - res = adc_get(channel, SOC_ADC_ADCCON_REF_AVDD5, decimation_rate); + res = adc_get(channel, ADC_SENSORS_REFERENCE, decimation_rate); + + /* Only allow negative values if using differential input */ + if((ADC_SENSORS_REFERENCE != SOC_ADC_ADCCON_REF_EXT_DIFF) && (res < 0)) { + res = 0; + } + return res; } /*---------------------------------------------------------------------------*/ @@ -111,12 +132,14 @@ configure(int type, int value) /* This should filter out disabled sensors as its value should be zero */ if((value < ZOUL_SENSORS_ADC_MIN) || (value > ZOUL_SENSORS_ADC_ALL)) { + PRINTF("ADC: invalid adc pin mask (0x%02X)\n", value); return ZOUL_SENSORS_ERROR; } if((value != ZOUL_SENSORS_ADC1) && (value != ZOUL_SENSORS_ADC2) && - (value != ZOUL_SENSORS_ADC3) && (value != ZOUL_SENSORS_ADC12) && - (value != ZOUL_SENSORS_ADC13) && (value != ZOUL_SENSORS_ADC23)) { + (value != ZOUL_SENSORS_ADC3) && (value != ZOUL_SENSORS_ADC4) && + (value != ZOUL_SENSORS_ADC5)) { + PRINTF("ADC: invalid adc pin mask\n"); return ZOUL_SENSORS_ERROR; } @@ -132,6 +155,12 @@ configure(int type, int value) if(value & ZOUL_SENSORS_ADC3) { ioc_set_over(GPIO_A_NUM, ADC_SENSORS_ADC3_PIN, IOC_OVERRIDE_ANA); } + if(value & ZOUL_SENSORS_ADC4) { + ioc_set_over(GPIO_A_NUM, ADC_SENSORS_ADC4_PIN, IOC_OVERRIDE_ANA); + } + if(value & ZOUL_SENSORS_ADC5) { + ioc_set_over(GPIO_A_NUM, ADC_SENSORS_ADC5_PIN, IOC_OVERRIDE_ANA); + } adc_init(); set_decimation_rate(SOC_ADC_ADCCON_DIV_512); enabled_channels = value; diff --git a/platform/zoul/dev/adc-sensors.h b/platform/zoul/dev/adc-sensors.h index 848af9dae..1a10c8d39 100644 --- a/platform/zoul/dev/adc-sensors.h +++ b/platform/zoul/dev/adc-sensors.h @@ -82,12 +82,19 @@ #define ADC_SENSORS "ADC sensors" #define ADC_SENSORS_PORT_BASE GPIO_PORT_TO_BASE(ADC_SENSORS_PORT) +#ifdef ADC_SENSORS_CONF_REFERENCE +#define ADC_SENSORS_REFERENCE ADC_SENSORS_CONF_REFERENCE +#else +#define ADC_SENSORS_REFERENCE SOC_ADC_ADCCON_REF_AVDD5 +#endif + /* * PA0-PA3 are hardcoded to UART0 and the user button for most Zolertia - * platforms, the following assumes PA0 shall not be used as ADC input, else + * platforms, the following assumes PA0-1 shall not be used as ADC input, else * re-write the below definitions */ -#define ZOUL_SENSORS_ADC_MIN 2 +#define ZOUL_SENSORS_ADC_MIN 2 /**< PA1 pin mask */ + /* ADC phidget-like connector ADC1 */ #if ADC_SENSORS_ADC1_PIN >= ZOUL_SENSORS_ADC_MIN #define ZOUL_SENSORS_ADC1 GPIO_PIN_MASK(ADC_SENSORS_ADC1_PIN) @@ -106,20 +113,25 @@ #else #define ZOUL_SENSORS_ADC3 0 #endif - +/* ADC phidget-like connector ADC4 */ +#if ADC_SENSORS_ADC4_PIN >= ZOUL_SENSORS_ADC_MIN +#define ZOUL_SENSORS_ADC4 GPIO_PIN_MASK(ADC_SENSORS_ADC4_PIN) +#else +#define ZOUL_SENSORS_ADC4 0 +#endif +/* ADC phidget-like connector ADC5 */ +#if ADC_SENSORS_ADC5_PIN >= ZOUL_SENSORS_ADC_MIN +#define ZOUL_SENSORS_ADC5 GPIO_PIN_MASK(ADC_SENSORS_ADC5_PIN) +#else +#define ZOUL_SENSORS_ADC5 0 +#endif /* * This is safe as the disabled sensors should have a zero value thus not * affecting the mask operations */ - -/* Enable all channels */ #define ZOUL_SENSORS_ADC_ALL (ZOUL_SENSORS_ADC1 + ZOUL_SENSORS_ADC2 + \ - ZOUL_SENSORS_ADC3) -/* Other allowed combinations */ -#define ZOUL_SENSORS_ADC12 (ZOUL_SENSORS_ADC1 + ZOUL_SENSORS_ADC2) -#define ZOUL_SENSORS_ADC13 (ZOUL_SENSORS_ADC1 + ZOUL_SENSORS_ADC3) -#define ZOUL_SENSORS_ADC23 (ZOUL_SENSORS_ADC2 + ZOUL_SENSORS_ADC3) - + ZOUL_SENSORS_ADC3 + ZOUL_SENSORS_ADC4 + \ + ZOUL_SENSORS_ADC5) /** @} */ /*---------------------------------------------------------------------------*/ extern const struct sensors_sensor adc_sensors; diff --git a/platform/zoul/dev/adc-wrapper.c b/platform/zoul/dev/adc-wrapper.c new file mode 100644 index 000000000..02cb5f77c --- /dev/null +++ b/platform/zoul/dev/adc-wrapper.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-adc-wrapper + * @{ + * + * \file + * Generic driver for the Zoul ADC wrapper for analogue sensors + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/clock.h" +#include "dev/ioc.h" +#include "dev/gpio.h" +#include "dev/adc.h" +#include "adc-sensors.h" +#include "adc-wrapper.h" +#include "zoul-sensors.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 1 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +typedef struct { + int type; + uint8_t pin_mask; + uint8_t vdd3; +} adc_info_t; + +typedef struct { + uint8_t sensors_num; + uint8_t sensors_ports; + adc_info_t sensor[ADC_SENSORS_MAX]; +} adc_wrapper_t; + +static adc_wrapper_t sensors; +/*---------------------------------------------------------------------------*/ +static uint16_t +convert_to_value(uint8_t index) +{ + uint32_t value; + value = adc_sensors.value(sensors.sensor[index].pin_mask); + + if(value == ZOUL_SENSORS_ERROR) { + PRINTF("ADC wrapper: failed retrieving data\n"); + return ADC_WRAPPER_ERROR; + } + + /* Default voltage divisor relation is 5/3 aprox, change at adc_wrapper.h, + * calculations below assume a decimation rate of 512 (12 bits ENOB) and + * AVVD5 voltage reference of 3.3V + */ + + if(!sensors.sensor[index].vdd3) { + value *= ADC_WRAPPER_EXTERNAL_VREF; + value /= ADC_WRAPPER_EXTERNAL_VREF_CROSSVAL; + } + + switch(sensors.sensor[index].type) { + case ANALOG_GROVE_LIGHT: + /* Light dependant resistor (LDR) resistance value*/ + value = (10230 - (value * 10)) / value; + /* TODO: With the resistance we could calculate the lux as 63*R^(-0.7) */ + return (uint16_t)value; + + case ANALOG_GROVE_LOUDNESS: + /* Based on the LM2904 amplifier (blue version with potentiometer) */ + return (uint16_t)value; + + case ANALOG_PHIDGET_ROTATION_1109: + /* Linear sensor with 0-300ยบ, 300/33000 = 0.00909 */ + value *= 909; + value /= 100000; + return (uint16_t)value; + + default: + return ADC_WRAPPER_ERROR; + } + + return ADC_WRAPPER_ERROR; +} +/*---------------------------------------------------------------------------*/ +static uint8_t +is_sensor_in_list(int type) +{ + uint8_t i; + + for(i = 0; i <= sensors.sensors_num; i++) { + if(sensors.sensor[i].type == type) { + return i + 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint8_t index; + uint16_t sensor_value; + + index = is_sensor_in_list(type); + + if(!index) { + PRINTF("ADC wrapper: sensor not registered\n"); + return ADC_WRAPPER_SUCCESS; + } + + /* Restore index value after the check */ + index -= 1; + sensor_value = convert_to_value(index); + + return sensor_value; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + uint8_t pin_mask = GPIO_PIN_MASK(value); + + if((type != ANALOG_GROVE_LIGHT) && (type != ANALOG_PHIDGET_ROTATION_1109) && + (type != ANALOG_GROVE_LOUDNESS)) { + PRINTF("ADC wrapper: sensor not supported, check adc_wrapper.h header\n"); + return ADC_WRAPPER_ERROR; + } + + if(sensors.sensors_num >= ADC_SENSORS_MAX) { + PRINTF("ADC wrapper: all adc channels available have been assigned\n"); + return ADC_WRAPPER_ERROR; + } + + if((value < 0x01) || (value > 0x07) || (value == BUTTON_USER_PIN)) { + PRINTF("ADC wrapper: invalid pin value, (PA0-PA1, PA3) are reserved\n"); + return ADC_WRAPPER_ERROR; + } + + if(sensors.sensors_ports & pin_mask) { + PRINTF("ADC wrapper: a sensor has been already assigned to this pin\n"); + return ADC_WRAPPER_ERROR; + } + + switch(type) { + /* V+3.3 sensors */ + case ANALOG_GROVE_LIGHT: + case ANALOG_GROVE_LOUDNESS: + case ANALOG_PHIDGET_ROTATION_1109: + if(adc_sensors.configure(SENSORS_HW_INIT, pin_mask) == + ZOUL_SENSORS_ERROR) { + return ADC_WRAPPER_ERROR; + } + sensors.sensor[sensors.sensors_num].type = type; + sensors.sensor[sensors.sensors_num].pin_mask = pin_mask; + sensors.sensor[sensors.sensors_num].vdd3 = 1; + break; + + default: + return ADC_WRAPPER_ERROR; + } + + PRINTF("ADC wrapper: type %u mask 0x%02X vdd3 %u\n", + sensors.sensor[sensors.sensors_num].type, + sensors.sensor[sensors.sensors_num].pin_mask, + sensors.sensor[sensors.sensors_num].vdd3); + + sensors.sensors_num++; + sensors.sensors_ports |= pin_mask; + + return ADC_WRAPPER_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adc_wrapper, ADC_WRAPPER, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ + diff --git a/platform/zoul/dev/adc-wrapper.h b/platform/zoul/dev/adc-wrapper.h new file mode 100644 index 000000000..5a9e63b19 --- /dev/null +++ b/platform/zoul/dev/adc-wrapper.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-sensors + * @{ + * + * \defgroup zoul-adc-wrapper Zoul adc wrapper to use analogue sensors + * + * The ADC wrapper allows to use analogue sensors on top of the ADC interface, + * obscuring the ADC configuration and required calculations to obtain actual + * sensor values. The driver allows to reuse the adc-wrapper implementation and + * add sensors easily, without duplicating code, providing also a simplified + * interface and exposing the available ADC assigned channels by a given + * platform. + * + * To use a given sensor simply use: adc_wrapper.configure(SENSOR_NAME, pin_no), + * where pin_no is a given pin in the PA port, check out the board.h for more + * information on available pins. To read a value just use + * adc_wrapper.value(SENSOR_NAME), the expected result would be the sensor value + * already converted to the sensor variable type, check the adc-wrapper file + * for more information. + * + * @{ + * + * \file + * Header file for the Zoul ADC wrapper + */ +/*---------------------------------------------------------------------------*/ +#ifndef ADC_WRAPPER_H_ +#define ADC_WRAPPER_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +#include "dev/soc-adc.h" +#include "dev/adc-sensors.h" +/*---------------------------------------------------------------------------*/ +#define ADC_WRAPPER_SUCCESS 0x00 +#define ADC_WRAPPER_ERROR (-1) +#define ADC_WRAPPER_EXTERNAL_VREF 5000 +#define ADC_WRAPPER_EXTERNAL_VREF_CROSSVAL 3300 +/*---------------------------------------------------------------------------*/ +#define ANALOG_GROVE_LIGHT 0x01 +#define ANALOG_PHIDGET_ROTATION_1109 0x02 +#define ANALOG_GROVE_LOUDNESS 0x03 +/* -------------------------------------------------------------------------- */ +#define ADC_WRAPPER "ADC wrapper API" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor adc_wrapper; +/*---------------------------------------------------------------------------*/ +#endif /* ADC_WRAPPER_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ + diff --git a/platform/zoul/dev/zoul-sensors.c b/platform/zoul/dev/zoul-sensors.c index 52dac52c3..e6e02c258 100644 --- a/platform/zoul/dev/zoul-sensors.c +++ b/platform/zoul/dev/zoul-sensors.c @@ -43,12 +43,11 @@ #include "contiki.h" #include "dev/cc2538-sensors.h" #include "dev/button-sensor.h" -#include "adc-sensors.h" #include /*---------------------------------------------------------------------------*/ /** \brief Exports global symbols for the sensor API */ -SENSORS(&button_sensor, &vdd3_sensor, &cc2538_temp_sensor, &adc_sensors); +SENSORS(&button_sensor, &vdd3_sensor, &cc2538_temp_sensor); /*---------------------------------------------------------------------------*/ /** * @} diff --git a/platform/zoul/dev/zoul-sensors.h b/platform/zoul/dev/zoul-sensors.h index 476ec41da..5682c972c 100644 --- a/platform/zoul/dev/zoul-sensors.h +++ b/platform/zoul/dev/zoul-sensors.h @@ -49,7 +49,6 @@ #include "lib/sensors.h" #include "dev/cc2538-sensors.h" #include "dev/button-sensor.h" -#include "adc-sensors.h" /*---------------------------------------------------------------------------*/ /** * \name Zoul sensor constants diff --git a/platform/zoul/firefly/board.h b/platform/zoul/firefly/board.h index 07d5eaf10..101a95706 100644 --- a/platform/zoul/firefly/board.h +++ b/platform/zoul/firefly/board.h @@ -202,6 +202,9 @@ #define ADC_SENSORS_ADC1_PIN 5 /**< ADC1 to PA5, 3V3 */ #define ADC_SENSORS_ADC2_PIN 4 /**< ADC2 to PA4, 3V3 */ #define ADC_SENSORS_ADC3_PIN 2 /**< ADC3 to PA2, 3V3 */ +#define ADC_SENSORS_ADC4_PIN 6 /**< ADC4 to PA6, 3V3 */ +#define ADC_SENSORS_ADC5_PIN 7 /**< ADC5 to PA7, 3V3 */ +#define ADC_SENSORS_MAX 5 /**< PA2, PA4, PA5, PA6, PA7 */ /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/platform/zoul/remote/board.h b/platform/zoul/remote/board.h index 563415f25..2ae4d8927 100644 --- a/platform/zoul/remote/board.h +++ b/platform/zoul/remote/board.h @@ -219,6 +219,9 @@ #define ADC_SENSORS_ADC1_PIN 5 /**< ADC1 to PA5, 3V3 */ #define ADC_SENSORS_ADC2_PIN (-1) /**< ADC2 to PA4, 3V3 */ #define ADC_SENSORS_ADC3_PIN 2 /**< ADC3 to PA2, 5V0 */ +#define ADC_SENSORS_ADC4_PIN (-1) /**< Not present */ +#define ADC_SENSORS_ADC5_PIN (-1) /**< Not present */ +#define ADC_SENSORS_MAX 2 /**< PA2, PA5 */ /** @} */ /*---------------------------------------------------------------------------*/ /**