My Profile Photo

Challenge Based Making


Bauanleitungen aus dem Kurs CBM an der Hochschule Mannheim


Das Team: Interaktiver Campusplan

Interaktiver Campusplan, dessen dreidimensionale Gebäude gedrückt werden können, um Informationen über das Gebäude und darin stattfindende Veranstaltungen angezeigt zu bekommen.

iExpo.gif

Pascal Perle, Marcel Klug, Sebastian Grüb, Rico Zieger

Einleitung

Immer wieder klagen Studenten darüber, dass sie sich nicht ausreichend über das Leben auf dem Campus sowie den dort angebotenen Veranstaltungen informiert fühlen. Der interaktive Campusplan bietet nun eine Lösung für dieses Problem, indem er den Studierenden spielerisch Informationen über die Gebäude sowie den darin stattfindende Veranstaltungen vermittelt und ihnen so indirekt dabei hilft, aktiver am Leben auf dem Hochschulcampus teilzunehmen. Der Plan besteht aus physischen 3D-Modellen der 10 Gebäude des Hauptcampus. Diese sind innen hohl, sodass mehrere LEDs zur farblichen Ausleuchtung der Gebäude darin platziert werden konnten. Die Gebäude selbst sind so positioniert, dass sie durch leichtes Drücken einen darunter liegenden Taster auslösen, der dann die Beleuchtung des jeweiligen Gebäudes aktiviert. Der gesamte Plan ist in einen stabilen Holzrahmen eingelassen, dessen Oberseite eine weiße Pappschicht bildet. Entsprechende Aussparungen in der Pappe sorgen dafür, dass die Gebäude durch sie hindurch ragen und von außen sichtbar sind. Über ein hölzernes Stativ ist ein Beamer knapp 80 cm oberhalb der Pappe befestigt und so ausgerichtet, dass auf die freien Flächen Informationen zu dem gerade gedrückten Gebäude projiziert werden können.

Material und Werkzeug

Folgende Materialien werden für den Bau des Campusplans benötigt:

Folgende Werkzeuge werden für den Bau des Campusplans benötigt:

Vorbereitung

1. Installieren von Raspbian

Sofern noch nicht geschehen, muss mit Raspbian zunächst ein Betriebssystem auf den Raspberry PI überspielt werden. Am einfachsten geht das mit Noobs, einem kompletten Installer für Raspbian. Weitere Informationen dazu gibt es hier.

2. Installieren der Arduino IDE

Um ein Programm für den Arduino zu schreiben bzw. um es darauf zu überspielen bietet sich die von Arduino selbst bereitgestellte IDE an. Zwar bietet diese nur eine sehr limitierte Funktionalität an, für unsere Zwecke ist das aber durchaus ausreichend. Die IDE kann hier heruntergeladen werden.

3. Importieren der LED Bibliothek

Um den von uns verwendeten LED-Streifen ansteuern zu können, wird diese Bibliothek benötigt. Eine Schritt für Schritt Anleitung zum Importieren der Bibliothek findet sich in der zugehörigen Readme-Datei.

Achtung: Ältere Versionen dieses LED-Streifens nutzen mit dem HL1606 ein anderes Chipset und benötigen daher auch andere Bibliotheken. Explizit wird dafür zumindest diese Bibliothek benötigt. Um PWM nutzen zu können, wird zusätzlich noch diese benötigt.

4. Installieren des Selenium-Treibers

Um mit dem Raspberry PI Informationen zu den Gebäuden anzeigen zu können, wird im späteren Verlauf eine Webseite genutzt. Da mit Python 2 eine Webseite aber immer nur als neuer Tab geöffnet werden kann, nutzen wir Selenium, um dieses Problem zu umgehen.

  • Selenium Installieren pip install selenium
  • Iceweasel installieren (Browser) sudo apt get install iceweasel
    • Version 0.15.0 herunterladen (einzige aktuell kompatible Version)
    • und nach “/usr/local/bin” entpacken

Step-by-Step-Guide

1. Holzrahmen +Pappdeckel bauen

Ein Holzrahmen von 60 cm x 70 cm wird gewählt, sodass die einzelnen Gebäude noch groß genug sind. Die Hauptplatte mit einer Dicke von 5 mm wird auf 10 mm dicke “Füße” gestellt. Um der Basis des Stativs für den Beamer zu gestatten unter der Fläche des Holzrahmens zu sitzen, wird die Hinterseite offen gelassen.

Auf die Oberseite der Hauptplatte wird ein Rahmen von 10 x 10 mm gesetzt. Der Pappdeckel mit einer Dicke von 5 mm sitzt im Rahmen auf 5 mm hohen Stützen und den vorhandenen Wattepads und schließt so mit dem Niveau des 10 mm hohen Rahmens ab.

