The Lazy-Persons Ventilation System

Frederik Bøttger-Roth frboe17
Marcus Lomstein marcj18

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

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

Sensorer:

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

Aktuatorer

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

Samlet materiale

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

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

Video gennemgang af systemet

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

Opbygning af hardware

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

Serielt Interface

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

Temperatur, Vand og Ultrasonisk Sensor

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

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

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

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

Stepper motor

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

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

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

LCD Display

Herunder ses hvordan LCD displayed er forbundet til Slave-Arduinoen

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

Opbygning af program

Systemet har tre forskellige states den kan være i

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

Herunder kan ses det samlede flow-diagram over systemet

Arduino 1, aka Master arduino

Arduino 2, aka Slave-arduino

Programmering og funktioner

Master arduino

Master arduinoens setup ser således ud

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

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

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

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

Master arduinoens loop funktion ser således ud.

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

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

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

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

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

  return (false);
}

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

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

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

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

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

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

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

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

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

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

Slave Arduino

Setup for slave arduino kan ses herunder

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

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

void updateState(int Press)
{

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

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

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

Opbygning af fysisk prototype

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

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

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

Konklusion

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

Perspektivering

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

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

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

More

Happy Home

Andreas Adriansen, Freya Arbjerg, Osman Khassouk

Introduktion

Happy Home fokuserer på at øge sikkerheden og gøre hjemmet mere komfortabelt. Systemet indeholder derfor en temperaturmåler, som har en indbygget skærm til let fremvise temperaturen i alle situationer. Temperaturmåleren samarbejder med en ventilator, som kan tændes automatisk hvis temperaturen er over 20°, eller af en fjernbetjening når indeklimaet i huset bliver for varmt.

Den anden funktion som kommer med happy home er en alarms installation, som kan aktiveres når man ikke er hjemme. Dette system fokuserer på at styrke sikkerheden i hjemmet. Alarmen aktiveres når man får uønsket besøg i hjemmet, og giver signal i form af en høj lyd frekvens.

Termistor med LCD

Dette er et kredsløb som kan måle temperaturen via en thermistor og vise den på en LCD skærm.

Komponenter:

  • Arduino Uno
  • LCD1602
  • 10kΩ potentiometer
  • 10kΩ modstand
  • 10kΩ thermistor (MF52D-103f-3950)

LCD-skærmen styres ved hjælp af de digitale pins 7 til 12. Spændingen fra thermistoren aflæses ved hjælp af analog pin 5. Husk at indstille potentiometeret til 10kΩ.

Kode

#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
float pin = A0;
float R1 = 10000;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

void setup() {
  lcd.begin(16, 2); // Columns and rows
  Serial.begin(9600);
}

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

  lcd.setCursor(0, 1);
  lcd.print(Tc);

  delay(500);
}

Alarm tutorial

Alarmsystemet er en alarm der aktiveres når en bevægelse registreres. Systemet er et simpelt kredsløb som bruger en piezo-højttaler som aktuator og en PIR-bevægelsessensor som sensor. Begge komponenter tilkobles til en Arduino Uno.



Komponenter:

De anvendte komponenter til alarmsystem:

  • PIR motion sensor
  • Piezo speaker (Buzzer)
  • Arduino Uno
  • Ledninger
  • Breadboard




PIR bevægelsessensor

PIR-bevægelsessensor måler infrarøde lys fra objekter i sit synsfelt, ændringer til det infrarøde lys i miljøet detekteres som bevægelse.

Piezo-højttaler (buzzer)

Piezo-højttaleren er en lydsignal anordning, der kan tilsluttes Arduino, hvor tonen kan bestemmes ud fra frekvens indstillingen. Højttaleren bruger en invers piezo-elektrisk effekt til at producere lydbølger.

Pins

PIR motion sensor has 3 pins.

  • GND – tilslut til jord.
  • OUT – tilslut til Arduino digital pin.
  • 5V – tilslut til 5V.

Piezo-højtaler har 2 pins.

  • GND – tilslut til jord.
  • OUT – tilslut til Arduino digital pin.

Skematisk

Sort Ledning – tilslut til jord.

Rød Ledning – tilslut til power.

Gul Ledning – tilslut Arduino pins.

Kode

int sensor = 10;            //the pin that the sensor is attached to
int buzzer = 11;
void setup() {
  pinMode(buzzer, OUTPUT);   //initialize buzzer as an output
  pinMode(sensor, INPUT);    //initialize sensor as an input
  Serial.begin(9600);        //initialize serial
}
void loop(){
  if(digitalRead(sensor) == HIGH){
    tone(buzzer, 450);
    Serial.println("Motion Detected");
    delay(200);
  }
  else{
    digitalWrite(led, LOW);
    noTone(buzzer);
    Serial.println("Motion Stopped");
    delay(200);
  }
}

Remote fan control

Dette systems job er at kunne tænde og slukke en blæser ved hjælp af en fjernbetjening. En infrarød sensor samler input fra fjernbetjeningen og en DC-motor med et blad på agerer som blæser.

Komponenterne inkluderet i dette system er:

  • Arduino Uno
  • Breadboard
  • DC-motor
  • L293D (H-bro)
  • Infrarød sensor
  • Fjernbetjening
  • Ledninger

L293D

Ovenover ses en oversigt over L293D. L293D kan styre to dc motorer, men i dette projekt behøves kun 1. Der tilsættes 5 volt til pin 1, pin 8, og pin 16. Da kun en motor er nødvendig tilsættes der kun ledninger til venstre side. Det vil sige input 1 og 2, ground pin 4 og 5, og output 1 og 2. Input 1 og 2 tager input fra Arduinoen og output 1 og 2 sender det videre til DC-motoren. Hvis det ene input er HIGH og det andet er LOW vil motoren rotere en vej, hvis det ændres til det omvendte, vil motoren rotere den anden vej.

Skematisk tegning

Kode

#include <IRremote.h>

// Define the pin for the IR Receiver and LED
int IRPIN = 3;

// Define the pin numbers
int motorPin1 = 13;
int motorPin2 = 2;

bool on = false;

void setup() {
    // Set the pin modes of the above IO pins to OUTPUT
    Serial.begin(9600);
    Serial.println("Enabling IRin");

    IrReceiver.begin(IRPIN, ENABLE_LED_FEEDBACK);

    Serial.println("Enabled IRin");
    pinMode(motorPin1, OUTPUT);
    pinMode(motorPin2, OUTPUT);

    digitalWrite(motorPin1, LOW);
    digitalWrite(motorPin2, HIGH);
    delay(500);
    digitalWrite(motorPin1, LOW);
    digitalWrite(motorPin2, LOW);
}

void loop() {
    // Turn the motor in one direction

     if (IrReceiver.decode()){
      String str = String(IrReceiver.decodedIRData.decodedRawData, HEX);
      Serial.println(str);
      if(str != "0"){
        if(!on){
          digitalWrite(motorPin1, LOW);
          digitalWrite(motorPin2, HIGH);
          Serial.println("Turned on");
        }
        else{
          digitalWrite(motorPin1, LOW);
          digitalWrite(motorPin2, LOW);
          Serial.println("Turned off");
        }
        on = !on;
      }
      IrReceiver.resume();
     }
    
    delay(1000);
 
}

Samlet system

Fysisk prototype 

Link til demo:

https://drive.google.com/file/d/18JmNdVYdRczAf82JtFdgqRlfdgcMde3s/view?usp=sharing (bemærk at temperaturen i programmet var sat til 21 grader i demoen før at motoren kører)

Systemer sammenspil

I den nyere version af vores system kan ventilationssystemet styres af temperaturen og fjernbetjeningen. Er temperaturen over 20 grader celsius tændes der for ventilationen, hvis den er under forbliver den slukket. Temperaturmåleren checkes konstant for ændringer i tilfælde af state skift.

Den anden tilføjelse er sammenspillet mellem fjernbetjening og ventilationssystem. For at brugeren kan noget manuel styring af ventilationen, kan fjernbetjeningen bruges til at override den målte temperatur i en kort periode. Styringen kan ses i flowchartet under dette afsnit.

Flowchart

Kode til det samlede program

#include <LiquidCrystal.h>
#include <IRremote.h>

int motorPin1 = 13;
int motorPin2 = 2;
int irPin = 3;
int motionSensorPin = 5;
int buzzerPin = 4;
int ledPin = 6;
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int thermistorPin = A5;
float R1 = 10000;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;
unsigned long REMOTE_LOCK_TIME = 10000;
unsigned long remotePressed = 0;

void setup() {
  lcd.begin(16, 2); // Columns and rows
  IrReceiver.begin(irPin, ENABLE_LED_FEEDBACK);
  pinMode(buzzerPin, OUTPUT);
  pinMode(motionSensorPin, INPUT);
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(ledPin, OUTPUT);

  Serial.begin(9600);
}

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

  lcd.setCursor(0, 1);
  lcd.print(Tc);

  return Tc;
}

void runAlarm(){
  if (digitalRead(motionSensorPin) == HIGH) {
    tone(buzzerPin, 450);
    Serial.println("Motion Detected");
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
    noTone(buzzerPin);
    Serial.println("Motion Stopped");
  }
}

void runRemote() {
  if (IrReceiver.decode()) {
    String str = String(IrReceiver.decodedIRData.decodedRawData, HEX);
    Serial.println(str);
    if(str != "0"){
      Serial.println("Remote presses");
      remotePressed = millis();
    }
    IrReceiver.resume();
  }
}

void runAircon(float temperature) {
  Serial.println(temperature);
  bool remoteTriggered = remotePressed != 0 && remotePressed + REMOTE_LOCK_TIME > millis();

  bool enable = temperature > 20;
  if (remoteTriggered) {
    enable = !enable;
  }

  if (enable) {
    digitalWrite(motorPin2, HIGH);
  } else {
    digitalWrite(motorPin2, LOW);
  }
}

void loop() {
  float temp = runTemperatureDisplay();
  runAlarm();
  runRemote();
  runAircon(temp);
  delay(500);
}

Problemer under opbygningen

Der forekom problemer under opbygningen af produktet, nogle som var til at fikse og andre, der krævede vi måtte skifte strategi. Det første problem kom i form af vores IR receiver. IR receiveren kan tyde mellem forskellige knapper på fjernbetjeningen som det kan ses i eksemplet forneden.

Der forekom dog problemer med dette komponent, som umiddelbart var udenfor vores kontrol. IR receiveren havde en tendens til at virke perfekt ved nogle testkørsler, men ved andre ville den begynde at printe de forkerte koder og endda skifte kode selvom der blev trykket på den samme knap. Dette kunne nogle gange fikses ved at sætte IR receiveren bedre fast på breadboardet, men den ville hurtigt gå i stykker igen. Gruppen endte med at løse dette problem ved at ikke spørge efter en specifik kode i programmet, men at spørge om koden != 0. På denne måde kunne man bruge fjernbetjeningen til at tænde og slukke motoren, men det er også kun den eneste funktionalitet fjernbetjeningen kan give, da programmet ikke længere kan tyde forskel på de forskellige knapper på fjernbetjeningen.

Der forekom også problemer med DC motoren i form af elektrisk støj, men dette blev der ikke umiddelbart fundet en løsning til.

Konklusion

Robotten opfylder de krav sat for projektet. Alle systemer medvirker til at forbedre hjemmet, enten i form af et ventilationssystem der er styret af temperaturen og fjernbetjening eller alarmsystemet som giver signal ved indbrud.

Perspektivering

Havde der været mere tid til projektet ville der havde været gjort forsøg på at bygge installationen som først planlagt. Planen var at bygge et dørsystem som er kontrolleret af en fjernbetjening, samtidig med at den kunne samarbejde med alarmsystemet. Der var dog problemer med aflæsning af den printede information fra fjernbetjening som vi ikke kunne løse i tide. Alarmsystemet blev bygget med denne installation i tankerne og er derfor ikke optimal i dens selvstændige tilstand.

More

Overvågeren

Gruppe:
Morten Krogh Jensen (mortj18@student.sdu.dk)
Thomas Steenfeldt Laursen (tlaur18@student.sdu.dk)

Semester:
F21

Afleveringsdato:
29. april 2021

Introduktion

I dette projekt har vi valgt at gå med en alarmløsning med dørlås. Dette system består af en række sensor- og aktuator-komponenter:

  • Sensorer
    • RFID-scanner: Til scanning af tag/brik eller keycard så brugen kan låse døren op
    • KeyPad: Brugeren kan indtaste en kode som åbner og låser døren.
    • Motion Sensor: Til at registrere om nogen er i huset når døren er låst.
    • Termistor: Til simulering en brandalarm i hjemmet.
  • Aktuatorer
    • Display: Til at vise Systemets tilstand
    • Servomotor: Til at styre låsen på døren.
    • DC Motor: Til at sætte rummet i overtryk i tilfælde af brand.
    • Buzzer: Til at give lyd i tilfælde af enten tyverialarm eller brandalarm.

Samlet set er dette system bygget til at man på flere forskellige måde kan aktivere og deaktivere alarmsystemer i sit hus. Bevægelsessensoren fungerer som indbrudsalarm og termistoren som brandalarm.

Systemet er bygget op, så det altid befinder sig i én af fire forskellige tilstande. Systemet vil skifte tilstand baseret på hvad der sker omkring det. Den aktuelle tilstand for systemet er vist med forskellige billeder på displayet. Herunder er de fire tilstande beskrevet:

  • Åben: Illustreret med glad smiley. Døren er oplåst, og den eneste aktive alarm er brandalarmen.
  • Lukket: Illustreret med sur smiley. Døren er låst og bevægelsessensoren samt brandalarm er aktiv.
  • Alarm: Illustreret med et udråbstegn. Døren var i låst tilstand og der blev registreret bevægelse i rummet. Døren forbliver låst og indbrudsalarmen lyder. Brandalarm forbliver aktiv.
  • Brand: Illustreret med en flamme. Temperaturen i bygningen er for høj og brandalarmen lyder. Døren låses op for at sikre flugtveje.

Derudover er der to visninger som displayet har, men som ikke knytter sig til specifikke tilstande:

  • Korrekt kode: Såfremt at der er indtastet en korrekt kode, eller brugt en godkendt RFID-enhed. Illustreret med et flueben
  • Forkert kode: Såfremt der er indtastet forkert kode, eller brugt en ikke-godkendt RFID-enhed. Illustreret med et kryds

Videogennemgang af løsningen

Demonstration af tilstande

I nedenstående video vises det hvordan at systemet starter i tilstanden ”Åben” (glad smiley), og derefter skiftes til ”Lukket” (sur smiley). Herefter aktiveres ”alarm” tilstanden (Udråbstegn) ved at bevægelsessensoren i rummet registrerer bevægelse. Skiftet til ”alarm” tilstand sker kun såfremt at systemet i forvejen er i tilstanden ”Lukket”. Den sidste tilstand, ”Brand” aktiveres i videoen ved at placere termistoren i en kop med vand på næsten 100 grader. Det ses at selvom alarmen i forvejen er aktiv så skifter systemet stadig tilstand til brand, da denne tilstand altid prioriteres over alle de andre tilstande. Under denne tilstand ses det også at blæseren, som skaber overtryk, er aktiv, samt man kan høre at servomotoren åbner døren for at gøre det nemmere for indespærrede folk at komme ud af den brændende bygning. Sidst i videoen ses det hvordan tilstanden resettes når der bliver brugt en valid RFID-tag.

Demonstration af RFID og keypad

Denne video er en demonstration af de forskellige muligheder for at låse samt åbne døren i alarmsystemet. Læg venligst mærke til hvordan displayet viser om det er en valid RFID-enhed, og om koden er korrekt, samt at displayet viser om døren er låst eller åben.

I starten af videoen ses det hvordan døren er låst og der derefter med kode bliver låst op, for at blive låst igen med samme kode efterfølgende. Herefter vises samme princip bare med RFID i stedet for Keypad, og det vises også at det ikke er muligt at åbne låsen med en RFID-enhed som ikke er godkendt.

Opbygning af hardware

Diagrammet herunder viser den endelige sammensætning af hardwaren. I midten ses de to Arduinoer som kontrollerer hele systemet. Det var nødvendigt med to Arduinoer, da vi med alle vores komponenter hurtigt løb tør for porte. Derfor forbandt vi keypad-komponenten til Arduinoen til venstre. Det eneste formål denne Arduino har er derfor at registrere input fra keypad’en og derefter give besked til Arduinoen til højre. Arduinoen til højre foretager derfor det meste af arbejdet og kan betragtes som den primære styreenhed i systemet.
For at mindske forvirring, vil vi i dette afsnit præsentere kredsløbsdiagrammerne for hver enkelt komponent hver for sig.

Figur 1 – Breadboard-diagram

Keypad

Som sagt er keypad-komponenten forbundet til den venstre Arduino. Herunder ses et forsimplet kredsløbsdiagram med kun keypad’en og de to Arduinoer. Keypad’en består af 4×4 grid. Derfor skal den optage hele otte digitale porte på Arduinoen. Dog har vores system ikke brug for bogstav-knapperne (A, B, C, og D) i højre kolonne af keypad’en. Det er derfor muligt at undlade den ene forbindelse.

Efter den venstre Arduino registrerer input, skal den meddele det til den primære Arduino. Dette er opnået med en I2C-forbindels gennem Arduinoernes A4 og A5-porte. Her er det yderligere vigtigt at Arduinoerne deler den samme jordforbindelse.

Figur 2 – Kredsløbsdiagram over keypad-setup

RFID-scanner

Diagrammet under viser hvordan RFID-scanneren er forbundet til den primære Arduino. Denne komponent skal forsynes med 3,3V, og er derfor forbundet til Arduinoens 3,3V-port.

RFID-scanneren kommunikerer med Arduinoen igennem SPI-protokollen (Serial Peripheral Interface) (men den understøtter også I2C og UART). De pins på RFID-scanneren der relaterer sig til SPI er MISO, MOSI, SCK, og SS/SDA. MISO står for Master In Slave Out og anvendes når slaven (RFID-scanneren) skal sende data til masteren (Arduinoen). MOSI står for Master Out Slave In og bruges til kommunikation fra master til slave. SCK er den pin hvor RFID-scanneren modtager et clock-signal fra Arduinoen. Dette sikrer at deres kommunikation er synkroniseret. I SPI-mode fungerer SS/SDA-pin’en som Slave Select. Den bruges til at bestemme hvilken slave der kommunikeres med hvis man har at gøre med et system med flere slave-enheder. Den sidste anvendte pin på RFID-scanneren er RST, og bruges til at genstarte eller slukke komponenten.

Arduinoen har dedikerede porte til MISO, MOSI, og SCK. Derfor er det vigtigt at disse pins på RFID-scanneren er forbundet til netop disse porte. RST og SS/SDA kan dog forbindes til valgfri porte.

Derudover har RFID-scanneren en IRQ-pin. Dette er en interrupt-pin som kan anvende til at give Arduinoen besked når et RFID-tag bliver scannet. Denne funktionalitet har vi ikke gjort brug af i dette projekt. Senere i program-delen af beskrives det hvordan vores system håndterer scanningen af RFID-tags.

Figur 3 – Kredsløbsdiagram over RFID

Display

Herunder ses kredsløbsdiagrammet for display-komponenten. Denne er forbundet til Arduinoen gennem fem pins: VCC, GND, DIN, CLK, og CS. Ligesom RFID-scanneren kommunikerer displayet og Arduinoen ved brug af SPI-protokollen. DIN svarer til MOSI (Master Out Slave In), CLK svarer til SCK, og CS svarer til SS (Slave Select). Bemærk at komponenten ikke har en MISO-pin siden den aldrig skal sende data til Arduinoen.

