Sparkfun: PIR Motion Sensor

From eLinux.org
Jump to: navigation, search


Overview: 2
Wiring:   2
Code:     1, Comment you code and give details of how to use it.
git:      2, put in git
Demo:     2
Total:    9-1=8 (-1 for second try)
Comments: Much better

Overview

The PIR Motion Sensor can be purchased from SparkFun. The datasheet describes it:

Easy-to-use motion detector with an analog interface. Power it with 5-12VDC, and you'll be alerted of any movement.

I found this tutorial very helpful: Arduino Tutorial

Wiring

PIRMotionSensor.jpg

This unit works great from 5 to 12V (datasheet shows 12V). You can also install a jumper wire past the 5V regulator on board to make this unit work at 3.3V. Sensor uses 1.6mA@3.3V. For the best results I found that I needed to power the sensor using the constant 5V power source on the BeagleBoard Bone Rail. This has the side effect of the device producing a 5V signal, which is to high to run through the gpio pins on the rail. To fix this the output signal needs to be reduced. Also, when wiring up the device the power pin needs a 10k pull-up resistor.

Sample C Code

The GPIO pins the you connect the senor to, is taken in as an argument to the program. Program found at https://github.com/atniptw/ECE497/tree/master/MiniProjects/Project2


/*Standard C Libraries*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>

/*Library I made to assist with GPIO handling*/
#include "gpio.h"

/****************************************************************
 * Constants
 ****************************************************************/
 
#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define POLL_TIMEOUT (3 * 1000) /* 3 seconds */
#define MAX_BUF 64

/****************************************************************
 * Global variables
 ****************************************************************/
int keepgoing = 1;	// Set to 0 when ctrl-c is pressed

/****************************************************************
 * signal_handler
 ****************************************************************/
// Callback called when SIGINT is sent to the process (Ctrl-C)
void signal_handler(int sig)
{
	printf( "Ctrl-C pressed, cleaning up and exiting..\n" );
	keepgoing = 0;
}

/****************************************************************
 * main
 ****************************************************************/
int main(int argc, char **argv)
{
	struct pollfd fdset[2];
	int nfds = 2;
	int gpio_fd, timeout, rc;
	char *buf[MAX_BUF];
	unsigned int gpio;
	int len;

	if (argc < 2) {
		printf("Usage: gpio-int <gpio-pin>\n\n");
		printf("Waits for a change in the GPIO pin voltage level or input on stdin\n");
		exit(-1);
	}

	// Set the signal callback for Ctrl-C
	signal(SIGINT, signal_handler);

	gpio = atoi(argv[1]);

	gpio_export(gpio);
	gpio_set_dir(gpio, 0);
	gpio_set_edge(gpio, "falling");  // Can be rising, falling or both
	gpio_fd = gpio_fd_open(gpio);

	timeout = POLL_TIMEOUT;

	while (keepgoing) {
		memset((void*)fdset, 0, sizeof(fdset));

		fdset[0].fd = STDIN_FILENO;
		fdset[0].events = POLLIN;
      
		fdset[1].fd = gpio_fd;
		fdset[1].events = POLLPRI;

		rc = poll(fdset, nfds, timeout);      

		if (rc < 0) {
			printf("\npoll() failed!\n");
			return -1;
		}
      
		if (rc == 0) {
			printf(".");
		}
                /* From the example code for doing interupts */
		if (fdset[1].revents & POLLPRI) {
			lseek(fdset[1].fd, 0, SEEK_SET);  // Read from the start of the file
			len = read(fdset[1].fd, buf, MAX_BUF);
                        /* A change in the signal means that there was motion detected */
			printf("\nMotion Detected, value=%c, len=%d\n",
				 buf[0], len);
                        /* The sensor needs a moment to re-calibrate after it was been tripped */
			usleep(5000000);
		}

		if (fdset[0].revents & POLLIN) {
			(void)read(fdset[0].fd, buf, 1);
			printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
		}

		fflush(stdout);
	}

	gpio_fd_close(gpio_fd);
	return 0;
}