Skip to main content

LED Strobe Light

I ordered a small strobe light more than a month ago from china, but it wasn’t delivered in time, so I made one from a LED light I had at home.

First, I wired this LED light through a NPN transistor. It couldn’t be wired directly to Arduino because it requires higher current than Arduino can provide. I’ve also wired a 10K Potentiometer for tuning the frequency of blinking.

Wiring diagram

Resistor wired from pin 2 is 1K Ohm and the pulldown resistor connecting transistor to the ground is 10K Ohm.

Wiring
Wiring

Programming everything was as simple turning pin on and off with delays in between linked to potentiometer. At higher frequencies I noticed that light was actually lit longer than it was off so the effect wasn’t as good as I expected it to be.

I had to adjust the delay before light turns on again to be longer at higher frequencies, but stay about the same at higher. I drew a graph time on-time off to represent this and figured out I could shift and stretch function y = -1/x to form the same line. The results were much better then.

Graph
Graph

A clip of the strobe light working.

Here is the code for Arduino.

int potPin = 2;    // input pin for the potentiometer
 int ledPin = 2;   // pin for the LED
 int val = 0;      
 int onTime = 0;
 int offTime = 0;
 void setup() {
   pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT 
 }
 void loop() {
   val = analogRead(potPin); // read the value from the potentiometer (10k Ohm) (approximately between 0 and 1000)
 onTime = val;
   offTime = (-2000000 / (onTime + 1000)) + 2000;
 onTime = onTime / 4;    //
   offTime = offTime / 4; // Intervals longer than 250ms were not useful for application, also makes potentiometer less sensible, so I could fine tune desired frequencies.
 if (onTime > 12)  { //keeps light off if potentiometer set to min
     digitalWrite(ledPin, HIGH); }
   delay(onTime);                  // how long the LED stays On
 if (onTime < 250){ //keeps light on when potentiometer set to max
     digitalWrite(ledPin, LOW); }
   delay(offTime);                  // how long the LED stays Off
 }

WeMos D1 ESP8266 Web Controlled Switch

Last year I made Room automation with Raspberry Pi and few Arduinos for switching lights and air conditioner on and off using my phone. It required lots of components for accomplishing a simple task. The reason was that Arduino itself cannot connect to wifi and NRF24L01+ module doesn’t support TCP/IP protocol, so I needed Raspberry Pi for wifi connection. Also using new Raspberry Pi for each light switch is just too expensive. This time I used WeMos ESP8266.

ESP866 is an inexpensive Wifi Module for Arduino that supports 802.11 b/g/n protocols and it can also run Arduino code. There are multiple versions of this SOC. Some require serial to USB adapter for programming and some have micro USB port. They also vary by amount of GPIO ports and memory they have.

List of parts that I also used for this project:

  • WeMos D1 ESP8266
  • Relay module
  • MB102 Breadboard Power Supply Module
  • Old notebooks power adapter

For assembly I connected notebook’s PSU to MB102 PSU module, MB102 to ESP8266 with USB cable and GPIO ports 0, 2 and ground on ESP8266 to Relay module.

ESP8266  WeMos
ESP8266 WeMos

I modified ESP8266 library example code and uploaded it on the WeMos ESP8266:

#include <ESP8266WiFi.h>

const char* ssid = "SSID";
const char* password = "wifi password";

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);

  // prepare GPIO2
  pinMode(2, OUTPUT);
  digitalWrite(2, 0);
  
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  
  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // Match the request
  int stat;
  if (req.indexOf("/gpio/0") != -1){
    digitalWrite(2, 0);
  }
  else if (req.indexOf("/gpio/1") != -1){
    digitalWrite(2, 1);
  }
  else if (req.indexOf("/status") != -1){
  }
  else {
    Serial.println("invalid request");
    client.stop();
    return;
  }

  // Set GPIO2 according to the request
  stat = digitalRead(2);
  
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n";
  s += (stat)?"high":"low";
  s += "</html>\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");

  // The client will actually be disconnected 
  // when the function returns and 'client' object is detroyed
}

