Hardware og Robotteknologi
Foråret 2021
Porteføljeopgave 2

Lars Philip Francisco Allerup
Maria Skougaard Andersen
Rune Philipsen



Vi har valgt at lave smarthome system kaldet Ultrahouse 2999, som både sørger for et bedre indeklima, et sikrere hjem og en smart postløsning.

Der bliver skabt bedre indeklima, ved at der automatisk bliver luftet ud, hvis der er for fugtigt i hjemmet samt en ventilator starter, hvis der er for varmt derinde. Hvis det er mørkt (nat eller slukket lys) og fugtigt i hjemmet bliver udluftningslågen kun åbnet lidt, så der ikke kan komme ubudne gæster indenfor. Endvidere hvis det er mørkt og varmt, tændes ventilationen ikke automatisk for at undgå beboerne bliver forkølede imens de sover, eller ventilatoren kører imens de ikke er til stede.

Derudover indeholder automationsløsningen et system, som får lys i forhaven til huset til at lyse op, når der er bevægelse ved vinduerne.
Ellers indeholder løsningen en smart løsning, der information husets beboere, når der er kommet post. 

Til systemet har vi brugt Arduinoen, breadbords, ledninger og modstande til opstillingen. 
Derudover har vi benyttet fire sensorere: En LDR, en hummity- og temperatur sensor, en afstandsmåler, en bevægelsessensor.
Endvidere har vi brugt fire aktuatorer: En buzzer, en dc motor, en servo motor, dc motor brushless fan. 
Derudover har vi benyttet en NPN transistor, et serielt interface: LCD

Indeklima Tutorial

Denne del af automationsløsningen giver dit hjem et bedre indeklima. System er blandt andet styret på baggrund af luftfugtigheden og temperaturen i dit hjem. Hvis der er for fugtigt, bliver der automatisk luftet ud. Hvis det er mørkt i rummet (nat eller du ikke er hjemme) bliver udluftningslågen kun åbnet lidt, så der ikke kravler nogen ind. Endvidere hvis det er lyst og varmt i dit hjem starter en ventilator, så du kan holde ud at være der.

Til systemet skal du bruge følgende komponenter:

  • 1 x Arduino Uno
  • 1 x DHT11 Temperatur og fugtigheds modul
  • 1 x LDR
  • 1 X 10 KΩ modstand
  • 1 x Power Supply Modul
  • 1 x 9V batteri
  • 1 x DC motor med propel
  • 1 x L293D (til at styre dc motoren)
  • 1 x Servo motor
  • 1 x LCD1602 Modul
  • 1 x 10 KΩ potentiometer
  • 1 x 74HC595 IC (til LCD displayet)

Derudover skal du også bruge LEGO, et LEGO-hængsel og ståltråd.

Opstillingen er nemmest at tage sektion for sektion.

Hardwareopstilling

DHT11 Temperatur- og fugtighedsmodul

Du skal have Arduinoen og breadboardet foran dig. Start med at forbind Arduinoens 5V til breadbordets ene lange power-række og for ligeledes ground på Arduinoen til ground på dit breadbord.
Sæt DHT11 Temperatur og fugtigheds modulet i breadbordet, dens første pin fra venstre forbinder vi til Arduinoens pin nr. 2 med en ledning. Pinnen i midten forbinder du med en ledning til rækken med 5V og sidste pin forbindes med ground.

LDR

Sæt LDRen i breadbordet, forbind dens højre ben med rækken med 5V, det andet ben, venstre ben, skal stå i serie med din 10 KΩ modstand, som er forbundet med en ledning til ground.

Det er en spændingsdeler du har lavet her. I rækken hvor både LDRen og resisteren har et ben, placerer du den ene ende af en ledning, den anden ende sætter du i Arduinoens analog A2 port.

For at kunne måle værdierne fra LDRen bliver du nødt til at lave sådan et spændingsdelerkredsløb. Grunden til dette er at LDRen er en variabel resistor som ændrer sin indre modstanden på baggrund af lysstyrken. For at måle denne ændring med Arduinoens Analog to Digital Converter, som omsætter forskellen i spændingen, og ikke forskellen på resistansen I LDRen, er det nødvendigt at have et referencepunkt hvorfra man kan måle spændingsfaldet. Hvilket ville havde været fra 0 – 5 V hvis spændingsdelerkredsløbet ikke blev anvendt.

Servo motor

Af LEGO eller et andet materiale skal du bygge et lille rum med en låge. Vi har lavet det af LEGO, et LEGO-hængsel og bundet ståltråd til lågen og servo motoren, så den kan åbne og lukke lågen.

