Project tutorial
Lightly

Lightly © GPL3+

Automate your curtains and add safety to your room, using the Arduino 101, WIZ750SR and Blynk, along with sensors and actuators!

  • 4,560 views
  • 3 comments
  • 20 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project

Lightly is a device for assisting you in some of your mundane day to day activities, as well as providing a level of safety in your room. It logs the temperature and data from light and smoke sensors to alert you in case of emergency situations such as a fire or smoke, and open and close your curtains (by a stepper motor) using a variety of options: predefined times (set as you want in your smartphone), light levels or temperature (heat). And everything can be controlled by your smartphone. By the addition of another motor, it can be set up to open your windows if it detects smoke, to allow it to get out and reduce risk of choking, notifying you of all events at all times.

Now on to the technical details - it is connected to Blynk by Ethernet using the Wiznet's WIZ750SR Serial to Ethernet device, and the microcontroller used is the Arduino 101. The Arduino 101 has an onboard accelerometer and BLE capabilities, but no Internet connectivity so the WIZ750SR is used. Grove modules will be used to add capabilities and provide an easy plug and play system.

Below is an overview of how Lightly works:

And these are the parts needed to build it:

I will say this in the start that I am using Grove Starter kit just for prototyping and making sure everything works. You may see that how I intended Lightly to look is very different from what I built, despite that, it still functions perfectly as intended. It may appear bulky and so, but you can build a proper case for it, get a bigger display and it will look and function exactly the same. But because I do not own a 3D printer, laser cutter, etc or even have access to these, I cannot build a case for the time being.

Note: I will not focus a lot in this documentation on the mechanical part of this project (attaching the motor to the curtains), as this may be different in each scenario, but searching online will certainly help you out.

Configuring the WIZ750SR

The WIZ750SR is a Serial to Ethernet converter which makes it very simple to connect your devices to the Internet, using Ethernet or a wired connection.

It also has an evaluation board (WIZ750SR-232/TTL-EVB Evaluation Board) to easily configure the WIZ750SR using the configuration tool Wiznet provides, which simplifies setting up the WIZ750SR.

Note: To test these Wiznet devices, if your PC does not have an RS-232 port, you must buy an RS-232 to USB converter separately; it is not included with the devices.

This is the pinout of the WIZ750SR:

And the pinout of the Arduino 101:

Now we move on to testing the WIZ750SR.

Note: I will assume your Wiznet devices are in their factory default state.

The reason for doing this testing is to confirm everything is working perfectly and will allow you to debug if any issues arise later on.

Testing the WIZ750SR:

Download and install the following programs on your Windows PC:

  • WIZ750SR Configuration Tool from here
  • Hercules from here. We will use this as a TCP Client to see if the device is connected and working properly
  • Arduino IDE with the Arduino 101 board installed. Just check online on how to do this; there are many resources online. For testing, we just need to use the Serial Monitor, but we need this later on as well, so better to have it installed.

Note: I am using Windows 7, things may be slightly different for you if you use other Windows versions.

After downloading and installing everything, plug in the WIZ750SR module to the evaluation board; if you unplugged it, and connect it as follows:

  • Ethernet cable, from the module to your PC.
  • Serial cable, from the evaluation board's serial port to your PC's serial port. You need to get an RS-232 to USB converter separately if your PC doesn't have one like mine.
  • USB Type B cable from the evaluation board to your PC.

It should look something like this:

Now you need to configure your PC to match the settings on the WIZ750SR. These are the default settings of the WIZ750SR:

So head over to your PC's network settings and change them to connect to the WIZ750SR. Basically, what you need to do is set your PC to not get an IP address or DNS automatically, but set it just like the WIZ750SR defaults. These can be changed later.

Go to your PCs "Network and Sharing Center", and click "Change adapter settings". From there, right your Local Area Connection (Or LAN) and go to its properties. Double click on "Internet Protocol Version 4 (TCP/IPv4)". Check the option for the user to specify the network settings and change it as in the image.

Note: IP address differs as it is unique for each device on a network and the rest is the same.

Once done, open the WIZ750SR configuration tool, and click the Search button. You should see your device's MAC address and be able to configure the WIZ750SR as you need from here, but leave the default values for now. This was just to confirm if it is connected properly.

Open the program Hercules, downloaded earlier, and go to the TCP client section. Enter the default IP address of the WIZ750SR as well as the default port, which should be 192.168.11.2 and 5000 respectively, and then click "Connect".

Once connected it will show this:

Minimize Hercules, and open the Arduino IDE. From there select the COM port for the Wiznet device and open the serial monitor (Set it to 115200 baud rate). You can check it in "Device Manager" if you don't know the COM port; there will be two different ones. Select the one which is your hardware serial or Serial to USB, depending on what you are using.

The other port COM 16, is a debug port available because we are using a USB type B cable to power the evaluation board; we don't need to use it now.

Open both Hercules and the Serial Monitor (with the correct serial port and baud rate) side by side, and try sending something from the Serial Monitor.

It will appear in Hercules, showing that a connection is established and your setup is working.

You will also find that if you type something in Hercules, it also gets echoed back in the Serial Monitor.

If everything is working, read on from the next section, and if you have issues just check your network settings or wires.