Siden displayet anvender samme kommunikationsprotokol som RFID-scanneren kan man forbinde dens MOSI- og CLK-pins til de pågældende porte på Arduinoen samtidig med RFID-scanneren. Dog havde vi problemer med denne løsning, så vi gav den separate porte. En ulempe ved denne løsning er at den skulle være en smule langsommere end hvis man brugte de dedikerede porte. Det er dog ikke noget vi mærkede til overhovedet.

Figur 4 – Kredsløbsdiagram over display

Servomotor

Kendetegnende ved servomotoren er at denne kan blive placeret i forudbestemte positioner og var derfor ideel for os at bruge som låsemekanisme til dette system. Servomotoren har tre terminaler, nemlig vcc (+), ground og signal. Vcc er vores 5v input, ground(-) er vores jordforbindelse, og signal(pulse) er forbundet direkte til vores Arduino hvor den får signalet om hvilken position den skal stå i. I vores tilfælde er servomotoren forbundet til digital pin 7 som det ses i kredsløbsdiagrammet nedenfor. I koden er der importeret et bibliotek som giver os muligheden for at bruge en vinkel som input, i vores tilfælde er det sat til at åben-tilstanden er 180 grader, og lukket/låst er 80 grader.

Den typiske servo har bestemte puls værdier som afgør positionen for servoen, og det samme er gældende for vores servo. Vores servo hedder en SG90 og i databladet for denne kan det ses at position ”0”, som er midterste position kræver en puls på 1.5ms, position ”90”, som er positionen længst mod højre, kræver en puls på 2ms og position ”-90” som er positionen længst mod venstre, kræver en puls på ca 1ms.

Figur 5 – Kredsløbsdiagram over servomotor

Motion sensor

I dette projekt er der brugt en PIR motion sensor, som er en bevægelses sensor som indeholder infrarødsensorer. Denne sensor udnytter andre objekter i verden som udsender infrarød belysning, f.eks. menneskekroppen, til at registrere om der er bevægelse inden for den 110 graders vinkel den kan se i.

På sensoren sidder to potentiometre som gør det muligt for brugeren at justere følsomheden for sensorerne.  Forbindelsen til denne enhed er meget simpel, da den kun skal bruge en 5v forbundet til VDD, en jord forbundet til ground, og en signal forbundet mellem signal og Arduino. Som det er vist i diagrammet nedenfor har vi forbundet vores til den digitale pin 8 i vores system.  Signalet som bruges som input i Arduinoen er enten af værdien 1 eller 0, hvor 1 er værdien for hvis sensoren registrerer bevægelse.

Figur 6 – Kredsløbsdiagram over motion sensor

Buzzer

Som man kan se på kredsløbsdiagrammet herunder, er der lavet en meget simpel forbindelse af buzzeren. Den bliver forsynet med strøm fra en af Arduinoens digitale output porte. Mellem buzzeren og ground er der forbundet en modstand på 220Ω. Denne begrænser strømstyrken til buzzeren, så den ikke brænder af. I databladet til buzzeren er det angivet at den maksimalt kan holde til 30mA [http://www.farnell.com/datasheets/2171929.pdf]. Ved hjælp af Ohms lov kan den nødvendige modstand beregnes:

Den nærmeste modstand vi havde tilgængelig var 220Ω.

Figur 7 – Kredsløbsdiagram over buzzer

Røgventilationssystem (DC-motor)

DC-motoren er en meget strømslugende komponent og kan derfor ikke styres direkte fra Arduinoen. Derfor får den strøm direkte fra den eksterne strømkilde igennem en H-bro (se kredsløbsdiagrammet herunder). H-broens pins 8 og 16 forsyner den med strøm og er derfor forbundet til 5V. Pin 4, 5, 12, og 13 er alle til jord, men vi har nøjes med at forbinde kun én af dem. Pins 11 og 14 er output til motoren. Om strømmen løber den ene eller anden vej igennem afhænger af om man sætter 5V på pin 10 eller 15. I vores tilfælde har vi kun forbundet pin 15 til digitalt output på Arduinoen, fordi den kun har brug for at køre den ene vej. Så når motoren skal tændes, sættes Arduinoens digital pin 4 til høj. Man kan argumentere for at vi kunne have nøjes med en simpel transistor i stedet for en H-bro, men den voldte os problemer.

Figur 8 – Kredsløbsdiagram over DC-motor

Brandregistreringssystem (Termistor)

Til at registrere om der er brand i huset, har vi benyttet os af en termistor. Dette er en resistor hvis størrelse afhænger af dens temperatur. Ved stuetemperatur målte vi en modstand på 10kΩ, og nedsænket i kogende vand faldt modstanden til 0,8kΩ.
Termistoren er forbundet i et spændingsdelerkredsløb (se kredsløbsdiagram i bunden af afsnit), så Arduinoen ved hjælp af en analog port kan måle om termistoren bliver varmere. Den faste modstand i spændingsdelerkredsløbet er på 2kΩ. Spændingen i punktet mellem de to modstande kaldes V_out og ændrer sig efter følgende formel. R_1 og R_2 er størrelsen på henholdsvis den faste og den variable modstand.

Det er ikke ligegyldigt hvilken størrelse fast modstand der bruges i spændingsdeleren. Man ønsker at vælge en modstand som giver stor variation i V_out siden det giver en højere ”opløsning”, og man kan registrere finere ændringer i temperaturen. Følgende beregninger viser hvordan vi kom frem til at en fast modstand på 2kΩ ville give den største variation af V_out.
Vi definerer ΔV som værende ændringen i V_out når termistoren går fra stuetemperatur til 100 grader:

Vi ønsker at ΔV er så stor som muligt for at få den fineste opløsning på spændingsdeleren. Vi kan nu substituere formlen for V_out ind i udtrukket:

Fra vores målinger vides det at R_2(stue)=10kΩ og R_2(100)=0,8kΩ. Siden vi forsyner spændingsdeleren med 5V, er V_in=5V.

Man kan nu betragte ΔV som værende en funktion af R_1. Herunder ses grafen for denne funktion:

Figur 9 – Graf over ΔV som funktion af R_1

Maksimumspunktet ligger et sted mellem R_1=2kΩ og R_1=3kΩ. Den nærmeste modstand vi har i sættet (uden at forbinde flere sammen) er 2kΩ, så det var hvad vi gik med.

Figur 10 – Kredsløbsdiagram over termistor

Opbygning af program

I dette afsnit beskrives opbygningen af de Arduino-kode vores system kører på (kan ses i bunden af afsnittet). Her vil vi dokumentere hvad de forskellige funktioner i vores system gør og hvordan softwaredelen af projektet hænger sammen. Der bliver i starten givet en overordnet beskrivelse af systemets flow og mulige tilstande. Derefter er metoderne listet op i den rækkefølge som de står i softwaren med en beskrivelse af deres ansvarsområde.

Overordnet opførsel

Som det tidligere har været beskrevet, vil vores system være i én af fire tilstande på hvilket som helst tidspunkt (OPEN, CLOSED, ALARM, EMERGENCY). Systemet kan skifte imellem tilstandene på flere forskellige måder. Dette er illustreret gennem tilstandsdiagrammet herunder. Dette diagram viser blandt andet at systemet kan gå i EMERGENCY-tilstand hvis der registreres brand uanset hvilken anden tilstand systemet har. Man slipper kun ud af EMERGECY ved at indtaste en korrekt kode eller scanne et korrekt RFID. I tilstanden CLOSED er bevægelses-sensoren tændt og ALARM kan aktiveres. Systemet går ud af ALARM på samme måde som EMERGENCY.

Figur 11 – Tilstandsdiagram

For at få en bedre indblik i hvordan systemet prioriterer sit input, kan man kigge på flowdiagrammet herunder. Dette viser rækkefølgen af de beslutninger som den primære Arduino tager mens den kører (i loop-funktionen). De øverste beslutninger eksekveres først og har derfor højest prioritet. Den starter med at læse termistor-sensoren for at afgøre om der er brand. Hvis det er tilfældet, går den direkte til EMERGENCY-tilstand. Ellers kører den videre til næste input. Hvis der registreres bevægelse inde i huset mens systemet har tilstanden CLOSED, må der være en ubuden gæst. Derfor initialiseres ALARM.

Den tredje form for input der læses er RFID-sensoren. Hvis der registreres den korrekte RFID-brik, vil systemet låse op (OPEN) hvis den befinder sig i en af de andre tilstande. Det er også muligt at låse døren fra OPEN tilstand hvis man scanner en RFID-brik (bemærk at døren også vil låse hvis en uautoriseret person anvender scanneren).
Den sidste form for input er Keypad’en. Arduinoen sammenligner den indtastede kode med den gemte korrekte kode. I tilfældet at koden er korrekt, vil systemet gå i enten CLOSED eller OPEN tilstand afhængig af om den nuværende tilstand er OPEN eller ej.

Til helt sidst i rækkefølgen sættes buzzeren til at larme, hvis tilstanden enten er ALARM eller EMERGENCY. Ellers springes dette skridt over.

Figur 12 – Flowdiagram

Beskrivelser af funktioner hos Arduino 1

setup()

I denne metode starter vi med at aktivere Serial.begin() for at kunne bruge vores Serial monitor.
Derefter sættes Keypad, Servo, Display, RFID, Alarm og DC motor op, med de porte som er påkrævet for at de kan sende og modtage de signaler som er krævet. Til sidst i setup() giver vi systemet den state som hedder ”Closed” og dette er for at sikre at et eventuelt strømnedbrud ikke resetter systemet og lader døren stå åben.

loop()

Denne metode følger flowdiagrammet beskrevet lidt højere oppe i afsnittet. I starten, når den skal kontrollere om der er brand, læser den værdien fra termistor-spændingsdeleren ved hjælp af analogRead. Hvis denne værdi er forbi en bestemt grænse vi har bestemt (tempSensorLimit), vil EMERGENCY-tilstanden aktiveres.

Bevægelsessensoren aflæses med en digitalRead på den port dedikeret til sensoren. Den returner enten true eller false afhængig af om der er bevægelse eller ej.

Resultatet fra RFID-scanneren hentes ved at kalde metoden rfidCheck. Metoden returnerer en streng som repræsenterer den unikke kode indbygget i en RFID-brik. Hvis ingen brik scannes, vil metoden returnere en tom streng. Dette bruger loop-metoden til at bestemme om der skal skiftes tilstand. Yderligere, hvis der scannes en godkendt RFID-brik, vil metoden blinkAnimation kaldes og displayet vil blinke et flueben. Hvis der scannes en ukendt RFID-brik, vil displayet blinke et kryds.

Logikken der håndterer Keypad’ens input minder meget om RFID-scannerens. De tal man indtaster på keypad’en gemmes i variablen received_code. Hvis received­_code ender på det afsluttende tegn (nummertegn #), sammenlignes received_code med den gemte korrekte kode, og der besluttes om tilstanden skal skiftes (meget som hos RFID-scanneren).

Sidst i loop metoden kontrolleres den nuværende tilstand, og hvis den er ALARM eller EMERGENCY (Brand), vil den afspille den ene eller anden lyd igennem buzzeren.

recieveEvent()

Oppe i setup-metoden registreres denne metode til at blive kaldt hver gang Arduinoen modtager noget fra den anden Arduino som håndterer keypad’en. Inde i metoden lægges det modtagne symbol til variablen received_code.

rfidCheck()

Her kontrolleres hvorvidt der er scannes en brik på RFID-scanneren. Hvis ikke der er registreret et en RFID-brik eller at den ikke kan læse dens unikke kode, returneres en tom streng. Ellers returneres brikkens unikke kode.

initState(State state)

Denne metode sørger for at tage den state som bliver givet som parameter og bruger denne til at aktivere de rigtige animationer i displayet samt justere servomotoren, så den passer til om døren er åben eller lukket i den pågældende tilstand. F.eks Hvis tilstanden er ”EMERGENCY”, så vil døren åbne og displayet skiftet til en flamme.

blinkAnimation(byte* sprite)

Denne metode tager et array af bytes ind som argument. Dette array er den animation som skal vises i displayet. Denne metode står så for at få displayet til at skifte mellem blankt display og vores sprite således at vores display blinker. Et eksempel er hvis brugeren indtaster korrekt kode, så vil denne metode sørge for at blinke fire gange med et flueben.

Buzzer(long duration, int  freq)

Denne metode bruges til at aktivere buzzeren på den port som den er knyttet til, og dermed sende signal om hvilken lyd den skal lave på baggrund af den frekvens som der ønskes og hvor længe hver tone skal være.

Beskrivelser af funktioner hos Arduino 2

Arduino 2 er meget simpel da dens eneste opgave er at tage inputtet fra vores keypad og videresende dette til Arduino 1, som laver alle kontroller af hvorvidt koden er godkendt eller ej.

setup()

Ligesom i Arduino 1 er vores setup lave til at initialisere de første elementer som senere skal bruges i loopet. I denne setup er det eneste vi gør at starte vores Serial Monitor med Serial.begin(), så vi har mulighed for at debugge undervejs, og derefter instantieres vores Wire-bibliotek som bruges til at lave forbindelsen mellem Arduino 1 og Arduino 2.

loop()

I loop på Arduino 2 kontrolleres der hvorvidt der er indtastet noget på vores Keypad og såfremt at det er tilfældet, så vil vi åbne en transmission til vores Arduino 1 og sende den indtastede værdi, for derefter at lukke transmissionen igen. Måden hvorpå beskeden sendes via Wire-biblioteket er over en protokol som hedder I2C. Denne protokol er lavet til Seriel kommunikation, og kan sende bytes på tværs af de forbundne enheder.

Andet

Det er også værd at tage med at denne kode også indeholder et bibliotek til håndtering af keypad og at deklarere i starten af koden hvordan vores knapper på keypadden ser ud i rækker og kolonner, og derefter registrer disse rækker og kolonner i biblioteket for at den rigtige knap, også for tildelt den rigtige værdi.

Arduino 1 code

#include <Wire.h>
#include <Servo.h>
#include <SPI.h>
#include <MFRC522.h>
#include <MaxMatrix.h>
#include <avr/pgmspace.h>

// KEYPAD INIT
String correct_code = "49555157";  // 1 7 3 9
String last_int = "";
String received_code = "";
String code_end = "35";   // #

// SERVO INIT
Servo servo;
int servoPin = 7;
int angleOpen = 180;
int angleClosed = 80;

// DISPLAY INIT
const int data  = 3;     // DIN or MOSI
const int load  = 10;    // CS
const int clock = 2;     // SCK
MaxMatrix m(data, load, clock, 1);
byte angry[] = {8, 8, B00000000, B11100110, B00100110, B00100000, B00100000, B00100110, B11100110, B00000000};
byte happy[] = {8, 8, B00000000, B11100110, B10000110, B10000000, B10000000, B10000110, B11100110, B00000000};
byte alarm[] = {8, 8, B00000000, B00000000, B00000000, B11011111, B11011111, B00000000, B00000000, B00000000};
byte emerg[] = {8, 8, B00000000, B00000000, B00111000, B01111110, B01111111, B00111100, B00000000, B00000000};
byte check[] = {8, 8, B00100000, B01000000, B10000000, B01000000, B00100000, B00010000, B00001000, B00000100};
byte cross[] = {8, 8, B10000001, B01000010, B00100100, B00011000, B00011000, B00100100, B01000010, B10000001};
byte* currentAnimation;

// RFID INIT
#define SS_PIN 6
#define RST_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
String correctRFID = "3C 39 0F 18";

// ALARM INIT
#define buzzerPin 9
#define pirPin 8

// THERMISTOR INIT
#define thermistor A0
int tempSensorLimit = 300;

// DC MOTOR INIT
#define dcMotorPin 4

enum State {
  EMERGENCY,
  ALARM,
  OPEN,
  CLOSED
};
State currentState = CLOSED;


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

  // KEYPAD SETUP
  Wire.begin(9);    // Start the I2C Bus as Slave on address 9
  Wire.onReceive(receiveEvent);   // Attach a function to trigger when something is received.

  // SERVO SETUP
  servo.attach(servoPin);
  servo.write(angleClosed);

  // DISPLAY SETUP
  m.init();
  m.setIntensity(2);  // led matrix intensity: 0-15

  //RFID SETUP
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522

  // ALARM SETUP
  pinMode(buzzerPin, OUTPUT);
  pinMode(pirPin, INPUT);

  // DC MOTOR SETUP
  pinMode(dcMotorPin, OUTPUT);

  initState(CLOSED);
}


void loop() {
  // ---------- FIRE CHECK ----------
  int tempSensorValue = analogRead(thermistor);
  if (tempSensorValue < tempSensorLimit) {
    if (currentState == ALARM || currentState == CLOSED || currentState == OPEN) {
      initState(EMERGENCY);
      return;
    }
  }

  // ---------- INTRUDER CHECK ----------
  int motion_val = digitalRead(pirPin);
  if (motion_val) {
    if (currentState == CLOSED) {
      initState(ALARM);
      return;
    }
  }

  // ---------- RFID CHECK ----------
  String rfidResult = rfidCheck();
  if (rfidResult != "") {
    if (rfidResult == correctRFID) {
      if (currentState == EMERGENCY || currentState == ALARM || currentState == CLOSED) {
        blinkAnimation(check);
        initState(OPEN);
        return;
      } else if (currentState == OPEN) {
        blinkAnimation(check);
        initState(CLOSED);
        return;
      }
    } else {
      blinkAnimation(cross);
      m.writeSprite(0, 0, currentAnimation);
      if (currentState == OPEN) {
        initState(CLOSED);
        return;
      }
    }
  }

  // ---------- KEYPAD CHECK ----------
  if (last_int == code_end) {
    last_int = "";
    if (received_code == correct_code + code_end) {
      received_code = "";
      blinkAnimation(check);
      if (currentState == EMERGENCY || currentState == ALARM || currentState == CLOSED) {
        initState(OPEN);
        return;
      } else if (currentState == OPEN) {
        initState(CLOSED);
        return;
      }
    } else {
      received_code = "";
      blinkAnimation(cross);
      m.writeSprite(0, 0, currentAnimation);
    }
  }

  // ---------- BUZZ BUZZING BUZZER ----------
  if (currentState == EMERGENCY) {
    buzzer(500, 2000);
  } else if (currentState == ALARM) {
    buzzer(500, 1600);
  }

}


void receiveEvent(int bytes) {
  last_int = (String)Wire.read();    // read one character from the I2C
  Serial.println(last_int);
  received_code += last_int;
}


String rfidCheck() {
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return "";
  }
  if (!mfrc522.PICC_ReadCardSerial()) {
    return "";
  }

  String content = "";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();

  return content.substring(1);
}

void initState(State state) {
  int motorAngle;
  currentState = state;
  if (state == EMERGENCY) {
    Serial.println("EMERGENCY");
    digitalWrite(dcMotorPin, HIGH);
    currentAnimation = emerg;
    motorAngle = angleOpen;
  } else if (currentState == ALARM) {
    Serial.println("ALARM");
    digitalWrite(dcMotorPin, LOW);
    currentAnimation = alarm;
    motorAngle = angleClosed;
  } else if (currentState == CLOSED) {
    Serial.println("CLOSED");
    digitalWrite(dcMotorPin, LOW);
    currentAnimation = angry;
    motorAngle = angleClosed;
  } else if (currentState == OPEN) {
    Serial.println("OPEN");
    digitalWrite(dcMotorPin, LOW);
    currentAnimation = happy;
    motorAngle = angleOpen;
  }
  m.clear();
  m.writeSprite(0, 0, currentAnimation);
  servo.write(motorAngle);
}