Step1-Box

2. Taster/Widerstände planen verlöten

Da jedes der zehn Gebäude auf einen Druck reagieren können soll, wird entsprechend für jedes Gebäude ein separater Taster benötigt. Der Arduino verfügt jedoch nicht über ausreichend Pins, um jeden davon einzeln anzusprechen, weshalb je fünf Taster parallel geschaltet werden. Durch die Verwendung unterschiedlicher Widerstände für jeden Taster kann mit nur einem Pin der anliegende Spannungswert eindeutig zugeordnet werden. Explizit werden vor je einen der Taster ein 47 Ohm, 100 Ohm, 150 Ohm, 220 Ohm und 1000 Ohm Widerstand geschaltet. Als Pulldown Widerstand wird ebenfalls ein 100 Ohm Widerstand verwendet. Nach dem ersten Taster wird ein Kabel zu einem analogen Inputpin gelegt, an dem die anliegenden Spannungswerte abgefragt werden können. Durch die unterschiedlichen Widerstände lässt sich so der gemessene Wert eindeutig einem Taster zuordnen.

Step2-Breadboard

Nachdem die Taster und Widerstände entsprechend verlötet wurden, empfiehlt es sich diese, wie auf unten stehendem Bild zu erkennen ist, mit doppelseitigem Klebeband und Iso-Tape auf dem Boden zu fixieren.

Step2-Verkabelung

3. LEDs verlöten und montieren

Damit jedes Gebäude auch erleuchtet, wenn es gedrückt wird, müssen die LEDs zusammen gelötet werden. In diesem Fall werden dafür 22 einzelne LEDs bzw. 11 doppelte LED-Stücke benötigt. Bei der Verkabelung dieser LEDs empfiehlt es sich zur besseren Unterscheidung der Kontakte verschiedene Farben zu verwenden: Rot für den +5V Kontakt, Blau für den Cl Kontakt, Grau für den Din Kontakt und schließlich Schwarz für den GND Kontakt. Die Länge der Kabel wird so abgemessen, dass sie passend zu den Abständen zwischen den Gebäuden sind. Um die Gebäude mit den LEDs verbinden zu können, werden Grundflächen aus Pappe ausgeschnitten. Diese verbinden im späteren Verlauf LEDs mit Gebäuden. Die Grundflächen benötigen hierzu zwei Klappen, damit die LEDs hindurchgeführt werden können.

Step3-1

Nun kann gelötet werden. Zu beachten ist, dass Gebäude G vier LEDs bzw. zwei doppelte LED-Stücke benötigt. In welcher Reihenfolge die Kontakte verlötet werden spielt zwar keine Rolle, die Praxis zeigt aber, dass es am einfachsten ist, mit dem untersten zu beginnen. Darüber hinaus sollten die Grundflächen schon nach dem Verlöten einzelner LED-Stücke in Position geschoben werden, da diese nachträglich nur noch schwer anzubringen sind.

Step3-2

4. 3D-Modellierung der Hochschulgebäude

Die 3D-Modelle der Hochschulgebäude werden mit der 3D-Modelling Software Blender angefertigt. Hierbei wurde die Blender-Version 2.78 benutzt. Die Modelle können manuell erstellt werden. Zur Vereinfachung und Zeiteinsparung können diese auch einfach über eine externe Datei wie OpenScreetMaps importiert werden. Diese Modelle müssen jedoch noch angepasst werden, um für den 3D-Druck verwendet werden zu können. Den Modellen fehlt die korrekte Dicke an den Wände sowie die richtige Skalierung. Die nötige Dicke kann mittels Solidify-Modifier gesetzt werden. Diesen findet man unter Properties > Modifiers > Add Modifier > Solidify.

Step4-1

Besonders Gebäude mit Rundungen müssen manuell korrigiert werden. Zusätzlich sollte auch die Decke der Gebäude auf eine einheitliche Dicke angepasst werden. Dazu müssen die Deckenflächen einfach im Edit-Mode verschoben werden. Die Skalierung kann erst später angewendet werden, da die Gebäude einzeln skaliert werden müssen. Im jetzigen Zustand würde die Skalierung nach dem Parent-Objekt gerichtet werden und deshalb nicht exakt auf das gewünschte Resultat führen.

Step4-2

