Contiki 2.5
temp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Swedish Institute of Computer Science
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 are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in
12  * the documentation and/or other materials provided with the
13  * distribution.
14  * * Neither the name of the copyright holders nor the names of
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 "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 /**
31  * \file
32  *
33  * \brief
34  * Driver for the on board temperature sensor.
35  *
36  * \author
37  * Mike Vidales mavida404@gmail.com
38  *
39  */
40 
41 #include "key.h"
42 #include "temp.h"
43 #include "lcd.h"
44 
45 /**
46  * \addtogroup lcd
47  * \{
48 */
49 
50 /** Type used together with find_temp() to find temperature */
51 typedef enum {
52  TEMP_ZERO_OFFSET_CELCIUS = -15,
53  TEMP_ZERO_OFFSET_FAHRENHEIT = 0
55 
56 #if defined( DOXYGEN )
57 static uint16_t temp_table_celcius[];
58 static uint16_t temp_table_fahrenheit[];
59 #else /* !DOXYGEN */
60 /** Celcius temperatures (ADC-value) from -15 to 60 degrees */
61 static uint16_t temp_table_celcius[] PROGMEM = {
62  923,917,911,904,898,891,883,876,868,860,851,843,834,825,815,
63  806,796,786,775,765,754,743,732,720,709,697,685,673,661,649,
64  636,624,611,599,586,574,562,549,537,524,512,500,488,476,464,
65  452,440,429,418,406,396,385,374,364,354,344,334,324,315,306,
66  297,288,279,271,263,255,247,240,233,225,219,212,205,199,193,
67  187,
68 };
69 
70 /** Fahrenheit temperatures (ADC-value) from 0 to 140 degrees */
71 static uint16_t temp_table_fahrenheit[] PROGMEM = {
72  938, 935, 932, 929, 926, 923, 920, 916, 913, 909, 906, 902, 898,
73  894, 891, 887, 882, 878, 874, 870, 865, 861, 856, 851, 847, 842,
74  837, 832, 827, 822, 816, 811, 806, 800, 795, 789, 783, 778, 772,
75  766, 760, 754, 748, 742, 735, 729, 723, 716, 710, 703, 697, 690,
76  684, 677, 670, 663, 657, 650, 643, 636, 629, 622, 616, 609, 602,
77  595, 588, 581, 574, 567, 560, 553, 546, 539, 533, 526, 519, 512,
78  505, 498, 492, 485, 478, 472, 465, 459, 452, 446, 439, 433, 426,
79  420, 414, 408, 402, 396, 390, 384, 378, 372, 366, 360, 355, 349,
80  344, 338, 333, 327, 322, 317, 312, 307, 302, 297, 292, 287, 282,
81  277, 273, 268, 264, 259, 255, 251, 246, 242, 238, 234, 230, 226,
82  222, 219, 215, 211, 207, 204, 200, 197, 194, 190, 187,
83 };
84 #endif /* !DOXYGEN */
85 
86 /** Flag indicating initialized or not */
87 bool temp_initialized = false;
88 
89 /** \brief Find array index corresponding to input ADC value
90  *
91  * Returned array index is actual temperature + zero offset. To
92  * get actual temperature, the zero offset (\ref temp_zero_offset_t)
93  * has to be subtracted.
94  *
95  * \param[in] value Value to seracah for in table
96  * \param[in] array Pointer to array in which to look for ADC value
97  * \param[in] count Size of array
98  *
99  *
100  * \return EOF on error
101  */
102 static int find_temp(int16_t value, uint16_t* array, int count);
103 
104 /*---------------------------------------------------------------------------*/
105 
106 /**
107  * \brief This will initialize the digital IO and adc channel for temperture readings.
108  * Optionally enable adc channel 2 for measurement of EXT_SUPL_SIG.
109  *
110  * \retval 0 Place holder for returning status.
111 */
112 int
114 {
115  /* Disable the Digital IO for the analog readings. */
116  DIDR0 |= (1 << ADC4D);
117 
118  /* Temp sens power pin as output */
119  TEMP_DDR |= (1 << TEMP_BIT_PWR);
120 
121  /* Power off temp sensor */
122  TEMP_PORT &= ~(1 << TEMP_BIT_PWR);
123 
124  /* Temp sens input, no pullup */
125  TEMP_DDR &= ~(1 << TEMP_BIT_IN);
126  TEMP_PORT &= ~(1 << TEMP_BIT_IN);
127 
128 #if MEASURE_ADC2
129  DIDR0 |= (1 << ADC2D);
130  TEMP_DDR &= ~(1 << 2);
131  TEMP_PORT &= ~(1 << 2);
132 #endif
133 
134  temp_initialized = true;
135 
136  return 0;
137 }
138 
139 /*---------------------------------------------------------------------------*/
140 
141 /**
142  * \brief This will disable temperature readings by reseting the initialed flag.
143 */
144 void
146 {
147  temp_initialized = false;
148 }
149 
150 /*---------------------------------------------------------------------------*/
151 
152 /**
153  * \brief This will turn on the adc channel for reading the temp sensor.
154  *
155  * After the raw adc value is stored, it will be used to lookup a degree conversion
156  * based on the tables for F or C.
157  * Optionally, EXT_SUPL_SIG is also read on channel 2 and stored in the global
158  * ADC2_reading for subsequent transfer to the 1284p web server.
159  *
160  * \param unit Used to determine what unit needs to be appended with the value.
161  *
162  * \return EOF This is an uninitialized adc error.
163  * \retval temp The newly converted value in degrees F or C.
164 */
165 #if MEASURE_ADC2
166 uint16_t ADC2_reading;
167 #endif
168 
169 int16_t
171 {
172  int16_t res;
173  int16_t temp;
174 
175  /* Return if temp sensor driver not initialized */
176  if (temp_initialized == false) {
177  return EOF;
178  }
179 
180  /* Power up sensor */
181  TEMP_PORT |= (1 << TEMP_BIT_PWR);
182 
183  /* Init ADC and measure */
184  adc_init(ADC_CHAN_ADC4, ADC_TRIG_FREE_RUN, ADC_REF_AVCC, ADC_PS_128);
186  while ((res = adc_result_get(ADC_ADJ_RIGHT)) == EOF ){
187  ;
188  }
189 
190 #if MEASURE_ADC2
191  /* Measure external voltage supply, routed to ADC2 through a 470K/100K divider*/
192  /* AVCC is 3.3 volts if using external supply, else Vbat which will be lower */
193  /* Convert result to millivolts assuming AVCC is 3.3 volts, on battery it will be lower! */
194  adc_init(ADC_CHAN_ADC2, ADC_TRIG_FREE_RUN, ADC_REF_AVCC, ADC_PS_128);
196  while ((ADC2_reading = adc_result_get(ADC_ADJ_RIGHT)) == EOF ){
197  ;
198  }
199  ADC2_reading = (ADC2_reading*((470+100)*3300UL))/(100*1024UL);
200 #endif
201 
202  adc_deinit();
203  /* Re-init the adc for buttons. */
204  key_init();
205 
206  /* Power down sensor */
207  TEMP_PORT &= ~(1 << TEMP_BIT_PWR);
208 
209  /* Get corresponding temperature from table */
210  if (unit == TEMP_UNIT_CELCIUS) {
211  temp = find_temp(res, temp_table_celcius, sizeof(temp_table_celcius)/sizeof(int)) + TEMP_ZERO_OFFSET_CELCIUS;
212  } else /*unit == TEMP_UNIT_FAHRENHEIT*/{
213  temp = find_temp(res, temp_table_fahrenheit, sizeof(temp_table_fahrenheit)/sizeof(int)) + TEMP_ZERO_OFFSET_FAHRENHEIT;
214  }
215 
216  return temp;
217 }
218 
219 /*---------------------------------------------------------------------------*/
220 
221 /**
222  * \brief Find array index corresponding to input ADC value
223  *
224  * Returned array index is actual temperature + zero offset. To
225  * get actual temperature, the zero offset (\ref temp_zero_offset_t)
226  * has to be subtracted.
227  *
228  * \param[in] value Value to search for in table
229  * \param[in] array Pointer to array in which to look for ADC value
230  * \param[in] count Size of array
231  *
232  * \return EOF on error
233 */
234 static int
235 find_temp(int16_t value, uint16_t* array, int count)
236 {
237  int i = 0;
238  int table_val = 0;
239  do{
240  table_val = pgm_read_word(&array[i]);
241  if (table_val < value) {
242  return i;
243  }
244  } while(++i<count);
245  return EOF;
246 }
247 
248 /** \} */