LEDs per Parallelport steuern

Anleitungen für "hausgemachte" LED Projekte

Moderator: T.Hoffmann

Antworten
Benutzeravatar
Morbus
Ultra-User
Ultra-User
Beiträge: 936
Registriert: Fr, 26.10.07, 21:25
Wohnort: Vaihingen
Kontaktdaten:

Sa, 26.05.12, 18:30

Hallo,

nach langer Abwesenheit melde ich mich mal wieder zu Wort. Ich hatte heute langeweile und mal versucht, ein paar LEDs per Parallelport (aka Druckerport) anzusteuern.

Zuerst einmal eine Animation die Ablaufen kann, wenn das ganze fertig ist:

Bild

Hier meine Vorgehensweise:


Grundlegendes erfährt man wie immer bei Wikipedia, hier einmal die Pinbelegung des Parallelports:

http://de.wikipedia.org/wiki/Parallelpo ... nittstelle

Um 8 LEDs anzusteuern benötigt man lediglich die Pins 2-9, also Data Bit 0 bis Data Bit 7 und natürlich die Masse.



Nun zum Schaltplan, dieser hält sich recht simpel, die Pins der Masse habe ich zusammengelötet. Für die Widerstände habe ich welche mit ~500 Ohm verwendet. Der Parallelport kann nicht sehr hoch belastet werden. Daher am besten mindestens 500 Ohm, wenn nicht sogar 1k Ohm Widerstände benutzen:

Bild

In echt sieht es folgender Maßen aus:

Bild

Nach dem Aufbau ist es wichtig, das ganze zu überprüfen. Geht etwas schief und der Parallelport ist direkt auf dem Mainboard, so kann das ganze Mainboard zerstört werden. Daher am besten PCI -Karten mit Parallelport benutzen. So weit ich weiß funktioniert das ganze mit USB <-> Parallelport-Modulen nicht.


So nun kommt es zum Interessanten Teil: Wie steuere ich die LEDs an?

Dafür gibt es eine sogenannte inpout32.dll, diese gibt es auch für 64-bit Systeme. Herunterladen kann man sie hier: http://logix4u.net/parallel-port

Ich habe die LEDs mittels eines C# Codes angesteuert. Zuerst einmal eine Klasse um später ein Objekt für den jeweiligen Parallelport zu erstellen (diesen Code habe ich kopiert).

Code: Alles auswählen

namespace ParallelPort
{
    public class PortAccess
    {
        [DllImport("inpout32.dll")]
        private static extern UInt32 IsInpOutDriverOpen();

        [DllImport("inpout32.dll")]
        private static extern void Out32(short PortAddress, short Data);

        [DllImport("inpout32.dll")]
        private static extern char Inp32(short PortAddress);

        [DllImport("inpout32.dll")]
        private static extern void DlPortWritePortUshort(short PortAddress, ushort Data);

        [DllImport("inpout32.dll")]
        private static extern ushort DlPortReadPortUshort(short PortAddress);

        [DllImport("inpout32.dll")]
        private static extern void DlPortWritePortUlong(int PortAddress, uint Data);

        [DllImport("inpout32.dll")]
        private static extern uint DlPortReadPortUlong(int PortAddress);

        [DllImport("inpoutx64.dll")]
        private static extern bool GetPhysLong(ref int PortAddress, ref uint Data);

        [DllImport("inpoutx64.dll")]
        private static extern bool SetPhysLong(ref int PortAddress, ref uint Data);

        //inpoutx64.dll

        [DllImport("inpoutx64.dll", EntryPoint = "IsInpOutDriverOpen")]
        private static extern UInt32 IsInpOutDriverOpen_x64();

        [DllImport("inpoutx64.dll", EntryPoint = "Out32")]
        private static extern void Out32_x64(short PortAddress, short Data);

        [DllImport("inpoutx64.dll", EntryPoint = "Inp32")]
        private static extern char Inp32_x64(short PortAddress);

