Emil Plante Passer

Lavet af:
Mickas Louis Jensen – micje19
Magnus Emil Rømer – maroe18

https://cdn.discordapp.com/attachments/690126007071408167/838461146683670583/IMG_20210502_190118.jpg
Billede 1: Færdig bygget hardware

INTRODUKTION
I portefølje opgaven skulle vi finde en automatiseret løsning til et almindeligt problem.
Det problem vi gerne ville kigge på, var et intelligent plante groenings system. Som ville gøre det meget nemmere at gro en sund plante og sørge for den får vand og næring nok. Her tænker man nok hvorfor lige en plante? Vi synes det lå rimeligt godt til det med at være studerende og måske ikke have de mest grønne fingre i livet. Derfor lå det næsten perfekt til at vi skulle skabe et system der gør det meget nemmere at gro en plante, det store fokuspunkt i projektet er nemlig at vores system kan fortælle dig hvornår din plante trænger til noget vand.

DIAGRAMTEGNING OG GENNEMGANG AF OBJEKTER

https://cdn.discordapp.com/attachments/690126007071408167/838436156315140126/unknown.png
Billede 2: Diagramtegning af systemet
  • 1 x Arduino
  • 1 x L293D h-bro
  • 1 x passive buzzer 
  • 1 x photo resistor 
  • 1 x Soil humidity sensor
  • 1 x Temperature sensor
  • 1 x LCD display
  • 1 x 3-6 dc motor
  • 1 x Water level sensor
  • 1 x 9 volt battery and adapter
  • 3 x 220 ohm resistor
  • 1 x 10k ohm resistor
  • 1 x RGB led

Blæser
Her kører der en dc motor, der blæser duften af planten rundt i lokalet og simulerer vind for planten. Da nogle planter kan have godt af at få en smule vind for at gro bedre.

Lys sensor
Lys sensoren bliver brugt til at holde øje med hvor meget lys planten for i løbet af dagen, nogle planter vil gerne have meget direkte sol og andre planter vil gerne have en blanding af sol og skygge. Så for at holde øje med det, måler vi mængden af lys planten for i løbet af en dag.

Temperatur sensor
Temperatur sensor bliver brugt til at måle rummets temperatur, for at sikre at planten ikke er for kold eller for varm til at gro ordenligt.

Jordfugtigheds sensor
Jordfugtighedssensoren måler fugtigheden af jorden planten er i, for at vide hvornår planten har brug for vand eller andet.

Vandstands sensor
Vand Sensoren måler mængden af vand tilbage i beholderen, for at kunne fortælle bruger hvornår der skal hældes mere vand i systemet.

LCD Display
Displayet bliver brugt til at oplyse om de forskellige sensor, hvor varmt rummet er, mængden af vand og jordens fugtighed.

Power supply & batteri
Power supply bliver brugt til at tilføre systemet noget mere strøm, da med de mange komponenter der er i vores system. Begyndte system hurtigt at mangle mere strøm for at kunne køre alle processerne optimalt. Dertil var vi nød til at tilføje et batteri til vores H-Bro for at vores blæser fik nok strøm.

H-bro
Der bruges en H-bro til at give dc motoren strøm nok til at kunne kører rundt.

Lysdiode og lyd system
Ved hjælp af en farveskiftende led diode og en buzzer, kommunikere planten med brugeren. i tilfælde af at den mangler vand eller andet.

HARDWARENS SAMMENSÆTNING

https://cdn.discordapp.com/attachments/690126007071408167/838461144137334784/IMG_20210502_190107.jpg
Billede 3: Hardwarens sammensætning

Vi har valgt at samle alt vores ledning i en lille kasse hvor sensorene stikker ud fra siderne af og displayet kan tilgås på siden af kassen. Dernæst har vi tilføjet et hul i toppen af kassen hvori man kan se et lys der lyser henholdsvis rød, gul eller grøn alt efter hvorvidt det er tid til at vande planten. Kasse løsningen virker fint, og kassen kan lukkes for at give hele systemet et mere “clean” look.

KODE

#include <LiquidCrystal.h>

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
float temp;
float tempCon;
int tempPin = A2;
int val = 0;
int soilPin = A0;
int soilPower = 7;
const int pump1 = A5;
const int pump2 = A4;
int red_light_pin= 13;
int green_light_pin = 10;
int blue_light_pin = 9;
int LDRsens = A3;
int Sunval = 0;
int resval = 0;  
int respin = A1; 
unsigned long sunTime;
int inSun;

void setup() 
{
  pinMode(pump1, OUTPUT);
  Serial.begin(9600); 
  lcd.begin(16, 2);
  pinMode(soilPower, OUTPUT);
  digitalWrite(soilPower, LOW);
    pinMode(red_light_pin, OUTPUT);
  pinMode(green_light_pin, OUTPUT);
  pinMode(blue_light_pin, OUTPUT);
}

void loop() 
{
  Sunval = analogRead(LDRsens);
  Serial.print(Sunval);
  digitalWrite(pump1, HIGH);

  soilMoist();
  delay(3000);
  lcd.clear();

  waterLev();
  delay(3000);
  lcd.clear();
  readTemp();
  delay(3000);
  lcd.clear();

  sunFunc();
  delay(3000);
  lcd.clear();
}

int readSoil()
{

    digitalWrite(soilPower, HIGH);
    delay(10);
    val = analogRead(soilPin);
    digitalWrite(soilPower, LOW);
    return val;
    val = map(val, 0, 1023, 0, 255);
}

int sunFunc() {
  lcd.print("Time in sun = ");
  if(Sunval > 400){
  sunTime = millis()/1000;
  inSun = sunTime;
  lcd.print(sunTime);
  lcd.print(" S");
  } else if(Sunval < 400) {
    lcd.print(inSun);
    lcd.print(" S");
  }
} 

int waterLev() {
  lcd.print("WATER LEVEL: ");

  lcd.setCursor(0, 1);

  resval = analogRead(respin);
  if (resval <= 100) {
    lcd.print("Empty ");
    tone(8, 240, 2000); 
  } else if (resval > 100 && resval <= 155) {
    lcd.print("Low ");
    tone(8, 640, 2000); 
  } else if (resval > 155 && resval <= 170) {
    lcd.print("Medium ");
  } else if (resval > 170) {
    lcd.print("High ");
  }
}

int soilMoist() {
  lcd.print("Soil Moisture = ");    

lcd.setCursor(0, 1);
lcd.print(readSoil());
if (val <= 200) {
    RGB_color(255, 0, 0); // Red
    digitalWrite(pump1, LOW); 
    lcd.clear();
    lcd.print("Water me!!");
    delay(10000);
  } else if (val > 200 && val <= 400) {
    RGB_color(255, 255, 0); // Yellow
    digitalWrite(pump1, LOW); 
  } else if (val > 400 && val <= 800) {
    RGB_color(0, 0, 255); // Blue
  } else if (val > 800) {
    RGB_color(0, 255, 0); // Green
  }
}

int readTemp() {
  temp = analogRead(tempPin);

   temp = (temp * 0.48828125);
   tempCon = (temp - 32)*5/9; 
  
   lcd.print("TEMPERATURE = ");
   lcd.print(tempCon);
   lcd.print("*C");
   lcd.println();
}

void RGB_color(int red_light_value, int green_light_value, int blue_light_value)
 {
  analogWrite(red_light_pin, red_light_value);
  analogWrite(green_light_pin, green_light_value);
  analogWrite(blue_light_pin, blue_light_value);
}

FLOWCHARTS

https://cdn.discordapp.com/attachments/690126007071408167/838632886247620618/Vand_niveau.png
Billede 4: Flowchart over vandmålerens funktioner

https://cdn.discordapp.com/attachments/690126007071408167/838635083795529788/Temperatur.png
Billede 5: Flowchart over temparatur målerens funktioner
https://cdn.discordapp.com/attachments/690126007071408167/838641919798149120/jordfugtighed_2.png
Billede 6: Flowchart over Jord fugtighedsmålerens funktioner
https://cdn.discordapp.com/attachments/690126007071408167/838625235519144016/LCD_Display.png
Billede 7: Flowchart over LCD displayets funktioner
https://cdn.discordapp.com/attachments/690126007071408167/838620284764028968/Sollys.png
Billede 8: Flowchart over LDR sensorens funktioner

VIDEO

https://drive.google.com/file/d/1A66HkDMq2-lujFqs-VNX767JlD_F7J5v/view?usp=sharing

PROBLEMER
Vi havde oprindeligt en drøm om at vi istedet for at have en blæser på planten ville vi have at en vandpumpe blev drevet istedet. Grundet hardware fejl af uforklarlige årsager kunne dette desværre ikke lykkedes.
Derudover løb vi ind i nogle strømsvigts problemer da vi havde tilføjet vores fjerde komponent til systemet. Dette løste vi dog hurtigt ved tilføjelsen af en power supply som nemt kunne tilføjes til breadboarded.

KONKLUSION
Systemet vi har lavet fungere godt til at tjekke status af ens plante og forholdene rundt omkring den. Uheldigvis lykkedes vi ikke med pumpe delen. Den fungere også godt til at give alarm når planten mangler vand, og virker godt hvis man har nogle planter der skal have meget specifikke forhold. Den automatisk vandingsdel mangler hvilket ville have gjort plantepasningen fuldstændig automatisk, men vi er kommet frem men en halv automatisk løsning som stadig er smart og kan være god til den glemsomme sjæl.

PERSPEKTIVERING
Vi kunne forbedre vores system ved at introducere Blynk appen, dette ville gøre det muligt at kigge på statusen af planten på ens telefon og dertil evt. tænde en vandpumpe som vi ellers også gerne ville have tilføjet. Man kunne også tilføje hjul eller en eller anden form for vippe funktion så planten kunne bevæge sig efter solen og altid få sollys hvis man havde en plante type der krævede det.

More

Smart home med lys- og varmekontrol

Navn på jeres automationsløsning

Smart home med lys- og varmekontrol

Navn på gruppemedlemmerne / forfatterne

Jakob Kuhrt Gamborg – Jajoe18

Peter Andreas Brændgaard – pebra18

Malte Bukrinski – mabuk18

Introduktion

Vi har lavet et rum hvor vi ønsker at kontrollere temperaturen via et vindue som kan åbne og lukke automatisk, samt en ventilator som kan få luften i bevægelse i rummet. Ydermere har vi en pære som bliver styret af en bevægelsessensor, lyssensor samt tidspunkt på døgnet. Til at styre temperaturen har vi benyttet os af en temperaturføler. 

Video gennemgang af løsningen

Opbygning af hardware fra TinkerCad

Husk at beskrive hvorfor og hvordan I har valgt at lave de enkelte løsninger

