51#include "lib/sensors.h"
61#define PRINTF(...) printf(__VA_ARGS__)
66#define DEBOUNCE_DURATION (CLOCK_SECOND >> 6)
68#define ANEMOMETER_SENSOR_PORT_BASE GPIO_PORT_TO_BASE(ANEMOMETER_SENSOR_PORT)
69#define ANEMOMETER_SENSOR_PIN_MASK GPIO_PIN_MASK(ANEMOMETER_SENSOR_PIN)
70#define RAIN_GAUGE_SENSOR_PORT_BASE GPIO_PORT_TO_BASE(RAIN_GAUGE_SENSOR_PORT)
71#define RAIN_GAUGE_SENSOR_PIN_MASK GPIO_PIN_MASK(RAIN_GAUGE_SENSOR_PIN)
73void (*rain_gauge_int_callback)(uint16_t value);
74void (*anemometer_int_callback)(uint16_t value);
76static uint8_t enabled;
78process_event_t anemometer_int_event;
79process_event_t rain_gauge_int_event;
81static struct ctimer ct;
82static struct timer debouncetimer;
89} weather_meter_sensors_t;
95 uint32_t value_buf_xm;
96 uint16_t value_avg_xm;
101 weather_meter_sensors_t rain_gauge;
102 weather_meter_sensors_t anemometer;
103} weather_meter_sensors;
106 int32_t value_buf_xm;
108 int16_t value_avg_xm;
109} weather_meter_wind_vane_ext_t;
111static weather_meter_sensors weather_sensors;
112static weather_meter_ext_t anemometer;
113static weather_meter_wind_vane_ext_t wind_vane;
118} wind_vane_mid_point_t;
142static const wind_vane_mid_point_t wind_vane_table[16] = {
162weather_meter_wind_vane_degrees(uint16_t value)
165 for(i = 0; i < 16; i++) {
166 if(value <= wind_vane_table[i].mid_point) {
167 return (
int)wind_vane_table[i].degree;
170 return (
int)wind_vane_table[i].degree;
175 PRINTF(
"Weather: invalid wind vane value\n");
176 return WEATHER_METER_ERROR;
180weather_meter_get_wind_dir(
void)
182 weather_sensors.wind_vane = adc_zoul.value(WIND_VANE_ADC);
183 if((int16_t)weather_sensors.wind_vane < 0) {
184 weather_sensors.wind_vane = 0;
186 return weather_meter_wind_vane_degrees(weather_sensors.wind_vane);
190ct_callback(
void *ptr)
194 int16_t wind_dir_delta;
198 ANEMOMETER_SENSOR_PIN_MASK);
199 wind_speed = weather_sensors.anemometer.ticks;
200 wind_speed *= WEATHER_METER_ANEMOMETER_SPEED_1S;
201 weather_sensors.anemometer.value = (uint16_t)wind_speed;
202 anemometer.ticks_avg++;
203 anemometer.value_avg += weather_sensors.anemometer.value;
204 anemometer.value_buf_xm += weather_sensors.anemometer.value;
207 if(weather_sensors.anemometer.value > anemometer.value_max) {
208 anemometer.value_max = weather_sensors.anemometer.value;
212 wind_dir = weather_meter_get_wind_dir();
213 wind_dir_delta = wind_dir - wind_vane.value_prev;
215 if(wind_dir_delta < -1800) {
216 wind_vane.value_prev += wind_dir_delta + 3600;
217 }
else if(wind_dir_delta > 1800) {
218 wind_vane.value_prev += wind_dir_delta - 3600;
220 wind_vane.value_prev += wind_dir_delta;
223 wind_vane.value_buf_xm += wind_vane.value_prev;
226 if(!(anemometer.ticks_avg % WEATHER_METER_AVG_PERIOD)) {
227 PRINTF(
"\nWeather: calculate the %u averages ***\n", WEATHER_METER_AVG_PERIOD);
229 if(anemometer.value_buf_xm) {
230 anemometer.value_avg_xm = anemometer.value_buf_xm / WEATHER_METER_AVG_PERIOD;
231 anemometer.value_buf_xm = 0;
233 anemometer.value_avg_xm = 0;
236 if(wind_vane.value_buf_xm >= 0) {
237 wind_vane.value_buf_xm = wind_vane.value_buf_xm / WEATHER_METER_AVG_PERIOD;
238 wind_vane.value_avg_xm = wind_vane.value_buf_xm;
240 wind_vane.value_buf_xm = ABS(wind_vane.value_buf_xm) / WEATHER_METER_AVG_PERIOD;
241 wind_vane.value_avg_xm = wind_vane.value_buf_xm;
242 wind_vane.value_avg_xm = ~wind_vane.value_avg_xm + 1;
245 if(wind_vane.value_avg_xm >= 3600) {
246 wind_vane.value_avg_xm -= 3600;
247 }
else if(wind_vane.value_avg_xm < 0) {
248 wind_vane.value_avg_xm += 3600;
251 wind_vane.value_buf_xm = 0;
252 wind_vane.value_prev = wind_dir;
256 if(!anemometer.ticks_avg) {
257 anemometer.value_avg = 0;
260 weather_sensors.anemometer.ticks = 0;
264 ANEMOMETER_SENSOR_PIN_MASK);
269PROCESS(weather_meter_int_process,
"Weather meter interrupt process handler");
279 if((ev == anemometer_int_event) && (weather_sensors.anemometer.int_en)) {
280 if(weather_sensors.anemometer.ticks >=
281 weather_sensors.anemometer.int_thres) {
282 anemometer_int_callback(weather_sensors.anemometer.ticks);
286 if((ev == rain_gauge_int_event) && (weather_sensors.rain_gauge.int_en)) {
287 if(weather_sensors.rain_gauge.ticks >=
288 weather_sensors.rain_gauge.int_thres) {
289 rain_gauge_int_callback(weather_sensors.rain_gauge.ticks);
300 .handler = weather_meter_interrupt_handler,
306 .handler = weather_meter_interrupt_handler,
320 timer_set(&debouncetimer, DEBOUNCE_DURATION);
326 if(pin_mask == rain_handler.pin_mask) {
327 weather_sensors.anemometer.ticks++;
328 process_post(&weather_meter_int_process, anemometer_int_event, NULL);
329 }
else if(pin_mask == anemometer_handler.pin_mask) {
330 weather_sensors.rain_gauge.ticks++;
331 aux = weather_sensors.rain_gauge.ticks * WEATHER_METER_AUX_RAIN_MM;
333 weather_sensors.rain_gauge.value = (uint16_t)aux;
334 process_post(&weather_meter_int_process, rain_gauge_int_event, NULL);
343 if((type != WEATHER_METER_ANEMOMETER) &&
344 (type != WEATHER_METER_RAIN_GAUGE) &&
345 (type != WEATHER_METER_WIND_VANE) &&
346 (type != WEATHER_METER_WIND_VANE_AVG_X) &&
347 (type != WEATHER_METER_ANEMOMETER_AVG) &&
348 (type != WEATHER_METER_ANEMOMETER_AVG_X) &&
349 (type != WEATHER_METER_ANEMOMETER_MAX)) {
350 PRINTF(
"Weather: requested an invalid sensor value\n");
351 return WEATHER_METER_ERROR;
355 PRINTF(
"Weather: module is not configured\n");
356 return WEATHER_METER_ERROR;
360 case WEATHER_METER_WIND_VANE:
361 return weather_meter_get_wind_dir();
363 case WEATHER_METER_WIND_VANE_AVG_X:
364 return wind_vane.value_avg_xm;
366 case WEATHER_METER_ANEMOMETER:
367 return weather_sensors.anemometer.value;
369 case WEATHER_METER_ANEMOMETER_AVG:
370 if(anemometer.value_avg <= 0) {
371 return (uint16_t)anemometer.value_avg;
373 aux = anemometer.value_avg / anemometer.ticks_avg;
374 return (uint16_t)aux;
376 case WEATHER_METER_ANEMOMETER_AVG_X:
377 return anemometer.value_avg_xm;
379 case WEATHER_METER_ANEMOMETER_MAX:
380 return anemometer.value_max;
386 case WEATHER_METER_RAIN_GAUGE:
387#if WEATHER_METER_RAIN_RETURN_TICKS
388 return weather_sensors.rain_gauge.ticks;
390 return weather_sensors.rain_gauge.value;
394 return WEATHER_METER_ERROR;
399configure(
int type,
int value)
401 if((type != WEATHER_METER_ACTIVE) &&
402 (type != WEATHER_METER_ANEMOMETER_INT_OVER) &&
403 (type != WEATHER_METER_RAIN_GAUGE_INT_OVER) &&
404 (type != WEATHER_METER_ANEMOMETER_INT_DIS) &&
405 (type != WEATHER_METER_RAIN_GAUGE_INT_DIS)) {
406 PRINTF(
"Weather: invalid configuration option\n");
407 return WEATHER_METER_ERROR;
410 if(type == WEATHER_METER_ACTIVE) {
412 anemometer.value_avg = 0;
413 anemometer.ticks_avg = 0;
415 weather_sensors.anemometer.int_en = 0;
416 weather_sensors.rain_gauge.int_en = 0;
417 weather_sensors.anemometer.ticks = 0;
418 weather_sensors.rain_gauge.ticks = 0;
419 weather_sensors.anemometer.value = 0;
420 weather_sensors.rain_gauge.value = 0;
423 anemometer_int_callback = NULL;
424 rain_gauge_int_callback = NULL;
426 ANEMOMETER_SENSOR_PIN_MASK);
428 RAIN_GAUGE_SENSOR_PIN_MASK);
431 PRINTF(
"Weather: disabled\n");
432 return WEATHER_METER_SUCCESS;
436 adc_zoul.configure(SENSORS_HW_INIT, WIND_VANE_ADC);
440 GPIO_SET_INPUT(ANEMOMETER_SENSOR_PORT_BASE, ANEMOMETER_SENSOR_PIN_MASK);
443 ANEMOMETER_SENSOR_PIN_MASK);
449 GPIO_SET_INPUT(RAIN_GAUGE_SENSOR_PORT_BASE, RAIN_GAUGE_SENSOR_PIN_MASK);
452 RAIN_GAUGE_SENSOR_PIN_MASK);
459 wind_vane.value_prev = weather_meter_get_wind_dir();
465 NVIC_EnableIRQ(ANEMOMETER_SENSOR_VECTOR);
466 NVIC_EnableIRQ(RAIN_GAUGE_SENSOR_VECTOR);
469 PRINTF(
"Weather: started\n");
470 return WEATHER_METER_SUCCESS;
474 case WEATHER_METER_ANEMOMETER_INT_OVER:
475 weather_sensors.anemometer.int_en = 1;
476 weather_sensors.anemometer.int_thres = value;
477 PRINTF(
"Weather: anemometer threshold %u\n", value);
479 case WEATHER_METER_RAIN_GAUGE_INT_OVER:
480 weather_sensors.rain_gauge.int_en = 1;
481 weather_sensors.rain_gauge.int_thres = value;
482 PRINTF(
"Weather: rain gauge threshold %u\n", value);
484 case WEATHER_METER_ANEMOMETER_INT_DIS:
485 PRINTF(
"Weather: anemometer int disabled\n");
486 weather_sensors.anemometer.int_en = 0;
488 case WEATHER_METER_RAIN_GAUGE_INT_DIS:
489 PRINTF(
"Weather: rain gauge int disabled\n");
490 weather_sensors.rain_gauge.int_en = 0;
493 return WEATHER_METER_ERROR;
496 return WEATHER_METER_SUCCESS;
499SENSORS_SENSOR(weather_meter, WEATHER_METER_SENSOR, value, configure, NULL);
Header file for the Zoul ADC interface.
Header file for the callback timer.
Header file for the GPIO HAL.
Header file with register and macro declarations for the cc2538 GPIO module.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE.
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
#define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on rising edge.
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
#define IOC_OVERRIDE_DIS
Override Disabled.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
#define CLOCK_SECOND
A second, measured in system clock time.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void gpio_hal_register_handler(gpio_hal_event_handler_t *handler)
Register a function to be called whenever a pin triggers an event.
uint32_t gpio_hal_pin_mask_t
GPIO pin mask representation.
#define gpio_hal_pin_to_mask(pin)
Convert a pin to a pin mask.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
void process_exit(struct process *p)
Cause a process to exit.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_YIELD()
Yield the currently running process.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
int timer_expired(struct timer *t)
Check if a timer has expired.
Header file with declarations for the I/O Control module.
Datatype for GPIO event handlers.
Header file for the cc2538 System Control driver.
Timer library header file.
Weather meter header file.
Implementation of a generic module controlling Zoul sensors.