void blinkAnimation(byte* sprite) {
  for (int i = 0; i < 4; i++) {
    m.writeSprite(0, 0, sprite);
    delay(250);
    m.clear();
    delay(250);
  }
}

void buzzer(long duration, int freq) {
  tone(buzzerPin, freq);
  delay(duration);
  noTone(buzzerPin);
}

Arduino 2 code

#include <Wire.h>
#include <Keypad.h>

const byte ROWS = 4; // number of rows
const byte COLS = 4; // number of columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6}; // row pinouts of the keypad R1 = D8, R2 = D7, R3 = D6, R4 = D5
byte colPins[COLS] = {5, 4, 3, 2};    // column pinouts of the keypad C1 = D4, C2 = D3, C3 = D2
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(9600);
  // Start the I2C Bus as Master
  Wire.begin();
}


void loop() {
  char key = keypad.getKey();

  if (key != NO_KEY) {
    Serial.println(key);
    Wire.beginTransmission(9); // transmit to device #9
    Wire.write(key);              // sends x
    Wire.endTransmission();    // stop transmitting
  }
}

Opbygning af den samlede fysiske prototype

Prototypen er bygget op af en papkasse med skillerum, som således skal simulere henholdsvis indersiden og ydersiden af en yderdør.

Figur 13 – Opbyggelsen fra ydersiden

Som det ses på figur 13, så vil dem som kommer på ydersiden blive mødt med en Keypad, RFID-scanner, samt et display, og dermed har de 2 forskellige muligheder for at få adgang til alarmsystemet og dørens lås.

Figur 14 – Opbyggelsen fra indersiden

På indersiden af huset er der en længere række af komponenter. Indersiden af bygningen har tre aktuatorer, nemlig en DC-motor, En servomotor, og en buzzer, hvor DC-motorens ansvar er at lave overtryk i lokalet, såfremt der er en brand, servomotorens ansvar er at fungere som lås til døren, og buzzerens ansvar er at signalere auditivt til brugen til tilfælde af Alarm eller brand.  Som sensorer inden i bygningen har vi her en bevægelsessensor som sender signal tilbage til den ene Arduino om hvis der er bevægelse i bygningen. En anden sensor er den termistor som registrerer temperaturen i rummet og som vi dermed kan læse på i softwaren, og vurdere hvornår der er brand. Både sensorer og aktuatorer i dette rum er knyttet til Arduino 1 som i softwaren håndterer deres input og output.

På billede 14 ses det også at der er 2 Arduinoer hvoraf Arduino 1 er hjernen bag det hele, og Arduino 2 kun håndtere input fra keypad og videresender den til Arduino 1, som derefter kontrollere hvor vidt at koden er godkendt.

I dette projekt er det valgt at tilknytte en strømforsyning til fumlebrættet hvor alle komponenterne henter deres strøm fra.

Konklusion

I dette projekt er det lykkedes at bygge en prototype til et alarmsystem til hjemmet.
Alarmsystemet er bygget op af 4 aktuatorer, 4 sensorer, en H-bro, 2 Arduinoer samt flere små komponenter, som tilsammen udgør et komplet alarmsystem som kan alarmere i tilfælde af brand eller indbrud. Der er igennem projektet lavet nøje overvejelser omkring hvilke komponenter systemet skulle indeholde, hvordan disse skulle prioriteres i softwaren, samt hvordan de skulle forbindes til de to Arduinoer. Specielt det sidste viste sig som en interessant opgave da mængden af porte var begrænset.

Ved siden af hardwareløsningen er der lavet et softwaresystem, som bruger input fra hardwaren til logisk at udregne og bestemme hvilke tilstande systemet skal være i på hvilke tidspunkter, samt oplyse brugeren med både visuelle og auditive effekter.

Perspektivering

Til fremtidig forbedring af produktet ville det være optimalt at lave hele systemet væsentligt mere kompakt så de fleste komponenter ville passe ind i en dørlås. Derudover ville man skulle have et backupsystem, så at man stadig har mulighed for at åbne døren, selv hvis strømmen gik.
Termistoren skulle fjernes og systemet skulle sættes til et rigtigt professionelt brandalarmeringssystem, som mere intelligent ville kunne definere hvorvidt der er brand, da den nuværende løsning gør det nemt at udnytte varme til at få adgang til bygningen.

I en fremtidig version ville det også være muligt at udvide alarmsystemet med sensorer ved vinduer og andre potentielle indgange, for at gøre det sværere for indbrudstyve at komme uden om alarmsystemet.

More

Not-So-Smart House

Juul, Simon Helsted 
Rasmussen, Frederik Lau 
Rasmussen, Simon Møller 
Rudolf, Tom Lars Bo 

Not-So-Smart House

Vi tog udgangspunkt i at skabe en løsning til hver af de fire foreslået kategorier:

  • Et bedre indeklima
  • Et sikrere hjem
  • Et smartere hjem
  • Et mere energieffektivt hjem

Ved at skabe løsninger for alle fire kategorier, skabte vi et mere fuldendt produkt, som vi vurderer ville afspejle, hvordan man ville benytte sig af hjemmeautomation i et virkeligt hjem. Samtidig er det også en måde at vise diversiteten på de problemstillinger, som man kan løse ved hjem af hjemmeautomation.

Et bedre indeklima

Ifølge sundhedsstyrelsen beløber den totale sygdomsbyrde, der kan tilskrives indeklimaforureninger, sig årligt til tab af 2 mio. sunde leveår i 26 EU-lande. Derfor har vi valgt at skabe en løsning, som kan forbedre indeklima. For at forbedre indeklimaet har vi inkorporeret et ventilationssystem. Her benyttede vi Temperature & Humidity modulet som vores sensor og en DC-motor med en fane, som er tilkoblet en H-bro. Ifølge Conair, som udvikler ventilationssystemer, er den optimale luftfugtighed i private hjem mellem 40 og 60%. Da det kræver en del arbejde at lave en løsning for luftbefugtning, fokuserede vi på at skabe en løsning for forhøjet luftfugtighed, som ofte forekommer når man laver mad, går i bad eller tørre tøj indendørs. Derfor har vi sat vores DC-motor til at trække luft ud af huset, hvis luftfugtigheden overstiger 60%, for derved at komme af med noget af den opbyggede damp, som forekommer af de ovenstående eksempler. I forbindelse med temperaturen valgte vi at 25° var den maksimale temperatur vi ville have inde i huset, så hvis temperaturen overstiger 25° starter ventilationen og trækker frisk luft ind i huset. Vi er klar over at denne funktion ikke ville virke når udendørstemperaturen overstiger 25°, men vi mente ikke at det lå inden for projektets rammer at skabe et køleanlæg 😀

Et sikrer hjem

Til at skabe et mere sikkert hjem valgte vi at benytte os af RFID-scanneren, som roterer en servo, der låser eller åbner døren. Nogle af fordelene ved at benytte en RFID-lås er, at de er meget nemme at tilpasse til brugernes behov, at det er nemt at aktivere og deaktivere kort, hvis man smider dem væk, og at RFID-kort kan programmeres og omprogrammeres, når aspekterne af sikkerhedskravene ændres. I vores tilfælde er der så også en ulempe, hvis der ikke at strøm til kredsløbet, da det medfører at man ikke har mulighed for at låse og åbne sin dør. I den virkelige verden ville dette dog kunne løses af et backup-batteri, som ville tilføje strøm i tilfælde af en strømafbrydelse. I vores system tjekker vi om det kort, som bliver læst, er en del af de korrekte kort. Herefter tjekker den om døren er låst eller åben og gør det modsatte.

Et smartere hjem

I disse coronatider er der meget fokus på smittespredning via kontaktflader, så vi tænkte at vi ville lave et løsningsforslag til at eliminere en af de hyppigt brugte overflader i en husstand, nemlig dørklokken. Vi inkorporerede derfor en ultrasonic sensor, som kan bruges til at måle afstand til et objekt, sammen med en buzzer. På den måde har vi lavet en kontaktfri dørklokke, som aktiveres, hvis der måles en afstand under 20 cm. Som en lille gimmick har fået buzzeren til at ændre tone alt efter hvor tæt genstanden er på sensoren. Denne funktion har ingen effekt, udover at være sjov og deraf vores “Not-So-Smart” Home.

Et mere energieffektivt hjem

Vores energieffektive løsning består af en lampe, som tænder når det bliver mørkt. På den måde sørger man for kun at have lyset tændt når det er nødvendigt. For at skabe den løsning har vi benyttet os af en LDR-resistor og en LED. Hvis værdien for LDR-resistoren kommer under 400, tænder vi for LED’en og når værdien overstiger 400 igen, så slukkes LED’en. Hvis man skulle optimere denne løsning, kunne man inkorporere en bevægelsessensor, så lyset kun er tændt når LDR-værdien er under 400 og der er bevægelse omkring lampen.

Videopræsentation af Not-So-Smart House

Her skulle der ligge en video, men hver gang den bliver uploadet er der ikke noget billede på, så der ligger et link i bunden af dokumentet

Opbygning af hardware

Master/slave relation

Vi har valgt koble to Arduinoer op i en master-slave relation, i det at det gav os flere pins at arbejde med. Vi vælger samtidigt også hovedsageligt at bruge master-arduinoen til at måle værdier fra sensorere, hvorefter at master-arduinoen sender et signal til slave-arduinoen om hvilke aktuatorere der skal aktiveres.
Master-slave opsætningen er lavet ved at koble arduinoernes A4 pins sammen, A5 pins sammen, og deres ground sammen.
Master-arduinoen starter med en Wire.beginTransimission() kommando, som gør den klar til at sende en kommando til slave-arduinoen med Wire.write() kommandoen. Efter en kommando er blevet sendt, stoppes transmissionen med Wire.endTransmission(). Kommandoerne som sendes til slave-arduinoen er en char variabel såsom “c”, “w”, og “k”, som slave-arduinoen bruger til at køre forskellige funktioner.

Dørklokke

Vi valgte at lave en dørklokke ved brug af en afstandssensor, som kunne hjælpe f.eks. under corona pandemien med at begrænse smitten, i det at man begrænser fysisk kontakt med berøringsfladen.
Dørklokken er lavet ved brug af en HC-SR04 afstandssensor til at måle afstanden fra sensoren, og en passiv buzzer til at fungere som selve dørklokken (tonen).
Afstandssensorens echo (pin 5) og trig (pin 6) pins er koblet til master-arduinoen, og afstanden er sat til 20 cm.
Vcc og GND er tilslutte henholdsvis 5V og ground.
Buzzeren er tilkoblet master-arduinoes pin 8, samt ground.

RFID Card Reader

Døren til huset er sat op med en servomotor der fungerer som dørlåsen, samt et MFRC522 RFID-modul til at læse et adgangskort, og ændrer servoens position til enten at låse døren eller låse døren op.
Servomotoren er tilkoblet slave-arduinoens pin 9 og henholdsvis 5V og ground.
RFID-modulet er tilkoblet master-arduinoen, med forbindelserne SDA (pin 10), SCK (pin 13), MOSI (pin 11), MISO (pin 12), GND (ground), RST (pin 9), 3.3V (3.3V).
Når et kort eller chip med det rigtige UID-tag bliver scannet, sendes et signal til slave-arduinoen om at et korrekt kort er blevet scannet. Hvis kortet er korrekt tjekker slave-arduinoen om døren er låst eller ej, og udfører den modsatte operation.

Ventilationssystem

Ventilationssystemet er lavet ved hjælp af en DHT11 sensor, samt en DC-motor med en fane tilkoblet. DC-motoren er tilkoblet en L293D H-bro for at kunne styre DC motoren. Idéen er at hvis der bliver for varmt inde i huset, vil blæseren trække luft ind i huset, mens at hvis luftfugtigheden i huset er for høj vil blæseren blæse luften ud af huset.
DHT11 sensoren er tilsluttet i master-arduinoen pin 3, og henholdsvis 5V og ground.
L293D H-broen er tilsluttet slave-arduinoen med forbindelserne En_1 (pin 11), Input 1 (pin 13), Output 1 (DC-motor +), 4xGROUND (ground), Output 2 (DC-motor -), Input 2 (pin 12), V_motor (5V), V+ (5V)

Lys

Lyset er sat op med en LDR, som måler en værdi baseret på hvor lyst det er. Hvis det bliver mørkt, vil sensoren måle en lavere værdi, og lyset tændes.
LDR-sensoren er tilsluttet master-arduinoen, sammen med en 10 kOhms modstand. Valget af en 10 kOhms modstand er taget på baggrund af databladet for LDR-sensoren. Yderligere bruges pin A1 til at måle sensorværdien.
LED’en er tilsluttet slave-arduinoens pin 5 sammen med en 330 Ohms modstand, samt henholdsvis 5V og ground.

LCD

Der er tilsluttet et 1602A LCD display, som giver information til brugeren omkring hvilke handlinger dere bliver udført i systemet.
Displayet er tilkoblet slave-arduinoen med tilslutningerne VSS (ground), VDD (5V), V0 (ground), RS (pin 2), RW (ground), E (pin 3), D4 (pin 4), D5 (pin 5), D6 (pin 6), D7 (pin 7), A (5V), K (ground)

Programmering

Da en arduino kun har et bestemt antal pins, lavede vi en ”Master-Slave” relation mellem to arduino’er. Dette gjorde det muligt at tilkoble flere elementer til vores smart house. Arduinodelen er sat op på den måde at Masteren har alle sensorerne, mens at slaven har aktuatorne.
Hele programmet blev opbygget som en prioriteringsliste, hvilket gjorde at vi kunne styrer hvad den skulle gøre før noget andet. I vores hus tjekker den f.eks. først om der er en nøgle som bliver scannet før den tjekker om der skal luftes ud. Måden vi har implementeret det er at vi kun sender 1 ting til vores slave ad gangen. Vi sikrer os dette ved at bruge den fornævnte Wire.endTransmission.
For at få Masteren op at kører skal man beskrive hvor man skal sende sine kommandoer hen til slaven.

setup(){
  Wire.begin(); // join i2c bus (address optional for master)
}
loop(){
  Wire.beginTransmission(4); // transmit to device #4
}

Til vores RFID laver vi et Array, hvor vi manuelt tilføjer de nøgler, som skal have adgang.

setup(){
  RFID_UIDS[0] = "99 ED 47 B3";
}

Herefter kører den i loop hvor den tjekker om en nøgle er blevet scannet. Hvis den matcher en i vores Array sender den en kommando til vores slave om at en rigtig nøgle er blevet scannet. Hvis den ikke er rigtig sender den at en forkert nøgle er blevet scannet.

content = "";
  byte letter;

  for (byte i = 0; i < RFID.uid.size; i++)
  {
    content.concat(String(RFID.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(RFID.uid.uidByte[i], HEX));
  }

  content.toUpperCase();
  if(content != ""){
    if (content.substring(1) == RFID_UIDS[0] || content.substring(1) == RFID_UIDS[1]) //UID of the access cards
    {
     CardReadBuzz(accessDT, 50);
     delay(100);
     CardReadBuzz(accessDT, 50);
     //Send korrekt til slave
     cmd ='c';
     Wire.write(cmd);
     Wire.endTrans
     }
     else
     {
      CardReadBuzz(deniedDT, 25);
      delay(50);
      CardReadBuzz(deniedDT, 25);
    
      //SEND FORKERT TIL SLAVE
      cmd = 'w';
      Wire.write(cmd);
      Wire.endTransmission();
      content = "";
    }
    Wire.endTransmission();    // stop transmitting
    delay(1000);
  }

Hvis koden kommer igennem RFID delen uden at den bliver stoppet, vil den måle luftfugtighed og temperatursensoren. Første prioriteten valgte vi at skulle være luftfugtighed, hvorefter den prøver at justere temperaturen hvis den er for høj.

//Vi kører den kun hver 2 sekund for at undgå fejl ved aflæsning af værdierne.
  currentMilli = millis();
  if(currentMilli - startMilli >= period)
  {
    //Får dataen fra sensoren
    int chk = DHT.read11(DHT11_PIN);

    //hvis luftfugtiheden er over 60% sender den 'h' til slaven
    if(DHT.humidity > 60 && highHum == false){
      highHum = true;
      highTemp = false;
      cmd = 'h';
      Wire.write(cmd);
      Wire.endTransmission();
    }
    //Hvis luftfugtigheden ikke er over 60% og den har været over 60% siden sidst, sender den 's' til slaven
    else if (DHT.humidity < 60 && highHum == true){
      highHum = false;
      cmd = 's';
      Wire.write(cmd);
      Wire.endTransmission();
    }

    //Hvis temperaturen er over 25 grader og luftfugtigheden ikke er over sender den 't' til slaven
    if(DHT.temperature > 25 && highTemp == false && highHum == false){
      highTemp = true;
      cmd = 't';
      Wire.write(cmd);
      Wire.endTransmission();
    }
    //hvis den kommer under 25 efter den har været i gang sender den 's' til slaven
    else if (DHT.temperature < 25 && highTemp == true && highHum ==false){
      highTemp = false;
      cmd = 's';
      Wire.write(cmd);
      Wire.endTransmission();
    }
    
    startMilli = currentMilli; 
  } 

Efter vores luftfugtighed og temperatur tjekker vi om det er mørkt udenfor. Dette gør vi med en LDR-sensor. Hvis dens værdier kommer under et vist punkt, tænder vi en lampe og hvis den kommer over igen, bliver den slukket.

 //Får dataen fra LDR sensoren
  ldrValue = analogRead(LDR);

  //Hvis den er lavere end 400 sender den 'l' til slaven
  if(ldrValue < 400 && lampLight == false){
    cmd = 'l';
    Wire.write(cmd);
    delay(100);
    lampLight = true;
    Wire.endTransmission();
  }
  //hvis den er over 400 og lampen er tændt, sender den 'k' til slaven
  else if(ldrValue > 400 && lampLight == true) {
    cmd = 'k';
    Wire.write(cmd);
    delay(100);
    lampLight = false;
    Wire.endTransmission();
  }

Dørklokken og buzzeren er lidt speciel da de sidder på Masteren. Dette gør at de altid vil fungere selvom at tidligere funktioner har kørt.

//Ultrasonic
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance= duration*0.034/2;

  //hvis den er inde for 20cm bliver der spillet en tone ellers sender den ingen tone
  if(distance <= 20){
    tone(BUZZER, 10000/distance);
  }else{
    noTone(BUZZER);
  }
}
//spiller en melodi med forskellige delay og forskellige tone
void CardReadBuzz(int delayTime, int buzzTimes) {
  for (int i = 0; i < buzzTimes; i++) {
    digitalWrite(BUZZER, HIGH);
    delay(delayTime);
    digitalWrite(BUZZER, LOW);
    delay(delayTime);
  }
}

I masteren sender den en ”char” til slaven. Alt efter hvad denne ”char” er, gør slaven forskellige ting med dens aktuatorer. For at skabe forbindelse til Masteren skal man gøre den klar til at modtage.

 //Begynder at modtage på pin A4 og tager imod events
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event

//Hver gang der kommer en kommando, bliver vores cmd variable lig med det.
void receiveEvent(int howMany)
{
   while(0 < Wire.available()) // loop through all but the last
  {
    cmd = Wire.read(); // receive byte as a character
  }
}

I slaven er der et stort If/else if-statement som kører forskellige funktioner alt efter hvad Masteren sender.