        [DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUshort")]
        private static extern void DlPortWritePortUshort_x64(short PortAddress, ushort Data);

        [DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUshort")]
        private static extern ushort DlPortReadPortUshort_x64(short PortAddress);

        [DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUlong")]
        private static extern void DlPortWritePortUlong_x64(int PortAddress, uint Data);

        [DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUlong")]
        private static extern uint DlPortReadPortUlong_x64(int PortAddress);

        [DllImport("inpoutx64.dll", EntryPoint = "GetPhysLong")]
        private static extern bool GetPhysLong_x64(ref int PortAddress, ref uint Data);

        [DllImport("inpoutx64.dll", EntryPoint = "SetPhysLong")]
        private static extern bool SetPhysLong_x64(ref int PortAddress, ref uint Data);

        private bool _X64;
        private short _PortAddress;

        public PortAccess(short PortAddress)
        {
            _X64 = false;
            _PortAddress = PortAddress;

            try
            {
                uint nResult = 0;
                try
                {
                    nResult = IsInpOutDriverOpen();
                }
                catch (BadImageFormatException)
                {
                    nResult = IsInpOutDriverOpen_x64();
                    if (nResult != 0)
                        _X64 = true;

                }

                if (nResult == 0)
                {
                    throw new ArgumentException("Unable to open InpOut32 driver");
                }
            }
            catch (DllNotFoundException)
            {
                throw new ArgumentException("Unable to find InpOut32.dll");
            }
        }

        public void Write(short Data)
        {
            if (_X64)
            {
                Out32_x64(_PortAddress, Data);
            }
            else
            {
                Out32(_PortAddress, Data);
            }
        }
    }
}
Nun muss ich ein Objekt der Klasse PortAccess erstellen. Die Standardportadresse für den Parallelport 1 ist übrigens 888. Das BooleanArray leds gibt an, ob die jeweiligen LEDs an oder aus sind (dazu gleich mehr). Mit .Write(0) schalte ich alle LEDs aus (dazu ebenfalls gleich mehr).

Code: Alles auswählen

        PortAccess pa;
        Boolean[] leds;

        public Test()
        {
            pa = new PortAccess(888);
            leds = new Boolean[8];
            pa.Write(0);
        }
Nun kann ich, nachdem ich mir ein Objekt der Klasse PortAccess erstellt habe, mit der Methode .Write(short Data) bestimmte Pins auf high schalten. Dazu muss ich eine 8-stellige Binärzahl der Methode übergeben, jede 1 dieser Zahl steht dabei für High (=5V) beim jeweiligen Pin, jede 0 steht für Low (=0V). Soll eine LED leuchten, so muss das jeweilige Bit der Binärzahl auf 1 gestellt werden.

Beispiel:
  • Alle LEDs aus -> 00000000 (binär) = 0 (dezimal) -> .Write(0)
  • Alle LEDs sollen leuchten -> 11111111 (binär) = 255 (dezimal) -> .Write(255)
  • Die erste und die vierte LED sollen leuchten -> 00001001 (binär) = 9 (dezimal), also .Write(9)
Da das umrechnen recht umständlich ist, bin ich folgendermaßen vorgegangen. Zuerst habe ich mir ein Boolean-Array der Länge 8 angelegt (standardmäßig sind alle Einträge false). Um die jeweilige LED anzuschalten muss ich lediglich die jeweilige Stelle des Arrays auf true setzen und eine Update-Funktion ausführen. Diese habe ich wie folgt erstellt:

Code: Alles auswählen

        private void updateLEDs()
        {
            short ledShort = 0;
            for (int i = 0; i < leds.Length; i++)
            {
                if (leds[i])
                {
                    ledShort += short.Parse(Math.Pow(2, i) + "");
                }
            }
            pa.Write(ledShort);
        }
Falls noch Fragen sind, dann gerne fragen. Ggf. lade ich auch noch ein Video hoch.

Grüße

Morbus
DerHelm
Mini-User
Beiträge: 1
Registriert: Mo, 29.07.13, 09:08

Mo, 29.07.13, 09:16

Als erstes einmal Danke für dieses HowTo. Es ist wirklich verständlich geschrieben aber ich muss trotzdem mal schnell noch ein paar Fragen loswerden.
1. Unter welchem Betriebssystem benutzt du dieses Tool?
2. Ich bekomme immer folgende Exception "Unable to find an entry point named 'IsInpOutDriverOpen' in DLL 'inpout32.dll'"
Irgendwie habe ich keine Ahnung wie ich das beheben soll. Ich arbeite aktuell unter Windows 8.1 Consumer Preview 64-Bit.
Diesen Fehler bekam ich aber auch unter Win8 professional 64-Bit. Also hab ich das ganze jetzt mit der 32-bit inpout32.dll für 32-bit Prozessoren kompiliert und bekomme diesen Fehler immer noch. Hast du vielleicht eine Idee woran das liegen könnte?

Danke!
Antworten