Tinkering Arduino

eine kleine Welt der Elektronik.

Erweiterung Des Countdown Timers Unter Verwendung Einer Angepassten Colorduino Bibliothek

Vor einem Monat habe ich hier die erste Version einen Zählers veröffentlicht. In dieser wurde der Quelltext der Colorduino DEMO für das Arduino Colors Shield verwendet. Das macht das Programm recht unübersichtlich. Die Arduino Software erlaubt es aber Programmteile als Bibliothek (Library) einzubinden. Im heutigen Beitrag möchte ich die Verwendung einer eigenen Bibliothek zeigen und das Programm für den Countdown erweitern und einen Kameraauslöser anbinden.

Das Ziel dieser Erweiterung soll sein:

  • Mit einen Taster kann der Countdown beliebig gestartet werden.
  • Mit zwei weiteren Tastern lässt sich die Zeit für den Countdown einstellen, wobei der Startwert für den nächsten Countdown erhalten bleibt.
  • Ein Piezo-Lautsprecher soll beim Countdown ein Ton ausgeben.
  • Am Ende des Countdowns soll bei einer Kamera ein Foto ausgelöst werden.

Einige Vorbreitungen sind erforderlich, damit neben dem Programm auch die Funktionalität erweitert werden kann.

Verbindung des Arduinos mit dem Colors Shield

Das ITEAD Colors Shield v1.1 lässt sich einfach auf den Arduino stecken, allerdings kann man dann nicht ohne weiteres die nicht verwendeten Pins des Arduinos verwenden. Wenn man kein passendes Shield hat, dass die Pins noch einmal heraus führt, kann man mit zwei Breadboards und einigen Drähten die notwendigen Pins des Ardinos mit dem Colors Shield verbinden und andere Bauelemente mit den freien Pins verbinden.

So könnte die Verbindung des Arduino mit dem Colors Shield dann aussehen.

Der Aufbau der Schaltung

Für den weiteren Schaltungsaufbau haben wir dann u.a. die PINs D0, D1, D2, D3 und A3, A4, A5 zur Verfügung, die in der Schaltung für die Taster und den Piezo Lautsprecher genutzt werden können. Im Programm wird der rechte Taster an PIN D2 für das Starten des Countdowns verantwortlich sein. der linke Taster an PIN A4 wird den Startwert um eine Sekunde erhöhen, der rechte der beiden Taster an PIN A5 wird den Startwert um eine Sekunde verringern. An PIN A3 wird der Piezo Lautsprecher betrieben.

Die Taster schalten auf HIGH und werden über das Programm entprellt, dazu aber später mehr. Damit ein definierter Wert an D2, A4 und A5 anliegt, wird der Taster zusätzlich mit GND verbunden. Direkt darf man das aber nicht machen, da es sonst zu einem Kurzschluss kommt. Daher wurde jeweils ein 10kOhm Widerstand dazwischen geschalten. Im Programm werden wir noch die Kamera auf dem freien PIN D5 ansteuern.

Wenn der Schaltungsaufbau soweit erledigt ist, können wir das Programm betrachten.

Verwendung einer Bibliothek für die Ausgabe auf dem Colors Shield / Colorduino

Im letzten Beitrag hatte ich den Ansatz ohne die Verwendung einer Bibliothek gewählt, was es nicht gerade erleichtert den Quelltext zu überblicken und zu sehen, was nun Teil der eigenen Programmierung ist und was lediglich für die Ausgabe benötigt wird. Wenn mit dem Colors Shield andere Projekte umgesetzt werden sollen, müsste man die entsprechenden Teile des Programms immer neu schreiben, oder zumindest aus einem alten Programm kopieren. Wie man sich vorstellen kann, ist das einerseits Fehleranfällig und andererseits schwierig zu aktualisieren. Daher bietet auch der Arduino an, auf Bibliotheken zurück zu greifen, die sicher jeder schon einmal eingebunden hat, ohne vielleicht genau zu wissen, dass es gemacht wurde. Eine Bibliothek ist dabei einfach gesagt, Programmcode, der möglichst allgemein (generisch) ist und alle Funktionen für eine Aufgabe kapselt. Warum sollte man also nicht alles, was für die Ausgabe auf dem Colors Shield (oder dem Colorduino) gebraucht wird und nicht zum Programm gehört in eine Bibliothek auslagern. Eine entsprechende Vorlage für eine solche Colorduino-Bibliothek habe ich auf Github Account von lincomatic gefunden. Diese habe ich zu in das eigene Projekt eingebunden und etwas erweitert, um noch ein wenig mehr Logik in die Bibliothek zu legen. Im Github Account tinkering-arduino findet man das zu diesem Beitrag das dazugehörige Projekt Countdown_8x8_RGB_LED in einer aktualisierten Version.

