zur navigation

6. Oktober 2012 Veröffentlicht von Heinrich in : Technik , einen kommentar schreiben

Lego Lagersystem

Lego Lagersystem Elektronik

Lego Lagersystem Elektronik

Dies ist ein Lagerroboter, der über USB am Computer angeschlossen ist. Er holt Dinge auf Befehl des Computers herbei. Umgesetzt mit Lego, einer Conrad-Relais-Karte und einem H-Tronic Spannungsmesser . Programmiert in JAVA mit Eclipse.


24. September 2012 Veröffentlicht von Heinrich in : Technik , einen kommentar schreiben

Atmel AT90USBKey 2 mit LCD-Display

Atmel AT90 mit Gleichmann LCD

Atmel AT90 USB Key 2 mit LCD-Display

Im folgenden findet ihr eine kurze Dokumentation darüber, wie man ein AT90-Chip mit einem LCD-Display kombinieren und programmieren kann.

Ziel ist es, mit dem AT90 einen eigenen Text auf dem LCD-Display anzuzeigen.

Die Komponenten

Um die Komponenten (Gleichmann GE-C1602B-TMI-JT/R und Atmel AT90USBKey) zweckmäßig miteinander verbinden zu können, ist eine Steckplatine hilfreich. So erspart man sich das Löten.

AT90 Ports

AT90 Ports

Der Aufbau

Leider sind die Ports am AT90 von den Dimensionen her von Atmel etwas unglücklich gewählt. Ich habe keine passenden Stiftleisten gefunden, die man als Aufsatz benutzen könnte.

Stattdessen habe ich einfach ein Kupferkabel benutzt, welches dem Durchmesser der Ports entspricht. Anschließend habe ich die Kabel mit einer Heißklebepistole miteinander verschmolzen. So ist eine halbwegs feste und kostengünstige Verbindung gegeben, die sich für Testzwecke sehr gut eignet.

LCD-Display Ports

LCD-Display Ports

Das LCD-Display habe ich direkt auf die Steckplatine gesetzt, da sich das Rastermaß der Steckplatine mit den Abständen der LCD-Ports deckt. Kleiner Tipp: Die Drahtstücke je ein bischen verbiegen und danach einzeln einsetzen. So drücken sich die Drähte gut an die Portkontakte des LCDs.

 

 

Die Programmierung

Wenn ihr den Quellcode einfach kopieren wollt, dann müsst ihr folgende Portverbindungen einhalten (je linke Spalte mit rechter Spalte verbinden):

AT90 LCD
PC0 Vss
PC1 Vdd
PC2 V0
PC3 RS
PC4 R/W
PC5 E
PC6 A
PC7 K
PD1 DB4
PD2 DB5
PD3 DB6
PD4 DB7

Top-Ansicht von AT90-USBKey2

 

 

 

 

Beispiel: PC0 = Port C Pin 0

Die Bezeichnungen für die LCD-Ports finden sich im Handbuch.

 

 

 

 

 

 

 

 

 

Übersicht der Funktionen (C-Quellcode kann unten heruntergeladen werden)

Um etwas auf den LCD zu schreiben, braucht man lediglich folgende Funktion, die sehr einfach zu benutzen ist:

int main() {	
	watchdog_off();
 
	//LCD-Init
	init_board_for_lcd();	
	lcd_init();
 
	lcd_show_strpos(0x00, "Joystickeingabe:");
        //0x00 bezeichnet hierbei die Stelle, an der der Text
        //im LCD-Display eingefügt werden soll.
        //0x00 = 1. Zeile 1. Stelle
        //0x05 = 1. Zeile 6. Stelle
        //0x0A = 1. Zeile 11. Stelle
        //0x45 = 2. Zeile 6. Stelle
        //0x4A = 2. Zeile 11. Stelle
}

Wenn jemand andere Ports verwenden möchte, muss dementsprechend die config.h anpassen.

Fall jemand den Quellcode anpassen/erweitern möchte, hier eine kurze Funktionsübersicht:

