Fred 453 Posted December 6, 2011 Share Posted December 6, 2011 Well, my first project is nothing spectacular. I call it the Pee-Light. When I walk into my bathroom in the middle of the night, an LED light in the ceiling gives me just enough light to see what I'm doing and not pee on the toilet seat. It's not enough to blind me when it comes on and I still have my night vision when I'm stumbling back to bed. On the negative side It probably lies somewhere between a project and "using a commercial product as intended". 90% of the hardware and maybe 75% of the software is an Olimex MSP430-PIR which itself was based on a reference design from TI. On the positive side It acheived my goal of finding my way around the MSP430. I didn't just copy and add to the software. I made sure I shifted code into my project bit by bit and understood it all. I used the USB stick from my EZ430-F2013 kit to program it. It's permanently and properly installed in my house and gets used at least once a day. (I've got a new baby so I'm up a lot.) The existing PIR sensor flashed an LED when it sensed movement. My extension to it was to use a light-dependent resistor to check whether it's dark and a simple transistor to allow a 9v battery to power an LED, The LED fitting I had lying around was designed for 12v and is sealed, but actually gives just the right amount of light when run from 9v. Some photos Code // ***************************************************************************** // Fred's PIR software // The majority of this code is from: // Code for application report SLAA283 - "Ultra-low Power Motion Detection using the MSP430F2013" // ****************************************************************************** #include // P1.7 LDR power // P1.6 LDR in // Hardware notes // P1.0 - LED // P1.4 - onboard switch // P2.7 - PIR_VCC // A4 - PIR (uses P1.1 and P1.2) // A3 - LDR (uses P1.6 and P1.7) // LDR between 1.5 (LDR power) and 1.6 (in) // 200k between 1.6 (in) and 0v // Threshold 1M ohm input < 50k // Work in progress // P1.5 - LDR power on // P1.6 - LDR in (dark = less than Vss/5 == 50k) // P1 #define LED_OUT BIT0 // Bit location for LED #define BUTTON_IN BIT4 #define LDR_PWR BIT5 #define LDR_IN BIT6 // P2 #define LIGHT_OUT BIT6 #define SENSOR_PWR BIT7 // Bit location for power to sensor #define PIR_THRESHOLD 50 // Threshold for motion #define LDR_THRESHOLD 50000 #define LIGHT_ON_TIME 20 // x about .5s #define PIR_IGNORE 3 static unsigned int result_old = 0; // Storage for last PIR conversion static char readingLDR = 1; static int lightTimer = 0; static int pirIgnoreTimer = 0; char testMode = 0; // LED control // Definition as used before defined void adcStartReadPIR(void); void adcStartReadLDR(void); void main(void) { //WDTCTL = WDTPW + WDTHOLD; // Use WD to wait about 10s WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL; // ACLK/32768, int timer: ~10s BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz DCOCTL = CALDCO_1MHZ; BCSCTL1 |= DIVA_2; // ACLK = VLO/4 BCSCTL3 |= LFXT1S_2; P1OUT = LDR_PWR | BUTTON_IN; P1DIR = LDR_PWR | LED_OUT; P1SEL = 0x00; P1REN |= BUTTON_IN; // P1.4 pullup P1IE |= BUTTON_IN; // P1.4 interrupt enabled P1IES |= BUTTON_IN; // P1.4 Hi/lo edge P1IFG &= ~BUTTON_IN; // P1.4 IFG cleared P2OUT = SENSOR_PWR; P2DIR = LIGHT_OUT | SENSOR_PWR; P2SEL = 0x00; SD16CTL = SD16VMIDON + SD16REFON + SD16SSEL_1; // 1.2V ref, SMCLK SD16AE = SD16AE1 | SD16AE2 // P1.1 & P1.2: A4+/- SD16_A inputs | SD16AE6; // P1.6: A3+ SD16_A inputs SD16CTL &= ~SD16VMIDON; // VMID off: used to settle ref cap //adcStartReadPIR(); // Wait for PIR sensor to settle: 1st WDT+ interval P1SEL |= LED_OUT; // Turn LED on with ACLK (for low Icc) while(!(IFG1 & WDTIFG)); // ~5.4s delay: PIR sensor settling P1SEL &= ~LED_OUT; // Turn LED off with ACLK (for low Icc) // Reconfig WDT+ for normal operation: interval of ~341msec WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1;// ACLK/512, int timer: 341msec BCSCTL1 |= DIVA_3; // ACLK = VLO/8 IE1 |= WDTIE; // Enable WDT interrupt _BIS_SR(LPM0_bits + GIE); } void adcStartReadPIR(void) { readingLDR = 0; SD16INCTL0 = SD16GAIN_4 + SD16INCH_4; // PGA = 4x, Diff inputs A4- & A4+ SD16CCTL0 = SD16SNGL + SD16IE; // Single conversion, 256OSR, Int enable SD16CTL |= SD16REFON; // If no, turn on SD16_A ref SD16CCTL0 |= SD16SC; // Set bit to start new conversion } void adcStartReadLDR(void) { readingLDR = 1; SD16INCTL0 = SD16GAIN_1 + SD16INCH_3; // PGA = 1x, Diff inputs A3- & A3+ SD16CCTL0 = SD16UNI + SD16SNGL + SD16IE; // Single conversion, 256OSR, Int enable SD16CTL |= SD16REFON; // If no, turn on SD16_A ref SD16CCTL0 |= SD16SC; // Set bit to start new conversion } void checkPIR(void) { // See if we've had movement volatile unsigned int result_new; volatile unsigned int change; SD16CTL &= ~SD16REFON; // Turn off SD16_A ref result_new = SD16MEM0; // Save result (clears IFG) if (result_new > result_old) // Get difference between samples change = result_new - result_old; else change = result_old - result_new; result_old = SD16MEM0; // Save last conversion // Ignore the first few readings after the light turns off if (pirIgnoreTimer < PIR_IGNORE) { pirIgnoreTimer++; return; } // If motion detected... if (change > PIR_THRESHOLD) { // LED now only used if it's light // Even this small light level affected LDR measurement P1OUT |= LED_OUT; // Light already on? if (P2OUT & LIGHT_OUT) { // Reset counter whether it's dark or not lightTimer = 0; } else { // Is it dark? adcStartReadLDR(); } } else { P1OUT &= ~LED_OUT; //adcStartReadPIR(); } } void checkLDR(void) { unsigned int val = SD16MEM0; if (testMode) { // Just LED = light if (val < LDR_THRESHOLD) P1OUT &= ~LED_OUT; else P1OUT |= LED_OUT; P2OUT &= ~LIGHT_OUT; __bis_SR_register_on_exit(SCG1+SCG0); // Return to LPM3 after reti return; } if (val < LDR_THRESHOLD) { // Switch light on P2OUT |= LIGHT_OUT; lightTimer = 0; } else { // Just show LED so we know it's working P1OUT |= LED_OUT; } } #pragma vector = SD16_VECTOR __interrupt void SD16ISR(void) { if (readingLDR) checkLDR(); else checkPIR(); __bis_SR_register_on_exit(SCG1+SCG0); // Return to LPM3 after reti } /****************************************************** // Watchdog Timer interrupt service routine ******************************************************/ #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { // Test mode just measures light level if (testMode) { adcStartReadLDR(); __bic_SR_register_on_exit(SCG1+SCG0); // Keep DCO & SMCLK on after reti } // Light on? if (P2OUT & LIGHT_OUT) { // Tick, tick, tick if (++lightTimer >= LIGHT_ON_TIME) { P2OUT &= ~LIGHT_OUT; pirIgnoreTimer = 0; } } if (P1OUT & LED_OUT) // Has motion already been detected? P1OUT &= ~LED_OUT; // If yes, turn off LED, measure on next loop else adcStartReadPIR(); __bic_SR_register_on_exit(SCG1+SCG0); // Keep DCO & SMCLK on after reti } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { testMode ^= 0x01; // Toggle test mode P1IFG &= ~BUTTON_IN; // P1.4 IFG cleared } Schematic Still need to do this, despite it not being very much. bluehash 1 Quote Link to post Share on other sites
bluehash 1,581 Posted December 6, 2011 Share Posted December 6, 2011 Hehehe.. good one.. good one.. For a second, when I read the title, I thought the LED would glow when pee'd on.. oh well.. it's been a long day. Quote Link to post Share on other sites
Fred 453 Posted December 6, 2011 Author Share Posted December 6, 2011 Version 2.0 might have an LED strip under the rim. ;-) Quote Link to post Share on other sites
simpleavr 399 Posted December 6, 2011 Share Posted December 6, 2011 Now that's one practical project. Thanks for sharing. Quote Link to post Share on other sites
simpleavr 399 Posted December 7, 2011 Share Posted December 7, 2011 Now would expand it by adding a rtc and have rgb led installed. There must still be a lot of code space and io pins left. We could then report the peepee hour via coloring the led w/ resistor ring codes.. .red for 2am, orange at 3am, yellow at 4am, etc. Just saying. Quote Link to post Share on other sites
cde 334 Posted December 7, 2011 Share Posted December 7, 2011 Add a piezo buzzer and have it play the final fantasy "you won the fight" music when you flush. Quote Link to post Share on other sites
kenemon 29 Posted December 7, 2011 Share Posted December 7, 2011 could the rim job LED change colors if the aim is off? Quote Link to post Share on other sites
zeke 693 Posted December 7, 2011 Share Posted December 7, 2011 That's a whizzy cool project! Quote Link to post Share on other sites
ike 53 Posted December 9, 2011 Share Posted December 9, 2011 You can use red LED to preserve your rhodopsin. http://en.wikipedia.org/wiki/Night_vision In biological night vision, molecules of rhodopsin in the rods of the eye undergo a change in shape as they absorb light. Rhodopsin is the chemical that allows night-vision, and is extremely sensitive to light. Exposed to a spectrum of light, the pigment immediately bleaches, and it takes about 30 minutes to regenerate fully, but most of the adaptation occurs within the first five or ten minutes in the dark. Rhodopsin in the human rods is less sensitive to the longer red wavelengths of light, so many people use red light to help preserve night vision as it only slowly depletes the eye's rhodopsin stores in the rods and instead is viewed by the cones. And you can make LED PWM controlled for a stroboscopic effect. This add a whole new dimension to the peeing experience. Quote Link to post Share on other sites
none 7 Posted December 12, 2011 Share Posted December 12, 2011 Out of respect for the one cleaning the place, you should sit down when your pee-light is on ;-) Quote Link to post Share on other sites
zeke 693 Posted December 13, 2011 Share Posted December 13, 2011 Okay, I think it's time to quote Monty Python. Quote Link to post Share on other sites
bluehash 1,581 Posted December 14, 2011 Share Posted December 14, 2011 Well.. Ahem. Had'ed Quote Link to post Share on other sites
Fred 453 Posted December 14, 2011 Author Share Posted December 14, 2011 Wow! I made it to hackaday. I wonder if it was the sheer genius of the project? The complexity? The flawless build quality? Or maybe just simple toilet humour. luke 1 Quote Link to post Share on other sites
gordon 229 Posted December 14, 2011 Share Posted December 14, 2011 There's nothing particularly funny about the toilet if you need to go. - What do you give to diarrheic hippo? - Way. Quote Link to post Share on other sites
tomb 0 Posted December 14, 2011 Share Posted December 14, 2011 In keeping with current trends, this should send a tweet when it's used. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.