Module automatically connects to wifi when powered and receives an IP address from router (192.168.1.45 for example). It’s IP may change every time module disconnects from wifi, so I assigned it static IP address on my router.

You can switch GPIO on by sending HTML request to “http://[ESP8266s ip address]/gpio/0” and to turn it off “~/gpio/1”. This is done simply by visiting url in a web browser.
Disadvantage of the code from libraries example is that you can’t tell whether GPIO is on or off. I modified it so that html response includes info about its status when you visit ~/status.

Turning the air conditioner on by typing http://192.168.1.45/gpio/0 into a browser and making sure that it’s on or off by visiting http://192.168.1.45/status it’s not very practical, so I made a simple web interface and added it to my homes dashboard webpage.

<?php
 //get the GPIO status
 $html = file_get_contents('http://192.168.1.45/status');
 if (strpos($html, 'low') !== false) {
     $status = 0;
 }
 else {
   $status = 1;
 }
 

   if ($_POST["15"] == "1") {
     if ($status == 1) {
       file_get_contents('http://192.168.1.45/gpio/0');
       $status = 0;
     }
     elseif ($status == 0) {
       file_get_contents('http://192.168.1.45/gpio/1');
       $status = 1;
     }
   }
 ?>
 

 <!DOCTYPE html>
 <html lang="en">
 <head>
   <title>Switch</title>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
 </head>
 <body>
 

 <div class="container">
   <div class="col-sm-3">
        <h3>Air conditioner</h3>
         <form  id="form" name="test" action="index.php" method="post">
           <input type="hidden" name="15" value="1"></input>
           <input type="submit" class="<?php if($status == 1) {print("btn btn-primary btn-lg btn-block");} else {print("btn btn-secondary btn-lg btn-block button");} ?>" value="<?php if($status == 1) {print("Turn Off");} else {print("Turn On");} ?>"></input>
         </form>
     </div>
     </div>
 </body>
 </html>

It displays a button with text “Turn on” or “Turn off” depending on the GPIOs current status. When you click it, it sends a html request to the module to change its GPIO state.
You can use as many ESP8266 modules as you want and manage them from a centralized web application.

Everything connected
Everything connected

Edit: Someone on Reddit requested code for managing multiple ESP8266s. So here is the code. To add new module, just add its IP address and name in the array.

<?php
 $devices = array(
     '192.168.1.66' => 'Light1',
     '192.168.1.45' => 'Light2',
     '192.168.1.47' => 'AirConditioner');
 

 $i = 0;
 foreach ($devices as $ip => $name) {
     $html = file_get_contents('http://' . $ip .'/status');
     if (strpos($html, 'low') !== false) {
         $status[$i] = 0;
     }
     else {
       $status[$i] = 1;
     }
     if ($_POST[$name] == "1") {
       if ($status[$i] == 1) {
         file_get_contents('http://'. $ip . '/gpio/0');
         $status[$i] = 0;
       }
       elseif ($status[$i] == 0) {
         file_get_contents('http://'. $ip . '/gpio/1');
         $status[$i] = 1;
       }
     }
   $i++;
 }
 ?>
  
 <!DOCTYPE html>
 <html lang="en">
 <head>
   <title>Switch Control Interface</title>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
 </head>
 <body>
  
   <div class="container">
     <div class="col-sm-4">
     <h2>Switch Control Interface</h2>
     <? $i=0; foreach ($devices as $ip => $name) { ?>
        <h3><?echo $name;?></h3>
           <form  id="form" name="test" action="index.php" method="post">
             <input type="hidden" name="<? echo $name; ?>" value="1"></input>
           <input type="submit" class="<? print ($status == 1 ? 'btn btn-primary btn-lg btn-block' : 'btn btn-secondary btn-lg btn-block button');?>" value="<?php print ($status == 1 ? 'Turn Off' : 'Turn On');?>"></input>
           </form>
     <?php $i++; } ?>
     </div>
   </div>
 </body>
 </html>

