Montag, 11. Februar 2013

LED 8x8 Matrix (Rot/Grün) Schaltung

Led8x8Matrix_01
Die LED 8x8 Matrix an meiner Schaltung.

So einige wie ich haben seltsamerweise kein Dokument zu der LED Matrix im Internet gefunden. Letzten Endes habe ich dann selbst durch einiges Prüfen herausgefunden, welcher Pin nun für welche Funktion ist. Anschließend konnte ich dann einen Versuchsaufbau starten, der allerdings aufwendiger wurde. Auf den ersten Blick sieht meine Schaltung mit den vielen Kabeln ziemlich unüberschaubar aus. Dennoch habe ich den Aufbau mal wieder aus dem Kopf heraus zusammengesteckt, woran man sieht, dass diese Schaltung nicht sonderlich kompliziert sein kann.

image
Die Verwendeten ICs. Shiftregister, 2x Demultiplexer und 2x Inverter

Für die Schaltung habe ich Folgendes verwendet:

  • LED 8x8 Matrix (Rot/Grün)
  • Shiftregister (74hc595)
  • 2x Demultiplexer (74HC154)
  • 2x Inverter (74F04)
  • 8x Widerstände (150 Ohm)
  • 2x kurze Breadboards
  • 1x langer Breadboard
  • und viel Kabel zum Verbinden

Der Netduino wird hier als Steuereinheit verwendet, auf dem später meine Library “Game of Life” läuft.

Der Shiftregister ist entscheidend für die Darstellung an der LED-Matrix, da diese Einheit den Zustand der Demultiplexer schaltet, wenn alle 8 Bits gesetzt wurden. Im meinem ersten Versuch habe ich die zwei Demultiplexer direkt am Netduino angeschlossen. Hierbei wurden mehrere LEDs als gesetzt geschaltet. Der Fehler ließ sich jedoch nachvollziehen. In einer Methode habe ich die 8 Ausgänge geschaltet, die sehr zeitnah nacheinander ausgeführt werden. Leider war dieser Vorgang nicht schnell genug, so dass sich während dieser Zeit auch andere Schaltzustände ergaben. Zwar leuchten die nicht gesetzten LEDs nicht hell, aber dennoch stört dieser Zustand.

Schaltbild_LED_Matrix_8x8
Schaltbild von der LED Matrix.

An der LED Matrix sind insgesamt 24 Pins und deswegen sind es zum Anschließen an einen einzelnen Netduino oder Arduino zu viel. Abhilfe schafft hier der Demultiplexer, der mit seinen 4 Eingängen bis zu 16 Zustände annehmen kann. Da einer nicht reicht, kommt ein zweiter hinzu, und wenn man diese in eine Matrix einbindet, dann können bis zu 256 Zustände erreicht werden. Den ersten Demultiplexer verwende ich für die 8 Reihen Rot und 8 Reihen Grün. Der zweite ist für die 8 Zeilen, die vorher durch einen Inverter geschaltet werden. Grund hierfür sind die Signale an den Demultiplexerausgängen, die negiert sind. Die Widerstände teilen die Spannung auf und trimmen die Stromaufnahme bei 20mA. Jedoch hier der Hinweis, dass ich die Spannung der LEDs auf 2.0V schätze. Also ergibt sich aus meiner Rechnung, dass am Widerstand 3V anliegen sollten. Mit der Grundformel R=U/I erhält man den benötigten Widerstandswert von 150Ohm. Im folgenden habe ich mir aus meinem Beispiel ein Schaltbild in Eagle erstellt. Was hier allerdings nicht so schön ist,ist dass die Last von den LEDs direkt an den ICs liegt. Also ist diese Schaltung aus diesem Grunde nur experimentell und nicht für den Dauerbetrieb geeignet. 

Schaltbild_LED_Matrix_8x8_Gesamt
Gesamtes Schaltbild, ohne Netduino.

Nun ein bisschen Quellcode zum Ende, den ich jedoch von Netduino.com abgeschrieben und etwas abgeändert habe. Ich empfehle auf der Seite nachzuschauen, falls die Verbindungen mit Shiftregister und Netduino unklar sein sollten.

private static OutputPort _Data = new OutputPort(Pins.GPIO_PIN_D0, false);
private static OutputPort _Clock = new OutputPort(Pins.GPIO_PIN_D1, false);
private static OutputPort _Latch = new OutputPort(Pins.GPIO_PIN_D2, false);

/// Code von der Seite Netduino
/// Der Besipeil code und ein Schaltbild

private static void UpdateLEDs(int value)
{
    _Latch.Write(false);

    for (int i = 0; i < 8; i++)
    {
        int bit = value & 0x80;
        value = value << 1;

        if (bit == 128)
        {
            _Data.Write(true);
        }
        else
        {
            _Data.Write(false);
        }

        _Clock.Write(true);
        //Thread.Sleep(1);
        SleepWhile(5);
        _Clock.Write(false);
    }
    _Latch.Write(true);
}

/// Dient als Ersatz zu Thread.Sleep
private static void SleepWhile(int count)
{
    for (int i = 0; i < count; i++){ }
}

Members und die Methode für das ansteuern des Shiftregister.

Wird nun an der Methode ein Wert zwischen 0 und 255 übergeben, wird die entsprechende Bit Einstellung am Shiftregister gesetzt. Dieser steuert die zwei Demultiplexer, die wiederum mit der LED Matrix verbunden sind und die entsprechende LED leuchtet.