Servo motoren har tre ledninger, brun, rød og orange. Den brune forbinder du med ground, den røde til 5V og den orange til Arduinoens pin 6.

DC Motor med propel

Til at starte med tager du dit power supply og sætter i dit breadboard med batteriet. Ground på Arduinoen forbinder du til øverste lange række i dit breadboard

DC motoren skal du nu til at koble til L293D chippen, som skal styre den.

Med L293D chippen foran dig, skal du placere det, så den ende der har et lille buet indhak vender mod venstre. Når Chippen vender denne vej, er dens pinne i nederste række nr.- 1, 2, 3, 4, 5, 6, 7, 8 og dens pinne øverst er 16, 15, 14, 13, 12, 11, 10, 9.
Ben 8 på chippen skal kobles til en ekstern strømforsyning, som forsyner motoren.
Ben 16 skal kobles til 5V fra Arduinoen, som forsyner logikken i chippen. Chippens pin 1 skal forbindes til Arduinoens port 9, chippens pin 2 skal forbindes til Arduinoens port 7, dens pin skal forbindes til dc motorens positive terminal, chippens pin 4 skal forbindes til ground, dens pin 6 skal forbindes til dc motorens negative terminal, chippens pin 7 skal forbindes til Arduinoens port 8.

Beregninger

Normal LED Beregning 

Til beregning af LED’erne som ikke er styret af transistor kredsløbet har vi undersøgt via datablad hvilken anbefablet strømstyrke som er den anbefalet værdi. Her fandt vi frem til at det mest optimale var at ligge mellem 16-18mA. Da valget stod mellem at vælge en 330 Ω modstand eller en 220 Ω for at kommet tættest på den ønskede værdi valgte vi at gå med 330 Ω modstanden da belysningen ikke behøvede at være kraftig inde i rummet   

DC Motor Fan
  • 1 x DC
  • 1 X P2N2222A
  • 1X 2 kΩ resistor
  • 1 X Diode

Som en tilføjelse til vores klima kontrol har vi valgt at tilføje en DC-motor fan, som skal starte hvis der er fugtigt i vores smarthome. Måden hvorpå kredsløbet er bygget op er følgende.

DC-motoren kræver mellem 5-7 volt og en strømstyrke på 200mA for at den kan køre. Da Arduinoen ikke kan levere sådan en strømstyrke, har vi anvendt en transistor, hvis base signal styres af en lille strøm fra Arduinoen til transistorens base ben. Denne strømstyrke skal sørge for at transistoren skifter mellem cutoff og saturated tilstand. Følgende beregninger er foretaget for at opnå den ønskede strømstyrke der flyder fra collector til emitter benene på transistoren.

Motor Beregning

Signalstyrkeværdien i følge databla77det for P2N2222A

Så kan vi beregne IEC

Vi har dermed fået opnået den ønskede strømstyrke som motoren kræver. Denne strømstyrke løber fra collector til emitter benene på transistor. Som en sikkerheds tilføjelse til kredsløbet og motoren har vi tilføjet en flyback diode. 

Shift Register 74HC596 Og LCD

Da vi under udviklingen af vores prototype, var ved at løbe tør for porte på Arduinoen, i det vores LCD 16*2 skræm kræver 6 porte, valgte vi at undersøge om det var muligt at få flere porte til Arduinoen. Her fandt vi frem til at man kunne bruge en 74HC585 som via 3 porte fra Arduinoen til komponenten frigiver 8 digitale porte. De frigivede porte kunne vi så bruge til at sende signal til vores LCD. Dvs udgangsporte fra shift register til indgangsporte på LCDén.

Beskrivelse af opsætningen

Her tager vi først udgangspunkt i 74HC595 og dens forbindelse til Arduinoens porte samt Ground og Vcc.

  • GND — Ground
  • VCC — 5 volt Arduino
  • SRCLC — 5 Volt Arduino
  • SRCLK — Pin 13 Arduino
  • RCLK — Pin 10 Arduino
  • OE — Ground
  • SER — Pin 11 Arduino
Forbindelse mellem LCD og 74HC596

Vi startede med at sætte LCD skærmen i breadbordet, dernæst kunne vi begynde at forbinde portene mellem LCD og  74HC596.

  • VSS – Arduino Ground
  • VDD — Arduino 5V
  • VO — Potentiometer midt pin (Husk 2 andre Pins ground -VCC)
  • RS — QB –74hc595
  • RW– Ground
  • E –QD
  • D4 — QE
  • D5 — QF
  • D6 — QG
  • D7 — QH
  • A — 5 Volt Arduino
  • K — Ground