Der bruges en spændingsdeler i samspil med photoresistoren, for at give den rigtige spænding til transistoren for at lampen lyser. Ifølge databladet går photoresistoren fra 100 kΩ ved mørke til omkring 8 kΩ ved normalt lys (https://cdn.sparkfun.com/datasheets/Sensors/LightImaging/SEN-09088.pdf). Output spændingen af en spændingsdeler gives ved følgende formel:

Vout = R2R1+R2 *Vin

Vi er interesseret i at der er høj output spænding, når photoresistoren er mørk, i.e. den har høj modstand. Samtidigt, skal der være lav outputspænding, når photoresistoren er lys. Ved at prøve os lidt frem fandt vi ud af den bedste kombination, som vi kunne lave med de modstande, der var til rådighed, var 25 kΩ. Det gav os følgende output spændinger:

Mørkt: Vout = 10000025000+100000 *5=4V

Lyst: Vout = 800025000+8000 *5=1.21V

Foran lysdioden er der selvfølgelig en modstand. Den er sat til 220 Ω for at være på den sikre side. Lysdioden kan tage max 75 mA (http://69.195.111.207/tutorial-download/?t=3mm_and_5mm_LED_Kit ), men lyser fuldt allerede ved 20 mA. En modstand på 220 Ω vil give 5V/220Ω = 22.7 mA ifølge ohms lov. 

Alle andre dele er simple inputs eller output alt efter delen. 

Kredsløbsdiagram

Opbygning af program

#include <dht.h>
#include <Servo.h>
#include <RTClib.h>
#include <Wire.h>

#define servoPin 6
#define dhtPin 7
#define motorPin 4
#define lightPin 8
#define motionPin 2
Servo servo;
RTC_DS1307 rtc;
dht dht;
int angle = 10;
int maxTemperature = 23;
int minTemperature = 20;
int lastMovement = 0;
int noMovementTime = 5;  
int startNightTime = 21;
int stopNightTime = 8;
int temperature;
uint32_t windowOpenTime = 0;
uint32_t minimumWindowOpeningTime = 10;
uint32_t windowOpeningInterval = 60;
DateTime now;
DateTime windowOpenDateTime;
bool isWindowOpen;

void setup() {
  Serial.begin(9600);
  setupRtc();
  
  servo.attach(servoPin);
  servo.write(angle); 
  pinMode(motorPin, OUTPUT);
  pinMode(lightPin, OUTPUT);
  pinMode(motionPin, INPUT);
}

void loop(){ 
  dht.read11(dhtPin);
  now = rtc.now();
  
  Serial.print("Time: ");
  printDateTime(now);

  setTemperature();
  printTemperature();
  ShouldVentilatorRun(); 
  ShouldThereBeLight();
  ShouldWindowOpen();
  printsWindow();

  Serial.println("");
  delay(1000);
}

void ShouldVentilatorRun(){
    if(temperature > maxTemperature ) {
      Serial.println("Is Ventilator On? Yes");
      digitalWrite(motorPin,HIGH);
   } else {
      digitalWrite(motorPin,LOW);
      Serial.println("Is Ventilator On? No");
  }
}

void ShouldWindowOpen(){
  if(isWindowOpen){
    // Close window
  if((temperature < maxTemperature) && compareTime(windowOpenDateTime+ TimeSpan(0,0,0,minimumWindowOpeningTime),now) == -1){
    servo.write(angle);  
    windowOpenDateTime = DateTime(now);
    Serial.println("Now Closing window");
    isWindowOpen = false;
  }
    // Open window
  } else if (!isWindowOpen){
    if(temperature > maxTemperature){
    servo.write(angle*6);
    windowOpenDateTime = DateTime(now);
    isWindowOpen = true;
  }
    if (compareTime(windowOpenDateTime+ TimeSpan(0,0,0,windowOpeningInterval),now) == -1) {
      servo.write(angle*6);
      windowOpenDateTime = DateTime(now);
     Serial.println("Opening window at interval time");
     isWindowOpen = true;
    }
  }
}
                               
void ShouldThereBeLight(){
  int isThereMotion = digitalRead(motionPin);;
  if (now.hour() > stopNightTime && now.hour() < startNightTime ) {
    if(isThereMotion == HIGH ) { 
      Serial.println("Is there motion? Yes");
      digitalWrite(lightPin,HIGH);
      }
      
    if(isThereMotion == LOW ) { 
      Serial.println("Is there motion? No");
      digitalWrite(lightPin,LOW);
      }
  } else { digitalWrite(lightPin,LOW); }
      
}

int compareTime(DateTime time1, DateTime time2) {
  if(time1.hour() > time2.hour()) {
    return 1;
    }
  else if(time2.hour()> time1.hour()) {
    return -1;
    }
  else {
    if(time1.minute() > time2.minute()) {
      return 1;
      } else if(time2.minute()> time1.minute()) {
        return -1;
      }
   else {
    if(time1.second() > time2.second()) {
      return 1;
      } else if(time2.second()> time1.second()) {
    return -1;
      }
    }
    return 0;
    }
}

void printDateTime(DateTime time) {
    Serial.print(time.hour());
    Serial.print(":");
    Serial.print(time.minute());
    Serial.print(":");
    Serial.println(time.second());
  }

void printTemperature() {
    Serial.print("Temperature: ");
    Serial.println(temperature);
  }

void setupRtc() {
   while (!Serial); // for Leonardo/Micro/Zero
    if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
   // if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
   // following line sets the RTC to the date & time this sketch was compiled
   // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    rtc.adjust(DateTime(2021,04,28,12,0,0));
   // }
  }

    void printsWindow() {
    Serial.print("Is window open? ");
    if(isWindowOpen){
        Serial.println("Yes");      
      } 
    if(!isWindowOpen) {
        Serial.println("No");
      } 
    Serial.print("OpenTime: ");
    printDateTime((windowOpenDateTime+ TimeSpan(0,0,0,windowOpeningInterval)));
   }

   void setTemperature() {
      if(dht.temperature != -999) {
        temperature = dht.temperature -4;
      }
   }
  

Output fra consolen

På billedet overfor ses et output fra konsollen, som vi har brugt til at debugge programmet. Her ses et eksempel hvor vinduet bliver åbnet, for at få frisk luft ind i lokalet, i demoen en gang i minuttet, normalvis en gang i timen, trods maks temperatur på 24 grader ikke er nået.

Dette print viser at når temperaturen er over 23 grader, åbner vinduet, og ventilatoren tændes.

Flow og tilstandsdiagrammer

Funktioner

Programmet har 2 hovedfunktioner; styring af lys og styring af temperatur. Lyset tændes på baggrund af tidspunktet på dagen. Hvis det for eksempel er et kontor, skal der ikke være tændt lys om natten. Lyset styres også af en bevægelsessensor, så der ikke er lys, hvis der ikke er nogen i rummet. 

Temperaturen kan reguleres ved hjælp af at åbne/lukke vinduer og tænde/slukke for en ventilator. En temperatursensor styrer hvorvidt, der er behov for at regulere temperaturen. Hvis det ikke er for varmt, så åbnes vinduet stadig med et regelmæssigt interval for at sikre et godt indeklima. 

Prioriteringer

Der er ikke som sådan indbygget prioriteringer i programmet. Der burde nok være noget sikring, der gør at ing slukkes som default. 

Opbygning af den samlede fysiske prototype

Hvordan er samspillet mellem mekanik, elektronik og software?

Koden har tre centrale metoder. En til hver aktuator; lys, vindue og ventilator. Hver metode håndterer logikken for hvorvidt aktuatoren skal være tændt eller slukket. 

Lys

Arduinoen outputter strøm til en modstand og en lysdiode. Efter lysdioden er der en transistor. Transistoren styres af photoresistoren. Photoresistoren indgår i en spændingsdeler sammen med en 25 kΩ modstand for at sikre, at transistoren for den rigtige spænding. 

Vindue

Vinduet styres af en servomotor, som er koblet direkte i arduinoen. En servomotor har tre pins; 5V, ground og signal.

Ventilator

Ventilatoren er bare en simpel DC-motor, som er får sine 5V direkte fra Arduinoen. 

Tid

Tiden styres af et RTC modul, som bruger I2C. Den kobles til Arduinoen i SCL og SDA inputs. 

Bevægelsessensor

Bevægelsessensoren outputter direkte til Arduinoen, som bruger det til at vurdere om lyset skal tændes. Bevægelsessensoren kan indstilles til at outputte i længere tid efter en registreret bevægelse for at styre hvor længe lyset skal forblive tændt. 

Konklusion

hvor godt løser jeres løsning de oprindelige problemstillinger?

Løsningen virker godt med at regulere temperaturen. Vinduet åbner og lukker som ønsket. Ventilatoren kører også som ønsket. Lyset tænder også, når der er bevægelse i rummet. Vinduet åbner også med et vist interval selvom temperaturen ikke er for høj, så et ordentligt indeklima vedligeholdes.

Der mangler at blive implementeret ordentlig håndtering af strømsvigt, så for eksempel vinduet ikke bliver efterladt åbent. 

Perspektivering

Hvad kan man gøre for at gøre den bedre?

Knapper til manuelt at interagere med systemet ville nok være at foretrække, hvis det skulle bruges i virkeligheden. Alle delene ville man nogle gange gerne aktivere uden for de definerede situationer. Måske har man brug for et mørkt rum eller man har lavet mad og der skal luftes ud. 

More

Smart Vindue

Lavet af Alexander Jessen, Henrik Hansen og Mikkel Abildholt

Brug en motor, temperatursensor, lyssensor, vippe sensor mm. til at bygge et smart vindue, der sørger for et godt indeklima, er energieffektivt og beskytter mod røveri.

Til denne opgave kigger vi på, at forbedre indeklimaet for bla. studerende som sidder hjemme med online undervisning. Man kan nemt blive fortabt i sit studie, særligt om sommeren kan det gå hen og blive for varmt, hvis man glemmer at åbne et vindue. Derfor vil vi gerne udvikle et smart system, som kan regulere et rums temperatur ved automatisk at åbne og lukke et vindue, afhængigt af den målte temperatur i rummet, såvel som solindfald. Løsningen kommer desuden med et display, til at vise temperatur, samt sikring mod indbrud.

Stykliste

  • 1 x Arduino Uno board
  • 1 stk. Papkasse af cirka 28 cm x 38 cm
  • 1 x Phototransistor
  • 1 x DC motor
  • 1 x L293DNE H-Bro
  • 1 x TMP36 Temperature sensor
  • 1 x BL-XT660 Vippe sensor
  • 1 x I2C LCD
  • 1 x Rød LED
  • 1 x Active Buzzer
  • 2 x 10kΩ Modstand
  • 1 x 220Ω modstand

Beskrivelse af nøglekomponenter

Temperatursensor (TMP36)

Denne type temperature sensor, er en lav volt precisions sensor, som måler temperaturen i celsius. Dette gør den ved at lave et volt output som er proportional med temperaturen i celsius. Denne type sensor kan måle temperaturer mellem -40℃ til +125℃. Den tager en spænding på min. 2.7V og max. 5.5V. Sensoren giver et output på 750 mV når den måler en temperatur på 25°C. Ved brug af en 5V arduino kan man bruge de følgende ligninger for at omregne den analog måling til en temperatur.

Konverter analog værdi mellem 0-1023 til spænding på 0-5000 mV:
Spændingen ved pin i milliVolt = (analog værdi) * (5000/1024)

Konverter spænding til temperatur i celsius:
Temperatur i celsius = [(analog spænding i mV) – 500] / 10

Nedenfor ses et Tinkercad setup som styrer 3 LED’er, afhængigt af målingen fra temperatursensoren. Det tre LED’er lyser op ved forskellige temperaturmålinger, navnligt blå ved 15-20℃, grøn ved 20-25℃ og rød ved 25-30℃. Koden findes i bilag.

Vippe sensor (BL-XT660)

Denne type vippe sensor fungere ved at den har 4 ben, som hver rammer en bold. Denne bold triller rundt inde i en lille plastkasse. Når sensoren bliver vippet under 45°, vil den være en slukket tilstand, da ingen af benene vil ramme bolden. Ud over dette kan den drejes 360° rundt. Den tager en spænding på under 12V.

Phototransistor (HW5P-1)

Phototransistor, er en variabel modstand. Det vil sige, at den ændre sin indre modstand, afhængigt af, hvor meget lyst den opfanger. Denne type phototransistor kan tage en spænding på 3 – 15V.

DC motor

Denne type DC motor har et max RPM på 6100, ved 30g. Den tager en max spænding på 6.0V.

H-Bro (L293DNE)

Denne type H-Bro er en høj volt, høj strømstyrke med 4 kanaler, som er designet til at køre inducerende belastning såsom DC motorer, og skifte strøm transistorer. Den tager en spænding på max. 7V.

LCD display 16×2

Et LCD display bruges i dette projekt til at udskrive information fra relevante sensorer. Displayet er 16×2, hvilket betyder at det har 16 kolonner og 2 rækker. Dette giver displayet (16×2) 32 karakterer. Hver karakter består af (5×8) 40 pixels. Dette giver tilsammen displayet (32×40) 1280 pixels at håndtere. Grundet kompleksiteten af dette kommer displayet med en I2C interface påført. Interfacen gør det muligt at kommuniere med displayet serielt. Nedenfor ses billeder af en delløsning hvor displayet bruges til at udskrive antallet af sekunder siden sidste reset. Desuden bruges et potentiometer til at styre kontrasten af den udskrevne tekst. Koden findes i bilag.

Kredsløbsdiagram

Step-by-step til arduino setup

Her er vores opstilling af kredsløbet i tinkercad

Gennemgang

  • Step 1: Tilslut din Arduino Uno til et breadbord. Her benyttes 5V outputtet fra Arduinoen, som tilsluttes til den positive linje på breadbordet. Ground på Arduinoen, bliver tilsluttet den negative linje på breadbordet.
  • Step 2: Tilslut det sekundære breadbord, ved at tilslutte de positive og negative linjer sammen.
  • Step 3: I det første breadbord, tilslut den første 1kΩ modstand til den negative linje på det første breadbord. Sæt den anden ende i linje j2 på breadbordet.
  • Step 4: På linje i2, tilsluttes en ledning, som føre hen til digital input 5 på Arduinoen.
  • Step 5: på linje f2-3 og g2-3, placeres tilt sensoren. Dette skal gøres med 4 hun-til-han ledninger.
  • Step 6: Sæt nu en ledning, som går fra linje j3, hen til den positive linje på breadbordet.
  • Step 7: Fra linje f10-17 og linje e10-17, placeres H-broen.
  • Step 8: H-broen skal have nogle ledninger tilsluttet, før DC-motoren kan tilsluttes. De følgende ledninger skal placeres: fra den positive linje på breadbordet, til j10. Fra j11 skal der gå en ledning til digital 2 på Arduinoen. Fra både j13 og j14, skal der gå en ledning til den negative linje på breadbordet. Fra g16 skal der gå en ledning til digital 4 på Arduinoen. Fra g17 skal der gå en ledning til digital 8 på Arduinoen. Til sidst skal der gå en ledning fra d17 til den positive linje på breadbordet.
  • Step 9: Tilslut nu DC-motoren. Her skal den negative ledning sidde i g12, og den positive skal sidde i g15.
  • Step 10: Tilslut nu den anden 1kΩ modstand, fra den negative linje til j24. For enden af denne modstand, i24, skal der gå en ledning til A1 på Arduinoen. Til højre for modstanden, j25, skal der gå en ledning til den positive linje.
  • Step 11: i f24 og f25, skal Phototransistoren sidde.
  • Step 12: Fra e22, skal der gå en ledning til den negative linje på breadbordet. Fra e27 skal der gå en ledning til digital 9. For enden af disse, c22 og c27, skal buzzeren sidde.
  • Step 13: fra den positive linje, skal der gå en ledning til j27, fra j28 skal der gå en ledning til A0 på Arduinoen. fra j29, skal der gå en ledning til den negative linje.
  • Step 14: I f27-29, skal temperatur sensoren sidde.
  • Step 15: Nu bevæger vi os over til breadbord nr. 2. Tilslut en ledning i digital 10. Denne ledning skal tilsluttes det lange ben på LED’en (Anoden). Fra det korte ben (Katoden), skal der tilsluttes en ledning, som føre hen til den negative linje på breadbordet.
  • Step 16: Her skal der tilsluttes en masse ledninger. Fra e14, skal der gå en ledning til den negative linje. fra e15, skal der gå en ledning til den positive linje. Fra e17, skal der gå en ledning til digital 13 på Arduinoen. Fra e18 skal der gå en ledning til den negative linje. Fra e19 skal der gå en ledning til digital 12 på Arduinoen. Fra e24 skal der gå en ledning til digital 11 på Arduinoen. Fra e25 skal der gå en ledning til digital 4 på Arduinoen. fra e26 skal der gå en ledning til digital 7 på Arduinoen. Fra e27 skal der gå en ledning til digital 6 på Arduinoen. fra i28 skal der sidde en 220Ω modstand, som går til den positive linje. Fra h28 skal der gå en ledning til e28. Til sidst skal der gå en ledning fra e29 til den negative linje på breadbordet.
  • Step 17: Tilslut nu LCD’en, så GND sidder i a14, og den sidste pin på LCD’en sidder i a29.
  • Step 18: Tilslut den positive ende af potentiometeret til den positive linje på breadbordet. Den negative ende af potentiometeret skal tilsluttes den negative linje på breadbordet.
  • Step 19: Tilslut det midterste ben fra potentiometeret til e16 på breadbordet.

Forklaring af koden

Koden herunder er inddelt i afsnit, hvori der følger en forklaring af den specifikke kode nedenunder. Først starter vi med deklarationer af den nødvendige data der skal bruges.

#include <LiquidCrystal.h>
 
LiquidCrystal lcd(6,7,4,11,12,13);
 
const int controlPin1 = 2;
const int controlPin2 = 3;
const int enablePin = 8;
const int ldrSensorPin = A1; //lyssensor (phototransister)
const int tempSensorPin = A0;
const int tiltSensorPin = 5;
const int ledPin = 9;
const int buzzerPin = 10;
 
int tempSensorValue = 0;
int ldrIndoorSensorValue = 0;
int ldrSensorValue = 0;
int tiltSensorValue = 0;
int motorEnabled = 0;
int motorSpeed = 0;
int motorDirection = 1;
 
float voltage = 0;
float temp = 0;
 
bool windowStateOpen = false;
bool expectedWindowState = false;

Først importeres et bibliotek for LCD displayed, hvilket tillader os at bruge prædefineret funktioner til at printe beskeder på skærmen. Derefter defineret hvilke pins LCD’en er sat til på arduionen. Herefter defineres der alle de forskellige data’er, startende med konstanterne, hvilke er de værdier vi ikke vil have skal ændre sig gennem koden. Disse bliver brugt til at navngive de tilsluttede pins hvor både kontakten til h-broen, og derved motoren findes, samt sensorerne. Herefter deklareres der de integers som skal holde værdierne af målingerne, efterfulgt at floats og bools.

void setup(){
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.clear();
 
  pinMode(tiltSensorPin, INPUT);
  pinMode(controlPin1, OUTPUT);
  pinMode(controlPin2, OUTPUT);
  pinMode(enablePin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(enablePin, LOW);
 
}

Dette afsnit bruges til at definere hvilken type vores pins skal være. Her sættes de pins sensorerne sidder i til at være input, da de skal modtage data. De pins som sidder til h-broen bliver sat til output, da de skal sende data. Derefter startes der med at sende en besked til h-broen, hvor den bliver sat til at være slukket. Dette gøres for at undgå motoren starter med at kører uønsket.

void loop(){
  tempSensorValue = analogRead(tempSensorPin);
  ldrSensorValue = analogRead(ldrSensorPin);
  tiltSensorValue = digitalRead(tiltSensorPin);
 
  voltage = (tempSensorValue/1024.0) * 5.0;
  temp = (voltage - 0.5) * 100;
 
  if(tiltSensorValue == 0){
  	windowStateOpen = false;
	} else {
  	windowStateOpen = true; 
	}
  
  if(windowStateOpen != expectedWindowState){
	delay(5000);
    if(!expectedWindowState){
  	lcd.clear();
      lcd.print("INDBRUD");
      tone(buzzerPin,3000,5000);
      digitalWrite(ledPin, HIGH);
	} else {
  	lcd.clear();
      lcd.print("I AM BROKEN");
      digitalWrite(ledPin, HIGH);
	}
  } else

Herfra starter den del af koden som kontinuerligt køres når der er strøm til boardet. Først hentes og gemmes der værdierne af sensorerne, hvorefter værdien for temperatursensoren bliver omregnet til den tilsvarende temperatur. Dertil tjekkes der for hvilken tilstand vinduet er i, om det er åbnet eller ej. Det er tilt-sensorens ansvar, og hvis vinduet er mere end 45 grader åbent sætter koden værdien til at være sand. Under 45 grader tæller vinduet som lukket, hvilket er et sikkerhedsbrug som kunne fikses ved brug af et accelerometer i stedet for tilt-sensoren.

Herefter begynder den primære del af loopet som styrer hvornår motoren skal kører. Først tjekkes der dog om vinduets tilstand er som den forventede tilstand. Dette gøres for at tjekke om der har været indbrud, da tilstanden af vinduet burde tilsvare tilstanden som koden forventer den i. Tilt sensoren bruges her til at være sikkerhedskontrollen.

   }    
   if(temp > 27){
        digitalWrite(controlPin1, HIGH);
        digitalWrite(controlPin2, LOW);
   	   analogWrite(enablePin, 200);
        expectedWindowState = true;
    	   delay(250);
        analogWrite(enablePin, 0);
	   } else if ( temp < 21 && ldrSensorValue < 800){
        digitalWrite(controlPin1, LOW);
        digitalWrite(controlPin2, HIGH);
        analogWrite(enablePin, 200); 
        expectedWindowState = false;
    	   delay(250);
        analogWrite(enablePin, 0);
	   } else if (ldrSensorValue >= 800 && temp > 20){
        digitalWrite(controlPin1, HIGH);
        digitalWrite(controlPin2, LOW);
        analogWrite(enablePin, 200);
        expectedWindowState = true;
    	   delay(250);
        analogWrite(enablePin, 0);
	   } else {
        digitalWrite(controlPin1, LOW);
        digitalWrite(controlPin2, HIGH);
        analogWrite(enablePin, 200);
        expectedWindowState = false;
    	   delay(250);
        analogWrite(enablePin, 0);
	}

Denne del af loopet tjekker hvilken temperatur der er i rummet, samt hvor meget lysindfald der er udefra. Ud fra disse to værdier vil vinduet enten åbne eller lukke. Værdierne der bestemmer hvornår koden køres er op til brugeren selv at bestemme, dog synes vi at disse grænser passede fint til vores behov.

    lcd.setCursor(0,0);
    lcd.print("Temperatur: ");
	lcd.print(temp);
    lcd.setCursor(0,1);
	if(windowStateOpen){
      lcd.print("Window: Open");
	} else if(!windowStateOpen){
      lcd.print("Window: Closed");
	}
  }
 
  delay(3000);
}

Her sendes data til LCD-displayed om hvad den skal vise. I dette eksempel vises temperaturen samt vinduets tilstand. Herefter er der et 3-sekunders delay for at få opsætningen til at kører mere flydende.

Flow/Tilstandsdiagram

Flowdiagram

Tilstandsdiagram

Guide til konstruktion af pap-model

Step-by-step guide til mål og kasse udskæringer

  1. Tegn 4 linjer. 2 af linjerne skal være ca. 6,5cm og 2 af linjerne skal være ca. 8cm.
  2. Skær et hul i pappet, enten med en kniv eller en saks.
  3. Tag det lille stykke pap, og skær et hul i midten af pappet, som er ca. 0,5cm x 0,5cm. Her kommer vippe sensoren til at være.
  4. I toppen af det udskårne hul, skæres der et udsnit på 4,5cm x 2,5cm. I dette udsnit skal DC-motoren placeret.
  5. Sæt det lille stykke pap fast på DC-motoren (Gerne på et lille plast stykke, som vist på billederne)
  6. Ved siden af hullet i papkassen, bliver Phototransistoren placeret.
  7. Vend derefter papkassen 90 grader, og skær et 2,5cm x 7,5cm udsnit. Her kommer LCD’en til at sidde.
  8. Ved siden af dette udsnit, omkring 2cm mellemrum, lave her et udsnit der er 1cm x 1cm. Dette hul skal bruges til Potentiometeret.

Muligheder for viderebygning

I fremtidige versioner af robotten, kunne man eventuelt tilføje en sensor, som kan registrere, om glasset i vinduet bliver smadret, da robotten lige nu, kun kan finde ud af om vinduet bliver åbnet uden at robotten har startet med at åbne vinduet.

Ud over dette, kunne man også tilføje en knap, så man kan åbne vinduet manuelt, eksempelvis hvis nu at man har brændt noget mad på ell.lign. Så man kan lufte ud, uden at robotten selv mener hvornår det korrekte tidspunkt, at åbne vinduet er på.

En anden tilføjelse kunne være, at tilføje en fugtigheds sensor. Dette ville være en god tilføjelse, hvis nu man eksempelvis har været i bad el.lign. og derfor har brug for at få åbnet et vindue, da der hurtigt kan godt hen og føles meget klamt i boligen.

Konklusion

Video af roboten

Bilag

Link til test videoer

https://drive.google.com/drive/folders/1U3qPkoeoxVOzz-c5p8LrIE2ZF_uyz6CZ?usp=sharing

Temperatursensor delløsning kode

int baselineTemp = 0;
int val = 0;

void setup()
{
  pinMode(A0, INPUT);
  Serial.begin(9600);

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
}

void loop()
{
  // set threshold temperature to activate LEDs
  baselineTemp = 15;

  val = analogRead(A0);
  float mv = (val/1024)*5000;
  float celsius = (mv-500)/10; 
  Serial.print("Temperature = ");
  Serial.print(celsius);
  Serial.print(" C");
  Serial.println();
  
  if (celsius < baselineTemp) {
    digitalWrite(2, HIGH);
    delay(300);
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
  }
  if (celsius >= baselineTemp && celsius < baselineTemp + 5) {
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
  }
  if (celsius >= baselineTemp + 5 && celsius < baselineTemp + 10) {
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
  }
  if (celsius >= baselineTemp + 10 && celsius < baselineTemp + 15) {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
  }
  if (celsius >= baselineTemp + 15) {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    delay(300);
    digitalWrite(4, LOW);
  }
  delay(300); // Wait for 300 millisecond(s)
}

LCD display delløsning kode

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
  // set the cursor to column 0, line 1
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
}

