Frederik Bøttger-Roth frboe17
Marcus Lomstein marcj18

Det midsommer, du lige vågnet op, og det er 30 grader i dit værelse. Du kæmper for at stå op og åbne dit vindue men sommerens hede har gjort din krop træg og udmatted. Du ligger nu og ønsker for intet andet end en automatisk løsning til at åbne det vindue der kan give dig den kølige morgen brise du sådan længes efter.

Denne løsning er nu kommet. The Lazy-Persons Ventilation System er en mekanisk arm der åbner og lukker dit vindue afhængig af din temperatur i det rum den er installeret i eller vejret udenfor. Løsninging består af en række aktuatorer og sensorer:

Sensorer:

  • DHT11 Temperature- and humidity Sensor
    • Brugt til at tage temperaturen i rummet
  • HC-SR04 Ultrasonic Sensor
    • Brugt til at finde distancen mellem vinduet og robotarmen.
  • Water Level Detection Sensor
    • Brugt til at registrere regn i det tilfælde det regner når vinduet er åbent
  • LDR
    • Brugt til at få lysstyrken i rummet, for at registrer om det er dag eller nat

Aktuatorer

  • 28BYJ-48 Stepper Motor
    • Brugt til at bevæge armen frem og tilbage
  • LCD1602A LCD Display
    • Brugt til at vise temperaturen, om det er dag eller nat, og status på systemet.
  • LED’s
    • Brugt til at vise status på systemet

Samlet materiale

Hardware Materiale
2x Arduino Uno R3
4x LED
1x LCD1602A LCD Display
1x Potentiometer
1x LDR
4x 330 Ohm Resistor
1x 5000 Ohm Resistor
1x 1000 Ohm Resistor
1x 28BYj-48 Stepper Motor
1x ULN2003A Stepper Motor Driver
1x DHT11 Temperature- and humidity Sensor
1x Water Level Detection Sensor
1x HC-SR04 Ultrasonic Sensor
1x S8050 NPN Transistor
1x Breadboard Power Supply Module
2x Buttons
En masse ledninger i varierende længde, både Han-til-Han og Han-til-Hun

Konstruktion Materiale
Lego eller lignede brikker til opbygning
Tandhjul til gearing
Tape til at lave en belægning på overflader så man nemt kan fjerne konstruktionen igen
Superlim.

Video gennemgang af systemet

Systemet er tested med at vinduet åbner når temperaturen er over 29 og vinduet lukker når den er under 27. Dette er udelukkende gjort for at teste det.

Opbygning af hardware

Herunder vises den overordnet diagram af hele systemmets opbygning, inkluderet alle de sensorer og aktuatore der indgår i systemet. Der er to Arduinos der snakker med hinanden, i et master/slave forhold. Masteren håndtere prioriteringen mellem states afhængig af de læsninger sensorene modtager og eksekvere statesne i form af at åbne og lukke vinduet. Derudover sender master-arduinoen informationer om state-skift, samt temperatur-skift til slave-arduinoen som viser hvilket state den er i i form af LED’s og på en LCD skærm.

Serielt Interface

Mængden af sensore og aktuatore nødvændigt til at lave dette system kræver flere pins end en enkelt Arduino kan forsyne. Vi har derfor brugt to Arduinos og forbundet dem via en I2C forbindelse. Dette gøres ved at forbinde Arduinosne i deres input pin A4 og A4 samt ground. Dette gør sådan at man kan sætte et master/slave-relationship op med vores Arduinos, hvor en Arduino sender beskeder til den anden. Ved brug af et library kaldet Wire, kan man så sætte forbindelsen op i koden, hvor Master Arduinoen kan sende data i form af bytes til Slave Arduinoen.

Temperatur, Vand og Ultrasonisk Sensor

De primærer sensore der anvendes til dette system er temperatur, vand, og ultrasonisk sensor. Deres opsætning i systemet er vist herunder i rækkefølgen ultrasonisk sensor, temperatur sensor, og vand niveau sensor, set fra venstre side.

Den ultrasoniske sensor bliver brugt til at finde distancen fra sensoren til vinduet. Hvis distancen er større eller mindre en bestemt distance, så stopper stepper motoren med at køre. Essentielt fungere den som en limitswitch. Sensoren er forbundet til arduinoen via 4 ledninger, VCC, GND, TRIG og ECHO. VCC og GND er henholdsvis power og ground forbindelser og TRIG og ECHO skal forbindes til to pins. I vores tilfælde brugte vi pin 2 og 3. Selve funktionaliteten af sensoren håndteres af et medfølgt library.

