1.0. Auflistung der angeschlossenen Devices

Das Programm "ListIows" listet alle angeschlossenen IOW 24, 40 und 56 Devices (im folgenden nur noch Devices genannt) auf. Wie wir später sehen werden kann es wichtig sein, die Seriennummer der Devices zu kennen. Dieses kleine Programm kann uns diese Information liefern.

     1 package de.wagner_ibw.iow;
     2
     3 /**
     4  * List all connected IO-Warrior devices.
     5  * @author Thomas Wagner
     6  */
     7 public class ListIows {
     8
     9     public static void main(String[] args) {
    10
    11		try {
    12  		IowFactory devs = IowFactory.getInstance();
    13			System.out.println("------- Version of iowkit library is '" + devs.getVersion() + "' --------");
    14			if (devs.getNumDevices() == 0) {
    15				System.out.println("Cannot find any plugged IO-Warrior device!");
    16				devs.exit(-1);
    17			} 
    18			System.out.println(devs.toString());
    19			devs.exit(0);
    20		}
    21		catch(UnsatisfiedLinkError e) {
    22			System.out.println(e);
    23			System.exit(-1);	
    24		}
    25		catch(NoClassDefFoundError e) {
    26			System.out.println("Cannot find java archive 'codemercs.jar'!");
    27			System.exit(-1);	
    28		}
    29	}
Zur Erklärung:

Die Anweisungen in Zeile 12 öffnet alle angeschlossenen Devices und liefert uns eine Instanz der Iow Factory. Unter Verwendung der Methode getNumDevices() der Klasse IowFactory kann ermittelt werden, wieviel Devices per USB angeschlossen sind (Zeile 14). Die Methode toString() (Zeile18) zeigt die Informationen über alle angeschlossenen Devices an (siehe auch Iow24.toString() Iow24.toString() und Iow56.toString()). Die Anweisung in Zeile 19 (exit(0)) schließt alle Devices und beendet das Programm. Im Prinzip könnte diese Anweisung weggelassen werden. Da jedoch beim öffnen der Devices für jedes Device ein Objekt der Klasse Iow24, Iow40 oder Iow56 erzeugt wird und bei dieser Erzeugung jeweils ein Thread gestartet wird, ist es erforderlich, diese mit dieser Anweisung ordentlich zu beenden. Tut man diese nicht, terminiert das Programm nicht und muß mit der Eingabe von CTRL+C im CMD- oder Konsolenfenster hart abgebrochen werden. Eine andere Art diese "harten Abbruches" ist die Anweisung in Zeile 23.

Das Programm könnte folgende Ausgabe liefern:
------- Version of iowkit library is 'IO-Warrior Kit V1.5' --------
Number of plugged IO-Warrior device(s): 3
Device1: IOW40,Handle[47775764],Id[5376],Rev[1021],Serial[00002632]
Device2: IOW24,Handle[47801132],Id[5377],Rev[1011],Serial[00000153]
Device3: IOW56,Handle[47826500],Id[5379],Rev[1001],Serial[0000011D]
Sollten zum Zeitpunkt der Programmausführung kein Device angeschlossen sein, wird folgende Meldung ausgegeben:
------- Version of iowkit library is 'IO-Warrior Kit V1.5' --------
Cannot find any plugged IO-Warrior device!

2.0. Ansteuerung eines LCD Displays

Das Programm "LcdTest" zeigt beispielhaft die Ansteuerung des LCD Displays. Die Klasse LCD enthält mehr als die hier verwendeten Methoden. Diese sind jedoch nicht so wichtig und werden später erklärt.

     1 package de.wagner_ibw.iow.test;
     2
     3 import de.wagner_ibw.iow.Iow;
     4 import de.wagner_ibw.iow.Iow24;
     5 import de.wagner_ibw.iow.Iow40;
     6 import de.wagner_ibw.iow.LCD;
     7 import de.wagner_ibw.lcd.LCD2x40;
     8 import de.wagner_ibw.lcd.LCD4x40;
     9
    10 /**
    11  * @author Thomas Wagner
    12  */
    13 public class LcdTest {
    14
    15     final static boolean CHECK_24 = false;
    16
    17     public static void main(String[] args) {
    18
    19         try {
    20             LCD lcd;
    21             IowFactory devs = IowFactory.getInstance();
    22
    23             if(CHECK_24) {
    24                 Iow24 dev24 = devs.getIow24Device();
    25                 lcd   = new LCD2x40();
    26                 dev24.addSpecialModeFunctionImpl((SpecialModeFunction)lcd);
    27             }
    28             else {
    29                 Iow40 dev40 = devs.getIow40Device();
    30                 lcd   = new LCD4x40(0,0)
    31                 dev24.addSpecialModeFunctionImpl((SpecialModeFunction)lcd);
    32             }
    33
    34             //Turn on display, cursor off and blinking off
    35             lcd.setDisplayControl(true, false, false);
    36
    37             //show greetings
    38             lcd.writeLine(1,2,false, "Test LCD class");
    39             Thread.sleep(2000);
    40
    41             //check LCD
    42             lcd.check();
    43             Thread.sleep(2000);
    44
    45             //clear the display
    46             lcd.clearLCD();
    47
    48             //build 8 special characters (several bars)
    49
    50                       //upper                              lower
    51             int[] c0 = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f};
    52             int[] c1 = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x00};
    53             int[] c2 = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x00,0x00};
    54             int[] c3 = {0x1f,0x1f,0x1f,0x1f,0x1f,0x00,0x00,0x00};
    55             int[] c4 = {0x1f,0x1f,0x1f,0x1f,0x00,0x00,0x00,0x00};
    56             int[] c5 = {0x1f,0x1f,0x1f,0x00,0x00,0x00,0x00,0x00};
    57             int[] c6 = {0x1f,0x1f,0x00,0x00,0x00,0x00,0x00,0x00};
    58             int[] c7 = {0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    59
    60             //load them up
    61             lcd.setSpecialChar(0,c0);
    62             lcd.setSpecialChar(1,c1);
    63             lcd.setSpecialChar(2,c2);
    64             lcd.setSpecialChar(3,c3);
    65             lcd.setSpecialChar(4,c4);
    66             lcd.setSpecialChar(5,c5);
    67             lcd.setSpecialChar(6,c6);
    68             lcd.setSpecialChar(7,c7);
    69
    70             //show them in line 1
    71             lcd.writeLine(1,true,"\0\1\2\3\4\5\6\7");
    72             Thread.sleep(2000);
    73
    74             //build 6 special characters for pictures (cars)
    75             int[] a0 = {0x00,0x00,0x01,0x0f,0x1f,0x1f,0x0f,0x06};
    76             int[] a1 = {0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,0x00,0x00};
    77             int[] a2 = {0x1c,0x1c,0x1e,0x1e,0x1f,0x1f,0x1e,0x0c};
    78             int[] a3 = {0x07,0x07,0x0f,0x0f,0x1f,0x1f,0x0f,0x06};
    79             int[] a4 = {0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x00,0x00};
    80             int[] a5 = {0x00,0x00,0x10,0x1e,0x1f,0x1f,0x1e,0x0c};
    81
    82             //load them up
    83             lcd.setSpecialChar(0,a0);
    84             lcd.setSpecialChar(1,a1);
    85             lcd.setSpecialChar(2,a2);
    86             lcd.setSpecialChar(3,a3);
    87             lcd.setSpecialChar(4,a4);
    88             lcd.setSpecialChar(5,a5);
    89
    90             //show them in line 1
    91             lcd.writeLine(1,true,"\0\1\2  \3\4\5");
    92             Thread.sleep(2000);
    93
    94             //move the car from left to right
    95             lcd.moveSprite(1,new String[]{"\3\4\5"},200);
    96             Thread.sleep(2000);
    97
    98             //build 4 special characters for an animated sprite
    99             int[] d0 = {0x00,0x04,0x04,0x04,0x04,0x04,0x00,0x00};
   100             int[] d1 = {0x00,0x01,0x02,0x04,0x08,0x10,0x00,0x00};
   101             int[] d2 = {0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x00};
   102             int[] d3 = {0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00};
   103
   104             //load them up
   105             lcd.setSpecialChar(0,d0);
   106             lcd.setSpecialChar(1,d1);
   107             lcd.setSpecialChar(2,d2);
   108             lcd.setSpecialChar(3,d3);
   109
   110             //moves the sprite from left to right
   111             lcd.moveSprite(1,new String[]{"\0","\1","\2","\3"},200);
   112
   113             Thread.sleep(2000);
   114             //clear the display
   115             lcd.clearLCD();
   116             //lcd.check();
   117             lcd.writeLine(lcd.getRows(),5,true, "The End");
   117a            devs.exit(0);
   118         }
   119         catch(Exception e) {
   120             e.printStackTrace();
   121             devs.exit(1);
   122         }
   123     }
   124 }
