June 8, 2019 · 9 min read

Smart Lighting With Leds and Photocells - my first attempts at programming an Arduino

How have I never played around with hardware before? I’ve had some ideas in the past, but who has the time to sit down and learn electronics? They’re kind of complicated.

I had my first Arduino class about a week ago - two hours of learning that is outside of my wheel house. I have read some basic schematics and can tell the difference between a resistor and a capacitor but actually putting them to practical use and building circuits proved pretty tricky to wrap my head around quickly

When I walked out of class, I had built my first circuit - a working LED. It was glorious. 3 days later and I sat down to rebuild it at home without instruction and I was perplexed, but I made my way back through it. Feeling a bit more confident, I set out to create 3 new projects in 1 week:

  1. Make an LED turn on when it’s dark and turns off when it’s bright
  2. Make an LED get bright when the environment gets bright (and a version that gets bright when the environment gets dark)
  3. Make an LED blink when the environment gets dark

I didn’t have a dedicated work space for doing this so I had to find a spare TV tray to go next to my desk - which might be its new permanent home. 

This is how I got them all working.

Smart lighting

Getting an LED setup on the Arduino board is pretty straight forward and adding in a Photocell for lighting detection is almost easier.

Setup the LED

Create a circuit from Pin 13 → Resistor → LED → to Power (and ground it).

Hello Blink

The code to get the light to turn on is incredibly simple and included as an example in the Arduino IDE. A quick YouTube search and there are plenty of videos on how to get your LED to blink.

Setup the Photocell

With the photocell, you’re going to connect the Power → Resistor → Photocell → Ground and connect that to the Pin (0) so we can read what values the photocell is receiving.

The photocell

In order to get the LED to turn on and off, we’ll need to figure out the values that the photocell is receiving when it’s light vs dark. Best way to do that is to push the values to the serial port and read them in the IDE.

“Smart” lighting code

This code couldn’t get more simple:

// The pins I'm using
// For the light
int sensorPin = 0;

// For the LED
int ledPin = 13;

void setup() {
  // Start communication to get values
  Serial.begin(9600);

  // Set the LED pin output
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // Get the values from the Photocell
  int sensorValue = analogRead(sensorPin);

  // Send the value to the serial port
  Serial.println(sensorValue,DEC);

  // Delay for 1 sec
  delay(1000);
}

After pushing the code to the Arduino and waving my hands over the photocell a few times, I getting the following values:

Values from the photocell as seen though the serial monitor

I’ll use these values to determine what’s bright and what’s dark, setting that value globally:

// The value when it's dark
int darkValue = 5;

// The value when it's bright
int brightValue = 10;

Then we can use those values to turn on / off the LED during the code’s loop:

// Check the values and determine if the LED should go on or off
if (sensorValue < darkValue){
  digitalWrite(ledPin, 1);
}
else{
  digitalWrite(ledPin, 0);
}

Pushing the code to the Arduino lets me wave my hand over the photocell to turn it on. Smart home lighting done with hardly any code.

Waving my hand over the photocell turns on the LED

The full smart lighting code:

// Pin# or the light
int sensorPin = 0;

// Pin# or the LED
int ledPin = 13;

// The value when it's dark
int darkValue = 5;

// The value when it's bright
int brightValue = 10;

void setup() {
// Set the LED pin output
  pinMode(ledPin, OUTPUT);
}
void loop() {
  // Get the value from the photocell
  int sensorValue = analogRead(sensorPin);

  // Check the values and determine if the LED should go on or off
  if (sensorValue < darkValue){
    digitalWrite(ledPin, 1);
  }
  else{
    digitalWrite(ledPin, 0);
   }

  // Delay for 1 sec
  delay(1000);
}

On to the next project!

Change an LED brightness based on the environment (a backlight)

What do we need to do, instead of just turning the LED on/off (setting the value of the output to HIGH and LOW), to get the LED to change it’s brightness based on the values that the photocell is getting? We’ll need to:

  • Change the output to the LED to be analog so it can take more than just the On/Off values
  • Figure out what the range of values we can tell the LED to be
  • Map the values that we are reading from the photocell to the output of the LED

Going Analog

I don’t know why I struggled with this for longer than it should have. I kind of forgot about the whole analog vs digital part of all this - that’s what I get considering I’m only a handful of hours into learning all this.  I started by trying to write other values to the LED output, googling what values it can take (0–255), and watching several YouTube videos before it dawned on me… oh right! So I changed the analogWrite(ledPin, HIGH) to digitalWrite(ledPin,50) and moved the pin from 13 (Digital) to 9 which could handle analog…

Using the same code as before and it worked:

if (sensorValue < darkValue){
  analogWrite(ledPin, 180);
}
else{
 analogWrite(ledPin, 20);
}

Mapping the photocell value to the LED output value

So my range of values that I was getting from the photocell was about 0–100 when I pointed a light bulb right at it. I could write those values directly to the LED output but that won’t make it very bright. So lets get this a bit closer to 255. If I want the upper value (100) to be closer to 255 I could just multiply by 2.5 - which gets me 250.

Lets create a variable, do some math and write those values just to see if if does indeed do what I’m expecting. I don’t need the if/then, so the code in loop() just becomes:

// Make the upper value of the photocell value to upper limit of LED output
int sensorToLEDvalue = sensorValue * 2.5;

// Send the calculated value to the LED
analogWrite(ledPin,sensorToLEDvalue);

That does indeed make the LED darker when it’s dark in my room and brighter when the lights are on. Which is what I was looking to do.

This gif is crappy but it is indeed getting brighter as I'm pointing my lamp at it

The full backlight code:

// Pin# of the photocell
int sensorPin = 0;

// Pin# of the LED
int ledPin = 9;

void setup() {
  // Start communication to get values
  Serial.begin(9600);

  // Set the LED pin output
  pinMode(ledPin, OUTPUT);
}
void loop() {
  // Get the value from the photocell
  int sensorValue = analogRead(sensorPin);

  // Make the upper value of the photocell value to upper limit of
  // LED output
  int sensorToLEDvalue = sensorValue * 2.5;

  // Send the calculated value to the LED
  analogWrite(ledPin,sensorToLEDvalue);

  // Delay for a bit
  delay(100);
}

Brighten an LED when the room gets darker

How about we keep going and see if we can get the LED to dim when the environment is bright and get more bright when the environment gets darker. 

In order to do that we need to reverse the values, the higher the number being read from the photocell, the higher the output to the LED. We want to use map() to get what we are looking for. Map takes 5 values, the value you are mapping, the input range and the output range.

// Map the upper value of the photocell value to lower limit of LED output
int sensorToLEDvalue = map(sensorValue, 0, 100, 255, 0);

Pushing that to the board now does exactly what I would expect, with one exception - while reading the serial of sensorToLEDvalue I got a negative number because 100 wasn’t quite the upper bound.

We want to make sure it stays positive so we need to make the upper bounds of the readout to never go above 100, assuming we will make it full brightness at that point. So before passing that value to map() lets make sure it’s never larger than 100:

// If sensorValue is above 100, let's keep it at 100.
if (sensorValue > 100) { sensorValue = 100}

That will keep the negative numbers away and now functions as I’d expect.

The brighter it gets in here, the dimmer the LED

The full reverse backlight code:

// Pin# of the photocell
int sensorPin = 0;

// Pin# of the LED
int ledPin = 9;

void setup() {
  // Start communication to get values
  Serial.begin(9600);

  // Set the LED pin output
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // Get the value from the photocell
  int sensorValue = analogRead(sensorPin);

  // If sensorValue is above 100, let's keep it at 100.
  if (sensorValue > 100) { sensorValue = 100}

  // Map the upper value of the photocell value to lower limit of the LED output
  int sensorToLEDvalue = map(sensorValue, 0, 100, 255, 0);

  // Send the calculated value to LED
  analogWrite(ledPin,sensorToLEDvalue);

  // Delay for a bit
  delay(100);
}

That brings us to the final task at hand.

Creating an emergency light by blinking an LED when the lights go dark

I figured out detecting darkness in the first project and turning the LED on and off based on the photocell value. Instead of just turning it on, how about we create a function that turns it on and off repeatedly?

// Function to Blink the LED
void blinkLED(){
  analogWrite(ledPin, 255);
  delay(20);
  analogWrite(ledPin, 0);
  delay(20);
}

Then let’s just call that function when we check if the sensorValue is less than the darkValue we set:

// Check the value of the sensor and if it's dark then blink the
// LED, if not turn it off.
  if ( sensorValue < darkValue ){
    blinkLED();
  }
  else{
    analogWrite(ledPin, 0);
  }

Pushed that onto the board and, holy crap, worked on the first try! I think I’m getting the hang of all this.

Darkness causes the blinking LED

The full emergency light code

// Pin# of the photocell
int sensorPin = 0;

// Pin# of the LED
int ledPin = 9;

// The value when it's dark
int darkValue = 5;

void setup() {
  // Start communication to get values
  Serial.begin(9600);

  // Set the LED pin output
  pinMode(ledPin, OUTPUT);
}

// Function to Blink the LED
void blinkLED(){
  analogWrite(ledPin, 255);
  delay(20);
  analogWrite(ledPin, 0);
  delay(20);
}

void loop() {
  // Get the value from the photocell
  int sensorValue = analogRead(sensorPin);

  // Check the value of the sensor and if it's dark then blink the
  // LED, if not turn it off.
  if ( sensorValue < darkValue ){
    blinkLED();
  }
  else{
    analogWrite(ledPin, 0);
  }

Can’t wait to move on to some more complicated ideas and see what all those Arduino accessories are (like what the heck is a servo?). So that is all I’ve got so far for smart lighting on the Arduino and I’m looking forward to sharing what else it is I’m doing next.

Document Metadata


Raw File With Signature: smart-lighting-with-leds-and-photocells.txt.asc

Hash of Raw File: 41f2ad4784f5733d860b9e9ddd20875c1c26f70c06970c0b850b909411c0af12

Ethereum Proof of Existance Transaction: 0xfa91348bf431cf6dfd6fc91844f6218f00cc115669c423e725ba4475e9ab2a3a

This text is Creative Commons:Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)

Need More?

If that wasn't enough, why not check out my blog, see how I work, or setup some time to talk to me. If you like what I'm doing, please support me by becoming a patron.