Da die Gebäude als Gesamtes gesehen werden und nicht als einzelne Gebäude, müssen sie vom Parent-Objekt getrennt werden. Dazu sind im Edit-Mode die entsprechenden Flächen/Faces des jeweiligen Gebäudes auszuwählen, was durch die Taste L beschleunigt werden kann. Die Auswahl kann dann via Taste P und der Auswahl von Selected separiert werden.

Step4-4

Abschließend muss noch die gewünschte Skalierung gesetzt werden. Hierfür muss in Blender unter Properties > Scene > Units das Unit-Preset auf Millimeters gesetzt werden. Die Größe der Gebäude kann nach persönlicher Vorliebe gewählt werden. In diesem Modell beträgt sie beispielsweise 5 cm. Die fertigen Gebäude müssen nun noch einzeln als STL-Datei exportiert werden.

Step4-6

5. Wattepads positionieren

Um die Gebäude drücken zu können, müssen diese auf einem etwas nachgebenden Boden sitzen. Es hat sich gezeigt, dass zwei handelsübliche Wattepads übereinander genau die richtige Höhe und Elastizität dafür bieten. Die Wattepads sind dafür ggf. zurecht zu schneiden und mittels doppelseitigem Klebeband so um die Taster zu positionieren, dass die Grundflächen der Gebäude gut aufliegen können.

WattePads

6. Alle Teile zusammen führen

Da bereits Taster und Wattepads auf dem Holzbrett befestigt sind, werden nun die LEDs und Gebäudemodelle angebracht. Hierzu werden zunächst die LEDs mit den Grundflächen und diese Grundflächen anschließend dann mit den Gebäuden selbst verklebt.

Step6-1

Als nächstes wird jedes Gebäude an seinem Stellplatz auf dem Holzbrett platziert. An den Seiten des Holzbretts und an 5-6 weiteren freien Stellen werden kleine Holzklötze angebracht. Diese dienen dazu, dass die Pappe, die als Abdeckung genutzt wird, nicht eingedrückt wird und es somit auch kein “Wackeln” gibt. Ist dies erledigt, kann nun die Pappe über die Häuser gelegt werden. Hierzu werden die Häuser langsam von unten durch die ihnen zugehörigen Löchern geführt.

Step6-2

7. Stativ für Beamer bauen + Beamer ausrichten

Um Informationen gut auf der Pappoberfläche darstellen zu können, wird diese mit einem Beamer von oben bestrahlt. Um den Beamer dort positionieren zu können, muss zunächst ein entsprechendes Stativ konstruiert werden. Dafür wird aus dem restlichen Holz, das beim Bau der Hauptplatte übrig geblieben ist, eine 60 x 35 Zentimeter große Platte ausgeschnitten. Diese dient dem Stativ als Standfuß. Anschließend wird die Holzleiste (100 cm x 4 cm x 4 cm), wie auf den Bildern gezeigt, mithilfe der Winkelverbinder am Ende der Platte befestigt.

Step7-1

Im nächsten Schritt wird die Holzleiste (20 cm x 4 cm x 2 cm) mit dem Scharnier am oberen Ende der zuvor montierten Leiste befestigt. Um den Beamer befestigen zu können, muss noch die 6 mm - Gewindeschraube durch die Leiste geschraubt und mit einer Mutter festgezogen werden. Es empfiehlt sich das Loch der Einfachheit halber vorzubohren. Die Gewindeschraube muss dabei in etwa 80 cm Höhe über der Bodenplatte durch die Leiste geschraubt werden. Zu guter Letzt wird noch eine beliebige andere Schraube als Abstandshalter so in die Stativstange geschraubt, dass die Leiste, auf der der Beamer befestigt ist, etwa 3 bis 4 Grad nach vorne geneigt wird.

Step7-2

8. Coding / Arduino mit Raspberry zusammenführen

Ergänzend zur Verdrahtung und dem physikalischen Aufbau der Taster und ihrer Widerstände muss der Arduino die Spannung am analogen PIN messen, auswerten und einem Gebäude zuordnen. Anschließend muss diese Zuordnung über die USB-Schnittstelle an den Raspberry Pi übertragen werden über den die Webseiten geöffnet werden.

Zuerst muss der Arduino an das Endgerät, mit installierter Arduino IDE oder lauffähigem Arduino Web Editor, über USB angeschlossen werden. Die Datei LEDbtn.ino wird dann in der Arduino IDE geöffnet und der Port, an welchem der Arduino gefunden wird, ausgewählt. Nun muss der Sketch (Arduino Programm Code) kompiliert und auf den Arduino hochgeladen werden. Abschließend muss der Arduino vom Computer getrennt und an den Raspberry angeschlossen werden. Ist der Arduino an den eingeschalteten Raspberry angeschlossen, startet das hochgeladene Programm automatisch.