Zur Erklärung:

Durch die Constante CHECK_24 wird gesteuert, ob ein IOW 24 oder 40 Device zum Einsatz kommen soll. Mit den Anweisungen in Zeile 26 und 30 besorgt man sich eine Referenz des jeweilige Devices. In Zeile 25 ( b.z.w. 30) wird dann einen neue Instanz der Klasse LCD erzeugt. Die Lcd-Klassen beinhalten lediglich Informationen zu den Anzahl der Zeilen und Spalten und zu den Zeilenanfangsadressen. Würde man die Werte als einzelne Parameter dem LCD-Konstruktor übergeben, wäre das sicherlich einen lange Liste. Und würde eine neuer Parameter dazukommen (wer weiß), müßte man jedesmal dessen Signatur ändern b.z.w. einen weiteren Konstruktor hinzufügen. Zur Zeit gibt es vier LCD-Beschreibungsklassen, aus deren Benennung geht hervor, für welche Displaytype sie zu verwenden sind:

Was passiert in der Klasse LCD? Im IOW Device wird der "LCD Special mode function" eingeschaltet und das Lcd Display initialisiert.

In den Anweisung in Zeile 35 wird dann das Display ein, der Cursor aus und auch das Blinken der aktuellen Position ausgeschaltet. Das bis jetzt alle meine Programme diese Zeile enthalten, wird wahrscheinlich in der nächsten Version der Bibliothek dies als Voreinstellung mit bei der Initialisierung des Displays erledigt (Meinungen dazu sind erwünscht).

