Smart Window
overview
software
home
hardware
team
The code for the SmartWindow was developed in Arduino. A stable version of the project's code is available below.

/************************************************************************************************************************
 * SmartWindow
 *
 *     When power is OFF, the window will move up and rotate to the default position.
 *     When power is ON, the window will move down and operate according to the mode switch.
 *     If mode is MANUAL, the window will rotate according to the position of the potentiometer.
 *       The window will rotate in the opposite direction with which the potentiometer is turned.
 *       The further the potentiometer is turned in either direction, the faster the rotation.
 *       This mode is used to define the reference light setting for the automatic mode.
 *     IF mode is AUTOMATIC, the window will rotate based on the reading of the light sensor with
 *       respect to the reference setting defined in manual mode. If there is less light in the room
 *       than the setting, the window will rotate such that more light is let in until the set value
 *       is reached. Likewise, more light in the room compared to the reference will cause the window
 *       to rotate such that less light is let in until the setting is reached.
 *     When motion sensor is ON during automatic mode, the window will operate in normal automatic
 *       mode as long as motion of a passive infrared-emitting body is present within a 20 ft radius
 *       of the sensor. If no motion is detected for more than 5 seconds, the window will rotate
 *       to allow no light into the room. Upon sensing motion, the window will rotate back to its
 *       former angular position and resume normal automatic operation.
 *
 * Ben Dokko, Kevin Huynh, Mitchell Olson, Simon Xu
 * UC Berkeley, 2009. ME 102 Project.
 *
 * last updated 12/01/09
 *
 ************************************************************************************************************************/

// analog inputs
int lightPin_in = 5;   // voltage from inside photoresistor
int lightPin_out = 4;  // voltage from outside photoresistor
int potPin = 0;        // potentiometer

// digital inputs
int powerPin = 2;      // power switch
int autoPin = 3;       // mode switch
int msensorPin = 4;    // motion sensor switch
int msignalPin = 5;    // motion sensor signal
int encPin_A = 6;      // encoder pin A
int encPin_B = 7;      // encoder pin B

// digital outputs
int pwmPin_vert = 9;   // to PWM pin for rotation
int dirPin_vert = 10;  // to Direction pin for rotation
int pwmPin_theta = 11; // to PWM pin for vertical motion
int dirPin_theta = 12; // to Direction pin for vertical motion

// variables
int power;             // power switch (HIGH = power on & window down, LOW = power off & window up)
int autom;             // mode switch (HIGH = automatic, LOW = manual)
int msensor;           // motion sensor switch (HIGH = on, LOW = off)
int msignal;           // signal from motion sensor (HIGH = motion, LOW = no motion)
int mflag = HIGH;      // flag for motion detection (HIGH = motion, LOW = no motion & start timer)
int tstart;            // motion sensor timer start when msignal first reads LOW
int tstop;             // motion sensor timer check for all subsequent msignal readings of LOW
int lastcnt;           // cnt where window was last before motion sensor took over
int potval;            // voltage from potentiometer (0-1023 mapped to 255 <- 0 -> 255)
int lightin;           // voltage from inside photoresistor (0-1023 mapped to 100-0)
int lightout;          // voltage from outside photoresistor (0-1023 mapped to 100-0)
int A;                 // previous signal from encoder pin A
int B;                 // previous signal from encoder pin B
int Anew;              // new signal from encoder pin A
int Bnew;              // new signal from encoder pin B
int cnt = 100;         // encoder count
int lower = 15;        // encoder count lower bound
int upper = 190;       // encoder count upper bound
int dir = LOW;         // direction of DC motors and encoder (HIGH = CCW or up, LOW = CW or down)
int mag_theta = 0;     // drive magnitude of theta motor (0-100% -> 0-255)
int mag_vert = 150;    // drive magnitude of vert motor (0-100% -> 0-255)
int dwellup = 10000;   // time to bring window up (10 seconds)
int dwelldown = 7750;  // time to bring window down (7.75 seconds)
int level = HIGH;      // vertical position of window (HIGH = up, LOW = down)
int setting;           // voltage setting for automatic mode defined in manual mode (0-1023 mapped to 100-0)
int tol = 1;           // voltage tolerance for tracking the reference light setting

//----------------------------------------------------------------------------------------------------//

