Skip to content

Commit

Permalink
Merge pull request #47 from FHNW-IP5-IP6/dev
Browse files Browse the repository at this point in the history
Release 1.1
  • Loading branch information
jbaettig committed Sep 8, 2020
2 parents 69b801b + 39ff5a4 commit 7d1d53d
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 57 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group 'ch.fhnw'
version '1.0'
version '1.1'

repositories {
jcenter()
Expand Down
12 changes: 6 additions & 6 deletions docs/Projektdokumentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -1370,7 +1370,7 @@ <h3 id="_erste_idee">6.1. Erste Idee</h3>
<div class="sect2">
<h3 id="_analyse_pi4j">6.2. Analyse Pi4J</h3>
<div class="paragraph">
<p>Da eine FHNW-Version von Pi4J nicht in Frage kommt, müssen wir eine andere Möglichkeit finden, wie wir den GPIO Simulator implementieren können. In einem ersten Schritt gilt es die Funktionalität und den Aufbau das gesamte Pi4J Pakets zu analysieren. Durch die Untersuchung möchten wir zusätzliche Erkenntnisse gewinnen, welche uns auf neue Ideen für mögliche Simulationsstrategien bringen.</p>
<p>Da eine FHNW-Version von Pi4J nicht in Frage kommt, müssen wir eine andere Möglichkeit finden, wie wir den GPIO Simulator implementieren können. In einem ersten Schritt gilt es, die Funktionalität und den Aufbau des gesamten Pi4J Pakets zu analysieren. Durch die Untersuchung möchten wir zusätzliche Erkenntnisse gewinnen, welche uns auf neue Ideen für mögliche Simulationsstrategien bringen.</p>
</div>
<div class="paragraph">
<p>Das Projekt Pi4J ist aufgeteilt in:</p>
Expand Down Expand Up @@ -1443,7 +1443,7 @@ <h3 id="_simulator_auf_ebene_device">6.6. Simulator auf Ebene Device</h3>
<p>Bei dieser Vorgehensweise würden wir das Ziel verfolgen, alle Funktionen von Pi4J-Device simulieren zu können. Der Umfang des Pi4J-Device Layer ist definitiv überschaubarer im Vergleich zu jenem vom Pi4J-Core. Pi4J-Device bietet direkt Klassen für einzelne Devices an, welche die nötigen GPIO Zugriffe abstrahieren.</p>
</div>
<div class="paragraph">
<p>Ansetzen würden wir bei dieser Implementationsart direkt bei den Device Beispielen von Pi4J. Für die oft verwendeten Devices würden wir eine eigene Klasse implementieren, welche die Simulation der Hardware übernehmen. Die Studentinnen und Studenten könnten in ihrem Code wählen, welches Device sie verwenden möchten. Entweder die durch uns implementierte Simulation oder das Pi4J-Device, welches direkt auf die Hardware zugreift. Dies hätte für uns den Vorteil, dass die Arbeit im Backend im Vergleich zur Simulation der GPIO Pins wesentlich geringer wäre und weniger Risiken mit sich bringt.</p>
<p>Ansetzen würden wir bei dieser Implementationsart direkt bei den Device Beispielen von Pi4J. Für die oft verwendeten Devices würden wir eigene Klassen implementieren, welche die Simulation der Hardware übernehmen. Die Studentinnen und Studenten könnten in ihrem Code wählen, welches Device sie verwenden möchten. Entweder das simulierte Device oder das Pi4J-Device, welches direkt auf die Hardware zugreift. Dies hätte für uns den Vorteil, dass die Arbeit im Backend im Vergleich zur Simulation der GPIO Pins wesentlich geringer wäre und weniger Risiken mit sich bringen würde.</p>
</div>
<div class="paragraph">
<p>Leider haben wir während unseren Recherchen festgestellt, dass Pi4J-Device in zukünftigen Releases nicht mehr weitergeführt wird. Aus diesem Grund bräuchte man eine eigene Pi4J-Device Version, welche dann von der FHNW weitergeführt und ergänzt werden könnte, wenn beispielsweise neue Devices benötigt werden.</p>
Expand Down Expand Up @@ -1515,7 +1515,7 @@ <h3 id="_problembeschreibung">7.1. Problembeschreibung</h3>
</div>
</div>
<div class="paragraph">
<p>Um unsere Implementation zu testen, haben wir die von uns geschriebene Klasse <code>BlinkLedDevice</code> so modifiziert, dass wir eine <code>LEDBase</code> vom Typ <code>GpioLEDSimulator</code> erhalten. Dies haben wir durch den im Konstruktor der Factory übergebenen Boolean festgelegt. Auf dem Simulator Device rufen wir nun die <code>bink()</code> Funktion auf.</p>
<p>Um unsere Implementation zu testen, haben wir die von uns geschriebene Klasse <code>BlinkLedDevice</code> so modifiziert, dass wir eine <code>LEDBase</code> vom Typ <code>GpioLEDSimulator</code> erhalten. Dies haben wir durch den im Konstruktor der Factory übergebenen Boolean festgelegt. Auf dem Simulator Device rufen wir nun die <code>blink()</code> Funktion auf.</p>
</div>
<div class="listingblock">
<div class="content">
Expand Down Expand Up @@ -1592,13 +1592,13 @@ <h3 id="_simulatedgpioprovider_verwerden">7.2. SimulatedGpioProvider verwerden</
<p>Generell gehen wir davon aus, dass wir unter Verwendung des <code>SimulatedGpioProvider</code> den Simulator wie geplant implementieren können. Der Benutzer müsste seinen Code jedoch nicht nur an einer Stelle anpassen, sondern an mindestens zwei Stellen. Das wäre aber wohl noch verkraftbar.</p>
</div>
<div class="paragraph">
<p>Durch unsere bisherig gesammelten Erfahrungen mit den Sensoren und Aktuatoren sind wir uns aber unsicher, wie viel eine Simulation dem Studenten schlussendlich überhaupt an Mehrwert bringt. Wenn wir beispielsweise ein I2C LCD simulieren würden, könnten wir lediglich den Text an einem bestimmten Ort (Konsole / File / Simulator) weitergeben und anzeigen. Ob nun die Verkabelung stimmt und der Text in die richtigen Bytes zerlegt wird, können wir kaum testen oder sicherstellen.</p>
<p>Durch unsere bisherig gesammelten Erfahrungen mit den Sensoren und Aktuatoren sind wir uns aber unsicher, wie viel eine Simulation dem Studenten schlussendlich überhaupt an Mehrwert bringt. Wenn wir beispielsweise ein I2C LCD simulieren würden, könnten wir lediglich den Text an einem bestimmten Ort (Konsole / File / Simulator) weitergeben und anzeigen. Ob nun die Verkabelung stimmt und der Text in die richtigen Bytes zerlegt wird, können wir kaum testen oder sicherstellen, da dafür die Logik des Mikrochips auf dem Gerät auch im Simulator simuliert werden müsste. Dies trifft nicht nur für das LCD zu, sondern für die meisten Sensoren und Aktuatoren. Bei einigen Geräten, wie dem Ultrasonic Ranger, muss die Zeit zwischen Emission und Rezeption der Ultraschallwelle in Mikrosekunden gemessen werden, was sehr stark von dem Gerät selber und der Umgebung abhängt. Eine Simulation könnte zufällige Zahlen zurückgeben, aber das würde dem Studierenden nicht helfen, da man erst wirklich sehen kann, ob die Berechnung korrekt ist, wenn man es mit der richtigen Hardware testet. In all diesen Fällen wäre ein Simulationsversuch reine Zeitverschwendung.</p>
</div>
</div>
<div class="sect2">
<h3 id="_der_simulator_wird_zum_ausführlichen_tutorial">7.3. Der Simulator wird zum ausführlichen Tutorial</h3>
<div class="paragraph">
<p>Diesen Ansatz haben wir bereits besprochen. Resultat der Projektarbeit wären eine Art Guide für die Verwendung von Pi4J-Devices, welche wir mit unseren eigen FHNW-Devices ergänzen können. Zusätzlich würden wir noch den Grove Hat und dessen Adapter unterstützen. Wir bieten dem Studenten somit stabile Beispiele, dessen Funktionsfähigkeit auf der verwendeten Hardware garantiert werden kann. Unserer Meinung nach wäre dieser Ansatz wesentlich gewinnbringender für die Studierenden als eine oberflächliche Simulation. Die schwierige Arbeit bei einem IoT Projekt hängt nämlich immer von der verwendeten Hardware ab.</p>
<p>Diesen Ansatz haben wir bereits besprochen. Resultat der Projektarbeit wären eine Art Guide für die Verwendung von Pi4J-Devices, welche wir mit unseren eigen FHNW-Devices ergänzen können. Zusätzlich würden wir noch den Grove Hat und dessen Adapter unterstützen. Wir bieten dem Studenten somit stabile Beispiele, dessen Funktionsfähigkeit auf der verwendeten Hardware garantiert werden kann. Unserer Meinung nach wäre dieser Ansatz wesentlich gewinnbringender für die Studierenden als eine oberflächliche Simulation. Die schwierige Arbeit bei einem GPIO Projekt hängt nämlich immer von der verwendeten Hardware ab.</p>
</div>
</div>
<div class="sect2">
Expand Down Expand Up @@ -1744,7 +1744,7 @@ <h2 id="_anhang">Anhang</h2>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2020-08-13 21:04:37 +0200
Last updated 2020-09-06 11:10:42 +0200
</div>
</div>
</body>
Expand Down
4 changes: 3 additions & 1 deletion docs/Tutorial.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,9 @@ image::./Grove_Ultrasonic_Ranger.jpg[width=75% RaspiCam Wiring]
[cols="1,1"]
|===
|*Konstruktor* |*Beschreibung*
|UltraSonicRangerComponent​(GroveAdapter groveAdapter) |Standard Constructor for the Ultra Sonic Ranger that only needs grove hat connection information.
|UltraSonicRangerComponent​(GroveAdapter groveAdapter) |Standard Constructor for the Grove Ultra Sonic Ranger that only needs grove hat connection information.
|UltraSonicRangerComponent​(Pin pin) |Constructor for the Ultrasonic Ranger that uses the same pin for the trigger and the echo
|UltraSonicRangerComponent​(Pin trigger, Pin echo) |Constructor for using the Grove Ultrasonic Ranger without the Grove Base Hat. This is also compatible with other Ultrasonic Rangers that use different pins for the trigger and the echo
|===

.Ultrasonic Ranger - Funktionen
Expand Down
54 changes: 35 additions & 19 deletions docs/Tutorial.html
Original file line number Diff line number Diff line change
Expand Up @@ -1972,7 +1972,7 @@ <h4 id="_anwendungsbeispiel_2">6.2.3. Anwendungsbeispiel</h4>
Console console = new Console();
console.promptForExit();

GpioPinDigitalInput pin = gpio.provisionDigitalInputPin(RaspiBcmPin.GPIO_17);
GpioPinDigitalInput pin = gpio.provisionDigitalInputPin(RaspiBcmPin.GPIO_25);
ButtonComponent button = new ButtonComponent(pin);

boolean lastStatePressed = false;
Expand Down Expand Up @@ -2107,7 +2107,7 @@ <h4 id="_anwendungsbeispiel_3">6.3.3. Anwendungsbeispiel</h4>
Console console = new Console();
console.promptForExit();

GpioPinPwmOutput pwm = gpio.provisionPwmOutputPin(RaspiBcmPin.GPIO_12);
GpioPinPwmOutput pwm = gpio.provisionPwmOutputPin(RaspiBcmPin.GPIO_18);
BuzzerComponent buzzer = new BuzzerComponent(pwm);

Note notes[] = { Note.G4, Note.G4, Note.G4, Note.DS4, Note.AS4, Note.G4, Note.DS4, Note.AS4, Note.G4, Note.D5,
Expand Down Expand Up @@ -2535,7 +2535,15 @@ <h4 id="_api_7">6.7.2. API</h4>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">UltraSonicRangerComponent​(GroveAdapter groveAdapter)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Standard Constructor for the Ultra Sonic Ranger that only needs grove hat connection information.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Standard Constructor for the Grove Ultra Sonic Ranger that only needs grove hat connection information.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">UltraSonicRangerComponent​(Pin pin)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Constructor for the Ultrasonic Ranger that uses the same pin for the trigger and the echo</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">UltraSonicRangerComponent​(Pin trigger, Pin echo)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Constructor for using the Grove Ultrasonic Ranger without the Grove Base Hat. This is also compatible with other Ultrasonic Rangers that use different pins for the trigger and the echo</p></td>
</tr>
</tbody>
</table>
Expand Down Expand Up @@ -2572,7 +2580,14 @@ <h4 id="_anwendungsbeispiel_7">6.7.3. Anwendungsbeispiel</h4>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java"> UltraSonicRangerComponent ultraSonicRangerComponent = new UltraSonicRangerComponent(GroveAdapter.D5);
<pre class="highlight"><code class="language-java" data-lang="java"> GpioFactory.setDefaultProvider(new RaspiGpioProvider(RaspiPinNumberingScheme.BROADCOM_PIN_NUMBERING));
final GpioController gpio = GpioFactory.getInstance();

//Ultrasonic Ranger on the CrowPi
GpioPinDigitalInput echo = gpio.provisionDigitalInputPin(RaspiBcmPin.GPIO_12);
GpioPinDigitalInput trigger = gpio.provisionDigitalInputPin(RaspiBcmPin.GPIO_16);

UltraSonicRangerComponent ultraSonicRangerComponent = new UltraSonicRangerComponent(trigger, echo);

//Shows the measured distance every second
while (true) {
Expand Down Expand Up @@ -3703,23 +3718,23 @@ <h4 id="_ausarbeitung_projektidee">7.2.1. Ausarbeitung Projektidee</h4>
<p>Die blauen Ovale im Diagramm entsprechen einzelnen Phasen, in welchen sich die Applikation befinden kann. Mit den Pfeilen wird angedeutet, wie zwischen den Phasen gewechselt werden kann. Zum Beispiel kann aus Phase 0 nur dann in die Phase 1 gewechselt werden, wenn ein Button gedrückt wird. Solange der Button nicht betätigt wird, bleibt das Programm in der Phase 0.</p>
</div>
<div class="paragraph">
<p>Als nächstes muss definiert werden, was in den jeweiligen Schritten alles geschehen soll.</p>
<p>Als nächstes muss definiert werden, was in den jeweiligen Phasen alles geschehen soll.</p>
</div>
<div class="paragraph">
<p><strong class="underline">Phase 0</strong>
In diesem Schritt wird darauf gewartet, dass ein User die Photo Booth via Button Click aktiviert. Das LCD zeigt einen Text an, welcher den Benutzer dazu einlädt, den Knopf zu drücken. Sobald der Button betätigt wurde, wechseln wir in den nächsten Phase.</p>
In dieser Phase wird darauf gewartet, dass ein User die Photo Booth via Button Click aktiviert. Das LCD zeigt einen Text an, welcher den Benutzer dazu einlädt, den Knopf zu drücken. Sobald der Button betätigt wurde, geht das Programm in die nächste Phase über.</p>
</div>
<div class="paragraph">
<p><strong class="underline">Phase 1</strong>
In dieser Phase wird solange gewartet, bis sich der Benutzer korrekt positioniert hat. Wir fordern den Benutzer via LCD auf, sich einen Meter von der Kamera zu entfernen. Die Distanz wird mit dem Grove Ultrasonic Ranger gemessen und auf dem LCD angezeigt. Solange sich der User nicht korrekt platziert hat, wird das LED Band rot leuchten. Sobald der Benutzer sich in der entsprechenden Distanz eingefunden hat, wechselt die Farbe des Bandes auf grün und es kann zum dritten Schritt übergegangen werden.</p>
In dieser Phase wird solange gewartet, bis sich der Benutzer korrekt positioniert hat. Der Benutzer wird via LCD aufgefordert, sich einen Meter von der Kamera zu entfernen. Die Distanz wird mit dem Grove Ultrasonic Ranger gemessen und auf dem LCD angezeigt. Solange sich der User nicht korrekt platziert hat, wird das LED Band rot leuchten. Sobald der Benutzer sich in der entsprechenden Distanz eingefunden hat, wechselt die Farbe des Bandes auf grün und es kann zu Phase 2 übergegangen werden.</p>
</div>
<div class="paragraph">
<p><strong class="underline">Phase 2</strong>
Dieser Phase startet einen Countdown von 5 Sekunden. Die verbleibende Zeit wird einerseits auf dem LCD angezeigt und andererseits durch den Stepper Motor mittels einer Skala indiziert. Bei jedem Sekundenwechsel ertönt ein Signalton via Buzzer. Sobald der Countdown abgelaufen ist, wird in den finalen Schritt gewechselt.</p>
In dieser Phase startet einen Countdown von 5 Sekunden. Die verbleibende Zeit wird einerseits auf dem LCD angezeigt und andererseits durch den Stepper Motor mittels einer Skala indiziert. Bei jedem Sekundenwechsel ertönt ein Signalton via Buzzer. Sobald der Countdown abgelaufen ist, wird in die finale Phase gewechselt.</p>
</div>
<div class="paragraph">
<p><strong class="underline">Phase 3</strong>
In diesem Schritt wird das Bild geschossen. Bevor dies passiert, leuchtet der LED Streifen weiss auf und der Buzzer spielt einen hohen Ton ab. Anschliessend wir das Bild erstellt und abgespeichert. Auf dem LCD wird angezeigt, dass das Bild geschossen wurde. Zu guter Letzt wird der Stepper Motor wieder auf seine initiale Position gesetzt und zurück in die Phase 0 gewechselt. Die Photo Booth ist bereit für den nächsten Kunden.</p>
In dieser letzten Phase wird das Bild geschossen. Bevor dies passiert, leuchtet der LED Streifen weiss auf und der Buzzer spielt einen hohen Ton ab. Anschliessend wir das Bild erstellt und abgespeichert. Auf dem LCD wird angezeigt, dass das Bild geschossen wurde. Zu guter Letzt wird der Stepper Motor wieder auf seine initiale Position gesetzt und das Programm wechselt zurück in die Phase 0. Die Photo Booth ist bereit für den nächsten Kunden.</p>
</div>
</div>
<div class="sect3">
Expand Down Expand Up @@ -3793,7 +3808,7 @@ <h4 id="_codierung">7.2.3. Codierung</h4>
GpioPinDigitalOutput out4 = gpio.provisionDigitalOutputPin(RaspiBcmPin.GPIO_25);
stepperMotor = new StepperMotorComponent(out1, out2, out3, out4);

ledStripDriver = new LedStripDriverComponent(GroveAdapter.D18);
ledStripDriver = new LedStripDriverComponent(GroveAdapter.D5);
ledStripDriver.start();
ledStripDriver.setColor(0, 0, 0);
ledStripDriver.stop();
Expand All @@ -3805,7 +3820,7 @@ <h4 id="_codierung">7.2.3. Codierung</h4>
.height(1080)
.encoding(Encoding.JPEG)
.quality(85)
.rotation(180);
.rotation(0);
raspberryPiCamera = new RaspberryPiCameraComponent(stillConfig);
}</code></pre>
</div>
Expand All @@ -3816,6 +3831,7 @@ <h4 id="_codierung">7.2.3. Codierung</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java"> private void waitForButtonPress() throws InterruptedException {
lcd.clearText();
lcd.displayText("Press Button", 1);
lcd.displayText("To Start!", 2);
Thread.sleep(1000);
Expand Down Expand Up @@ -3958,7 +3974,7 @@ <h4 id="_status_modifizieren">8.1.1. Status modifizieren</h4>
if (dimmable) {
setBrightness(0);
} else {
pin.high();
pin.low();
}

ComponentLogger.logInfo("LedComponent: LED turned off");
Expand Down Expand Up @@ -4404,12 +4420,12 @@ <h4 id="_trigger_signal">8.6.1. Trigger Signal</h4>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java"> ComponentLogger.logInfo("UltraSonicRangerComponent: Trigger to measure distance");
Gpio.pinMode(pin, Gpio.OUTPUT);
Gpio.digitalWrite(pin, false);
Gpio.pinMode(triggerPin, Gpio.OUTPUT);
Gpio.digitalWrite(triggerPin, false);
Thread.sleep(0, 2000);
Gpio.digitalWrite(pin, true);
Gpio.digitalWrite(triggerPin, true);
Thread.sleep(0, 10000);
Gpio.digitalWrite(pin, false);</code></pre>
Gpio.digitalWrite(triggerPin, false);</code></pre>
</div>
</div>
</div>
Expand All @@ -4424,15 +4440,15 @@ <h4 id="_echo_messen">8.6.2. Echo messen</h4>
int TIMEOUT = 1000000; //just a large number to avoid an endless loop when there is a device problem

//wait for the pulse to start (ultra sonic wave sent)
while (count &lt; TIMEOUT &amp;&amp; Gpio.digitalRead(pin) == 0)
while (count &lt; TIMEOUT &amp;&amp; Gpio.digitalRead(echoPin) == 0)
count++;

if (count &gt;= TIMEOUT) return 0;
long t1 = microTime();

count = 0;
//wait for the pulse to end (ultra sonic wave received)
while (count &lt; TIMEOUT &amp;&amp; Gpio.digitalRead(pin) == 1)
while (count &lt; TIMEOUT &amp;&amp; Gpio.digitalRead(echoPin) == 1)
count++;
if (count &gt;= TIMEOUT) return 0;
long t2 = microTime();
Expand Down Expand Up @@ -5729,7 +5745,7 @@ <h2 id="_literaturverzeichnis">Literaturverzeichnis</h2>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2020-08-13 20:54:26 +0200
Last updated 2020-09-08 10:39:57 +0200
</div>
</div>
</body>
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/fhnwexamples/Examples.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ private static void initializeDeviceExamples() {
deviceExamples.add(new SerialCamera(11, "Grove Serial Camera example"));
deviceExamples.add(new RaspberryPiCameraDevice(12, "Raspberry Pi Camera example"));
deviceExamples.add(new LedStripDriverDevice(13, "LED Strip Driver example"));
deviceExamples.add(new SampleProject(99, "SampleProject!"));
deviceExamples.add(new PresentationProject(98, "Presentation Project!"));
deviceExamples.add(new SampleProject(99, "Sample Project!"));
}

/**
Expand Down
Loading

0 comments on commit 7d1d53d

Please sign in to comment.