Kodeopstilling

I toppen af din kode skal du importere nogle biblioteker, som skal bruges til LCD displayet, servoen og fugtigheds- og temperatur modulet.

//SPI LCD/Shiftregister SETUP
#include <ShiftedLCD.h>
#include <SPI.h>
//Servo
#include <ServoTimer2.h>

Herefter sætter du objektet op til LCDen.

//LCD SETUP: 16 kolonner og 2 rækker på lcden
LiquidCrystal lcd(10);// initialisere bibloteket med parameteren der svarer til nummeret på 74HC59 komponentens pin.

Servo motor objektet laver du, laver en variabel til dens pin på Arduinoen og laver en variabel der er servo motorens vinkler

//Servo2
ServoTimer2 myServo;

int servoPin = 6;
int servoVinkelOpen = 750 ;   //Værdien afhænger af dit eget setup.. 
int servoVinkelClosed = 1400; //Værdien afhænger af dit eget setup..
int servoVinkelMid = 1000;    //Værdien afhænger af dit eget setup..

Så laver du objektet til temperatur og fugtighedssensoren, tildeler den sin pin på Arduinoen og laver variable som senere skal bruges til at indeholde værdien af fugtigheden og temperaturen som sensoren opfanger. Sidst laver du variabler til at holde en værdi for lysstyrken i rummet samt.

// Klima Kontrol -> Fugt - Temperatur sensor  og LDR
#define Type DHT11
int sensePin = 2;
DHT HT(sensePin, Type); 

float humidity;
float tempC;

int lightVal = 0;
int lightPin = A2;

Nu laver du nogle variable klar til dc motoren.

//DC Motor Controller Chip - L293D
int speedPin = 9;
int dir1 = 7;
int dir2 = 8; 
int mSpeed = 170;//motor speed mellem 0 og 255

Så er vi nået til setup, heri bliver servoens pin sat op

 // Servo
 myServo.attach(servoPin);

DC motoren bliver sat op som output og lightPin som input.

//DC Motor Chip
pinMode(speedPin, OUTPUT);
pinMode(dir1, OUTPUT);
pinMode(dir2,OUTPUT);
  
//LDR
pinMode(lightPin, INPUT);

LCD displayet bliver sat op og fugtigheds og temperatur sensoren startes.

//LCD SETUP: 16 kolonner og 2 rækker på lcden
lcd.begin(16, 2); // opsætning af LCD's antal af kolonner og rækker:
lcd.print("UltraHouse 2999!");   // Skriver en besked til LCD.

//FUGT&TEMPSENSOR SETUP: starter fugtighed og temperatur sensoren
HT.begin();

I dit script skal du skrive en funktion som tager tre input, temperaturen i rummet, fugtigheden og en værdi for lyset i rummet.

Funktionen sørger for, hvis der er fugtigt og lyst åbnes en udluftningslåge, hvis det er fugtigt og mørkt åbner udluftningslågen kun lidt.
Endvidere hvis der er lyst og varmt i rummet tændes en blæser.

void smartIndeklima(float humidity, float tempC, int lightVal)
{
  /*Tjek op på hvad normal fugtighed -- pt 26 i rummet   */
  if (humidity >= 50 && lightVal > 700) // -- Lightval er 195 i vindueslys (56 er laveste målt ) - lysere laver værdi --> 722 næste fuld mørke -- resistansen i LDR forøges med mørke
  {
    //fugtigt åben og der er lys i rummet
    myServo.write(servoVinkelOpen);
  } else if (humidity > 50 && lightVal < 700)
  {
    //fugtigt og mindre lys, vinduet skal kun åbne lidt
    myServo.write(servoVinkelMid);
    
  } 
  else if (humidity < 50)  
  {
    //den er lukket
    myServo.write(servoVinkelClosed);
  }

  if (tempC > 20 && lightVal < 700)  
  {
    /*Tænd DCfan */
    digitalWrite(fanDc,HIGH);

    //tænd DC motor blæseren, retning og hastighed
    digitalWrite(dir1, LOW);
    digitalWrite(dir2,HIGH);
    analogWrite(speedPin, mSpeed);
  } 
  else if (tempC < 24)
  {
    /*DC-Fan*/
    digitalWrite(fanDc,LOW);
    /*DC-Motor*/
    digitalWrite(dir1, LOW);
    digitalWrite(dir2,LOW);
  }
}