More

Lockbox

Lavet af Marcus Pedersen og Jakob Schledermann.

Introduktion

I dette projekt har vi konstrueret en låseboks der kun åbner når en række krav tilfredsstilles. Dette kan gavne hvis man har værdier man vil låse væk, men man ikke stoler på de mere traditionelle låsekasse løsninger der allerede er på markedet. Vi har altså valgt at lave en samlet løsning der tager mange forskellige elementer og samler dem under et projekt. Vi mener at sikkerhed i hjemmet er vigtigt og derfor kan denne løsning bringe inspiration til andre sikkerhedsmæssige projekter i hjemmet.  

Kredsløb

Vi har valgt at fokusere på komponenter der kan benyttes i et sikkerhedssystem og derfor har vi benyttet følgende komponenter:

  • 2 stk Arduino uno
  • LCD1602 module
  • Membrane switch module
  • Rotary Encoder
  • Passive buzzer
  • LDR
  • DC motor 
  • L293D
  • LED

Først og fremmest har vi valgt at benytte to forskellige arduino til løsningen. Dette valg blev truffet på baggrund af vi gerne ville benytte membrane switch modulet og samtidigt også ville benytte en LCD skærm, hvorfra der ikke er nok digital porte til at understøtte begge muligheder med en arduino uden at prototype expansion modulet i brug. Vi beslutted derfor at dele ansvarsområderne op mellem de to arduinoer så de hver især stod for at håndtere specifikke dele af koden. LCD display ville vi gerne benytte da vi havde eftersom at det er vigtigt at returnere data til brugeren af et sikkerhedssystem, således at man kan se de input der bliver givet til systemet. Membrane switch modulet er oplagt til at skrive koder ind og det er dette det bliver benyttet til. Vi har flere gange gået frem og tilbage mellem rotary encoder og et potentiometer til vores løsning. Vi besluttede at benyttet rotary encoder da der er mere frihed i hvordan den skal operere i forhold til det mere begrænsede potentiometer. Til sidst besluttede vi os for at bruge en dc motor der bliver kontrolleret af L293d controlleren. Dette er til at styre løse mekanismen i systemet. Udover de ovenstående elementer bliver der brugt status leder til at vise tilstanden af systemet.

Video

DC motor og H-bro

For at kunne åbne og lukke for boksen anvender vi en DC motor. DC motoren omdanner elektrisk energi om til mekanisk energi for at skubbe låsemekanismen til siden. For at sørge for at dc motoren kan dreje begge veje, altså både åbne og lukke, anvender vi en H-bro. 

LCD display

Vores LCD display hjælper brugeren med at give aktivt feedback når de prøver at åbne boksen. På displayet vises brugerens input, hvilket består af pin koden de indtaster og rotary encoder værdien. Der bliver kun vist en af gangen så boksen prioriterer at vise den indtastelsesmetode der sidst blev brugt.

LDR

For at åbne boksen kræver det også at man lyser lys på en LDR sensor. Sensoren virker ved at mere lys giver mindre modstand, så man ender med at få et analog input. Til boksen har vi valgt at LDR værdien skal være over en bestemt værdi for at give adgang til brugeren.

Rotary encoder

I vores projekt bliver vores rotary encoder brugt til at give adgang til boksen. Et af kravene for at åbne boksen er at rotary encoder værdien er den rigtige værdi som allerede er defineret. Grunden til at vi valgte at bruge en rotary encoder i stedet for en potentiometer er dens digitale output gør det nemmere at arbejde med i softwaren.

LED indikatorer

For at indikere om boksen er låst eller åben har vi anvendt rød og grøn LEDer, hvor grøn indikerer åben state og rød indikerer åben state.

Buzzer

Når den rigtige kode er indtastet på keypadden, rotary encoderen peger på den rigtige værdi og LDR sensoren får den rigtige mængde lys, åbner boksen. Når boksen bliver åbnet beeper buzzeren en “boksen er nu åben” melodi, men hvis man fejler åbning requirements beeper den en “forkert kode” melodi.

Kode

Vores kode består af 2 filer, eftersom hver arduino kører deres egen fil. Den ene arduino registrere input fra membrane switches, og sender dataen videre ved hjælp af UART over RX og TX pins på arduino boardet. 

Pin kode arduinoen:

Den anden arduino består af resten af koden og taler også med den anden arduino for at binde det hele sammen. Til at starte med har vi defineret porte og globale variabler:

Derefter kommer setuppet hvor vi har markeret hvilke pins der skal hvad. Grunden til at vi ikke har alle de pins vi bruger i setup er grundet mange af de libraries vi anvender har predefinet om de er in eller outputs.

Loop funktionen kører igennem og tjekker om alle låsemekanismer er låst op ved at få input fra sensorerne, og hvis ikke alle låse er åbne, så sørg for at boksen stadig er lukket.

Opbygning af den samlede fysiske prototype

Den samlede fysiske prototype er opbygget af elektronikkomponenter beskrevet i tidliger afsnit, samt mekaniske elementer der spiller sammen til at samle et fuldendt system. Prototypen består af de elektroniske dele samt en æske til at have delene i, og til sidst en 3D printet låsemekanisme der har kan låse boksen men en deadbolt. Låsemekanismen er placeret på en hældning sådan at der konstant skal leveres strøm til dc motoren for at opretholde dens placering sådan at den undgår at falde tilbage pga den relative lille modstand sår systemet er låst. Alle elementerne er placeret inde i boksen hvorfra displayet, membran switch, rotary encoder er placeret yderst på boksen sådan at man kan interagere med systemet. 

Konklusion

Vores løsning retter sig efter problemstillingen ved at skabe et sikre hjem. Selve sikkerhedssystemet behøver ikke at være bundet til voksen og kan benyttes i ander instanser såsom en smartere dørlås eller lignenede. Alle kravene er blevet overholdt og samlet set mener vi at løsninger bringer noget til det moderne smart home. 

Perspektivering

Der er flere elementer som vi havde tænkt at tilføje i fremtiden som ekstra aller alternative løsninger, nogle af de elementer der kunne tilføjes er RFID læseren og et mere udbredt alarm system. 

Hele Koden

Github link: https://github.com/j-winkel/Robottek-PF2.git

More

PF2: Sentry Intruder Prevention

Gruppemedlemmer

Jens Kristian Vitus Bering – jberi18@student.sdu.dk

Karl Amadeus Finsson Hansen – karlh18@student.sdu.dk

Pradeep Thayaparan – prtha18@student.sdu.dk

Introduktion

Corona tiderne har vist sig at have været yderst effektive mod indbrud, da der har været markant lavere indbrud end de par sidste år. Denne positive spiral kan snart ændres, når landet lukker mere op efter flere folk er blevet vaccineret. Derfor har gruppen lavet et alarmsystem, der forsøger, at skabe mere sikkerhed i hjemmet.

Videogennemgang af løsningen

Opbygning af hardware

Figur 1 – Fritzing tegning af Sentry Intruder Prevention

Anvendte komponenter

SensorActuatorAndet
Motion SensorDC MotorH-Bro
ThermistorPassive BuzzerPower Supply Module
RFIDLCDResistor: 10k OHMPotentiometer(10k)
Tabel 1 – Anvendte Komponenter

Sentry Intruder Prevention-Systemet bruger en papkasse som erstatning for et hus. For at lave systemet skulle systemet primært udføre tre operationer. Systemet skulle opfange, at der var nogen i huset. System skulle vide hvordan den skulle udløse en alarm og systemet skulle vide, hvornår det skulle udløse alarm. Figur 1 samt Tabel 1 giver overblik over de anvendte komponenter i systemet.

Er der nogen i huset?

Den første del var, at opfange at der var nogen inde i rummet. Gruppen stod overfor et valg af brugen af en PIR Motion Sensor, som er generel sensor der kan opfange bevægelser foran sig eller en Ultrasonic Sensor som kan måle afstanden fra et objekt. Da gruppen blot ville vide, om der var nogen i rummet og ikke om, hvor tæt man var, valgte gruppen at gå med PIR Motion Sensoren og blev sat på indersiden af vores paphus med retning mod døren.

Hvornår skal der udløses alarm?

Den anden del vat finde ud af, hvornår en alarm skulle udløses eller snarere hvornår den ikke skulle udløses. Til dette formål stod valget mellem et slags kode system såsom indtaste en pinkode ved hjælp af en Membrane Switch eller et kort system som som ville tillade adgang til huset uden at udløse alarmen ved at bruge et Radio Frequency Identification modul (RFID). Valget faldt på RFID da dette var lidt mere spændende at arbejde med og blev sat uden på kassen lige ved dør indgangen. For at komme ind i huset skulle man derfor have et gyldigt kort. Hvis man ikke havde det og gik igennem huset ville PIR Motion Sensoren registrere, at der var nogen inde i huset når der ikke skulle være nogen og udløse alarm. 

Hvordan skal alarmen udløses? 

Den sidste del var, hvad der ville ske, hvis vores PIR-Motion Sensor registrerer nogen bevægelse inde i paphuset når den ikke burde. Til dette formål blev der anvendt en DC Motor til at trække en snor op foran døren, og en Passive Buzzer som alarmlyd.

Skærm og Temperatur 

Udover de tre væsentlige dele var der også nogle mindre ting at tage fat om. Brugen af en DC Motor krævede, at Power Supply Module til at være den primære strømforsyning til systemet samt en LCD-skærm til at vise temperatur fra Thermistoren såfremt, udover at også vise “Access Granted” og “Access Denied” på skærmen når kortet blev brugt.

Kredsløbsdiagram

På Figure 2 ses kredsløbsdiagrammet for Sentry Intruder Prevention. Kredsløbs diagrammet viser det elektriske kredsløb mellem komponenterne. Via diagrammet er det muligt, at visualisere hvordan strømmen går komponent til komponent og hvilken indflydelse det har.

Figur 2 – Kredsløbsdiagram af Sentry Intruder Prevention

Opbygning af program

Sentry Intruder Prevention er lavet således, at for at komme ind i huset skal man scanne sit kort ind. Hvis der ikke skannet et gyldigt kort og vedkommende er gået ind i gennem døren, så vil systemet tolke dette som et indbrud og udløse alarmen.

Figure 3 – Flow Diagram of Sentry Intruder Prevention

Start

Ovenstående flow diagram på figur 3 viser overordnet, hvordan adfærden i systemet. Ved Start konfigurerer projektet alle sine moduler og gør systemet klar til at køre.

Card found

Som nævnt er det nødvendigt at anvende et brugbart kort for at komme igennem huset. Når du lægger kortet på RFID scanneren vil denne tjekke om det er gyldigt. Det første tjek i denne process er om der er mere en et kort foran RFID scanneren. Hvis der er mere end et sker et “collision” og det vil blive afvist. Hvis kun et kort vil det gå videre i processen vil at læse kortets ID. Hvis kortet er gyldigt vil give “Access Granted” og vedkommende har 10 sekunder at gå ind i huset før alarmen går i gang igen. Hvis der ikke var et gyldigt kort ID ville det sige “Access Denied” på LCD-skærmen og dermed afvise personen at komme ind.

Card Not Found

Hvis programmet ikke er i “Access Granted” tilstand og døren alligevel går op vil PIR Motion Sensoren opfange bevægelse i rummet og udløse alarmen. Alarmen er sammenkobling af en Passive Buzzer som udløser støj og en DC Motor der strammer et reb op således, at den nægter vedkommende at gå igennem døren.

Kode

Den nedenstående kode er struktureret således, at metoderne er deklareret i toppen af siden imens implementationen af den ligger længere nede for at give indblik.

#include <SPI.h>
#include <RFID.h>
#include <LiquidCrystal.h>

//---------------------------------------Component Pins & Method Declarations--------------------------//

// DC Motor
int speedPin = 5;
int dir1 = 4;
int dir2 = 3;

void setDCMotorPins();
void setDCMotorSpeedAndDirection(int, char);

//Passive Buzzer
int passiveBuzzerPin = 8;

void alarmBuzzerSound();

// Pir Motion Sensor
int pirPin = 2;
int pirSensorValue;

//Thermistor
int thermistorPin = A5;
int temperatureSensorValue;

void calcTemp();

//LCD
LiquidCrystal lcd(7, A0, A1, A2, A3, A4);

// RFID
RFID rfid(10, 9);
unsigned char status;
unsigned char str[MAX_LEN];
String accessGranted[2] = {"131212513717"};
int accessGrantedSize = 2;

void checkCardRFID();
//------------------------------------------Arduino Setup & Loop------------------------------------//

void setup()
{
  setDCMotorPins();
  Serial.begin(9600);
  SPI.begin();
  rfid.init();

  lcd.begin(16, 2);
  pinMode(pirPin, INPUT);
}

void loop()
{
  checkCardRFID();
  lcd.clear();
  lcd.setCursor(0, 1);
  delayMicroseconds(2);
  pirSensorValue = digitalRead(pirPin);
  if (pirSensorValue == HIGH)
  {
    alarmBuzzerSound();
    setDCMotorSpeedAndDirection(255, 'r');
    lcd.clear();
  }
  calcTemp();
}
//-------------------------------------Function Implementation-------------------------------------------//

void checkCardRFID()
{
  if (rfid.findCard(PICC_REQIDL, str) == MI_OK) //Wait for a tag to be placed near the reader
  {
    Serial.println("Card found");
    String temp = "";                //Temporary variable to store the read RFID number
    if (rfid.anticoll(str) == MI_OK) //Anti-collision detection, read tag serial number
    {
      Serial.print("The card's ID number is : ");
      for (int i = 0; i < 4; i++) //Record and display the tag serial number
      {
        temp = temp + (0x0F & (str[i] >> 4));
        temp = temp + (0x0F & str[i]);
      }
      Serial.println(temp);
      checkAccess(temp); //Check if the identified tag is an allowed to open tag
    }
    rfid.selectTag(str); //Lock card to prevent a redundant read, removing the line will make the sketch read cards continually
  }
  rfid.halt();
}

void checkAccess(String temp) //Function to check if an identified tag is registered to allow access
{
  boolean granted = false;
  for (int i = 0; i <= (accessGrantedSize - 1); i++) //Runs through all tag ID numbers registered in the array
  {
    if (accessGranted[i] == temp) //If a tag is found then open/close the lock
    {
      Serial.println("Access Granted");
      lcd.print("access granted");
      granted = true;
      delay(10000);
    }
  }
  if (granted == false) //If the tag is not found
  {
    lcd.print("Access Denied");
  }
}

void setDCMotorPins()
{
  pinMode(speedPin, OUTPUT);
  pinMode(dir1, OUTPUT);
  pinMode(dir2, OUTPUT);
}

void setDCMotorSpeedAndDirection(int speed, char direction)
{
  if (direction = 'r')
  {
    digitalWrite(dir1, LOW);
    digitalWrite(dir2, HIGH);
    analogWrite(speedPin, 255);
  }
  else if (direction = 'l')
  {
    digitalWrite(dir2, LOW);
    digitalWrite(dir1, HIGH);
    analogWrite(speedPin, 255);
  }
}

void alarmBuzzerSound()
{
  for (int i = 0; i < 255; i++)
  {
    analogWrite(passiveBuzzerPin, i);
  }

  for (int i = 255; i > 0; i--)
  {
    analogWrite(passiveBuzzerPin, i);
  }
}

void calcTemp()
{
  lcd.setCursor(0, 0);
  temperatureSensorValue = analogRead(thermistorPin);
  double tempK = log(100000 * ((1024.0 / temperatureSensorValue - 1)));
  tempK = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * tempK * tempK)) * tempK);
  float tempC = tempK - 273.15;
  lcd.print("Temp = ");
  lcd.print(tempC);
};

Uddybende om funktionerne

Der er lavet nogle funktioner som har hver sit ansvar og de beskrevet nedenstående.