Here is a video demonstration of last years system. Front-end webapp is the same and it functions the same.

Laser Sensor Timer using Arduino

I’ve made this project during project week in high school. This timer can be useful for timing races over short distances, because the result is more accurate than using handheld stopwatch. The average reaction time of a human is approximately 0.25s which is a lot when the total time can be as low as about 7 seconds.

List of parts that I used to make this project:

A laser is pointed to photoresistor which is connected to analog pin on the arduino. Using code below, you can read the value of analog ping (photoresistor) in range of 1 to 1000. The more photons fall on the photoresistor in a given time, the higher is the read value. The value of ambient light read from analog pin is in my case 400, and 800 while the laser is pointed at the photocell.

void setup() {
 Serial.begin(9600);
 }
 void loop() {
 Serial.println(analogRead(0));
}

We can use this to determine whether there is a clear path between laser and photocell or not. Now we just need a display and a button to start the timer. Well we can also wire a starting pistol instead. Here is my diagram: (R1, connected to button, is 10k and R2 is 1.5k)

Arduino Timer Diagram
Arduino Timer Diagram

I used OLED 128×64 I2C display, which requires these two libraries: SSD1306 and GFX. You can use any Arduino compatible display.

Components on a breadboard
Components on a breadboard

And here is my final code. For timing, I’m using millis() function, which returns the number of milliseconds since the Arduino board began running the current program. When the start button is pressed, it saves value of millis in a variable and also current value of photoResistor. Then the program is displaying current time and constantly checking value of photoresistor. If it drops below 90% of a value at the beginning, it means that the path between laser and photoresistor is broken.
When I first made the program in school, I made it stop the timer at this event. But if we are using it for running, where you need to cross the finish line, timer shouldn’t stop just yet. Instead, it should wait until runner goes past the line and then stop the timer. So it waits for laser to shine on the photoresistor again and then stops the timer.

//display
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

//timer      
unsigned long time;
unsigned long timeStop;
unsigned long startMs;
unsigned long timeEnd;  
float seconds;
float secondsStop;

int buttonState = 0;  
int photoResistor = 0;
int photoResistorStart = 0;
int photoResistorStop = 0;

int start = 0;

void displayTime(float currentTime){
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0); 
  display.print(currentTime); display.print(" s");
  display.display();
  return;
  }

void setup()   {
  Serial.begin(57600);
  //display  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
  display.clearDisplay();
  
  // start button
  pinMode(2, INPUT);
  delay(1000);
  
  //display start screen
  displayTime(0.00);
}


void loop() {
  photoResistor = analogRead(0);
  buttonState = digitalRead(2);

 if (buttonState == HIGH and start == 0) {
    photoResistorStart = analogRead(0);
    photoResistorStop = photoResistorStart * 0.9;
    start = 1;
    startMs = millis();  
  }
 
  if (start == 1 and timeEnd == 0) {
    time = millis() - startMs;
    seconds = (float) time / 1000;
    displayTime(seconds);
  }
  
  if (photoResistor < photoResistorStop and timeEnd == 0) {   
    while( photoResistor < photoResistorStop){
      photoResistor = analogRead(0);
      time = millis() - startMs;
      seconds = (float) time / 1000;
      displayTime(seconds);
    }
    timeStop = millis() - startMs;
    secondsStop = (float) time / 1000;
    displayTime(secondsStop);
    timeEnd = 1;
  }
  
  if (timeEnd == 1){
   displayTime(secondsStop);
  }  
}
Timer System
Timer System

For now, timer can only store one value and if it was used outside on a bright day, difference between the values of ambient light and the laser on the photoresistor wouldn’t be sufficient. You can make cover for photoresistor so that only light from laser would fall on it, thus making the system more reliable. For keeping the laser directed, I used laser on distance meter, which I attached on camera tripod.

Here is a test video of my timer.

Room automation with Raspberry Pi and Arduino