void loop()
{
  Serial.println(cmd);

  NormalMessageLCD();

  if(cmd == 'c')
  {
    CorrectKey();
  }
  else if(cmd == 'w')
  {
    WrongKey();
  }
  else if(cmd == 'l')
  {
    LampON();
  }
  else if(cmd == 'k')
  {
    LampOFF();
  }
  else if(cmd == 'h'){
    HumSuck();
  }
  else if(cmd == 't'){
    TempSuck();
  }
  else if(cmd == 's'){
    DCStop();
  }
  cmd ="";
  delay(100);
}

På billedet er der illustreret hvordan programmet ville kører igennem et flowdiagram.

Den samlede prototype

Modellen er opbygget på en måde der er meget funktionel orienteret og der blev ikke tage særlig meget hensyn til æstetik. Den består af pap og blev samlet ved hjælp af gaffatape og en limpistol.
På forsiden befinder der sig en dør der kan låses med et RFID-kort. RFID-scanneren befinder sig ved siden af døren. Desuden sidder der et display over døren, hvilket giver information om kortet enten bliver godkendt eller afvist. Den mekaniske del af låsen består en servo-motor og lidt lego (billede). Når kortet bliver godkendt, bevæger servoen sig 90 grader i enten den ene eller den anden retning.

Dørklokken er også ved siden af døren og består af en buzzer og en afstands-sensor. Når sensoren sanser noget inden for 20 cm, aktiveres buzzeren. Buzzerens frekvens bestemmes af den sansede afstand.

Lampen befinder sig på en arm på siden af huset og består af en LED og en LDR-sensor. Når LDR-sensoren sanser at det bliver mørkt udenfor bliver LED’en tændt.

Ventilations-systemet består af en temperatur og luftfugtigheds –sensor og en DC-motor som fungerer som ventilator.  Temperatur og luftfugtigheds -sensoren befinder sig inden i huset. Ventilatoren befinder sig i en ekstra boks der sidder på siden af huset. Når temperaturen i huset kommer over 25 grader, vil ventilatoren trække luft ind i huset og når luftfugtigheden overstiger 60% vil den trække luft ud af huset.

Arduinoerne er placeret på bagsiden af huset sammen med to breadboards, hvilket gjorde det mere overskueligt at samle alle komponenter.

Konklusion

Vi vurderer at vores løsningsforslag lever op til de krav vi satte i starten af projektet og vi viser hvor diversificeret problemstillinger man kan løse ved hjemmeautomation. Hver del af projektet løser et specifikt problem, som kunne være med til at forbedre levevilkårene i et privat hjem eller arbejdsplads. Vi har vist hvordan man kan optimere indeklimaet med et ventilationssystem, hvordan man kan gøre sin dørlås mere sikker og nem at tilpasse til den enkeltes behov, hvordan man kan skabe energieffektiv udendørsbelysning og hvordan man kan mindske spredning af virus ved at lave en kontaktfri dørklokke. Vi vurderer at alle løsninger ville være mulige og værd at installere, hvis man ønskede at optimere sit hjem eller arbejdsplads. Ved alle løsningerne ville det være muligt at optimere større eller mindre ting, men de grundlæggende funktioner fungerer som de skal.

Perspektivering

Generelt er vi tilfredse med vores løsninger, men hvis de skulle inkorporeres i et ægte hus, kommer der her en liste over forbedringer til de forskellige løsninger.

Dørklokken

I vores løsning sidder buzzeren udenfor huset, da det gav mest mening når vi skulle teste prototypen, så i et rigtigt hus skulle den selvfølgelig sættes indenfor. Men for at give brugeren en form for feedback når de har aktiveret dørklokken, kunne man tilføje en LED, som lyste når den havde modtaget et input, eller en lille buzzer, som gav auditiv feedback ved input.

RFID-lås

I vores version hardcoder vi de rigtige kort ind, men for at optimere dette, skulle man implementere at man kan tilføje og fjerne kort med et ‘master’kort. I forhold til RFID så er der rigtig mange muligheder for at lave et smartere system alt efter behov. Så hvis man skal bruge det i en stor kontorbygning, kunne man f.eks. bruge det til at tracke hvilke lokaler som er frie, hvor mange som benytter sig af lokale X eller hvor når den seneste person gik fra lokale Y osv.

Udluftning

Som beskrevet tidligere fungere vores temperaturregulation kun så længe at temperaturen udvendigt er koldere end 25 grader, så her kunne man med fordel tilkoble et køleanlæg

Lys

For at optimere energibesparelsen ved vores lys kunne man forbinde den med en bevægelsessensor, så lyset kun tændte når det var mørkt og der var nogen til stede inde for lysets rækkevidde.

Bilag

Link til video og Arduino-kode:
https://drive.google.com/drive/folders/1oFmt8Ly_ZknmvZzK0wxpJ3Eov0kahYXn?usp=sharing

More

MAKkamaster 3000

af Anders, Kasper og Michelle

Kender du det, når du vågner op om morgenen, og du dårligt kan tænke, før du har fået din første kop kaffe?

Det kan vi heller ikke.

Vi har derfor ombygget en almindelig kaffemaskine efter princippet at have en app, hvor man fra sengen af, allerede når man vågner, kan sætte kaffemaskinen i gang og vælge antal kopper, man ønsker brygget, inden man står ud af sengen.

Kaffemaskinen er dog i denne prototype styret via arduino og tilslutning til computer. Dette har udgjort denne løsning:

I denne video er maskinen testet, mens den brygger 10 kopper for at få vandsensorens funktion med.

For at bygge en lignende kaffemaskine skal du bruge:

1 Kaffemaskine

2 Arduino

1 Servo motor

1 LCD1602 display

1 Passiv buzzer

1 Vandsensor

1 LED

1 Diode rectifier

1 HC-SR501 PIR motion sensor

1 NPN PN2222 Transistor

1 5V Relæ

1 Ultrasonic sensor

1 Potentiometer

Følgende modstande:

1 x 100 Ω

1 x 220 Ω

1 x 1K Ω

og en god portion ledninger

Opsætningsvejledning af elektronik og hardware

For at have nok pins til rådighed, har vi brugt to arduinoer og sat dem i master-slave-opsætningen ved brug af I2C kommunikation (kilde 1), hvilket kan få flere enheder til at kommunikere mellem hinanden ved brug af kun to ledninger. Dette er gjort ved at forbinde dem analogt fra pin 4 til 4 og pin 5 til 5. Den sidste tilslutning mellem de to arduinoer er en ground til ground. Med denne opsætning sidder alle sensorer på master og aktuatorer på slave.

Opsætning af to arduinoer i master-slave-opsætning i Tinkercad.

Vi lægger ud med tilslutningen af vores display på slave arduinoen, der skal synliggøre for brugeren, hvor i brygningsprocessen kaffemaskinen befinder sig. Ledningerne er forbundet som vist på nedenstående billede og i underliggende skema. Der er anvendt en modstand på  220 Ω i tilslutningen til backlight pin. Dette er gjort på baggrund af måling af spændingsfald på displayet, der var 0,01. Vi har herefter regnet modstanden via formlen R = (Vss-3,3)/0,01. Resultatet er 170, hvorfor vi har rundet op til den nærmeste modstand, vi havde tilgængelig.

Tilslutning af display på slaven opstillet i Tinkercad

PinTilslutning
1GND
25 V
3GND
4Digital 7
5GND
6Digital 10
7
8
9
10
11Digital 2
12Digital 3
13Digital 4
14Digital 5
15220Ω + 5V
16GND

De forskellige pins er sat op med afsæt i deres funktion, som er angivet i denne tabel:

Kilde: https://create.arduino.cc/projecthub/najad/interfacing-lcd1602-with-arduino-764ec4

Derefter har vi tilsluttet en buzzer på slaven, så kaffemaskinen kan udsende en lyd, hvis der påfyldes for stor mængde vand. Buzzeren er tilsluttet digital pin 8 og en modstand på 100 Ω jævnfør arduino projektvejledning (Kilde 2).

Opsætning af buzzer på slaven i Tinkercad

Bevægelsessensoren slår relæet og dermed kaffemaskinen fra, når kaffen er færdig og bliver hentet. Bevægelsessensoren er tilsluttet digital pin 7 på masteren.

Opstilling af bevægelsessensorens tilskulning til masteren i Tinkercad.

For at være sikker på, kaffemaskinens vandtank ikke løber over ved påfyldning, har vi sat en vandsensor, der giver besked ved overflow. Vandsensoren er tilsluttet masteren på analog pin A2, og power på vand sensoren er sat til digital pin 2, som vist herunder, da dette øger levetiden på sensoren, da der kommer korrosion hurtigere på sensoren, når den er tændt hele tiden (Kilde 3).

Vandsensor tilslutning til master i Tinkercad med lidt hjælp fra Paint.

For at kontrollere mængden af kaffen, der skal brygges, har vi tilføjet en kaffedispenser, der skal kontrollere, hvor stor mængden af kaffe, der tilføres filteret. Denne beholder består at en cylinderform, der er åben i toppen og med en låge i bunden, som bevæges af en servomotor. Servoen er tilsluttet digital pin 11 på slaven.

3D tegning af kaffedispenser med bunden opad.

Opstilling af servomotor-tilslutning på slaven i Tinkercad.

Åbning og lukning af dispenser med servo

For at finde ud af, hvor længe dispenseren skal være åben, har vi beregnet kaffens flow igennem:

Beregning af kaffes flow gennem dispenseren.

Vi er derfor kommet frem til, at den skal være åben ca. 22 ms pr kop, da der bruges ca 3,5 g kaffe pr kop.

De 3,5 g er fundet ved at veje den mængde kaffe, der kan være i en doseringsske til 2 kopper. Denne mængde vejede 7 g, og der må derfor gå 3,5 g pr kop.

Brugeren af kaffemaskinen kan vælge antallet af kopper, der skal brygges ved hjælp af et potentiometer. Dette er tilsluttet masteren på analog pin A1.

Tilslutning af potentiometer til master i Tinkercad.

For at tænde kaffemaskinen, har vi benyttet en sonar. Når den registrere en afstand på 5 cm, vil relæet tænde for strømmen, så kaffemaskinen kan påbegynde kaffebrygningen. Sonaren er tilsluttet masteren via digital pin 12 på triggeren og digital pin 13 på echo.

Tilslutning af sonar til masteren i Tinkercad.

For at kontrollere strømtilslutningen til kaffemaskinen, er der sat et relæ på opstillingen. Relæet er tilsluttet kaffemaskinen via ben normaly open. Herudover er relæet tilkoblet en diode for at ensrette spændingen i opstillingen, så der ikke sker et tilbageflow, når transistoren er slukket. Transistorens påsatte modstand er 1 kΩ jævnfør datablad (Kilde 4).

LED’en i denne opstilling repræsenterer tlslutningen af kaffemaskinen.

Relæets tilslutning til kaffemaskine og diode i Tinkercad. LED repræsenterer kaffemaskinen.

Opbygning af program

For at master kan sende data til slave, er dataen omdannet til et array med 4 pladser. Transmissionen kører så via et forloop, der læser data på de fire pladser, sender den læste data, stopper transmissionen og starter så forfra efter 0,5 sekunder.

Kodeudsnit af Masters datatransmission til Slave

Kaffebrygningen er tidsstyret, og vi har derfor taget tid på kaffemaskinen, mens den har brygget forskellige mængder kaffe. Disse tider er herefter indsat i koden, for at sætte tidsbegrænsning på brygningsstadiet.

Tidstagning under kaffebrygning.

I tidsberegningen skal der ud over bryggetiden tages hensyn til servoens åbnetid. Det har vi gjort med inten openTime, der er fastsat via kilde 5.

Kodeudsnit af servostyring

Ud fra tidstagningen er der derefter estimeret en samlet brygningstid, der spænder fra relæet åbner for strømmen til maskinen og til kaffen er færdigbrygget. Tid er brugt som indikation, da der ikke var en tilgængelig sensor, der kunne måle på mængden af færdigbrygget kaffe, og maskinen ikke har en automatisk sluk-knap.

Kodeudsnit af brygningstid

Kodningen kan inddeles i tre tilstande; præ-brygning, brygning og brygning afsluttet.

Under præ-brygning holdes der øje med, at der ikke sker påfyldning af for meget vand i beholderen. Sker dette vil buzzeren aktiveres som advarsel. Herudover afventes angivelse af antal kopper, der ønskes brygget. Antallet kan ses på displayet. Når antallet er angivet, afventes startsignalet, som er fra ultrasonic sensor. Så snart dette signal opfattes, startes brygnings tilstanden.

Under brygning doseres kaffemængden til filteret, og strømmen tilsluttes til kaffemaskinen, så kaffebrygningen kan påbegyndes.

Ved Brygning afsluttet afventes registrering af bevægelse fra bevægelsessensoren, så den bryggede kaffe fjernes, inden der returneres til præ-brygning stadiet.

Programmets flow kan beskrives som i nedenstående diagram:

Kode til Master arduino

#include <Wire.h>

float floatMap(float x, float in_min, float in_max, float out_min, float out_max)
{
  return(x-in_min)*(out_max - out_min)/(in_max-in_min)+out_min;
}

int data[4];

int potPin = A1;
int potVal = 0;
int pirPin = 7;
int state = LOW;
int pirValue = 0; // Send
int sonarTrig = 12; 
int sonarEcho = 13; 
int distance; // Send
long duration;
int waterPin = A2; 
int waterPower = 2; 
int waterVal = 0; // Send

int cups = 0; // Send

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

  pinMode(sonarTrig, OUTPUT);
  pinMode(sonarEcho, INPUT);
  pinMode(pirPin, INPUT);
  pinMode(waterPower, OUTPUT);
  digitalWrite(waterPower, LOW);
  
  Wire.begin(); // Starts the I2C Bus as Master
}


void loop() {
  // reads value from potentiometer
  potVal = analogRead(potPin);

  // remaps the value from 0 to 10 and adds variable to array.
  float value = floatMap(potVal, 0, 1023, 0, 10);
  cups = value + 0.5;
  data[0] = cups;

  // sends signal from the ultrasonic distance sensor
  digitalWrite(sonarTrig, HIGH);
  delayMicroseconds(10);
  digitalWrite(sonarTrig, LOW);

  // registers the time the signal takes to return and calculates it to a distance, then adds the distance to array
  duration = pulseIn(sonarEcho, HIGH);
  distance = 0.017 * duration;
  data[1] = distance;

  // reads the value of the PIR motion sensor and adds the value to the array
  pirValue = digitalRead(pirPin);
  data[2] = pirValue;

  // opens the power, reads the value, closes the power of the water-sensor and adds the value to array
  digitalWrite(waterPower, HIGH);
  delay(10);
  waterVal = analogRead(waterPin);
  digitalWrite(waterPower, LOW);
  data[3] = waterVal;
  
  // Sends the variables to slave, by looping through the loop and sending the data.
  Wire.beginTransmission(9); // transmit to device #9
  for(int i = 0; i < 4; i++){
    if(i == 4) {
      i = 0;
    }
    Wire.write(data[i]);              // sends x 
  }
  Wire.endTransmission();    // stop transmitting
  
  delay(500);
  
}

Kode til slave arduino

#include <Wire.h>
#include <Servo.h>
#include <LiquidCrystal.h>

Servo myServo;

int data[4];

int Relay = 6; 
int buzzerPin = 8;

int openTime = 200;
int servoClosed = 0;
int servoOpen = 90;

int cups = 0;
int distance = 0;
int pirValue = 0;
int waterVal = 0;

int brewTime = 0;
bool brewing = false;

const int rs = 7, en = 10, d4 = 2, d5 = 3, d6 = 4, d7 = 5;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

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

  myServo.attach(11);
  myServo.write(servoClosed);
  
  pinMode(buzzerPin, OUTPUT);
  pinMode(Relay, OUTPUT);

  Wire.begin(9); // Starts transmission with master using I2C 
  // Attaches a function to trigger when something is received.
  Wire.onReceive(receiveEvent);
}

void receiveEvent(int bytes) {
  // loops through the data retrieved and adds the values to the four sensorvariables
  for(int i = 0; i < 4; i++){
    if(i == 4) {
      i = 0;
    }
    data[i] = Wire.read(); // read one character from the I2C
  }
  cups = data[0];
  distance = data[1];
  pirValue = data[2];
  waterVal = data[3];
}
void receiveNoEvent(){
  // Nothing
}

void loop() {
  while (!brewing) {
    // lcd display shows amount of cups to brew.
    lcd.begin(16,2);
    lcd.print("CUPS:");
    lcd.setCursor(0,1);
    lcd.print(cups);

    // if distance from sonar to hand is closer than 5cm and there are more than 1 cup, on display -> run function to make coffee.
    if(distance < 5 && cups != 0) {
      MakeCoffee(cups);
    }
  
    // Read water-level and if high enough or overflow -> Turn on buzzer
    if(waterVal > 160){
      tone(buzzerPin, 10);
    }
    else {
      noTone(buzzerPin);
    }

    // Use the PIR motion sensor to detect person in room to turn of relay
    if(pirValue == 1){
      digitalWrite(Relay, LOW);
    }

    delay(500);
    // Turn water power on and off between reading.
  }

  while (brewing) {
    // lcd display shows the remaining brewing time in seconds.
    lcd.begin(16,2);
    lcd.print("SECONDS REMAINING:");
    lcd.setCursor(0,1);
    lcd.print(brewTime);

    delay(1000);
    brewTime -= 1;
  }
}

void MakeCoffee(int cups) {
  // Disables sensors from interupting the relay from making coffee
  Wire.onReceive(receiveNoEvent);
  brewing = true;

  // disables buzzer
  noTone(buzzerPin);
  
  // calculates the time the servo needs to be open (22ms*cups)
  int servoDelay = openTime+(22*cups);
  
  // Fill coffee in the filter by opening and closing the servo 
  myServo.write(servoOpen);
  delay(servoDelay);
  myServo.write(servoClosed);

  delay(500);
  
  // Turn on relay that brews the coffee
  digitalWrite(Relay, HIGH);
  
  // have the relay running for x amount of time based on cup
  if(cups == 1 || cups == 2){
    delay(275000);
    brewTime = 275;
  } else if(cups == 3 || cups == 4){
    delay(400000);
    brewTime = 400;
  } else if(cups == 5 || cups == 6){
    delay(650000);
    brewTime = 650;
  } else if(cups == 7 || cups == 8){
    delay(800000);
    brewTime = 800;
  } else if(cups == 9 || cups == 10){
    delay(940000);
    brewTime = 940;
  } 

  // after delay, reset the void loop, so sensors can get data again.
  Wire.onReceive(receiveEvent);
  brewing = false;
}

Samlet opbygning af fysisk prototype

Samlet opbygning i Tinkercad

Samlet opbygning i Schematics. Denne er ikke komplet, da nogle af vores komponenter ikke fandtes i programmet og derfor er indsat som noter.

Billeder af den færdige opstilling med kaffemaskine

Kaffedispenseren er sat lige over filteret, mens vandsensoren er sat direkte ned i vandbeholderen. Resten af elektronikopstillingen er placeret ved siden af maskinen med ultrasonic- og bevægelsessensor placeret frit foran maskinen til registrering af bevægelser for start og stop.

Perspektivering

For at perfektionere vores prototype, bør der tilføjes en regulerbar vandtilslutning, så kaffemaskinen kun tager den mængde vand ind i beholderen, der skal bruges til det ønskede antal kopper på lige fod med kaffedispenseren. I den forbindelse bør vandsensoren også være længere, så det er muligt at have status på, hvor fyldt vandbeholderen er, og den bør være mere vandtæt i toppen, da der dannes kondens på indersiden af låget.
En grund til, at vi endte ud med 8 kopper kaffe i stedet for de 10, vi bryggede i testvideoen, kan være at vores vand sensor kom op på de 160 units, som der står i koden at den skal reagere ved, tidligere end hvad vi før havde målt. Dette kan evt. løses med en anden sensor, som alligevel ville blive brugt, hvis man skulle måle ud til andre kopper kaffe. Grove 10cm liquid sensor kan blive brugt ved kaffemaskiner, hvor vand beholder er under 10 cm dyb.