Temperatur sensoren bliver brugt til at måle temperaturen i rummet. Hvis temperaturen stiger over eller under en bestemt temperatur, starter stepper motoren, og enten åbner eller lukker vinduet afhængig af temperaturen. Denne sensor er forbundet via 3 ledninger, igen to pins til henholdsvis power og ground, samt en til en pin i arduinoen. Der er også et library til denne sensor.

Den sidste sensor er et vand niveau sensor, der anvendes til det scenarie at det skulle begynde at regne imens vinduet er åbent. Sensoren er forbundet med 3 ledninger, to til power og ground, samt en enkelt input pin i A0. Sensoren læses ved hjælp af en simpel analog read.

Stepper motor

Vi har valgt at bruge en stepper motor til at håndtere bevægelsen af armen der åbner og lukker vinduet, da det var den motor der var kraftigst af de muligheder vi havde. Stepper motoren af forbundet til systemet således vist herunder

Stepper motoren kræver en ekstern power supply til at køre. Denne kan ses til venstre på diagrammet. De fire ledninger der går ind i Arduinoen er forbundet til pin 9, 10, 11, 12. Selve stepper motoren håndteres af et library som giver muligheden for at sende til stepper motoren hvor mange steps den skal køre.

Da denne del af systemet både indvolvere en ekstern power supply og en arduino, har vi lavet en status diode der indikere om både power supply og Arduino er tændt. Dette er gjort via en NPN transistor. Collecter delen af transistoren er forbundet til den eksterne powersupply som også har en LED sat på. Base delen er forbunder til arduinoen power pin. Dette medføre så at når begge dele er tændt, trigger arduinoens power pin base i transistoren, hvilket medføre at strøm løber igennem collecteren og videre ud af emitteren på transistoren, som således tænder LED’en.

LCD Display

Herunder ses hvordan LCD displayed er forbundet til Slave-Arduinoen

Potentiometeret justere LCD displayets kontrast, så man nemt selv kan finjustere. LCD displayet viser temperaturen i rummet, om det er dag eller nat, og hvilken state systemet er i.

Opbygning af program

Systemet har tre forskellige states den kan være i

Åben vindue: Vinduet er åbent, og afventer at temperaturen falder til det bestemte niveau
Lukket vindue: Vinduet er lukket og afventer at temperaturen stiger til det bestemte niveau
Regn: Uafhængigt af temperatur, lukkes vinduet og venter til at vand sensoren ikke længer registrere regn.

Herunder kan ses det samlede flow-diagram over systemet

Arduino 1, aka Master arduino

Arduino 2, aka Slave-arduino

Programmering og funktioner

Master arduino

Master arduinoens setup ser således ud

#include <Wire.h>
#include <Stepper.h>
#include <dht_nonblocking.h>
#include "SR04.h"
//Ultrasonic sensor
#define TRIGGER_PIN 4
#define ECHO_PIN 3
//Temperature and humidity sensor
#define DHT_SENSOR_TYPE DHT_TYPE_11
#define DHT_SENSOR_PIN 2
//Buttons for manual testing
#define CLOSE_BUTTON 6
#define OPEN_BUTTON 5
//water sensor
#define WATER_SENSOR 0

//Stepper motor settings
const int stepsPerRevolution = 2000; 
const int rolePerMinute = 15;        
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
//Temp sensor initialization
DHT_nonblocking dht_sensor(DHT_SENSOR_PIN, DHT_SENSOR_TYPE);
//Ultrasonic sensor init
SR04 sr04 = SR04(ECHO_PIN, TRIGGER_PIN);

//Distance to window in CM
long distance;
//Value from water sensor
int waterAmount;
//Sets manual mode for testing purposes
bool manual = false;
//Open or close state
bool shouldOpen = false;
//Rain state
bool isRain = false;
//Distance limit toggles when reached
bool reachedClosedEndpoint = false;
bool reachedOpenEndpoint = false;

void setup()
{
  pinMode(OPEN_BUTTON, INPUT_PULLUP);
  pinMode(CLOSE_BUTTON, INPUT_PULLUP);
  myStepper.setSpeed(rolePerMinute);
  //Gets the initial distance to window
  distance = sr04.Distance();
  //Initializes the wire library to enable I2C communication between Master and Slave arduino
  Wire.begin();
  Serial.begin(9600);
}

Master arduinoens loop funktion ser således ud.

