Motorized Window Blinds Controller

2,813

30

1

Introduction: Motorized Window Blinds Controller

For this project you will be creating a device that is capable of opening and closing window blinds, both automatically and manually (via a push button), based upon a time schedule and sensor data from a light dependent resistor. In addition, this device will be able to display messages to the user.

I personally embarked on this project to keep my plants happy and healthy!

Step 1: What You'll Need: Part I

Materials:

For the hardware

  • Solderless Breadboard (x1)
  • Light Dependent Resistor (x1)
  • Push Button (x1)
  • 16 x 2 LCD Display (x1)
  • Servo Motor (x1)
  • Motor Attachments My servo came with a little set of attachments.
  • Arduino Uno (x1)
  • Micro-USB to USB Cable (x1)
  • 5v USB Wall Adapter (x2)
  • Dupont Connector (x8) I used two each of red, orange, yellow, and green
  • Assorted Colors of Electrical Wire I used red, black, white, yellow, green, and blue
  • Electrical Tape

For the hardware's housing

  • 2 Pieces of 14" x 3 5/8" Birch Plywood for the Top and Bottom *all of your wood should be a 1/2" thick*
  • 1 Piece of 14" x 3 1/4" Birch Plywood for the Front Face *I used all scrap wood for this project*
  • 1 Piece of 5 5/16" x 3 1/4" Birch Plywood for Back Face I
  • 1 Piece of 3 1/4" x 1 3/4" Birch Plywood for Back Face II
  • 1 Piece of 9 3/16" x 3 1/4" Birch Plywood for Back Face III
  • 1 Piece of 3 1/4" x 2 1/2" Birch Plywood for Side I
  • 1 Piece of 3 1/4" x 3 5/8" Birch Plywood for Side II
  • 1 Piece of 2" x 3/4" x 3/8" Birch Plywood for Breadboard Support
  • 1 Piece of 3/8" x 3/4" x 1/2" Birch Plywood for Breadboard Support
  • 1/4" Gage Wooden Dowel (x1)
  • 1/2" Gage Wooden Dowel (x1)
  • 1/8" thick Plexiglas
  • 5/8" Gage Rubber Stopper (x1)
  • 15/32" Gage Test Tube I used a glass test tube but would recommend using a plastic one
  • Brad Nails
  • Wood Glue
  • Two-Part Epoxy
  • Tung Oil Not necessary but gives the wood a nice finish
  • Twist Ties Also not necessary, but are useful for tidying wires
  • Sculpey - Oven Bake Polymer Clay

Step 2: What You'll Need: Part II

Tools:

Here, I'm going to list the tools I used for this project. I am lucky enough to have access to a well equipped woodshop and some of the tools I used are likely unavailable to the average-joe, so I will try to provide alternatives throughout the rest of this instructable.

  • Ruler
  • Pencil
  • Multi-meter
  • Wire Cutters
  • Soldering Iron
  • X-acto Knife
  • Drill
  • Drill Bits - 5/8", 1/2", 1/4"
  • Miter Gauge
  • Jig Saw
  • Band Saw
  • Table Saw
  • Mouse Palm Sander
  • Various Wood/Metal Files
  • Sand Paper
  • C-clamps
  • Strap Clamps
  • Vice Clamp

Step 3: Cut Your Plywood and Plexiglass

I used the table saw to cut the longer pieces of wood and a miter saw to cut the rest. However, you could probably get by using a hacksaw to makes these cuts. I also used the band saw with a miter gauge to cut the indent into the top and bottom pieces.

The top and bottom of your hardware's housing should 14" long and 3 5/8" wide. You'll need to cut a rectangle out of the side of your top and bottom pieces, that is 4 13/16" long and 1 1/18" wide (this is the "indent", that I referred to previously).

The front face should be 14" long and 3 1/4" wide. You're going to need 3 back faces due to that indent cut into the top and bottom pieces earlier. Your 3 back faces should be cut as such:

  • Back Face I - 5 5/16" x 3 1/4"
  • Back Face II - 1 3/4" x 3 1/4"
  • Back Face III - 9 3/16" x 3 1/4"

Your first side piece will need to be 3 1/4" long and 2 1/2" wide and your second side piece should be 3 1/4" long and 3 5/8" wide.

You'll need two supports for your breadboard, one should be 2" long, 3/4" wide, and a 3/8" thick and the other should be 3/8" long, 3/4" wide, and a 1/2" thick.