setDCMotorPins()-metoden har til ansvar at konfigurere de forskellige pins som DC Motoren anvender.

setDCMotorSpeedAndDirection(int speed, char direction)-metoden har til ansvar at sætte omdrejningshastigheden og  om den skal med eller imod klokken. Den bliver brugt når rebet skal strammes.
alarmBuzzerSound()-metoden har til ansvar at afspille en konstant buzz lyd  ved brug af den Passive Buzzer komponent

checkCardRFID() – Metoden har til ansvar at at læse kort ind på RFID komponentet ved hjælp af et bibiotek som hedder RFID. Den står for at læse det kort man sætter til komponentet og udskrive dens ID i serial, derefter laver den et kald til en funktion som hedder checkAccess()

checkAccess()-metoden har til ansvar at se om det kort man har sat til RFID komponentet godkendt til adgang, det gør den ved at kigge imod et array af godkendte ID’s. Hvis den er godkendt laver den et print til vores LCD skærm hvor der står “Access Granted” og derefter laver den et delay på 10 sekunder som er den tid vores alarmsystem så er slået fra, hvis den ikke er godkendt skriver den “Access Denied” til vores LCD og intet andet sker.

De 4 første funktioner bliver alle kaldt fra vores loop, og det er her selve alarm systemet er skrevet

Opbygning af den samlede fysiske prototype

Før produktet kan blive brugt i praksis måtte gruppen bygge et mini hus ud af pap, for derefter, at demonstrere et rigtigt scenarie med de komponenter, som er blevet beskrevet i forrige afsnit. Figur 4 og 5 viser den fysiske opbygning af produktet. Papkassen skal forestille et hus med en dør. Derudover kan de benyttede komponenter også ses. Bevægelsessensoren var klistret fast på siden af kassen med noget klæbemasse, så den er tættest på døren så muligt og dermed kan registrere noget bevægelse når døren åbnes. På billederne kan DC motoren ses, som er blevet sat sammen med et træstykke, for at kunne vikle tråden sammen, lige så snart, at bevægelsessensoren har registreret noget bevægelse. Produktet udgør også af et Power Supply Module, som skal supplere noget strøm til bla. DC motoren da, arduinoen i sig selv ikke var stærk nok. Den Passive Buzzer er ikke blevet klæbet til væggen på samme måde men er dog placeret i kassen, så den vil kunne afgive lyd. DC Motoren er styret af ved hjælp af en H-bro. Den er placeret direkte i breadboardet, som ligger i kassen. 

Potentiometeret og Termistoren er placeret på breadboardet, men kunne i princippet også være monteret længere væk fra breadboardet for at virkeliggøre scenariet med alarmsystemet, men dette undlod gruppen at gøre, hvilket kan læses i perspektiveringsafsnittet. Det har dog været muligt at få placeret nogle af komponenterne længere væk fra hinanden ved hjælp af female to male ledninger. 

Figur 4 – Indvendigt billede af alarmsystemet i paphuset
Figur 5 – Udvendigt billede af alarmsystemet i paphuset

Billede 5 viser kassen forfra, hvoraf komponenterne LCD display og RFID kan ses. Komponenterne er sat op således, at man kan se dem lige foran døren og dermed få besked lige så snart man har kørt kortet. I kassen er der blevet skåret et lille udsnit, så displayets ledninger kan forbindes til breadboardet, som på den måde kan give et bedre look udefra uden nogen former for ledninger. Samme fremgangsmåde er brugt på RFID.

Konklusion

Gruppen har formået at lave et alarmsystem, hvori alarmsystemet går i gang, hvis man ikke har indtastet sit kort før man går ind gennem døren. Gruppen har derfor delvist nået målet om at lave et hjemmealarm system, men må indrømme, at resultatet ikke er elegant. Systemet har alle komponenterne på plads, men gruppen har måttet lave nogle modifikationer, såsom at lave systemet til en miniature version og yderligere placere komponenter længere ned end oprindeligt planlagt grundet manglende ledninger.

Perspektivering

Overordnet Manglende Lednings Forlængere (Female to Male)

Gruppen ønskede at teste systemet på en normal måde, i en fuld skala udgave således, at det blev brugt ved døren til et hus. På grund af manglen på forlængerledninger (female to male) blev dette desværre ikke en mulighed, og derfor var gruppen nødt til at lave en miniature version af systemet. Og derfor vil flere af underpunkterne understøtte dette overordnede punkt.

LCD ligger langt nede ved døren

Oprindeligt ville gruppen gerne have LCD’en omkring midt dørs højde ved siden af således, at man kunne se temperaturen og om man kunne gå ind gennem døren. LCD ligger så langt nede ved døren fordi den krævede 12 ledninger og hvis de skulle forlænges ville det kræve 12 yderligere og dette havde gruppen ikke til rådighed.

Termistoren & Alarmen ligger bare indenfor huset uden sammenkobling

Alarmen(Passive Buzzer) og Temperaturmåleren(Termistoren) i løsningen ligger bare indenfor huset, men oprindeligt var planen at hænge dem op ved hjælp af klister eller lignende, men grundet manglende ledninger var dette ikke en mulighed.

Måtte skifte første projekt ud

Oprindeligt ville gruppen lave et projekt med en hjemme spritdispenser, hvori den ville have forskellige ekstra funktioner og ikke lukke dig ind i huset før du har sprittet hænder for ellers ville man risikere at udløse en alarm. Gruppen måtte dog desværre konkludere, at 3 servo motorer og en DC motor samlet ikke var stærke nok til at trykke sprit flasken for at få spritten ud af den. Derfor skiftede gruppen over til et alarmsystem og fik brugt flere idéer fra det forrige projekt.

More

CyberHouse

Kevin Lavlund Hansen – kehan18@student.sdu.dk
Rasmus Sjøholm Stamm – rasta17@student.sdu.dk
Benjamin Clement Klerens – bekle18@student.sdu.dk

Vi ville skabe et automatiseret hjem, hvor fokus har været på at gøre dagligdagen nemmere for folk i hustanden. Vi har derfor valgt at inkorporerer 3 forskellige løsninger:

  • Automatic door – Dør der åbner når der er bevægelse foran
  • Air conditioning – Temperatur aktiveret blæser
  • Futuristic alarm clock – Alarm ur

Disse løsninger er beskrevet i hvert sit afsnit og kan bygges på samme breadboard for at få det samlede system.
De kan derfor også fungere uafhængigt af hinanden.

Samlet materiale liste

  • Arduino UNO
  • PIR sensor (HC-SR501)
  • Servo motor (SG90)
  • Termistor
  • Modstand
    • 10k Ohm
    • 2x 220 Ohm
  • NPN Transistor (PN2222)
  • DC Motor 
  • Diode (1N4007)
  • Kondensator
    • 100nf keramisk
  • Rotary Encoder
  • DS1307 (RTC) 
  • LCD1602A
  • Potmeter
    • 10k Ohm
  • Aktiv buzzer

Delløsninger

Automatic door

Materialer

  • Arduino UNO
  • PIR sensor (HC-SR501)
  • Servo motor (SG90)

Komponenter og kredsløb

Denne delløsning automatiserer døråbning som resultat af fysisk bevægelse. Dette opnås vha. En servo motor til at dreje døren om dens aksel, samt en Passive Infrared sensor (PIR), som giver Arduinoen signal, når den registrerer bevægelse. Arduinoen vil herefter give signal til servoen om at åbne døren, samt lukke den efter en sat tidsperiode.

Servo motor

Servoen kan typisk (afhængig af model) rotere 180 grader. Den styres af Arduinoens PWM-pins, hvor signalets duty-cycle afgør motorens vinkel. I denne løsning bruges Arduinoens indbyggede bibliotek Servo.h til at styre servoen, hvilket betyder at vi ikke skal bekymre os om at definere duty cycles, men i stedet bare angive den ønskede vinkelgrad.

PIR sensor

PIR-sensoren virker ved at have en udgående signal-pin som, når bevægelse registreres, sættes højt i et bestemt tidsinterval. Dette signal sættes på en indgående pin på Arduinoen, så den kan aflæses og reageres på. Vi har valgt at bruge en af Arduinoens analoge inputs, så signalet kan aflæses præcist (0-1023), frem for høj/lav.

Sensoren kan indstilles vha. potentiometre, samt tre pins der skal kortsluttes i én af to kombinationer, som sidder på PCB’et. Hvordan disse virker, afhænger af komponentens model, men i vores tilfælde gælder jf. datasheet:

Time delay adjust

Time delay, eller forsinkelse, afgør hvor lang tid signal-pinnen bevares høj ved bevægelse.
Med uret: Højere forsinkelse, maksimum = ca. 5 minutter
Mod uret: Lavere forsinkelse, minimum = ca. 3 sekunder
Indstil på laveste forsinkelse.

Sensitivity adjust

Sensitivity, eller følsomhed, afgør hvor langt sensoren vil registrere bevægelse.
Med uret: Lavere følsomhed, minimum = ca. 3 meter
Mod uret: Højere følsomhed, maksimum = ca. 7 meter
Indstil på laveste følsomhed.

Trigger selection jumper


Indstil på Repeatable Trigger Mode.

Kredsløb

I AutoDesk Tinkercad kan løsningen opstilles og testes som vist:

Løsningens kredsløbsdiagram ser således ud:

Kode

Løsningens kodning er langt fra kompliceret, så her er der ikke meget at snakke om. Den mest essentielle del af programmet ligger i funktionen handleDoor(), hvor PIR-sensoren checkes for højt signal via analogRead(). Hvis dette er tilfældet, åbnes døren med Servo.write() (på doorServo objektet), og lukkes derefter igen efter fem sekunder (ligeledes med Servo.write()).

Ovenstående beskrivelse er opsummeret i følgende flow-diagram:

door.h

#include <Servo.h>

Servo doorServo;

int doorServoPin = 5;
int PIRPin = A3;

boolean isOpen = false;
unsigned long previousTime;


int sensMvmt;
int noiseThreshold = 100; // Threshold for recognizing PIR trigger

void readSensor() {
  sensMvmt = analogRead(PIRPin);
}

void openDoor() {
  doorServo.write(0);
  isOpen = true;
}

void closeDoor() {
  doorServo.write(180);
  isOpen = false;
}

// setup
void setupDoor() {
  doorServo.attach(doorServoPin);
  previousTime = millis();
  closeDoor();
}

// loop
void handleDoor() {
  readSensor();

  if (sensMvmt >= noiseThreshold && isOpen == false) {
    openDoor();
    previousTime = millis();
  } else if ((millis() - previousTime) >= 5000) {
    closeDoor();
  }
}

Air conditioning

Materialer

  • Arduino UNO
  • Termistor
  • Modstand
    • 10k Ohm
    • 220 Ohm
  • NPN Transistor (PN2222)
  • DC Motor 
  • Diode (1N4007)
  • Kondensator
    • 100nf keramisk

Komponenter og kredsløb

Denne delløsning aktiverer en DC motor, når at temperaturen, der er målt gennem thermistoren, bliver høj nok. På denne måde virker komponenterne tilsammen som et mini AC-anlæg.

Thermistor

Da modstanden i termistoren afhænger af temperaturen, kan vi derfor beregne rummets temperatur med dette komponent. Dog kommer komponentens output ikke direkte i celsius eller lignende enhed, men kan dog beregnes ud Steinhart-Hart ligningen.

Steinhart-Hart ligningen approksimerer en temperatur i Kelvin-enheden, ud fra konstanter der varierer fra hvor stor modstand termistoren er på. Konstanterne i kode-eksemplet er baseret ud fra en 10k termistor.

Steinhart-Hart ligningen kræver at vi kender den svingende modstand i termistoren, som afhænger af temperaturen. For at kende modstanden, bruger vi spændingsdeler-formlen, hvor vi isolere R2. Når vi allerede kender R1 som er 10k Ohm,  VIn er 5V og Vout måler vi i kredsløbet på Arduinoen. R2 er selvfølgelig termistorens modstand, som vi vil bruge i Steinhart-Hart ligningen til at finde en approksimerende værdi for temperaturen.

Efter vores værdier er gået igennem formlen, så er vores output i Kelvin, og vi kan derfor anvende denne omregning:

Endelig har vi vores output i celsius, som er en mere relaterbar værdi og nu kan refereres til i koden.

DC motor

DC-motoren styres af temperaturen som måles igennem termistoren. Hvis at rummets temperatur måles til at være over 30-graders celsius, så sender Arduinoen en spænding igennem til motoren. Derimod hvis temperaturen falder under 30-graders celsius, så slukkes der for spændingen.

Til DC-motoren kobles en diode, som sikrer at strømmen løber den samme retning. Dette gøres for at undgå en modsat strøm fra motoren, hvor strømmen vil løbe i den modsatte retning og potentielt vil forvolde skade på komponenterne. Derudover er derudover er der loddet en keramisk kondensator på tværs af motorens poler for at reducere støj.

Kredsløb

Kredsløbet opsat på breadboard:

Løsningens kredsløbsdiagram ser således ud:

Kode

Koden bag denne løsning er en anelse kompliceret, primært pga. af brugen af Steinhart-Hart ligningen. Herudover er der tale om et simpelt check på thermistorens måling (omregnet til celius via Steinhart-Hart). Måler den over en sat grænseværdi (e.g. 20 grader celsius), bruges digitalWrite() funktionen til at sætte en pin høj, som åbner for transistoren til DC motoren. Ligeledes bruges digitalWrite() til at lukke transistoren, når temperaturen er under grænseværdien.

Ovenstående beskrivelse er opsummeret i følgende flow-diagram:

fan.h

#define MOTOR_PIN 13

int ThermistorPin = A0;
int Vo;
float R1 = 10000;
float logR2, R2, T, Tc, Tf;
float c1 = 0.001125308852122, c2 = 0.000234711863267, c3 = 0.000000085663516;

boolean fanRunning = false;

void setupFan() {
  pinMode(MOTOR_PIN, OUTPUT);
}

float readTemp() {
  Vo = analogRead(ThermistorPin);
  R2 = R1 * (1023.0 / (float)Vo - 1.0);
  logR2 = log(R2);
  T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
  Tc = T - 273.15;
  return Tc;

}

void runFan() {
  digitalWrite(MOTOR_PIN, 1);
  fanRunning = true;
}

void stopFan() {
  digitalWrite(MOTOR_PIN, 0);
  fanRunning = false;
}

void handleFan() {
  if (readTemp() > 30.00 && !fanRunning) {
    runFan();
  } else if (readTemp() < 30.00 && fanRunning){
    stopFan();
  }
}

Futuristic alarm clock

Materialer

  • Arduino UNO
  • Rotary Encoder
  • DS1307 (RTC) 
  • LCD1602A
  • Potmeter
    • 10k Ohm
  • Modstand
    • 220 Ohm
  • Activ buzzer

Komponenter og kredsløb

LCD

Et Liquid Crystal Display (LCD) bruges til at vise hvad klokken er, samt til at indstille alarmen. 

Der er 16 forbindelser på displayet, men eftersom vi benytter os af 4-bit mode kan vi ignorere 4 af dem. 

Arduino LCD Tutorial | How To Connect an LCD to Arduino
GNDEr en jordforbindelse
VCCForbindes til 5 volt
VoSluttes til et potmeter – Denne forbindelse bruges til at regulere kontrasten i displayet
RSForbindes til pin 6 på arduinoen – Register select
R/WStår for Read/Write, for at kunne skrive til displayet skal denne forbindelse sættes lav
EnForbindes til pin 7 på arduinoen – Står for Enable og skal sættes høj når der bliver sendt data til displayet
D0 – D3Bliver ikke benyttet eftersom vi benytter os af 4-bit mode
D4 – D7Forbindes til pin 8 – 11 i stigende rækkefølge – Data pins
AForbindes til 5 volt gennem en modstand – Anoden på baggrundslyset
CForbindes til jord – Katoden på baggrundslyset

DS1307 (RTC)

En Real Time Clock (RTC) er, som navnet antyder, et ur. Modulet indeholder selve DS1307 chippen samt et knapcelle batteri. Dette batteri er ansvarligt for at holde gang i chippen, selv efter VCC er blevet frakoblet. Arduinoen kan gennem I2C interfacet kommunikere med dette komponent og derved holde styr på hvad klokken er.

GNDForbindes til jord
VCCForbindes til 5 volt
SDASluttes til SDA pinen på arduinoen (eller A4) – Data input/output
SCLSluttes til SCL pinen på arduinoen (eller A5) – Clock input, bruges til at synkronisere data der bliver sendt
SQWBliver ikke benyttet – Square wave frequency

Rotary Encoder

Der bliver anvendt en rotary encoder til at sætte alarmen i systemet. Knappen bliver brugt til at skifte mellem at vise klokken og sætte alarmen. For at indstille alarmen skal brugeren dreje på akslen, drejes der mod uret reduceres timeren for alarm og drejes der med uret bliver den forøget.

CLKForbindes til pin 3 på arduinoen – Primære output puls, sender en puls hver gang akslen bliver roteret et klik
DTForbindes til pin 4 på arduinoen – Identisk med CLK, men med et 90 grader faseskift
SWForbindes til pin 2 på arduinoen – En knap, er lav når akslen bliver presset ned
VCCForbindes til 5 volt
GNDForbindes til jord

En rotary encoder virker ved at have to outputs, CLK og DT (også kendt som output A og B), der begge sender pulse. Disse outputs har et mellemrum mellem sig:

Tag udgangspunkt i illustrationen ovenfor, når vi roterer akslen vil det ene output altid blive forbundet med jord før det andet. Roterer vi med uret bliver output A sat lav før output B, roterer vi derimod mod uret bliver output B sat lav før output A.

Med denne viden kan vi nu med registrere hvilken vej brugeren drejer himstergimsen.