One of the first things I did with Raspberry Pi was connecting relay board to it and than switch the light, which was connected to the relay, on and off using command line. This wasn’t very useful since every time I wanted to switch light, I had to first SSH to Raspberry and then use the command like “gpio -g write 17 1” to turn on the light. Another problem was that I could only switch two lights because I had to run cables from physical light switch to relays. If I wanted to switch the light that I have on the other side of the room, I would have to install cables through the room. Then I came up with the solution of using few Arduinos + nRF24L01 wireless modules and user friendly web app.

List of parts that I used to make this project:

The first problem I encountered was getting arduinos to communicate using nRF24L01 modules. I read on forums that arduino might not provide enough current through 3.3V for powering nRF24L01 modules and I had to solder 10uF capacitor to Vcc and ground pins on the module.

nRF24L01+ module with 10uF capacitor
nRF24L01+ module with 10uF capacitor

You can check how to connect nRF24L01 module to Arduino here. I used this library for nRF24L01+: RF24 library.

After I got nRF24L01 modules to work, I wrote the arduino program that sends either value 1 or 2 to other Arduino, whenever push button was pressed or released. For the arduino used as receiver I wrote another program that receives data and switches GPIO pin state according to received value. Later I put data in array, so I could control multiple arduinos.

Arduino transmitter – the one connected to raspberry. You only need one.

 #include <SPI.h>
 #include <nRF24L01.h>
 #include <RF24.h>
 #define CE_PIN   9
 #define CSN_PIN 10
 

 const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe
 RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
 int state[2];
 int i = 5;
 

 //"button"
 const int buttonPin = 3;
 int buttonState = 0;
 

 //"button2"
 const int button2Pin = 2;
 int button2State = 0;
 

 void setup() 
 { 
    Serial.begin(9600);
   radio.begin();
   radio.openWritingPipe(pipe);
   
   //"button"
   pinMode(buttonPin, INPUT_PULLUP);    
   
     //"button2"
   pinMode(button2Pin, INPUT_PULLUP); 
 }
 

 void loop()
 {
     buttonState = digitalRead(buttonPin);
     if (!buttonState == HIGH) {
       state[0] = 2; 
     }
     else {
       state[0] = 1;
     }  
     
     button2State = digitalRead(button2Pin);
     if (!button2State == HIGH) {
       state[1] = 2; 
     }
     else {
       state[1] = 1;
     }  
     
    // radio send on command
        while (i > 1) {       
           radio.write( state, sizeof(state));
           i = i - 1;
        }
        
   i = 5;
 }

Arduino receiver – connected to relay, which is switching the device on/off. You can use more of them.

 #include <SPI.h>
 #include <nRF24L01.h>
 #include <RF24.h>
 #define CE_PIN   9
 #define CSN_PIN 10
 

 const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe
 RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
 

 int state[2]; 
 int i = 1;
 

 void setup()  
 {
   Serial.begin(9600);
   delay(1000);
   radio.begin();
   radio.openReadingPipe(1,pipe);
   radio.startListening();;
 

   //pins connected to relay module
   //You should use array if you're using more devices
   pinMode(2, OUTPUT);
   pinMode(3, OUTPUT);
   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);
 }
 

 

 void loop()  
 {
 

   //module is constantly listening for data
   if ( radio.available() )
   {
     // Read the data payload until we've received everything
     bool done = false;
     while (!done)
     {
       // Fetch the data payload
       done = radio.read( state, sizeof(state) );    
 

       //if you're using more remote devices, you should use loop
       if ( state[0] == 1 ) {
           digitalWrite(2, HIGH); 
       }
       
       if ( state[0] == 2 ) {
           digitalWrite(2, LOW); 
       }
       
       if ( state[1] == 1 ) {
           digitalWrite(3, HIGH); 
       }
       
       if ( state[1] == 2 ) {
           digitalWrite(3, LOW); 
       }
       
     }
   }
   else
   {    
     i = i+1;
   }
 

   //I experienced some trouble when system was up for a long time and it stopped listening,
   //so in case of a problem, nRF24 module will restart.
   if (i > 50){
     i = 1;
     radio.stopListening();
     radio.begin();
     radio.openReadingPipe(1,pipe);
     radio.startListening();
     delay(1000);
 

   }
 

 }