Connecting the WIZ750SR to Blynk:

Now that we have tested that the WIZ750SR is working and set up properly, we need to make it connect to the Blynk cloud.

First you need to find the Blynk server's IP address, which may differ depending on your location. To do that, open a command prompt and type:

ping blynk-cloud.com

It will show an IP address, note that down.

Now we need to configure the WIZ750SR to connect to the Blynk cloud and that will be done using the configuration tool. So with the WIZ750SR plugged in the evaluation board and wiring exactly the same as when testing it (You can leave the RS-232 connection if you want, and just connect the USB type B and Ethernet cable), open the WIZ750SR configuration tool. Select your device and make the following changes to it:

Note: I will be using DHCP because it the router will automatically allot the IP address to the WIZ750SR, which is what I want and I think most probably you should select DHCP too if you if you can't figure out what to do. But, you can always modify it as per your network.

Don't forget to click the "Setting" button on top, and it should show this:

The settings won't be saved until you press the "Setting" button, so make sure to do this, and wait until you see the confirmation.

Now we have set up the WIZ750SR to establish a connection with the Blynk cloud once an Ethernet wire is connected, but we need to connect the Arduino 101 as well, which will send data through the WIZ750SR.

Configuring the Blynk app

The Blynk app works on both Android and iOS, but I will be using Android. We can easily connect our hardware Blynk use in IoT projects and it has a great number of features making it very useful, and it has support for a lot of microcontrollers.

We need to configure the Blynk app first as it will give us an authentication token, which we need to get our code working. To get the authentication code, scan the QR code through the Blynk app on your Android or iOS device:

It will automatically create a project called Lightly, with the required widgets:

Once done, check your e-mail address for the authentication code and note it down as we need it later.

Setting up the Arduino 101

Now that you have the authentication code, what you need to do is to download the Lightly: Blynk Code and add the authentication token.

Once modified, upload the code and connect the WIZ750SR first to the Arduino 101, and then the sensors and motor.

Connecting the WIZ750SR with the Arduino 101:

Connecting the WIZ750SR with the Arduino 101 is pretty easy and straightforward. First plug the Grove base shield onto your Arduino 101 (I have the base shield v2), because you have to connect the sensors and modules to it as well:

Then you can proceed to connect the WIZ750SR. This row has all all the pins you need to connect to your Arduino:

The Arduino 101 uses the 3.3v logic level, and the WIZ750SR needs 3.3v for powering up and also uses the 3.3v logic level, same as the Arduino 101. This means that there is no need for a logic level converter. Simply connect as follows:

  • Tx of Arduino ----> Rx of WIZ750SR
  • Rx of Arduino ----> Tx of WIZ750SR
  • 3.3v of Arduino ----> Vcc of WIZ750SR
  • Gnd of Arduino ----> Gnd of WIZ750SR

It would be much better to use a connector than to directly solder wires because you can easily remove the WIZ750SR as needed. I have made a connector like this:

Note: You may notice two wires for Vcc, I have connected one to the 3.3v pin of the Arduino 101 and will use the other one later for powering up the Grove Temperature Sensor which works at 3.3v too.

The connector plugged on the WIZ750SR:

Now plug in the wires to the Arduino 101 + Base shield combination. This is how that looks like:

Connecting the sensors to the Arduino 101:

For the sensors, I will be using the Grove Starter Kit for the Arduino 101 and its Grove modules. The modules will be plugged into the base shield and I will be using the:

  • RGB LCD Display
  • Temperature Sensor
  • Light Sensor
  • Gas Sensor
  • Gear Stepper motor with driver

But because I don't have the Grove Gas Sensor, I will simply be using the commonly available MQ2 gas sensor from eBay. You can modify the code if needed for the Grove Gas Sensor if you have it and make Lightly completely plug and play (although it still is - to a significant amount).

I will not go into the details of connecting because it is very simple; if you can't figure that out, now is not the time to be building this. It would be much more better to go and play a bit more with electronics, and then come back once you feel more confident with your skills.

