Motion Sensor
I make a simple motion sensor from scratch for using with the Raspberry Pi.
I bemused a lot about building a motion sensor, but now I can actually post something useful. Everything I am about to tell you about can be found at my github page, including the Eagle files and Arduino scripts. Here is the finished product (still thinking about making an enclosure):
Motion sensor + RF transmitter
Components (order from eBay to get really cheap)
The motion sensor is simply a PIR sensor connected to a 434MHz RF transmitter via an encoder. The encoder uses four bits, in the form of resistors tied to HIGH (+VCC) or LOW (GND). That’s enough for 12 sensors. The ATtiny85 is programmed via an Arduino which allows for devising a smart way of sending the RF data. It can be programmed to send the output as randomized timed sequences in order to reduce the conflicts of having other motion sensors on the same band. I also used some code from Alex for running the ATtiny at low power, so it is battery capable:
#include <avr/sleep.h> //Needed for sleep_mode
#include <avr/wdt.h> //Needed to enable/disable watch dog timer
int pinLed = 0;
int irSensor = 2; // (pin 7 on chip)
void setup(){
pinMode(pinLed,OUTPUT);
pinMode(irSensor,INPUT);
//Power down various bits of hardware to lower power usage
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT
sleep_enable();
}
void loop(){
ADCSRA &= ~(1<<ADEN); //Disable ADC, saves ~230uA
setup_watchdog(5); //Setup watchdog to go off after 1sec
sleep_mode(); //Go to sleep! Wake up 1sec later and check water
//Check for water
ADCSRA |= (1<<ADEN); //Enable ADC
int val = digitalRead(irSensor);
while (val == HIGH) {
digitalWrite(pinLed, HIGH); // turn the LED on (HIGH is the voltage level)
delay(500); // wait for a second
val = digitalRead(irSensor);
}
digitalWrite(pinLed, LOW); // turn the LED off by making the voltage LOW
}
//This runs each time the watch dog wakes us up from sleep
ISR(WDT_vect) {
//Don't do anything. This is just here so that we wake up.
}
//Sets the watchdog timer to wake us up, but not reset
//0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
//6=1sec, 7=2sec, 8=4sec, 9=8sec
//From: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void setup_watchdog(int timerPrescaler) {
if (timerPrescaler > 9 ) timerPrescaler = 9; //Limit incoming amount to legal settings
byte bb = timerPrescaler & 7;
if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary
//This order of commands is important and cannot be combined
MCUSR &= ~(1<<WDRF); //Clear the watch dog reset
WDTCR |= (1<<WDCE) | (1<<WDE); //Set WD_change enable, set WD enable
WDTCR = bb; //Set new watchdog timeout value
WDTCR |= _BV(WDIE); //Set the interrupt enable, this will keep unit from resetting after each int
}
Here is the schematic for the main motion sensor module:
And the resulting board schematic (after lots of trials to eliminate air-wires):
To make the board, I followed the instructions from blondihacks to the tee. The only difference is that I used a etching solution of 4% HCl and 1% H2O2 which etched in about 10min (the vinegar was too slow for me). Here is the finished version after some trial and error.
RF Receiver
Components
- Arduino
- PT2272 encoder
- 434 MHz RF receiver
This circuit is even simpler. Connect the RF receiver output to the DIN of the PT2272. Then put each output pin (the four bits) into the Arduino pins 3-6. It’s best to connect the VT (Viable Transmission indicator) pin of the PT2272 to the Pin 2 of the Arduino so that you can attach an interrupt on it. This way whenever VT goes high, the Arduino will read the other four pins and use that to determine which sensor is which (I leave this to you, though). The basic code for this is very simple:
int ledpin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE); //pin 2
Serial.begin(9600);
}
void loop()
{
digitalWrite(ledpin, state);
}
void blink()
{
int a = digitalRead(3);
int b = digitalRead(4);
int c = digitalRead(5);
int d = digitalRead(6);
Serial.println(String(a) + " " + String(b) + " " + String(c) + " " + String(d) + " ");
if (a+b+c+d>0){
state = true;
} else{
state = false;
}
}