I en anden funktion CheckHumidityTemperature, som kaldes af en timer, læses værdien for lyset i rummet. Temperatur og fugtighedssensoren opfanger temperaturen og fugtigheden og værdierne bliver skrevet ud på LCD displayet.
I slutningen af denne funktion kaldes smartIndeklima funktionen

void CheckHumidityTemperature() {
  if (HumidCheck)
  {
    lightVal = analogRead(lightPin);   //læser LDR- værdien af lysstyrke 
    Serial.println(lightVal);
    delay(100);
  
    humidity = HT.readHumidity();
    tempC = HT.readTemperature();
  
    lcd.setCursor(0, 0);
  
    lcd.print("Temp C= ");
    lcd.print(tempC);
  
    lcd.setCursor(0, 1);
    lcd.print("Humidity= ");
    lcd.print(humidity);
    lcd.print("%");
    delay(500);
  
    //kalder funktionen med de tre parametre
    //funktionen er skrevet nederst på siden
    smartIndeklima(humidity, tempC, lightVal);
  } 
}

Postkasse Tutorial

Dette element af projektet er en sensor og alarm til din postkasse, så at du inde fra dit hjem, kan vide når du har fået post.
Til projektet bruges disse komponenter:

  • 1 x Arduino Uno
  • 1 x HC-SR04
  • 1 x Passiv buzzer
  • 1 x LED
  • 2 x 330Ω Modstande
  • 10 x Ledninger

Hardwareopstilling

Din HC-SR04 sættes i breadboardet og bliver forbundet så at Vcc-Pin går til 5V, Trigger-pinnen til pin A0 på arduinoen, Echo-pinnen til pin A1 på arduinoen og ground til ground.

Med sensoren på plads, sætter vi dernæst alarmsystemet i.
LED’en or den passive buzzer sættes på breadboardet. LED’en sættes i serie med den ene af modstandene, hvilken der kommer først er ligegyldigt. Ligeså sætter Buzzeren i serie med den anden modstande, rækkefølgen også ligegyldig. Den positive side af LED-Serien sættes til pin 4 på arduinoen og den positive side af Buzzer-serien sættes specifikt til pin 5 på arduinoen, da vi skal bruge PWM til at sende forskellige frekvenser til buzzeren for forskellige toner.
Sidst sættes den negative side af begge serier til ground.

Kodeopstilling

Til kodeopstillingen starter vi med at skrive vores pins og variabler op.

int triggerPin = A0;
int echoPin = A1;
int ledPin = 4;
int buzzerPin = 5;

long duration;
long cm;
long minDist = 10;
long canIBuzz = 0;
bool postCheck = false;

Dernæst skriver vi i setup vores pins op

Serial.begin(9600);
  
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);

Så skriver vi vores PostkasseCheck funktion, som kaldes af en timer. Denne funktion bruger HC-SR04 komponentet til at aflæse distancen i postkassen og dermed om der er noget post i postkassen hvilket ville have en lavere distance. Givet at den målte distance er indenfor vores krav, så kaldes den anden funktion YouveGotMail.

void PostkasseCheck() {
  if (postCheck) {
    //Ved at give en kort lav puls først, sikrer vi en ren Høj puls
    digitalWrite(triggerPin, LOW);
    delayMicroseconds(5);
    //Høj puls vi bruger til distance
    digitalWrite(triggerPin, HIGH);
    delayMicroseconds(10);
    //Sensoren skal føle en høj puls i mindst 10 mikrosekunder
    digitalWrite(triggerPin, LOW);

    //Læser højt puls, Duration er tiden(ms) mellem send og modtag
    duration = pulseIn(echoPin, HIGH);

    cm = ((duration / 2) * 0.0343);
    //divideres med 2 fordi vi kun skal have distancen den ene vej
    // 0.0343 er lydens hastighed i cm/s ved 20 grader celcius

    Serial.print("dist i cm: ");
    Serial.print(cm);
    Serial.println();

    if (cm <= minDist)
      YouveGotMail();

    if (cm > minDist)
    {
      canIBuzz = 0;
      digitalWrite (ledMailPin, LOW);
    }
    postCheck = false;
  }
}

Den sidste funktion for postkassen er YouveGotMail funktionen, som er vores displayfunktion der fortæller når der er post ved brug af henholdsvis lyd og lys.