Normalerweise würde man hier einen LED Matrix Treiber verwenden, um sich die umfangreiche Verkabelung zu sparen. Jedoch möchte ich zeigen, dass es auch andere Lösungen gibt und hoffe, dass dieses Bespiel dem einen oder anderen weiterhilft.

Mein Beispiel mit “Game of Life” und einem Gleiter.

Sonntag, 3. Februar 2013

UART WiFi Server Client Module kann auch senden

Netduino_WiFi_01
Netduino Plus, Shield, WiFi Module und der Sensor

Diesmal möchte ich ein Beispiel beschreiben, in dem nicht der Netduino der Empfänger ist, sondern der Sender, ohne dass auf die Serverfunktion verzichtet werden muss. Der Quellcode vom letzten Blog-Post wird an Server und Client seitig erweitert. Am Server (Netduino) Quellcode ist dies sogar recht simpel, da man an dieser Stelle nur vier weitere Zeilen Code hinzufügen muss:

while (true)
{
      byte[] message = Encoding.UTF8.GetBytes("DateTime: " + DateTime.Now.ToString());
      _SerialPort.Write(message, 0, message.Length);
      Thread.Sleep(1000);
}

Relativ simpel fällt der Code für das Senden aus.

In der “While”-Schleife ist nun zu sehen, dass ich die aktuelle Zeit als String wiedergebe und anschließend in ein Byte Array umwandle, um es für den Schreibvorgang vorzubereiten. Die “Write”-Methode selbst erledigt den Rest und gibt den Inhalt an das WiFi Modul weiter.

Am Client jedoch ist ein wenig mehr Arbeit notwendig. Wenn die Daten ankommen, muss auch ein Event erfolgen, um die Daten zu verarbeiten und schließlich an die Anwendung auszugeben.

image
Das Programm mit einem zusätzlichen TextBlock für den Empfang.

Für den Empfang der PC Anwendung habe ich eine recht einfache Lösung verwendet, die auch leicht nachvollziehbar ist. Leider ist diese aber nicht ideal, da es eventuell zur Vollauslastung kommt, wenn hier die Schleife nicht etwas gebremst wird. Ein besseres Beispiel gibt es auf MSDN, wie hier mit Hilfe der Socket Klasse ein Event erstellt werden kann.

Nun zur Erweiterung in der Client Socket Klasse, wo eine weitere Methode später im Thread ausgeführt wird. Die Thread-Klasse selbst kommt in den Member Bereich mit dem Namen “_ThreadWaitReceive”. Der Grund hierfür ist, dass später beim Schließen der Klasse der Thread beendet werden muss. Sonst läuft der Thread weiter, obwohl die Anwendung selbst lange beendet wurde.

private Thread _ThreadWaitReceive;

private void WaitReceive(object obj)
{
     byte[] buffer = new byte[1024];

     while (_Socket != null && buffer.Length > _Socket.Receive(buffer, SocketFlags.None))
     {
          string message = Encoding.UTF8.GetString(buffer).Replace('\0', ' ').Trim();
          ReceiveEvent(message);
          buffer = new byte[1024];
     }
}

Die zusätzliche Methode für den Empfang.

Mit der Encoding wird der String eingelesen und über die Methoden Replace() und Trim()  werden die leeren Inhalte gefiltert. Mit der folgenden Zeile wird dann der Inhalt an die Event Methode übergeben.

public delegate void NetworkReceiveEventHandler(object sender, NetworkStatusEventArgs e);
public event NetworkReceiveEventHandler NetworkReceiveEvent;
public virtual void ReceiveEvent(string message)
{
    if (NetworkReceiveEvent != null & !string.IsNullOrEmpty(message))
    {
         NetworkReceiveEvent(this, new NetworkStatusEventArgs(message.Trim()));
    }
}

Die Methode, mit Handler und Event.

Mit dem Event geht es weiter an die Oberfläche, um den Inhalt des Empfang in einem TextBlock lesen zu können.

public MainWindow()
{
    InitializeComponent();

    _Client.NetworkReceiveEvent += new ClientController.NetworkReceiveEventHandler(_Client_NetworkReceiveEvent);
}

private void _Client_NetworkReceiveEvent(object sender, NetworkStatusEventArgs e)
{
    Dispatcher.BeginInvoke(new WriteReceiveHandler(WriteReceive), new object[] { e.Message });
}

private delegate void WriteReceiveHandler(string message);

private void WriteReceive(string message)
{
    textBlockDataReceive.Text = message;
}

Event zugewiesen, Handler für die Oberfläche und Methode, um in die Textbox zu schreiben.

Mit ein paar Code Zeilen Ergänzungen ist nun die PC Anwendung und der Netduino imstande, in beide Richtungen zu kommunizieren. Sicherlich gibt es hier etwas besseres, als sich nur das DateTime anzuzeigen. Zwinkerndes Smiley

Wie bereits zuvor gibt es wieder das Ganze in zwei fertigen Solutions, mit den Quelltexten und natürlich auch den Kommentaren.

Die Solutions für den Download:

Ameisen Simulation und andere Dinge

Wer lange sich schon mit C# beschäftig, hat sicherlich schon mal was von AntMe gelesen oder gehört. Diese Idee hatte ich aufgegriffen und mi...