Dr. Bloom

Aus toolbox_interaktion
Wechseln zu: Navigation, Suche
"Dr. Bloom" mit seinen Sensoren

Hinter dem Pseudonym Dr. Bloom [ˈdɒktə bluːm] (dt. = Doktor Blütenpracht) verbirgt sich ein interaktives System, welches ermöglicht, dass auch Personen, die keinen grünen Daumen haben, rechtzeitig über die Bedürfnisse ihrer Pflanzen, via Twitter, in Kenntnis gesetzt werden.

Einleitung

Die folgende Dokumentation beschreibt das Semesterprojekt „Dr. Bloom“ im Fach Interaktion BME Semester III (2014/15). Die Grundidee des Projekts basiert auf der Interaktion zwischen Mensch und Pflanze. Durch Einsatz von Sensoren ist es möglich, Bedürfnisse einer Pflanze nach ausreichend Licht, Feuchtigkeit und angemessener Temperatur visuell darzustellen, um so richtig auf diese reagieren zu können.

Team

Das Projektteam setzte sich aus vier Personen zusammen, die Erfahrungen in verschiedensten Bereichen wie Programmieren, Datenbanken und Design vorweisen konnten. Ein Projektleiter wurde nicht definiert und war an dieser Stelle auch nicht notwendig, da eine gute Kommunikation zwischen den einzelnen Teammitgliedern bereits vorhanden war und sich zu Beginn schnell ein einheitlicher Projektgedanke herauskristallisierte.

Projektfindung

Da jedes Teammitglied seine eigene Vorstellung eines interaktiven Projektes hatte, war es notwendig zunächst alle relevanten Ideen zusammenzutragen, um dann im nächsten Schritt auf einen Nenner zu kommen. Folgende Projekte wurden ernsthaft in Betracht gezogen:

  • Kaffeemaschine mit Sprachsteuerung
  • Musik-Loopbox mit Gestensteuerung
  • Moving Head mit Personenerfassung
  • Pflanzensensoren mit visueller Ausgabewerte

Letztlich setzte sich die Idee einer Pflanze, die ihre Bedürfnisse visuell mitteilt, durch. Weiterhin kamen wir zu dem Entschluss eine Sprachsteuerung mit einzubauen, die es ermöglichen sollte, mit der Pflanze zu sprechen. Diese Erweiterung wurde jedoch in der frühen Anlaufphase des Projekts, nach Abschätzung der Zeit, verworfen.

Projektanforderung

Durch die Definition des Projektes konnte man grundlegende Anforderungen feststellen. Diese werden im Folgenden dargestellt.

Grafik: Projektübersicht
1. Auslesen der Werte
Es soll möglich sein, Feuchtigkeit der Pflanzenerde, sowie Helligkeit und Temperatur ihrer aktuellen Umgebung zu erfassen.
2. Verarbeitung der Werte
Die ausgelesenen Werte sollen über eine Schnittstelle berechnet und für spätere Verwendung vorgehalten werden. Aus diesen Werten sollen interpretierbare Mittelwerte berechnet werden können.
3. Ausgabe einer Information
Aus diesen Mittelwerten soll nun ein bestimmter Zustand der Pflanze angenommen werden, welcher zu einer Ausgabe einer eindeutig verständlichen Information in Text- oder Bildform führen soll.

Durchführung

Benötigte Mittel

Die Liste der benötigten Mittel ergab sich aus den Faktoren, Projektanforderung, Wissenstand der Mitglieder, Zeitbegrenzung und bereits vorhandenen Mitteln. Wie schon in der Einleitung beschrieben, soll es möglich sein, Werte mit Sensoren auszulesen. Daraus folgt der Bedarf von passenden Sensoren. Weiter ist ein geeignetes Medium mit Sensoren-Anbindung, wie z.B. ein Raspberry Pi oder ein Arduino vonnöten.

Arduino mit Sensoren

Im Bestand der Hochschule befand sich bereits ein Arduino mit Temperatur und Lichtsensor. Daher entschieden wir uns, bestehende Ressourcen zu verwenden. Allerdings fehlte noch ein passender Feuchtigkeitssensor, welcher nachbestellt wurde.

Da der Arduino selbst nicht über ein User Interface verfügt, war ein weiteres Mittel zur Verarbeitung notwendig. Hier entschieden wir uns für einen Raspberry Pi, der einem Teammitglied gehörte.

Um nun die Sensorwerte zu verarbeiten, benötigten wir diverse Software: Zunächst bespielten wir den Raspberry Pi mit dem abgespeckten Debian „Rasbian“, welches das Betriebssystem stellte. Der weitere Bedarf an Software ergab sich aus dem Wissensstand der Teammitglieder und den Anforderungen des Projekts. Da alle Mitglieder Erfahrungen im Bereich der Webprogrammierung und Einsatz von Datenbanken hatten, entschieden wir uns an dieser Stelle zunächst für die Verarbeitung mit PHP und MySQL. Um den Datenstrom, der vom Arduino über eine USB-Verbindung kommen sollte, abzufangen, mussten wir auf die Serielle Schnittstelle des Raspberry Pi zugreifen. Hierzu wählten wir die File / Stream I/O-Extension Dio.