void YouveGotMail()
{
  //lys hvis mail
  digitalWrite(ledMailPin, HIGH);

  //Første gang der er mail siden sidstm så buzzer vi også
  if (canIBuzz == 0)
  {
    tone(buzzerPin, 1046);
    delay(200);
    noTone(buzzerPin);
    delay(200);
    tone(buzzerPin, 1318.51);
    delay(200);
    noTone(buzzerPin);
    delay(200);
    tone(buzzerPin, 1567.98);
    delay(200);
    noTone(buzzerPin);
    delay(200);
    tone(buzzerPin, 2093.00);
    delay(200);
    noTone(buzzerPin);
    delay(200);

    //men KUN første gang
    canIBuzz = 1;
  }
}

Motionssensor Tutorial

Dette tredje element af Ultrahouse 2999 gør brug af en Infrarødsensor til at tænde et lys når der detekteres motion.

  • 1 x Arduino Uno
  • 1 x HC-SR501
  • 3 x LED
  • 4 x 330Ω Modstande

Hardwareopstilling

HC-SR501 PIR Motion sensor module

Som en sikkerhedsfunktion til vores smart-home prototype har vi valgt at implementere en Infarød bevægelsessensor. Denne sensor registrerer hvis der er bevægelse i en vinkel indenfor 110 grader, som man kan justere på sensitivitets potentiometer som sidder på modulet. På det andet potentiometer kan man justere hvor længe tiden skal være høj efter sensoren har opfanget bevægelse. Tiden er mellem 3 – 300 sekunder. I vores modul har vi valgt 3 meter på sensitiviteten og ca. 30 sekunder på tids potentiometers. Deruvoer er der et delay på 5 sekunder hvor sensoren ikke kan opfange bevægelse efter den har læst en værdi.

PIR modulet har 3 pins, ground, Vcc og digital output. For at få den til at virke med arduinoen skal Vcc tilsluttets til minimum 5 V – og ground til common ground, digital output-pin til en af arduinoens digitale porte.

Med den infarøde bevægelsessensor har man også muligheden for at justere på hvordan sensoren skal holde et signal som højt eller lavt. Her har man muligheden for at vælge mellem Hold/repeat/retriggering(H) eller No-Repeat/Non-Retriggering(L). Disse funktioner styres af en jumper som, man kan indstille efter projektets behov.

Forskellen på disse er at signalet fra (H) vil være sat til høj så længe der er bevægelse og ved (L) vil signalet være høj tilsvarende den tid som er valgt på tid potentiometeret.

Til vores applikation har vi valgt at have vores jumper ved L, så signalet vil forblive højt i det tidsrum som er angivet via tids potentiometeret.

En sidste ting som er vigtig for at PIR sensoren virker optimalt er at give den tid til at kalibrere rummets infrarøde energi, første gang applikationen og sensoren starter op – dette kan være mellem 30-60 sekunder.

På billedet fornenden ses et overblik over PIR modulet.

Kodeopstilling

Til kodeopstillingen starter vi med at skrive vores pins og variabler op.

int motionSensor = 3;        // pin som sensoren er tilsluttet
int ledAlarm = 8;   //12     // Alarm LEDS

int state = LOW;             // default værdi-ingen bevægelse
int motionSensorVal = 0;     // sensor status værdi

Dernæst skriver vi i setup vores pins

  pinMode(motionSensor, INPUT);    // initialisere sensor som input
  pinMode(ledAlarm, OUTPUT);

Funktionen CheckMotion, der bliver kaldt af et software interrupt, er forholdvis simpel og tænder et lys når der detekteres et Højt signal.

void CheckMotion() 
{
  motionSensorVal = digitalRead(motionSensor);   // læser sensorens værdi

  if (motionSensorVal == HIGH) // tjekker om sensorens værdi er Høj
  {           
    digitalWrite(ledAlarm, HIGH);
    
    if (state == LOW) {
      Serial.println("Motion detected!");   //Sikrer at vi kun udskriver værdien engang

      state = HIGH;       // opdaterer variablen til høj
    }
  }
  else if (motionSensorVal == LOW) {
    digitalWrite(ledAlarm, LOW);

    if  (state == HIGH) {
      Serial.println("Motion stopped!");
      state = LOW;       // opdaterer variablen til lav
    }
  }
}

Prioriteringsfunktioner og Flowdiagram

Vi har en prioritering opsat ved brug af timers til to af elementerne og et softwareinterrupt til et af elementerne.
Vores timers er skrevet op som variabler og bruges i tjek-funktioner med bool-værdier som tjek.