Das Installieren der Bibliothek ist sehr einfach. Der Ordner der Bibliothek, in diesem Fall Colorduino wird in das Verzeichnis “Documents/Arduino/libraries” kopiert. Anschließend muss die Arduino Software neu gestartet werden. Auf der Arduino Seite findet man auch eine ausführliche Installationsanleitung.

Die Einbindung ist mit einem

1
#include "Colorduino.h"

ist dass dann auch schon getan.

Das Programm

Das Hauptprogramm

Es lohnt sich wahrscheinlich nicht, die 400 Zeilen Programm zu besprechen, so dass ich einige wichtige Teile herausgreife und mich am Ablauf orientieren werden. Dazu gehören auf jeden Fall die Funktionen setup() und loop(). Achtung, im Gegensatz zu frühren Beispielen ist die Angabe der Zeilennummern auf die Codebeispiele bezogen, nicht auf die im Programm selbst.

1
2
3
4
5
6
7
8
unsigned char whiteBalace[3] = {1,63,63}; // red=1, green=63, blue=63

const int startButtonIn = 2;  // D2
const int upButtonIn = 19;    // A5
const int downButtonIn = 18;  // A4

const int speakerOut = 17;    // A3
const int cameraShotOut = 5;  // D5
1
2
3
4
5
6
7
8
9
10
11
void setup() {
  pinMode(startButtonIn, INPUT);
  pinMode(upButtonIn, INPUT);
  pinMode(downButtonIn, INPUT);

  pinMode(speakerOut, OUTPUT);
  pinMode(cameraShotOut, OUTPUT);

  Colorduino.init();
  Colorduino.setWhiteBal(whiteBalace);
}

Neben den Konfigurationen der zusätzlichen PINs für die Tastern, den Piezo-Lautsprecher und der Anbindung der Kamera wird in Zeile 18 die Initialisierungsfunktion der Colorduino Bibliothek aufgerufen und in Zeile 19 der Weißabgleich durchgeführt. Die Werte können natürlich bei euch andere sein.

1
2
3
4
5
6
7
8
9
unsigned int wait = 100;
unsigned int count_down_start = 10;
unsigned int count_down = count_down_start;
unsigned long time_before, time_after;

unsigned int pixel_r = 0;
unsigned int pixel_g = 0;
unsigned int pixel_b = 0;
unsigned int freq = 0;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  pixel_r = 0;
  pixel_g = 0;
  pixel_b = 100;

  freq = 0;

  showNumber( count_down_start, pixel_r, pixel_g, pixel_b );

  if (digitalRead(upButtonIn) == HIGH) {
    upButtonInPressed();
  } else if (digitalRead(downButtonIn) == HIGH) {
    downButtonInPressed();
  } else if (digitalRead(startButtonIn) == HIGH) {
    startButtonInPressed();
  }

  delay(10);

In den Zeilen 1-3 werden die Werte für die Farben der Ausgabe geändert. Die Zeilen 9-15 prüfen, ob der Wert HIGH an einem der PINs anliegt. Je nach dem welcher Taster gedrückt wurde, wird eine entsprechende Funktion aufgerufen. Da die Funktionen upButtonInPressed() und downButtonInPressed() sehr ähnlich sind, soll exemplarisch die upButtonInPressed() angesehen werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void upButtonInPressed() {
  if (count_down_start == 99) return;

  delay(10);

  if (digitalRead(upButtonIn) == HIGH) {
    playTone( TONE_D*2, TONE_LENGTH );

    slideNumber(count_down_start, pixel_r, pixel_g, pixel_b, 30, 1, -1);
    count_down_start += 1;

    while (digitalRead(upButtonIn) == HIGH) {
      delay(10);
    }
    delay(50);
  }
}