You'll later be using your dowels to create a sort of wooden button or push/pull knob but we may as well go ahead and cut them now. All of these cuts were done on the miter saw. From the 1/2" gage dowel, you'll cut two pieces. One should be 5/8" long and the other 3/32" From the 1/4" gage dowel, you should cut a single piece that is roughly an 1/8" long. I suggest cutting your 1/4" gage dowel and shorter 1/2" gage dowel longer than you need and sanding them down to size.

The plexiglas is for a sort of lid mechanism and will be attached to the top piece. I cut my plexiglas using the band saw, with a fence attached. You could also use a Plexiglas cutter, which are cheap and easy to use. You'll need to cut six strips of plexiglas, all at different lengths:

Each piece should be an 1/8" thick and 5/16" wide.

  • 1 piece of plexiglas 4 1/2" long
  • 1 piece of plexiglas 1 5/8" long
  • 1 piece of plexiglas 1" long
  • 1 piece of plexiglas 8 1/4" long
  • 1 piece of plexiglas 3" long
  • 1 piece of plexiglas 13" long

To make sure your fence is positioned correctly, measure from the edge of the band saw's table to the saw blade and add 5/16". Measure from one side of band saw and clamp that side down, then do the same to the other.

Step 4: Miter All of Your Edges

I mitered all of my edges using the table saw. If you're using a table saw, you'll need to remove the guard and hose that rest atop the blade and tilt the blade to a 45°. If you don't have access to a table saw, you could try to miter the edges using a hacksaw but it might be easier to just make butt joints instead.

On all of the pieces, except for back face's I and II, you should miter all of the edges on the same face of each piece of wood. This means that as you miter the edges of a piece, it should lay flat on the table and at no point should you need to lift it off the table - you should only need to rotate it to change which edge you are mitering.

For the top and bottom pieces, be sure to miter on opposite faces so that the pieces are mirrors of each other rather than exact duplicates.

For back face's I and II, you'll have to miter one of the 3 1/4" edges on the opposite face of all the other edges.

Refer to the image, if you're still unclear on where to miter.

Step 5: Cut Grooves for Lid and Internal Supports

This simple lid will allow you to freely insert or remove the hardware from your housing. To create this, you'll need to cut grooves into the meeting edges of both sides, all 4 faces, and the top of your housing.

To cut all of my grooves, I used the table saw. You could do these cuts with a hacksaw, but it might be kind of a hassle. If you do intend on using a hacksaw, I highly recommend clamping your wood down with two other pieces of wood atop it in such a fashion that they create a guide channel.

If you're using a table saw, in order for your wood to pass over the blade, you'll have to remove the hose and guard that rests behind and atop it, just as you did for the mitered edges.

  • For the top the grooves should all be 13/32" deep and should be 5/16" in from the edge, you should run the top over the blade on its inner face (the face that will be on the inside of the housing). You're going to miter every edge on the top piece.

For all the other pieces, the grooves should be 27/32" deep and 5/16" in from the edge but into the sides of the wood rather than its face. You only need to put a groove on a single edge on each piece.

For the supports, you're going to want to create sort of a lip on them, so you'll pass them over the blade multiple times so that you're left with a small ledge protruding along one side. This ledge should be 3/16" thick and about 5/32" in height for the first support for you breadboard. The lip on the second support for your breadboard should be a little thinner, at 3/32" thick.

Step 6: Glue in Plexiglas Strips

Take your plexiglas strips and glue them into the grooves of a corresponding size, on your top piece. Be sure to use two-part epoxy to do this, seeing that wood glue will not hold.

Step 7: Drill Holes Into Your Wood and Rubber Stopper

On the top piece, you're going need to drill quite a few holes:

*The measurements are made in reference to the inside face of the top piece.*

  • First, drill a 5/8" hole centered and 1 1/4" in from the edge that will connect to side II. This hole will be for your light dependent resistor
  • Then, drill a 1/4" hole centered and 2 5/8" in from the edge of the indent. These holes will be for your push button
    • In the same hole. take your 1/2" drill bit and drill down 5/16", be sure to go slow.
    • Flip the wood over and drill down 3/16"...still the same hole.
  • Next you'll need to draw a rectangle that is the same dimensions as your servo, centered and 13/16" in from the edge of the indent.
  • Using the 1/4" drill bit, drill a hole inside each corner of the rectangle.

On the front face, you're going to need to create a well for the lcd screen and, thus, we need to make holes for the jig saw:

*The measurements are made in reference to the outside face for the front face and bottom pieces.*

  • Draw a rectangle that is the same dimensions as your lcd screen, centered and 1 3/16" in from the left edge.
  • Using the 1/4" drill bit, drill 4 holes with one inside each corner of the rectangle.

The micro-USB to USB and spliced USB cable will need a 5/8" hole to pass through. Drill this hole on the bottom, centered and 1" in from the edge on the skinnier side.

Now I know that drilling a hole into a rubber stopper of this size sounds ridiculous but it's feasible. The stopper will ride up the drill bit but it's nothing to be concerned about. You're going to have to widen this hole quite a bit more, so use an exact-o knife to remove some material. Once the hole is big enough, run a circular wood file though it and continue to do this until you're test tube fits into the hole.

Step 8: Modify Servo and Create Wells for the Servo and LCD And

In order for your servo to fit in the well, you'll have to sand or cut off the nubs on the sides - I used a belt sander to do so but you could probably get them off with a hacksaw.

I used the jig saw to create my wells, using a blade thin enough to fit into the previously drilled holes.

  • Once you've cut out your rectangle, cleanup the inside of your wells with a flat wood file. Each time I changed the orientation of my wood in the vice, I checked to make sure it was level at the top before filing.
  • If your LCD screen or servo can fit snugly into your well, go ahead and bevel the edges of your well that will be visible from the outside.
    • To do this I used a c-clamp to attach my wood flat onto the table and used flat files to bevel the edges
    • To round the corners of my well, I used a circular wood file.

Step 9: Glueing the Two Faces, Bottom, and Blank Side Together

Using wood glue, I joined together the four faces, two sides and bottom of the housing. While I was glueing I strapped the top piece in to maintain the housing's structure but did not glue it. To hold all the pieces in place while the glue dried, I used four strap clamps, two c-clamps, and a bunch of these little metal corners that accompany the strap clamps. You'll need to cut and or find a piece of wood that will fit into the indentation, so that pressure is applied there as well.

Step 10: Creating Push Button and Enclosure for Light Dependent Resistor

*All the images used here are from my first version of the housing, so ignore the plexiglas sticking out of the sides.*

To create this push button, you're going to use the 3 pieces of wood you cut from your dowels.

  • Take the side of your housing with plexiglas attached and on the backside place your 3/16" long dowel into the circular well we created.
  • Flip your wood over and place a dot of wood glue onto your 1/8" long dowel, then place it into the 1/4" hole and press it into the 3/16" dowel.
  • Finally, take your 5/16" dowel and put it in the circular well, atop your 1/8" dowel.
  • Firmly squeeze all these pieces together and rotate them, to make sure they can move around within their hole.

For the enclosure for the light dependent resistor you'll need to cut your glass or plastic test-tube down to size. I made my test-tube just long enough to protrude roughly 3/8" out of the hole we drilled for it. So the total length of my test tube is 7/8".

  • To cut my glass, I used a triangular metal file to score the tube. Be sure to score perpendicular to the glass. You're score doesn't need to be very long, just about a 1/4".
  • Once you've scored your glass, take your tube and place the score on the opposite side of your two thumbs and snap the glass. You should get a clean edge, but I certainly didn't.
  • If your edge is a little rough, you can sand the glass down on high grit sandpaper. Anything below 150 grit and your glass will start to chip.
  • If you're still unclear on how to break the glass, this website may be helpful http://www.ilpi.com/glassblowing/tutorial_cutting...

If you're cutting a plastic test-tube, you can easily do so with a band saw or a hacksaw.

Once your glass/plastic is cut, all you have to do is stick it into the rubber stopper we modified earlier and then shove these two things into the 5/8" hole we drilled. If for whatever reason your hole is slightly too large, you can glue the enclosure into the hole with epoxy.

Step 11: Strengthening Your Housing

To make my box a little stronger, I placed eight wood screws in the bottom of the housing using a drill. In earnest, I just eye-balled where to put them and went for it. So just refer to the image and place them roughly a 1/4" in from the edge.

Step 12: Adding Supports to the Inside of Your Housing

Your hardware will need some supports inside of your housing, to prevent it from waggling around too much.

  • Take your top piece or lid and put your servo into the cutout you made for it.
  • Then, take your internal support that is 2" long and glue it in so that it's flush with the right side of your servo and positioned right on top of it.
  • Then, take your second support for the breadboard and glue it's 3/16" in from the right inner-edge and 1/8" in from the top inner-edge of your wood.
  • I used a c-clamp to hold my supports in place, while the wood glue dried.