void loop()
{
  float temperature = 23.0;
  float humidity;

  /* Measure temperature and humidity.  If the functions returns
     true, then a measurement is available. */
  if (getSensorInformation(&temperature, &humidity, &distance, &waterAmount) == true)
  {
    //Checks the water amount and if above threshold, enable the rain state and sends a signal to slave arduino
    if (waterAmount > 10)
    {
      isRain = true;
      shouldOpen = false;
      Wire.beginTransmission(1);
      Wire.write(2);
      Wire.endTransmission();
    }
    else
    {
      isRain = false;
      //If temperature is above threshold, sets close state, and send signal to slave arduino
      if (temperature > 24)
      {
        shouldOpen = true;
        Wire.beginTransmission(1);
        Wire.write(1);
        Wire.endTransmission();
      }
      //If temperature is below threshold, sets open state, and send signal to slave arduino
      else if (temperature < 24)
      {
        shouldOpen = false;
        Wire.beginTransmission(1);
        Wire.write(0);
        Wire.endTransmission();
      }
    }
    //sends the temperature to the slave arduino
    int castedTemp = (int)temperature;
    Wire.beginTransmission(1);
    Wire.write(castedTemp);
    Wire.endTransmission();
  }
  moveStepper(distance, waterAmount, temperature);
}

Det første der tjekkes er om funktionen getSensorInformation() er true. Dette er fordi getSensorInformation kun bliver kaldt hver sekund for ikke at overloade arduinoen med instruktioner, da det kan påvirke steppermoterens hastighed. GetSensorInformation(), som ses nedenunder, checker ud fra millis() om der er gået et sekund. Hvis der er, bliver alle sensore læst og returneret i form at “Out Parameters”. Dette er gjort så det er nemt at returnere flere værdier i samme funktion.

tatic bool getSensorInformation(float *temperature, float *humidity, long *distance, int *waterAmount)
{
  static unsigned long timestamp = millis();

  /* Measure once every four seconds. */
  if (millis() - timestamp > 1000ul)
  {
    if (dht_sensor.measure(temperature, humidity) == true)
    {
      timestamp = millis();
      //Gets distance in cm to the window
      *distance = sr04.Distance();
      //Gets water level, to register rain
      *waterAmount = analogRead(WATER_SENSOR);
      return (true);
    }
  }

  return (false);
}

Disse værdier bliver således tjekket om de nærmer sig de grænser der er sat. Hvis de gør, ændre staten sig, og systemet reagere i følge med hvilken state den er i. Når de states opdatere sendes de via I2C til Slave Arduinoen som så opdatere dens state visualisering. Temperaturen sendes også til Slave Arduinoen hver gang getSensorInformation() bliver kaldt

Til sidst bliver moveStepper() funktionen kaldt som rykker på robot armen, afhængig af hvilken state systemet er i. Denne funktion tager distance som paramter. Distance er distancen mellem den ultrasoniske senser og vinduet. Distancen er nødvændig for at sørge for motoren stopper med at køre når vinduet enten er lukket eller åbent.

void moveStepper(long distance, int waterAmount, float temperature)
{
  if (isRain)
  {
    closeWindow(distance);
  }
  else
  {
    if (!shouldOpen && !manual)
    {
      closeWindow(distance);
    }
    else if (shouldOpen && !manual)
    {
      openWindow(distance);
    }

    if (digitalRead(CLOSE_BUTTON) == LOW && manual)
    {

      openWindow(distance);
    }
    if (digitalRead(OPEN_BUTTON) == LOW && manual)
    {
      closeWindow(distance);
    }
  }
}

void closeWindow(long distance)
{
  if (distance >= 14L && !reachedClosedEndpoint)
  {
    reachedClosedEndpoint = true;
  }
  if (!reachedClosedEndpoint)
  {
    myStepper.step(-1);
    reachedOpenEndpoint = false;
  }
}

void openWindow(long distance)
{
  if (distance < 4L && !reachedOpenEndpoint)
  {
    reachedOpenEndpoint = true;
  }

  if (!reachedOpenEndpoint)
  {
    myStepper.step(1);
    reachedClosedEndpoint = false;
  }
}

Her kan man se hvornår motoren starter eller stopper. Hvis systemet enten er i “closed” state eller “rain” state, så kaldes closeWindow() funktionen. I denne funktion checkes det om distancen er under et bestemt threshold og at den ikke allerede har registreret det i forvejen. Grunden til at dette checkes er at den ultrasoniske sensor er tilbøjelig til at være upræcis. Så for at sikre sig at motoren ikke bevæger sig unødigt, sættes der en boolean til så snart den når til grænsen en enkelt gang.

Hvis checksne går igennem bevæger stepper motoren sig et step hver loop iteration, indtil grænsen er nået.

Slave Arduino

Setup for slave arduino kan ses herunder