Kredsløb

Eftersom flere af komponenterne i dette kredsløb ikke er tilgængelige i AutoDesk Tinkercad er kredsløbet blevet opstillet i programmet Fritzing i stedet. Desuden er den rotary encoder brugt i det fysiske kredsløb ikke tilgængeligt, og er derfor blevet erstattet af en med kun jordforbindelse, CLK og DT samt en knap ved siden af.

Løsningens kredsløbsdiagram ser således ud:

Kode

Koden der er ansvarlig for denne løsning kan virke en smule kompliceret, men kan forklares forholdsvist simpelt. Der eksistere to interrupts, en for akslen og en for knappen fra encoderen. Dette sikre at systemet ikke går glip af en tryk på knappen eller et klik på akslen. Functionen for knappen er også ansvarlig for at skrive timeren til EEPROM, således at timeren bliver gemt. Derudover er der en handle function som checker om alarmen skal starte.

Eksterne Biblioteker

  • RTClib

Koden der er ansvarlig for alarmen bruger RTClib fra adafruit til at kommunikere med den Real Time Clock (RTC). Dette bibliotek kan blive downloadet i Arduino IDE gennem den integreret Library Manager.

Følgende flow-diagram opsummere den tidligere beskrevet kode.

alarm.h

#include <LiquidCrystal.h>
#include <RTClib.h>
#include <EEPROM.h>

#define SW 2
#define BUZZER_PIN 12
#define CLK 3
#define DT 4

RTC_DS1307 rtc;

int stateCLK, lastStateCLK;

int alarmHour_addr = 0;
int alarmMinute_addr = 1;
int sens = 5;
int alarmDuration = 30;
int alarmHour, alarmMinute;

boolean alarmActive = true;

boolean alarmChanged = false;

DateTime now;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(11, 10, 9, 8, 7, 6);

// Print the current time to the LCD
void printLCDTime() {
  lcd.setCursor(0, 1);
  if (now.hour() < 10) {
    lcd.print("0");
  }
  lcd.print(now.hour(), DEC);
  lcd.print(":");
  if (now.minute() < 10) {
    lcd.print("0");
  }
  lcd.print(now.minute(), DEC);
}

// Print the current alarm timer to the LCD
void printLCDAlarm() {
  lcd.setCursor(0, 1);
  if (alarmHour < 10) {
    lcd.print("0");
  }
  lcd.print(alarmHour, DEC);
  lcd.print(":");
  if (alarmMinute < 10) {
    lcd.print("0");
  }
  lcd.print(alarmMinute, DEC);
}

void printLCD() {
  if (!alarmActive) {
    printLCDAlarm();
  } else {
    printLCDTime();
  }
}

// Decrease alarm timer by the value of 'sens'
void decreaseAlarm() {
  if (alarmMinute - sens < 0) {
    if (alarmHour > 0) {
      alarmHour--;
      alarmMinute = 60 - sens;
    }
  } else {
    alarmMinute = alarmMinute - sens;
  }
}

// Increase alarm timer by the value of 'sens'
void increaseAlarm() {
  if  (alarmMinute + sens >= 60) {
    if (alarmHour < 23) {
      alarmHour++;
      alarmMinute = 0;
    }
  } else {
    alarmMinute = alarmMinute + sens;
  }
}

void rotate() {
  if (!alarmActive) {
    stateCLK = digitalRead(CLK);
    // If the previous and the current state of CLK are different, that means a Pulse has occured
    if (stateCLK != lastStateCLK && stateCLK == 1) {
      // If DT state is different to CLK state, that means the encoder is rotating clockwise
      if (digitalRead(DT) != stateCLK) {
        decreaseAlarm();
      } else {
        increaseAlarm();
      }
      printLCDAlarm();
      alarmChanged = true;
    }
    lastStateCLK = stateCLK; // Updates the previous state of the CLK with the current state
  }
}

void saveAlarm() {
  if (EEPROM.read(alarmHour_addr) != alarmHour) {
    EEPROM.write(alarmHour_addr, alarmHour);
  }
  if (EEPROM.read(alarmMinute_addr) != alarmMinute) {
    EEPROM.write(alarmMinute_addr, alarmMinute);
  }
  Serial.println("wrote alarm to eeprom!");
}

void button() {
  alarmActive = !alarmActive;
  lcd.clear();
  if (alarmActive) {
    saveAlarm();
    lcd.print("Current time:");
    printLCDTime();
  }
  else {
    lcd.print("Alarm time:");
    printLCDAlarm();
  }
}

void runAlarm() {
  delay(500);
  digitalWrite(BUZZER_PIN, 1);
  delay(500);
  digitalWrite(BUZZER_PIN, 0);
}

void setupAlarm() {
  if (!rtc.begin()) {
    Serial.println("Could not find RTC!");
  }


  if (!rtc.isrunning()) {
    Serial.println("RTC not running, setting time");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  alarmHour = EEPROM.read(alarmHour_addr);
  alarmMinute = EEPROM.read(alarmMinute_addr);

  // Uncomment to reset clock
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // Uncomment to reset EEPROM
  // EEPROM.write(alarmHour_addr, 8);
  // EEPROM.write(alarmMinute_addr, 0);

  // Using the internal pullup resistors for the rotary encoder
  pinMode(SW, INPUT_PULLUP);
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DT, INPUT_PULLUP);

  pinMode(BUZZER_PIN, OUTPUT);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  lastStateCLK = digitalRead(CLK);

  // Attaching interrupt to CLK pin of rotary encoder
  // (This is needed to make sure each change is registered)
  attachInterrupt(digitalPinToInterrupt(SW), button, FALLING);
  attachInterrupt(digitalPinToInterrupt(CLK), rotate, CHANGE);
  lcd.print("Current time:");
}

void handleAlarm() {

  // Fetch new time info from RTC
  now = rtc.now();

  // Check if alarm is active, run alarm if time is equal to the time of the alarm
  if (alarmActive == true) {
    printLCDTime();
    if (alarmHour == now.hour() && alarmMinute == now.minute() && (now.second() < alarmDuration)) {
      runAlarm();
    }
  }
}

PF2.ino

De tre header files (door.h, fan.h og alarm.h) inkluderes i sketch filen hvor deres setup functions og loop functions bliver kørt fra. Her bliver de tre states fra hvert subsystem også printet til seriel porten hvis der sker ændringer.

#include "fan.h"
#include "door.h"
#include "alarm.h"

boolean lastFanRunning;
boolean lastIsOpen;
boolean lastAlarmActive;

void printStates() {
  if (lastFanRunning != fanRunning) {
    Serial.print("Is the fan running: ");
    Serial.println(fanRunning);
  }

  if (lastIsOpen != isOpen) {
    Serial.print("Is the door open: ");
    Serial.println(isOpen);
  }

  if (lastAlarmActive != alarmActive) {
    Serial.print("Is the alarm active: ");
    Serial.println(alarmActive);
  }

  lastFanRunning = fanRunning;
  lastIsOpen = isOpen;
  lastAlarmActive = alarmActive;
}

void setup() {
  Serial.begin(9600);
  Serial.println("smart home booting");
  setupFan();
  setupDoor();
  setupAlarm();
  Serial.println("smart home running");
}

void loop() {
  printStates();
  handleFan();
  handleDoor();
  handleAlarm();
  delay(50);
}

Konklusion

Blog-indlæggets smart-home installation opfylder de krav, som projektet stiller, men opfylder ikke helt de krav for oprindelig havde sat for løsning. Samlet set havde vi sat øjnene på at installationen havde mere interkommunikation mellem de forskellige moduler, så vores automatiske dør kunne være låst i bestemte tidsrum, eksempelvis kl. 22:00 til 07:00. Dog bidrager hvert modul til at gøre hjemmet smartere på hver sin måde. Døren gør det nemmere at komme ind/ud for, hvis man f.eks. har handlet ind, og blæser-systemet hjælper med at forbedre indeklimaet. Alarmen-displayet fungerer både som ur og alarm, som medvirker til at gøre hjemmet smartere.

Perspektivering

Motoren viste sig at genere for meget støj for at displayet kunne fungere uden fejl, vi var derfor nødt til at lave ændringer på blæser kredsløbet for at reducere støjen.

Som systemet er lavet, opdateres displayet hver loop-cycle, havde der været plads i systemet, kunne SQW pinden på RTC’en været brugt til at signalere til arduinoen at et minut var passeret. Arduinoen kunne herefter opdatere displayet uden behov for at gøre det i hvert loop.

Github side med relevante filer:

https://github.com/benjaminklerens/PF2_robottek

More

Just A Rather Very Intelligent System

 

Portfolio aflevering 2
Hardware og Robotteknologi
Vejledere:
Bente Charlotte Weigelin & Jacob Nielsen
Gruppe:
Eva K. Nøhr Larsen, Jens H. Jakobsen, Nickolai Petersen.

Introduktion

De hjemme automations problemstillinger vi har valgt:

Illustration 1 – Smarthome


I Portefølje-2 opgaven skulle der findes problemstillinger, som kunne løses ved hjælp af automation. Gruppen var særlig opmærksom på ordet “problemstillinger”. Det betød at systemet som skulle laves kunne løse en række problemer, der tilsammen har en central hændelse og dermed binder dem sammen. 


Gruppen blev enige om at skabe et system, som kunne hjælpe en bruger igennem en dagligdag med minimal indflydelse. Ud fra denne idé skabte vi “J.A.R.V.I.S”.

“J.A.R.V.I.S” eller “Just A Rather Very Intelligent System ” er en simulering af et komplet intelligent hjem med fire fokusområder, taget ud fra ovenstående samtale i gruppen. De fire fokusområder blev fundet ved at kigge på hvilke punkter alle i gruppen havde til fælles, i en dagligdag, fra morgen til aften. Den første problemstilling var styringen af gardiner, ud fra hvornår solen står op og går ned. Her kom vi frem til automatiske gardiner som selv ruller op/ned alt efter om det er mørkt/lyst udenfor. Derudover blev automatisk styring af temperatur sat på som endnu et system, som især er et problem om sommeren. En blæser skulle derfor skulle kunne starte hvis der er mere end 22C i huset. En bevægelsessensor som tænder lyset ved bevægelse. Dette ville fjerne problemet i at skulle lede efter en kontakt, hvis man eksempelvis kom sent hjem. En lås som åbnes med nøglebrik, som automatisk låser døren hvis man glemmer dette og som har ekstra feature ved at kunne låses med en remotecontrol og lave den kendte “bip-bip” lyd, som man kender fra sin  bil, når man slår centrallåsen til med sin fjernbetjente bilnøgle.

Disse features blev delt op i følgende problemstillinger samt de elementer, som skal bruges til at bygge dem:

Dagslys og Gardiner
Gardinerne er bliver styret af en DC motor som kan åben og lukke gardinet. Dette system bruger en photoresister, som vil registrere lysindfaldet på huset der simulerer dagens gang.

Blæser
Der er monteret en temperatursensor som vil registrere hvorvidt om en bestemt temperatur er overstreget og hvis dette er tilfældet, starte en DC motor med en monteret blæser. 

Bevægelsessensorer og lys
Der vil være monteret bevægelsessensorer i form af en PIR sensor på alle tre etager af huset som vil sikre at der altid er lys hvor der er bevægelse.

Dør/briklås
Døren kan kun låses op med en nøglebrik både indvendig og udvendig derudover er der monteret en afstandssensorer som vil registrere hvorvidt om du har låst døren når du går ind i huset og vil låse døren automatisk. Låsen selv vil blive styret af en Servo motor. 

Main Control Center
Hvor inputs skal kunne ses af brugerne via en LCD skærm, samt mulighed for at man skal kunne styre systemet manuelt med en fjernbetjening. 

Step By Step Guide til Projektet

Tjekliste over ting som skal bruges.

Liste over de elementer du skal bruge fra det komplette arduino starter kit :

  • 1 x arduino Controller Board
  • 1x Servo motor
  • 1x RFID Modul
  • 1x Passive Buzzer
  • 1x Ultrasonic Sensor
  • 1x PIR Motion Sensor
  • 4x White LED
  • 1x Temperature and Humidity module
  • 1x 3-6 DC motor
  • 1x L293D h-bro
  • 1x Photo Resistor
  • 1x LCD modul
  • 1x IR Receiver
  • 1x Remote

Udover tilkøb til projektet

  • 1x arduino Controller Board
  • 2x PIR Motion Sensor
  • 1x 3-6 DC motor

Planen

Lav en plan over sammenkoblinger

Lav en overordnet plan over hvad der skal styres, hvad der er input og output. Sæt gerne det hele i skema så der kan dannes et overblik. Tegn gerne det hele ind i TinkerCad eller Fritzling. På denne måde får man styr på sine prioteter, rækkefølge og inputsmuligheder på arduinoerne. Vi tegnede i begge programmer men efter at udvide Fritzing med Elegoo- pakken, er det de tegninger som er mest komplette. 

Illustration 2 – Opdelingsskema af Input/Output

Illustration 3 – Kredsløb kort

En eller to arduinoer -og hvordan?

Til dette projekt har vi lavet et “Master/Slave”forhold mellem de to arduino boards. Hvilket  betyder at den ene af de to arduinoer som sender alle beslutningerne er “Master” og den anden tager imod alle beslutningerne er “Slave”. Se illustration som viser hvordan man forbinder de to arduinoer nedenfor.

Illustration 4 -Master/Slave

Udover at systemet kører et master/slave forhold opdelte vi de to arduinoer op mellem input og output, på denne måde stod masteren for alle input. Dette giver god mening da “Master” modtager inputs og laver en vurdering (en logik) og sender vurdering over til “Slaven”, hvorefter “Slaven” starter/tænder/slukker output enhederne.

Illustration 5 – Første Sammenkobling

Sammenkoble alle enheder efter din plan.

“Divide and conquer” har været et gennemgående tema. Tilslutning kræver at man kan holde tungen lige i munden, men er man omhyggelig og følger sin plan til punkt og prikke lykkes det til sidst at tilslutte alle komponenter til de to arduinoer.  Man kan med fordel opdele de to arduinoer på to breadboards i form af:

Master = Input
Slave = Output.

Dette gør det nemmere at bibeholde overblikket.

Programmeringens Tre Faser

For lettere at kunne forklare hvordan programmeringen finder sted, er dette afsnit delt op i tre underemner som fortæller om masterens inputs, slavens outputs og til sidst om kommunikationen imellem de to.

Fase 1. Arduino-Master og Inputs

På denne enhed arbejder vi med med en arduino (Master) hvortil der er tilsluttet:

  • 1x RFID Modul
  • 1x Ultrasonic Sensor
  • 3x PIR Motion Sensor
  • 1x Temperature and Humidity module
  • 1x Photo Resistor
  • 1x IR Receiver + Remote

Inputs på en styreenhed er afgørende for hvor mange ting systemet “ved” og man derefter kan handle ud fra. I dette projekt arbejde vi med to input områder (sikkerhed og bekvemmelighed).

Døren – Sikkerhed 


Døren har et adgangssystem bestående af en (1x RFID Modul) også kaldet en nøglebrik som skal registrerer brugerens adgang.

Koden læser det input der fortæller hvorvidt om den rigtige nøglebrik er blevet benyttet eller ej. Er der ændringer vil state.Laas skifte værdi og Slaven sætter låsen til det der passer.

Kodeeksempel 1 – Kortlæser

Automatisk Lås. – Sikkerhed 

Når brugeren har fået adgang til huset og er gået ind sidder der er en Ultrasonic Sensor og registre at personen er nået et punkt inde i huset for så at sende besked om at døren skal låse.

Kodeeksempel 2 – Afstandsmåler

OBS. Da man blot kan sætte en funktion ind i koden som automatisk låser døren igen, når den har været åben efter 1 min ca -Samt at vi ikke har kunnet finde ud af hvor og hvordan vi skulle placere den soniske afstandssensor i pap-huset og implementeringen i koden, måler den kun en værdi og sender denne til SerialMonitor.

Lys – Sikkerhed/Bekvemmelighed 

På alle tre etager af ejendommen er der monteret 1x PIR Motion Sensor de har til opgave at registrere bevægelse af to grunde. Er bygning i tilstande ”state.Alarm == til” skal dette fungere som alarmsystem. 

Er bygning i tilstand ”state.Alarm == fra” skal det fungere som energibesparende i forhold til lyset automatisk slukker.

Kodeeksempel 3 – Pir Logik

Temperatur – Bekvemmelighed

På siden af husets er der monteret “Temperature and Humidity module” som arbejder sammen med blæseren. Hvis funktion er at køle huset ned. Koden har to stadier; tempereret og for varmt.

Kodeeksempel 4 – Temperatur

Lysindfald – Bekvemmelighed 

Huset er udstyret med en Photo Resistor som hjælper til med at fortælle systemet, om det er nat eller dag. Om dagen skal gardiner gå op og er det nat, skal de gå ned. 

Kodeeksempel 5 – Photoresistor

Remote Control – Bekvemmelighed

Stort set hele husets output system er sat op til at kunne styres manuelt med en fjernbetjening, de vil “overrule” -eller slå de automatiserede funktioner fra, så brugeren kan indstille gardin, lys og blæser efter behov.

Automatiseringen af huset sættes til igen ved tryk på “0”.

Kodeeksempel 6 – Remotecontrol

Dette er et kode udsnit der viser registrering af tryk på remotecontrol og en enkelt funktion der slår slå alarmen fra. 

Op og ned knapperne ruller gardinet op eller ned, vol + tænder blæser og vol- slukker. Derudover kan alle lys tændes og slukkes på hhv knap 1, 2 eller 3.

 Illustration 6 – Remote + IR-receiver 

Fase 2. Arduino Slave og Outputs