Step 13: Finishing Your Housing

Now that your housing is all put together, you can sand the outside and apply a coating of some sort to your wood.

I used tung oil and have put on a couple coats (I have plans of putting on a few more). You have to re-sand and wait 24 hours between each coating of tung oil .

There you have it, you've completed the housing for your hardware!

Step 14: Attaching a French Cleat to Your Housing

If you'd like to wall mount your housing, IFrench cleats are super easy to make and fairly strong. This cleat will allow you to hang your window blinds controller on the wall.

Here's a nice little instructable on French cleats: https://www.instructables.com/id/French-Cleat/

I would make two cleats, one to go on back face I and the other for back face II. The dimensions of your cleats are dependent upon size of your window casing.

Step 15: Making Your Blinds Rod Connector

To make your blinds rod connector:

  • Roll your polymer clay into a cylinder. You'll want the cylinder to be larger in circumference than your blinds rod. The length of your clay connector depends upon whether you are attaching your housing to the wall or resting it on the windowsill. I made my connector using a 1/4 of the polymer clay and rolled it to 1 1/2" long
  • Flatten the top and bottom of your cylinder by lightly tapping them on a flat surface.
  • Take your cylinder and gently wiggle the blinds rod into it.
  • Wiggle the rod back out and gently roll the cylinder again, if it has become misshapen. If you're blinds connector is still kinda lumpy after this step, don't fret it doesn't have to be pretty - just functional. The most important thing is that your connector, blinds rod, and servo all align vertically.
  • Lightly press the sides of cylinder, around the impression made from the rod, to make sure the opening is not too loose.
  • Bake your rod connector in the oven for 15 minutes at 275° F.
  • Let the connector cool.
  • Glue the connector to one of the servo attachments, with epoxy.

Voilà, now you have a mechanism to attach your servo to your twist rod!

Step 16: Modifying Your Servo for Continuous Rotation

Standard servos only have 180 degrees of motion and, as far as I'm aware, most blinds rods require multiple rotations to open or close. So, you're going to have to modify your servo for continuous rotation. Modifying a servo is quite simple, all you have to do is remove the physical stop that prevents the gear from rotating further and alter the slot that the potentiometer goes into.

To do so, I followed this video:

https://www.youtube.com/watch?v=SK8mhnEzcvY

Step 17: Making Your LCD and Servo Power Source

The Arduino cannot power both the LCD display and servo at the same time, so they'll need to be provided with a separate power source.

To create this, I used:

  • 5v USB Wall Adapter
  • 2 Insulated Wires preferably of different colors or with different identifying marks
  • USB Cable
  • Wire Cutters
  • X-acto Knife
  • Soldering Iron
  • Silver Solder
  • Electrical Tape
  • Multi-meter

I roughly followed this video:

The main difference is that we cut away all except for the red and black wires because these are the only two that we need to provide power.

If you don't feel like watching the video all the way through, here are some loose instructions to keep you on track:

  1. Chop off the non-USB head of your USB cable or just one of the heads if it's a USB to USB.
  2. Strip approximately an inch of the exterior insulation, using an x-acto knife or wire cutters.
  3. Cutaway the insulating metal wire, plastic-y foil material, string, and all wires but the red and black.
  4. Strip the red and black wires about 1/2" .
  5. Strip both ends of your two insulated wires about 1/2".
  6. Twist the stripped red wire and a stripped portion of one of your insulated wires together.
  7. Twist the stripped black wire and a stripped portion of the other insulated wire together.
  8. Solder each of these two connections.
  9. Tightly wrap each connection in electrical tape separately and then tape them together. *you do not want these two wires to touch, it'd be a bad time for everyone involved*
  10. Twist up the stripped ends of your two wires, so they're nice and tight (don't twist them together).
  11. Connect the USB end of your spliced cable to the 5v adapter.
  12. Check to see if multimeter reads 5v, to make sure your connection is good. If so, well done! If not, try again!

Step 18: Constructing Your Hardware

To recap, here's what you'll need to construct your hardware:

  • Materials -
    • Solderless Breadboard (x1)
    • Light Dependent Resistor (x1)
    • Push Button (x1)
    • 16 x 2 LCD Display (x1)
    • Servo Motor (x1)
    • Arduino Uno (x1)
    • Micro-USB to USB Cable (x1)
    • USB Wall Adapter (x1)
    • Spliced USB Cable and 5v Adapter (x1)
    • Dupont Connector (x4) I used red, orange, yellow, and green
    • Pre-made Connector (x3) I used black, red, and white
    • Assorted Colors of Electrical Wire I used red, black, white, yellow, green, and blue
    • Maybe a Rubber-band or Hair-tie
    • Blinds Connector
  • Tools -
    • Wire Cutters
    • Small Phillips Head Screw Driver
    • Teeny Tiny, Flat Head Screw Driver
    • Belt Sander or Sand Paper
    • Hands

