I/O LED (Part 4)
Here is a new version of the sensing LED. The sensing LED is turned on almost all the time, with very short periods of time during which it is biased as a photo LED. The measuring time is so short that it is almost impossible to observe the flickering effect. Approaching a source of intense light will turn the sensing LED off!
This amazing process is perfomed using the following code
/* SensingLED as per: MITSUBISHI ELECTRIC RESEARCH LABORATORIES: Very Low-Cost Sensing and Communication Using Bidirectional LEDs by Paul Dietz, William Yerazunis, Darren Leigh TR2003-35 July 2003 The LED will be turned on when the ambiant light is lower than a trigger point and turned on under light exposure ATmega328 powered Arduinos only Copyright (C) 2012 Didier Longueville This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #define CATHODE_PIN PINB0 /* Connect the cathode of the sensing LED to the specified pin */ #define ANODE_PIN PINB1 /* Connect the anode of the sensing LED to the specified pin */ uint16_t triggerPoint = 2000; /* This depends on the LED properties */ uint16_t interval = 1000; /* Measurement interval */ uint32_t nextDataAcq, now; /* LED status */ #define LED_STS_OFF_ALL_LOW 0 #define LED_STS_OFF_ALL_HIGH 1 #define LED_STS_FORWARD 2 #define LED_STS_REVERSE 3 /* Register masks */ uint8_t cathodeMask = (1 << CATHODE_PIN); uint8_t anodeMask = (1 << ANODE_PIN); uint8_t cathodeAndAnodeMask = (cathodeMask | anodeMask); void setup() { /* Initialize serial comm port */ Serial.begin(115200); /* Set output ports */ BlinkCtrlLED(3); delay(1000); }; void loop() { /* Pause until next data acquisition */ do { now = millis(); } while(now < nextDataAcq); nextDataAcq = (now + interval); /**/ if (Darkness() >= triggerPoint) { PhotoLEDCtrl(LED_STS_FORWARD); /* Turn LED on */ } else { PhotoLEDCtrl(LED_STS_OFF_ALL_LOW); /* Turn LED off */ } }; void BlinkCtrlLED(uint8_t cycles) /* Blink control led */ { for (uint8_t i = 0; i < cycles; i++) { PhotoLEDCtrl(LED_STS_FORWARD); delay(200); PhotoLEDCtrl(LED_STS_OFF_ALL_LOW); delay(200); } }; uint16_t Darkness(void) /* Compute the "amount" of darkness */ { uint32_t start; uint16_t elapsedTime = 0; /* Bias LED in reverse mode */ PhotoLEDCtrl(LED_STS_REVERSE); /* Give a litlle time for setting voltage */ delayMicroseconds(10); /* Set Cathode pin in input mode */ DDRB &= ~cathodeMask; /* Set Cathode pin in high Z mode */ PORTB &= ~cathodeMask; /* Measuring cycle */ start = micros(); /* Wait for the cathode pin to reach the low level */ while ((cathodeMask & PINB) && (elapsedTime < triggerPoint)) { elapsedTime = (micros() - start); }; /* Print elapsed time */ // Serial.print((millis() / 1000.0), 1); // Serial.print(";"); // Serial.print(elapsedTime, DEC); // Serial.println(); /* End print */ return(elapsedTime); }; void PhotoLEDCtrl(uint8_t state) /* Control LED state */ { /* Set port direction */ DDRB |= (cathodeAndAnodeMask); switch(state) { case LED_STS_OFF_ALL_LOW: /* Turn LED off: no biasing */ PORTB &= ~(cathodeAndAnodeMask); /* Anode and Cathode to Ground */ break; case LED_STS_OFF_ALL_HIGH: /* Turn LED off: no biasing */ PORTB |= (cathodeAndAnodeMask); /* Anode and Cathode to VCC */ break; case LED_STS_FORWARD: /* forward polarity */ PORTB |= anodeMask; /* Anode to VCC */ PORTB &= ~cathodeMask; /* Cathode to Ground */ break; case LED_STS_REVERSE: /* reverse polarity */ PORTB &= ~anodeMask; /* Anode to Ground */ PORTB |= cathodeMask; /* Cathode to VCC */ break; } };