På denne enhed arbejder vi med med en arduino (Slave) hvortil der er tilsluttet: 

  • 1x Passive Buzzer
  • 4x White LED
  • 2x 3-6 DC motor
  • 1x L293D h-bro
  • 1x LCD modul
  • 1x Servomotor

Buzzeren/Alarmen

Den Passive Buzzer har to funktioner.

  1. Fungerere som alarm

I tilfælde af at bevægelsessensorer viser tegn på bevægelse under stadiet ”state.Laas  == til” skal Buzzeren reagere med en alarm lyd (ALARM).

  1. LÅST/ÅBEN Tilstand

Når du benytter nøglebrik eller remote control til at åbne eller låse huset, skal lyden indikere brugeren at handling er udført.

Kodeeksempel 7 – Alarmsystem

Kodeeksempel 8 – Alarm Lyd

Lys

Lysets har to funktioner i dette smarthome. Den første funktion er belysning på alle tre etager og den anden er med et sammenspil med buzzeren for at indikere at alarmen er til. 

Kodeeksempel 9 – Lys logik

Motor 1 – RulleGardin

Rullegardinets motor reagerer efter at photo resistorens indikation og rulle gardinet op eller ned efter behov, men som udgangspunkt om det er nat eller dag. For at det kan lade sig gøre skal motoren kunne køre i begge retninger og derfor har vi benyttet en H-bro løsning, som har den fordel udover at kunne styre to motorer på samme tid også kan styre hvilken retning strømmen skal komme fra og på den måde os styre om motoren køre urets retning eller mod urets retning. 

Kodeeksempel 10 – Gardin logik

Motor 2 – Blæseren/Fan

Blæseren i huset fungere som husets kølersystem. Når Temperature and Humidity module vurdere at huset er overophedet bliver der sendt en besked til Slaven om at starte motoren via H-Broen.

Kodeeksempel 11 – Gardin logik

LCD Skærmen

LCD skærmens funktion er den primære kommunikation til brugeren der skal fortælle hvilket stadie huset er i.

Kodeeksempel 12 Temperature state
Kodeeksempel 13 LCD Humidity state
Kodeeksempel 14 Day/Night time State

Dette er kort udsnit af koden som fortæller brugeren hvorvidt om det er nat eller dag.

Displayet viser tre stadier den looper igennem; temperatur, humidity og til sidst hvilken tid vi er på dagen.


Fase 3. Kommunikation imellem

Kommunikation mellem de to enheder bliver sendt som en struct og kun i det omfang at der er sket en ændring. Når der sker en ændring på en af masterens inputs enheder, som er definerede “Game Changers” bliver der sat en ny værdi på denne struct. Structen bliver derefte sendt til Slaven som aflæser og reagere.

struct State {
  float Temperature;
  float Humidity;
  AlarmState Alarm;
  bool Laas;
  bool Gardin;
  bool LysStue;
  bool LysEtage1;
  bool LysEtage2;
  bool Fan;
  bool Night;
};

På master deklareres både staten og “oldState”, de sammenlignes og når de to ikke er ens mere sendes Staten til Slaven og denne State bliver derefter til en ny “oldState” -som så sammenlignes med state og sådan køres der hele tiden i ring.

På Slave modtages State fra Master, så oprettes en lokal “newState”. Beskeden fra Master læses ind i “newState”, herefter sammenlignes de og hvis der pludselig er en “newState” som ikke er ens med state, så udføres den handling som er sat dertil. 


Rammen For Projektet

For at danne ramme for projektet valgte vi i dette tilfælde at tage brug i et dukkehus af pap. Mest fordi det er nemt at simulere et hus og det at materialet er af pap gør det nemt at skære til og omrokere sider, vinduer osv. (Ingen børn har lidt overlast ved at få ødelagt et pap-dukkehus).

Illustration 7 – Kreative materiale

Opbygning af hardware – fra TinkerCad/Fritzing

Herunder kommer beskrivelser af selve hardware opbygningen. Da den er lettere indviklet er den meget kort vist og beskrevet.

Kredsløbsdiagrammer!

I starten havde vi to tegninger -en i TinkerCad som kunne ikke kunne implementerer RFID systemet -og Fritzing der ikke kunne implementerer remoten…

Indtil vi fandt ud af at Elegoo har en pakke med deres komponenter til Fritzing -og derfra kunne vi få alle komponenter ind i en tegning! 

Kodeeksempel 8 – Schematic overview
Kodeeksempel 9 – Kredsløbs overview

Beskrive hvorfor og hvordan i har valgt at lave de enkelte løsninger.

Først tænkte vi kun på hvad vi ville lave. Vi tog ingen hensyn til om vi kunne bygge den løsning vi havde i tankerne. Det her har vi jo aldrig prøvet før, så det kan vi sikkert sagtens!

Så fandt vi ud af at der manglede porte. Derefter fandt vi ud af at nogle ting ikke kan sidde i fx. port 0 eller andre steder da nogle af Elegoo’s ting er specificeret bestemte porte.

Vi fik dobbelttjekket om porte er analoge eller digitale og om det er nødvendigt med PVM på de digitale porte. 

Vi fik dog afskrevet de fysiske knapper til kun at involvere remoten -og har dermed brugt alle porte på de 2 arduinoer.


Opbygning af program 

Kodeeksempel 10 – Flowdiagram

For generelt at beskrive hvordan systemet fungerer, kan man ud fra ovenstående billede se at vi har gjort brug af to arduinoer der er blevet delt som Master og Slave.

Master Arduino styrer logikken og har sensorerne med inputs.

Kommunikationen mellem de to arduinoer foregår sådan at Master tjekker om der er sket ændringer i “State” -er der det, sendes beskeden til Slave over I2C Wire kommunikation. 

Kodeeksempel 15 – State ændring 

Når Slave modtager en besked, laves en lokal newState State, hvor den nye state kopieres ind i. Så sammenlignes hver State og derudfra tændes/slukkes de forskellige aktuatorer ud fra hver deres givne muligheder.

Kodeeksempel 16 – Sending State Info

Funktioner

Herunder forklares funktionerne i hhv. Master og Slave, hvor det nærmere forklares hvad de to gør.

Det er stort set pseudokoden til de to Arduino programmer.

Master

Inkluder 7 biblioteker.
#definer temp/Hum, afstandssensor, PIR system, IR Remote og RFID nøglekortlæser.
Sætter og deklarerer forskellige parametre.
Enum AlarmState.
Tidsintervaller til forskellige forsinkelser. (fx. skal lyset først slukke efter 20 sek uden bevægelse)
Automatik
Struct State

Aflæser Hum & Temp hvert 3. sekund.
Aflæser Afstand hvert 0,2. sek
Hvert 1,5 sek aflæses om IR receiver har modtaget signal
	Hvis den har:
{
Power -> Lås = true.
Op ->  Gardin = false.*   		*)Ved tryk på knap med kursiv, 
Ned -> Gardin = true.			slås automatisk tilstand fra.
Vol+ -> Fan = true.
Vol- -> Fan = false.
1-3 -> Lampe 1-3 = true else false.
0 -> Slår automatisk tilstand til 
}
TranslateIR -oversætter digitale tal til fx “Power” 
Aflæser hvert sekund om RFID chippen er tæt på
	Er den det:
		{Tjek om det er den rigtige brik og giv adgang, hvis rigtig brik}
Send besked til Slave ved ændringer
Setup starter Pir, RFID, Remote og Wire.
Loop tjekker lyssensor om det er nat, 
hvis gardinet er automatisk vil det rulle ned ved nat, 
tjekker temperatur og om blæseren skal tændes. 
Måler afstand, 
tjekker PIR systemet og tænder lyset hvis der er bevægelse 
-er der bevægelse og døren låst startes alarm.
Er det automatisk tilstand, slukkes lyset efter 20 sek uden bevægelse.

Til slut i loop kaldes Remotes signaler, RFID signaler, print til SerialMonitor og Send til Slave.

Slave

Inkluder 3 bibloteker
#definer motor 1 & 2.
Enum AlarmState
Sætter og deklarerer
	lås, 
lys, 
display og 
buzzer.
Melodier
StructState

Display opdateres hvert 3. sek
Definerer de tre ikoner.

Update Display skifter hvert 3. sekund til næste “array”.

RecieveEvent modtager beskeden fra Master
hvis ændret så
{tænd/sluk lys
åben/luk lås + melodi
afspil melodi ved alarm
tænd + eller - til Gardin motor
tænd/sluk blæser.
} 
Så kopieres newState til state

Setup starter Wire kommunikation, lys, lås, LCD display samt de tre symboler til display.
Loop har det tidsinterval som gør længden af en tone, samt en gardinTimeout der stanser gardinets motor efter 0,3 sek.

Prioriteringer

Vores prioriteringer er få, men i de to følgende afsnit fortælles om de dele der har haft indflydelse på både programmets prioritering i læsning af koden, samt det at en remote skal kunne “overrule” det automatiske system.

Delay() vs. millis().  

Meget tidligt i projektet finder vi ud af at delay absolut ikke er optimalt.

Et delay pauser hele programmet i de millisekunder en parameter definerer.

Millis() på den anden side er en funktion som returnerer det antal millisekunder der er gået siden programmets start.

Dette giver en mere akkurat timing og man sikre også at loopet kan køre så tit vi vil, hvorimod man ikke ved hvor lang tid loopet vil tage, når man bruger delay.

Hvordan remote overruler det automatiske system

Der er lavet forskellige boolske automations-stadier som bruges til gardin, blæser og lys. Når der så registreres tryk på de knapper der styrer blæser, lys og gardin sættes det automatiske-stadie til falsk. Nu vil de tre dele så blive i et ikke-automatisk-stadie, da alle de automatiske funktioner kræver at det automatiske stadie er sandt.

Opbygning af den samlede fysiske prototype

Herunder beskrevet hvordan det samlede udtryk er. Der er i Links et video link til youtube hvor man kan se det samlede produkt i aktion.

Hvordan er samspillet mellem mekanik, elektronik og software?

Samspillet fungerer rigtig godt! Når alt koden er opdateret -fx de rigtige ben i virkeligheden og i koden, fungerer den fysiske prototype generelt godt. Det har for alle gruppemedlemmer været spændende og lærerigt at få det hele til at gå op i en højere enhed.


Konklusion

Hvor godt løser jeres løsning de oprindelige problemstillinger?

Denne Portefølje opgave, gik ud på at lave et automatisering af hjemmet. Dette besluttede gruppen som skulle løses ved hjælp af flere systemer, som hver skulle løse deres egen problemstilling, men som samlet skulle kunne løse scenariet, “Dagligdag”.

Photosensor og Gardinets funktion starter scenarie, ved at brugeren står op, med åbent Gardin. Som brugeren går gennem huset vil lyset tænde automatisk. Brugeren skal ikke længere tænke over at tænde/slukke lys når han/hun går gennem huset. Brugeren forlader huset og kan let åbne og låse huset med sin personlige låsenøgle og Remote. Om brugeren er hjemme eller ej, holder blæseren og temperatursensoren, temperaturen nede på et behageligt niveau. Hjemmet er sikret med et alarmsystem, som tænder for en alarmen, hvis brugeren ikke er kommet hjem og bevægelses sensor bliver aktiveret. Når brugeren kommer hjem, er det let at låse op med sin nøglebrik og deaktivere alarmen. Når mørket falder, ruller gardinerne automatisk ned igen. 

Samlet løser disse enkelte elementer det scenarie “dagligdag”. Brugeren kan komme fra seng til dør, og fra dør til seng igen, med minimum indflydelse på hverken husets sikkerhed og eller indeklima.

Med de rette indstillinger gennem ardoinoerne og deres Master/Slave system, løser J.A.R.V.I.S opgaven at holde styr på elementerne. Master/Slave systemet gjorde det mulig at kunne opdele opgaverne i yderligere 2 dele i form af inputs og outputs. Dette gjorde at der var mere styr på koden, kontrol over systemet og at scripte kunne samarbejde, uanset hvilke elementer der kommunikerede.

Ideen om at løse portefølje opgaven ud fra gruppens erfaringer fra dagligdagen, gjorde ikke bare at gruppen kunne finde mange forskellige scenarier, som kunne løse opgaven, men også løse den med relevante problemformuleringer og løsninger, som gruppens egne medlemmer oplevede i deres daglig.

Perspektivering

Hvad kan man gøre for at gøre den bedre?

En videreudvikling af projektet kunne være at flere elementer havde kontrol over lyset. Lyset i sin nuværende tilstand kan kun tænde og slukke ud fra PIR og Remote input. LED lysene i etagerne kunne derfor også blive influeret af alarmsystemet eksempelvis. Dette ville give en ekstra sikkerhed, da hele huset vil blive et stort larmende og lysende kaos, i tilfælde af indbrud. Når huset bliver låst af, kunne lysende også lyse op, ud fra lyden fra buzzeren. Dette ville skabe et sjov scenarie, men også give en klar besked til brugeren uden for, huset at huset nu er låst. Ideen bygger den måde at en bil kommunikere sine tilstande til en bruger. 

Afstandssensoren kunne optimeres ved at få den til at kommunikere med låsesystemet. I dens nuværende tilstand har afstandssensoren ikke andre funktioner end at måle en afstand og sende den enhed til monitoren. Den originale plan og dermed også noget vi kunne have implementere bedre, ville være at bruge afstandssensoren til at opfange en værdi som indikerer at brugeren er kommer hjem. Går man længere ind i huset, uden at låse døren, vil systemet undgå at brugeren har glemt at låse og låser døren automatisk.

Der er sikkert mange flere små opdateringer som kan forbedre “J.A.R.V.IS” og netop også derfor er det blot version 0.01.


Links; 

Youtube Link til Projekt præsentationen:


Master/Slave forholdet mellem to arduinoer:
https://www.arduino.cc/en/Tutorial/LibraryExamples/MasterWriter

Omkring Struct
https://www.ibm.com/docs/en/zos/2.2.0?topic=types-structures-unions

More

Dette_projekt_har_en_lang_titel_men_er_bare_et_alarmsystem

Anders Bjørn Øbro & Rasmus Bundsgaard

Video link: https://drive.google.com/file/d/1My3AFTRMGfyxT8A-JAJg8_Ir0CPq4n0Q/view?usp=sharing

Vi har bygget et sikkerhedssystem til en model af et hus, da vi mener det er essentielt for at føle tryghed i sit eget hus. Mange alarmsystemer kan i dag enten til- og frakobles uden kode via en chip, som husets beboere kan tage med sig, eller med kode via en fastmonteret alarm på en væg. Vi har dog valgt at bruge en fjernbetjening, for at illustrere en kobling af dem begge. Dette er ikke valgt fordi det er en bedre metode end de ovenstående to, men fordi det illustrere fordelene ved begge metoder. Vores kobling af de to metoder ville dog være mere fordelagtig hvis vi havde inkorporeret en chip i fjernbetjeningen som gjorde det muligt at til- eller frakoble alarmsystemet uden at skulle taste koden, men vi prioriterede de andre elementer i projektet højere. Når koden tastes på fjernbetjeningen, vil det kunne ses på en LCD-skærm, som giver brugeren feedback om alarmsystemets status. Derudover vil en korrekt kode aktivere systemets sensorer, herunder en PIR bevægelsessensor, en ultralydssensor, og en LDR sensor. Bevægelsessensoren aktiveres af alle bevægelser i rummet. Ultralydssensoren aktiveres hvis lydbølgerne bliver kortere end det valgte, hvilket indikere at en person er gået foran sensoren. LDR sensoren aktiveres hvis der kommer et pludseligt udsving i lysmålingen, hvilket indikere at en person har tændt et lys, eller lyst på sensoren med en lommelygte. Hvis en af sensorerne aktiveres, vil en piezo højtaler spille en høj alarm-lyd, samtidig med at en motor drejer to LED’er rundt, med blinkende blåt og rødt lys, for at symbolisere politilygter.

På nedenstående billede kan der ses et billede af vores Tinkercad model.

Som det kan ses på billedet, valgte vi at sætte to Arduinoer sammen, for at kunne bruge flere pins, og samtidig opdele alarmsystemets dele. Dette gjorde det muligt at koble alle sensorer på den ene Arduino, og alle aktuatorer på den anden Arduino (bortset fra LCD skærmen). På den måde kan den ene Arduino (A1) ses som værende ‘master’, da den tjekker systemets status, og om en sensor er gået i gang. Hvis en sensor aktiveres, sender den et ‘HIGH’-signal gennem breadboardet til en anden Arduino. Den anden Arduino (A2) kan ses som værende ‘slave’, da dens eneste formål er at vente på signalet, og derefter gøre indbrudstyven opmærksom på at alarmen er gået i gang, ved at spille lyde på piezo-højtaleren og blinke med LED’erne.

På nedenstående billede kan der ses et billede af vores Fritzing model.

Obs. ledningerne i portene i Arduinoerne er ikke vejledende.

På nedenstående flowchart ses projektets kodemæssige prioritering:

Som det kan ses på flowchartet, er systemets vigtigste prioritering at tjekke om koden bliver indtastet, da vi ønsker at kunne gøre dette med det samme. Derefter bliver der tjekket om systemet er aktiveret. Dette bestemmer om informationen fra sensorerne skal tilgodeses eller om der faktisk skal handles. Derfor bliver der altid kaldt på checkPassword funktionen for at finde ud af om der er logget ind eller ej.

Den ene Arduino (A1) styrer sensorer og om brugeren har logget ind på systemet. Den anden Arduino(A2) håndterer alarmsystemets aktuatorer, hvis den første Arduino opdager indbrud. 

Samtalen mellem de to Arduinoer er simpel og består kun af et high-low signal, afhængigt af om nogle er brudt ind eller ej.

Samlet opstilling

