Skip to content

Final Project

The concept for my final project is a motion activated light that slowly opens and closes.

../../images/finalproject/mech_sketch3d.jpg

../../images/finalproject/mech_sketch.jpg

Mechanical Mechanisms

Auxetic Material

Example Material

Sensors and software

../../images/finalproject/sensor_proto.jpg

Basic functionality of the circuit:

  • When motion is detected the LED turns on slowly

  • Brightness of the LED is controled through PWM

  • The color of the LED is determined from the temperature reading on TRD termperature sensor

Code for the prototype sensors

    #include <Arduino.h>
    #include <DHTesp.h>

    // ----- Pins (adjust if needed) -----
    static const int PIN_PIR = 4;     
    static const int PIN_DHT = 15;    

    // Common-cathode RGB LED pins (each via resistor)
    static const int PIN_RED   = 12;
    static const int PIN_GREEN = 13;
    static const int PIN_BLUE  = 14;

    // ----- PWM settings -----
    static const int PWM_FREQ = 5000;
    static const int PWM_BITS = 8; // 0..255

    // ----- Motion/LED behavior -----
    static const uint32_t HOLD_MS       = 2000;
    static const uint8_t  TARGET_BRIGHT = 255;
    static const uint8_t  FADE_STEP     = 3;
    static const uint16_t STEP_DELAY_MS = 10;

    // ----- DHT -----
    DHTesp dht;
    uint32_t lastDhtReadMs = 0;
    static const uint32_t DHT_PERIOD_MS = 2000;

    // ----- Temperature -> color tuning -----
    static const float COLD_C = 18.0;
    static const float HOT_C  = 28.0;

    // State
    uint32_t lastMotionMs = 0;
    uint8_t  currentBright = 0;
    float lastTempC = NAN;

    // Clamp helpers
    static inline uint8_t clamp8(int v) {
    if (v < 0) return 0;
    if (v > 255) return 255;
    return (uint8_t)v;
    }

    static inline float clampf(float v, float lo, float hi) {
    if (v < lo) return lo;
    if (v > hi) return hi;
    return v;
    }

    // COMMON CATHODE: no inversion needed
    void writeLed(int pin, uint8_t brightness) {
    ledcWrite(pin, brightness);
    }

    // Apply global brightness scaling
    void setRgbScaled(uint8_t r, uint8_t g, uint8_t b, uint8_t globalBright) {
    uint8_t rs = (uint8_t)((r * (uint16_t)globalBright) / 255);
    uint8_t gs = (uint8_t)((g * (uint16_t)globalBright) / 255);
    uint8_t bs = (uint8_t)((b * (uint16_t)globalBright) / 255);

    writeLed(PIN_RED,   rs);
    writeLed(PIN_GREEN, gs);
    writeLed(PIN_BLUE,  bs);
    }

    // Temperature -> RGB gradient
    void colorFromTemp(float tC, uint8_t &r, uint8_t &g, uint8_t &b) {
    if (isnan(tC)) {
        r = 180; g = 0; b = 180;
        return;
    }

    float t = clampf(tC, COLD_C, HOT_C);
    float x = (t - COLD_C) / (HOT_C - COLD_C);

    if (x <= 0.5f) {
        float u = x / 0.5f;
        r = 0;
        g = clamp8((int)(255.0f * u));
        b = clamp8((int)(255.0f * (1.0f - u)));
    } else {
        float u = (x - 0.5f) / 0.5f;
        r = clamp8((int)(255.0f * u));
        g = clamp8((int)(255.0f * (1.0f - u)));
        b = 0;
    }
    }

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

    pinMode(PIN_PIR, INPUT_PULLDOWN);

    ledcAttach(PIN_RED,   PWM_FREQ, PWM_BITS);
    ledcAttach(PIN_GREEN, PWM_FREQ, PWM_BITS);
    ledcAttach(PIN_BLUE,  PWM_FREQ, PWM_BITS);

    setRgbScaled(0,0,0,0);

    dht.setup(PIN_DHT, DHTesp::DHT11);

    Serial.println("Common Cathode version running.");
    }

    void loop() {
    uint32_t now = millis();

    // PIR
    bool motionNow = (digitalRead(PIN_PIR) == HIGH);
    if (motionNow) lastMotionMs = now;

    bool motionActive = (now - lastMotionMs) < HOLD_MS;
    uint8_t targetBright = motionActive ? TARGET_BRIGHT : 0;

    // DHT read
    if (now - lastDhtReadMs >= DHT_PERIOD_MS) {
        lastDhtReadMs = now;

        TempAndHumidity th = dht.getTempAndHumidity();
        if (!isnan(th.temperature)) {
        lastTempC = th.temperature;
        Serial.print("Temp: ");
        Serial.print(lastTempC, 1);
        Serial.print(" C  Humidity: ");
        Serial.println(th.humidity, 0);
        }
    }

    // Determine base color
    uint8_t baseR, baseG, baseB;
    colorFromTemp(lastTempC, baseR, baseG, baseB);

    // Smooth fade
    if (currentBright < targetBright) {
        currentBright = (uint8_t)min((int)targetBright, (int)currentBright + (int)FADE_STEP);
    } 
    else if (currentBright > targetBright) {
        currentBright = (uint8_t)max((int)targetBright, (int)currentBright - (int)FADE_STEP);
    }

    setRgbScaled(baseR, baseG, baseB, currentBright);

    delay(STEP_DELAY_MS);
    }