De to timers sættes så til samme værdi som Millis er, altså tiden i millisekunder siden start er opnået, i slutningen af setup

//Timer
long postkasseDelay = 21600000;// Tjekker post hver 6. time 
long HumidDelay = 300000; //Tjekker luftfugtighed og temperatur hver 5. minut
long postkasseTimer;
long HumidTimer;

//State booleans
bool postCheck = false;
bool HumidCheck = false;

void setup() 
{
  postkasseTimer = millis();
  HumidTimer = millis();
}

I vores loop skriver vi så vores tjek-funktioner op så at de kaldes og derfra styrer hvorvidt en funktion skal aktiveres.

void loop() 
{
    PreCheckHumidityTemperature(); 
    CheckHumidityTemperature(); 
    CheckMailtime(); 
}

Disse timertjek tjekker så om tiden er gået, for så at udføre funktionen og sætte timerne til at være millis, så at timerne følger med.

void PreCheckHumidityTemperature()
{
  if (millis() - HumidTimer > HumidDelay)
    HumidTimer = millis();
    HumidCheck = true;    
}

void CheckMailtime() {
  CheckPostkasseTimer();
  PostkasseCheck();
}

void CheckPostkasseTimer() {
  if (millis() - postkasseTimer > postkasseDelay)
    postkasseTimer = millis();
    postCheck = true;
}

HumidCheck og postCheck kontrollerer så om hvorvidt tiden er gået og at funktionen må gå igang.

Derudover så har vi et softwareinterrupt som hver 6. sekund pauser resten af koden for at tjekke om MotionCheck må køre, for så at hoppe tilbage til loopet.

SoftwareInterruptet sættes op i Setup og kræver biblioteket TimerOne.h

#include <TimerOne.h>

void setup() 
{
  Timer1.initialize(6000000);    // Software interrupts - cheker motion hver 6 sekund, står i mikrosekunder
  Timer1.attachInterrupt(CheckMotion); // Tilføjer den funktion som skal kaldes
}

Opbygning af den samlede fysiske prototype

Den fysiske prototype af Ultrahouse 2999 er hovedsageligt konstrueret af LEGO, elektroniske komponenter og kode. LEGOet udgør konstruktionen af huset, mekanikken sker på baggrund af input til sensorer, som derefter starter nogle aktuatorer. Alt mekanikken er styret af software. 

Komplet hardwareopstilling

Komplet kodeopstilling

/*Libary Import */
/* SPI LCD/Shiftregister SETUP  */
#include <ShiftedLCD.h>
#include <SPI.h>

/* Servo 2 */
#include"ServoTimer2.h"
ServoTimer2 myServo;

/*Temperatur og futighed*/
#include "DHT.h"
/*Softwareinterrupt*/
#include <TimerOne.h>

/*LCD - Skærm */
LiquidCrystal lcd(10);// initialisere bibloteket med parameteren der svarer til nummeret på 74HC59 komponentens spin.

/*Postkasse*/
int triggerPin = A0;
int echoPin = A1;
int ledMailPin = 4; // Postkasse led
int buzzerPin = 5;//analog

long duration;
long cm;
long minDist = 10;
long canIBuzz = 0;

/*Servo 2*/
int servoPin = 6;
int servoVinkelOpen = 750 ;   //Værdien afhænger af dit eget setup.. 
int servoVinkelClosed = 1400; //Værdien afhænger af dit eget setup..
int servoVinkelMid = 1000;    //Værdien afhænger af dit eget setup..


/* Klima Kontrol -> Fugt - Temperatur sensor  og LDR*/
#define Type DHT11
int sensePin = 2; // ahr bytte plads
DHT HT(sensePin, Type); 

float humidity;
float tempC;

int lightVal = 0;
int lightPin = A2;

/*DC Motor Controller Chip - L293D*/
int speedPin = 9;
int dir1 = 7;
int dir2 = 8; 
int mSpeed = 170;//motor speed mellem 0 og 255

/*Motion Sensor */
int motionSensor = 3;        // pin som sensoren er tilsluttet
int ledAlarm = 8;   //12     // Alarm LEDS
int state = LOW;             // default værdi-ingen bevægelse
int motionSensorVal = 0;     // sensor status værdi


/*Timers*/
long postkasseDelay = 21600000;// Tjekker post hver 6. time 
long HumidDelay = 1000; //300000 --- Skal ændres tilbage
long postkasseTimer;
long HumidTimer;

/*State booleans*/
bool postCheck = false;
bool HumidCheck = false;