Note: Here are a few things which I found out and are very critical to get this working. Read them before moving on:

  • The Grove Temperature Sensor (I have v1.2) doesn't give the proper temperature when the base shield's voltage switch is at 5v, but the values are reasonable when it is at 3.3v. Therefore, I just connected it directly to the 3.3v supply of the Arduino 101 (Hence the two wires for Vcc from the WIZ750SR).
  • The RGB LCD Display doesn't work unless the Grove Base Shield's switch is at 5v (and the temperature sensor won't work unless it is at 3.3v, so you need to think about this).
  • I made the circuit such that I plugged in the Grove modules to the base shield itself, but used a separate 5v DC adaptor to power up the stepper motor, as well as the MQ2 gas sensor. This was done so that I could easily change the stepper motor with something more powerful and use another stepper motor driver, and also I didn't want to damage the Arduino 101 by drawing more current than it can handle. This is why I will not give you the diagram of how to connect but you must figure out the voltages for your setup yourself.
  • Make sure to have a common ground wire between the Arduino 101 and your external power supply for powering the stepper motor and gas sensor.

Connect everything as follows, taking care of the required voltages yourself, I won't go into that as I said above:

  • I will assume that the WIZ750SR is already connected to the Arduino 101 from the previous step.
  • Connect the Light module to pin A0.
  • Connect the Temperature module to pin A1.
  • Connect the MQ2 gas sensor to pin A2 (I would recommend to connect this to an external power supply)
  • Connect the Grove RGB LCD display to any I2C plug.
  • Connect the stepper to it's driver board, and connect the driver board's power (must be to an external power supply - I use a 5v 2A adaptor) and also make sure the external power supply and Arduino have a common ground. Wire up the stepper to pins 8, 9, 10 and 11 of the Arduino.

Note: You can also power the Arduino 101 from the Vin pin by using a power supply but I would say not to do it this way at the moment. You can do it later on once you know everything is working as it should.

This diagram will assist you in connecting everything:-

Note: This diagram only tells which pins to connect where. I assume you have connected everything as per it's proper voltage requirements!

This is what everything should look like:

After connecting everything:

After you connect everything; the WIZ750SR and the modules with the Arduino 101, and having uploaded the code with the authentication token, you have nearly built Lightly (except for a case).

And this is the vision I had in mind when designing it:

So now that we are ready, move on to the next section for testing Lightly.

Testing and using Lightly

Plug an Ethernet cable from the WIZ750SR to your router, and power on the Arduino. The lights on the WIZ750SR change to this:

It means that it is connected to your router/modem, and after a few moments, you should see this on the display:

If you see this, congratulations, your Arduino 101 is successfully connected to your Blynk project through the WIZ750SR (using ethernet), and you have built the electrical part of Lightly; what's left is the setting as per your needs.

The display will then show and update the temperature and light values:

Note: I have not yet built a mechanism for the curtains to move along with the motor due to lack of time, but as I have showed you, the motor moves on just as expected and the time can be adjusted according to your setup.

Now open the Lightly project in the Blynk app, and you will see that the widgets are getting updated:

Now, that the values are updated and all, we move on to testing the motor. By default, the code assumes that the curtain is open. This is a Blynk screenshot when the curtain is closed:

During opening and closing the curtains (when the motor spins), this is showed on the screen:

I should add here that getting the motor to work as needed was probably the hardest part in building Lightly. This was because the motor blocks the code from moving forward (you can read about this online), if run for a long time, it would disrupt the rest of the code. So the solution, using timers. This is the algorithm which shows how it works:

  • It assumes that the curtain is open by default.
  • It waits until number of successive light readings are captured below the light threshold.
  • Once they exceed that number, it gives a command to close the curtain.
  • The moment the command to close is given, a timer starts, and the motor starts rotating in a direction to close the curtain (should be set by the user).
  • A time value is already set in the code (you should adjust this yourself depending upon your curtains and mechanism), and the motor will run for at least the time set (compared with the timer started earlier), not in one go but in repetitions.
  • In this way the curtain will close slowly over the time value set by the user.
  • Once closed, the code will wait until successive light reading above the light threshold are available, and it will send a command to open the curtain, and so on.

So, to test the motor, put your hand on the light sensor (to block light) and wait for some time (until it exceeds the number of successive readings below the light threshold), you will see the motor spin (at least till the specified time). Along with that, you will see that the curtain state changes to closed in the Blynk app. Now that it is closed, shining a bright light continuously on the light sensor till the number of successive readings exceeds the limit, will cause the motor to spin in reverse, and the curtain state changes to open again. The following video demonstrates this:

By now, you should have a clear idea of how the Light Control feature works. But there is another feature called 'User Controlled' curtains.

Let's say that you don't want your curtains to be opened automatically, but to open and close at a specific time, and also be able to easily change that time. To change to User Controlled curtains, simply press the yellow Light Controlled button in the Blynk app (V5 widget) and it will switch to User Controlled:

The Timer widget is used for setting the time. Users can set any time for opening or closing the curtains as shown in the screenshot below:

'Start time' will send the command to open the curtains while stop time will send the command to close them. Here is a demonstration of this:

The smoke sensor widget shows the current smoke level, and if it exceeds a pre-defined threshold in the code, the display color changes to red showing that there is a problem:

Note: You can also use another motor for opening the windows when the smoke sensor gets past the threshold. This will allow air circulation and reduce risk of choking for people inside in the unlucky event of a fire.

You can set the display color as you want using the ZERGBA widget, which is fun to use. Below is a video demonstration for that:

Other than that, you can make notifications appear on your smartphone by adding the following line anytime in the code:

Blynk.notify("YourMessageHere");

The sketch I wrote basically connects your WIZ750SR to Blynk, meaning you can modify it in any way Blynk allows. You can use the Blynk app to modify the interface from your smartphone as well and set up conditions by using the Eventor widget. You can add graphs for temperature or anything, as you like.

The code:

For you to be able to use Lightly, you need to have an understanding of how the code works, and so be able to adjust the variables as you need.

The interval is in milliseconds, and the lightThreshold is less on purpose, so that you can check it easily. You will need to change it to something which suits your setup. Also adjust the mq2threshold if you want.

Adjust the interval; your motor will run at least until this time, and increasing repetitions increases the number of times your motor runs in one go, it should be one at least.

Motor speed and steps should be good for the Grove Stepper Motor, but you will need to change if you are using another motor.

The rest is simple and self-explanatory.

Attaching the motor to the curtains:

Lightly makes sure that the stepper motor spins clockwise and anti-clockwise, but to make your curtains actually move, you need to attach the motor to them in some way. This will differ for each case as anyone can point out, therefore, I have decided not to go in the details. And frankly speaking, I haven't made a mechanism yet for myself due to the lack of time.

But this should give you a general idea:

Another connection method

Suppose you do not want to use Blynk for some reason in the project.

Your other option would be to configure the WIZ750SR as a TCP server and make your devices connect as a client to the WIZ750SR to view the sensor data or change variables.

To use this upload the "Lightly TCP Server" code to your Arduino 101.

You will also need to re-configure the WIZ750SR to work as a TCP Server. To do that, plug it in the evaluation board and connect it with your PC (exactly as described previously), and open the WIZ750SR configuration tool. Configure it depending upon your setup; you need to set it as TCP server and set the local IP to static or DHCP. I will be using DHCP. Don't forget to click the Setting button after configuration is complete, and wait for the configuration complete message.

Then wire everything up as before (according to the connection diagram) and power it up.

You need to know the IP address and the port of the WIZ750SR. Getting the IP address depends on how you set IP allocation. If it is static, use the same IP, and if DHCP, get it from your router's webpage once you connect the ethernet cable.

Open Hercules on your PC, set it up as the TCP Client using the WIZ750SR's IP and port, it should show connected and display the sensor data each second, like this:

You can configure the following variables by typing their exact name, as in the picture below:

For example, if you want to change the lightThreshold, simply type in "lightThreshold" in Hercules and click Send:

Enter the new value and it will show the updated value as well:

And the same for any variable in the list given above:

Note: These values just reset back to default once the Arduino 101 is unplugged. If you need to change something permanently, edit it in the code.

Using the TCP Server method, you will be only able to open or close your curtains using by light; if you want to use the "User Controlled" feature as with Blynk, you need some way to manage time on your Arduino 101.

Note: To adjust timing for sending sensor data to the WIZ750SR, use the SimpleTimer library's function. By default, it sends data every two seconds.

Port forwarding for remote access:

You can use port forwarding to remotely connect to the WIZ750SR, the same way as CCTV cameras work over the internet, but I haven't tried that. I wanted to test this but my ISP is blocking the ports; I had previously spent a lot of time trying to achieve this for another project and found out in the end that my ISP was interfering, therefore, I did not go through the hassle now. You can always check online for information on how to do this, as it differs from router to router.

Adding a connection password:

A feature of the WIZ750SR is to add a connection password. To do that, configure the WIZ750SR like this:

Once set up, using the same TCP Server code, connect everything according to the connection diagram. Open Hercules and enter IP and port, when you try to connect it will connect and then disconnect after a brief moment. This is because it is not receiving the proper password. This is how it looks:

To make it work, do the following:

This provides security, as it will not allow unauthorized devices to connect. To be honest, this connection password won't make much of a difference in Lightly, but can be very useful in other applications, so I just described how to do this.

Further improvements

Lightly can be further improved by the following things:

  • You could use a bigger and more powerful motor. I had modified the existing code to work with another stepper motor, a bigger one, using the popular Easydriver as the motor driver. Just refer to Sparkfun's Easydriver hook-up guide here. I got this motor easily working by using Sparkfun's guide and code. And simply copying that code over to the existing Lightly code got it working. You should do that as well if you want to use a more powerful motor, but again, make sure to get the voltage right! For example, this can be a code snippet to make a larger stepper motor move forward using the Easy Driver:
   digitalWrite(dir, LOW); //Pull direction pin low to move "forward"
   for (x = 1; x < 1000; x++) //Loop the forward stepping enough times for motion to be visible
   {
     digitalWrite(stp, HIGH); //Trigger step pin forward
     delay(1);
     digitalWrite(stp, LOW); //Pull step pin low so it can be triggered again
     delay(1);
   }

And this to make it spin in the opposite direction:

   digitalWrite(dir, HIGH); //Pull direction pin high to move in "reverse"
   for (x = 1; x < 1000; x++) //Loop the stepping enough times for motion to be visible
   {
     digitalWrite(stp, HIGH); //Trigger step pin forward
     delay(1);
     digitalWrite(stp, LOW); //Pull step pin low so it can be triggered again
     delay(1);
   }

A picture of the motor I used with the Easydriver:

  • Another improvement would be to use EEPROM to hold the variables, so that you can configure them over the Internet, without uploading the code. You could also do this, without an EEPROM through Blynk, but I won't go through that.
  • You could add an extra motor in the code by copying the code of the first one (one motor spins clockwise while the other anti-clockwise) to make Lightly work with double panel curtains.
  • Using a better and larger display as in the cover photo will also make it look good.
  • Adding limit switches will also be an upgrade.
  • Using the WIZ750SR's TCP Client/Server mode, modify the code to connect with both Blynk and a TCP client when available.
  • Feel free to add more widgets to the Blynk app and change the code as needed. The WIZ750SR works exactly with Blynk as any other hardware already present in Blynk. The Blynk documentation here allows you to add your own hardware to Blynk with a small modification, and that is exactly what I did to get Blynk to work with the WIZ750SR, and it turned out to be very good. You can add any changes to the Blynk app to improve Lightly and it will work.
  • I also ordered the Arduino protoshield and when it arrived, I made a shield for the WIZ750SR. This was done to reduce the mess of wires and make it look neater. This is the result:

You will notice it is pretty easy to set up the electronics part, but you may have some trouble when attaching the motor with your curtains. Let me know about what you thought of Lightly, and make sure to comment if you have any questions.

Code

Lightly: Blynk CodeArduino
Add your authentication token and upload to the Arduino 101. Once tested and working, adjust values according to your setup.
#include <Wire.h>
#include <Stepper.h>
#include "rgb_lcd.h"
#include <Ethernet.h>
#include <SimpleTimer.h>
#include <BlynkSimpleStream.h>

//Defining Blynk virtual pins
#define vTEMPERATURE_PIN V0
#define vMQ2_PIN V1
#define vLIGHT_PIN V2
#define vEVENTOR_PIN V3
#define vZERGBA_PIN V4
#define vSWITCH_PIN V5
#define vCURTAINSTATE_PIN V6

//The code is written assuming that the curtain is open for the first time, meaning it will only close first
//and then open, and so on...

//Variables you may need to set:
char auth[] = "YourAuthToken";      //You should get this from the Blynk app
float lightThreshold = 20.0;        //Threshold  value which decides whether to open or close the curtain
float mq2Threshold = 45.0;          //Enter the smoke sensor threshold values from 0 to 100 as needed
long lightCounterThreshold = 60000;  //Minimum successive light readings before Lightly decides to open or close the curtains
long interval = 20000;              //The motor will run for at least this time (in milliseconds)
int repetitions = 3;                //Increasing this number increases the time the motor runs in each go
int stepsPerRevolution = 400;       //The steps per revolution for your motor
int motorSpeed = 60;                //Speed of the motor. 60 is a good value for the Grove Stepper Motor for me

//Do not change these variables if you don't know what you're doing
float temperature, mq2Percent, light;   //These hold the sensor values
long previousMillis;                    //Holds the previous reading for the motor running timer
long openCounter, closeCounter;         //Counter telling how many successive readings taken to open or close curtains
bool motorMoving = false;               //Sets the motor as not moving in the start of the program
bool curtainState = false;              //curtainState false means curtain is open and true means closed
int eventorValue, switchValue;          //Variables for the holding widget values
int pinLight = A0;                      //Pin for the light module
int pinTemp = A1;                       //Pin for the temperature module
int pinMq2 = A2;                        //Pin for the gas sensor
int colorR = 255, colorG = 255, colorB = 255;    //Default colour is white for the Grove RGB LCD

//Initializing the LCD and Simpletimer library
rgb_lcd lcd;
SimpleTimer timer;

//Initialize the stepper library on pins 8 to 11
//Try 8,10,9,11 if everything appears ok and you still have issues with the motor. The stepper motor I used wouldn't
//work with the order 8,9,10,11. Browsing the internet about this issue showed that the wires can sometimes not be
//in the expected order. You can read about that here: https://forum.arduino.cc/index.php?topic=143276.0
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup()
{
  Serial.begin(9600);
  Serial1.begin(115200);

  delay(1000); // Give the WIZ750SR a second to initialize

  Blynk.begin(Serial1, auth);

  //Setup the timed fuctions
  timer.setInterval(1000L, sendSensorValues);
  timer.setInterval(2000L, displayData);

  lcd.begin(16, 2);

  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  lcd.setRGB(colorR, colorG, colorB);
  lcd.setCursor(0, 0);
  lcd.print("    Lightly");
  lcd.setCursor(0, 1);
  lcd.print("Smarter Lighting");

  //Default curtain state is open
  Blynk.virtualWrite(vCURTAINSTATE_PIN, curtainState);
}

void loop()
{
  Blynk.run();
  getSensorData();
  timer.run();
  if (switchValue == 0) {
    openWithLight();
  }
  if (switchValue == 1) {
    openWithEventor();
  }
}

void getSensorData() {
  int B = 3975;
  float resistance;
  int mq2Value = analogRead(pinMq2);
  int val = analogRead(pinTemp);
  int sensorReading = analogRead(pinLight);
  light = map(sensorReading, 0, 1023, 0, 100);
  mq2Percent = (mq2Value / 1023.0) * 100.0;
  resistance = (float)(1023 - val) * 10000 / val;
  temperature = 1 / (log(resistance / 10000) / B + 1 / 298.15) - 273.15;
}

void displayData() {
  if (checkForSmoke() == true) {
    int colorRed = 255;
    int colorGr = 0;
    int colorBl = 0;
    lcd.clear();
    lcd.setRGB(colorRed, colorGr, colorBl);
    lcd.setCursor(0, 0);
    lcd.print("Fire detected!");
    lcd.setCursor(0, 1);
    lcd.print("MQ2: ");
    lcd.print(mq2Percent);
    lcd.print(" %");
  }
  else if (checkForSmoke() == false) {
    lcd.setRGB(colorR, colorG, colorB);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temperature);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("Light: ");
    lcd.print(light);
    lcd.print("%");
  }
}