The attached file is for the Fritzing schematic pictured above.

Step 19: Cutting and Stripping Your Wires

I decided to cut my wires pretty short, so they would allow the breadboard to rest closer to the wood when it's in the housing.

You'll need to cut:

  • 1 black wire 4" long
  • 3 black wires 1 3/16" long
  • 1 black wire 7/8" long
  • 1 red wire 4" long
  • 3 red wires 7/8" long
  • 1 green wire 1 3/16" long
  • 1 yellow wire 7/8" long
  • 1 blue wire 3" long
  • 1 blue wire 4 1/4" long

The exposed or stripped area of all of your wires should be roughly 2/8" long. To strip your wires, simply cut a slit lengthwise along your wire and peel.

Go ahead and trim the legs of your resistors to a similar length as the exposed wires.

Step 20: Wiring Your Breadboard

From the bottom to the top of your breadboard, with the negative pins on the left :

  • 4" black wire going to -4 this wire will connect to gnd on the Arduino
  • 4" red wire going to +4 this wire will connect to 5v on the Arduino
  • 7/8" red wire going from +5 to A5 this will be the (+) ground for your pushbutton
  • 1 3/16" black wire going from -10 to A10 this will be the (-) ground for your pushbutton
  • Resistor going from B7 to B10
  • 4 1/4" blue wire going to 7C this wire will be the communication for your pushbutton and go to pin 8 on your Arduino
  • 7/8" red wire going from +44 to A44 this will be the (+) ground for your servo
  • Pre-made red connector going to B44 this wire will connect to the red wire on your servo
  • 1 3/16" black wire going from -46 to A46 this will be the (-) ground for your servo
  • Pre-made black connector going to B46 this wire will connect to the black wire on your servo
  • 7/8" black wire going from -29 to -32 this wire connects the ground for the two halves of your breadboard
  • 7/8" red wire going from +49 to A49 this wire will be (+) ground for your LDR
  • Light dependent resistor going from E49 to E51
  • 3" blue wire going to C51 this wire will be the communication wire for your light dependent resistor and connect to pin 7 on the Arduino
  • Resistor going from B51 to B53
  • 1 3/16" black wire going from -53 to A53 this will serve as the (-) ground for your light dependent resistor
  • 7/8" yellow wire going from +37 to A37 this will serve as the (+) ground for your lcd display
  • 1 3/16" green wire going from -39 to A39 this will serve as the (-) ground for your lcd display
  • 2 8" yellow dupont connectors going to B37 this will connect the (+) ground to VCC on your lcd display
  • 2 8" green dupont connectors going to B39 this will connect the (-) ground to GND on your lcd display

Step 21: Wiring Your Arduino

So that they would come easily in and out of my housing and so that my wiring wouldn't get too terribly messed up, I rubber-banded the back of my Arduino (micro-USB port facing down) to the back of my breadboard - about 1 5/16" down from the top.

  • Connect the 4" black wire going to -4 to gnd on the Arduino. provides (-) ground to breadboard
  • Connect the 4" red wire going to +4 to 5v on the Arduino. provides (+) ground to breadboard
  • Connect the 4 1/4" blue wire going to 7C to pin 8 on the Arduino. allows for communicating between pushbutton and Arduino
  • Connect the 3" blue wire going to C51 to pin A0 on the Arduino. allows for communication between light dependent resistor and Arduino
  • Connect the pre-made white connector to pin 9 on the Arduino. allows for communication between servo and breadboard
  • You will also have two dupont connectors going to SCL and SDA on the Arduino, for communication with the LCD, but we will connect these after everything is already in the housing.