#include <Wire.h>
#include <LiquidCrystal.h>
//State LED pins
#define WINDOW_CLOSED_LED 2
#define WINDOW_OPEN_LED 4
#define RAIN_LED 3
//LDR pin
#define LDR A2
//Signal message
byte I2C_Message;
//LCD setup
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
bool isDay;
void setup()
{
  //Starts LCD
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Starting up...");
  pinMode(WINDOW_CLOSED_LED, OUTPUT);
  pinMode(WINDOW_OPEN_LED, OUTPUT);
  pinMode(RAIN_LED, OUTPUT);
  pinMode(LDR, INPUT);
  //Checks the light from the LDR
  checkLight();
  //Starts I2C communication
  Wire.begin(1);
  Wire.onReceive(updateState);
}

De forskellige pins, som state LEDerne bruger bliver defineret og initialiseret. Derudover startes I2C-forbindelsen med Master Arduinoen. Der bliver sat en event-listener op på forbindelsen så hver gang et signal bliver sendt til Slave Arduinoen, bliver updateState()-funktionen kaldt. Herunder er updateState()-funktionen

void updateState(int Press)
{

  I2C_Message = Wire.read();
  if (I2C_Message == 1)
  {
    digitalWrite(WINDOW_OPEN_LED, HIGH);
    digitalWrite(WINDOW_CLOSED_LED, LOW);
    digitalWrite(RAIN_LED, LOW);
    lcd.setCursor(0, 1);
    lcd.print("Window Open");
  }
  else if (I2C_Message == 0)
  {
    digitalWrite(WINDOW_CLOSED_LED, HIGH);
    digitalWrite(WINDOW_OPEN_LED, LOW);
    digitalWrite(RAIN_LED, LOW);
    lcd.setCursor(0, 1);
    lcd.print("Window closed");
  }
  else if (I2C_Message == 2)
  {
    digitalWrite(RAIN_LED, HIGH);
    digitalWrite(WINDOW_OPEN_LED, LOW);
    digitalWrite(WINDOW_CLOSED_LED, LOW);
    lcd.setCursor(0, 1);
    lcd.print("Rain, closing");
  }
  else
  {
    lcd.setCursor(0, 0);
    lcd.print("Temp: ");
    lcd.print(I2C_Message);
    if(isDay){
      lcd.print("    DAY");
    } else {
      lcd.print("    NGT");
    }
  }

UpdateState-funktionen læser således det signal der er sendt fra Master Arduinoen, og opdatere visualisering af system state, afhængig af hvad for en besked der modtages. Derudover opdateres også dag eller nat beskrivelsen afhængig af den value isDay har, som bliver sat i funktionen checkLight(). Denne funktion kan ses herunder.

void checkLight()
{
  int ldrValue = analogRead(LDR);
  if (ldrValue > 300)
  {
    isDay = true;
  }
  else
  {
    isDay = false;
  }
}

Opbygning af fysisk prototype

Selve prototypen er bygget i lego da det var let tilgængeligt for os. Lego gjorde det nemt for os at skifte dele, ombygge og ændre mening undervejs Stepper motorens roterende kraft bliver omdannet til lineær kraft via Lego tandhjul, som således trækker eller skubber vinduet. Der er også lavet gearing idet stepper motorens drejningsmoment ikke var stærk nok til at bevæge vinduet uden. Dette kan ses på billedet herunder

Den ultrasoniske sensor er placeret ved siden af armen der skubber eller trækker vinduet for at få den mest præcise læsning af distancen til vinduet. Vand sensoren er placeret så tæt på vindueskarmen som muligt. Dette er gjort i det tilfælde at det regner, at regn dråber vil lande på sensoren og så ændre staten på system til “Rain”, således resultere i at vinduet lukker.

Temperatur måleren er placeret så langt væk fra vinduet som muligt, i det vi gerne vil have den mest korrekte rum temperatur muligt.

Konklusion

Vi har løst de problemstillinger der var sat foran os i dette projekt. Vi har anvendt et spektrum af forskellige aktuatore og sensore til at bygge en automatiseret løsning der reagere på omgivelserne. Vores system måler både temperatur, distance og potentiel regn, og tager alle disse variabler med i hvad en skal gøre. Hvis temperaturen er for høj åben vinduet, hvis temperaturen er for lav eller der er regn luk vinduet.

Perspektivering

Selve funktionen for vores system fungere som det skal, men der er flere aspekter der kunne tilføjes. Vores valgt af temperatur sensor, giver os den mulighed også at måle luftfugtigheden. Der kunne implementeres at selvom temperaturen er lav, så skal vinduet stadig åbnes hvis luftfugtigheden er nået et bestemt punkt.

Man kan kun ændre temperatur grænserne i koden på det her tidspunkt. Det ville være optimalt at man senere kunne ændre dem via en remote eller knapper.

Derudover er selve konstruktionen meget minimalt og stadig i prototype stadie. Hvis der skulle laves forbedringer der så det muligvis 3D-printet dele der kan sættes sammen så hele systemet kan sættes sammen mere kompakt og ordentligt.

Leave a Reply