ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_interface_adc_ntc.c
Go to the documentation of this file.
2 
3 #if (RI_ADC_NTC_ENABLED || DOXYGEN)
4 
5 #include "ruuvi_driver_error.h"
6 #include "ruuvi_driver_sensor.h"
10 
15 
26 #ifdef RI_ADC_NTC_CHANNEL
27 #define ADC_NTC_USE_CHANNEL RI_ADC_NTC_CHANNEL
28 #else
29 #define ADC_NTC_USE_CHANNEL 1
30 #endif
31 
32 #ifdef RI_ADC_NTC_DIVIDER
33 #define ADC_NTC_USE_DIVIDER RI_ADC_NTC_DIVIDER
34 #else
35 #define ADC_NTC_USE_DIVIDER 1.00f
36 #endif
37 
38 #ifdef RI_ADC_NTC_VDD
39 #define ADC_NTC_USE_VDD RI_ADC_NTC_VDD
40 #else
41 #define ADC_NTC_USE_VDD 3.60f
42 #endif
43 
44 #ifdef RI_ADC_NTC_BALANCE
45 #define ADC_NTC_BALANCE RI_ADC_NTC_BALANCE
46 #else
47 #define ADC_NTC_BALANCE 10000.00f
48 #endif
49 
50 #ifdef RI_ADC_NTC_DEFAULT_RES
51 #define ADC_NTC_DEFAULT_RES RI_ADC_NTC_DEFAULT_RES
52 #else
53 #define ADC_NTC_DEFAULT_RES 10000.00f
54 #endif
55 
56 #ifdef RI_ADC_NTC_DEFAULT_TEMP
57 #define ADC_NTC_DEFAULT_TEMP RI_ADC_NTC_DEFAULT_TEMP
58 #else
59 #define ADC_NTC_DEFAULT_TEMP 25.00f
60 #endif
61 
62 #ifdef RI_ADC_NTC_DEFAULT_BETA
63 #define ADC_NTC_DEFAULT_BETA RI_ADC_NTC_DEFAULT_BETA
64 #else
65 #define ADC_NTC_DEFAULT_BETA 3974.0f
66 #endif
67 
68 #define ADC_NTC_DATA_COUNTER 1
69 #define ADC_NTC_DEFAULT_BITFIELD 0
70 #define ADC_NTC_ENABLE_BYTE 1
71 #define ADC_K_TO_C_CONST 273.15f
72 #define ADC_NTC_DEFAULT_TEMP_K (ADC_NTC_DEFAULT_TEMP + ADC_K_TO_C_CONST)
73 
74 static ri_adc_pins_config_t adc_ntc_pins_config =
75 {
77 #ifdef RI_ADC_ADV_CONFIG
78  .p_pin.resistor = RI_ADC_RESISTOR_DISABLED,
79 #endif
80 };
81 
82 static ri_adc_channel_config_t adc_ntc_config =
83 {
85  .vref = RI_ADC_VREF_EXTERNAL,
86 #ifdef RI_ADC_ADV_CONFIG
87  .gain = RI_ADC_GAIN1_6,
88  .acqtime = RI_ADC_ACQTIME_10US,
89 #endif
90 };
91 
92 static ri_adc_get_data_t adc_ntc_options =
93 {
95  .divider = ADC_NTC_USE_DIVIDER,
96 };
97 
98 static uint64_t m_tsample;
99 static bool m_autorefresh;
101 static bool m_is_init;
102 static const char m_sensor_name[] = "NTC";
103 
111 static float ratio_to_temperature (const float * const ratio)
112 {
113  float result = RD_FLOAT_INVALID;
114  float Rt;
115  float Rb = (float) ADC_NTC_BALANCE;
116  float beta = (float) ADC_NTC_DEFAULT_BETA;
117  float T0 = (float) ADC_NTC_DEFAULT_TEMP_K;
118  float R0 = (float) RI_ADC_NTC_DEFAULT_RES;
119 
120  if ( (NULL != ratio) && (*ratio >= 0.0F) && (*ratio <= 1.0F))
121  {
122  // Calculate NTC resistance.
123  Rt = (Rb * *ratio) / (1.0F - *ratio);
124  // 1/T = 1/T0 + 1/B * ln(R/R0)
125  result = 1.0F / ( (1 / T0) + ( (1 / beta) * log (Rt / R0)));
126  // Convert K->C
127  result -= ADC_K_TO_C_CONST;
128  }
129 
130  return result;
131 }
132 
133 static rd_status_t get_data (void)
134 {
135  rd_status_t err_code = RD_SUCCESS;
136  float ratio;
137  m_tsample = rd_sensor_timestamp_get();
138 
140  &adc_ntc_options,
141  &ratio))
142  {
143  //m_temperture = volts_to_temperature (&volts);
144  m_temperture = ratio_to_temperature (&ratio);
145  }
146  else
147  {
148  err_code = RD_ERROR_INVALID_STATE;
149  }
150 
151  return err_code;
152 }
153 
155 {
156  uint8_t mode;
157  rd_status_t err_code = ri_adc_ntc_mode_get (&mode);
158  return err_code | validate_default_input_set (samplerate, mode);
159 }
161 {
162  uint8_t mode;
163  rd_status_t err_code = ri_adc_ntc_mode_get (&mode);
164  return err_code | validate_default_input_set (resolution, mode);
165 }
166 
168 {
169  uint8_t mode;
170  rd_status_t err_code = ri_adc_ntc_mode_get (&mode);
171  return err_code | validate_default_input_set (scale, mode);
172 }
173 
174 rd_status_t ri_adc_ntc_dsp_set (uint8_t * dsp, uint8_t * parameter)
175 {
176  uint8_t mode;
177  rd_status_t err_code = ri_adc_ntc_mode_get (&mode);
178  err_code |= validate_default_input_set (parameter, mode);
179 
180  if (RD_SUCCESS == err_code)
181  {
182  if (NULL == dsp)
183  {
184  err_code = RD_ERROR_NULL;
185  }
186  else
187  {
188  if (RD_SENSOR_DSP_LAST != (*dsp))
189  {
190  err_code = RD_ERROR_NOT_SUPPORTED;
191  }
192  }
193  }
194 
195  return RD_SUCCESS;
196 }
197 
198 rd_status_t ri_adc_ntc_dsp_get (uint8_t * dsp, uint8_t * parameter)
199 {
200  return ( (validate_default_input_get (dsp)) |
201  validate_default_input_get (parameter));
202 }
203 
205  environmental_sensor, rd_bus_t bus, uint8_t handle)
206 {
207  rd_status_t err_code = RD_SUCCESS;
208 
209  if (NULL == environmental_sensor)
210  {
211  err_code = RD_ERROR_NULL;
212  }
213  else
214  {
215  if (m_is_init)
216  {
217  err_code = RD_ERROR_INVALID_STATE;
218  }
219  else
220  {
221  rd_sensor_initialize (environmental_sensor);
222  environmental_sensor->name = m_sensor_name;
223  err_code |= ri_adc_init (NULL);
224  adc_ntc_pins_config.p_pin.channel = handle;
226  &adc_ntc_pins_config,
227  &adc_ntc_config);
228 
229  if (RD_SUCCESS == err_code)
230  {
231  environmental_sensor->init = ri_adc_ntc_init;
232  environmental_sensor->uninit = ri_adc_ntc_uninit;
233  environmental_sensor->samplerate_set = ri_adc_ntc_samplerate_set;
234  environmental_sensor->samplerate_get = validate_default_input_get;
235  environmental_sensor->resolution_set = ri_adc_ntc_resolution_set;
236  environmental_sensor->resolution_get = validate_default_input_get;
237  environmental_sensor->scale_set = ri_adc_ntc_scale_set;
238  environmental_sensor->scale_get = validate_default_input_get;
239  environmental_sensor->dsp_set = ri_adc_ntc_dsp_set;
240  environmental_sensor->dsp_get = ri_adc_ntc_dsp_get;
241  environmental_sensor->mode_set = ri_adc_ntc_mode_set;
242  environmental_sensor->mode_get = ri_adc_ntc_mode_get;
243  environmental_sensor->data_get = ri_adc_ntc_data_get;
244  environmental_sensor->configuration_set = rd_sensor_configuration_set;
245  environmental_sensor->configuration_get = rd_sensor_configuration_get;
246  environmental_sensor->provides.datas.temperature_c = ADC_NTC_ENABLE_BYTE;
247  m_tsample = RD_UINT64_INVALID;
248  m_is_init = true;
249  }
250  }
251  }
252 
253  return err_code;
254 }
255 
257  rd_bus_t bus, uint8_t handle)
258 {
259  rd_status_t err_code = RD_SUCCESS;
260 
261  if (NULL == sensor)
262  {
263  err_code = RD_ERROR_NULL;
264  }
265  else
266  {
267  rd_sensor_uninitialize (sensor);
268  m_tsample = RD_UINT64_INVALID;
269  m_is_init = false;
270  m_autorefresh = false;
271  err_code |= ri_adc_stop (ADC_NTC_USE_CHANNEL);
272  }
273 
274  return err_code;
275 }
276 
278 {
280 
281  if (NULL == mode)
282  {
283  err_code = RD_ERROR_NULL;
284  }
285  else
286  {
287  if ( (RD_SENSOR_CFG_SLEEP == (*mode)) ||
288  (RD_SENSOR_CFG_DEFAULT == (*mode)))
289  {
290  m_autorefresh = false;
291  (*mode) = RD_SENSOR_CFG_SLEEP;
292  err_code = RD_SUCCESS;
293  }
294 
295  if (RD_SENSOR_CFG_CONTINUOUS == (*mode))
296  {
297  m_autorefresh = true;
298  err_code = RD_SUCCESS;
299  }
300 
301  if (RD_SENSOR_CFG_SINGLE == *mode)
302  {
303  uint8_t current_mode;
304  ri_adc_ntc_mode_get (&current_mode);
305 
306  if (RD_SENSOR_CFG_CONTINUOUS == current_mode)
307  {
308  (*mode) = RD_SENSOR_CFG_CONTINUOUS;
309  err_code = RD_ERROR_INVALID_STATE;
310  }
311  else
312  {
313  m_autorefresh = false;
314  (*mode) = RD_SENSOR_CFG_SLEEP;
315  err_code = get_data();
316  }
317  }
318  }
319 
320  return err_code;
321 }
322 
324 {
325  rd_status_t err_code = RD_SUCCESS;
326 
327  if (NULL == mode)
328  {
329  err_code = RD_ERROR_NULL;
330  }
331  else
332  {
333  if (m_autorefresh)
334  {
335  (*mode) = RD_SENSOR_CFG_CONTINUOUS;
336  }
337 
338  if (!m_autorefresh)
339  {
340  (*mode) = RD_SENSOR_CFG_SLEEP;
341  }
342  }
343 
344  return err_code;
345 }
346 
348  p_data)
349 {
350  rd_status_t err_code = RD_SUCCESS;
351 
352  if (NULL == p_data)
353  {
354  err_code = RD_ERROR_NULL;
355  }
356  else
357  {
358  if (m_autorefresh)
359  {
360  err_code = get_data();
361  }
362 
363  if ( (RD_SUCCESS == err_code) &&
364  (RD_UINT64_INVALID != m_tsample))
365  {
366  rd_sensor_data_t d_environmental;
368  float env_values;
369  env_values = m_temperture;
371  d_environmental.data = &env_values;
372  d_environmental.valid = env_fields;
373  d_environmental.fields = env_fields;
374  rd_sensor_data_populate (p_data,
375  &d_environmental,
376  p_data->fields);
377  p_data->timestamp_ms = m_tsample;
378  }
379  }
380 
381  return err_code;
382 }
383 
384 #endif
#define RD_ERROR_NULL
Null Pointer.
uint32_t rd_status_t
bitfield for representing errors
#define RD_FLOAT_INVALID
Signal that value should not be used.
#define RD_ERROR_NOT_SUPPORTED
Not supported.
#define RD_SUCCESS
Internal Error.
#define RD_UINT64_INVALID
Signal that value should not be used.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_SENSOR_DSP_LAST
Return last value from sensor. Parameter: No effect. Use default.
#define RD_SENSOR_CFG_SLEEP
Sensor should go to sleep immediately.
#define RD_SENSOR_CFG_DEFAULT
Default value, always valid for the sensor.
void rd_sensor_uninitialize(rd_sensor_t *const p_sensor)
Mark sensor as uninitialized by calling the generic initialization. Will not clear the name of the se...
rd_status_t rd_sensor_configuration_get(const rd_sensor_t *sensor, rd_sensor_configuration_t *config)
Implementation of ref rd_configuration_fp.
void rd_sensor_initialize(rd_sensor_t *const p_sensor)
Initialize sensor struct with non-null pointers which return RD_ERROR_NOT_INITIALIZED.
rd_status_t validate_default_input_set(uint8_t *const input, const uint8_t mode)
Validate that given setting can be set on a sensor which supports only default value.
void rd_sensor_data_populate(rd_sensor_data_t *const target, const rd_sensor_data_t *const provided, const rd_sensor_data_fields_t requested)
Populate given target data with data provided by sensor as requested.
rd_status_t rd_sensor_configuration_set(const rd_sensor_t *sensor, rd_sensor_configuration_t *config)
Implementation of ref rd_configuration_fp.
#define RD_SENSOR_CFG_CONTINUOUS
Sensor will keep sampling at defined sample rate.
rd_bus_t
Type of bus sensor uses.
uint64_t rd_sensor_timestamp_get(void)
Calls the timestamp function and returns its value.
rd_status_t validate_default_input_get(uint8_t *const input)
Validate and get input when only allowed value is default.
#define RD_SENSOR_CFG_SINGLE
Sensor should go to sleep after single measurement.
Header to enable and disable module compilation.
#define RI_ADC_NTC_DEFAULT_RES
NTC at default temp.
Ruuvi error codes and error check function.
Ruuvi sensor interface Lifecycle: Beta
Interface for controlling ADC onboard MCU.
@ RI_ADC_MODE_SINGLE
Single ended mode.
@ RI_ADC_VREF_EXTERNAL
External voltage reference.
rd_status_t ri_adc_get_data_ratio(uint8_t channel_num, ri_adc_get_data_t *p_config, float *p_data)
Get ADC data in volts.
@ RI_ADC_GND
GND of device.
rd_status_t ri_adc_stop(uint8_t channel_num)
Stop use ADC channel.
rd_status_t ri_adc_configure(uint8_t channel_num, ri_adc_pins_config_t *p_pins, ri_adc_channel_config_t *p_config)
Configure ADC channel.
rd_status_t ri_adc_init(ri_adc_config_t *p_config)
Initialization of ADC.
rd_status_t ri_adc_ntc_dsp_set(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
rd_status_t ri_adc_ntc_mode_set(uint8_t *mode)
rd_sensor_setup_fp
#define ADC_NTC_USE_CHANNEL
float m_temperture
Last measured temperature.
rd_status_t ri_adc_ntc_data_get(rd_sensor_data_t *const p_data)
rd_sensor_data_fp
rd_status_t ri_adc_ntc_resolution_set(uint8_t *resolution)
rd_sensor_setup_fp
rd_status_t ri_adc_ntc_uninit(rd_sensor_t *sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
#define ADC_NTC_DATA_COUNTER
rd_status_t ri_adc_ntc_dsp_get(uint8_t *dsp, uint8_t *parameter)
rd_sensor_dsp_fp
#define ADC_NTC_USE_DIVIDER
rd_status_t ri_adc_ntc_init(rd_sensor_t *environmental_sensor, rd_bus_t bus, uint8_t handle)
rd_sensor_init_fp
#define ADC_K_TO_C_CONST
#define ADC_NTC_DEFAULT_BITFIELD
#define ADC_NTC_DEFAULT_BETA
rd_status_t ri_adc_ntc_scale_set(uint8_t *scale)
rd_sensor_setup_fp
rd_status_t ri_adc_ntc_samplerate_set(uint8_t *samplerate)
rd_sensor_setup_fp
#define ADC_NTC_ENABLE_BYTE
#define ADC_NTC_BALANCE
#define ADC_NTC_USE_VDD
rd_status_t ri_adc_ntc_mode_get(uint8_t *mode)
rd_sensor_setup_fp
#define ADC_NTC_DEFAULT_TEMP_K
unsigned int temperature_c
Temperature, celcius.
Generic sensor data struct.
float * data
Data of sensor. Must contain as many elements as fields has bits set.
uint64_t timestamp_ms
Timestamp of the event, rd_sensor_timestamp_get.
rd_sensor_data_fields_t valid
Listing of valid data in this sample.
rd_sensor_data_fields_t fields
Description of datafields which may be contained in this sample.
Interface to sensor. Some sensors can implement additional functions. The additional functions are de...
rd_sensor_data_fp data_get
rd_sensor_data_fp
rd_configuration_fp configuration_set
rd_configuration_fp
rd_sensor_setup_fp samplerate_get
rd_sensor_setup_fp
rd_sensor_setup_fp resolution_get
rd_sensor_setup_fp
rd_sensor_init_fp uninit
rd_sensor_init_fp
rd_configuration_fp configuration_get
rd_configuration_fp
rd_sensor_dsp_fp dsp_get
rd_sensor_dsp_fp
rd_sensor_data_fields_t provides
Description of data fields the sensor is able to provide.
rd_sensor_dsp_fp dsp_set
rd_sensor_dsp_fp
rd_sensor_setup_fp mode_set
rd_sensor_setup_fp
const char * name
Sensor human-readable name. Should be at most 8 bytes long.
rd_sensor_setup_fp mode_get
rd_sensor_setup_fp
rd_sensor_setup_fp samplerate_set
rd_sensor_setup_fp
rd_sensor_init_fp init
rd_sensor_init_fp
rd_sensor_setup_fp scale_set
rd_sensor_setup_fp
rd_sensor_setup_fp resolution_set
rd_sensor_setup_fp
rd_sensor_setup_fp scale_get
rd_sensor_setup_fp
Union to access sensor data.
uint32_t bitfield
Bitfield used to access sensor data.
rd_sensor_data_bitfield_t datas
Structured data field.