Arduino Lektion 89: 4fach Segmentanzeige TM1636 / TM1637

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.

Temperaturanzeige des NTC-Widerstandes am RTC Shield von Open-Smart
Temperaturanzeige des NTC-Widerstandes am RTC Shield von Open-Smart

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 besondert 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ück liefern. 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;
  }
}
Video
 
Download

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.