void displayOpeningCurtains() {
  const int colorR = 255;
  const int colorG = 255;
  const int colorB = 0;
  lcd.setRGB(colorR, colorG, colorB);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("    Opening");
  lcd.setCursor(0, 1);
  lcd.print("   Curtains!");
}

void displayClosingCurtains() {
  const int colorR = 255;
  const int colorG = 140;
  const int colorB = 0;
  lcd.setRGB(colorR, colorG, colorB);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("    Closing");
  lcd.setCursor(0, 1);
  lcd.print("   Curtains!");
}

void sendSensorValues() {
  //Sending the sensor values to the Blynk server
  Blynk.virtualWrite(vCURTAINSTATE_PIN, curtainState);
  Blynk.virtualWrite(vTEMPERATURE_PIN, temperature);
  Blynk.virtualWrite(vMQ2_PIN, mq2Percent);
  Blynk.virtualWrite(vLIGHT_PIN, light);
}

bool checkForSmoke() {
  if (mq2Percent > mq2Threshold) {
    return true;
  } else   return false;
}

void motorOpenOrClose() {
  if ((motorMoving == true) && (curtainState == true) && (interval > (millis() - previousMillis))) {
    displayClosingCurtains();
    for (int i = 0; i <= repetitions; i++) {
      myStepper.setSpeed(motorSpeed);
      myStepper.step(-stepsPerRevolution);
    }
  }
  if ((motorMoving == true) && (curtainState == false) && (interval > (millis() - previousMillis))) {
    displayOpeningCurtains();
    for (int i = 0; i <= repetitions; i++) {
      myStepper.setSpeed(motorSpeed);
      myStepper.step(stepsPerRevolution);
    }
  }
}