Funktion Wirkung
lcd_show_strpos(uint8_t pos, char *data) Schreibt einen String an die Position pos
lcd_show_string(char *data) Schreibt einen String hinter die zuletzt beschriebene Position
lcd_show_char(uint8_t data) Schreibt einen Buchstaben hinter die zuletzt beschriebene Position
lcd_cmd_setcurser(uint8_t data) Ändert die Curserposition (wo soll das nächste Zeichen geschrieben werden)
lcd_cmd_cleardisplay() Löscht den Displaytext
lcd_cmd(uint8_t data) Sendet ein 8bit-Command an den LCD-Chip
lcd_sende_bits(uint8_t data) Sendet 4bit an LCD
lcd_flanke() Es werden die bits gelesen, die durch lcd_sende_bits() angelegt wurden
lcd_init() Initialisierung des LCDs (Parameter in der config.h)
init_board_for_lcd() Initialisierung des AT90 (Parameter in der config.h)

» Download: AVR-Projekt: AT90USBKey 2 mit Gleichmann LCD-Display

 

Programm-Code auf das AT90 Board aufspielen

– Stelle sicher, dass das AT90-Board resettet ist. Sicherheitshalber nochmal einen Reset durchführen:
Zuerst HWB-Knopf (auf der Platine) drücken und gedrückt halten, dann RST drücken, während man noch HWB gedrückt hält. Anschließend RST loslassen und danach HWB loslassen.

– Dann muss das Projekt in AVR compiliert werden (z.B. über F7). Anschließend öffnet man FLIP (hier V3.4.5) und wählt:

– „Select a Communication Medium (zweites Icon von links)“ -> „USB“ (Kann unter Win7 Probleme machen, bei mir hat es auf WinXP aber funktioniert)

