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

Leave a Reply