Schwierigkeiten

Schnell stellte sich heraus, dass es alles andere als einfach war, die benötigten Severdienste und Erweiterungen zu installieren. Nicht zuletzt aus mangelnder Fachkenntnis ließen wir die Idee, das Projekt mit PHP und MySQL zu realisieren, fallen und entschieden uns für eine andere Variante. Node.JS mit seiner Erweiterung Meteor.JS und der dokumentenorientierten Datenbank MongoDB war eine mögliche Lösung für dieses Problem. Jedoch stellte uns dies vor neue Herausforderungen. Der Raspberry Pi läuft mit einem Prozessor mit ARM-Architektur. Node.JS konnte problemlos installiert werden. Die Schwierigkeit lag darin, MongoDB zu installieren, da es von Haus aus nur mit X86 Prozessoren läuft. Ein inoffizielles Tutorial, das schnell gefunden war, sollte Abhilfe schaffen und es so ermöglichen, MongoDB zu installieren. Letztlich scheiterte es jedoch daran. Die Erstellung einer Datenbank war nicht möglich. Leider verwendeten wir für diesen Teil des Projekts viel Zeit, weshalb er hier erwähnt werden muss.

Aufgrund der bereits vorangeschrittenen Zeit entschieden wir uns, die Daten mit einem unserer teameigenen Laptops direkt mit dem Arduino zu verbinden, die Daten so auszulesen und via Node.JS und MongoDB lokal zu verarbeiten.

Auch die Idee, die Bedürfnisse der Pflanze visuell darzustellen wurde wieder verworfen. Um dennoch eine Kommunikation von Pflanze zu Mensch herzustellen, entschieden wir uns für einen pflanzeneigenen Twitter Account. Dieser sollte ermöglichen, dass die Pflanze je nach Bedarf ihre Bedürfnisse twittert.

Entwickelter Code

Arduino Abfrage Sensoren

const int serialPort = 9600;

// Sensor inputs
const int lightSensorPin = 0;
const int tempSensorPin = 1;
const int moistureSensorPin = 4;

// LED outputs
const int lightLedPin = 9;
const int tempLedPin = 10;
const int moistureLedPin = 11;

// light variables
float ambientLight;
float lightTuned;
int high = 0;
int low = 1023;

// temperature variables
float tempLevel;
float tempTuned;

// moisture variables
float moistureLevel;
float moistness;

void setup()
{
  pinMode(lightLedPin, OUTPUT);
  pinMode(tempLedPin, OUTPUT);
  Serial.begin(serialPort);
}

void loop()
{
  delay(3000);
  // LIGHT
  ambientLight = measureVoltage(lightSensorPin, 1);
  lightTuned = lightManualTune(ambientLight);
  sendSerialMessage(lightTuned, "L", "_");
  setLedPinStatus(lightLedPin, lightTuned, 0);
  
  // TEMPERATURE
  tempLevel = measureVoltage(tempSensorPin, 0.004882814);
  tempTuned = tempManualTune(tempLevel);
  sendSerialMessage(tempTuned, "C", "_");
  setLedPinStatus(tempLedPin, tempTuned, 26.0);
  
  // ACTUAL MOISTURE
  moistureLevel = analogRead(moistureSensorPin);
  moistness = 100-(moistureLevel*100/750);
  sendSerialMessage(moistness, "M", "_");
  setLedPinStatus(moistureLedPin, moistness, 40.0);
  
  //delay(27000);
}

float measureVoltage(int sensorPin, float optimizer){
  return getVoltage(sensorPin, optimizer);
}

float getVoltage(int pin, float optimizer)
{
  return (analogRead(pin) * optimizer);
}

float lightManualTune(int light)
{
  // Remember you're JUST changing the 0, 1023 in the line below!
  light = map(light, 50, 1000, 0, 255);
  light = constrain(light, 0, 255);
  return light;
}

float tempManualTune(float temp){
  return (temp - 0.55) * 100.0;
}

void setLedPinStatus(int pinNumber, float actualValue, float triggerValue){
  if (triggerValue == 0){
    analogWrite(pinNumber, actualValue);
  } else if (actualValue > triggerValue){
    analogWrite(pinNumber, 255);
  } else {
    analogWrite(pinNumber, 0);
  } 
}

void sendSerialMessage(float value, String prefixFlag, String seperator){
  Serial.print(prefixFlag);
  Serial.print(seperator);
  Serial.print(value, 2);
  Serial.println(seperator);
}

/*
// Moisture
const int moistureSensorPin1 = 2;
const int moistureSensorPin2 = 3;
moistureLevel = measureVoltage(moistureSensorPin1, 1.0) - measureVoltage(moistureSensorPin2, 1.0);
resistance = ((moistureLevel/1000)/0.04);
sendSerialMessage(resistance, "M", "_");
setLedPinStatus(moistureLedPin, moistureLevel, 10.0);
  
void lightAutoTune(float light)
{
  // As we mentioned above, the light-sensing circuit we built
  // won't have a range all the way from 0 to 1023. It will likely
  // be more like 300 (dark) to 800 (light).
  
  if (light < low)
  {
    low = light;
  }
  if (light > high)
  {
    high = light;
  }
  light = map(light, low+30, high-30, 0, 255);
  light = constrain(light, 0, 255);
}

//IF DATA SHOULD BE SENT ONLY ON REQUEST
if(Serial.readString() == "update") {
  Serial.print("update_update");
}

*/