void openWithEventor() {
  if (curtainState == 0) {
    if ((eventorValue == 0) && (motorMoving == false)) {
      previousMillis = millis();
      motorMoving = true;
      curtainState = true;
    }
  }
  if (curtainState == 1) {
    if ((eventorValue == 1) && (motorMoving == false)) {
      previousMillis = millis();
      motorMoving = true;
      curtainState = false;
    }
  }
  motorOpenOrClose();
  if ((motorMoving == true) && ((millis() - previousMillis) > interval)) {
    myStepper.setSpeed(0);
    myStepper.step(stepsPerRevolution);
    motorMoving = false;
    eventorValue = 2; // Just a random number to wait for the next command. Not exactly needed!
    curtainState != curtainState;
  }
}

void openWithLight() {
  if (light >= lightThreshold) {
    if (curtainState == 1) {
      openCounter++;
    }
  }
  else {
    openCounter = 0;
  }
  if (light < lightThreshold) {
    if (curtainState == 0) {
      closeCounter++;
    }
  }
  else {
    closeCounter = 0;
  }
  if ((closeCounter > lightCounterThreshold) && (motorMoving == false)) {
    previousMillis = millis();
    motorMoving = true;
    curtainState = true;
  }
  if ((openCounter > lightCounterThreshold) && (motorMoving == false)) {
    previousMillis = millis();
    motorMoving = true;
    curtainState = false;
  }
  motorOpenOrClose();
  if ((motorMoving == true) && ((millis() - previousMillis) > interval)) {
    myStepper.setSpeed(0);
    myStepper.step(stepsPerRevolution);
    motorMoving = false;
    curtainState != curtainState;
    openCounter = 0;
    closeCounter = 0;
  }
}

