51 #include "lib/sensors.h"
60 #define PRINTF(...) printf(__VA_ARGS__)
65 #define DEBOUNCE_DURATION (CLOCK_SECOND >> 6)
67 #define ANEMOMETER_SENSOR_PORT_BASE GPIO_PORT_TO_BASE(ANEMOMETER_SENSOR_PORT)
68 #define ANEMOMETER_SENSOR_PIN_MASK GPIO_PIN_MASK(ANEMOMETER_SENSOR_PIN)
69 #define RAIN_GAUGE_SENSOR_PORT_BASE GPIO_PORT_TO_BASE(RAIN_GAUGE_SENSOR_PORT)
70 #define RAIN_GAUGE_SENSOR_PIN_MASK GPIO_PIN_MASK(RAIN_GAUGE_SENSOR_PIN)
72 void (*rain_gauge_int_callback)(uint16_t value);
73 void (*anemometer_int_callback)(uint16_t value);
75 static uint8_t enabled;
77 process_event_t anemometer_int_event;
78 process_event_t rain_gauge_int_event;
80 static struct ctimer ct;
81 static struct timer debouncetimer;
88 } weather_meter_sensors_t;
94 uint32_t value_buf_xm;
95 uint16_t value_avg_xm;
96 } weather_meter_ext_t;
100 weather_meter_sensors_t rain_gauge;
101 weather_meter_sensors_t anemometer;
102 } weather_meter_sensors;
105 int32_t value_buf_xm;
107 int16_t value_avg_xm;
108 } weather_meter_wind_vane_ext_t;
110 static weather_meter_sensors weather_sensors;
111 static weather_meter_ext_t anemometer;
112 static weather_meter_wind_vane_ext_t wind_vane;
117 } wind_vane_mid_point_t;
141 static const wind_vane_mid_point_t wind_vane_table[16] = {
161 weather_meter_wind_vane_degrees(uint16_t value)
164 for(i = 0; i < 16; i++) {
165 if(value <= wind_vane_table[i].mid_point) {
166 return (
int)wind_vane_table[i].degree;
169 return (
int)wind_vane_table[i].degree;
174 PRINTF(
"Weather: invalid wind vane value\n");
175 return WEATHER_METER_ERROR;
179 weather_meter_get_wind_dir(
void)
181 weather_sensors.wind_vane = adc_zoul.value(WIND_VANE_ADC);
182 if((int16_t)weather_sensors.wind_vane < 0) {
183 weather_sensors.wind_vane = 0;
185 return weather_meter_wind_vane_degrees(weather_sensors.wind_vane);
189 ct_callback(
void *ptr)
193 int16_t wind_dir_delta;
197 ANEMOMETER_SENSOR_PIN_MASK);
198 wind_speed = weather_sensors.anemometer.ticks;
199 wind_speed *= WEATHER_METER_ANEMOMETER_SPEED_1S;
200 weather_sensors.anemometer.value = (uint16_t)wind_speed;
201 anemometer.ticks_avg++;
202 anemometer.value_avg += weather_sensors.anemometer.value;
203 anemometer.value_buf_xm += weather_sensors.anemometer.value;
206 if(weather_sensors.anemometer.value > anemometer.value_max) {
207 anemometer.value_max = weather_sensors.anemometer.value;
211 wind_dir = weather_meter_get_wind_dir();
212 wind_dir_delta = wind_dir - wind_vane.value_prev;
214 if(wind_dir_delta < -1800) {
215 wind_vane.value_prev += wind_dir_delta + 3600;
216 }
else if(wind_dir_delta > 1800) {
217 wind_vane.value_prev += wind_dir_delta - 3600;
219 wind_vane.value_prev += wind_dir_delta;
222 wind_vane.value_buf_xm += wind_vane.value_prev;
225 if(!(anemometer.ticks_avg % WEATHER_METER_AVG_PERIOD)) {
226 PRINTF(
"\nWeather: calculate the %u averages ***\n", WEATHER_METER_AVG_PERIOD);
228 if(anemometer.value_buf_xm) {
229 anemometer.value_avg_xm = anemometer.value_buf_xm / WEATHER_METER_AVG_PERIOD;
230 anemometer.value_buf_xm = 0;
232 anemometer.value_avg_xm = 0;
235 if(wind_vane.value_buf_xm >= 0) {
236 wind_vane.value_buf_xm = wind_vane.value_buf_xm / WEATHER_METER_AVG_PERIOD;
237 wind_vane.value_avg_xm = wind_vane.value_buf_xm;
239 wind_vane.value_buf_xm = ABS(wind_vane.value_buf_xm) / WEATHER_METER_AVG_PERIOD;
240 wind_vane.value_avg_xm = wind_vane.value_buf_xm;
241 wind_vane.value_avg_xm = ~wind_vane.value_avg_xm + 1;
244 if(wind_vane.value_avg_xm >= 3600) {
245 wind_vane.value_avg_xm -= 3600;
246 }
else if(wind_vane.value_avg_xm < 0) {
247 wind_vane.value_avg_xm += 3600;
250 wind_vane.value_buf_xm = 0;
251 wind_vane.value_prev = wind_dir;
255 if(!anemometer.ticks_avg) {
256 anemometer.value_avg = 0;
259 weather_sensors.anemometer.ticks = 0;
263 ANEMOMETER_SENSOR_PIN_MASK);
268 PROCESS(weather_meter_int_process,
"Weather meter interrupt process handler");
278 if((ev == anemometer_int_event) && (weather_sensors.anemometer.int_en)) {
279 if(weather_sensors.anemometer.ticks >=
280 weather_sensors.anemometer.int_thres) {
281 anemometer_int_callback(weather_sensors.anemometer.ticks);
285 if((ev == rain_gauge_int_event) && (weather_sensors.rain_gauge.int_en)) {
286 if(weather_sensors.rain_gauge.ticks >=
287 weather_sensors.rain_gauge.int_thres) {
288 rain_gauge_int_callback(weather_sensors.rain_gauge.ticks);
296 weather_meter_interrupt_handler(uint8_t port, uint8_t pin)
311 if((port == ANEMOMETER_SENSOR_PORT) && (pin == ANEMOMETER_SENSOR_PIN)) {
312 weather_sensors.anemometer.ticks++;
314 }
else if((port == RAIN_GAUGE_SENSOR_PORT) && (pin == RAIN_GAUGE_SENSOR_PIN)) {
315 weather_sensors.rain_gauge.ticks++;
316 aux = weather_sensors.rain_gauge.ticks * WEATHER_METER_AUX_RAIN_MM;
318 weather_sensors.rain_gauge.value = (uint16_t)aux;
328 if((type != WEATHER_METER_ANEMOMETER) &&
329 (type != WEATHER_METER_RAIN_GAUGE) &&
330 (type != WEATHER_METER_WIND_VANE) &&
331 (type != WEATHER_METER_WIND_VANE_AVG_X) &&
332 (type != WEATHER_METER_ANEMOMETER_AVG) &&
333 (type != WEATHER_METER_ANEMOMETER_AVG_X) &&
334 (type != WEATHER_METER_ANEMOMETER_MAX)) {
335 PRINTF(
"Weather: requested an invalid sensor value\n");
336 return WEATHER_METER_ERROR;
340 PRINTF(
"Weather: module is not configured\n");
341 return WEATHER_METER_ERROR;
345 case WEATHER_METER_WIND_VANE:
346 return weather_meter_get_wind_dir();
348 case WEATHER_METER_WIND_VANE_AVG_X:
349 return wind_vane.value_avg_xm;
351 case WEATHER_METER_ANEMOMETER:
352 return weather_sensors.anemometer.value;
354 case WEATHER_METER_ANEMOMETER_AVG:
355 if(anemometer.value_avg <= 0) {
356 return (uint16_t)anemometer.value_avg;
358 aux = anemometer.value_avg / anemometer.ticks_avg;
359 return (uint16_t)aux;
361 case WEATHER_METER_ANEMOMETER_AVG_X:
362 return anemometer.value_avg_xm;
364 case WEATHER_METER_ANEMOMETER_MAX:
365 return anemometer.value_max;
371 case WEATHER_METER_RAIN_GAUGE:
372 #if WEATHER_METER_RAIN_RETURN_TICKS
373 return weather_sensors.rain_gauge.ticks;
375 return weather_sensors.rain_gauge.value;
379 return WEATHER_METER_ERROR;
384 configure(
int type,
int value)
386 if((type != WEATHER_METER_ACTIVE) &&
387 (type != WEATHER_METER_ANEMOMETER_INT_OVER) &&
388 (type != WEATHER_METER_RAIN_GAUGE_INT_OVER) &&
389 (type != WEATHER_METER_ANEMOMETER_INT_DIS) &&
390 (type != WEATHER_METER_RAIN_GAUGE_INT_DIS)) {
391 PRINTF(
"Weather: invalid configuration option\n");
392 return WEATHER_METER_ERROR;
395 if(type == WEATHER_METER_ACTIVE) {
397 anemometer.value_avg = 0;
398 anemometer.ticks_avg = 0;
400 weather_sensors.anemometer.int_en = 0;
401 weather_sensors.rain_gauge.int_en = 0;
402 weather_sensors.anemometer.ticks = 0;
403 weather_sensors.rain_gauge.ticks = 0;
404 weather_sensors.anemometer.value = 0;
405 weather_sensors.rain_gauge.value = 0;
408 anemometer_int_callback =
NULL;
409 rain_gauge_int_callback =
NULL;
411 ANEMOMETER_SENSOR_PIN_MASK);
413 RAIN_GAUGE_SENSOR_PIN_MASK);
416 PRINTF(
"Weather: disabled\n");
417 return WEATHER_METER_SUCCESS;
421 adc_zoul.configure(SENSORS_HW_INIT, WIND_VANE_ADC);
425 GPIO_SET_INPUT(ANEMOMETER_SENSOR_PORT_BASE, ANEMOMETER_SENSOR_PIN_MASK);
428 ANEMOMETER_SENSOR_PIN_MASK);
431 ANEMOMETER_SENSOR_PIN);
435 GPIO_SET_INPUT(RAIN_GAUGE_SENSOR_PORT_BASE, RAIN_GAUGE_SENSOR_PIN_MASK);
438 RAIN_GAUGE_SENSOR_PIN_MASK);
441 RAIN_GAUGE_SENSOR_PIN);
446 wind_vane.value_prev = weather_meter_get_wind_dir();
456 PRINTF(
"Weather: started\n");
457 return WEATHER_METER_SUCCESS;
461 case WEATHER_METER_ANEMOMETER_INT_OVER:
462 weather_sensors.anemometer.int_en = 1;
463 weather_sensors.anemometer.int_thres = value;
464 PRINTF(
"Weather: anemometer threshold %u\n", value);
466 case WEATHER_METER_RAIN_GAUGE_INT_OVER:
467 weather_sensors.rain_gauge.int_en = 1;
468 weather_sensors.rain_gauge.int_thres = value;
469 PRINTF(
"Weather: rain gauge threshold %u\n", value);
471 case WEATHER_METER_ANEMOMETER_INT_DIS:
472 PRINTF(
"Weather: anemometer int disabled\n");
473 weather_sensors.anemometer.int_en = 0;
475 case WEATHER_METER_RAIN_GAUGE_INT_DIS:
476 PRINTF(
"Weather: rain gauge int disabled\n");
477 weather_sensors.rain_gauge.int_en = 0;
480 return WEATHER_METER_ERROR;
483 return WEATHER_METER_SUCCESS;
486 SENSORS_SENSOR(weather_meter, WEATHER_METER_SENSOR, value, configure,
NULL);
#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 DEBOUNCE_DURATION
Delay before button state is assumed to be stable.
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable 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 IOC_OVERRIDE_DIS
Override Disabled.
Timer library header file.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
Header file for the Zoul ADC interface.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
void process_exit(struct process *p)
Cause a process to exit.
Implementation of a generic module controlling Zoul sensors.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
Header file for the callback timer
#define NULL
The null pointer.
Header file with declarations for the I/O Control module.
#define PROCESS_YIELD()
Yield the currently running process.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Header file for the cc2538 System Control driver.
#define CLOCK_SECOND
A second, measured in system clock time.
#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.
void process_start(struct process *p, process_data_t data)
Start a process.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable 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.
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
Weather meter header file.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define PROCESS_BEGIN()
Define the beginning of a process.