Step 22: Inserting Hardware Into Its Housing and Wiring Servo + LCD Display

    • Place the LCD display into its well, with the red dupont connector connecting to the SCL pin and the orange dupont connector connecting to SDA on your the LCD display.
    • Place the servo into its well.
    • Thread the spliced USB cable through the hole you drilled for it and attach the (-) ground to GND on the Arduino and the (+) to +59 on the breadboard.
    • Nestle the breadboard/Arduino into its supports.
    • Connect the pre-made white wire to the white wire on your servo. allows for communication between servo and Arduino
    • Connect the pre-made red wire to the red wire on your servo. provides (+) ground for servo
    • Connect the pre-made black wire to the black wire on your servo. provides the (-) ground for servo
    • Thread the micro-USB to USB cable through the hole you drilled for it and connect it to the Arduino's USB port. provides power to your Arduino
    • Connect the red dupont connector to the SCL pin and the orange dupont connector to the SDA pin, on the Arduino. allows for communication between LCD display and Arduino
    • Connect the yellow dupont connector to VCC and the green dupont connector to GND, on the LCD display. provides (+) and (-) ground to the LCD display
    • You can now close your lid.

    You're all done with the hard part! Congrats!

    Step 23: Upload Code to Your Arduino

    Before you upload the code to your Arduino, the .ino, .h and .cpp files must all be in a folder together.

    Here's the main code:

    <p>/* Blinds Controller<br> *  This project allows you to open and close your blinds via the push of a button, display messages dependent upon sensor input and automatically open blinds based on sensor input. 
     *  Code was created via the combination and modification of code from:
     *  <a href="https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://forum.arduino.cc/index.php?topic=424068.0"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://www.arduino.cc/en/Hacking/LibraryTutorial"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://arduino.stackexchange.com/questions/17536/controlling-servo-motors-with-push-button-problem-though"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://arduino-info.wikispaces.com/LCD-Blue-I2C"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://gist.github.com/RC1140/3299197"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://maker.pro/education/using-an-ldr-sensor-with-arduino-a-tutorial-for-beginners"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="https://gist.github.com/RC1140/3299197"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  <a href="http://forum.arduino.cc/index.php?topic=122446.0"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     *  
     *  You can download the LiquidCrystal_I2C library from here: <a href="https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library"> https://learn.adafruit.com/multi-tasking-the-ardu...</a>
     */</p><p>#include "Display.h"
    #include "Twist.h"
    #include "Arduino.h" 
    #include <LiquidCrystal_I2C.h>
    <liquidcrystal_i2c.h>
    #include <Wire.h><wire.h>
    #include <string.h><string.h></string.h></wire.h></liquidcrystal_i2c.h></p><p><liquidcrystal_i2c.h><wire.h>#include <Servo.h></wire.h></liquidcrystal_i2c.h></p><p> 
    Twist twist1(15);</p><p>Display display1;</p><p> 
    void setup() 
    {  
      twist1.Attach(9);
      Serial.begin(9600);
    } 
     
     
    void loop() 
    { 
      display1.Message1(1);
      display1.Message2();
      display1.Message3();
      twist1.Update();
      twist1.AutoOpen();
    };</p>

    Here's Display.h:

    <p>#ifndef Display_h<br> #define Display_h
     
    #include "Arduino.h"
    #include <LiquidCrystal_I2C.h>
    <liquidcrystal_i2c.h>
    #include <Wire.h><string.h>
    #include <string.h><wire.h>
       
     
     class Display
     {
      
    unsigned long previousMillisMessage2 = 0;        // will store last time LCD was updated w/Message 2
    unsigned long previousMillisMessage3 = 0;        // will store last time LCD was updated w/Message 3
    unsigned long currentMillis;
    unsigned long intervalMessage2 = 625;           // interval at which to update LCD for Message 2
    unsigned long intervalMessage3 = 24UL*60UL*60UL*1000UL;  // interval at which to update LCD for Message 3
    unsigned long waitMessage3 = 2UL*60UL*60UL*1000UL; //interval at which Message 3 waits to display</wire.h></string.h></liquidcrystal_i2c.h></p><p>int  updateInterval;      // interval between updates
    unsigned long lastUpdate; // last update of position</p><p>const int ldrPin = A0;  // light dependent resistor pin
    int ldrState = 0;  // variable to store the value coming from the sensor</p><p>const int buttonPin = 8; // pushbutton pin
    int buttonState = 0; //local variable to hold button states</p><p>int directionState = 0;</p><p> 
    public:
     void Message1(int refreshSeconds);
     void Message2();
     void Message3();
     };
      #endif</p>

    Here's Display.cpp:

    <p>#include "Display.h"<br>#include <LiquidCrystal_I2C.h>
    <liquidcrystal_i2c.h> 
    #include "Arduino.h" 
    #include <Wire.h><wire.h>
    #include <string.h><string.h></string.h></wire.h></liquidcrystal_i2c.h></p><p>LiquidCrystal_I2C lcd(0x3F, 16, 2);
    char message1[] = "Open the damn blinds! Or else, innocent plants will die.";
    unsigned long previousMillisMessage1 = 0;  
    int pos = 0;</p><p>const int ldrPin = A0;  // light dependent resistor pin
    int ldrState = 0;  // variable to store the value coming from the sensor</p><p>void Display::Message1(int refreshSeconds)
    {
     
      ldrState = digitalRead(ldrPin);
       if (ldrState == HIGH)
        {
      
      //Check if the current second since restart is a mod of refresh seconds , 
      //if it is then update the display , it must also not equal the previously 
      //stored value to prevent duplicate refreshes
      if((millis()/650) % refreshSeconds == 0 && previousMillisMessage1 != (millis()/650)){
        previousMillisMessage1 =  (millis()/650);//Store the current time we entered for comparison on the next cycle</p><p>    lcd.setCursor(0, 1);//Set our draw position , set second param to 0 to use the top line
        char lcdTop[16];//Create a char array to store the text for the line
        int copySize = 16; // What is the size of our screen , this could probably be moved outside the loop but its more dynamic like this
        if(strlen(message1) < 16)
        {
            //if the message is bigger than the current buffer use its length instead;
            copySize = strlen(message1);
        }
        //Store the current position temporarily and invert its sign if its negative since we are going in reverse
        int tempPos = pos;
        if(tempPos < 0)
        {
            tempPos = -(tempPos);
        }
        //Build the lcd text by copying the required text out of our template message variable 
        memcpy(&lcdTop[0],&message1[tempPos],copySize);
        lcd.print(lcdTop);//Print it from position 0
        //Increase the current position and check if the position + 16 (screen size) would be larger than the message length , if it is go in reverse by inverting the sign.
        pos += 1;
        if(pos +16 >= strlen(message1))
        {
          pos = -(pos);
        }
      }
    }
    }</p><p>  void Display::Message2()
     {
     lcd.begin();</p><p>   {
         if((millis() - lastUpdate) > updateInterval)  // time to update
         {
           lastUpdate = millis();</p><p>    buttonState = digitalRead(buttonPin);
       if (directionState == 0) {
         if (buttonState == HIGH) {
           directionState = 1;
           {
      lcd.clear();
      lcd.setCursor(0,0); //Start at character 0 on line 0
      lcd.print("Thank you!");
          
           }
         }
       } </p><p>   else if (directionState == 1) {
         if (buttonState == HIGH) {
           directionState = 0;
        {  
      lcd.clear();
      lcd.setCursor(0,0); //Start at character 0 on line 0
      lcd.print("Thank you!");
         
       }
      }
     }
      }
       }
        }
     </p><p>void Display::Message3()
     {
     lcd.begin();
     ldrState = digitalRead(ldrPin); //read the digital value of ldrPin with digitalRead() function and store the value in ldrValue variable 
     buttonState = digitalRead(buttonPin); //read the digital state of the buttonPin with digitalRead() function and store the value in ldrState variable
     
          
      
      {
        {
         unsigned long currentMillis = millis();</p><p>    if(currentMillis - previousMillisMessage3 > intervalMessage3) {
          //update last LCD write
           if ((ldrState == HIGH) && (directionState == 0)) {
              previousMillisMessage3 = currentMillis;   
      }
     
        else if(currentMillis - previousMillisMessage3 > waitMessage3) {
             if ((ldrState == HIGH) && (directionState == 1)) {   
                lcd.clear();
                lcd.setCursor(0,0); //Start at character 0 on line 0
                lcd.print("Shame on you!");
                previousMillisMessage3 = currentMillis;
     
        }
         }
          }
           }
            }
     }</p>

    Here's Twist.h:

    <p>#ifndef Twist_h<br> #define Twist_h
     
     #include "Arduino.h"
     #include <Servo.h><servo.h>
     
     class Twist
     {
       const int servoPin = 9; // servo pin 
       Servo servo;              // the servo
       int directionState = 1; //direction state of 1 = closed, direction state of 0 = open
       int pos = 90;  // variable to store the servo position
       int increment;        // increment to move for each interval
       int  updateInterval;      // interval between updates
       unsigned long lastUpdate; // last update of position</servo.h></p><p>   
    unsigned long previousMillisAutoOpen = 0;        // will store last time LCD was updated
    unsigned long currentMillisAutoOpen;
    const unsigned long intervalAutoOpen = 24UL*60UL*60UL*100UL;   // Check whether blinds were opened every 24 
    const unsigned long waitAutoOpen = 2UL*60UL*60UL*100UL;  //2 hr wait for auto open
      
      const int buttonPin = 8; // pushbutton pin
      byte buttonPushCounter = 0;   // counter for the number of button 
      byte lastPushCount = 0;
      int buttonState = 0;
      int lastButtonState = 0;</p><p>  const int ldrPin = 6;  // light dependent resistor pin
     int ldrState = 0; // local variable to hold ldr states
      
     public: 
      
      Twist(int interval);
      void Attach(int pin);
      void Detach();
      void Update();
      void AutoOpen();
     };</p><p> #endif</p>

    Here's Twist.cpp:

    <p>#include "Arduino.h"<br> #include "Twist.h"
     #include <Servo.h><servo.h></servo.h></p><p>  byte buttonPushCounter = 0;   // counter for the number of button 
      byte lastPushCount = 0;
     int buttonState = 0;
     int lastButtonState = 0;</p><p> 
      Twist::Twist(int interval)
       {
      updateInterval = interval;
       }
     
      void Twist::Attach(int pin)
       {
         servo.attach(9);
       }
       void Twist::Detach()
       {
         servo.detach();
       }</p><p>   void Twist::Update() 
       {
         buttonState = digitalRead(buttonPin);
         if (buttonState != lastButtonState) {  // if the state has changed, increment the counter
         if (buttonState == HIGH) { // if the current state is HIGH then the button went from off to on:
          buttonPushCounter++;
       }
         if (buttonPushCounter == 5) buttonPushCounter = 0;         // rollover every fourth press
         if (lastPushCount != buttonPushCounter)              // only do output if the count has changed
       {
          Serial.println("on");
          Serial.print("number of button pushes: ");
          Serial.println(buttonPushCounter);
        } else 
        {
          // if the current state is LOW then the button went from on to off:
          Serial.println("off");
        }
     
      }
      // save the current state as the last state, for next time through the loop
      lastButtonState = buttonState;</p><p>   if((millis() - lastUpdate) > updateInterval)  // time to update
         {
           lastUpdate = millis();
           pos += increment;
           
      
      if (directionState == 0) {
        if (buttonPushCounter == 1) {
          directionState = 1;
          servo.attach(9);
          for (pos = 90; pos < 180; pos = pos + 1) { //blinds close
            servo.write(pos);</p><p>      }
      
        }
      } 
        if (buttonPushCounter == 2) {  //blinds stop
         
            servo.detach();     
        }
      
        else if (directionState == 1) {
        if (buttonPushCounter == 3) {
          directionState = 0;
          servo.attach(9);
          for (pos = 90; pos < 180; pos = pos - 1) { //blinds open
            servo.write(pos);</p><p>      }
      
        }
      } 
        if (buttonPushCounter == 4) { //blinds stop
      servo.detach();
       }
       }
        }
         </p><p>  void Twist::AutoOpen()
      { 
        unsigned long currentMillis1 = millis();
        if (currentMillisAutoOpen - previousMillisAutoOpen > intervalAutoOpen) {
          ldrState = digitalRead(ldrPin); 
          {
            if ((ldrState == HIGH) && (directionState == 1)) { 
          }
          previousMillisAutoOpen = currentMillisAutoOpen;
        }
        }</p><p>    else if (currentMillisAutoOpen - previousMillisAutoOpen  > waitAutoOpen) {
          //update last servo write
           pos += increment;
          ldrState = digitalRead(ldrPin); //read the digital value of ldrPin with digitalRead() function and store the vaue in ldrValue variable 
     {
      if ((ldrState == HIGH) && (directionState == 1))
      {
        directionState = 0;
          servo.attach(9);
          for (pos = 90; pos < 180; pos = pos - 1) { //blinds open
            servo.write(pos);
            servo.detach();
            previousMillisAutoOpen = currentMillisAutoOpen;
           
          }
         }
        }
       }
      }</p>

    Share

      Recommendations

      • Tiny Home Contest

        Tiny Home Contest
      • Creative Misuse Contest

        Creative Misuse Contest
      • Fix It! Contest

        Fix It! Contest

      Discussions

      Very nicely built. I have plans for something similar for a set of curtains. One thing you (or others) might consider if you ever do a revision is adding a temperature sensor. I have rooms where closing the blinds in the summer sun , and opening them for the winter sun, makes a huge difference to the usability of the room. Not so good for your plants obviously . Thanks for the write up.