/*Fan DC Motor */
int fanDc = A4;
void setup() {

  Serial.begin(9600);

  /*Motion Sensor Og Led */
  pinMode(motionSensor, INPUT);    // initialisere sensor som input
  pinMode(ledAlarm, OUTPUT);

  /* Postkasse */
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(ledMailPin, OUTPUT);
 
  /* Servo */  
   myServo.attach(servoPin);  
   
  /*DC Motor Chip --  */
  pinMode(speedPin, OUTPUT);
  pinMode(dir1, OUTPUT);
  pinMode(dir2,OUTPUT);
  
  /* LDR */
  pinMode(lightPin, INPUT);

 /* LCD SETUP: 16 kolonner og 2 rækker på lcden */ 
  lcd.begin(16, 2); // opsætning af LCD's antal af columns og rows:
  lcd.print("UltraHouse 3000!");   // Skriver en besked til LCD.

  /*FUGT&TEMPSENSOR SETUP: starter fugtighed og temperatur sensoren */
  HT.begin();

  myServo.write(1400); //750åben --  1400lukket

  /*Start Delay */
  delay(30000); // PIR Sensor delay 

  
  postkasseTimer = millis();
  HumidTimer = millis();
  Timer1.initialize(6000000);    // Software interrupts - cheker motion hver 6 sekund 
  Timer1.attachInterrupt(CheckMotion); // Tilføjer den funktion som skal kaldes

  /*DC FAN */
  pinMode(fanDc,OUTPUT);
}

void loop() {
  /* SKal AKtiveres
    PreCheckHumidityTemperature(); 
    CheckHumidityTemperature(); 
    CheckMailtime(); 
 */


   digitalWrite(fanDc,HIGH); // fjernes 
   postCheck = true;
   PostkasseCheck();
   CheckMotion(); 
   
}

/*POSTKASSE FUNKTIONER START*/
void CheckMailtime() {
  CheckPostkasseTimer();
  PostkasseCheck();
}

void CheckPostkasseTimer() {
  if (millis() - postkasseTimer > postkasseDelay)
    postkasseTimer = millis();
    postCheck = true;
}

void PostkasseCheck() {
  if (postCheck) {
    //Ved at give en kort lav puls først, sikrer vi en ren Høj puls
    digitalWrite(triggerPin, LOW);
    delayMicroseconds(5);
    //Høj puls vi bruger til distance
    digitalWrite(triggerPin, HIGH);
    delayMicroseconds(10);
    //Sensoren skal føle en høj puls i mindst 10 mikrosekunder
    digitalWrite(triggerPin, LOW);

    //Læser højt puls, Duration er tiden(ms) mellem send og modtag
    duration = pulseIn(echoPin, HIGH);

    cm = ((duration / 2) * 0.0343);
    //divideres med 2 fordi vi kun skal have distancen den ene vej
    // 0.0343 er lydens hastighed i cm/s ved 20 grader celcius

    Serial.print("dist i cm: ");
    Serial.print(cm);
    Serial.println();

    if (cm <= minDist)
      YouveGotMail();

    if (cm > minDist)
    {
      canIBuzz = 0;
      digitalWrite (ledMailPin, LOW);
    }
    postCheck = false;
  }
}

void YouveGotMail()
{
  //lys hvis mail
  digitalWrite(ledMailPin, HIGH);

  //Første gang der er mail siden sidstm så buzzer vi også
  if (canIBuzz == 0)
  {
    tone(buzzerPin, 1046);
    delay(200);
    noTone(buzzerPin);
    delay(200);
    tone(buzzerPin, 1318.51);
    delay(200);
    noTone(buzzerPin);
    delay(200);
    tone(buzzerPin, 1567.98);
    delay(200);
    noTone(buzzerPin);
    delay(200);
    tone(buzzerPin, 2093.00);
    delay(200);
    noTone(buzzerPin);
    delay(200);

    //men KUN første gang
    canIBuzz = 1;
  }
}

/*POSTKASSE FUNKTIONER STOP*/
void PreCheckHumidityTemperature()
{
  if (millis() - HumidTimer > HumidDelay)
    HumidTimer = millis();
    HumidCheck = true;    
}

