In diesem Tutorial möchte ich eine einfache Lösung vorstellen wie man die 4fach Segmentanzeige TM1637 bzw. TM1636 ansteuern kann.
Diese beiden Segmentanzeigen sind zbsp. auf den multifunktionalen Shields (RTC Shield und Rich Shield) von Open-Smart verbaut.
Nun möchte ich gerne vorstellen wie man diese beiden Segmentanzeigen ansteuern kann.
Auch für diese Segmentanzeigen gibt es eine Bibliothek, welche wir zunächst einmal installieren müssen.
Auch wenn die Bibliothek die Bezeichnung TM1636 trägt funktioniert diese auch für den Chip TM1637.
Der Bibliothek liegen einige Beispiele bei. Aus genau so einem Beispiel habe ich mir eine Funktion abgeleitet, um den Temperaturwert eines NTC-Widerstandes auf der Segmentanzeige anzeigen zu lassen.
Da wir nicht nur Temperaturen anzeigen lassen wollen, sondern auch zbsp. Uhrzeit, Werte eines Fotowiderstandes so benötigen wir jeweils eine andere Funktion jedoch immer mit den gleichen Konstanten. Daher habe ich mich einmal entschlossen eine kleine Bibliothek erstellen.
Funktionen
Die Bibliothek umfasst die Funktionen für das Anzeigen von Zahlen und Uhrzeiten.
getNumber(double value)
Die Funktion getNumber erhält als Parameter den Wert als Double welcher angezeigt werden soll. Zunächst einmal wird die Zahl in ein String umgewandelt (ohne Nachkommastellen).
String temp = String(value, 0);
Danach wird geprüft, ob die Zahl kleiner als 1000 ist, wenn ja, dann soll ein Leerzeichen an die erstelle Stelle des Arrays eingefügt werden.
if(value < 1000){ disp[++bits] = SPACE; }
Wenn die Zahl kleiner als 100 aber größer als 0 ist dann soll ein zusätzliches Leerzeichen eingefügt werden ansonsten ein Minuszeichen.
if(value < 100 && value > 0){ disp[++bits] = SPACE; } else if(value < 0){ disp[++bits] = NEGATIVE_SIGN; } if(value < 10 && value > 0){ disp[++bits] = SPACE; }
Nun muss noch die eigentliche Zahl in Ihre Bestandteile zerlegt werden. Dazu durchlaufen wir alle Stellen des Strings mit einer For-Schleife. Da Strings auch Steuerzeichen enthalten können, müssen wir diese besonders behandeln. Dieses wird uns durch die Funktion “charAt” erleichtert, denn man erhält den ASCII-Code zurück. Die Zahlen liegen im Bereich von 48 bis 57 d.h. wir brauchen nur prüfen, ob der ASCII-Code zwischen diesen beiden Werten liegt und nur dann fügen wir die Zahl in das Array ein.
for(int i = 0;i< temp.length();i++){ int pos = temp.charAt(i); if(pos >= 48 && pos <= 57){ pos = pos - ASCII_OFFSET; disp[++bits] = values[pos]; } }
Funktion “getNumber”
int8_t* getNumber(double value){ String temp = String(value, 0); int bits = -1; if(value < 1000){ disp[++bits] = SPACE; } if(value < 100 && value > 0){ disp[++bits] = SPACE; } else if(value < 0){ disp[++bits] = NEGATIVE_SIGN; } for(int i = 0;i< temp.length();i++){ int pos = temp.charAt(i); if(pos >= 48 && pos <= 57){ pos = pos - ASCII_OFFSET; disp[++bits] = values[pos]; } } return disp; }
getTime(int hours, int minutes)
Da man mit einer 4fach 7 Segmentanzeige maximal Stunden & Minuten anzeigen kann, erhält die Funktion “getTime” als Parameter die Werte für Stunden & Minuten.
Wenn gewünscht kann man auch Minuten & Sekunden übergeben.
Zunächst einmal werden die Zahlen wieder in Strings umgewandelt. Da wir hier mit Zeiteinheiten rechnen gibt es keine Kommastellen, welche wir entfernen müssen.
String stunden = String(hours); String minuten = String(minutes);
Als Nächstes prüfen wir, ob die Stunde kleiner als 10 ist, wenn ja, dann wird eine führende 0 in das Array eingefügt und an die zweite Stelle der Wert für die Stunde, andernfalls wird an der ersten bzw. zweiten Stelle die Zahl aus der Stunde eingesetzt.
if(hours < 10){ disp[++bits] = NUM_0; int firstChar = stunden.charAt(0)-48; disp[++bits] = values[firstChar]; } else { int firstChar = stunden.charAt(0)-48; int secondChar = stunden.charAt(1)-48; disp[++bits] = values[firstChar]; disp[++bits] = values[secondChar]; }
Das Gleiche wird auch mit den Werten für die Minuten gemacht.
if(minutes < 10){ disp[++bits] = NUM_0; int firstChar = minuten.charAt(0)-48; disp[++bits] = values[firstChar]; } else { int firstChar = minuten.charAt(0)-48; int secondChar = minuten.charAt(1)-48; disp[++bits] = values[firstChar]; disp[++bits] = values[secondChar]; }
Damit wir jedoch doppelten Code vermeiden möchten , erzeugen wir eine zusätzliche
Funktion “void convertNumbers(int number, int offset)” welche die Zahl übergeben bekommt.
Da das Array, welches die Zahlen für die spätere Anzeige enthält, global definiert wurde müssen wir in der Funktion nichts zurückliefern. Jedoch müssen wir zusätzlich ein Offset übergeben damit wir die Funktion 2-mal aufrufen können und die Zahl an der korrekten Stelle eingetragen wird.
void convertNumbers(int number, int offset){ int8_t result[2]; int bits = -1+offset; String numbers = String(number); if(number < 10){ disp[++bits] = NUM_0; int firstChar = numbers.charAt(0)-ASCII_OFFSET; disp[++bits] = values[firstChar]; } else { int firstChar = numbers.charAt(0)-ASCII_OFFSET; int secondChar = numbers.charAt(1)-ASCII_OFFSET; disp[++bits] = values[firstChar]; disp[++bits] = values[secondChar]; } }
Wichtig ist nun der geänderte Code in der Funktion “getTime”. Denn hier nutzen wir unsere zuvor erzeugte Funktion.
int8_t* getTime(int hours, int minutes){ convertNumbers(hours,0); convertNumbers(minutes,2); return disp; }
Funktion “getTime”
void convertNumbers(int number, int offset){ int8_t result[2]; int bits = -1+offset; String numbers = String(number); if(number < 10){ disp[++bits] = NUM_0; int firstChar = numbers.charAt(0)-ASCII_OFFSET; disp[++bits] = values[firstChar]; } else { int firstChar = numbers.charAt(0)-ASCII_OFFSET; int secondChar = numbers.charAt(1)-ASCII_OFFSET; disp[++bits] = values[firstChar]; disp[++bits] = values[secondChar]; } } int8_t* getTime(int hours, int minutes){ convertNumbers(hours,0); convertNumbers(minutes,2); return disp; }
Beispiele
Im Folgenden möchte ich zu jeder dieser Funktion ein kleines Beispiel zeigen.
Beispiel – anzeigen einer Uhrzeit
#include "TM1636.h" #include <math.h> #include "functions.h" #include <Wire.h> #include <TimeLib.h> #include <DS1307RTC.h> //Pins für das RTC Shield #define CLK 7 #define DATA 8 //Pins für das Rich Shield //#define CLK 10 //#define DATA 11 TM1636 tm1636(CLK, DATA); const int ntcWiderstand = 10000; // NTC-Widerstand mit 10 kOhm const int MAX_ANALOG_VALUE = 1023; void setup(){ Serial.begin(9600); //Initialisieren der Anzeige. tm1636.init(); } void loop(){ tmElements_t tm; if (RTC.read(tm)) { if((tm.Second %2)==0){ tm1636.point(POINT_ON); } else { tm1636.point(POINT_OFF); } tm1636.display(getTime(tm.Hour, tm.Minute)); } //eine kleine Pause 500ms. delay(500); }
Video
Download
Beispiel – anzeigen einer Zahl
#include "TM1636.h" #include <math.h> #include "functions.h" //Pins für das RTC Shield #define CLK 7 #define DATA 8 //Pins für das Rich Shield //#define CLK 10 //#define DATA 11 double number = 0; TM1636 tm1636(CLK, DATA); void setup(){ Serial.begin(9600); //Initialisieren der Anzeige. tm1636.init(); } void loop(){ tm1636.display(getNumber(++number)); //eine kleine Pause 500ms. delay(25); if(number > 9999){ number = 0; } }
1 thought on “Arduino Lektion 89: 4fach Segmentanzeige TM1636 / TM1637”