Vi oplevede at tingene på toppen af maskinen (kaffedispenseren især), der var limet på, ikke blev stående efter endt brygning ved længerevarende brygningstid, da den varme damp smeltede limen, der holdt det på plads. Denne problematik knytter sig til den anvendte kaffemaskine, da vi på maskinen før dette, havde mere plads at arbejde på, hvor tingene ikke ville komme i forbindelse med den varme damp.

Den kaffemaskine, vi har anvendt har et vandtab, der stiger med antallet af kopper kaffe, der bliver brygget. Vandtabet ligger på ca 9% vurderet ud fra, at der ved påfyldning til 8 kopper kun brygges 7,5 kopper.

Konklusion 

Vores mål om at lave en opsætning, der illustrere en app-styret kaffemaskine er lykkedes.

Det er muligt at styre mængden af kaffe, der brygges baseret på antal kopper, gennem potentiometer, kaffedispenser og servo. Det er herudover muligt at vise, hvilket stadie brygningen befinder sig i, samt valgte antal kopper via displayet og styre strømtilslutningen til kaffemaskinen via relæ opsætningen.

Konstruktionen kan med få ændringer overføres til app-styring.

Kilder

Kilde 1: https://www.digikey.dk/en/articles/why-the-inter-integrated-circuit-bus-makes-connecting-ics-so-easy?utm_adgroup=Integrated%20Circuits&utm_source=google&utm_medium=cpc&utm_campaign=Dynamic%20Search_EN_Product&utm_term=&productid=&gclid=CjwKCAjwj6SEBhAOEiwAvFRuKOJzQJkPkanAJQZMgViC72uDLx7UY-sJbQLPfvjP5-SSjGrMK5TJjBoCpgUQAvD_BwE

Kilde 2: https://create.arduino.cc/projecthub/SURYATEJA/use-a-buzzer-module-piezo-speaker-using-arduino-uno-89df45

Kilde 3: https://lastminuteengineers.com/water-level-sensor-arduino-tutorial/

Kilde 4: https://www.onsemi.com/pdf/datasheet/p2n2222a-d.pdf

Kilde 5: https://datasheetspdf.com/pdf/791970/TowerPro/SG90/1

More

Light Suppressor 6969

Gruppe:

Jonas Lund – Jolun18@student.sdu.dk
Patrick Nielsen – Panie18@student.sdu.dk
Mads Emil Falkenstrøm – Mafal17@student.sdu.dk


Indledning

Vores problemstilling henvender sig til problematikken omkring automatisering af lys og temperaturregulering af et rum. Når morgen undervisningen begynder kl 8, er det ikke altid man lige får rullet gardinerne fra og lader morgensolen komme ind. Et velkendt scenarie de fleste nok kender til. Dette kan føre til mørke rum, og en forøget elregning da man nu er nødt til at tænde lyset i stedet. Det er måske også nødvendigt at tænde en radiator da solen ikke kan varme rummet op på samme måde som hvis gardinerne var trukket fra.
Det modsatte scenarie kan også gøre sig gældende. Forestil dig at du er midt i en god undervisning, og solen pludselig rammer din skærm så du ikke kan se hvad din underviser har gang i. Men du har heller ikke noget trådløst headset. Hvad gør du? Introducing: 

Light Suppressor 6969.

Et smart automatiseret system der selv åbner og lukker gardinet når temperaturen bliver for høj eller lav. Den medfølgende fjernbetjening sørger for at brugeren selv kan rulle gardinet fra eller til hvis man er uenig med robottens beslutning. Derudover medfølger der også en lydsensor, der gør det muligt at aktivere systemet ved at klappe 2 gange i træk.

Video og billeder

Video demo af klappe funktionen
Video demo af fjernbetjening
Billede af robotten

Opbygning af hardware – fra Fritzing

Følgende komponenter blev brugt i forhold til opsætningen af systemet:

ComponentQuantity
Arduino Uno1x
X113647(ULN2003) Stepper Driver Board1x
Stepper Motor (28BYJ-48)1x
KY-038 Sound Sensor Module1x
KY-022 Infrared Receiver Module1x
Thermistor1x
10k Ω 2x
Green LED1x
Red LED1x
Pushbutton1x

Valgte løsninger

Til systemet er et væld af løsninger blevet implementeret for at sikre god diversitet så alle brugere kan finde den løsning der passer bedst for dem. Der er blandt andet tilført en lydsensor til at opfange når der klappes, for at rulle gardinet til at fra. Yderligere er der tilføjet en knap for mere fysisk anvendelse, og der er også tilføjet en fjernbetjening så man ikke behøver at rejse sig for at trykke på knappen på robotten.
For at robotten automatisk skal kunne rulle gardinerne til eller fra er der tilføjet en termistor for at måle temperaturen. Bliver der for varmt i rummet rulles gardinerne automatisk for, og fra hvis der er for koldt i rummet.
Der er anvendt to LED indikatorer for at vise robottens tilstande. Rød for at indikere at robotten er i mute tilstand, og grøn for at vise at robotten modtager et signal.
Der anvendes en stepper motor og h-bro som gør brug af en darlington motor driver. Dette gøres for at motoren kan dreje både med- og mod uret. Denne funktionalitet gør at gardinet både kan rulles for, men også fra.

Opbygning af program

Flow- og tilstandsdiagrammer

tilstande: PAUSED, CLOSED, OPEN

Funktioner

STEPS

Der er kun 32 trin (11,25 grader) pr. Omdrejning, og indeni er der et reduktionssæt på 1/64. (Faktisk er dens 1 / 64,128, men for de fleste formål er 1/16 en tilstrækkelig tilnærmelse) Hvad dette betyder er, at der virkelig er 32 * 64,128 trin pr. Omdrejning = 2052 trin. [1]

close_curtain

Når vi får stepper motoren til at dreje, går vi det et trin ad gangen og tjekker løbende om man via infrarød fjernbetjeningen har sendt en power off kommando, som vil tvinge robotten i en PAUSE tilstand, der går at vi bryder ud af while loopet, der får motoren til at dreje, når vi er færdige deaktiver vi motoren for at spare på strøm og varme.

get_temperature_in_celcius

Fra spændingsdelerkredsløbs formlen får vi givet at:

Vout= (Vin * Rt) / (R + Rt)

Så vil værdien af Rt være givet på formlen:

Rt = R (Vin/Vout) – 1

Her vil Rt være modstanden af ​​termistor og R vil være 10k ohm modstand.

Denne ligning bruges til beregning af termistorresistens ud fra den målte værdi af udgangsspændingen Vo. Vi kan få værdien af ​​Voltage Vout fra ADC-værdien ved pin A0 i Arduino som vist i Arduino-koden angivet ovenover.

Beregning af temperatur fra termistormodstanden. Matematisk kan termistormodstanden kun beregnes ved hjælp af Stein-Hart-ligningen:

T = 1 / (A + Bln(Rt) + Cln (Rt)3 )

Hvor, A, B og C er konstanterne og Rt er termistormodstanden og ln repræsenterer log.

Den konstante værdi for den anvendte termistor i projektet er A = 1.009249522 × 10−3, B = 2.378405444 × 10−4, C = 2.019202697 × 10−7. Disse konstante værdier kan opnås fra regnemaskinen her ved at indtaste de tre modstandsværdier for termistor ved tre forskellige temperaturer. Du kan enten få disse konstante værdier direkte fra databladet til Thermistor, eller du kan få tre modstandsværdier ved forskellige temperaturer og få konstantværdierne ved hjælp af den givne lommeregner.

Så til beregning af temperaturen har vi kun brug for værdien af termistormodstand. Efter at have fået værdien af Rt fra ovenstående beregning anbringes værdierne i Stein-hart ligningen, og vi får værdien af temperaturen i enheden kelvin. Da der er mindre ændringer i udgangsspændingen, forårsager temperaturændring. [2]

check if sound claps

I vores algoritme for at tjekke om vi har klappet 2 gange for at aktivere gardinet, tjekker vi først om der i øjeblikket er en lyd, for at sikre os at afvise flere lyde i en enkelt loop cyklus tjekker vi på om nuværende støj tid er over sidste støj tid og lægger en grænse på, samt tjekker vi om der var stille før nuværende støj detektion. Derefter bliver der tjekket om det aktuelle klap er mindre end 0.8 sekunder efter det som vi antager for at være det første klap. Til sidst for at undgå et tredje klap som en del af mønsteret.

Prioriteringer

Systemet starter så snart der enten trykkes på fjernbetjeningen, den fysiske knap på maskinen eller den registrerer en klappen, såfremt den ikke er muted. Hvis fjernbetjeningen anvendes kan der, som det ses i flowdiagrammet, anvendes flere knapper for at styre åbning, og lukning af gardiner, samt sætte robotten i pause state. Det er også muligt at “mute” lyd og temperatur.
Den fysiske knap anvendes også til styring af gardinerne, og hvis benyttet tjekkes state først, og derefter åbnes, eller lukkes gardinerne alt efter staten.
Det er også muligt at anvende en klappe mekanisme for at styre gardinet. Hvis robotten ikke er muted, vil den registrere en klappen med hænderne og følger herefter samme mønster som nævnt før. Hvis en klappen ikke bliver registreret vil systemet selv åbne og lukke gardinerne alt efter temperaturen i rummet.

Det er værd at bemærke at fjernbetjeningen vægtes højere end de to andre funktioner, hvor den fysiske knap har en højere prioritet end hvis robotten ikke er muted. Den automatiske løsning vil altså altid vige for brugen af den fysiske knap, som igen må vige for brugen af fjernbetjeningen.

Konklusion

Light Suppressor 6969 leverer en multifunktions indeklima justerings- og optimerings løsning, komplet med automatiseret åbning og lukning af vinduer, en knap så muligheden for selv at styre om de skal være åbne eller lukkede, en lydsensor der gør det muligt at klappe hænderne sammen for at få den til at åbne og lukke, samt en fjernbetjening for nemt at åbne og lukke gardinerne. Vi mener at vores problemstilling er løst med en gennemtænkt løsning.  

Perspektivering

En yderligere udvidelse til systemet ville være tilføjelsen af muligheden for automatisk at åbne og lukke vinduet til at fremme indeklimaet og temperaturregulering.
Det ville yderligere være en opgradering at anvende en stærkere motor for nemmere at kunne dreje gardinet rundt. Diverse sensorer kunne også ændres til analog for at optimere lys- og temperatur sensitiviteten, samt have muligheden for at kunne indstille sensitiviteten via fjernbetjeningen og muligvis tilføje et LCD-display til at give et overblik over nuværende temperatur og hvad ens sensitivitet er sat til. Ved tests kørsel af robotten, fandt vi frem til at robotten vejede for lidt i forhold til den kraft den skulle bruge til at kunne rotere gardinet, så fremadrettet vil en montering på væggen eller tilføje vægt til robotten kunne afhjælpe dette problem.
Light Supressor 6969 har 2 LED’er dog uden nogen resistor. Dette kan være med til at begrænse deres levetid, og bør laves om i det endelige design.

Kode

#include <IRremote.h>
#include <Stepper.h>
#define STEPS 2052 // the number of steps in one revolution of your motor (28BYJ-48)
// general setup
const int delayTime = 500;
const int buttonPin = 6;
int buttonState = 0;    
// sound setup
const int soundSensor = 7;
const int ledPin = 5;
const int mutedLedPin = 4;
boolean val = 0;
bool muted = false;
int lastSoundValue;
int soundValue;
long lastNoiseTime = 0;
long currentNoiseTime = 0;
long lastLightChange = 0;
// motor setup 
int numberOfRotations = 4.5;
//const int stepsPerRevolution = 2048; 
int motorPins[] = {8, 9, 10, 11};
Stepper stepper(STEPS, 8, 10, 9, 11);
// remote setup
int IR_RECEIVE_PIN = 12;
// thermistor
int ThermistorPin = 0;
int Vo;
float R1 = 10000.0;
float logRt, T, Tc;
float A = 1.009249522e-03, B = 2.378405444e-04, C = 2.019202697e-07;
// states
enum RobotStates { PAUSED, CLOSED, OPEN };
RobotStates robotState = OPEN;
void setup() {
  Serial.begin(9600);
  stepper.setSpeed(10);
  pinMode(soundSensor, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(mutedLedPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);
}
void disable_motor() {
  for(int num=0;num<4;num++) digitalWrite(motorPins[num],LOW);
}
void check_if_paused_IR_command() {
  if (IrReceiver.decode()) {
     IrReceiver.printIRResultShort(&Serial);
     IrReceiver.resume();
     if (IrReceiver.decodedIRData.command == 0x45) {
        // power off - disable/enable
        robotState = PAUSED;
        Serial.println("Robot PAUSED");
     }
  }
}
void close_curtains() {
  Serial.println("Closing Blinds");
  int ran_steps = 0;
  while (robotState != PAUSED && ran_steps < STEPS*numberOfRotations) {
    check_if_paused_IR_command();
    stepper.step(1);
    ran_steps++;
  }
  robotState = CLOSED;
  disable_motor(); // always desable stepper motors after use to reduce power consumption and heating
}
void open_curtains() {
  Serial.println("Opening Blinds");
  int ran_steps = 0;
  while (robotState != PAUSED && ran_steps > -STEPS*numberOfRotations) {
    check_if_paused_IR_command();
    stepper.step(-1);
    ran_steps--;
  }
  robotState = OPEN;
  disable_motor(); // always desable stepper motors after use to reduce power consumption and heating
}
void control_curtain() {
  if (robotState == CLOSED) {
    open_curtains();
  } else {
    close_curtains();
  }
}
float get_temperature_in_celcius(int Vo) {
  logRt = log(R1*((1024.0/Vo-1)));
  T = (1.0 / (A + B*logRt + C*logRt*logRt*logRt));  // We get the temperature value in Kelvin from this Stein-Hart equation
  Tc = T - 273.15;  // Convert Kelvin to Celsius
  return Tc;
}
void loop() {
  if (IrReceiver.decode()) {
     IrReceiver.printIRResultShort(&Serial);
     IrReceiver.resume();
     // vol up 0x46
     // vol down 0x15
     // power off 0x45
     // play/pause 0x40
     // channel up 0x9
     // channel down 0x7
     if (IrReceiver.decodedIRData.command == 0x9 || IrReceiver.decodedIRData.command == 0x46) {
        // channel up & vol up - curtains up
        digitalWrite(ledPin, HIGH);
        Serial.println("Robot CLOSE");
        close_curtains();
     }
     if (IrReceiver.decodedIRData.command == 0x7 || IrReceiver.decodedIRData.command == 0x15) {
        // channel down & vol down - curtains down
        digitalWrite(ledPin, HIGH);
        Serial.println("Robot OPEN");
        open_curtains();
     }
     if (IrReceiver.decodedIRData.command == 0x45) {
        // power off - disable/enable
        digitalWrite(ledPin, HIGH);
        robotState = PAUSED;
        disable_motor(); // always desable stepper motors after use to reduce power consumption and heating
        Serial.println("Robot PAUSED");
     }
     if (IrReceiver.decodedIRData.command == 0x40) {
        // play/pause - mute/unmute
        digitalWrite(ledPin, HIGH);
        muted = !muted;
        Serial.print("muted: ");
        Serial.println(muted);
        digitalWrite(mutedLedPin, muted);
     }
  }
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    control_curtain();
  }
  if (!muted) {
      soundValue = digitalRead(soundSensor);
      //Serial.println(soundValue);
      currentNoiseTime = millis();
      if (soundValue == HIGH) { // if there is currently a noise
        if (
          (currentNoiseTime > lastNoiseTime + 200) && // to debounce a sound occurring in more than a loop cycle as a single noise
          (lastSoundValue == 0) &&  // if it was silent before
          (currentNoiseTime < lastNoiseTime + 800) && // if current clap is less than 0.8 seconds after the first clap
          (currentNoiseTime > lastLightChange + 1000) // to avoid taking a third clap as part of a pattern
        ) {
          digitalWrite(ledPin, HIGH);
          lastLightChange = currentNoiseTime;
          control_curtain();
         }
         lastNoiseTime = currentNoiseTime;
      }
  }
  if (!muted) {
    float temperature = get_temperature_in_celcius(analogRead(ThermistorPin));
    if (temperature > 22 && robotState != CLOSED) {
      close_curtains();  
    }
    if (temperature < 20 && robotState != OPEN) {
      open_curtains();
    }
  }
  
  digitalWrite(ledPin, LOW);
  lastSoundValue = soundValue;
} 

Kilder

More

Hvordan man laver et energi effektivt SmartHome – Tutorial

Af Louise Sjodsholm og Ricco Flyckt

Introduktion

Vi har valgt at lave en tutorial til at få et smartere og mere energi effektivt hjem, hvor der også er fokus på et bedre indeklima. Det har været i førersæde at energi kun skal bruges når brugeren er i sit eget hjem. Dette sikrer også at brugeren ikke kan glemme at slukke lyset eller ventilationen. Alt er automatiseret, og ventilationen bliver reguleret ud fra hvor varmt det er. Brugeren får desuden også en alarm hvis der skulle være en for høj luftfugtighed, mens vinduet åbnes, for at regulere luftfugtigheden indendørs. Når der registreres at en bruger er hjemme, kører systemet på baggrund af en timer. Dette sørger for at der slukkes for hele hjemmet, når brugeren har forladt det. Ved hjælp af et RTC-modul og I2C kommunikation, times hvornår der sidst er registreret en person, således en timer sørger for at hjemmet slukkes efter den angivne tid, hvis ikke der registreres en igen. Dette sørger for at optimere energiforbruget.

Nedenstående ses et galleri af den færdige prototype, som der kan forventes at få, hvis tutorialen udføres.

Videogennemgang af løsningen

Opbygning af hardware – fra TinkerCad

Til at opbygge smarthome løsningen anvendes 11 komponenter fra “Elegoo The most Complete Starter kit”, disse er kategoriseret i nedenstående skema, som værende henholdsvis en sensor, aktuator eller andet. Derudover anvendes der modstande, ledninger, breadboards og en Arduino Uno.

Tabel der beskriver hvilke sensorer, aktuatorer og andet der anvendes i tutorialen.

Opbygningen af hvert enkelt delkredsløb af det samlede system er beskrevet herunder med begrundelser for valg i processen, og beskrivelser af krav til brug af komponenterne. Til sidst er hele kredsløbet vist som helhed.

Servo motor der anvendes til at åbne vindue

Servo motor og Arduino

Da Servo motoren har et indbygget reguleringssystem, vil det ikke være nødvendigt at anvende diode eller transistor. Det er derfor så enkelt som at sætte en 5V spænding, ground og et signal Pin, her Pin 10, til Servo motoren, for at kunne styre motoren 180 grader.

LCD der anvendes til at vise temperatur og luftfugtighed

LCD display og Arduino

I Tinkercad var det ikke muligt at finde netop det LCD display der anvendes i denne tutorial.

Hvis der arbejdes med LCD’et fra denne tutorial skal LCD’en sættes op således:

Tabel over hvordan at vores LCD display er sat op med Arduinoen.

Buzzer til alarmering om for høj luftfugtighed

Buzzer og Arduino