In der ersten Zeile der Funktion wird geprüft, ob der Startwert für den Countdown schon bei dem Maximum von 99 liegt. Mehr kann derzeit nicht dargestellt werden und wird so verhindert. Die Pause und das erneute Auslesen des Buttons nach einer kurzen Pause, dient zum programmatischen Entprellen des Tasters. In Zeile 7 wird dann ein Ton ausgegeben. Warum der Ton über eine eigene Funktion playTone() so ausgegeben wird und nicht die Funktion tone() für den Arduino verwendet wird, soll später, wenn die Funktion besprochen wird, erklärt werden. In Zeile 9 wird eine Funktion aufgerufen, die die nächste Zahl auf dem Display ausgibt. Was genau passiert, wird bei der Behandlung der Funktion erklärt. Ich möchte an dieser Stelle nur darauf hinweisen, dass diese Zeile ich von der Zeile in der Funktion downButtonInPressed() unterscheidet. Die zwei zusätzlichen Parameter sind Optional und sollen vom Standard abweichen. Der vorletzte Parameter gibt an, dass next nicht -1 sondern 1 ist, also die nächst höhere Zahl reingerollt werden soll. Der letzte Parameter wird auf -1 gesetzt, und gibt so die Richtung des reinrollens an. Hier von oben nach unten. In den Zeilen 12-14 wird noch auf das Loslassen des Tasters gewartet. Möchte man, die Funktion so umbauen, dass so lange automatisch erhöht werden soll, bis der Taster losgelassen wird, kann man diese Zeilen entfernen. Im aktuellen Programm ist für jedes Erhöhen ein Tastendruck erforderlich.

In der Hauptschleife loop() wurde noch der Taster für das Starten des Countdowns abgefragt. Dieser ruft die Funktion startButtonInPressed() auf, die im folgenden betrachtet werden soll.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void startButtonInPressed() {
  delay(10);

  if (digitalRead(startButtonIn) == HIGH) {
    playMelody( melody, beats );

    countDown();

    while (digitalRead(startButtonIn) == HIGH) {
      delay(10);
    }
    delay(50);
  }
}

Auch in dieser Funktion finden wir die programmatische Entprellung. Im Gegensatz zu den Tastern für “up” und “down”, wird in Zeile 5 die Funktion playMelody() aufgerufen. Neben dem Aufruf der Funktion countDown() ist in der Funktion nichts aufregendes zu finden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void countDown() {
  pixel_r = 0;
  pixel_g = 100;
  pixel_b = 0;

  freq = TONE_C;

  count_down = count_down_start;

  for (count_down; count_down > 0; count_down--) {

    time_before = millis();
    if (count_down <= 4) {
      pixel_r = 100;
      pixel_g = 0;
      pixel_b = 0;
      freq = TONE_C * 2;
    }
    slideNumber(count_down, pixel_r, pixel_g, pixel_b, 30);

    playTone( freq, TONE_LENGTH );

    time_after = millis();
    delay( 1000 - (time_after-time_before) );
  }

  countDownEnded();

  count_down = count_down_start;
}

Diese Funktion sollte aus dem vorangegangen Beitrag in ähnlicher Art und Weise zu finden. Ich möchte an dieser Stelle auch auf den Beitrag verweisen. Im wesentlichen sind hier folgende Änderungen hinzugekommen:

  • Der Funktionsaufruf DispSlideInt() in Zeile 19 wurde zu slideNumber() geändert.
  • Es wird ein Ton nach jedem Zählen ausgegeben. Dafür sind die Zeilen 6,17 und 21 verantwortlich.
  • In Zeile 27 wird die Funktion countDownEnded() aufgerufen, die dann das Auslösen der Kamera übernehmen kann.
  • In Zeile 29 wird der Startwert für den Countdown wieder eingestellt.

Bevor wir uns die Funktionen für die Ausgabe der Zahlen anschauen, will ich kurz auf playMelody() und playTone() eingehen.

Die Funktionen playMelody() und playTone()

Die Ausgabefunktionen showNumber(), slideNumber() und blinkNumber()

Links

Auch diesmal habe ich ein kleines Video aufgenommen:

Im GitHub-Account findet man das aktualisierte Projekt Countdown_8x8_RGB_LED und dem entsprechenden Commit.

Comments