BLYNK_WRITE(vZERGBA_PIN) {
  colorR = param[0].asInt();
  colorG = param[1].asInt();
  colorB = param[2].asInt();
  lcd.setRGB(colorR, colorG, colorB);
}

BLYNK_WRITE(vEVENTOR_PIN) {
  //Use the Eventor widget to check if it's time to do a task
  eventorValue =  param.asInt(); // 0 to 1
}

BLYNK_WRITE(vSWITCH_PIN) {
  //Default is Light control
  switchValue =  param.asInt(); // 0 to 1
}
Lightly: TCP Server CodeArduino
Upload this code and wire according to the connection diagram if you want to use the WIZ750SR as TCP Server
#include <SimpleTimer.h>
#include <Stepper.h>
#include "rgb_lcd.h"
#include <Wire.h>

//The code is written assuming that the curtain is open for the first time, meaning it will only close first
//and then open, and so on...

//Variables you may need to set:
float lightThreshold = 20.0;        //Threshold  value which decides whether to open or close the curtain
float mq2Threshold = 45.0;          //Enter the smoke sensor threshold values from 0 to 100 as needed
long lightCounterThreshold = 60000;  //Minimum successive light readings before Lightly decides to open or close the curtains
long interval = 20000;              //The motor will run for at least this time (in milliseconds)
int repetitions = 3;                //Increasing this number increases the time the motor runs in each go
int stepsPerRevolution = 400;       //The steps per revolution for your motor
int motorSpeed = 60;                //Speed of the motor. 60 is a good value for the Grove Stepper Motor for me

