
7 changed files with 380 additions and 0 deletions
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup driver_pir PIR Motion Sensor |
||||
* @ingroup drivers |
||||
* @brief Device driver interface for the PIR motion sensor |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Device driver interface for the PIR motion sensor |
||||
* |
||||
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef __PIR_H |
||||
#define __PIR_H |
||||
|
||||
#include "kernel_types.h" |
||||
#include "periph/gpio.h" |
||||
|
||||
/**
|
||||
* @brief device descriptor for a PIR sensor |
||||
*/ |
||||
typedef struct { |
||||
gpio_t gpio_dev; /**< GPIO device which is used */ |
||||
kernel_pid_t msg_thread_pid; /**< thread to msg on irq */ |
||||
} pir_t; |
||||
|
||||
#ifndef PIR_MSG_T_STATUS_START |
||||
#define PIR_MSG_T_STATUS_START 150 |
||||
#endif |
||||
|
||||
typedef enum { |
||||
PIR_STATUS_HI = PIR_MSG_T_STATUS_START, /**< motion was detected */ |
||||
PIR_STATUS_LO, /**< no motion is detected */ |
||||
} pir_event_t; |
||||
|
||||
/**
|
||||
* @brief Initialize a PIR motion sensor |
||||
* |
||||
* The PIR motion sensor is interfaced by a single GPIO pin, specified by |
||||
* `gpio`. |
||||
* |
||||
* @note |
||||
* The sensor needs up to a minute to settle down before meaningful |
||||
* measurements can be made. |
||||
* |
||||
* @param[out] dev device descriptor of an PIR sensor |
||||
* @param[in] gpio the GPIO device the sensor is connected to |
||||
* |
||||
* @return 0 on success |
||||
* @return -1 on error |
||||
*/ |
||||
int pir_init(pir_t *dev, gpio_t gpio); |
||||
|
||||
/**
|
||||
* @brief Read the current status of the motion sensor |
||||
* |
||||
* @param[in] dev device descriptor of the PIR motion sensor to read from |
||||
* |
||||
* @return 1 if motion is detected, 0 otherwise |
||||
*/ |
||||
pir_event_t pir_get_status(pir_t *dev); |
||||
|
||||
/**
|
||||
* @brief Register a thread for notification whan state changes on the |
||||
* motion sensor. |
||||
* |
||||
* @note |
||||
* This configures the gpio device for interrupt driven operation. |
||||
* |
||||
* @param[in] dev device descriptor of the PIR motion sensor to |
||||
* register for |
||||
* |
||||
* @return 0 on succuess, |
||||
* @return -1 on internal errors, |
||||
* @return -2 if another thread is registered already |
||||
*/ |
||||
int pir_register_thread(pir_t *dev); |
||||
|
||||
#endif /* __PIR_H */ |
||||
/** @} */ |
@ -0,0 +1,3 @@
|
||||
MODULE = pir
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup driver_pir |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Device driver implementation for the PIR motion sensor |
||||
* |
||||
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include "pir.h" |
||||
#include "thread.h" |
||||
#include "msg.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
/**********************************************************************
|
||||
* internal API declaration |
||||
**********************************************************************/ |
||||
|
||||
static int pir_activate_int(pir_t *dev); |
||||
static void pir_callback(void *dev); |
||||
static void pir_send_msg(pir_t *dev, pir_event_t event); |
||||
|
||||
/**********************************************************************
|
||||
* public API implementation |
||||
**********************************************************************/ |
||||
|
||||
int pir_init(pir_t *dev, gpio_t gpio) |
||||
{ |
||||
dev->gpio_dev = gpio; |
||||
dev->msg_thread_pid = KERNEL_PID_UNDEF; |
||||
return gpio_init_in(dev->gpio_dev, GPIO_NOPULL); |
||||
} |
||||
|
||||
pir_event_t pir_get_status(pir_t *dev) |
||||
{ |
||||
return ((gpio_read(dev->gpio_dev) == 0) ? PIR_STATUS_LO : PIR_STATUS_HI); |
||||
} |
||||
|
||||
int pir_register_thread(pir_t *dev) |
||||
{ |
||||
if (dev->msg_thread_pid != KERNEL_PID_UNDEF) { |
||||
if (dev->msg_thread_pid != thread_getpid()) { |
||||
DEBUG("pir_register_thread: already registered to another thread\n"); |
||||
return -2; |
||||
} |
||||
} |
||||
else { |
||||
DEBUG("pir_register_thread: activating interrupt for %p..\n", dev); |
||||
if (pir_activate_int(dev) != 0) { |
||||
DEBUG("\tfailed\n"); |
||||
return -1; |
||||
} |
||||
DEBUG("\tsuccess\n"); |
||||
} |
||||
dev->msg_thread_pid = thread_getpid(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**********************************************************************
|
||||
* internal API implementation |
||||
**********************************************************************/ |
||||
|
||||
static void pir_send_msg(pir_t *dev, pir_event_t event) |
||||
{ |
||||
DEBUG("pir_send_msg\n"); |
||||
msg_t m = { .type = event, .content.ptr = (char*) dev, }; |
||||
|
||||
int ret = msg_send_int(&m, dev->msg_thread_pid); |
||||
DEBUG("pir_send_msg: msg_send_int: %i\n", ret); |
||||
switch (ret) { |
||||
case 0: |
||||
DEBUG("pir_send_msg: msg_thread_pid not receptive, event is lost"); |
||||
break; |
||||
case 1: |
||||
DEBUG("pir_send_msg: OK"); |
||||
break; |
||||
case -1: |
||||
DEBUG("pir_send_msg: msg_thread_pid is gone, clearing it"); |
||||
dev->msg_thread_pid = KERNEL_PID_UNDEF; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static void pir_callback(void *arg) |
||||
{ |
||||
DEBUG("pir_callback: %p\n", arg); |
||||
pir_t *dev = (pir_t*) arg; |
||||
if (dev->msg_thread_pid != KERNEL_PID_UNDEF) { |
||||
pir_send_msg(dev, pir_get_status(dev)); |
||||
} |
||||
} |
||||
|
||||
static int pir_activate_int(pir_t *dev) |
||||
{ |
||||
return gpio_init_int(dev->gpio_dev, GPIO_NOPULL, GPIO_BOTH, pir_callback, dev); |
||||
} |
@ -0,0 +1,29 @@
|
||||
APPLICATION = driver_pir
|
||||
include ../Makefile.tests_common |
||||
|
||||
# These boards do not suport periph/gpio.h at the time of this writing:
|
||||
BOARD_BLACKLIST = native arduino-mega2560 avsextrem chronos mbed_lpc1768 msb-430 msb-430h msba2 pttu qemu-i386 redbee-econotag telosb wsn430-v1_3b wsn430-v1_4 z1
|
||||
|
||||
# Define default pin mappings for some boards:
|
||||
BOARD_WHITELIST = stm32f4discovery arduino-due
|
||||
ifneq (,$(filter stm32f4discovery,$(BOARD))) |
||||
export PIR_GPIO ?= GPIO_8
|
||||
endif |
||||
ifneq (,$(filter arduino-due,$(BOARD))) |
||||
export PIR_GPIO ?= GPIO_10
|
||||
endif |
||||
|
||||
USEMODULE += pir
|
||||
USEMODULE += vtimer
|
||||
|
||||
ifneq (,$(PIR_GPIO)) |
||||
CFLAGS += -DPIR_GPIO=$(PIR_GPIO)
|
||||
endif |
||||
|
||||
include $(RIOTBASE)/Makefile.include |
||||
|
||||
all-polling: CFLAGS += -DTEST_PIR_POLLING |
||||
|
||||
all-polling: all |
||||
|
||||
all-interrupt: all |
@ -0,0 +1,60 @@
|
||||
# About |
||||
This is a manual test application for the PIR motion sensor driver. |
||||
|
||||
In order to build this application, you need to add the board to the |
||||
Makefile's `WHITELIST` first and define a pin mapping (see below). |
||||
|
||||
|
||||
# Usage |
||||
There are two ways to test this. You can either actively poll the sensor |
||||
state, or you can register a thread which receives messages for state |
||||
changes. |
||||
|
||||
## Interrupt driven |
||||
Connect the sensor's "out" pin to a GPIO of your board that can be |
||||
configured to create interrupts. |
||||
Compile and flash this test application like: |
||||
|
||||
export BOARD=your_board |
||||
export PIR_GPIO=name_of_your_pin |
||||
make clean |
||||
make all-interrupt |
||||
make flash |
||||
|
||||
The output should look like: |
||||
|
||||
kernel_init(): jumping into first task... |
||||
|
||||
PIR motion sensor test application |
||||
|
||||
Initializing PIR sensor at GPIO_8... [OK] |
||||
|
||||
Registering PIR handler thread... [OK] |
||||
PIR handler got a message: the movement has ceased. |
||||
PIR handler got a message: something started moving. |
||||
PIR handler got a message: the movement has ceased. |
||||
|
||||
|
||||
## Polling Mode |
||||
Connect the sensor's "out" pin to any GPIO pin of you board. |
||||
Compile and flash this test application like: |
||||
|
||||
export BOARD=your_board |
||||
export PIR_GPIO=name_of_your_pin |
||||
make clean |
||||
make all-polling |
||||
make flash |
||||
|
||||
The output should look like this: |
||||
|
||||
kernel_init(): jumping into first task... |
||||
PIR motion sensor test application |
||||
|
||||
Initializing PIR sensor at GPIO_10... [OK] |
||||
|
||||
Printing sensor state every second. |
||||
Status: lo |
||||
... |
||||
Status: lo |
||||
Status: hi |
||||
... |
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup tests |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Test application for the PIR motion sensor driver |
||||
* |
||||
* @author Ludwig Ortmann <ludwig.ortmann@fu-berlin.de> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#ifndef PIR_GPIO |
||||
#error "PIR_GPIO not defined" |
||||
#endif |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include "thread.h" |
||||
#include "vtimer.h" |
||||
#include "pir.h" |
||||
|
||||
char pir_handler_stack[KERNEL_CONF_STACKSIZE_MAIN]; |
||||
pir_t dev; |
||||
|
||||
void* pir_handler(void *arg) |
||||
{ |
||||
msg_t msg_q[1]; |
||||
msg_init_queue(msg_q, 1); |
||||
|
||||
printf("Registering PIR handler thread... %s\n", |
||||
pir_register_thread(&dev) == 0 ? "[OK]" : "[Failed]"); |
||||
|
||||
msg_t m; |
||||
while (msg_receive(&m)) { |
||||
printf("PIR handler got a message: "); |
||||
switch (m.type) { |
||||
case PIR_STATUS_HI: |
||||
puts("something started moving."); |
||||
break; |
||||
case PIR_STATUS_LO: |
||||
puts("the movement has ceased."); |
||||
break; |
||||
default: |
||||
puts("stray message."); |
||||
break; |
||||
} |
||||
} |
||||
puts("PIR handler: this should not have happened!"); |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
int main(void) |
||||
{ |
||||
puts("PIR motion sensor test application\n"); |
||||
printf("Initializing PIR sensor at GPIO_%i... ", PIR_GPIO); |
||||
if (pir_init(&dev, PIR_GPIO) == 0) { |
||||
puts("[OK]\n"); |
||||
} |
||||
else { |
||||
puts("[Failed]"); |
||||
return 1; |
||||
} |
||||
|
||||
#if TEST_PIR_POLLING |
||||
puts("Printing sensor state every second."); |
||||
while (1) { |
||||
printf("Status: %s\n", pir_get_status(&dev) == PIR_STATUS_LO ? "lo" : "hi"); |
||||
vtimer_usleep(1000 * 1000); |
||||
} |
||||
#else |
||||
thread_create( |
||||
pir_handler_stack, sizeof(pir_handler_stack), PRIORITY_MAIN - 1, |
||||
CREATE_WOUT_YIELD | CREATE_STACKTEST, |
||||
pir_handler, NULL, "pir_handler"); |
||||
#endif |
||||
return 0; |
||||
} |
Loading…
Reference in new issue