/*Humidity And Temperature */
void CheckHumidityTemperature() {
  if (HumidCheck)
  {
  
    lightVal = analogRead(lightPin);   //læser LDR- værdien af lysstyrke 
    Serial.println(lightVal);
    delay(100);
  
    humidity = HT.readHumidity();
    tempC = HT.readTemperature();

    lcd.clear();
    lcd.setCursor(0, 0);

    lcd.print("Temp C= ");
    lcd.print(tempC);
  
    lcd.setCursor(0, 1);
    lcd.print("Humidity= ");
    lcd.print(humidity);
    lcd.print("%");
    delay(500);
  
    //kalder funktionen med de tre parametre
    //funktionen er skrevet nederst på siden
    smartIndeklima(humidity, tempC, lightVal);
  } 
}

//funktion hvis det er mørkt/nat/slukket lys
//skal vinduet ikke åbne særlig meget, så der ikke kommer tyve ind
//og blæseren skal heller ikke tænde

void smartIndeklima(float humidity, float tempC, int lightVal)
{
  /*Chek Op på hvad normal fugtighed -- pt 26 i rummet   */
  if (humidity >= 50 && lightVal < 700) // -- Lightval er 195 i vindueslys (56 er laveste målt ) - lysere laver værdi --> 722 næste fuld mørke -- resistansen i LDR forøges med mørke
  {
    //fugtigt åben og der er lys i rummet
    myServo.write(servoVinkelOpen); // OBS lad os lave det til en bestemt variabel 
  } else if (humidity > 50 && lightVal > 700)
  {
    //fugtigt og mindre lys, vinduet skal kun åbne lidt
    myServo.write(servoVinkelMid);// OBS lad os lave det til en bestemt variabel
   
  }  else if (humidity < 50)  
  {
    //den er lukket
    myServo.write(servoVinkelClosed);
  }

  if (tempC > 20 && lightVal < 700)  // ændret tegn
  {
   /*Tænd DCfan */
    digitalWrite(fanDc,HIGH);
   
    /*Tænd DC motor blæseren, retning og hastighed */
    digitalWrite(dir1, LOW);
    digitalWrite(dir2,HIGH);
    analogWrite(speedPin, mSpeed);
  } 
  
  else if (tempC < 24)
  {
    /*DC-Fan*/
    digitalWrite(fanDc,LOW);
    /*DC-Motor*/
    digitalWrite(dir1, LOW);
    digitalWrite(dir2,LOW);
  }
}

/*Motion Tracker  */
void CheckMotion() {
  motionSensorVal = digitalRead(motionSensor);   // læser sensorens værdi

  if (motionSensorVal == HIGH) {           // tjekker om sensorens værdi er Høj
    digitalWrite(ledAlarm, HIGH);
    
    if (state == LOW) {
      Serial.println("Motion detected!");   //Sikre at vi kun udskriver værdien engang --
      state = HIGH;       // opdatere variablen til høj
    }
  }
  else if (motionSensorVal == LOW) {
    digitalWrite(ledAlarm, LOW);

    if  (state == HIGH) {
      Serial.println("Motion stopped!");
      state = LOW;       // opdatere variablen til lav
    }
  }
}

Videoer af konstruktionen

Konklusion

Ultrahouse 2999 som er vores automationssystem, løser vores problemstillinger godt. Undervejs er dc motoren gået i stykker, og det ene ben af chippen L293D faldt af, som styrer dc motoren/ vores ventilator. 

Perspektivering

I forhold til registrering af bevægelse ved husets vindue, som på nuværende tidspunkt tænder spotlys, hvis der er bevægelse, kan man videreudvikle det til et alarmsystem. Eksempelvis kan en buzzer starte inde i huset, hvis der er nogen ved vinduet. Endvidere hvis der ikke er nogen inde i huset og vinduet bliver smadret, kan der sendes en besked til naboerne (eller en alarmcentral), om at der er indbrud i huset. 

For at inkorporere flere sensorer til familiens smarthome, kan de også vælge at få en water level detection sensor module, som måler vandstanden i kælderen. hvis der måles vand i kælderen bliver der åbnet en låge til en stor underjordisk tom tank, som vandet kan løbe over i, så de undgår en oversvømmelse. 

Derudover kan familien også få en løsning til deres hjem, som er lavet ud af sound sensor modulet, som får LEDer i forskellige farver til at blinke, alt efter om der er for meget larm i hjemmet eller tilpas lyd.

Referencer

https://lastminuteengineers.com/pir-sensor-arduino-tutorial/
https://sudaspace.wordpress.com/2015/12/18/control-lcd-display-using-shift-registers-74hc595n/
https://lastminuteengineers.com/74hc595-shift-register-arduino-tutorial/
https://www.youtube.com/watch?v=fPLEncYrl4Q&t=1402s

Leave a Reply