Buzzeren er et enkelt komponent, der kun kræver en spænding og at det er groundet. Der anvendes en Pin fra Arduinoen til at kontrollere hvornår at buzzeren skal have en spænding, så den kun laver lyde når vi er interesserede i det. Denne pin er Pin 9.
Yderligere anvendes der en modstand på 200 Ohm. Denne er fundet ved trial and error, og kan ændres hvis man ønsker en højere eller en lavere lydstyrke.

LDR til at vurdere hvor lyst det er udenfor

LDR modstand og Arduino

LDR’en varierer modstanden afhængigt af mængden af lys på den. Den sættes op i et spændingsdeler kredsløb. Der er i datasheetet angivet at modenstanden varierer mellem 18k ohm og 50 k ohm. Spændingsdelerformlen anvendes til at beregne den spænding der vil kunne måles efter photoresistoren.

Tages der udgangspunkt i 50 k Ohm modstanden

Dermed kan spændingen der måles, variere op til næsten 5 V, hvilket giver stor variation da størrelsen på hvert enkelt step vil udregnes til at være 0,0049, grundet signalet kan variere mellem 0 og 1023.

Dermed er det muligt at adskille værdierne meget præcist da hvert enkelt step er meget småt.

Signalet hentes fra den analoge pin A0.

LED der tændes når det er mørkt udenfor

LED Dioder og Arduino

Belysningen i Smart-Home’et er lavet ved hjælp af to LED pærer. Disse er parallelt forbundet, og vil derfor kun kræve et output fra Pin 13. Var de derimod serielt forbundet, ville en pære kunne springe, og det ville slukke alt lyset i huset. Disse to LED pærer er mest optimale omkring 30mA [1]. Hertil kan der udregnes hvilken modstand der kræves med et output fra Arduino’en på 5V.

Dette betyder at der skal anvendes en modstand tæt på 200 ohm. Beregnes strømmen der vil komme gennem pærerne, hvis der anvendes en 200 ohm modstand med ohms lov, vil dette være 25 mA, som ses af nedenstående beregning.


[1] Elegoo Datasheet LED

DC motor til ventilatoren

DC Motor og Arduino

DC motoren kræver en højere strøm[1] end Arduino boardet kan give fra en pin[2]. Hertil anvendes der en transistor, for at forstærke strømmen.

Desuden kan der forekomme at når der slukkes for strømmen, kan der komme en negativ strøm fra DC-motoren, hvilket kan beskadige transistoren. Hertil anvendes en diode, der har til formål at kun tillade at føre strøm i en retning. Desuden anvendes der også en 200 Ohm modstand til at begrænse strømmen ind i transistoren


[1] 70mA unloaded, 250 mA Loaded Current (Max) – Fra Elegoo DC-motor Datasheet

[2] Arduino kan maks give 40 mA ampere fra en Pin -https://playground.arduino.cc/Main/ArduinoPinCurrentLimitations/

PIR sensor til at registrere om der er en i hjemmet

PIR Sensor og Arduino

PIR sensoren har tre ben, en til 5V, en til ground og en til at læse sensorens værdi. Her anvendes Pin 8 til at læse sensorens værdi, efterfølgende er den sat til 5V fra Arduino’en og til sidst er den grounded.

DHT temperatur og luftfugtighedssensor til måle temperatur og luftfugtighed

TMP Sensoren i Tinkercad burde være en DHT11 sensor, men konceptet er det samme

Det var ikke muligt at anvende temperatur sensoren (DHT11) i Tinkercad, men ovenstående ses det på samme måde som det er opsat i Smart-home’et. Den er sat til pin 7, fra signaldelen af sensoren.

Efterfølgende er der 5V sat til, og til sidst er sensoren groundet.

RTC modul, til at holde styr på tiden

RTC Modul og Arduino

RTC modulet tæller sekunder, minutter, timer, dag i måneden, måned, ugedage og år. I denne tutorial anvendes den til at holde styr på hvornår der er gået x antal tid siden en person er detekteret. Modulet anvender kommunikation i form af I2C som serielt interface. Dette betyder at modulet skal kobles til pins’ne SDA og SCL, hvor SCL er signalet der synkroniserer dataoverførslen fra slaven (RTC modulet) til masteren (Arduinoen), mens SDA er selve dataen. Modulet skal derudover sættes til 5V og GND.

Det samlede kredsløb

Ovenstående ses et billede af hele systemet. Dette system er fysisk over to etager i Smart-home’et, da f.eks. blæseren giver bedst mening at være oppe i loftet, og skærmen giver bedst mening at være så brugeren kan se den. Dette kan ses længere nede i tutorialen.
Hele systemet bliver kontrolleret af ét script ved hjælp af én Arduino. Dette kan ses på flow diagrammet  nedenstående.

Opbygning af program

Systemets opførsel er beskrevet i diagrammet, hvor der først læses fra PIR sensoren, for at vurdere hvorvidt der er en hjemme. Når den ikke har registret noget, og detekterer LOW, betyder det der ikke er en hjemme. Detekteres der i stedet HIGH, gemmes tidspunktet som læses fra RTC modulet, og der laves en variable som indeholder det tidspunkt systemet skal slukke. Herfra læses værdien fra den analoge LDR modstand, hvor det vurderes om det er så mørkt at lyst skal tænde. Hvis det ikke skal tænde fortsættes der til at kigge på temperatur og luftfugtighed. Dette er ligeledes næste step, efter at have tændt lyset, hvis det er mørkt. Det vurderes hvorvidt temperaturen er over 20 grader, hvis den er tændes ventilatoren, hvis ikke kigges der på om tidspunktet for at systemet skal slukke er nået. Ved luftfugtighed over 50% tændes buzzeren for at informere brugeren om at der er høj luftfugtighed, mens vinduet åbnes, ved at ændre servo motorens position. Samtidigt skrives temperaturen samt luftfugtigheden på LCD-displayet. Sidst kigges der på om tiden er gået, hvis tiden er gået betyder det brugeren ikke er hjemme, og PIR sensorens værdi læses igen. Hvis tiden ikke er gået, da der er detekteret en bruger på ny, og derved sat en ny sluk tid, betyder det brugeren er hjemme, og tidspunktet gemmes derfor, inden programmet fortsætter i loopet igen.

Funktioner

Arduino scriptet vil blive fremvist, funktion for funktion. Ønskes der at se hele scriptet, ses det nederst på siden i denne tutorial.

Igennem programmet testes der først for om der er en bruger hjemme. Dette gøres ved hjælp af funktionen ”BrugerHjemme()”. Her anvendes en PIR sensor, og hvis PIR sensorens output er ”HIGH” betyder det at der er en person som er gået forbi PIR sensoren. Hertil ses funktionen:

bool BrugerHjemme()
{
  return digitalRead(pirPin) == HIGH;
}

Da vi nu er klar over at brugeren er hjemme, sætter vi en timer, fra hvornår vi igen skal teste om brugeren stadigvæk er hjemme.  Se loop delen af scriptet nedenstående.

Efterfølgende sættes booleanen hjemme til at være lig med true.

Herefter er både Timeren større end ”now” hvilket er klokken på nuværende tidspunkt, og ”hjemme” er sat til true. Dette betyder at vi hopper ind i sætningen der starter vores smarthome.  Her bliver startSmartHome() funktionen kaldt, hvis de 30 minutter stadigvæk ikke er gået, samtidig bliver der løbende testet om brugeren igen er til at se. Hvis brugeren er det, laves en ny Timer, på tiden vi har nu, plus den tid vi vil have at der skal gå før systemet slukker.

void loop() 
{
  DateTime now = rtc.now(); //Tager tiden der er lige nu
  DateTime future (now + TimeSpan(0,HJEMME_TID_TIMER,HJEMME_TID_MINUTTER,HJEMME_TID_SEKUNDER)); //Tager tiden + Den tid der skal lægges til 
  if (BrugerHjemme()) //Tester med PIR sensor om brugeren er hjemme, hvis brugeren er hjemme er det true - Funktionskald
  {
    Timer = future; //Sætter timeren til sluktidspunktet
    hjemme = true; //Det er nu sandt at der er en hjemme 
  }

  if (Timer >= now && hjemme) //Der er nu en forskel fra vores satte timer og tidspunktet nu og der er en hjemme.
  {
    startSmartHome(); //Kalder startSmartHome funktionen, der tænder for sensorer og aktuatorer
  
    if (BrugerHjemme()) //Er brugeren stadigvæk hjemnme?  Hvis ja, Lav en ny timer
    {
      Timer = future;
      hjemme=true;
    }
  }
  else 
  {
      slukSmartHome();
      hjemme = false; // Hjemme er ikke længere sand.
  }

}

Start SmartHome Funktionen kan ses nedenstående.

void startSmartHome()
{
  if (solLys()) //Er der sol? Funktions kald til LDR modstand
  {
    digitalWrite(ledPin, LOW);  //Slukker lys hvis der er sollys
  }
  else
  {
    digitalWrite(ledPin,HIGH); //Tænder hvis der ikke er sollys
  }
  
  int chk = DHT.read11(DHT11_PIN); // Aflæser temperatur og humidity sensor
  delay(500); //Delay så LCD skærmen kan følge med
  
  if (DHT.humidity > 50) //Er der mere end 50 i luftfugtighed? Kald en alarm fra buzzeren
  {
  minServo.write(90);
  tone(buzzer, 1000); 
  delay(500);        
  noTone(buzzer);     
  delay(500);        
  }
   else //Luft fugtigheden er under 50, og vi har derfor en OK luftfugtighed.
  {
    minServo.write(0); //Lukker vinduet, da der er en okay luft fugtighed. 
  }
  delay(1000);
  int temp = DHT.temperature; //Tager temperaturen fra sensoren
  fanSpeed(temp); //Kontrollerer hastigheden på blæseren, alt efter hvor varmt det er 
  opdaterLCD(DHT.temperature,DHT.humidity); //Opdaterer LCD skærmen med temperaturen og humidity som parameter
}

Som ovenstående set er dette funktionen som kører hele smart home funktionaliteten i hjemmet. Smarthome funktionen anvender andre funktioner i programmet, b.la. tjekkes der ved hjælp af funktionen ”solLys()” for om det er sandt at LDRpinnens output er større end 200. Hvis ja sendes der true tilbage.

bool solLys ()
{
  return analogRead(LDRPin) > 200; //Sender true hvis LDR har målt over 200
}

Hertil slukkes lyset, som set i startSmartHome funktionen, inde i huset hvis der er detekteret lys udenfor, og omvendt hvis der ikke er detekteret lys over en grænseværdi på 200.

Efterfølgende læses humidity og temperatur sensorens værdi. Hvis luftfugtigheden er over 50%, åbnes vinduet i hjemmet, og der kommer en alarm, så brugeren er opmærksom på at luftfugtigheden er høj.

Hvis der derimod ikke er en høj luftfugtighed lukkes vinduet.

Sensorens temperatur værdi anvendes til at styre ventilationssystemet, bestående af en DC motor. Her er der lavet en funktion der hedder ”fanSpeed()”, der tager temperaturen som parameter, og ud fra temperaturen vil hastigheden af blæseren ændres. Denne funktion ses nedenstående

void fanSpeed(int temperature)
{
  if (temperature > 30)
  {
    analogWrite(dcMotorPin,255); 
  }
  else if (temperature > 28)
  {
    analogWrite(dcMotorPin,150);
  }
  else if (temperature > 20)
  {
    analogWrite(dcMotorPin,75);
  }
  else
  {
    analogWrite(dcMotorPin,0);
  }
}

Til sidst opdateres LCD’et.  Dette er en simpel funktion der tager temperatur og luftfugtigheden som parameter, og skriver dette på skærmen, se billede nedenstående. Når setCursor funktionen fra lcd librariet sættes til 0,1, går vi ned på næste linje.

void opdaterLCD(int temp, int humidity)
{
  lcd.setCursor(0,0); 
  lcd.print("Temperatur:");
  lcd.print(temp);
  lcd.print((char)223);
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Luft H2O:  ");
  lcd.print(humidity);
  lcd.print("%");
}

Dette udgør samlet set startSmartHome funktionen.

Når tiden er gået, hoppes der ind i else sætningen i loop delen af scriptet. Her slukkes systemet. Dette indebærer både at alt fjernes på LCD skærmen, alt lyset slukkes i huset, blæseren slukkes og vinduerne lukkes.

void slukSmartHome()
{
  lcd.clear(); //Fjerner alt fra LCD skærmen
  digitalWrite(ledPin, LOW); //Slukker alt lyset i huset 
  analogWrite(dcMotorPin,0); //Slukker blæseren
  minServo.write(0); //Lukker vinduet når der ikke er nogle hjemme.
}

Prioriteringer

Programmets vigtigste ydeevne er at sikre at der kun bruges energi, når brugeren er hjemme. Af denne grund er det højeste i hierarkiet at tjekke om Brugeren rent faktisk er hjemme, ved hjælp af PIR sensoren. Hvis brugeren ikke er blevet senset af PIR sensoren, vil programmet aldrig kunne hoppe ind i ”startSmartHome()” funktionen. Desuden hvis brugeren ikke er detekteret, når timeren er gået vil programmet ligeledes slukke alt, for at spare energi, og starter herved kun igen når en bruger er blevet detekteret.

Opbygning af den samlede fysiske prototype

I tutorialen er Smart Home’et fordelt på to etager.

Dette skyldes f.eks. at en ventilator ventilerer et rum bedst fra loftet, hvor Temperatur og luftfugtighedssensoren giver den bedste måling i rummet hvor brugeren er i.  På samme måde er LED dioderne placeret i loftet, for at give den bedste udstråling.
Desuden er Buzzeren og LCD skærmen også placeret i stuen, for at brugeren kan få feedback på hvad der sker i systemet, havde buzzeren været placeret på loftet ville brugeren ikke kunne høre alarmen, ligesom de ikke ville kunne aflæse skærmen hvis ikke den var i stuen.
PIR sensoren er sat på bagvæggen i stuen, for at kunne sense hele rummet, så uanset hvor brugeren er vil brugeren blive detekteret. Den kunne ligeledes placeres i loftet for bedre at kunne detekterer i hele rummet, der var dog ikke plads på prototypen derfor placeres den på bagvæggen.

Klokken har ikke en direkte påvirkning på brugerens opfattelse af systemet, og er af den grund blevet placeret på loftet, så det ikke fylder.
LDR modstanden kunne både være placeret inde i stuen og udenfor. Der blev valgt at LDR modstanden skulle være placeret udenfor, og hvis der var sol udenfor kunne man konkludere der ikke behøves lys inde i stuen. På den anden side kan man reflektere over om, det var en bedre repræsentation af om der er nok lys i selve huset hvis LDR modstanden var inde i huset, og ikke udelukkende kigger på udenfor som helhed.

Servo motoren der åbner vinduet er placeret som hængselsled på vinduet, under vinduet i det ene hjørne af vinduet. Dette sikrer at vinduet åbner udad.  Rent mekanisk set åbner vinduet kun 90 grader, for at sikre at vinduet ikke rammer på noget udenfor, men det vil være muligt at ændre det til mere end 90 grader hvis dette ønskes.  

Herunder ses et billede af servo motorens placering, samt når vinduet er åbent og lukket

Alt som ikke skal være i det rum brugeren befinder sig i er placeret på loftet, og kan ses af nedenstående billede. Dette dækker over, Arduinoen, RTC modulet, breadboard, samt LED’er og DC motor der er placeret i loftet så det kan ses i stuen.

Loftet i huset

I stuen er placeret de sensorer og aktuatorer som er relevante for systemets funktions og brugerens mulighed for at aflæse temperatur og luftfugtighed. Disse kan ses nedenstående

Stuen i huset

Konklusion

Tutorialens problemstilling var at være så energi effektiv som muligt, og automatisere så mange opgaver som muligt, hvilket gør at brugeren får et lettere og bedre liv. Dette indebærer også at indeklimaet altid vil blive reguleret ved hjælp af servo motor, samt DHT11 – luftfugtighed og temperatur sensor. Yderligere skal brugeren ikke tænde og slukke for ventilatoren, alt efter om der kommer sol og gør rummet ekstra varmt. Ventilatoren reguleres nemlig alt efter hvor varmt der er inde i huset.
Desuden har brugeren mulighed for at få status på hvor vi befinder os i programmet, ved hjælp af LCD-skærmen og LED pærerne i loftet, som samtidig også kun tændes når der mørkt udenfor (LDR modstand)
Alt dette havde til formål at kun køre når brugeren er hjemme i huset, og derved spare energi. Dette er blevet løst ved hjælp af PIR sensoren, der gør at systemet kun aktiveres når en person er blevet detekteret.

Det kan derfor konkluderes at ved hjælp af Servo motor der åbner vindue når luftfugtigheden er for høj og buzzer der informerer brugeren om dette, samt DC motor der ventilerer rummet når temperaturen er for høj, vil der forekomme et bedre indeklima for brugeren.

Ligeledes kan der konkluderes at hjemmet er et mere energi effektivt hjem, da hele systemet kun kan køre, når en bruger er i huset, og lyset kun tændes når der er mørkt udenfor.

Perspektivering

Der kan perspektiveres over forskellige forbedringer til systemet. En forbedring kunne være, en anden måde at registrere hvorvidt brugeren er hjemme. Dette kunne løses ved at anvende et RFID modul, eller et membrane switch module, hvor brugeren enten scanner et kort eller skriver en kode når de kommer hjem. Således skal systemet køre indtil brugeren har forladt hjemmet, og skrevet en kode for at låse, eller scannet sit kort. Dette vil forhindre det mulige problem der er i den nuværende løsning, hvor systemet slukker, hvis ikke PIR sensoren har set en person indenfor tidsgrænsen. Hvis der tilføjes en af de nævnte løsninger til at vurdere om en person er hjemme, ville der kunne placeres en PIR sensor i hvert rum, og derved spares energi, da der kunne tændes for systemerne og lyset lokalt. Desuden ville det være spændende at automatisere vanding af blomster. Hertil kunne man måle på fugtigheden af jorden, og når jordens fugtighed var under en fundet grænseværdi kunne man tænde for en kontrollerbar vandslange.

Alt Arduino Kode

Nedenstående ses hele Arduino koden, som er beskrevet del for del i opbygningen af programmet.

#include <LiquidCrystal.h> // LCD Skærm
#include <dht.h> // Humidity/Temperature sensor
#include <Wire.h> // I^2C kommunikation
#include "RTClib.h" // Clock
#include <Servo.h>
//Clock
DateTime Timer; //Timer for hvornår tiden er gået.
RTC_DS1307 rtc; 

//LCD Skærm
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

//LED
int ledPin = 13; 

//PIR sensor
int pirPin = 8;
int pirVal = 0;

//DHT sensor
dht DHT;
int DHT11_PIN =  7;


int dcMotorPin = 6;
int servoMotorPin = 10;
int buzzer = 9;
int LDRPin = A0;

bool hjemme;