In der Zeile 42 wird die Methode check() der Klasse LCD aufgerufen. Diese Methode kann zur Kontrolle der Lcd-Beschreibungsklasse verwendet werden. Sie gibt auf jeder Zeile eine komplette Zeile mit der Zahl aus, welche der Zeilennummer entspricht. Zum Beispiel:

LCD4x20Generic: 11111111111111111111
                22222222222222222222
                33333333333333333333
		44444444444444444444

LCD2x40Generic: 1111111111111111111111111111111111111111
                2222222222222222222222222222222222222222	
Würde man ein 2x40 Display mit der 4x20 Beschreibungsklasse verwenden, ergibt sich folgende Ausgabe auf dem Display:
1111111111111111111133333333333333333333
2222222222222222222244444444444444444444

Doch nun wollen wir endlich Text ausgeben. Ich bin der Meinung, das man am häufigsten den Text nur zeilenweise ausgeben wird (Die Aussichten, über die Zeilengrenzen hinweg eine ordentliche Ausgabe zu erhalten, ist eher gering). So ist die Methode writeLine() entstanden. Diese gibt es mir zwei Signaturen:

lcd.writeLine(zeile,spalte,löschen,text);  zum Beispiel  lcd.writeLine(1,2,false, "1. Signature");
lcd.writeLine(zeile,löschen,text);         zum Beispiel  lcd.writeLine(1,true, "2. Signature");
Fehlt der Parameter 'spalte', wird automatisch die erste Spalte benutzt (Die Zählung der Zeilen und Spalten beginnt immer mit der 1!). Der Parameter 'löschen' bestimmt, ob vor der Textausgabe die Textzeile ab der Position 'spalte' gelöscht wird. Da nur so viele Zeichen ausgegeben werden, wie in der Zeichenkette 'text' enthalten sind wird so vermieden, dass Reste einen alten Ausgabe sichtbar bleiben, wenn einen später ausgegeben Zeichenkette weniger Zeichen enthält. Ist der Text in 'text' länger als einen Zeile des Displays (b.z.w. der Rest der Zeile, wenn 'spalte' > 1 ist), wird er abgeschnitten. So werden unerwünschte "Überschreibeffekte" im Display vermieden.