Node Main Module

Empfängt Daten und leitet sie an Anwendungen weiter (Datenbank, Twitter, usw.).

var serialport = require("serialport");
var SerialPort = serialport.SerialPort; // localize object constructor
var sp = new SerialPort("/dev/tty.usbmodem1411", {
	parser: serialport.parsers.readline("\n")
});
var formatterSerialToJSON = require('./formatterSerialToJSON.js');
//var mognoDBAccess = require('./mongoDBAccess.js');
var twitterAlert = require('./twitterAlert.js');

recieveSerialData(sp);

function recieveSerialData (port) {
	port.on("data", function (data) {
		var dataSet = formatterSerialToJSON(data);
		//mognoDBAccess(dataSet.flag, dataSet.val, dataSet.tStamp);
		twitterAlert(dataSet.flag, dataSet.val);
	});		
}

Node Serial Data Parser

var dataWrapperObject = { flag: null,	val: null, tStamp: null };
module.exports = dataWrapperObject;

dataWrapperObject.format = function(data){
	var measurementContainer = data.split('_');
	var currentTime = new Date();
	dataWrapperObject.flag = measurementContainer[0];
	dataWrapperObject.val = measurementContainer[1];
	dataWrapperObject.tStamp = createTimeStamp(currentTime);
	return dataWrapperObject;	
};

function createTimeStamp (time) {
	stamp = time.toDateString()+", "+time.toLocaleTimeString();
	return stamp;
}

Bedarfsliste in der Zusammenfassung

Erstes zusammenbauen aller Bauteile
  • Hardware
    • Arduino
    • Bauteile
      • Sensoren: Feuchtigkeit, Helligkeit, Temperatur
      • Widerstände
      • Leuchtdioden
      • Steckplatine
    • USB-Verbindungskabel
    • Rechner (MacBook Air mid 2013)
  • Software
    • Webserver: node.js, serialPort, node-twitter
    • Datenbank: mongoDB
  • Pflanze an sich
  • viel Geduld :-)

Mögliche Erweiterung

Die Entwicklung des Projektes ist bei weitem noch nicht am Ende. Es gibt genug Potential zur Weiterentwicklung. Im Folgenden wollen wir einen Ausblick auf diese Möglichkeiten geben.

E-Mail-Anbindung

Es soll möglich sein, dass die Pflanze ihre Bedürfnisse direkt per E-Mail an ihren Pfleger sendet.

Web-Applikation

Eine Weboberfläche über die man z.B. diverse Tweets verwalten kann und über Charts eine grafische Ansicht auf den Messwerteverlauf hat. Alternativ könnte man hier eine Art Netzwerk aufbauen, dessen User für eine optimale Pflanzenpflege belohnt werden.

Display

An einem am Blumentopf angebrachten LCD-Bildschirm sollen Grafiken ausgegeben werden, die den aktuellen „Gemütszustand“ der Pflanze wiederspiegeln.

automatisierte(s) Gießen und UV-Bestrahlung

Durch eine Wasserpumpe und eine am Blumentopf angebrachte UV-Lampe soll es möglich sein, dass je nach Messwert die Pflanze automatisch gegossen oder beleuchtet wird.

Speech API

Über ein am Blumentopf angebrachtes Mikrofon soll es ermöglicht werden, mit der Pflanze zu reden oder gewisse Funktionen anzusteuern.

Fazit

Planung des Bedarfes

Wegen unerwartet langer Lieferzeit des Feuchtigkeitsensors mussten wir auf Alternativen zurückgreifen. Dies führte zu zusätzlichem Zeitaufwand. Für zukünftige Projekte müssen wir unsere Bedarfsanforderung früher und besser planen.

Bewertes zahlt sich aus

Die anfänglichen Versuche, die Schnittstelle auf dem Raspberry Pi mit diversen Web-Technologien, die z.T. noch nicht ausgereift waren, zu realisieren, scheiterten kläglich. In Zukunft werden wir, bei strengen Zeitvorgaben, eher auf bewerte Technologien zurückgreifen.

Iterativ vs. Wasserfall

Ein großer Vorteil war die Flexibilität unseres Teams. Eine iterative Herangehensweise an die Lösung des Projektes half uns den ständig sich ändernden Spezifikationen gerecht zu werden. Dies werden wir, bei nicht zu strengen Vorgaben, beibehalten.

Aus Fehlern lernt man

Die Mehrarbeitszeit, welche durch diverse Komplikationen entstand, war jedoch nicht umsonst. Unsere Fähigkeit an der Konsole, im Bereich Webprogrammierung und Teambuilding wurden erweitert. Des Weiteren bekamen wir einen Einblick in verschiedenste Hard- und Software Technologien.

Insgesamt war das Projekt ein Erfolg und darf gerne weiterentwickelt werden.

Weblinks