I had to get Raspbery Pi and Arduino-transmitter to comunicate, so I replaced push button with transistor and raspberry pi circuit. Therefore when I used command for changing the GPIO state on raspberry pi – “gpio -g write 17 1”, The current would flow through base of the NPN transistor and hence closing the circuit on the arduino side, so arduino reads different state on gpio pin, causing it to send data to other arduino which controls the light.

Here is my final diagram (both resistors are 10k):

Diagram
Diagram

Last step was to make web interface. First I wrote back-end in php for switching GPIO state of one pin on the Raspberry. It executed command to read current state of the GPIO pin and if the state was off, it executed same command as I used before to turn it on and vice versa. So whenever I reloaded the web page, the light turned on or off. I found some jQuerry mobile buttons on w3schools that I later used in my UI. I put gpio pins and names of devices in the array and used foreach loop so when I added another device – air conditioner, I only had to insert GPIO pin and name of the device in the array.

nRF24L01 module peeking from air conditioner (Arduino is inside)
nRF24L01 module peeking from air conditioner (Arduino is inside)

Web app code:

<?php
//specify gpio pins and names for devices
$gpioPins = array(
    17 => 'Big light',
    27 => 'Bedside light',
    21 => 'Small     ',
    20 => 'Air conditioner');

$i = 0;

//check current state for every gpio pin
foreach ($gpioPins as $pin => $name) {
    exec ( "gpio -g read $pin" , $status[$i] );
    $state[$i] = $status[$i][0];
//if button was pressed, change the gpio value of selected device (pin) depending on the previous state
    if ($_POST["$pin"] == "1") {
        system ( "gpio -g mode $pin out" );
        if ($state[$i] == 1) {
            system ("gpio -g write $pin 0");
            $state[$i] = 0;
        }elseif ($state[$i] == 0) {
            system ("gpio -g write $pin 1");
            $state[$i] = 1;
        }
    }
    $i++;
}
/* default gpio state of devices (i'm using pullup like switch for remote devices, so off state is "1")
im using three-way switch for big light, so i can turn on/off light from normal switch too,
but then I can't monitor on/off state of the light using this setup */
$defaultState = array($status[0],0,1,1);
?>
<!DOCTYPE HTML>
<html>
    <head>
        <title>Remote</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css">
        <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
        <meta charset="UTF-8">
    </head>
    <body>
        <div data-role="page" id="pageone">
            <?php $i=0; foreach ($gpioPins as $pin => $name) { ?>
            <div data-role="header">
                <h1><?php echo $name; ?></h1>
            </div>
            <div data-role="main" class="ui-content">
                <form  id="test" name="test" action="index.php" method="post">
                    <input type="hidden" name="<?php echo $pin; ?>" value="1"></input>
                    <div class="ui-btn ui-input-btn <?php if($state[$i] == $defaultState[$i]) {print("ui-btn-b");} ?> ">
                        <?php if($state[$i] == $defaultState[$i]) {print("Turn Off");} else {print("Turn On");} ?>
                        <input type="submit" data-corners="false" data-enhanced="true" value="On/Off"></input>
                    </div>
                </form>
            </div>
            <?php $i++; } ?>
        </div>
    </body>
</html>

Video demo:

Here is the picture of the final transmitter side setup. I have two GPIO pins on Raspberry connected to relay next to it and two connected to arduino through transistor circuit. Oh, and Aruino is powered by Raspberry pi’s USB.

Transmitter side final configuration
Transmitter side final configuration

If you are doing this project yourself, make sure you have installed apache2, php and wiringPi on your Raspberry Pi:

sudo apt-get install apache2 php5
git clone git://git.drogon.net/wiringPi
cd wiringPi
git pull origin
cd wiringPi
./build