Arduino 1 består af følgende komponenter og udførsler:

  1. Tjek fjernbetjening:
    • Her modtages input fra fjernbetjeningen, som i tjekker om der blev indtastet en korrekt adgangskode.
  2. LCD skærm
    • Baseret på artiklen fra Bakker (2020) , valgte vi at bruge en 220Ω modstand til baggrundsbelysningen for en sikkerheds skyld, selvom dette ikke er nødvendigt, da databladet fra Elegoo (2021) fortæller den kan tage 5,5 volt som absolut maks. 
    • Den fungerer som systemets feedback til brugeren.
  3. PIR bevægelsessensor
    • En af alarmsystemets sensorer, som er placeret mod indgangen, og kan måle hele rummet for bevægelse.
  4. LDR lyssensor
    • Vi har brugt en 220Ω modstand baseret på  Using an LDR Sensor With Arduino (2019).
    • Fungerer som en af alarmsystemets sensorer. Måler lysforskellen i rummet, svarende til at en person tænder en lampe eller lyser med en lommelygte.
  5. Ultralyd sensor
    • Fungerer som en af alarmsystemets sensorer. Måler om afstanden til modsatte væg bliver kortere, hvilket indikerer at noget/nogen er gået ind foran.
  6. Signal til Arduino 2
    • Sender et ‘high’ signal når alarmen bliver aktiveret.

Arduino A2 modtager et signal fra Arduino A1 og udfører følgende handlinger:

  1. DC motor
    • Ved hjælp af en h-bro, og nogle Lego-dele som gearing, roterer vi motoren hver sin retning. Fordi vi går fra små tandhjul til større, vil gearene rotere langsommere. Moteren er sat til et lille hvidt tandhjul, som drejer et stort gråt tandhjul. På det store tandhjul har vi sat et meget lille gråt tandhjul, som igen roterer et stort gråt tandhjul, hvorpå lysdioderne er placeret.
  2. LED lysdioder
    • Baseret på artiklen Arduino – BlinkWithoutDelay (2021) , har vi brugt en 220Ω modstand til hver LED pærer.
    • De er placeret på DC motoren, og blinker skiftevis mens alarmen er i gang.
  3. Piezo højtaler

Gennemgang af koden:

Det første A1 tjekker er om fjernbetjeningen modtager input

Her bliver inputtet afkodet af oversætterfunktionen. Derudover vil inputtet ændre en række password variabler. Vi har ikke kunnet finde en metode til at tilføje et indeks til et array dynamisk. Vores løsning til dette problem er at lave fire variabler, henholdsvis password- A, B, C og D. Når der modtages et input, vil det nyeste input sættes til passwordA, og det sidste input vil rokeres til at være passwordB, osv. Indtil de fire varibler stemmer overens med den prædefinerede kode: 1,2,3,4.

Hvis det stemmer overens bliver systemet enten slået til eller fra, afhængigt af dets tidligere stadie. 

Hvis alarmen er slået til, vil nedenstående funktioner udføres, som tjekker om der er registreret bevægelse eller lys i rummet. 

Hvis der registreres enten lys, bevægelse eller ny distance til ultralydsensoren bliver funktionen SendArduinoSignal kaldt, med et ‘High’-signal, hvilket slår alarmen til. Efter nogle sekunder slår vi alarmen fra igen.

I koden til Arduino A2 sørger vi for at kunne måle ‘High’/’Low’-signaler fra den Arduino A1 i Setup med attachInterrupt, som sørger for at ændre mellem state 0 og 1 afhæng af signalet. I Loop tjekker vi dets state, og aktivere aktuatorerne hvis nødvendigt.

////////////////////////////////////////////////////////////A1///////////////////////////////////////////////////////
// IRremote - Version: Latest 
#include <IRremote.h>
#include <IRremoteInt.h>
#include <LiquidCrystal.h>

//display
int receiver = 12; // Signal Pin of IR receiver to Arduino Digital Pin 11


const int PIN_TO_SENSOR = 8;   // the pin that OUTPUT pin of sensor is connected to
int pinStateCurrent   = LOW; // current state of pin
int pinStatePrevious  = LOW; // previous state of pin

const int pingPin = 11; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 10; // Echo Pin of Ultrasonic Sensor

const int ldrPin = A0;
int andenArduino = 13;
int caliUltra = 0;

int passwordA;
int passwordB;
int passwordC;
int passwordD;
int passwordStartAlarm;
bool unlocked = true;
/*-----( Declare objects )-----*/
IRrecv irrecv(receiver);     // create instance of 'irrecv'
decode_results results;      // create instance of 'decode_results'
LiquidCrystal lcd = LiquidCrystal(2, 3, 4, 5, 6, 7);

void setup()
{
  pinMode(andenArduino, OUTPUT);
  Serial.begin(9600);
  Serial.println("IR Receiver Button Decode"); 
  irrecv.enableIRIn(); // Start the receiver
  lcd.begin(16, 2);
  pinMode(PIN_TO_SENSOR, INPUT);
  pinMode(ldrPin, INPUT);
}

void loop()
{
  
  CheckForControllerInput();
  turnSystemOn();
  
  if(unlocked==false)
  {
    CheckForMovement();
    CheckUltraSoundDistance();
    ChechLight();
  }

  delay(300);
  
}
//Her slås alarmsystemet til og fra
void turnSystemOn() {
  if(passwordA==4 && passwordB==3 && passwordC ==2 && passwordD == 1) {
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("CORRECT PASSWORD");
    delay(3000);
    lcd.clear();
    if(unlocked == true)
      {
         unlocked = false;
         lcd.print("Alarmsystem on");
         delay(3000);
         lcd.clear();
         clearPassword();
      }
    else
      {
         unlocked = true;
         lcd.print("Alarmsystem off");
         delay(3000);
         lcd.clear();
         clearPassword();
      }    
  }
}


void clearPassword()
{
    passwordA=0;
    passwordB=0;
    passwordC=0;
    passwordD=0;
}
  
void CheckForMovement() {
  pinStatePrevious = pinStateCurrent; // store old state
  pinStateCurrent = digitalRead(PIN_TO_SENSOR);   // read new state
  
  if (pinStatePrevious == LOW && pinStateCurrent == HIGH) {   // pin state change: LOW -> HIGH
    Serial.println("movement detected"); 
 
    lcd.print("movement detected!");
    // start alarm!
    SendArduinoSignal(HIGH);
    delay(3000);
    SendArduinoSignal(LOW);
    lcd.clear();
      
  } 
  else if (pinStatePrevious == HIGH && pinStateCurrent == LOW) {   // pin state change: HIGH -> LOW
    lcd.print("movement stopped!");
    delay(3000);
    lcd.clear();
  }
}

void SendArduinoSignal(int state) {
  digitalWrite(andenArduino, state);
}

void CheckForControllerInput () {
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    passwordD = passwordC;
    passwordC = passwordB;
    passwordB = passwordA;
    
    Serial.println(results.value); // > here you get the integer from your Remote
    // use an Decimal to Hexadecimal Converter to get the Hex like this: http://www.binaryhexconverter.com/decimal-to-hex-converter
    // add your Mapping in the function translateIR > check the two examples with Power and number 5-Button
    translateIR(); 
    irrecv.resume(); // receive the next value
  } 
}

void CheckUltraSoundDistance() {
  long duration, inches, cm;
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(pingPin, LOW);
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  delay(100);
  
  if(caliUltra==0)
    {
      caliUltra = cm;
    }

  if(cm != caliUltra)
    {
       Serial.println("BUSTED"); 
       lcd.print("someone moving by");
       SendArduinoSignal(HIGH);
       delay(3000);
       SendArduinoSignal(LOW);
       lcd.clear();
    }
}
long microsecondsToInches(long microseconds) {
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds) 
{
  return microseconds / 29 / 2;
}

void ChechLight()
  {
  int ldrStatus = analogRead(ldrPin);

  if (ldrStatus <= 150) 
    {
    Serial.println("det er mørkt");
      return;
  
    } 
  
  else 
    {

      Serial.println("det er ikke mørkt");
        lcd.print("Light detected");
        delay(3000);
        lcd.clear();
        SendArduinoSignal(HIGH);
        delay(3000);
        SendArduinoSignal(LOW);
    }
  
  }

void translateIR() // takes action based on IR code received
{
  lcd.setCursor(2, 0);
  switch(results.value) 
  {
    case 0xFFA25D: lcd.print("POWER"); break;     
    case 0xFFE21D: lcd.print("FUNC/STOP"); break;
    case 0xFF629D: lcd.print("VOL+"); break;
    case 0xFF22DD: lcd.print("FAST BACK");    break;
    case 0xFF02FD: lcd.print("PAUSE");    break;
    case 0xFFC23D: lcd.print("FAST FORWARD");   break;
    case 0xFFE01F: lcd.print("DOWN");    break;
    case 0xFFA857: lcd.print("VOL-");    break;
    case 0xFF906F: lcd.print("UP");    break;
    case 0xFF9867: lcd.print("EQ");    break;
    case 0xFFB04F: lcd.print("ST/REPT");    break;
    
    case 0xFF6897: 
      lcd.print("0");   
      passwordA = 0;
      break;
    case 0xFF30CF: 
    Serial.println("1");
      lcd.print("1");    
      passwordA = 1;
      
      break;
    case 0xFF18E7: 
      lcd.print("2");
      passwordA = 2;
      break;
    case 0xFF7A85: 
      lcd.print("3");   
      passwordA = 3;
      break;
    case 0xFF10EF: 
      lcd.print("4");   
      passwordA = 4; 
      break; 
    case 0xFF38C7: 
      lcd.print("5");    
      passwordA = 5;
      break;     
    case 0xFF5AA5: 
      lcd.print("6");    
      passwordA = 6;
      break;
    case 0xFF42BD: 
      lcd.print("7");    
      passwordA = 7;
      break;
    case 0xFF4AB5: 
      lcd.print("8");    
      passwordA = 8;
      break;
    case 0xFF52AD: 
      lcd.print("9");    
      passwordA = 9;
      break;
    case 0xFFFFFFFF: lcd.print(" REPEAT");break;  
    default: lcd.print("");
  }
  delay(500);
}
         
////////////////////////////////////////////////////////////A2///////////////////////////////////////////////////////
const int pwm = 7;
  
const int in_1 = 6; 
const int in_2 = 5;
int andenArduino = 2;
int val = 0;
const int redPin = 8;
const int bluePin = 3;
const int buzzer = 9;
int state = 1;
void setup() 
{ 
  pinMode(buzzer,OUTPUT);
  pinMode(pwm,OUTPUT); 
  pinMode(in_1,OUTPUT); 
  pinMode(in_2,OUTPUT); 
  pinMode(andenArduino, INPUT);
  pinMode(redPin,OUTPUT);
  pinMode(bluePin,OUTPUT);

 
  attachInterrupt(digitalPinToInterrupt(andenArduino),isr,RISING); // trigger on rising edge of master voltage signal
}

void loop() {

 
  if (state==1)
    {
          larmeAlarm();
          DCmotor();
          state=0;
    }
  
  
}

void isr() 
{
 state=1;
}

void larmeAlarm(){
  
   for(int i=0;i<5;i++)
    {
      tone(buzzer, 1000);
      delay(300);//wait for 1ms
      tone(buzzer, 2000);
      delay(300);//wait for 1ms
      noTone(buzzer);
    }
  }

void blinkendeLygter(){
  
  digitalWrite(bluePin,LOW);
  digitalWrite(redPin,HIGH);
  delay(200);
  digitalWrite(redPin,LOW); 
  digitalWrite(bluePin,HIGH);
  delay(200);
   digitalWrite(redPin,LOW); 
  digitalWrite(bluePin,LOW);
 }

 void DCmotor()
  {
  digitalWrite(in_1,LOW); 
          digitalWrite(in_2,HIGH); 
          analogWrite(pwm,255);
          blinkendeLygter();
          //delay for 3 sec Clock wise motion
          
          delay(1000);
          
          //for break
          
          digitalWrite(in_1,HIGH); 
          digitalWrite(in_2,HIGH); 
          delay(200);
          
          //for anticlock wise
          
          digitalWrite(in_1,HIGH); 
          digitalWrite(in_2,LOW); 
          blinkendeLygter();
          delay(1000);
          
          //for break
          
          digitalWrite(in_1,HIGH); 
          digitalWrite(in_2,HIGH); 
          delay(200);
  
  }

Konklusion

Vi mener at alarmsystemet er meget effektivt, med kun enkelte mekanikker som kunne forbedres. Det er muligt at logge ind og ud af systemet, og alarmen er meget hurtig til at registrere bevægelser eller lysændringer i rummet. Alle sensorer fungere som de skal, og det eneste problem er at de nogle kan kan være lidt for overfølsomme. Dette ville godt kunne være et problem hvis der kom bevægelse fra en nærliggende vej, som kan registreres gennem et vindue. Vi mener at dioderne og alarmen fungerer som de skal. Det største problem vi oplevede var i forbindelse med DC motoren og dens gearing. Vi ville gerne have at dioderne på motoren roterede to omgange, men der var for meget modstand i opsætningen. Dette gjalt især friktionen mellem motorens Lego-gear og de resterende gear, da vi ikke kunne placere motoren helt vinkelret mod de andre gear. Det var derfor svært at lave et responsivt system der gav mulighed for fuld rotation. Selvom projektet har mulighed for forbedring er vi tilfredse med alarmsystemet.

Perspektivering

Grundet begrænsede ressourcer til projektet valgte vi at bruge en photoresistor til alarmsystemet, selvom det ikke er en særlig optimal måde at opfange en tyv på. Dette skyldes at en tyv sagtens kan begå indbrud ved dagslys, som betyder at der ikke behøves at tænde nogen lys, derudover vil den blive påvirket af eksempelvis en udefra kørende bil, som lyser ind gennem vinduet. I vores projekt kunne vi dog have forbedret brugen af denne sensor ved at gemme værdier løbende, for at tage et gennemsnit, og på baggrund af dette vurdere hvilke ændringer der er i rummet over en kort periode, og vurdere om der er en person i huset.

Som nævnt i konklusionen havde vi problemer med en høj modstand i gearingen. Selve konstruktionen var opbygget meget omhyggeligt, men sammensætningen mellem Lego og DC motoren skabte problemer. Vi kunne derfor forbedre projektet ved at lave en gearing som er beregnet til vores DC motor, eller brugt en Lego-motor til at skabe samme effekt.

Vores valg af fjernbetjening til projektets til- og fra kobling medførte nogle komplikationer i koden. Vi valgte derfor at nedprioritere muligheden for at kunne ændre koden undervejs, og have flere kode-kombinationer. Derudover ville fjernbetjeningens funktionalitet forbedres hvis vi tilkoblede en chip, så man ikke behøvede at indtaste en kode hver gang. Dette kunne derfor forbedres til en anden gang.

Referenceliste

Bakker, B. (2020, August 24). How to Control an LCD Display with Arduino (8 Examples). Makerguides.Com. https://www.makerguides.com/character-lcd-arduino-tutorial/?fbclid=IwAR3BJhdwMA6ru1JCcn8lcgndPyaSU90P9uzn6rtTZbt6v3k-C0PleSQGVcA

ELEGOO UNO R3 Project The Most Complete Starter Kit Tutorial. (2021, March 28). ELEGOO Official. https://www.elegoo.com/blogs/arduino-projects/elegoo-uno-r3-project-the-most-complete-starter-kit-tutorial

Using an LDR Sensor With Arduino. (2019, August 27). Codevele. https://codevele.com/tutorials/arduino/using-an-ldr-sensor-with-arduino.html

Arduino – BlinkWithoutDelay. (ukendt forfatter). Arduino. Hentet April 29, 2021, fra https://www.arduino.cc/en/pmwiki.php?n=Tutorial/BlinkWithoutDelay

Circuit design Piezo. (ukendt forfatter). Tinkercad. Hentet April 29, 2021, fra https://www.tinkercad.com/things/hOu3am5ihCm-piezo

More

“Fan”tastic Indeklima 2.0

Nils Lauritzen og Niklas Rosendahl

Vi kender alle sammen til det problem, at man har sat inde på sit værelse i mange timer, og man går lige ud for at hente et eller andet. Når man så kommer tilbage lægger man mærke til at rummet man har sat i er totalt indelukket og der er en tyk luft i lokalet. Man bliver for det meste overrasket over man ikke har lagt mærke til at man har sat i det. Genvex videncenter(Indeklima i hjemmet: fem tegn på, at du har dårligt indeklima – Genvex, n.d.) skriver at et dårlig indeklima kan medfører hovedpine, træthed og i værste fald sygdom. De skriver at en essentielt ting man skal gøre for at få et godt indeklima er at lufte ud. De skriver dog at kun 1 ud af 10 danskere husker at lufte ud 2-3 gange om dagen, som er det anbefalet antal gange. Det har vi prøvet lave en løsning på ved et automatisk udluftning system, som åbner et vindue og lufter rummet ud ved hjælp af ventilation når luftfugtigheden er for høj.

Målsætningen ved vores prototype er at kunne simulerer en løsning af problemstillingen rent funktionelt. Derfor skalerer vi det hele ned i dukkehus størrelse.

Konstruktionen af vores prototype har vi anvendt følgende:

Hardware:

  • Arduino UNO R3 Controller Board
  • DHt11 Tem and Hum Module
  • 2x Potentiometer 10k
  • LCD1602 Module
  • Power Supply Module
  • L293D
  • 2x 3-6V Motor
  • Fan Blade
  • 2x 830 Tire-Points Breadboard
  • 9V1A Adapter 
  • 3x 330 Ω Resistors
  • 220 Ω Resistor
  • 10k  Ω Resistor
  • Diode Rectifier 
  • NPN Transistor PN2222
  • Button
  • 1x Rød og 1x Grøn LED
  • En helveds masse ledninger 😉              