const int HJEMME_TID_SEKUNDER =0 ;
const int HJEMME_TID_MINUTTER = 30;
const int HJEMME_TID_TIMER = 0;
Servo minServo;
void setup() {
  Wire.begin();
  rtc.begin();
  lcd.begin(16, 2);
  lcd.print("Starting....");
  lcd.setCursor(0,1);
  lcd.print("....  ");

  pinMode(ledPin, OUTPUT);    //LED er et output
  pinMode(pirPin, INPUT);     // PIR tager et input
  pinMode(buzzer, OUTPUT);    // Buzzer laver et output
  pinMode(dcMotorPin,OUTPUT);   //Motor laver et output
  pinMode(LDRPin,INPUT);      //LDR tager et input
  minServo.attach(servoMotorPin);
  minServo.write(0); //Kalibrering af Servo Motor
  SetupClock(); //Funktionskald der Opsætter klokken
  lcd.clear();
}
void loop() 
{
  DateTime now = rtc.now(); //Tager tiden der er lige nu
  DateTime future (now + TimeSpan(0,HJEMME_TID_TIMER,HJEMME_TID_MINUTTER,HJEMME_TID_SEKUNDER)); //Tager tiden + Den tid der skal lægges til 
  if (BrugerHjemme()) //Tester med PIR sensor om brugeren er hjemme, hvis brugeren er hjemme er det true - Funktionskald
  {
    Timer = future; //Sætter timeren til sluktidspunktet
    hjemme = true; //Det er nu sandt at der er en hjemme 
  }

  if (Timer >= now && hjemme) //Der er nu en forskel fra vores satte timer og tidspunktet nu og der er en hjemme.
  {
    startSmartHome(); //Kalder startSmartHome funktionen, der tænder for sensorer og aktuatorer
  
    if (BrugerHjemme()) //Er brugeren stadigvæk hjemnme?  Hvis ja, Lav en ny timer
    {
      Timer = future;
      hjemme=true;
    }
  }
  else 
  {
      slukSmartHome();
      hjemme = false; // Hjemme er ikke længere sand.
  }

}

void SetupClock()
{
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    Serial.begin(9600);
   while (!Serial); // for Leonardo/Micro/Zero

  Serial.begin(9600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
  
}
}

bool BrugerHjemme()
{
  return digitalRead(pirPin) == HIGH;
}

bool solLys ()
{
  return analogRead(LDRPin) > 200; //Sender true hvis LDR har målt over 300
}

void fanSpeed(int temperature)
{
  if (temperature > 30)
  {
    analogWrite(dcMotorPin,255); 
  }
  else if (temperature > 28)
  {
    analogWrite(dcMotorPin,150);
  }
  else if (temperature > 20)
  {
    analogWrite(dcMotorPin,75);
  }
  else
  {
    analogWrite(dcMotorPin,0);
  }
}



void opdaterLCD(int temp, int humidity)
{
  lcd.setCursor(0,0); 
  lcd.print("Temperatur:");
  lcd.print(temp);
  lcd.print((char)223);
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Luft H2O:  ");
  lcd.print(humidity);
  lcd.print("%");
}

void startSmartHome()
{
  if (solLys()) //Er der sol? Funktions kald til LDR modstand
  {
    digitalWrite(ledPin, LOW);  //Slukker lys hvis der er sollys
  }
  else
  {
    digitalWrite(ledPin,HIGH); //Tænder hvis der ikke er sollys
  }
  
  int chk = DHT.read11(DHT11_PIN); // Aflæser temperatur og humidity sensor
  delay(500); //Delay så LCD skærmen kan følge med
  
  if (DHT.humidity > 50) //Er der mere end 50 i luftfugtighed? Kald en alarm fra buzzeren
  {
  minServo.write(90);
  tone(buzzer, 1000); 
  delay(500);        
  noTone(buzzer);     
  delay(500);        
  }
   else //Luft fugtigheden er under 50, og vi har derfor en OK luftfugtighed.
  {
    minServo.write(0); //Lukker vinduet, da der er en okay luft fugtighed. 
  }
  delay(1000);
  int temp = DHT.temperature; //Tager temperaturen fra sensoren
  fanSpeed(temp); //Kontrollerer hastigheden på blæseren, alt efter hvor varmt det er 
  opdaterLCD(DHT.temperature,DHT.humidity); //Opdaterer LCD skærmen med temperaturen og humidity som parameter
}

void slukSmartHome()
{
  lcd.clear(); //Fjerner alt fra LCD skærmen
  digitalWrite(ledPin, LOW); //Slukker alt lyset i huset 
  analogWrite(dcMotorPin,0); //Slukker blæseren
  minServo.write(0); //Lukker vinduet når der ikke er nogle hjemme.
}
More

Smart Home

Ajithan Christian, Jeppe Olesen og Mathias Katz Sørensen

Introduktion

Smart Home er primært en løsning der sikrere hjemmet. Systemet indeholder en dørlås som styres, af enten et kort eller en chip, efter brugeren præference. Hvis en ubuden gæst skulle komme ind i boligen, vil de blive opdaget af afstandssensoren. Dette vil aktivere alarmen som vil blinke med lyset og larme. 

Ud over øget sikkerhed leverer Smart Home et bedre indeklima, da luftfugtighed og temperatur kan måles og aktiverer ventilation. Løsningen forsøger også at være energieffektiv, da sollyset bestemmer hvorvidt lyset tændes, når der låser op. Ved høj sol tændes lyset ikke, mens det tændes om natten eller i overskyet vejr.

Smart Home er opbygget for at lave en simpel, smart løsning til et hus, som har flere forskellige former for funktionalitet.

Sikkerheden, som styres af låsesystemet, er øget fra en bolig, hvor der kun benyttes normale låse, da indtrængen bliver registreret.

De andre funktionaliteter, ventilation og kontrol af lyset, er inkluderet for at automatisere enkelte dele af hjemmet. Når de ønskede grænser for lys,  varme og luftfugtighed er indtastet løser systemet det for beboeren.

Videogennemgang af løsningen

Opbygning af hardware

Smart home består forskellige kredsløb, som i helheden udgør Smart Home. Smart Home består af: 

  • En servo motor, som står for dørlåsningen. SG90.
  • Afstandsmåler til at detektere indbrud. HC-SR04. 
  • RFID chip sensor, RC522 
  • Tilsstandslys, som indikere chip tilstand. 
  • Automatisk regulerende lys
  • Lyssensor, som registrere sollyset.
  • Temperatur og fugtighedssensor, til at registrere klima 
  • Regulerende ventilation. 
  • En buzzer
  • En mikrokontroller, som styre alle enheder. 

Servo motoren er sat op så den låser døren ved 90 grader. Når RFID sensoren registrere den rigtige chip, vil servoen rotere til 180 grader, hvormed døren bliver låst op. Servoen har indbygget driver, modstand og gearinger, derfor kan den sættes direkte til mikrokontrolleren. 

Afstandsmåleren er en ultrasonisk sensor, som registrerer afstand. Sensoren er placeret foran døren i en højde, hvor husdyr ikke vil påvirke den. Sensoren er monteret på en væg, som er vinkelret med døren, hvorpå sensoren måler afstanden til en modsat væg. Sensoren måler dermed parallelt med døren. Servoen bliver forsynet med 5V fra mikrokontrolleren og grounded ift mikrokontrolleren. 

Afstandsmåleren sender ultralyd for at bestemme en afstand. Sensoren sender radiobølger ud og måler hastigheden for hvornår de modtages igen. Den anvendte sensor har indbygget sender og modtager, derfor kan den forsynes og styret via mikrokontrolleren. 

Til opstillingen anvedes en HC-SR04. Denne er opsat som vist på figuren, dog har den en trigger og et echo pin i stedet for en samlet signal pin. Trigger pin holdes HIGH i 10mikrosekunder for at initialiseret målingen ved at sende ultralyd. Echo pin er kun højt i den tid bølgerne er sendt, dermed den tid det tager for signalet og nå tilbage. Hvis bølgerne fra sensoren er lavere end en prædefineret tærskelværdi, vil den alarmere resten af systemet, men kun i det tilfælde hvor døren er låst. Hvis afstanden er lav, når chippen ikke har registreret den rigtige nøgle, vil det betyde, at en uvedkommende gæst er kommet ind i huset. Hvis RFID registrerer den rigtig chip vil afstandsmåleren ikke have nogen betydning. Afstandsmåleren bliver forsynet med 5V fra mikrokontrolleren og grounded ift mikrokontrolleren. 

RFID RC522 chiplæser styre adgangen til huset. RC522 er en modul reader og writer, som kan modtage signal fra kort og tags. RC522 tilsluttes direkte til mikrokontrolleren med en forsyning på under 5V, derfor forsynes den med 3,3V fra mikrokontrolleren og groundes ift denne. 

Chip tilstands lys skal registrere tilstanden af chip læseren. Dette giver brugeren en indikation om hvorvidt chippen har åbnet døren eller ikke. Når døren er låst til tilstands lyset være rødt indtil den rigtig chip sættes for læseren, hvorefter denne vil skifte til grønt.

Opsætningen er en simpelt LED opsætning, hvor LEDen sidder i serie med en ballast modstand. Modstanden sikre at LED’en ikke får for meget strøm og dermed ikke brænder. LED’erne bliver forsynet med 5V og skal have omkring 20mA, som er lige under maks værdien. Modstanden for LED’erne beregnes iht. Ohms lov. 

V = I * R
Da spændingen er 5V og strømmen skal være 20mA, kan R isoleres og regnes 

R = 5V/ 0,02 A = 250 ohm. 

Dermed vælges for LED’erne en modstand på 220 ohm. LED’erne bliver forsynet med 5V fra mikrokontrolleren og grounded ift mikrokontrolleren. 

Automatisk reguleret lys med LDR sensor. Smart Home vil være mere energieffektiv ved delvis at regulere lyset i hjemme. Ved hjælp af lysitensiteten udenfor kan lyssensoren vurdere, hvorvidt det er nødvendigt med lys indenfor. LDR’en registerer lyset som via kode kan aktivere indelyset. Indelyset aktiveres via en transistor, som enten er HIGH eller LOW. Ved HIGH tilstand indikeres, at LDR modstanden er lav, hvormed lyset udenfor er lavet og derfor sendes der strøm til lyset, dette gælder også omvendt.  

LDR kredsløbet er sat op i en spændingsdeler, med en modstand på 10K ohm. Værdien er valgt ved trial and error, hvor 10K ohm giver det bedste udsving fra sensor, dermed et bedre analogt interval. Ud fra denne værdi vil en tærskelværdi vurdere, hvorvidt lyset skal tændes eller forblive slukket. Lyset er sat sammen med en transistor som en switch, som styres af pin 2. Tærskelværdien for sensoren kan brugerdefineres. Kredsløbet bliver forsynet med 5V fra mikrokontrolleren og gounded ift denne. 

Ventilationen styre indeklimaet og reguleres ved hjælp af en temperatur og fugtighedssensor. Sensoren registrerer både temperatur og fugtighed, hvorpå en tærskel aktiverer en DC-motor med en fane. Tærskelværdien kan brugerdefineres og man kan selv vælge om det skal afhænge af temperatur eller luftfugtighed, i koden længere nede er der taget udgangspunkt i luftfugtighed. 

Arduinoen kan ikke forsyne mere end 50mA, hvilket motoren skal bruge, derfor skal der anvendes transistor. Da retningen af motoren ikke skal reguleres anvendes der ikke en h-bro, men en enkelt transistor. Transistoren sikre den rette strøm til motoren. Transistoren er en spændingsregulator og aktiveres når base spændingen er over en spænding på 2,4 V.

Det kan opstår et spike, når motoren pludselig stoppes, da det magnetiske felt i motoren kan kollapse og generere en ufrivillig spænding. Denne spænding kan skade transistoren og ødelægge den, derfor bruges en flyback diode, som afleder spike spændingen væk fra transistoren. Base modstanden er på 1K ohm og reducere strømmer, for ikke og skade transistoren. Kredsløbet bliver forsynet med 5 V fra mikrokontrolleren og grounded ift denne. 

Buzzer agerer som lyden i alarmsystemet. Når en forkert chip registreres afgiver buzzeren en lyd, som er forskellige fra når chippen er rigtig. Derudover går buzzeren i gang, hvis der er detekteret indbrud ved en høj bippende alarmtone. Buzzeren kan styre direkte fra mikrokontrolleren og er forsynet med 5 V fra mikrokontrolleren og grounded ift. 

Hvert element bliver drevet af en microcontroller, hvor den endelige opstilling kan ses herunder. Da Tinkercad ikke understøtter en RFID chip er der på modellen brugt en membrane switch module, dog er denne i opstillingen en RFID.

Opbygning af program

#include <HCSR04.h> // bib til afstandsmåler 
#include <SPI.h> // bib til RFID nøglechip 
#include <MFRC522.h> //bib til nøglechip
#include <Servo.h> // bib til servostyring
#include "dht.h" // bib til humidity sensor

int triggerPin = 7; // Pin til USS trigger
int echoPin = 6; // Pin til USS echo

UltraSonicDistanceSensor afstand(triggerPin, echoPin); // Initialiser afstand fra bib

#define SS_PIN 10 // Pin til chip 
#define RST_PIN 9 // pin til chip 
MFRC522 mfrc522(SS_PIN, RST_PIN); // chip initalisering

const int transistorValue = 2; // pin til transistor
const int buzzer = 4; // Pin til Buzzer
const int venti = 5; // Pin til ventilation
#define dht_apin A0 // pin til humidity
dht DHT;

int servoPin = 3;  // Pin til Servo

const int LDR = A3; // Pin til LDR


int input_val = 0; //intialisere værdien til 0
int stat; //status tilstand (0 = låst, 1 = åben)
int x = 0; //status til at tjekke hvor mange gange det rigtige kort er læst

Servo myServo; // Servo initalisering fra bib.

void setup() {

  Serial.begin(9600);
  SPI.begin(); 
  mfrc522.PCD_Init();
  Serial.println("Scan card");
  Serial.println();
  pinMode(transistorValue, OUTPUT); 
  pinMode(buzzer, OUTPUT); 
  pinMode(venti, OUTPUT);
  
  myServo.attach(servoPin);
  myServo.write(90);

 pinMode(A4, OUTPUT); 
 pinMode(A5, OUTPUT); 
 digitalWrite(A4, HIGH);
 digitalWrite(venti, LOW);
 stat = 0; //status tilstand (0 = låst, 1 = åben)

}

void loop() {

  input_val = analogRead(LDR); //måler og udskriver LDR værdif
  Serial.print("LDR Value is: ");
  Serial.println(input_val);
  delay(1000);
  Serial.println(stat);

   DHT.read11(dht_apin); //måler og udskriver fugtighed og temepratur værdier
    Serial.print("Luft fugtighed = ");
    Serial.print(DHT.humidity);
    Serial.print("%  ");
    Serial.print("temperatur = ");
    Serial.print(DHT.temperature); 
    Serial.println("C  ");

if(DHT.humidity > 50) //hvis fugtighed overstiger tændes dc-motor 
{
  digitalWrite(venti, HIGH); 
}
else 
{
  digitalWrite(venti, LOW);
}

double distance = afstand.measureDistanceCm(); //måler og udskriver afstanden fra afstandsmåler
Serial.println(distance);

if (distance < 10 && stat == 0) //Hvis distance bliver midnre end 10 og der er låst, tændes alarmen og døren låses.
{
  servoClose(); 
  Serial.println("WARNING!! UNKNOW INTRUDER - POLICE IS ALARMED ");
  while(stat == 0){
  AlarmSound();
  digitalWrite(transistorValue, HIGH); 
  delay(10);
  AlarmSound(); 
  digitalWrite(transistorValue, LOW); 
  delay(10);
  
  if (mfrc522.PICC_IsNewCardPresent()) { //checker efter nyt kort for at kunne abryde alarmen
  return;
 }
    if(mfrc522.PICC_ReadCardSerial()) {
     return; 
      }
      for (byte i = 0; i < mfrc522.uid.size; ++i) {
      Serial.print(mfrc522.uid.uidByte[i], HEX); 
      Serial.print(" "); 
    }
  }
}


  
   // kigger efter nyt kort
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return; // Returner hvis sandt 
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }

    //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();


if (content.substring(1) == "3C D7 4A 23" && x == 0) 
//hvis den rigtig chip læses og x = 0, køres følgende funktioner.
{
   Serial.println(" Access authorized");
   Serial.println();
   servoOpen();
   UnlockSound();
   digitalWrite(A5, HIGH);
   digitalWrite(A4, LOW);
   stat = 1; 
   x++; 
   Serial.println(stat);
   if (input_val < 400){ //checker LDR værdi og tænder indørs lyset ud fra udvendigt lys.
   digitalWrite(transistorValue, HIGH);
   }
   else 
   digitalWrite(transistorValue, LOW); 

}
else {
    Serial.println(" Access denied"); //hvis ikke den rigtige chip læses eller x ikke er 0, køåres følgende funktioner
    LockSound();
    servoClose();
    digitalWrite(A4, HIGH);
    digitalWrite(A5, LOW);
    digitalWrite(transistorValue, LOW);
    stat = 0;
    x = 0; 
    Serial.println(stat);
    }

     // kigger efter nyt kort
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return; // Returner hvis sandt 
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }

  if((content.substring(1) == "3C D7 4A 23") && x == 1) //hvis det rigtige kort læses, hvilket i dette tilfælde er kortet med koden 3C D7 4A 23, og x =1, køres følgende funktioner:
   {
    servoClose();
    LockSound();
    stat = 0;
    x = 0; 
    digitalWrite(A4, HIGH);
    digitalWrite(A5, LOW);
   }
}

 void LockSound(){ //lock lyd
  tone(buzzer, 1600); 
  delay(250);      
  noTone(buzzer);    
  tone(buzzer, 800);
  delay(350);
  noTone(buzzer);
  delay(15);
  tone(buzzer, 800);
  delay(350);
  noTone(buzzer);
}

void UnlockSound(){ //unlock lyd
  tone(buzzer, 800); 
  delay(250);      
  noTone(buzzer);    
  tone(buzzer, 1600);
  delay(350);
  noTone(buzzer);  
}

void AlarmSound(){ //alarm lyd 
  tone(buzzer, 4000); 
  delay(70);      
  noTone(buzzer);    
  delay(70);       
  tone(buzzer, 3800);
  delay(70);        
  noTone(buzzer);     
}

void servoOpen() //kører servomoter til at åbne døren
{
  myServo.write(90);
  delay(100); 
  myServo.write(0); 
}

void servoClose() //kører servomoter til at lukke døren
{
  myServo.write(90);
  delay(1000);
}

Flowdiagram

Ingen tilgængelig beskrivelse.

Prioriteringer og funktioner

Systemets højeste prioritet er at tjekke om om der læses en ny chip, da funktionen skal bruges til at slå alarmsystemet til eller fra, samt stoppe eventuelle alarmer.

Når alarmsystemet oploader er alarmsystemet slået fra, og får stat værdien 0.

Når alarmsystemet er slået til tjekkes det om distancen fra afstandssensoren bliver mindre end 10. Hvis dette gør sig gældende vil dette sætte gang i alarmen, der får buzzeren til at afspille alarmlyden, blinke med lyset (transistorValue) samt låse døren. Derudover tjekkes konstant om nyt kort registreres fra chiplæseren. På denne måde kan en falsk alarm afsluttes, da alarmen ellers kører i loop indtil den slås fra .

Når den rigtige chip læses af chip læseren første gang, vil dette resultere i at døren låses op, da x her vil være 0. x er en status funktion, som tjekker status for, hvor mange gange den rigtige chip er blevet læst. Efter læsning af den rigtige chip incrumentere x med 1. Dette betyder at næste gange chippen læses, er x ikke 0, og derfor ikke opfylder if sætningen for at slå alarmsystemet fra. Herefter tjekker systemet om der er lys udenfor. Er det mørket udenfor, vil lyset indenfor automatisk tænde, ellers vil lyset forblive slukket.

Hvis ikke den rigtige chip læses af chip læseren, vil døren låses, lyset slukkes og status værdierne stat og x sættes til 0.

Hvis den rigtige chip læses igen vil x derfor være = 1, da x blev incrumenteret efter første læsning, låses døren og statusværdier stat og x sættes til 0.