//Do not change these variables if you don't know what you're doing
String input;
float temperature, mq2Percent, light;   //These hold the sensor values
long previousMillis;                    //Holds the previous reading for the motor running timer
long openCounter, closeCounter;         //Counter telling how many successive readings taken to open or close curtains
bool motorMoving = false;               //Sets the motor as not moving in the start of the program
bool curtainState = false;              //curtainState false means curtain is open and true means closed
int pinLight = A0;                      //Pin for the light module
int pinTemp = A1;                       //Pin for the temperature module
int pinMq2 = A2;                        //Pin for the gas sensor
int colorR = 255, colorG = 255, colorB = 255;    //Default colour is white for the Grove RGB LCD

//Initializing the LCD and Simpletimer library
rgb_lcd lcd;
SimpleTimer timer;

//Initialize the stepper library on pins 8 to 11
//Try 8,10,9,11 if everything appears ok and you still have issues with the motor. The stepper motor I used wouldn't
//work with the order 8,9,10,11. Browsing the internet about this issue showed that the wires can sometimes not be
//in the expected order. You can read about that here: https://forum.arduino.cc/index.php?topic=143276.0
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup()
{
  Serial.begin(9600);
  Serial1.begin(115200);

  delay(1000); // Give the WIZ750SR a second to initialize

  //Setup the timed fuctions
  timer.setInterval(1000L, sendSensorValues);
  timer.setInterval(2000L, displayData);

  lcd.begin(16, 2);

  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  lcd.setRGB(colorR, colorG, colorB);
  lcd.setCursor(0, 0);
  lcd.print("    Lightly");
  lcd.setCursor(0, 1);
  lcd.print("Smarter Lighting");
  delay(2000);
}

void loop()
{
  getSensorData();
  timer.run();
  openWithLight();
  checkForChangingVariables();
}

void getSensorData() {
  int B = 3975;
  float resistance;
  int mq2Value = analogRead(pinMq2);
  int val = analogRead(pinTemp);
  int sensorReading = analogRead(pinLight);
  light = map(sensorReading, 0, 1023, 0, 100);
  mq2Percent = (mq2Value / 1023.0) * 100.0;
  resistance = (float)(1023 - val) * 10000 / val;
  temperature = 1 / (log(resistance / 10000) / B + 1 / 298.15) - 273.15;
}

void displayData() {
  if (checkForSmoke() == true) {
    int colorRed = 255;
    int colorGr = 0;
    int colorBl = 0;
    lcd.clear();
    lcd.setRGB(colorRed, colorGr, colorBl);
    lcd.setCursor(0, 0);
    lcd.print("Fire detected!");
    lcd.setCursor(0, 1);
    lcd.print("MQ2: ");
    lcd.print(mq2Percent);
    lcd.print(" %");
  }
  else if (checkForSmoke() == false) {
    lcd.setRGB(colorR, colorG, colorB);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(temperature);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("Light: ");
    lcd.print(light);
    lcd.print("%");
  }
}

void displayOpeningCurtains() {
  const int colorR = 255;
  const int colorG = 255;
  const int colorB = 0;
  lcd.setRGB(colorR, colorG, colorB);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("    Opening");
  lcd.setCursor(0, 1);
  lcd.print("   Curtains!");
}

void displayClosingCurtains() {
  const int colorR = 255;
  const int colorG = 140;
  const int colorB = 0;
  lcd.setRGB(colorR, colorG, colorB);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("    Closing");
  lcd.setCursor(0, 1);
  lcd.print("   Curtains!");
}

void sendSensorValues() {
  Serial1.println();
  Serial1.print("Temperature: ");
  Serial1.print(temperature);
  Serial1.println(" C");
  Serial1.print("Smoke: ");
  Serial1.print(mq2Percent);
  Serial1.println("%");
  Serial1.print("Light: ");
  Serial1.println(light);
  Serial1.print("Curtain State: ");
  if (curtainState == true) {
    Serial1.println("Opened");
  }
  if (curtainState == false) {
    Serial1.println("Closed");
  }
}

bool checkForSmoke() {
  if (mq2Percent > mq2Threshold) {
    return true;
  } else   return false;
}

void motorOpenOrClose() {
  if ((motorMoving == true) && (curtainState == true) && (interval > (millis() - previousMillis))) {
    displayClosingCurtains();
    for (int i = 0; i <= repetitions; i++) {
      myStepper.setSpeed(motorSpeed);
      myStepper.step(-stepsPerRevolution);
    }
  }
  if ((motorMoving == true) && (curtainState == false) && (interval > (millis() - previousMillis))) {
    displayOpeningCurtains();
    for (int i = 0; i <= repetitions; i++) {
      myStepper.setSpeed(motorSpeed);
      myStepper.step(stepsPerRevolution);
    }
  }
}

void openWithLight() {
  if (light >= lightThreshold) {
    if (curtainState == 1) {
      openCounter++;
    }
  }
  else {
    openCounter = 0;
  }
  if (light < lightThreshold) {
    if (curtainState == 0) {
      closeCounter++;
    }
  }
  else {
    closeCounter = 0;
  }
  if ((closeCounter > lightCounterThreshold) && (motorMoving == false)) {
    previousMillis = millis();
    motorMoving = true;
    curtainState = true;
  }
  if ((openCounter > lightCounterThreshold) && (motorMoving == false)) {
    previousMillis = millis();
    motorMoving = true;
    curtainState = false;
  }
  motorOpenOrClose();
  if ((motorMoving == true) && ((millis() - previousMillis) > interval)) {
    myStepper.setSpeed(0);
    myStepper.step(stepsPerRevolution);
    motorMoving = false;
    curtainState != curtainState;
    openCounter = 0;
    closeCounter = 0;
  }
}