Konstruktion af det fysiske miljø har vi anvendt:

  • Pap
  • Lego
  • Snor
  • Tape
  • Kop
  • Kogende Vand
Billede1 af prototype

Opbygning af hardware

I denne løsnings er der lige nøjagtig nok pins i en enkelt arduino, men til gengæld at det nødvendig at køre med 2 kredsløb med hver deres strømforsyning. Da denne løsning benytter både 2 dc motor og 1 LCD module, og LCD’en bruger omkring 5v som standard kunne vi hurtig regne ud vi skulle bruge mere power!(LCD datablad). Som løsning på dette køre systemet over 2 strømforsyninger. Den ene kredsløb for strøm fra Arduinoen, og den anden for strøm fra et power supply module. Vi anbefaler at man forsyner modulet med strøm fra en kontakt i væggen, og ikke batteri da batteriet løber hurtig tør for strøm.

Billede 2 af system og de fleste komponenters cirka placering på de 2 breadboards.

Som det ses på billedet kan det se lidt kaotisk ud vi vil derfor nu gennemgå de 2 kredsløb hver for sig, og kom ind på opsætningen af hver enkelte komponent. Fremgangs måden i skabelse af systemet var, at fandt de hoved komponenter vi gerne ville bruge. Efterfølgende slog vi dem op 1 efter 1 og satte os ind i hvordan man anvender dem. Til sidst samlede vi så det hele i 2 kredsløbs

Kredsløb 1 (strøm fra Arduino) 

I det første kredsløb kan deles op i 3 afdelinger. Vi har vores LCD Module, Temp-Hum module også har vi en knap og potentiometer hvis funktion er at kunne skrue op og ned for hastigheden på den ene motor.

LCD1602 Opsætning 

LCD funktion i vores prototype er at den skal kunne give os information om hvad vores Temp-Hum sensor måler, og hvor meget farten er på den ene af motorerne.

billede3 opsætning af LCD Skærm

Den er tilsluttet således 

Pin på LCDTilslutning
Pin 1 VSS GroundGnd
Pin 2 VDD 5v5v
Pin 3 VE (Contrast)Potentiometer 
Pin 4 RS (Register Select)Digital 2
Pin 5 RW (Read/Write)Gnd
Pin 6 E(Enable)Digital 3
Pin 11 D4Digital 5
Pin 12 D5Digital 4
Pin 13  D6Digital 6
Pin 14 D7Digital 7
Pin 15 Backlight Anode 220Ω + 5v
Pin 16 Backlight CathodeGnd

Ved Pin 15 ved LCD skærmen er der en lille modstand på 220Ω(ARDUINO LCD SET UP AND PROGRAMMING GUIDE, n.d.) som bestemmer den bagerste lysstyrke på skærmen. Hvis man tager en mindre modstand på bliver lysstyrken højere. Potentiometerets funktion er at man kan skrue op og ned på skærmens kontrast.

DHT11 Temperatur og Humidity Module

Opsætningen af sensoren er forholdsvis lige til hvor vi har valgt at tilslutte sensorens data-Pin til digital input 8 på Arduinoen.

billede4 opsætning af Hum-Temp Sensor

Knap og Potentiometer

Vores Knap og potentiometers funktion er at, den styre hastigheden på den ene motor, så man kan bestemme sig for hvor kraftig ventilation man gerne vil have. 

billede5 opsætning af knap og potentiometer

Vi tilslutter knappen input til digital input 13 på arduinoen. Modstanden på 10k fungere som en pull down or pull up resistor som giver gør at vi kan få et low input når knappen ikke bliver trykket(Arduino Button Tutorial Using Arduino DigitalRead Function, n.d.). Denne løsning passede godt til vores ide der vi godt kunne tænke at når man skulle justere motorens hastighed ville vi gerne have man skulle holde knappen inde.

Kredsløb 2 Power supply Module

kredsløb 2 består af alle vores aktivator, som er 2 dc-motor og 2 LED pærer(Make a Simple LED Circuit, n.d.) som fungere som indikationslys til hvornår motoren køre den ene og anden vej. Det skal simulerer at vinduet åbner og lukker. Når den ene motorer køre for den tilføjet strøm igennem i H-Bro module så vi kan sende strømmen i begge retninger.

billede 6 opsætning af motor med H-bro module

Den anden motorer for tilføjet strøm igennem en NPN transistor, så vi gennem vores kode kan bestemme hvor meget strøm motoren skal have så vi kan styrer hastigheden. Det skal simulerer hvor hurtig man gerne vil have den skal ventilerer. Vi at sat en diode på så vi sikre os at strømmen kun løber i en retning.

billede7 opsætning af Proppel moter med transistor
Kredsløbs diagram over hele systemet

Opbygning af program

Koden til systemet er opdelt i fire primære stadier med en ekstra sekundært stadie. De fire stadier er således:

  1. Neutral: Her venter systemet på at luftfugtigheden bliver for høj.
  2. Start Udluftning: I dette stadie startes udluftningen, eller rettere sagt, den åbner vinduet.
  3. Udluftning: Her startes blæseren og den køre indtil at luftfugtigheden falder til et passende niveau.
  4. Afslut Udluftning: Her slukkes blæseren og vinduet lukkes efterfølgende. 

Fordelen ved at opdele programmet i stadier, hjælper os med at kontroller hvilken kode der skal køre, og hvornår den skal køre. Der kan dog være funktioner, der skal være tilgængelige under flere stadier, og de befinder sig under det femte stadie. Det sidste sekundære stadie, kaldet “Any State” repræsenterer disse funktioner, og fungerer således at den afbryder den nuværende stadie og den ønskede kalder sin funktion, hvor den efterfølgende fortsætter i den tidligere stadie.

Setup

Til dette program er der tilkoblet to ekstra biblioteker. Det første kaldet “dth.h”, tilføjer de nødvendige funktioner, så temperature og humidity modulet kan fungerer som ønsket. Det næste bibliotek tilføjer de nødvendige funktioner for, at LCD displayet kan fungerer som ønsket.

Udover dette tilkobles de forskellige komponenter igennem de pins, de er sat i på Arduinoen. Den maksimale tilladte og den minimale acceptable luftfugtighed defineres igennem “maxHum” og “minHum” variablerne, der er integers. De har således startværdierne 70 og 55. Vi undersøgte hvad den optimale luftfugtighed indenfor er mellem 40-50% (Nymann, 2020), og skal holdes under 60%. Vi nærmere indblik kan vi se at vi havde læst lidt forkert da den gennemsnitlige luftfugtighed vi har kodet der skal ligge på under 55%. Så ved videre test ville vi nok skrue den ned på 45%
Den nuværende hastighed til blæseren kaldet “fanSpeed”, bliver også defineret som integer med en startværdi som 150. 

Stadie 1

Som beskrevet i ovenstående diagram, tjekker stadie 1 hele tiden om luftfugtigheden er tilpas, hvis ikke rykker vi videre til det næste stadie.
Dette kan skrives som et while loop, hvor den bruger den nuværende luftfugtighed og den maximale tilladte luftfugtighed som parameter.

Stadie 2

Dette stadie start hele udluftning processen. Først startes motoren, hvor den bagefter slukkes igen efter et halvt sekund. Motoren trækker i en snor, der henholdsvis er tilkoblet et vindue, der trækkes åben. 

Motorens første ben sættes bare til HIGH, mens den anden fortsat er LOW. Hvilket betyder at motoren køre en bestemt retning. Så et delay, hvor motoren derefter sættes til LOW i begge retninger.

Stadie 3

I dette stadie tænder vi for blæseren indtil at luftfugtigheden er på et passende niveau. Hvis den så fortsætter vi til næste stadie. Dette gøres igen igennem et while loop med luftfugtigheden og den tilladte luftfugtighed som parameter.

Stadie 4

I dette stadie slukkes blæseren, hvorpå vinduet derefter lukkes igen.
Her sætter vi blæserens ben til LOW, hvor vi efterfølgende sætter vindue motorens motor andet ben til HIGH, mens det første forbliver i LOW. Dette fører strømmen igennem motoren i den modsatte retning fra tidligere ved hjælp af en H-bro, hvilket får motoren til at køre modsat. På den måde bliver vinduet lukket i stedet for åbnet igen.
Der er derefter et kort delay, hvor motorens ben bliver sat til LOW og den slukkes. Herefter bevæger vi os tilbage til stadie 1.

Funktioner

Udover de fire stadier har vi også to funktioner, der bliver kaldet iblandt dem. Den første er kaldet PrintHum(), den har formålet at opdaterer den tilkoblede LCD display i systemet med de relevante information omkring luftfugtigheden. Denne funktion bliver kaldt hele tiden i de tidligere stadier med mindre den næste funktion bliver kaldet.

Den næste funktion bliver kaldt, når brugeren trykker på en knap tilkoblet til systemet. Funktionen hedder FanControl(), og den giver brugeren mulighed for at dreje på et tilkoblet potentiometer, der justerer hvor kraftigt blæseren skal køre.

Efterfølgende ændre den LCD displayet, så den fortæller brugeren hvor stærk motoren er med den nuværende indstilling. Da denne funktionen ændre displayet kan den ikke blive kaldt på samme tid som den tidligere funktion, da der opstår en konflikt med deres formål. De bliver derfor separeret igennem en if statement, der tjekker om spilleren trykker på en knap, i de forskellige stadier.

Motorens kraft kan ændres gennem en transistor, der styrer hvor meget strøm der passerer igennem motoren, når den tændes.

Endelige Program

Det endelige program og diagram ser derfor således ud.

//libraries
#include <dht.h>
#include <LiquidCrystal.h>

//skærm pins
LiquidCrystal lcd(2, 3, 5, 4, 6, 7);

//tem og hum sensor
dht DHT;
#define DHT8_PIN 8

//vinduemotor pin
const int pwm = 12;
const int in_1 = 10; 
const int in_2 = 11;

//FanMoter pin
int motorPin = 9;

// fanSpeed knap Pin
int buttonPin = 13;
int buttonState = 0; 

//Potentiometer til fanSpeed
int potPin = 0;
int val = 0;
int fanSpeed = 150;

// Humidity Niveauer 
int maxHum = 70;
int minHum = 55;

void setup(){
  Serial.begin(9600);
  
  lcd.begin(16, 2); //vælger hvilke felter der skal bruges

  pinMode(pwm,OUTPUT); 
  pinMode(in_1,OUTPUT); 
  pinMode(in_2,OUTPUT); 
  pinMode(motorPin, OUTPUT);
  pinMode(buttonPin, INPUT);

}

void loop(){

  // Stadie 1
  while(DHT.humidity < maxHum) {
    buttonState = digitalRead(buttonPin);

    // Any State
    if (buttonState == HIGH) {
      FanControl();
    }  
    else {
      PrintHum(); 
    }  
    
    delay(2000);
  }

  // Stadie 2
  if (DHT.humidity > maxHum){

    // motor 1 åbner vinduet
    digitalWrite(in_1,HIGH);
    digitalWrite(in_2,LOW);
    analogWrite(pwm,255);
    
    //delay på x antal tid
    delay(500);
    
    //slukker
    digitalWrite(in_1,LOW);
    digitalWrite(in_2,LOW);

    // Stadie 3
    while(DHT.humidity >= minHum){
        
      //printer temp og hum til skærm
      buttonState = digitalRead(buttonPin);

      // Anystate
      if (buttonState == HIGH) {
          FanControl();
      }
      else {
          PrintHum();
      }           
        
      //køre den anden motor
      analogWrite(motorPin, fanSpeed);
      delay(2000);       
     }
  }

  // Stadie 4
  if(DHT.humidity <= minHum){
       
     digitalWrite(motorPin, LOW);
     
     digitalWrite(in_1,LOW);
     digitalWrite(in_2,HIGH);
     delay(250);
     digitalWrite(in_1,LOW);
     digitalWrite(in_2,LOW);
  }

}

//FanSpeed Funktion
void FanControl() {

  // Tjek færdig fra potentiometer
  int val = analogRead(potPin);
  fanSpeed = val/4;

  // Pådater display
  lcd.clear();
  lcd.setCursor(0,0); 
  lcd.print("Fan Speed:");
  lcd.setCursor(0, 1);
  lcd.print(fanSpeed);
}

void PrintHum() {
  int chk = DHT.read11(DHT8_PIN);
  lcd.clear();
  lcd.setCursor(0,0); 

  // Print temerpatur
  lcd.print("Temp: ");
  lcd.print(DHT.temperature);
  lcd.print((char)223);
  lcd.print("C");

  // Print humidity
  lcd.setCursor(0,1);
  lcd.print("Humidity: ");
  lcd.print(DHT.humidity);
  lcd.print("%");

  // Print til serial monitor til data opsamling
  Serial.print("Temp: ");
  Serial.println(DHT.temperature);
  Serial.print("Humidity: ");
  Serial.println(DHT.humidity);
   
}

Opbygning af den samlede fysiske prototype

Vi valgte at konstruerer vores system med en masse pap og tape, da vi følte os lidt tidspresset, og vi ikke er særligt stærke inden for mekanik. Derfor valgte vi at konstruerer det så simpelt som muligt.

Her ses skitsen til vores fysiske model

Som set på skitsen, består huset af en papkasse med et enkelt vindue, der trækkes åben med en snor bundet fast til en dc motor. Snoren går igennem husets væg ovenpå vinduet, så det trækkes opad, når snoren spændes, og den lader vinduet falde ned, når snoren løsnes.
Bag på huset sidder selve systemets kredsløb. Det vil sige breadboard, Arduino, LCD display, status dioder, knap, potentiometer osv. Blæseren og luftfugtigheds modulet sidder også fast bagpå, men de går igennem væggen og ind i selve huset.

Test

Vi har lavet mange små test undervejs før vi lavede den fysiske prototype, for at se om systemet virker som det skulle. Måden vi gjorde dette på var at ånde ind i sensoren, så den kom over 70% i luftfugtighed for at se om motorerne startede når de skulle. Da det virkede optimalt lavede vi så et rum ud af pap og installerede systemet. Planen var at vi ville tage en kop med kogende vand med ind i rummet også se hvor længe det ville tage før luftfugtigheden ville falde ned til den den optimale %. Vi fandt dog hurtig ud af at huset var for stort og fanen og vinduet var for lille. Så den havde ikke den store effekt i det skabte indeklima.

Konklusion

Metoden vi valgte at teste på var nok lidt urealistisk, da den mængde fugtighed man for fra kogende vand, er noget voldsommere end hvordan det ville fungere på et normal værelse. Denne test ville nok mere svare til udluftning af et badeværelse når man har været i bad eller lignende. Kort sagt fungerer vores løsning som den skal. Den måler konstant rummets luftfugtighed igennem en “temperature and humidity module”, og hvis den er for høj åbner systemets husets vindue, hvor der efterfølgende startes en blæser, og der bliver luftet ud. Når luftfugtigheden er på et passende niveau igen, slukkes blæseren og vinduet lukkes. .

Perspektivering – Hvad kan man gøre for at gøre den bedre?

Systemet fungerer som det skal, men sådan som det ser ud lige nu, tager den ikke højde for specielt mange parameter. Den tager højde for luftfugtigheden og brugerens ønskede hastighed til blæseren.
Men hvad nu hvis det er nat, og brugeren ikke ønsker at deres vindue åbner midt om natten for at undgå yderligere frygt for indbrud. Dette kunne gøres igennem en photoresistor, der tjekker rummets lys niveau, og hvis den var for lav, så starter den ikke luftfugtighed system, når det er nat.

Udover dette, fungerer systemet rent funktionelt, men konstruktionsmæssigt er der flere mangler i systemet. Den første kunne være, at papkassen der skulle fungerer som hus, var for stor sammenlignet med de anvendte dele. Blæseren var eksempelvis ikke stort nok til at overhovedet have en indflydelse på rummets indeklima.
Husets vindue bestod også som en flap, der var klistret fast med gaffatape, hvor en snor tilkoblet en dc motoren trækker den op og ned. Dette fungerede heller ikke helt optimalt, hvor vinduet nogle gange bare hang fast i pap væggen omkring den, eller den ikke kunne lukke helt i, fordi den ikke sad ordentligt fast i dens ramme. Det kunne løses ved at konstruerer et mere mekanisk vindue, der styres af et gearing system sammen med motoren.

Kilder

Indeklima i hjemmet: fem tegn på, at du har dårligt indeklima – Genvex. (n.d.). indeklima-i-hjemmet-sadan-bliver-det-bedre. Retrieved April 29, 2021, from https://www.genvex.com/videnscenter/indeklima-i-hjemmet-sadan-bliver-det-bedre

ARDUINO LCD SET UP AND PROGRAMMING GUIDE. (n.d.). ARDUINO LCD SET UP AND PROGRAMMING GUIDE. Retrieved April 29, 2021, from https://www.circuitbasics.com/how-to-set-up-an-lcd-display-on-an-arduino/

Arduino Button Tutorial Using Arduino DigitalRead Function. (n.d.). Arduino Project Hub. Retrieved April 29, 2021, from https://create.arduino.cc/projecthub/muhammad-aqib/arduino-button-tutorial-using-arduino-digitalread-function-08adb5

Make a Simple LED Circuit. (n.d.). Arduino Project Hub. Retrieved April 29, 2021, from https://create.arduino.cc/projecthub/rowan07/make-a-simple-led-circuit-ce8308

Nymann, E. (2020, October 5). What Is the Ideal Indoor Humidity Level at Home in Summer? Weather Station Advisor. https://www.weatherstationadvisor.com/ideal-summer-indoor-humidity-level/

More

Ultrahouse 2999

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

More