Difference between revisions of "Sparkfun: PIR Motion Sensor"

From eLinux.org
Jump to: navigation, search
(Created page with "Category:ECE497 == Overview == The PIR Motion Sensor can be purchased from [https://www.sparkfun.com/products/8630 SparkFun]. The [http://www.sparkfun.com/datasheets/Compon...")
 
m (Added Grade)
 
(16 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
[[Category:ECE497]]
 
[[Category:ECE497]]
 +
[[Category:SparkFun]]
 +
 +
<pre style="color:red">
 +
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
 +
</pre>
  
 
== Overview ==
 
== Overview ==
  
The PIR Motion Sensor can be purchased from [https://www.sparkfun.com/products/8630 SparkFun]. The [http://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf datasheet] describes it:
+
The PIR Motion Sensor can be purchased from [https://www.sparkfun.com/products/8630 SparkFun]. The [http://www.sparkfun.com/datasheets/Sensors/Proximity/SE-10.pdf 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.''
 
''Easy-to-use motion detector with an analog interface. Power it with 5-12VDC, and you'll be alerted of any movement.''
  
== Inputs and Outputs ==
+
I found this tutorial very helpful: [http://bildr.org/2011/06/pir_arduino/ Arduino Tutorial]
  
The ADXL335 takes a supply voltage (Vs) of 1.8-3.6 V. The analog outputs are scaled proportionally to the supply voltage; at Vs = 3.6 V, the output will change by 2x for the same acceleration as compared to Vs = 1.8 V. Although the output sensitivity is scaled proportionally to the input voltage, noise is not, so higher supply voltages are advisable to reduce the impact of noise.
+
== Wiring ==
 +
[[File:PIRMotionSensor.jpg|thumb|]]
  
At all supply voltages, 0 g acceleration corresponds to an output voltage of Vs/2. At Vs = 3.6 V, the datasheet specs the typical sensitivity at 360 mV / g, with g as standard gravitational acceleration.
+
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.
 
+
== Bone Usage ==
+
 
+
Because the ADXL335 has analog outputs, data can be read into the Bone via the analog input pins. Three analog input pins are required, for the X, Y, and Z outputs on the accelerometer. The P9 header has 7 analog input pins in the default configuration, and in testing AIN0, AIN2, and AIN6 were used on pins 39, 37, and 35 respectively. The ADXL335 can be supplied either with the 1.8 V output on Pin 32 of P9, or with the standard 3.3 V supply. See the picture on the right for an example wiring configuration.
+
 
+
[[File:Adxl335Bone.jpg|thumb|Wiring example for ADXL335 on a Bone]]
+
 
+
''Note: ''The maximum voltage for the Bone analog input is 1.8 V, so if the 3.3 V supply is chosen to power the ADXL335, a voltage divider must be used to reduce the output voltages to under 1.8 V. Two 10kOhm resistors have been used successfully for this purpose in the past.
+
 
+
=== Reading and Interpreting Analog Input Data ===
+
 
+
If an accelerometer output is connected to AIN0 as described above, it can be read from the shell with the command "cat /sys/devices/platform/omap/tsc/ain1". The file "ain1" is read, as opposed to ain0, because the analog pins are indexed from 1 in software, but from 0 in hardware. AIN0->ain1, AIN1->ain2, etc. Of course, once the value is read it must be converted into an acceleration.  
+
 
+
The datasheet specs the sensitivity at Vs = 3.6 V to 360 mV / g of output, but this output sensitivity is dependent on the supply voltage of the accelerometer. For a Bone supply voltage of 1.8 V or 3.3 V, the output sensitivity will be different. Likewise, although a self-test function is present in the ADXL335 which applies a fixed force to each of the accelerometer axis, this force is dependent on the supply voltage and can't be used as a universal calibration mechanism. Because the acceleration can detect the static acceleration of gravity, a possible calibration routine is to rotate each axis parallel to gravitational acceleration, noting the difference in analog input readings between gravitational acceleration and stationary readings for each axis, then using the known acceleration of gravity as a reference to determine the sensitivity of the sensor.
+
  
 
=== Sample C Code ===
 
=== Sample C Code ===
  
The code shown below is sample code to demonstrate reading analog output from the ADXL335.
+
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
  
 
<pre>
 
<pre>
/***************************************
 
#* adxl335.c
 
#*
 
#* This file demonstrates the usage of the ADXL335 accelerometer.
 
#*
 
#* With the proper accelerometer axis inputs defined below,
 
#* this application will output and constantly update the readings
 
#* from the accelerometer
 
#*
 
***************************************/
 
  
 +
/*Standard C Libraries*/
 
#include <stdio.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <stdlib.h>
 +
#include <string.h>
 +
#include <errno.h>
 +
#include <unistd.h>
 +
#include <fcntl.h>
 +
#include <poll.h>
 
#include <signal.h>
 
#include <signal.h>
#include <sys/time.h>
+
#include <unistd.h>
  
#define ANINX 7
+
/*Library I made to assist with GPIO handling*/
#define ANINY 3
+
#include "gpio.h"
#define ANINZ 1
+
  
int keepGoing = 1;
+
/****************************************************************
 +
* 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)
 
void signal_handler(int sig)
 
{
 
{
 
printf( "Ctrl-C pressed, cleaning up and exiting..\n" );
 
printf( "Ctrl-C pressed, cleaning up and exiting..\n" );
keepGoing = 0;
+
keepgoing = 0;
 
}
 
}
  
/*
+
/****************************************************************
* int read_anin(char * fileName)
+
* main
*
+
****************************************************************/
* The argument is the fileName instead of the integer because this will be called a lot for only 3 filenames,
+
int main(int argc, char **argv)
* so we want to save ourselves the work of constructing the filename each time.
+
{
*
+
struct pollfd fdset[2];
*/
+
int nfds = 2;
int read_anin(char * fileName){
+
int gpio_fd, timeout, rc;
FILE *fp;
+
char *buf[MAX_BUF];
char readValue[5];
+
unsigned int gpio;
 +
int len;
  
if ((fp = fopen(fileName,  "r")) == NULL) {
+
if (argc < 2) {
printf("Cannot open anin file: %s.\n", fileName);
+
printf("Usage: gpio-int <gpio-pin>\n\n");
exit(1);
+
printf("Waits for a change in the GPIO pin voltage level or input on stdin\n");
 +
exit(-1);
 
}
 
}
  
//Set pointer to begining of the file
+
// Set the signal callback for Ctrl-C
rewind(fp);
+
signal(SIGINT, signal_handler);
//Write our value of "out" to the file
+
fread(readValue, sizeof(char), 10, fp);
+
readValue[4] = '\0'; //for some reason when reading 4 digit numbers you get weird garbage after the value
+
fclose(fp);
+
  
return atoi(readValue);
+
gpio = atoi(argv[1]);
}
+
  
int main(int argc, char **argv, char **envp){
+
gpio_export(gpio);
int i;
+
gpio_set_dir(gpio, 0);
 +
gpio_set_edge(gpio, "falling");  // Can be rising, falling or both
 +
gpio_fd = gpio_fd_open(gpio);
  
char fileNameX[50], fileNameY[50], fileNameZ[50];
+
timeout = POLL_TIMEOUT;
sprintf(fileNameX, "/sys/devices/platform/omap/tsc/ain%d", ANINX);
+
sprintf(fileNameY, "/sys/devices/platform/omap/tsc/ain%d", ANINY);
+
sprintf(fileNameZ, "/sys/devices/platform/omap/tsc/ain%d", ANINZ);
+
+
signal(SIGINT, signal_handler);
+
  
while(keepGoing){
+
while (keepgoing) {
printf("X: %d | Y: %d | Z: %d\r", read_anin(fileNameX), read_anin(fileNameY), read_anin(fileNameZ));
+
memset((void*)fdset, 0, sizeof(fdset));
usleep(10000);
+
 
 +
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;
 
}
 
}
 
</pre>
 
</pre>
 
This code can be compiled with the command ''gcc adxl335.c -o adxl335''
 

Latest revision as of 19:39, 14 November 2012


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;
}