Abfragen der ADC-Kanäle
In dem folgenden Beispiel wird gezeigt, wie die Multithreading-Fähigkeiten von JControl verwendet werden können, um in einer Applikation kontinuierlich die Messwerte der ADC-Kanäle aufzunehmen, ohne den normalen Programmablauf dadurch zu beeinträchtigen. So kann im Vordergrund beispielsweise eine grafische Benutzerschnittstelle angezeigt werden, während im Hintergrund automatisch auf Änderungen von Messwerten reagiert wird.
Unsere Applikation soll zunächst herausfinden, wie viele ADC-Kanäle auf dem System verfügbar sind und dann entsprechend viele Threads starten, die die Messwerte kontinuierlich einlesen. Der folgende Quelltext zeigt, wie diese Aufgabe mit JControl realisiert werden kann.
1 | import jcontrol.io.ADC; |
2 | import jcontrol.io.Display; |
3 | import jcontrol.lang.ThreadExt; |
4 | import jcontrol.system.Management; |
5 | |
6 | /** |
7 | * This example shows how to read out ADC values on JControl. |
8 | * Furthermore, the usage of multiple threads in one application |
9 | * is demonstrated. |
10 | * |
11 | * <p>(C) DOMOLOGIC Home Automation GmbH 2003</p> |
12 | */ |
13 | public class ADCExample { |
14 | /** array to store ADCReader instances in */ |
15 | ADCReader adcreaders[]; |
16 | |
17 | |
18 | /** |
19 | * Inner class <code>ADCReader</code> realizes a thread |
20 | * that continuously reads and stores ADC values. |
21 | */ |
22 | class ADCReader extends Thread { |
23 | /** adc channel */ |
24 | int channel; |
25 | /** last read value */ |
26 | int value = 0; |
27 | /** thread instance */ |
28 | Thread instance = null; |
29 | |
30 | /** |
31 | * Constructs an <code>ADCReader</code> thread. |
32 | * @param channel the ADC input channel to read values from |
33 | */ |
34 | public ADCReader(int channel) { |
35 | instance = this; |
36 | this.channel = channel; |
37 | this.start(); |
38 | } |
39 | |
40 | /** |
41 | * This method is invoked when the thread execution starts. |
42 | * @see java.lang.Runnable#run() |
43 | */ |
44 | public void run() { |
45 | while (instance == this) { |
46 | // read current adc value |
47 | value = ADC.getValue(channel); |
48 | |
49 | // sleep for 100 millis |
50 | try { |
51 | ThreadExt.sleep(100); |
52 | } catch (InterruptedException e) {} |
53 | } |
54 | } |
55 | |
56 | /** |
57 | * Stop thread execution. |
58 | */ |
59 | public void quit() { |
60 | instance = null; |
61 | } |
62 | |
63 | /** |
64 | * Retrieve current adc value |
65 | */ |
66 | public int getValue() { |
67 | return value; |
68 | } |
69 | } |
70 | |
71 | |
72 | /** |
73 | * Constructs an <code>ADCExample</code> instance. |
74 | * We start as many <code>ADCReader</code> threads as |
75 | * adc input channels exist. |
76 | */ |
77 | public ADCExample() { |
78 | String s = Management.getProperty("io.adcchannels"); |
79 | int numchannels = Integer.parseInt(s); |
80 | |
81 | adcreaders = new ADCReader[numchannels]; |
82 | |
83 | // create ADCReader threads and store instances into an array |
84 | for (int i=0; i<numchannels; i++) |
85 | adcreaders[i] = new ADCReader(i); |
86 | |
87 | // draw adc status continuously on lcd |
88 | drawStatus(); |
89 | } |
90 | |
91 | |
92 | /** |
93 | * Draw ADC values (read by ADCReader threads) on lcd |
94 | */ |
95 | void drawStatus() { |
96 | Display lcd = new Display(); |
97 | |
98 | while (true) { |
99 | lcd.clearDisplay(); |
100 | |
101 | // show adc values on lcd |
102 | for (int i=0; i<adcreaders.length; i++) { |
103 | lcd.drawString("ADC channel ".concat( |
104 | String.valueOf(i)).concat(" value: ").concat( |
105 | String.valueOf(adcreaders[i].getValue())), |
106 | 0, 8*i); |
107 | } |
108 | |
109 | // sleep for 500 millis |
110 | try { |
111 | ThreadExt.sleep(500); |
112 | } catch (InterruptedException e) {} |
113 | } |
114 | } |
115 | |
116 | /** |
117 | * Main method. Program execution starts here. |
118 | */ |
119 | public static void main(String[] args) { |
120 | new ADCExample(); |
121 | } |
122 | } |
Listing 1: ADCExample.java
Die Hauptklasse ADCExample
enthält eine innere Klasse ADCReader
, welche die Eigenschaften eines Thread-Objekts erfüllt. Wenn der Thread durch einen Aufruf der Methode start
gestartet wird, (hier im Konstruktor public ADCReader(int channel)
), folgt automatisch ein Aufruf der Methode run()
. Diese liest in einer Endlosschleife alle 100ms den aktuellen Wert des im Konstruktor spezifizierten ADC-Kanals ein. Dazu wird die getValue
-Methode aus der ADC
-Klasse verwendet.
Die Aufgabe der Hauptklasse ADCExample
ist einfach: Es müssen lediglich genau so viele ADCReader
-Instanzen erzeugt werden wie ADC-Kanäle im System verfügbar sind. Die Anzahl letzterer kann durch einen Aufruf der Methode Management.getProperty("io.adcchannels")
auf jedem JControl-System erfragt werden. Wurden die ADCReader
-Instanzen erzeugt, läuft die kontinuierliche Messwerterfassung ohne weiteres Zutun der Hauptklasse automatisch im Hintergrund.