Hackster is hosting Impact Spotlights: Industrial Automation. Watch the stream live on Thursday!Hackster is hosting Impact Spotlights: Industrial Automation. Stream on Thursday!
Ishan ThakurLuke Gutman
Published © GPL3+

Open Sesame! (Automatic Blinds)

A wireless way for blinds to open, based off both motion and the amount of light outside.

BeginnerFull instructions provided10 hours220
Open Sesame! (Automatic Blinds)

Things used in this project

Hardware components

Breadboard (generic)
Breadboard (generic)
×1
Test Accessory, AC Power Adaptor
Test Accessory, AC Power Adaptor
×1
DC motor (generic)
×1
Motor Driver Module, Single Axis
Motor Driver Module, Single Axis
×1
Circular Connector Cable Seal, Heat Shrinkable Sealing Boot
Circular Connector Cable Seal, Heat Shrinkable Sealing Boot
×1
Photon
Particle Photon
×2

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires

Story

Read more

Custom parts and enclosures

Motor/Blind coupling

Motor Stay

Schematics

Motor circuit diagram

Motor stay and coupling

Motor circuit

Button Circuit Diagram

Button circuit

Code

Motor Board

C/C++
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_IO_Particle.h>
#include "Particle.h"

int motionSensorValue = 0;
int lightSensorValue = 0;

int motionSensorPin = D2;
int lightSensorPin = A2;

int dir1pin = D0;
int dir2pin = D1;
int pwm1pin = D8;
int pwm2pin = D7;

bool blindState = false; // false = closed, true = open

unsigned long motionStartTime = 0;
unsigned long lightStartTime = 0; 

int motionCounter = 0;

unsigned long lastUpdateTime = 0;
const int updateInterval = 4000; // Update interval in milliseconds

#include <application.h>
#include "Adafruit_IO_Client.h"

 
#define AIO_KEY "aio_zhXk22R5lngBtRTCDQ21Ivoe8zPC"          // Adafruit IO AIO Key
TCPClient client;                                           // TCP Client used by Adafruit IO library
 
// Create the AIO client object
Adafruit_IO_Client  AIOClient = Adafruit_IO_Client(client, AIO_KEY);
 
// Create a feed object to send and get data
Adafruit_IO_Feed    motionSensorFeed = AIOClient.getFeed("motion-sensor");
Adafruit_IO_Feed    lightSensorFeed = AIOClient.getFeed("light-sensor");
    
void setup() {
    Serial.begin(9600);
    
    AIOClient.begin();

    pinMode(motionSensorPin, INPUT);
    pinMode(lightSensorPin, INPUT);
    pinMode(dir1pin, OUTPUT);
    pinMode(dir2pin, OUTPUT);
    pinMode(pwm1pin, OUTPUT);
    pinMode(pwm2pin, OUTPUT);
    
    Particle.function("controlBlinds", controlBlind);
    Particle.subscribe("buttonController", controlButton, MY_DEVICES);
    
    Particle.publish("blindClose", PRIVATE);
}

void loop() {
    motionSensorValue = digitalRead(motionSensorPin);
    lightSensorValue = analogRead(lightSensorPin);
    
        // Check if it's time to update the feeds
    if ((millis() - lastUpdateTime) >= updateInterval) {
        // Send sensor values to Adafruit IO feeds
        motionSensorFeed.send(String(motionSensorValue));
        lightSensorFeed.send(String(lightSensorValue));
        
        Serial.println("updating to adafruit");

        // Update the last update time
        lastUpdateTime = millis();
    }
    
    //Serial.println(motionSensorValue);

    // Check if motion has been detected for 2 seconds
    if (motionSensorValue == 1) {
        motionCounter++;
        if (motionCounter == 15) {
            Serial.println("motion detected for 2 seconds, togglilng blinds");
            toggleBlinds(); // Toggle the state of the blinds
            motionCounter = 0;
        }
    }
    
    if (motionCounter > 0) {
        motionStartTime = millis();
        if ((millis() - motionStartTime) >= 5000) {
            motionCounter = 0;
            motionStartTime = 0;
        }
    }

    // Check if light value has gone over 1000
    if (lightSensorValue > 2500) {
        if (lightStartTime == 0) {
            lightStartTime = millis(); // Record the start time of light being above the threshold
        }

        // Check if light has been above the threshold for 2 seconds
        if ((millis() - lightStartTime) >= 2000) {
            Serial.println("darkness detected for 2 seconds, togglilng blinds");
            closeBlinds();
            lightStartTime = 0;
        }
    } else {
        lightStartTime = 0; // Reset the light start time if light is below the threshold
    }
    
    
    delay(50);
}

void openBlinds() {
    Serial.println("opening blinds");
    if (!blindState) { // Check if blinds are not already open
        // Add code to open the blinds using the motor
        digitalWrite(dir1pin, HIGH);
        digitalWrite(dir2pin, HIGH);
        analogWrite(pwm1pin, 255);
        analogWrite(pwm2pin, 0);
        delay(6000); // Run the motor for 10 seconds
        stopMotor(); // Stop the motor
        blindState = true;
        Particle.publish("blindOpen", PRIVATE);
    }
}

void toggleBlinds() {
    // Toggle the state of the blinds
    if (blindState) {
        closeBlinds();
    } else {
        openBlinds();
    }
}

void closeBlinds() {
    Serial.println("closing blinds");
    if (blindState) { // Check if blinds are not already closed
        // Add code to close the blinds using the motor
        digitalWrite(dir1pin, HIGH);
        digitalWrite(dir2pin, HIGH);
        analogWrite(pwm1pin, 0);
        analogWrite(pwm2pin, 255);
        delay(6000); // Run the motor for 10 seconds
        stopMotor(); // Stop the motor
        blindState = false;
        Particle.publish("blindClose", PRIVATE);
    }
}

void stopMotor() {
    // Add code to stop the motor
    digitalWrite(dir1pin, LOW);
    digitalWrite(dir2pin, LOW);
    analogWrite(pwm1pin, 0);
    analogWrite(pwm2pin, 0);
}



int controlBlind(String command) {
    if (command == "open") {
        openBlinds();
        return 1;
    } else if (command == "close") {
        closeBlinds();
        return 0;
    } else {
        return -1;
    }
}

void controlButton(const char *event, const char *data) {
    toggleBlinds();
}

Inter-device communication

C/C++
// Device 1 (Sender) Code with Ultrasonic Sensor

const int buttonPin = D9;

int analogvalue = 1;


void setup() {
  pinMode(buttonPin, INPUT);
  Particle.variable("analogvalue", &analogvalue, INT);
  Particle.subscribe("blindClose", blindClose, MY_DEVICES);
  Particle.subscribe("blindOpen", blindOpen, MY_DEVICES);
  Serial.begin(9600);
  
  RGB.control(true);
  RGB.brightness(255);
}

void loop() {

  // Read the distance from the ultrasonic sensor
  int analogvalue = digitalRead(buttonPin);
  //Particle.variable("analogvalue", &analogvalue, INT);
  
  if (analogvalue == 0) {
      Particle.publish("buttonController", PRIVATE);
      delay(1000);
  }
  
  Serial.println(analogvalue);

  delay(250);
}

void blindOpen(const char *event, const char *data) {
    RGB.color(0, 255, 0);
}
void blindClose(const char *event, const char *data) {
    RGB.color(255, 0, 0);
}

Credits

Ishan Thakur
1 project • 0 followers
Contact
Luke Gutman
1 project • 0 followers
Contact

Comments

Please log in or sign up to comment.