void setup() {
  pinMode(pwmPin_theta,OUTPUT);
  pinMode(dirPin_theta,OUTPUT);
  pinMode(pwmPin_vert,OUTPUT);
  pinMode(dirPin_vert,OUTPUT);
  Serial.begin(9600);
  power = digitalRead(powerPin); // check power switch
  A = digitalRead(encPin_A); // initialize encoder pin A
  B = digitalRead(encPin_B); // initialize encoder pin B
}

void loop() {
  //----------------------------------------------------------------------------------------------------// power OFF //
  while (power == LOW) {
    // move window up
    if (level == LOW) {
      digitalWrite(dirPin_vert,HIGH);
      analogWrite(pwmPin_vert,mag_vert);
      delay(dwellup);
      analogWrite(pwmPin_vert,0);
      level = HIGH;
    }
    // return to default angle
    if (cnt > 100) {
      dir = LOW;
      mag_theta = 200;
    }
    else if (cnt < 100) {
      dir = HIGH;
      mag_theta = 200;
    }
    else {
      mag_theta = 0;
    }
    digitalWrite(dirPin_theta,dir);
    analogWrite(pwmPin_theta,mag_theta);
    //-------------------------------------------------- encoder start
    Anew = digitalRead(encPin_A);
    Bnew = digitalRead(encPin_B);
    if (Anew != A || Bnew != B) {
      if (dir == LOW && cnt > lower) {
        cnt = cnt - 1;
        A = Anew;
        B = Bnew;
      }
      else if (dir == HIGH && cnt < upper) {
        cnt = cnt + 1;
        A = Anew;
        B = Bnew;
      }
      else {
        A = Anew;
        B = Bnew;
      }
      // Serial.println(cnt);
    }
    //-------------------------------------------------- encoder end
    power = digitalRead(powerPin); // check power switch
    // stop moving if switch changes
    if (power == HIGH) {
      analogWrite(pwmPin_theta,0);
    }
  }
  //----------------------------------------------------------------------------------------------------// power ON //
  while (power == HIGH) {
    // move window down
    if (level == HIGH) {
      digitalWrite(dirPin_vert,LOW);
      analogWrite(pwmPin_vert,mag_vert);
      delay(dwelldown);
      analogWrite(pwmPin_vert,0);
      level = LOW;
    }
    autom = digitalRead(autoPin); // check mode switch
    //---------------------------------------------------------------------------------------------------- manual mode
    while (autom == LOW && power == HIGH) {
      // velocity control of polarized window angle
      potval = analogRead(potPin); // read potentiometer
      if (potval >= 0 && potval <= 500 && cnt > lower + 1){
        dir = LOW;
        mag_theta = map(potval,0,500,255,0);
      }
      else if (potval >= 523 && potval <= 1023 && cnt < upper - 1){
        dir = HIGH;
        mag_theta = map(potval,523,1023,0,255);
      }
      else { // zero drive region: 500-523
        mag_theta = 0;
      }
      digitalWrite(dirPin_theta,dir);
      analogWrite(pwmPin_theta,mag_theta);
      //-------------------------------------------------- encoder start
      Anew = digitalRead(encPin_A);
      Bnew = digitalRead(encPin_B);
      if (Anew != A || Bnew != B) {
        if (dir == LOW && cnt > lower) {
          cnt = cnt - 1;
          A = Anew;
          B = Bnew;
        }
        else if (dir == HIGH && cnt < upper) {
          cnt = cnt + 1;
          A = Anew;
          B = Bnew;
        }
        else {
          A = Anew;
          B = Bnew;
        }
        // Serial.println(cnt);
      }
      //-------------------------------------------------- encoder end
      // reference light setting
      lightin = analogRead(lightPin_in);
      setting = map(lightin,0,1023,100,0);
      // check power and mode switches
      autom = digitalRead(autoPin);
      power = digitalRead(powerPin);
      // stop moving if switches change
      if (autom == HIGH || power == LOW) {
        analogWrite(pwmPin_theta,0);
      }
    }
    //---------------------------------------------------------------------------------------------------- automatic mode
    while (autom == HIGH && power == HIGH) {
      //---------------------------------------------------------------------- motion sensor start
      msensor = digitalRead(msensorPin); // check motion sensor switch
      if (msensor == HIGH) {
        msignal = digitalRead(msignalPin); // read motion signal
        if (msignal == HIGH) { // motion detected
          mflag == HIGH;
        }
        else if (msignal == LOW && mflag == HIGH) { // no motion, start timer
          tstart = millis();
          mflag = LOW;
        }
        else if (msignal == LOW && mflag == LOW) { // still no motion, check timer
          tstop = millis();
          lastcnt = cnt;
          // no motion detected for more than 5 seconds, rotate to 0% light in
          while (msignal == LOW && msensor == HIGH && autom == HIGH && power == HIGH && tstop - tstart > 5000) {
            if (cnt < upper - 1) {
              dir = HIGH;
              mag_theta = 150;
            }
            else {
              mag_theta = 0;
            }
            digitalWrite(dirPin_theta,dir);
            analogWrite(pwmPin_theta,mag_theta);
            //-------------------------------------------------- encoder start
            Anew = digitalRead(encPin_A);
            Bnew = digitalRead(encPin_B);
            if (Anew != A || Bnew != B) {
              if (dir == LOW && cnt > lower) {
                cnt = cnt - 1;
                A = Anew;
                B = Bnew;
              }
              else if (dir == HIGH && cnt < upper) {
                cnt = cnt + 1;
                A = Anew;
                B = Bnew;
              }
              else {
                A = Anew;
                B = Bnew;
              }
              // Serial.println(cnt);
            }
            //-------------------------------------------------- encoder end
            // check motion signal and switches
            msignal = digitalRead(msignalPin);
            msensor = digitalRead(msensorPin);
            autom = digitalRead(autoPin);
            power = digitalRead(powerPin);
            if (msignal == HIGH || msensor == LOW || autom == LOW || power == LOW) {
              // rotate back to former angular position
              while (mflag != HIGH) {
                if (cnt > lastcnt) {
                  dir = LOW;
                  mag_theta = 200;
                }
                else {
                  mag_theta = 0;
                  mflag = HIGH;
                }
                digitalWrite(dirPin_theta,dir);
                analogWrite(pwmPin_theta,mag_theta);
                //-------------------------------------------------- encoder start
                Anew = digitalRead(encPin_A);
                Bnew = digitalRead(encPin_B);
                if (Anew != A || Bnew != B) {
                  if (dir == LOW && cnt > lower) {
                    cnt = cnt - 1;
                    A = Anew;
                    B = Bnew;
                  }
                  else if (dir == HIGH && cnt < upper) {
                    cnt = cnt + 1;
                    A = Anew;
                    B = Bnew;
                  }
                  else {
                    A = Anew;
                    B = Bnew;
                  }
                  // Serial.println(cnt);
                }
                //-------------------------------------------------- encoder end
              }
            }
          }

        }
      }
      else if (msensor == LOW) {
        mflag = HIGH;
      }
      //---------------------------------------------------------------------- motion sensor end
      // check light sensor
      lightin = analogRead(lightPin_in);
      lightin = map(lightin,0,1023,100,0);
      Serial.println(lightin);
      // track reference light setting
      if (lightin < setting - tol && cnt > lower + 1) {
        dir = LOW;
        mag_theta = 70;
      }
      else if (lightin > setting + tol && cnt < upper - 1) {
        dir = HIGH;
        mag_theta = 70;
      }
      else {
        mag_theta = 0;
      }
      digitalWrite(dirPin_theta,dir);
      analogWrite(pwmPin_theta,mag_theta);
      //-------------------------------------------------- encoder start
      Anew = digitalRead(encPin_A);
      Bnew = digitalRead(encPin_B);
      if (Anew != A || Bnew != B) {
        if (dir == LOW && cnt > lower) {
          cnt = cnt - 1;
          A = Anew;
          B = Bnew;
        }
        else if (dir == HIGH && cnt < upper) {
          cnt = cnt + 1;
          A = Anew;
          B = Bnew;
        }
        else {
          A = Anew;
          B = Bnew;
        }
        // Serial.println(cnt);
      }
      //-------------------------------------------------- encoder end
      // check power and mode switches
      autom = digitalRead(autoPin);
      power = digitalRead(powerPin);
      // stop moving if switches change
      if (autom == LOW || power == LOW) {
        analogWrite(pwmPin_theta,0);
      }
    }
  }
}
//----------------------------------------------------------------------------------------------------//



Home    |    Overview    |    Hardware    |    Software    |    Team

SmartWindow is a rotating polarized window that allows in an optimal amount of light based on light detection and user input. Constructed with polycarbonate window panes and coded in Arduino, SmartWindow aims to serve as a foundation for an energy-saving, sustainable window concept. The project was conceived within the ME102 senior design course at the University of California, Berkeley during Fall of 2009.
Ben Dokko, Kevin Huynh, Mitch Olson, & Simon Xu

Copyright 2009
All Rights Reserved.