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) 73 void (*rain_gauge_int_callback)(uint16_t value);
74 void (*anemometer_int_callback)(uint16_t value);
76 static uint8_t enabled;
78 process_event_t anemometer_int_event;
79 process_event_t rain_gauge_int_event;
81 static struct ctimer ct;
82 static struct timer debouncetimer;
89 } weather_meter_sensors_t;
95 uint32_t value_buf_xm;
96 uint16_t value_avg_xm;
97 } weather_meter_ext_t;
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;
111 static weather_meter_sensors weather_sensors;
112 static weather_meter_ext_t anemometer;
113 static weather_meter_wind_vane_ext_t wind_vane;
118 } wind_vane_mid_point_t;
142 static const wind_vane_mid_point_t wind_vane_table[16] = {
162 weather_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;
180 weather_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);
190 ct_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);
269 PROCESS(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,
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;
399 configure(
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();
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;
499 SENSORS_SENSOR(weather_meter, WEATHER_METER_SENSOR, value, configure, NULL);
Datatype for GPIO event handlers.
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
#define PROCESS(name, strname)
Declare a process.
Header file for the cc2538 System Control driver.
Weather meter header file.
#define PROCESS_BEGIN()
Define the beginning of a process.
Header file with register and macro declarations for the cc2538 GPIO module.
#define PROCESS_END()
Define the end of a process.
Header file with declarations for the I/O Control module.
#define IOC_OVERRIDE_DIS
Override Disabled.
Timer library header file.
#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.
Implementation of a generic module controlling Zoul sensors.
void process_exit(struct process *p)
Cause a process to exit.
void gpio_hal_register_handler(gpio_hal_event_handler_t *handler)
Register a function to be called whenever a pin triggers an event.
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
Enable External Interrupt.
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
#define CLOCK_SECOND
A second, measured in system clock time.
Header file for the callback timer
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
int timer_expired(struct timer *t)
Check if a timer has expired.
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
#define PROCESS_YIELD()
Yield the currently running process.
uint32_t gpio_hal_pin_mask_t
GPIO pin mask representation.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
#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...
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
#define gpio_hal_pin_to_mask(pin)
Convert a pin to a pin mask.
Header file for the GPIO HAL.
Header file for the Zoul ADC interface.
void process_start(struct process *p, process_data_t data)
Start a process.