Udover alarmsystemet, måles fugtigheden inde i huset konstant. Hvis fugtigheden overstiger tærskelværdien på 50, igangsættes dc-motoren, der kører indtil luftfugtigheden atter falder under tærskelværdien.

Konklusion

Systemet løser de opgaver som var tiltænkt dog med enkelte skønhedsfejl, som ville kunne rettes for at optimere løsningen.

Perspektivering

Denne løsning opfylder problemstillingen og aspekterne af et smart home, hvor der gennem forskellige sammensætninger kan skabes et energieffektivt, bæredygtigt og sikkert hjem. De anvendte aktuator og sensor til løsningen er en måde, hvorpå et smart home kan skabes, derfor kan disse også erstattes af andre sensor eller aktuator. 

Den simple løsning med en servo til dørlåsen, vil i virkeligheden være mere kompleks, men dog stadig ladsiggørlig med en større servo. Denne vil i dette tilfælde være indbygge i døren og ikke være af plastikvinger. 

Opstilling har kun taget højde for indbrud gennem døren, da huset ikke har nogle vinduer. I et virkelig setting, vil der være sensor placeret ved alle åbninger, altså vinduer og døre, som alle er med til at skabe sikkerhed. Yderligere kan det anvendes en motion sensor som tjekker for bevægelse i huset, denne vil blive programmere så den tager højde for husdyr. Da prototype huset var uden tag blev denne løsning ikke med motion sensor. Motion sensor i et hus uden tag, ville resultere i at systemet ville detektere indbrud, hver gang vi lavede bevægelse tæt på prototypehuset.

Alle automatiserede løsninger, som er styret via software skal kunne tilgås via manuelle elektroniske løsninger. Derfor skal brugeren kunne justere lyset og ventilationen selv. Yderligere vil brugeren have mulighed for at tilgå alle løsninger via en displayskærm, hvor de kan aktivere eller deaktivere forskellige dele, og kan justere de brugerdefinerede tærskelværdier.

More

TeaDunker

Mads Bergholdt Sørensen & Martin Bjerkov Hansen

I denne løsning er der fokus på automatisering af at lave te. Her vil det ved hjælp af aktuatorer og sensorer laves te med varme regulering. Inspirationen kommer af, at når der skal laves en kop te er det altid en længere proces som altid involvere en brændt tunge. Ved hjælp af et ræsonnement af sensorer og aktuatorer skabes der en løsning til den perfekte kop te. 

Før den endelige opstilling, blev hver enkelt komponent testet individuelt, både kredsløb og program, således det til sidst nemt kunne sættes sammen. Dette gav et godt overblik til processen.

Servo motor

En SG90 servo motor, kan køre uden en transistor, grundet dens indre reguleringssystem. Der er tre ledninger; en til 5V, en til GND og en til en port der kan udgive et PWM signal. Efter erfaring, er det bedst at bruge en analog port. PWM signalet bliver oversat til en specifikt vinkel ind i motoren, og der kan på den måde bestemmes ret præcist hvor motoren skal befinde sig henne, mellem 0 og 180 grader. Der bliver brugt to til denne opstilling, som skal styre hvert sit led i en robotarm.

DC motor med enkelt transistor

Bruger en transistor til at trække nok strøm til DC motoren, da den skal bruge mere end hvad Arduinoen kan give som output. Motoren styres meget simpelt, ved at aktivere hvad end digital port, den er forbundet til. Hvis man havde ønsket at den kørte begge veje, kunne den sætte op i en H-bro af transistorer. Resistoren sat ind før Base pin, er ment til at limitere mængden af strøm der føres ind i transistoren. Ellers er DC motoren forbundet til Collector benet, og GND forbundet til Emitter benet.

Termo sensor

Selvom den der bruges i selve opstillingen er anderledes end den tilgængelig på Tinkercad, er det stadig de samme pinouts. Der er til 5V, til GND og en til selve sensor output. Da det er en digital sensor, skal den kobles til en digital port i stedet for en analog port. Det vil sige, at dataen sendes i digitale “pakker”, i modsætning til analoge hvor der sendes varierende spændinger til aflæsning. 

Water level detector

Til at måle hvor meget vand der er i koppen, bruges en water level sensor. Dette er en analog sensor som giver en værdi ud fra hvor meget af sensoren er dækket med vand. De lange strimler som sidder på sensoren reagere på vandet og danner en værdi. 

Ultrasonic sensor

Som start mekanisme for systemet er der implementeret en ultrasonic sensor som aktivere robotten når der holdes en hånd eller en anden genstand tæt på den. Måden at sensoren virker på er ved at udsende lyd bølger, som bliver reflekteret af genstande foran sensoren. De reflekterede lyd bølger bliver så omdannet til et elektrisk signal som kan omregnes til en distance. 

LED indikatorer

Til at indikere forskellige tilstande af programmet, ændres der farve i en RGB LED for en visuel forståelse af systemet. Når programmet ikke er i gang lyser LED’en rød, hvis programmet derimod er i gang, lyser LED’en grønt og hvis programmet ikke køre men dc motoren stadig blæser med kold luft lyser LED’en blåt. RGB LED’en virker ved at få input fra 3 pins, alt efter hvor meget strøm der går til hvert ben kan farven justeres til den givne farver der ønskes, ud fra at blande rød, blå og grøn. Til at definere farverne brugt i programmet sættes den respektive farves digitale pin til HIGH og de andre pins til LOW. 

Fuld konkret komponent liste

For at opsummere, bliver der brugt disse komponenter til opstillingen:

1x PN2222 transistor

1x DC motor

2x SG90 servo motor

1x RGB LED med en 220Ohm modstand til hver af de tre anode ben

1x Ultrasonic sensor

1x Water level sensor

1x DHT11 Temperature/Humidity module 

Opstilling af prototype

Her ses et billede af løsningen hvor robotarmen er monteret med to servo motorer der får tebrevet til at blive hævet og sænket i glasset. I glasset er der monteret en water level sensor, der indikere hvor meget vand der er i glasset. På siden af koppen er monteret en lille blå temperatur sensor som måler temperaturen af te’en. Til højre ses en dc motor med påsat propel som køler på koppen for at varme regulere te’en. Til sidst kan der under hovedet på propellen anes en LED som viser tilstanden af programmet, i dette tilfælde lyser den grønt hvilket indikere at programmet er aktiveret af ultrasonic sensoren som ligger bag ved opstillingen, som hånden aktivere. 

Flowchart over programmering/prioriteringer

Til at starte programmet aflæses ultrasonic sensoren, hvis værdien er mindre end 20 cm går programmet videre sætter først LED til grøn, læser så temperatur og water level sensor værdierne. Dernæst aktiveres servo motorerne og DC motoren. Hvis ultrasonic sensor værdien stadig er mindre end 20 cm køre programmet i et loop. Hvis værdien ikke længere er 20 cm ændres LED farven til Rød og programmet slutter.

Udklip af kode/beskrivelser

Følgende vil der tages udklip og beskrive enkelte dele af programmet. 

Koden for den ultrasoniske sensor, benytter sig af forholdsvis simple kommandoer. Dens echoPin er defineret som værende input og dens pingPin er defineret til at være output. Hvad der essentielt sker, er at pingPin aktiveres i intervaller, som gør sensoren sender lydbølger ud, der reflekteres på overflader og “opfanges” af echoPin. Med en udregning, kan der findes frem til hvor langt væk dette objekt er, da det vides hastigheden af lydbølgerne. Der bruges long-funktionen til at regne det i centimeter. 

Hvis der er et objekt tættere på end 20 cm, aktiveres resten af programmet. Her lyser LED’en også grøn for at indikere aktivering. 

Ved temperatur sensoren, gøres der meget brug af de libraries som findes til den. Ideen er meget simpel; hvis der sker en fejl for indlæsningen, skriver den en error på Serial monitoren, ellers printer den temperaturen ud. 

Der blev testet hvilke vinkler der passede bedst, og derfor er de sat så specifikke som set her. Dette får robotarmen til at køre op og ned, og dermed dyppe teposen i vandet. Der benyttes her det indbygget library for styring af servomotorer. 

Hvis waterlevel sensoren giver en værdi på over eller lig 100 (det svarer til hvis den er dyppet omtrent 2 cm) begynder DC motoren at rotere og “køle” te ned.  

Konklusion

Baseret på den originale ide om at lave et system der kunne dyppe din te, menes opstillingen at kunne fuldføre dette. Løsningen fungerer fint, men det blev ikke testet med kogende vand, da waterlevel sensoren faktisk kun kan fungere optimalt mellem 10 og 30 grader.

Der menes at den endelige opstilling, opfylder de opgivende problemstillinger. Der bruges tre sensorer (Waterlevel, temperatur, ultrasonic) og tre aktuatorer (en DC og to servomotorer). En transistor bruges til at trække nok strøm til at køre DC motoren og temperatursensoren er digital. Det ottende komponent er bare en RGB LED, men fungerer fint som statusindikator. 

Outputtet fra de forskellige sensorer, bruges til at aktivere de tre aktuatorer. Der sker dermed et fint sammenspil mellem den fysiske verden, programmeringen og mekanikken.

Perspektivering

Det ville gerne være ønsket at styre DC motoren baseret på både waterlevel og temperatur sensoren, men der skete ikke nogen betydelig temperaturændring, da alt bare foregik under stuetemperatur. Hvis det skulle være forbedret, kunne waterlevel sensoren måske være erstattet af noget andet, således der kunne benyttes vand med højere temperatur og dermed observere en reel ændring af temperatur når man blæste på koppen med DC motoren. 

Der kunne være brugt lidt mere tid på at sortere ledningerne, således et mere overskueligt billedet af opstillingen kunne tages. Det endte med at blive lidt kaotisk, som gjorde alt ikke kunne fotograferes optimalt på én gang.

Video af opstillingen

Fulde program

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Servo.h>

Servo myservoUP;
Servo myservoDOWN;

#define DHTPIN 8     // Digital pin connected to the DHT sensor 
#define DHTTYPE    DHT11     

DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;

const int pingPin = 7; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 6; // Echo Pin of Ultrasonic Sensor

 int dc = 5, r = 4, g = 3, b = 2;

 
void setup() {

  Serial.begin(9600);
  
  myservoUP.attach(A0);
  myservoDOWN.attach(A1);

 

  pinMode(b, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(r, OUTPUT);
  pinMode(dc, OUTPUT);

  digitalWrite(b, LOW);
  digitalWrite(g, LOW);
  digitalWrite(r, LOW);
 
  dht.begin();
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);
  delayMS = sensor.min_delay / 1000;

     pinMode(echoPin, INPUT);
     pinMode(pingPin, OUTPUT);
}

void loop() {


  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Ultra sonic sensor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   long duration, cm;
   digitalWrite(pingPin, LOW);
   delayMicroseconds(2);
   digitalWrite(pingPin, HIGH);
   delayMicroseconds(10);
   digitalWrite(pingPin, LOW);
   duration = pulseIn(echoPin, HIGH);
   cm = microsecondsToCentimeters(duration);
   delay(100);
   //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Ultra sonic sensor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

   //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Startup of program %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if ( cm < 20){
  digitalWrite(b, LOW);
  digitalWrite(g, HIGH);
  digitalWrite(r, LOW);


   //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Temprature sensor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  delay(delayMS);
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  }
  else {
    Serial.print(F("Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("°C"));
  }

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Humidity & Temprature sensor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Controlls of servos %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  myservoUP.write(125); //Øverste del
  myservoDOWN.write(90);
  delay(1000);
  myservoUP.write(200);
  myservoDOWN.write(150);
  delay(1000);


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Controlls of servos %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DC motor Controlls %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if ( analogRead(A5) >= 100){
 digitalWrite(dc, HIGH);
}
else{
  digitalWrite(dc, LOW);
  }

  //Slutningen på det originale if-statement
  }
  
  else {
  digitalWrite(b, LOW);
  digitalWrite(g, LOW);
  digitalWrite(r, HIGH);
    }


//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Startup of program %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  

}

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

Løjtnant lyssensor

Lavet af Alexander Jessen, Henrik Hansen og Mikkel Abildholt

Billede af færdigt setup

Kravene for opgaven var, at lave en solcelle styring der drejer en solcelle efter solens lys med en motor, for at optimere udnyttelsen af solens energi.

Måde vi gik til denne opgave, var ved at lave lidt research, om hvordan et solcelle styringssystem eventuelt kunne se ud. På baggrund af denne research, opstillede vi en løsning der opfyldte kravene for opgaven.

Planen, hvor solcellen skal ligge er vinklet på en ca. 30-45 graders vinkel. Den er vinklet således, da vi baseret på kravene fra opgaven var begrænset til kun en motor (DC eller Servo motor). Fordelen ved at have den vinklet sådan er, at solen har meget stor sandsynlighed for at stå direkte på, og vi kan derfor få mest ud af solcellen, ved at have den på en vinkel. Vi har valg kun at bruge 2 LDR-modstande til at registrere det bevægende lys. Imellem disse placerede vi et stykke pap, for at begge LDR-modstande ikke har samme input. Vi kan herudfra sammenligne de to outputs fra LDR-modstande og bestemme om solcelle planet skal drejes en bestemt vej. 

Motoren er placeret i bunden af prototypen. Grunden til at den er placeret der, er på grund af mangel på korrekte ressourcer. Da vi startede på opbygningen af prototypen, ville vi gerne have at motoren sad på siden af solcelle planet, men vi fandt hurtigt ud af, at vi manglede nogle ting til motoren, for at få den til at virke som vi først havde tiltænkt. På grund af dette mangel, måtte vi finde på en ny løsning, som endte med at vi skulle bruge vores servomotor, og placere den på bunden af prototypen.

Kredsløbet i Tinkercad

Robotten og delkomponenter

Hardware

Til opgaven, er disse komponenter benyttet:

  • 2x LDR-modstande
  • 1x 100 μF kondensator
  • 2x 10 kΩ modstand
  • 2x 1 kΩ modstand
  • 2x LED’er
  • Servomotor
  • Arduino

LDR-modstand

LDR-modstande, er en variabel modstand. Det vil sige, at den ændre sin indre modstand, afhængigt af hvor meget lyst den opfanger.

Da vores robot kun bevæger sig på en lineær akse, fra x til y, behøvede vi kun at bruge 2 LDR-modstande, for at kunne få robotten til at fungere. Her bliver hver LDR-modstands output sat til hver sin analog pin, for at kunne læse deres output. Vi benytter os af analog, og ikke digital, da vi skal aflæse værdier, som er andet end bare 0 eller 1.

Elektrisk kondensator

I vores kredsløb, har vi valgt at bruge en en Elektrisk kondensator/kapacitor, i forbindelse med servomotoren. Kapacitoren fungere således, at den kan have en bestemt elektrisk kapacitet. Den fungere lidt ligesom et genopladeligt batteri, men op- og aflader meget hurtigere. Vi har brugt den i vores kredsløb, for at udjævne spændingsniveauet igennem kredsløbet. 

Beregning af modstande til LED

Vi fandt i gennem et datasheet fra sparkfun.com at den anbefalede strømstyrke til vores LED’er er 16-18 mA, og dertil benyttede vi os af ohms lov til at beregne modstanden.

Det tætteste vi havde på dette var en 1k ohm modstand, hvilket vi valgte at bruge. Det betød at vores LED’er fik en strømstyrke på 5mA, hvilket medfører at lysniveauet på dem var lavere end det kunne være.

Flow diagram

Robottens opførsel er designet til at følge et lys, som bliver opfanget af de to LDR-modstande som er på planet, hvor solcellen ligger. Disse 2 LDR-modstande måler konstant lyset og sender et signal til servomotoren om, hvilken retning den skal justere solcelle planet. hvis den ene LDR-modstand får mere lys end den anden, bevæger robotten sig mod den LDR-modstand, som får mest lys.

Kode

#include <Servo.h>
Servo myServo;

int const ,ldrPinZero = A0, ,ldrPinOne = A1;
int const redLEDPin = 5, greenLEDPin = 6;
int ldrValZero, ,ldrValOne;
int angle;

void setup() {
  Serial.begin(9600);
  myServo.attach(3);
  pinMode(redLEDPin, OUTPUT);
  pinMode(greenLEDPin, OUTPUT);

  analogWrite(greenLEDPin, 1023);
  analogWrite(redLEDPin, 0);
}

void loop() {
  ldrValZero = analogRead(ldrPinZero);
  ldrValOne = analogRead(ldrPinOne);
  myServo.write(angle);
  Serial.print("ldr 0: ");
  Serial.print(ldrValZero);
  Serial.print(", ldr 1: ");
  Serial.print(ldrValOne);
  Serial.print(", vinkel: ");
  Serial.println(angle);
  delay(1000);

  if(ldrValZero < ldrValOne){
    angle = angle + 1;
  } else if (ldrValZero > ldrValOne){
    angle = angle - 1;
  }

  if(angle < 0){
    analogWrite(greenLEDPin, 0);
    analogWrite(redLEDPin, 1023); 
    angle = 169;
    myServo.write(angle);
    delay(1000);
    analogWrite(greenLEDPin, 1023);
    analogWrite(redLEDPin, 0); 
  } else if (angle > 179){
    analogWrite(greenLEDPin, 0);
    analogWrite(redLEDPin, 1023); 
    angle = 9;
    myServo.write(angle);
    delay(1000);
    analogWrite(greenLEDPin, 1023);
    analogWrite(redLEDPin, 0); 
  }
  
}

Testkørsel

Test 1 blev kørt i tidsrummet 12:00-13:15 og test 2 blev kørt mellem 13:45-15:00.

Den første test kørte mens der var mere eller mindre skyfrit og masser af sol. Dette medførte et pænere resultat af testen, da der ikke var den store variation i sensorernes værdi.

Den anden test kørte mens skyerne begyndte at bevæge sig ind over himlen, hvilket medførte flere spring i lyssensorernes værdi, og resulterede i en mere sporadisk adfærd.

Generelle udfordringer

Det største problem vi stødte ind i, under opbygningen af prototypen, var at vi ikke kunne sætte vores ledninger sammen med vores LDR-modstande, da vi manglede en loddekolbe for at kunne få dette løst. Her var vores umiddelbare løsning at benytte elektrikertape for at holde ledningerne sammen, dog medførte dette et problem da ledningerne er for stive for motoren at trække på. Det gjorde så at platformen som LDR-modstandene sad på, ikke kunne drejes. Derfor besluttede vi os at købe nogle nye male/female ledninger som ikke var solidt wires, så monteringen af sensorerne ville være nemmere, samt for at undgå at ledningerne ville gå hen og blive et problem for bevægeligheden af robotten.

Ud over dette, fandt vi også ud af, at vi ikke havde nogle 220 ohm modstande i vores kit, så vi måtte nøjes med at benytte os af 1k ohm modstande til LED’erne i stedet.

Konklusion

Robotten/prototypen løser opgavebeskrivelsen, da vi kun har brugt én motor og et par LDR-modstande. Ud over dette kan den også følge et lys, som bevæger sig fra øst til vest.

Robotten kan bla. forbedres, ved at tilføje en ekstra motor, og 2 ekstra LDR-modstande. Dette kan gøre robottens tracking af solen mere præcis, da den bedre kan registrere hvilke retninger den skal dreje, for at være parallel med med solen/lyskilden.

Timelapse af demo-video

Videoen vare 1 minut og 16 sekunder, og viser et timelapse over en test vi kørte

https://drive.google.com/file/d/1wv4sU_NtZx_L6DVVrobGlSg0Swo0r0N6/view?usp=sharing

More