– „Load HEX File (drittes Icon von Rechts)“ -> die zuvor kompilierte HEX-Datei suchen (hier: $projektordner/default/test.hex

– Unter „Operations Flow“ müssen alle Häkchen angewählt werden

– Drücke Run und dann Start Application (+Reset)

Jetzt müsste der gewünschte Text auf dem LCD-Display zu sehen sein.

 


9. April 2012 Veröffentlicht von Heinrich in : Technik , einen kommentar schreiben

.vmf-Tools Beta

Hier ein Projekt von mir aus dem Jahr 2009:

An wen richtet sich vmf.Tools?
An alle, die mit dem Valve-Hammer-Editor der Source-Engine arbeiten.

 

 

 

Was bringt mir dabei vmf.Tools?

Die aktuelle Beta-Version von vmf.Tools bietet dir einen Entity-Konstrukt-Duplikator direkt im Browser.

Bitte was?

Stell dir vor, du hast ein Entity-Konstrukt erstellt – zum Beispiel eine schwingende Lampe, die an einem Seil hängt, ein dynamisch Licht hat und zerstörbar ist. Um ein derartiges Konstrukt zu erstellen, benötigt es viele Arbeitsschritte. Am Ende hat man viele viele Entities, mit Namen, Parent, Outputs usw.
Will man diese Lampe nun ein zweites mal im Level haben, so reicht es nicht aus, das Konstrukt per Copy&Paste zu kopieren, sondern man muss auch alle Parameter per Hand anpassen, damit das zweite Konstrukt unabhängig vom ersten funktionieren kann.
Hier hilft vmf.Tools aus. Mit vmf.Tools wird einem die lästige Kopierarbeit abgenommen. Es muss nur einmal ein Template-Konstrukt erstellt werden, welches dann dupliziert werden kann. Die Parameter Name, Parent, Outputs usw. werden automatisch angepasst, so dass sich keiner der Duplikate nachher mit einem anderen überschneiden wird.
So kann man die schwingende Lampe 10 mal (und auch öfter) duplizieren und an verschiedenen Orten der Map einfügen.

Was muss ich dabei beachten?

Das Entity-Konstrukt, dass du duplizieren möchtest, muss in einer eigenen .vmf-Datei abgespeichert werden. Nur das Konstrukt, nichts anderes. Anschließend lädst du die Datei hier hoch und konfigurierst das Programm nach deinen Ansprüchen.
Dabei ist es egal, ob das Konstrukt aus World-Brushes, Displacements, Brushentities und/oder Pointentities besteht.
Aufgrund der Betaversion MUSS in dieser Datei mindestens ein World-Brush UND ein Entity vorhanden sein, ansonsten erzeugt das Programm einen falschen Code.

Ist vmf.Tools auf bestimmte Source-Mods begrenzt?

Eigentlich nein. vmf.Tools wurde erfolgeich mit Half-Life 2 Maps getestet. Mit welchen verschiedenen Abwandlungen der Source-Engine das Programm noch zurecht kommt, ist nicht getestet. Theoretisch muss vmf.Tools mit allen Mods zurechtkommen (auch Custom-Entities sind kein Problem), da der Syntax der .vmf-Dateien von Valve „genormt“ ist.

Weblinks:


19. Dezember 2011 Veröffentlicht von Heinrich in : Technik , einen kommentar schreiben

Widerstandsmessung Conradrelaiskarte

Conrad Relaiskarte

Wie groß ist der Widerstand der Conrad-Relaiskarte? (Bildquelle: Google)

Siehe auch: Conrad-Relaiskarte mit JAVA steuern
.
Da das Handbuch mir nichts über den Widerstand der Relaiskarte verraten hat, musste ich eine eigene Messung vornehmen, um eben jenes herauszufinden. In der Graphik seht ihr die Messreihe als Graphen.
.
Der Widerstand ist abhängig von der Anzahl n der eingeschalteten Relais. Bei n=0 Relais ist der Widerstand am höchsten. Werden Relais eingeschaltet, sinkt der Gesamt-Widerstand der Relaiskarte.

 



19. September 2011 Veröffentlicht von Heinrich in : Technik , einen kommentar schreiben

H-TRONIC USB Datenerfassungssystem per JAVA (HB627)

H-TRONIC USB 12-Bit-Datenerfassungssystem Baustein (Quelle: Google)

H-TRONIC USB 12-Bit-Datenerfassungssystem Baustein (Quelle: Google)

H-TRONIC USB 12-Bit-Datenerfassungssystem (HB627) mit JAVA steuern

Update 18.03.2012: Absturzursache behoben (falls nicht alle Bytes empfangen wurden und die ArrayList nicht die erwartete Länge bekam). Der Code hier im Artikel wurde dementsprechend auch aktualisiert.

Mit dieser Platine kann man 8 verschiedene analoge Signale im Spannungsbereich von 0 bis 4095 mV messen. Dies tut die Karte im Grunde auch sehr zuverlässig, jedoch kann man sich, gerade als JAVA-Nutzer, an einigen Ecken der Lieferung ärgern. Dazu später mehr.

Das Prinzip

Wir senden eine Byte-Folge an die Karte (Befehl) und erhalten die aktuellen Spannungswerte als Antwort zurück. Laut Handbuch geht das 300x in der Sekunde, bei mir läuft die Karte allerdings erst bei höchstens 75 Abfragen in der Sekunde stabil, was aber (im Grunde)* immer noch sehr schnell ist.

Pro-Argumente

  • Messungen (im Grunde)* sehr genau
  • Arbeitet (im Grunde)* sehr schnell
  • Gute Verarbeitung

Contra-Argumente

  • (*) Nur unter ideal-Voraussetzungen: Wenn an einem Kontakt kein geschlossener Stromkreis mit einer gewissen Spannung anliegt, so bekommt man für diesen Kontakt einen „Zufallswert“ als Spannung geliefert. So muss man durch eine Messreihe unerwünschte Messergebnisse erfassen und rausfiltern. Das erhöht den Arbeitsaufwand für einen brauchbare Messreihe. Dieser Fehler der Karte ist besonders ärgerlich, wenn man (wie ich) eben messen will, ob ein Stromkreis geschlossen oder offen ist.
  • Kein Stecker mitgeliefert
  • Karte kann nicht Kaskadiert werden (mehrere in „Reihe“ schalten und über einen USB-Port steuern)
  • Handbuch / Dokumentation sehr mager
Mitgeliefertes Beispielprogramm: Liegt keine Spannung an, so erhalten wir willkürliche Spannungswerte. An Kontakt 8 liegt eine konstante Spannung an.

Mitgeliefertes Beispielprogramm: Liegt keine Spannung an, so erhalten wir willkürliche Spannungswerte. An Kontakt 8 liegt eine konstante Spannung an.

.

Anwendung der JAVA-Klasse

Die im folgenden beschriebene JAVA-Klasse braucht KEINE „Idealvoraussetzungen“ (wie unter Contra (*) beschrieben). Der Preis dafür ist lediglich, dass die Abfrage etwas länger dauert. Das Prinzip: Es werden mehrere Messungen (cfg: „newLaps“) unmittelbar hintereinander ausgeführt und verglichen: Sind stark schwankende Werte gemessen worden, so geht die Klasse davon aus, dass dort keine Spannung anliegt (es werden willkürliche Messwerte gesendet, ein Bug der Mess-Karte!). Bewegen sich die Schwankungen allerdings innerhalb eines bestimmten Intervalls (cfg: „newTolerance“), so wird diese Spannung als richtig bzw. zuverlässig interpretiert. Ferner kann man einstellen, welche Spannung mindestens anliegen muss, um als richtig gewertet zu werden. Die im unteren Beispiel verwendete Konfigurationseinstellung hat bei mir mit (wahrscheinlich)** 100%iger Genauigkeit die richtigen Messwerte geliefert.

(** Nach tausenden Messdurchläufen keine Abweichung der Messwerte von den realen Umständen)

Zunächst müssen wir bei Nutzung von Windows 7 die RXTXcomm.jar eingebunden haben. Wie das geht, könnt ihr im Artikel zur Relaiskarte nachlesen. Danach können wir die Klassen verwenden. Hier einen kleinen Crashkurs zu meiner Klasse:

public class Main {	
	public static void main (String args[]) {
 
		//VERBINDUNG AUFBAUEN
		HB627 hb627 = new HB627("COM19");
 
                //KLASSE KONFIGURIEREN
		//hb627.setCfg(newSleepTime, newLaps, newTolerance, newMinimumMV);
		//STANDARDEINSTELLUNGEN:
		//newLaps = 5; //Wieviele Messrunden soll eine Messung (ein Race) surchlaufen, bevor entschieden wird, ob der Port einen zuverlässigen Wert übermittelt hat? (je mehr, desto zuverlässiger); Wert = 1 setzen, wenn keine Messreihe vorgenommen werden soll, sondern im "klassischen" Sinne gemessen werden soll
		//newTolerance = 25; //in mV. Wie hoch darf die Durchschnitts-Differenz zwischen den Messrunden-Werten eines einzelnen Mess-Ports höchstens sein, um noch als zuverlässiges Ergebnis eingestuft zu werden.
		//newSleepTime = 16; //Wie lange soll nach jedem Kommando (nach jeder Runde [lap]) gewartet werden?
		//newMinimumMV = 1500; //Welchen Wert muss die Messung mindestens haben, um ÜBERHAUPT berücksichtigt zu werden?
 
                //ALLE PORTS GLEICHZEITIG LESEN / MESSEN
		//Wo liegt eine konstante Spannung an?
		boolean[] resultB = hb627.readAll();
 
	        //Wie hoch sind die anliegenden Spannungen? (vorher muss "readAll" oder "read" aufgerufen worden sein)
		int[] voltages = hb627.getVoltage();
 
                //Ergebnisse ausgeben	
			for (int j = 0; j<resultB.length;j++) {
				System.out.println(resultB[j]);
				System.out.println(voltages[j]);
			}
 
                 //PORTS EINZELN LESEN / MESSEN
                        boolean result = hb627.read(8);
			int[] voltages = hb627.getVoltage();
			System.out.println(result);
			System.out.println(voltages[0]);
 
                }
}

Der Quellcode der JAVA-Klasse

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.TooManyListenersException;
 
 
public class HB627 {
	private CommPortIdentifier commPortIdentifier; 
	private SerialPort serialPort;
	private OutputStream outputStream;
	private BufferedOutputStream out;
	private InputStream inputStream;
 
	private int cfg_laps;
	private int cfg_tolerance;
	private int sleepTime;
	private int mVschwelle;
 
	private int commando; //letztes durchgeführtes commando
	private int lap; //aktuelle runde im rennen (race) (jedes race liefert ein Messergebnis in form von true oder false zurück)
 
	private ArrayList<Integer> finalResults;
	private ArrayList<byte[]> respondResults;
	private boolean[] booleanResults;
 
 
	//KONSTRUKTOR: VERBINDUNG MIT EMPFAENGERKARTE HERSTELLEN (z.B. comName = "COM17" )
	HB627(String comName) {
 
		booleanResults = new boolean[8];
 
		cfg_laps = 4; //Wieviele Messrunden soll eine Messung (ein Race) surchlaufen, bevor entschieden wird, ob der Port einen zuverlässigen Wert übermittelt hat? (je mehr, desto zuverlässiger)
		cfg_tolerance = 20; //in mV. Wie hoch darf die Durchschnitts-Differenz zwischen den Messrunden-Werten eines einzelnen Mess-Ports höchstens sein, um noch als zuverlässiges Ergebnis eingestuft zu werden.
		sleepTime = 15; //Wie lange soll nach jedem Kommando (nach jeder Runde [lap]) gewartet werden?
		mVschwelle = 1500; //Welchen Wert muss die Messung mindestens haben, um ÜBERHAUPT berücksichtigt zu werden?
 
		finalResults = new ArrayList<Integer>();
		respondResults = new ArrayList<byte[]>();
 
 
		//COM-PORT-OPEN
		if (!Main.simulation) {
 
 
			try {
				commPortIdentifier = CommPortIdentifier.getPortIdentifier(comName);
				serialPort = (SerialPort) commPortIdentifier.open(comName,2000);
				serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
 
				outputStream = serialPort.getOutputStream();
				out = new BufferedOutputStream(outputStream);
 
				System.out.println("Connected to " + comName + "");
 
 
			 }
			 catch(Exception exc)
			 {
				 System.out.println("Fehler Outputstream :"+exc);			
			 }
 
			 //INPUT-STREAM
			 try {
				inputStream = serialPort.getInputStream();
 
				System.out.println("Inputstream open " + comName + "");
 
			 } catch (IOException exc) {
				System.out.println("Fehler Inputstream :"+exc);
			 }
			 try {
					serialPort.addEventListener(new serialPortEventListener());
					System.out.println("Add Eventlistener " + comName + "");
 
				} catch (TooManyListenersException e) {
					System.out.println("TooManyListenersException für Serialport");
				}
				serialPort.notifyOnDataAvailable(true);
		}	
	}
 
	void setCfg(int newSleepTime, int newLaps, int newTolerance, int newMinimumMV) {
		sleepTime = newSleepTime;
		cfg_laps = newLaps;
		cfg_tolerance = newTolerance;
		mVschwelle = newMinimumMV;
	}
 
	int getSleepTime() {
		return sleepTime;
	}
 
	//KOMMANDO-METHODE
	private void cmd(int third) {
		commando = third;
		lap++;
 
		//KOMMANDOS IN ARRAY SCHREIBEN
 
		//Datenpaket schnüren 
		byte[] sendData = new byte[3];
		sendData[0] = (byte) 99; //byte0_array[0];
		sendData[1] = (byte) 48; //cmd;
		sendData[2] = (byte) (48+third); //(cmd ^ sendData[0]);
 
 
		//DATEN SENDEN
		if (!Main.simulation) {
			try {
				out.write(sendData, 0, 3);
				out.flush();
 
				//System.out.println("Data send: First " + sendData[0] + "; second " + sendData[1] + "; third " + sendData[2] + " ");
			} catch (IOException e) {
				System.out.println("No data sended");
			}
 
			//WARTEN
			try {
				//System.out.println("wait " + sleepTime + "ms");
				Thread.sleep(sleepTime);
			} catch (InterruptedException e) {
				System.out.println("Sleeping failed");
			}
		}
	}
 
	//VERBINDUNG ZUR HB627-KARTE BEENDEN
	void close() {
		if (!Main.simulation) {
			serialPort.close();
			System.out.println("Connection closed");
		}
	}
 
	//EINGEHENDES SIGNAL AUS HIGH-BYTE UND LOW-BYTE UMRECHNEN
	int parseResponse(byte highByte, byte lowByte) {
		int intHB = 0;
		int intLB = 0;
 
		//In positive Zahlen parsen
		if (highByte < 0) {
			intHB = 256 + highByte;
		} else {
			intHB = highByte;
		}
 
		if (lowByte < 0) {
			intLB = 256 + lowByte;
		} else {
			intLB = lowByte;
		}
 
		//IN FERTGE ZAHL UMRECHNEN
		int result = (int) ((intHB*10) + intLB*0); //LOW-BYTE WIRD zZ IGNORIERT!
 
		return result;
	}
 
	//NEUES RENNEN / NEUE MESSUNG: GRUNDLAGE SCHAFFEN (Vergleichswerte zurücksetzen)
	private void newRace() {
		respondResults.clear();
		finalResults.clear();
		lap = 0;
 
		for (int i = 0;i<booleanResults.length; i++) {
			booleanResults[i] = false;
		}
 
	}
 
	//EINEN PORT LESEN/MESSEN
	boolean read(int port) {
		newRace();
 
		for (int i = 0; i<cfg_laps;i++) {
			cmd(port);
		}
 
		if (finalResults.size() > 0) {				
			//System.out.println("FR: " + finalResults.get(0));
 
			/*System.out.println(" ");
			for (int k = 0;k<finalResults.size();k++) {
				System.out.print(finalResults.get(k) + " ");
			}*/
 
			//hat der messwert die mindest-volt-schwelle erreicht?
 
			//if (finalResults.get(0) >= mVschwelle || true) {
 
				int durchschnitt = 0;
				int differenz = 0;
				int high;
 
				//durchschnitt ausrechnen
 
				System.out.println(finalResults.size()+" "+cfg_laps);
 
				if (finalResults.size() == (cfg_laps*8)) {
					for (int i = 0; i<cfg_laps;i++) {
						durchschnitt += finalResults.get((i*8));
					}
 
 
					durchschnitt = durchschnitt/cfg_laps;
 
					//Checken, ob höchstdifferenz eingehalten wird
					for (int i = 0; i<cfg_laps;i++) {
 
						high = (i*8);
						if (durchschnitt > finalResults.get(high)) {
							differenz += durchschnitt-finalResults.get(high);
						} else {
							differenz += finalResults.get(high)-durchschnitt;
						}
 
					}
 
					if ((differenz/cfg_laps) > cfg_tolerance ) {
						System.out.println("!tolerance: " + (differenz/cfg_laps));
						return false;
					} else {
						System.out.println("tolerance: " + (differenz/cfg_laps));
						booleanResults[0] = true;
						return true;
 
					}
				} else {
					System.out.println("Notice: (Array-Fehler)");
					return false;
				}
			} else {
				return false;
			}
		//} else {
		//	return false;
		//}		
	}
 
	//ALLE PORTS LESEN/MESSEN
	boolean[] readAll() {
		newRace();
 
 
		for (int i = 0; i<cfg_laps;i++) {
			cmd(9);
		}
 
		boolean[] result = {false,false,false,false,false,false,false,false}; 
		if (finalResults.size() > 0) {				
 
 
			/*System.out.println(" ");
			for (int k = 0;k<finalResults.size();k++) {
				System.out.print(finalResults.get(k) + " ");
			}*/
 
			for(int i = 0; i<8;i++) {
				//System.out.println("FR "+(i+1)+": " + finalResults.get(i));
 
				if(finalResults.get(i) > mVschwelle) {
 
					int durchschnitt = 0;
					int differenz = 0;
					int high;
 
					//durchschnitt ausrechnen
					for (int j = 0; j<cfg_laps;j++) {
						durchschnitt += finalResults.get((j*8)+i);
					}
					durchschnitt = durchschnitt/cfg_laps;
 
					//Checken, ob höchstdifferenz eingehalten wird
					for (int j = 0; j<cfg_laps;j++) {
						high = (j*8)+i;
 
						/*if (i==7) {
							System.out.println(durchschnitt + " dif " + finalResults.get(high));
						}*/
 
						if (durchschnitt > finalResults.get(high)) {
							differenz += durchschnitt-finalResults.get(high);
						} else {
							differenz += finalResults.get(high)-durchschnitt;
						}
 
					}
 
					if ((differenz/cfg_laps) > cfg_tolerance ) {
						//System.out.println("!tolerance: " + (differenz/cfg_laps));
						result[i] = false;
					} else {
						//System.out.println("tolerance: " + (differenz/cfg_laps));
						booleanResults[i] = true;
						result[i] = true;
					}
 
 
 
				}
			}
		}
 
		return result;
	}
 
	//MESSWERTE IN mV-Ausgeben
	int[] getVoltage() {
 
		int[] result = new int[8];
 
		for (int i = 0;i<8;i++) {
			if (booleanResults[i]) {
				result[i] = finalResults.get(i);
			} else {
				result[i] = 0;
			}
		}
 
		return result;
 
	}
 
	//DATEN EMPFANGEN & VERARBEITEN
	public void serialPortDataAvailable() {
		try {
			byte[] data = new byte[17];
 
 
 
			while(inputStream.available() > 0) {
 
				inputStream.read(data, 0, data.length);
				//System.out.println("[] "+data[0]+" "+data[1]+" "+data[2]+" "+data[3]+" "+data[4]+" "+data[5]+" "+data[6]+" "+data[7]+" "+data[8]+" "+data[9]+" "+data[10]+" "+data[11]+" "+data[12]+" "+data[13]+" "+data[14]+" "+data[15]+" "+data[16]+"");
 
				byte[] currentbytes = new byte[2];
				int currentvoltage;
 
				int fb;
				int sb;
 
				for (int i = 0;i<(data.length);i++) {
 
					fb = 2+(i*2)-1;
					sb = 2+(i*2);
 
					if (sb < 17) {
 
					if (commando == 9) {
						currentbytes[1] = data[sb];
						currentbytes[0] = data[fb];
 
					} else {
						currentbytes[0] = data[sb];
						currentbytes[1] = data[fb];
					}
 
					currentvoltage = this.parseResponse(currentbytes[0], currentbytes[1]);
 
					respondResults.add(currentbytes);
					finalResults.add(currentvoltage);
 
 
					//System.out.print(currentvoltage + "(" +fb+ "" +sb+ "): " + data[fb] + "/ " + data[sb] +" || ");
					}
				}
				//System.out.println(" ");
 
			}
		} catch (IOException e) {
			System.out.println("!!! Data could not be recieved !!!");
		}
	}
 
	class serialPortEventListener implements SerialPortEventListener {
		public void serialEvent(SerialPortEvent event) {
			switch (event.getEventType()) {
			case SerialPortEvent.DATA_AVAILABLE:
				serialPortDataAvailable();
				break;
			case SerialPortEvent.BI:
			case SerialPortEvent.CD:
			case SerialPortEvent.CTS:
			case SerialPortEvent.DSR:
			case SerialPortEvent.FE:
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			case SerialPortEvent.PE:
			case SerialPortEvent.RI:
			default:
			}
		}
	}	
 
 
}

Bekannte / Mögliche Schwachstellen / Bugs in der Klasse

  • Ich habe nicht geprüft (da in meinem Anwendungsbereich unerheblich) ob die gemessenen Spannungswerte („getVoltage()“) den realen Spannungswerten entsprechen. Eventuell ergibt sich die tatsächliche Spannung erst nach durch die Differenz von 4095… oder auch nicht. Ausgeschlossen werden kann ist, dass „getVoltage()“ falsche ergebnisse liefert. Man muss diese eben nur richtig interpretieren können.
  • Die Umrechnung von High-Byte und Lowbyte (Antwort von der Empfängerkarte) ist möglicherweise unvollständig, jedoch ausreichend (für meine Zwecke). Für eine Umrechnung unter berücksichtigung des Low-Bytes fehlt mir bisher die korrekte Formel, die sich auch nicht aus dem Handbuch ergibt. Sobald ich in diesem Punkt weiter bin, werde ich das im Kommentarbereich ergänzen.