
Sturzi's Arduino-Bastelprojekt #2 - Speed-o-Meter und Rundenzähler mit Infrarot-Lichtschranken
-
-
Cool… selber 3d gedruckt?
So ein Ding ist schon praktisch…
-
Cool… selber 3d gedruckt?
So ein Ding ist schon praktisch…Sicher. Ich habe aber noch Einiges vor. Das war erst der erste Prototyp.
-
Ich hab einen Entwurf mit sperrholz und transparentem Polycarbonat auf dem Tisch… mal schauen ob das was wird.
-
Ich hab einen Entwurf mit sperrholz und transparentem Polycarbonat auf dem Tisch… mal schauen ob das was wird.
Da bin ich gespannt.
-
Soweit habe ich alles zusammen gebaut und die Anzeige zeigt an was sie soll.
Der Schalter hat im Moment noch keine Funktion?
Warum tauchen im Programm am Ende aus Beitrag #80 die Konstanten und die Setups für die pinMode aus Beitrag #74 nicht auf? Habe ich etwas verschlafen oder werden die im Moment noch nicht benötigt?
-
Der Schalter hat im Moment noch keine Funktion?
Das ist richtig.
Warum tauchen im Programm am Ende aus Beitrag #80 die Konstanten und die Setups für die pinMode aus Beitrag #74 nicht auf? Habe ich etwas verschlafen oder werden die im Moment noch nicht benötigt?
Die werden im Moment noch nicht benötigt.
-
Hoi Röbi
Bei mir zeigt die Anzeige an, wie du es vorgemacht hast. Nur der Arduino ist nicht rot geworden, dafür meine Ohren. Sehr lange blieben in der Anzeige die Runden auf "**" stehen. Bis ich im Test einen Schreibfehler fand, der in der Compilation keine Fehlermeldung erzeugte.
Jetzt klappt es.
Gruss Oski
-
Hallo Röbi, liebe ARDUINO-Mitfieberer
Ich habe das Display ebenfalls mit den Daten zum Leben erweckt. Da ich den Typ B habe, braucht es einige Änderungen, die hier im Anhang eingetragen sind. Insbesondere sind im void setup() die Zeilen lcd.init() und zusätzlich lcd.backlight() eingefügt.
ohne lcd.rücklicht() bleibt das Display dunkel.
Gruss Peter
-
Hoi Röbi
Auch bei mir sieht derAufbau ähnlich aus. und es zeigt das gewünschte an.
Da bin ich schon ganz glücklich.
Ich bin ehrlich, verstanden habe ich nicht alles aber gewisse Zusammenhänge kommen mir duch das wiederholen schneller wieder in den Sinn.
Eine Frage zum Anschluss der Sensoren habe ich noch.
Plus/GND sind klar aber welchen Pin nehme ich für die Verbindungen 11 und 12? da gibt es D0 und A0
-
Hallo Andy
Schön, dass es bei dir auch funktioniert!
Eine Frage zum Anschluss der Sensoren habe ich noch.
Plus/GND sind klar aber welchen Pin nehme ich für die Verbindungen 11 und 12? da gibt es D0 und A0
Andy, schau beim Beitrag 69. Dort ist es erklärt.
Beim Typ C sind die Pins 12 und 11 bei der 9-Stiften-Gruppe rechts oben, der 2. und der 3. Stift von links. Sie sind angeschrieben mit D12 und D11 (D steht für Digital). A steht für die Analog Inputs, aber die brauchen wir bei dem Projekt nicht.
Beim Typ D sind die Pins 12 und 11 bei der Löt-Ösen-Gruppe rechts oben die 2. und die 3. Öse von links (ich habe sie nur durch durchpiepsen herausgefunden).
-
-
Hoi Röbi
Es macht alles was es muss Herzlichen Dank!!
Sigu
-
Guten Abend
Auch mein Display zeigt das gewollte an :-).
Bin aber nicht 100% sicher ob ich die Lichtschranken richtig angeschlossen habe. Bei beiden ist Ruhezustand die rote LED aktiv, sobald ich diese anstosse ist auch die grüne aktiv und erlischt nachdem sie wieder "frei" sind.
Gruess
Erich
-
-
@Erwin, Oski, Peter, Andy, Roland, Sigu, Erich und Martin: Vielen Dank für die verschiedenen Rück- und Erfolgsmeldungen. Es freut mich, dass es soweit geklappt hat.
-
Zwischenschritt für Typ C und D - Keypad Handling
Wir benötigen einen Taster, um die Anzeige zu löschen, damit das Speed-o-Meter für die nächste Messung bereit ist. Wenn wir schon ein Keypad-Shield mit Tastern haben, wollen wir einen davon für diesen Zweck brauchen. Wir haben insgesamt sechs Taster:
- Derjenige ganz rechts ist der Reset-Taster für den Arduino. Er hat die gleiche Funktion wie der Taster auf dem Arduino selber, nämlich den Arduino neu zu starten. Über diesen können wir NICHT nach unserem Gutdünken verfügen.
- Derjenige ganz links (Select) steht zur freien Verfügung
- Die inneren vier, in einem Trapez angeordneten, sind gedacht für links, ab, auf und rechts. Auch über diese können wir frei verfügen.
Ich schlage vor, dass wir die Select-Taste (die linke) für das Löschen der Anzeige und das Bereitstellen der Speed-o-Meter für neue Messungen verwenden.
Damit wir nicht für jeden Taster einen eigenen digitalen Eingang verwenden (eigentlich verschwenden) müssen, hat sich der Entwickler des Keypad-Shields etwas einfallen lassen. Die fünf Taster (alle ausser dem Reset) sind intern in einer Anordnung von Widerständen als Spannungsteiler verbunden. Dieser ist fest mit dem analogen Eingang A0 verdrahtet. Durch diesen Trick verursacht jede Taste eine andere Spannung am A0, die wir per Programm erkennen können.
Die Funktion buttonPressedOnKeypad() liest nun den A0 ein, stellt fest, welcher Taster gedrückt worden ist und meldet das ans aufrufende Programm zurück.
Übernehmt folgendes Programm in die Sandbox (oder wie ihr auch immer ein Test-Programm nennt) und probiert es aus:
Code
Alles anzeigen#include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); const byte KEYPAD_BUTTON_NONE = 0; const byte KEYPAD_BUTTON_SELECT = 1; const byte KEYPAD_BUTTON_LEFT = 2; const byte KEYPAD_BUTTON_DOWN = 3; const byte KEYPAD_BUTTON_UP = 4; const byte KEYPAD_BUTTON_RIGHT = 5; void setup() { lcd.begin(16, 2); lcd.clear(); } void loop() { byte button = buttonPressedOnKeypad(); lcd.setCursor(0, 0); if (button == KEYPAD_BUTTON_SELECT) { lcd.print("select "); } else if (button == KEYPAD_BUTTON_LEFT) { lcd.print("nach links "); } else if (button == KEYPAD_BUTTON_DOWN) { lcd.print("nach unten "); } else if (button == KEYPAD_BUTTON_UP) { lcd.print("nach oben "); } else if (button == KEYPAD_BUTTON_RIGHT) { lcd.print("nach rechts "); } else { lcd.print("nichts gedrueckt"); } delay(200); } byte buttonPressedOnKeypad() { int inpVal = analogRead(A0); if (inpVal < 70) return KEYPAD_BUTTON_RIGHT; if (inpVal < 256) return KEYPAD_BUTTON_UP; if (inpVal < 440) return KEYPAD_BUTTON_DOWN; if (inpVal < 670) return KEYPAD_BUTTON_LEFT; if (inpVal < 900) return KEYPAD_BUTTON_SELECT; return KEYPAD_BUTTON_NONE; }
Zeilen 5 bis 10: Diese Konstanten definieren Rückgabe-Werte für die einzelnen Taster. Die Verwendung von symbolischen Konstanten anstatt blossen Nummern, macht das Programm leserlicher und damit leichter verständlich.
Zeilen 36 bis 44: Dies ist eine neue Funktion. Sie liest den analogen Eingang A0 ein und speichert den Wert in inpVal vom Typ int. Je nach eingelesenem Wert bringt die Funktion eine der oben definierten Konstanten zurück. Die beiden Typen C und D liefern leicht unterschiedliche Werte, weil sie unterschiedliche Spannungsteiler eingebaut haben. Ich habe aber Grenzwerte (in den if-Statements) ermitteln können, die für beide Typen passen.
Auf dem Display müsste jetzt angezeigt werden, was im Moment gedrückt ist.
Wenn es funktioniert, müsstet ihr die Konstanten auf den Zeilen 5 bis 10 ins Speed-o-Meter Programm übernehmen (im oberen Teil vor der setup() Funktion. Die Funktion buttonPressedOnKeypad() (Zeilen 36 bis 44) kann als neue Funktion unten angehängt werden.
Zum Schluss fügt noch folgende Funktion dazu:
Codebool clearButtonPressed() { if (buttonPressedOnKeypad() == KEYPAD_BUTTON_SELECT) { return true; } else { return false; } }
Diejenigen mit Typ A oder B haben bekanntlich kein Keypad Shield. Diese müssen sich mit einem gewöhnlichen Taster begnügen für die Rücksetzung der Werte. Die Funktion clearButtonPressed() wird nun als Version für Keypad (siehe oben) und als Version für gewöhnliche Taster verfügbar sein (nächster Beitrag).
Wir (Typ C und D) brauchen den gewöhnlichen Taster nicht mehr. Diesen können wir entfernen und auch die beiden Programmzeilen
const byte PIN_PUSH_BUTTON = 3;
pinMode(PIN_PUSH_BUTTON, INPUT_PULLUP);
brauchen wir nicht mehr.
-
Zwischenschritt für Typ A und B - Taster Handling
Wir benötigen einen Taster, um die Anzeige zu löschen, damit das Speed-o-Meter für die nächste Messung bereit ist. Da wir kein Keypad-Shield mit Tastern haben, behelfen wir uns mit einem gewöhnlichen Taster, der gemäss Beitrag 74 angeschlossen ist.
Die beiden Programmzeilen
const byte PIN_PUSH_BUTTON = 3;
pinMode(PIN_PUSH_BUTTON, INPUT_PULLUP);
müssten eigentlich schon im Programm vorhanden sein. Ansonsten bitte ergänzen.
Übernehmt folgendes Programm in die Sandbox (oder wie ihr auch immer ein Test-Programm nennt) und probiert es aus (die Spezialitäten für Typ B natürlich entsprechend angepasst):
Code
Alles anzeigen#include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const byte PIN_PUSH_BUTTON = 3; void setup() { lcd.begin(16, 2); lcd.clear(); pinMode(PIN_PUSH_BUTTON, INPUT_PULLUP); } void loop() { lcd.setCursor(0, 0); if (clearButtonPressed()) { lcd.print("clear button"); } else { lcd.clear(); } delay(200); } bool clearButtonPressed() { if (digitalRead(PIN_PUSH_BUTTON)) { return false; } else { return true; } }
Auf dem Display müsste jetzt angezeigt werden, wenn der Taster gerade gedrückt ist.
-
Die gedrückten Tasten werden korrekt angezeigt, dieser Teil funktioniert bei mir.
Das Speed-o-Meter Programm lässt sich fehlerfrei kompilieren, es passiert aber nichts wenn ich die Tasten drücke. Hat das damit zu tun, dass in der Zeile 16 und 17 ein Wert hineingeschrieben ist?
Code
Alles anzeigen#include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); const byte KEYPAD_BUTTON_NONE = 0; const byte KEYPAD_BUTTON_SELECT = 1; const byte KEYPAD_BUTTON_LEFT = 2; const byte KEYPAD_BUTTON_DOWN = 3; const byte KEYPAD_BUTTON_UP = 4; const byte KEYPAD_BUTTON_RIGHT = 5; const float MAX_VALUE_FOR_KM_PER_HOUR = 999.9; const int MAX_VALUE_FOR_LAP_COUNT = 99; const unsigned int MAX_VALUE_FOR_ELAPSED_TIME = 999.9; float speedKilometersPerHour[2] = {95.1, 103.2}; float averageSpeed[2] = {96.6, 102.8}; int lapCount[2] = {4, 3}; // Rundenzähler void setup() { lcd.begin(16, 2); lcd.clear(); displayResults(); } void loop() { } byte buttonPressedOnKeypad() { int inpVal = analogRead(A0); if (inpVal < 70) return KEYPAD_BUTTON_RIGHT; if (inpVal < 256) return KEYPAD_BUTTON_UP; if (inpVal < 440) return KEYPAD_BUTTON_DOWN; if (inpVal < 670) return KEYPAD_BUTTON_LEFT; if (inpVal < 900) return KEYPAD_BUTTON_SELECT; return KEYPAD_BUTTON_NONE; } bool clearButtonPressed() { if (buttonPressedOnKeypad() == KEYPAD_BUTTON_SELECT) { return true; } else { return false; } } void displayResults() { char buffer[6]; for (byte dir = 0; dir < 2; dir++) { if (speedKilometersPerHour[dir] > MAX_VALUE_FOR_KM_PER_HOUR) { strcpy(buffer, "*****"); } else { dtostrf(speedKilometersPerHour[dir], 5, 1, buffer); } lcd.setCursor(0, dir); lcd.print(buffer); if (averageSpeed[dir] > MAX_VALUE_FOR_KM_PER_HOUR) { strcpy(buffer, "*****"); } else { dtostrf(averageSpeed[dir], 5, 1, buffer); } lcd.setCursor(6, dir); lcd.print(buffer); if (lapCount[dir] > MAX_VALUE_FOR_LAP_COUNT) { strcpy(buffer, "**"); } else { sprintf(buffer, "%2d", lapCount[dir]); } lcd.setCursor(12, dir); lcd.print(buffer); } }
-
Das Speed-o-Meter Programm lässt sich fehlerfrei kompilieren, es passiert aber nichts wenn ich die Tasten drücke. Hat das damit zu tun, dass in der Zeile 16 und 17 ein Wert hineingeschrieben ist?
Erwin, hier passiert nichts, weil noch gar nichts passieren soll
. Die Funktion clearButtonPressed() ist erst vorbereitet und wird erst im nächsten Beitrag aufgerufen. So lang ist noch Geduld gefragt.