Contiki-NG
adc-sensors.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016, Zolertia - http://www.zolertia.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31/*---------------------------------------------------------------------------*/
32/**
33 * \addtogroup zoul-adc-sensors
34 * @{
35 *
36 * \file
37 * Generic driver for the Zoul ADC wrapper for analogue sensors
38 */
39/*---------------------------------------------------------------------------*/
40#include "contiki.h"
41#include "sys/clock.h"
42#include "dev/ioc.h"
43#include "dev/gpio.h"
44#include "dev/adc.h"
45#include "adc-sensors.h"
46#include "adc-zoul.h"
47#include "zoul-sensors.h"
48#include <stdio.h>
49#include <stdint.h>
50/*---------------------------------------------------------------------------*/
51#define DEBUG 0
52#if DEBUG
53#define PRINTF(...) printf(__VA_ARGS__)
54#else
55#define PRINTF(...)
56#endif
57/*---------------------------------------------------------------------------*/
58typedef struct {
59 int type;
60 uint8_t pin_mask;
61 uint8_t vdd3;
62} adc_info_t;
63
64typedef struct {
65 uint8_t sensors_num;
66 uint8_t sensors_ports;
67 adc_info_t sensor[ADC_SENSORS_MAX];
68} adc_wrapper_t;
69
70static adc_wrapper_t sensors;
71/*---------------------------------------------------------------------------*/
72static uint16_t
73convert_to_value(uint8_t index)
74{
75 uint32_t value;
76 value = adc_zoul.value(sensors.sensor[index].pin_mask);
77
78 if(value == ZOUL_SENSORS_ERROR) {
79 PRINTF("ADC sensors: failed retrieving data\n");
80 return ADC_WRAPPER_ERROR;
81 }
82
83 /* Default voltage divisor relation is 5/3 aprox, change at adc_wrapper.h,
84 * calculations below assume a decimation rate of 512 (12 bits ENOB) and
85 * AVVD5 voltage reference of 3.3V
86 */
87
88 if(!sensors.sensor[index].vdd3) {
89 value *= ADC_WRAPPER_EXTERNAL_VREF;
90 value /= ADC_WRAPPER_EXTERNAL_VREF_CROSSVAL;
91 }
92
93 switch(sensors.sensor[index].type) {
94 case ANALOG_GROVE_LIGHT:
95 /* Light dependant resistor (LDR) resistance value*/
96 value = (10230 - (value * 10)) / value;
97 /* TODO: With the resistance we could calculate the lux as 63*R^(-0.7) */
98 return (uint16_t)value;
99
100 case ANALOG_GROVE_LOUDNESS:
101 /* Based on the LM2904 amplifier (blue version with potentiometer) */
102 return (uint16_t)value;
103
104 case ANALOG_PHIDGET_ROTATION_1109:
105 /* Linear sensor with 0-300ยบ, 300/33000 = 0.00909 */
106 value *= 909;
107 value /= 100000;
108 return (uint16_t)value;
109
110 /* VDD+5 sensors */
111 case ANALOG_VAC_SENSOR:
112 /* Linear sensor from 0 to 5 V; 0.0088 resolution*/
113 value *= 88;
114 value /= 10000;
115 return (uint16_t)value;
116
117 case ANALOG_AAC_SENSOR:
118 /* Linear sensor from 0 to 5 V;*/
119 return (uint16_t)value;
120
121 default:
122 return ADC_WRAPPER_ERROR;
123 }
124
125 return ADC_WRAPPER_ERROR;
126}
127/*---------------------------------------------------------------------------*/
128static uint8_t
129is_sensor_in_list(int type)
130{
131 uint8_t i;
132
133 for(i = 0; i <= sensors.sensors_num; i++) {
134 if(sensors.sensor[i].type == type) {
135 return i + 1;
136 }
137 }
138 return 0;
139}
140/*---------------------------------------------------------------------------*/
141static int
142value(int type)
143{
144 uint8_t index;
145 uint16_t sensor_value;
146
147 index = is_sensor_in_list(type);
148
149 if(!index) {
150 PRINTF("ADC sensors: sensor not registered\n");
151 return ADC_WRAPPER_SUCCESS;
152 }
153
154 /* Restore index value after the check */
155 index -= 1;
156 sensor_value = convert_to_value(index);
157
158 return sensor_value;
159}
160/*---------------------------------------------------------------------------*/
161static int
162configure(int type, int value)
163{
164 uint8_t pin_mask = GPIO_PIN_MASK(value);
165
166 if((type != ANALOG_GROVE_LIGHT) && (type != ANALOG_PHIDGET_ROTATION_1109) &&
167 (type != ANALOG_GROVE_LOUDNESS) && (type != ANALOG_VAC_SENSOR) &&
168 (type != ANALOG_AAC_SENSOR) ) {
169 PRINTF("ADC sensors: sensor not supported, check adc_wrapper.h header\n");
170 return ADC_WRAPPER_ERROR;
171 }
172
173 if(sensors.sensors_num >= ADC_SENSORS_MAX) {
174 PRINTF("ADC sensors: all adc channels available have been assigned\n");
175 return ADC_WRAPPER_ERROR;
176 }
177
178 if((value < 0x01) || (value > 0x07) || ((value == BUTTON_USER_PIN) && (ADC_SENSORS_ADC6_PIN < 0))) {
179 PRINTF("ADC sensors: invalid pin value, (PA0-PA1, PA3) are reserved\n");
180 return ADC_WRAPPER_ERROR;
181 }
182
183 if(sensors.sensors_ports & pin_mask) {
184 PRINTF("ADC sensors: a sensor has been already assigned to this pin\n");
185 return ADC_WRAPPER_ERROR;
186 }
187
188 switch(type) {
189 /* V+3.3 sensors */
190 case ANALOG_GROVE_LIGHT:
191 case ANALOG_GROVE_LOUDNESS:
192 case ANALOG_PHIDGET_ROTATION_1109:
193 if(adc_zoul.configure(SENSORS_HW_INIT, pin_mask) == ZOUL_SENSORS_ERROR) {
194 return ADC_WRAPPER_ERROR;
195 }
196 sensors.sensor[sensors.sensors_num].type = type;
197 sensors.sensor[sensors.sensors_num].pin_mask = pin_mask;
198 sensors.sensor[sensors.sensors_num].vdd3 = 1;
199 break;
200
201 /*V+5 sensors*/
202 case ANALOG_VAC_SENSOR:
203 case ANALOG_AAC_SENSOR:
204 if(adc_zoul.configure(SENSORS_HW_INIT, pin_mask) == ZOUL_SENSORS_ERROR) {
205 return ADC_WRAPPER_ERROR;
206 }
207 sensors.sensor[sensors.sensors_num].type = type;
208 sensors.sensor[sensors.sensors_num].pin_mask = pin_mask;
209 sensors.sensor[sensors.sensors_num].vdd3 = 0;
210 break;
211
212
213 default:
214 return ADC_WRAPPER_ERROR;
215 }
216
217 PRINTF("ADC sensors: type %u mask 0x%02X vdd3 %u\n",
218 sensors.sensor[sensors.sensors_num].type,
219 sensors.sensor[sensors.sensors_num].pin_mask,
220 sensors.sensor[sensors.sensors_num].vdd3);
221
222 sensors.sensors_num++;
223 sensors.sensors_ports |= pin_mask;
224
225 return ADC_WRAPPER_SUCCESS;
226}
227/*---------------------------------------------------------------------------*/
228SENSORS_SENSOR(adc_sensors, ADC_SENSORS, value, configure, NULL);
229/*---------------------------------------------------------------------------*/
230/** @} */
231
Header file for the Zoul ADC sensors API.
Header file for the Zoul ADC interface.
Header file for the cc2538 ADC driver.
Header file with register and macro declarations for the cc2538 GPIO module.
#define GPIO_PIN_MASK(PIN)
Converts a pin number to a pin mask.
Definition: gpio.h:320
#define ADC_SENSORS_MAX
Maximum sensors
Definition: board.h:243
#define ADC_SENSORS_ADC6_PIN
ADC6 not declared
Definition: board.h:237
Header file with declarations for the I/O Control module.
Implementation of a generic module controlling Zoul sensors.