void checkForChangingVariables() {
  input = Serial1.readString();
  if (input == "lightThreshold") {
    Serial1.println();
    Serial1.print("'lightThreshold' value is: ");
    Serial1.println(lightThreshold);
    Serial1.print("Please enter the new value from 1 to 100: ");
    lightThreshold = 0.0;
    while (lightThreshold == 0.0) {
      lightThreshold = Serial1.parseFloat();
    }
    Serial1.println();
    Serial1.print("New 'lightThreshold' value is: ");
    Serial1.println(lightThreshold);
    Serial1.println();
  }
  if (input == "mq2Threshold") {
    Serial1.println();
    Serial1.print("'mq2Threshold' value is: ");
    Serial1.println(mq2Threshold);
    Serial1.print("Please enter the new value from 1 to 100: ");
    mq2Threshold = 0.0;
    while (mq2Threshold == 0.0) {
      mq2Threshold = Serial1.parseFloat();
    }
    Serial1.println();
    Serial1.print("New 'mq2Threshold' value is: ");
    Serial1.println(mq2Threshold);
    Serial1.println();
  }
  if (input == "lightCounterThreshold") {
    Serial1.println();
    Serial1.print("'lightCounterThreshold' value is: ");
    Serial1.println(lightCounterThreshold);
    Serial1.print("Please enter the new value: ");
    lightCounterThreshold = 0;
    while (lightCounterThreshold == 0) {
      lightCounterThreshold = Serial1.parseInt();
    }
    Serial1.println();
    Serial1.print("New 'lightCounterThreshold' value is: ");
    Serial1.println(lightCounterThreshold);
    Serial1.println();
  }
  if (input == "interval") {
    Serial1.println();
    Serial1.print("'interval' value is: ");
    Serial1.println(interval);
    Serial1.print("Please enter the new value: ");
    interval = 0;
    while (interval == 0) {
      interval = Serial1.parseInt();
    }
    Serial1.println();
    Serial1.print("New 'interval' value is: ");
    Serial1.println(interval);
    Serial1.println();
  }
  if (input == "repetitions") {
    Serial1.println();
    Serial1.print("'repetitions' value is: ");
    Serial1.println(repetitions);
    Serial1.print("Please enter the new value (at least 1): ");
    repetitions = 0;
    while (repetitions == 0) {
      repetitions = Serial1.parseInt();
    }
    Serial1.println();
    Serial1.print("New 'repetitions' value is: ");
    Serial1.println(repetitions);
    Serial1.println();
  }
  if (input == "stepsPerRevolution") {
    Serial1.println();
    Serial1.print("'stepsPerRevolution' value is: ");
    Serial1.println(stepsPerRevolution);
    Serial1.print("Please enter the new value: ");
    stepsPerRevolution = 0;
    while (stepsPerRevolution == 0) {
      stepsPerRevolution = Serial1.parseInt();
    }
    Serial1.println();
    Serial1.print("New 'stepsPerRevolution' value is: ");
    Serial1.println(stepsPerRevolution);
    Serial1.println();
  }
  if (input == "motorSpeed") {
    Serial1.println();
    Serial1.print("'motorSpeed' value is: ");
    Serial1.println(motorSpeed);
    Serial1.print("Please enter the new value: ");
    motorSpeed = 0;
    while (motorSpeed == 0) {
      motorSpeed = Serial1.parseInt();
    }
    Serial1.println();
    Serial1.print("New 'motorSpeed' value is: ");
    Serial1.println(motorSpeed);
    Serial1.println();
  }
}

Custom parts and enclosures

Lightly case
This is just an example model of how I want the enclosure to be, not at all ready to use!

Schematics

Connection Diagram
Wire it up after setting according to this, but take care of the voltages yourself; I won't talk about that.
Lightly diagram 2 wstfh4kusb

Comments

Similar projects you might like

Smart Garbage Monitoring System Using Arduino 101

Project tutorial by Technovation

  • 22,638 views
  • 7 comments
  • 37 respects

SMS alerts for arduino 101 BLE

Project tutorial by Alexis Santiago Allende

  • 2,007 views
  • 0 comments
  • 8 respects

SMART CUBE: A New Way to Control Your Home

Project tutorial by Alberto Sartori

  • 13,940 views
  • 7 comments
  • 31 respects

Eco-Thing #1 "Eco-Smart-Container V1.0"

Project tutorial by Alexis Santiago Allende

  • 5,305 views
  • 4 comments
  • 28 respects

Hackster Live April 2017 Workshop - Optional - Easy Add-on

Project tutorial by Katie Kristoff

  • 900 views
  • 3 comments
  • 7 respects

Waternator 293

Project tutorial by Thug Design

  • 2,616 views
  • 1 comment
  • 5 respects
Add projectSign up / Login