LCD Displays bieten die Möglichkeit, acht benutzerdefinierte Zeiche zu definieren. Diese haben dann den Zeichencode 0 bis 7 (bei der Ausgabe als String müssen diese dann "gequoted" werden: "\0" ... "\7"). In den Zeilen 51 bis 58 werden 8 solche Zeiche definiert (ein immer kürzer werdender Klotz). Mit den Anweisungen in Zeile 61 bis 68 werden diese dan in das Display geschrieben. Erster Parameter der Methode lcd.setSpecialChar() ist der gewünschte Zeichencode des Sonderzeichens und er zweite das zuvor definierte Array der Pixeldaten.

Mehr aus Spielerei ist die Methode zur Animation von Sonderzeichen (es können natürlich auch "normale" Zeichen verwendet werden) entstanden. In Zeile 74 mis 91 werden sechs Sonderzeichen definiert und ausgegeben, von denen jeweils drei ein Auto (jeweils vorwärts und rückwärts) darstellen soll. Mit der Anweisung in Zeile 95 "fährt" dann das Auto von links nach rechts. Die Methode moveSprite() benötigt als ersten Parameter die gewünschte Displayzeile. Der nächtse Parameter ist ein Stringarray, welches den String von Sonderzeichen enthält, welcher dann z.B. das Auto darstellt. Aber es kommt noch besser, Das ein String-Array mehrere Strings aufnehmen kann, könne wir hier mehrer Sets von Sonderzeien angebe, welche dann nacheinander "abgespielt" werden. In Zeile 99 bis 111 wird ein Strich definiert, der sich drehend von links nach rechts bewegt.

Preisfrage: welche Ausgabe erzeugt diese Anweisung an Stelle der Anweisung in Zeile 111?
lcd.moveSprite(1,new String[]{"\0\1","\1\2","\2\3","\3\0"},200);
Der dritte Parameter ist die Zeit im ms, die die Bewegungsgeschwindigkeit beeinflußt. Werte unter 200 (ms) sind weniger geeignet, da das LCD Display im Zeichenaufbau so träge ist, das die Zeichen nicht mehr richtig schwarz dargestellt werden.

Zusammenfassung

Das war (oder ist) der erste Teil des Tutorials. Ich hoffe, es ist halbwegs verständlich. Meinungsäußerungen und Vorschläge willkommen. Vielleicht findet sich auch jemand (der sich damit auskennet), der das Tutorial in eine ansprechendere Form bringen kann. Mehr zu den Klassen auch in der JavaDoc. Das das ganze jedoch noch in der Entwicklung ist am besten nur die Klassen und Methoden benutzten, die im Tutorial erwähnt werden. Die sind einigermaßen getestet.

Im nächsten Teil werden wir Eingänge abfragen und Ausgänge schalten.

zurück zum Inhalt zurück zur Startseite
© 2005-2007 by Thomas Wagner, Mail: thomas at wagner-ibw dot de (aktuallisiert: 10.04.2007)