Quellcode Raspberry Pi (python2)

# -*- coding: utf-8 -*-
import serial
from selenium import webdriver

ser = serial.Serial('/dev/ttyACM0', 9600)


def buildUrl(name):
    return 'file:///home/pi/BtnShow/websites/building{0}.html'.format(name)


browser = webdriver.Firefox()
browser.maximize_window()
browser.get(buildUrl('A'))

lastInput = ""
while True:
    inputLine = ser.readline().rstrip()
    print(inputLine)
    if inputLine != lastInput:
        lastInput = inputLine
        try:
            browser.get(buildUrl(inputLine))
        except:
            pass

Quellcode Arduino

#include "LPD8806.h"
#include "SPI.h" // Comment out this line if using Trinket or Gemma
#ifdef __AVR_ATtiny85__
#include <avr/power.h>
#endif

// Button values
int lastValue = 0;
int currentValue = 0;

const int deviation = 50;

const int btnPerPin = 5;

const int btnPins[]                    = {1, 2};
const char btnBuildings[][btnPerPin]   = {   {'A'  , 'B'   , 'C', 'E'   , 'F'   }, {'G'               , 'H' , 'J'     , 'K'     , 'L'    }};
const int btnValues[][btnPerPin]       = {  { 318  , 408   , 695, 511   , 91    }, {319               , 409 , 696     , 512     , 91     } };
const int ledPositions[][btnPerPin][4] = { { {6, 7}, {4, 5}, {3}, {8, 9}, {0   }}, { {18, 19, 20 , 21}, {10}, {12, 13}, {16, 17}, {14, 15}}};

char selectedBuilding = ' ';
char selectedBuildingLEDs[] = {0, 0};

// Number of RGB LEDs in strand:
const int nLEDs = 22;

// Chose 2 pins for output; can be any valid output pins:
const int dataPin  = 3;
const int clockPin = 2;

LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);


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

#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
  clock_prescale_set(clock_div_1); // Enable 16 MHz on Trinket
#endif

  // Start up the LED strip
  strip.begin();

  // Update the strip, to start they are all 'off'
  strip.show();

  startUpShow();
}

void loop() {
  selectedBuilding = ' ';

  for (int i = 0; i < sizeof(btnPins) / sizeof(*btnPins); i++) {
    currentValue = analogRead(btnPins[i]);

    if (!isSameValue(currentValue, 0, 25)) {
      for (int j = 0; j < sizeof(btnValues[i]) / sizeof(*btnValues[i]); j++) {
        if (isSameValue(currentValue, btnValues[i][j], deviation)) {
          selectedBuilding = btnBuildings[i][j];
          selectedBuildingLEDs[0] = i;
          selectedBuildingLEDs[1] = j;
        }
      }
    }
  }

  if (selectedBuilding != ' ') {
    Serial.println(selectedBuilding); // send to Pi

    for (int i = 0; i < strip.numPixels(); i++) strip.setPixelColor(i, 0); // turn all pixels off

    for (int i = 0; i < sizeof(ledPositions[selectedBuildingLEDs[0]][selectedBuildingLEDs[1]]) / sizeof(*ledPositions[selectedBuildingLEDs[0]][selectedBuildingLEDs[1]]); i++) {
      if (!(i > 0 && ledPositions[selectedBuildingLEDs[0]][selectedBuildingLEDs[1]][i] == 0)) {
        strip.setPixelColor(ledPositions[selectedBuildingLEDs[0]][selectedBuildingLEDs[1]][i], strip.Color(0, 0, 255));
      }
    }
    strip.show(); // Refresh LED states

    delay(100);
  }

}

boolean isSameValue(int originalValue, int compareValue, int deviation) {
  return originalValue >= compareValue - deviation && originalValue <= compareValue + deviation;
}

void startUpShow() {

  for (int i = 0; i < sizeof(ledPositions) / sizeof(*ledPositions); i++) {
    for (int j = 0; j < sizeof(ledPositions[i]) / sizeof(*ledPositions[i]); j++) {
      for (byte m = 0; m <= 127; m++) {
        for (int k = 0; k < sizeof(ledPositions[i][j]) / sizeof(*ledPositions[i][j]); k++) {
          if (!(k > 0 && ledPositions[i][j][k] == 0)) {
            strip.setPixelColor(ledPositions[i][j][k], strip.Color(0, 0, m));
            delay(1);
            strip.show(); // Refresh LED states
          }
        }
      }
    }
  }

  for (int i = 0; i < strip.numPixels(); i++) strip.setPixelColor(i, 0);
  strip.show(); // Refresh LED states

}