受信バッファの処理について

Sun SPOT についてのご質問はこちら。情報交換などにもご利用ください。

受信バッファの処理について

投稿記事by 桐蔭高校科学部 » 2010年8月13日(金) 16:08

はじめまして。桐蔭高校の松本です。
今、アドバイスを参考にしてGPSが正常に動作するようにしました。(GPS単独で確認しました。)

GPSとその他のセンサー群(気温,加速度,照度)を並行して動作させたいと思っています。(センサー群だけでも正常に動作します。)
単純に処理を並べたところ、0.03秒の壁が厚く、やはり受信バッファが一杯になってしまい以下のエラーが表示されます。
コード: 全て選択
java.io.IOException: UART data overrun error
    at java.lang.Throwable.<init>(bci=16)
    at java.lang.Throwable.<init>(bci=5)
    at java.lang.Exception.<init>(bci=6)
    at java.io.IOException.<init>(bci=6)
    in virtual method #110 of com.sun.spot.sensorboard.EDemoController(bci=271)
    at com.sun.spot.sensorboard.EDemoController.readUART(bci=48)
    at com.sun.spot.sensorboard.EDemoBoard.readUART(bci=10)
    at org.sunspotworld.UARTInputStream.read(UARTInputStream.java:30)



1)GPSからの受信を止める(または、受信バッファに溜めない)
2)センサー処理
3)GPSからの受信をはじめる(または、受信バッファに溜めはじめる)
ということを定期的(できれば1秒で1サイクル程度)に繰り返すことは可能でしょうか。 可能であれば具体的な方法も教えて下さい。
桐蔭高校科学部
 
記事: 40
登録日時: 2010年7月23日(金) 09:06

Re: 受信バッファの処理について

投稿記事by yamaguch » 2010年8月13日(金) 18:02

定期的に温度や加速度などを取るのであれば、Timer と TimerTask を使うのが簡単でしょう。
講習会の資料を見てください。

山口
yamaguch
 
記事: 482
登録日時: 2010年7月06日(火) 17:37

Re: 受信バッファの処理について

投稿記事by 桐蔭高校科学部 » 2010年8月14日(土) 17:15

桐蔭高校科学部の松本です。
講習会の資料に沿ってTimerTask を使用してみました。
GPSと他のセンサー群を並列で動かすことは一応できました。
しかし、肝心のデータが(稀に実数で帰ってくるときもありますが)3.019615821258567E-307の様な形でかえってきてしまい、データの意味が分かりません。
データを実数で返すためにはどうすればいいでしょうか。

以下がコードです。
コード: 全て選択
package org.sunspotworld;
import com.sun.spot.sensorboard.peripheral.LEDColor;
import com.sun.squawk.io.BufferedReader;
import java.io.InputStreamReader;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.IDemoBoard;
import com.sun.spot.sensorboard.peripheral.ISwitch;
import com.sun.spot.sensorboard.peripheral.ITemperatureInput;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3D;
import com.sun.spot.sensorboard.peripheral.ILightSensor;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class ModeSelection extends SunSpotApplicationAdapter {
IDemoBoard eDemo = EDemoBoard.getInstance();
ITriColorLED[] leds = eDemo.getLEDs();
ISwitch sw1 = eDemo.getSwitches()[EDemoBoard.SW1];
ISwitch sw2 = eDemo.getSwitches()[EDemoBoard.SW2];
ITemperatureInput tempSensor = eDemo.getADCTemperature();
IAccelerometer3D accelSensor = eDemo.getAccelerometer();//6g made taiousasete
ILightSensor lightSensor = eDemo.getLightSensor();
RMS rms;
BufferedReader in;
static final String DB = "GPSRecordStore";
static final int RECORD = 0;
static final int PRINT = 1;
static final int DELETE = 2;
ModeSelector modeSelector;
int sensorWork = 0;
protected void setup() {
System.out.println("setup");
Timer timer = new Timer();
TimerTask task = new sensorTask();
long time = System.currentTimeMillis();
long period = 700;
Date date = new Date(time + period);
timer.schedule(task, date, period);
modeSelector = new ModeSelector(LEDColor.GREEN, LEDColor.CYAN,
LEDColor.RED);
while (!modeSelector.selected()) {
sleep(100);
}
switch (modeSelector.getMode()) {
case RECORD:
rms = RMS.getInstance(DB, true);
in = new BufferedReader(new InputStreamReader(new UARTInputStream(9600)));
break;
case PRINT:
rms = RMS.getInstance(DB, false);
break;
}
}
protected void loop() throws Exception {
switch (modeSelector.getMode()) {
case RECORD:
String sentence = in.readLine();
System.out.println("??Get??");
if (sentence.startsWith("$GPGGA")) {
System.out.println("GetGet");
rms.writeString(sentence).
flush();
System.out.println("Keep!");
sensorWork = 1;
} else {
sensorWork = 0;
}
if (sw1.isClosed() || sw2.isClosed() == true) {
exitLoop();
}
break;
case PRINT:
if (rms.hasMoreRecords()) {
System.out.println(rms.readString());//GPS
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
System.out.println(rms.readDouble());//データの種類におうじてStringとdouble を変えてください
rms.skip();
} else {
exitLoop();
}
break;
case DELETE:
RMS.delete(DB);
exitLoop();
}
}
class sensorTask extends TimerTask {
public void run() {
if (sensorWork == 1) {
try {
rms.writeDouble(accelSensor.getAccel()).flush();
rms.writeDouble(accelSensor.getAccelX()).flush();
rms.writeDouble(accelSensor.getAccelY()).flush();
rms.writeDouble(accelSensor.getAccelZ()).flush();
rms.writeDouble(accelSensor.getTiltX()).flush();
rms.writeDouble(accelSensor.getTiltY()).flush();
rms.writeDouble(accelSensor.getTiltZ()).flush();
rms.writeDouble(tempSensor.getCelsius()).flush();
rms.writeDouble((0.488758553274682 * a1.getValue()) - 67.84).flush();
rms.writeDouble(lightSensor.getValue() * 2).flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
protected void cleanup() throws Exception {
System.out.println("Cleanup");
in.close();
}
}



以下が出力です。
コード: 全て選択
$GPGGA,071918.780,3413.3709,N,13511.2378,E,0,00,3.7,1776.2,M,0.0,M,,0000*54
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
0.9263998502637951
$GPGGA,071925.780,3413.3709,N,13511.2378,E,0,00,3.7,1776.2,M,0.0,M,,0000*5A
3.019615821258567E-307
0.9205906154278636
-0.10472610096670247
-0.09398496240601505
0.9049409237379162
36.25
27.46791788856305
$GPGGA,071927.780,3413.3709,N,13511.2378,E,0,00,3.7,1776.2,M,0.0,M,,0000*58
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
$GPGGA,072609.780,3413.3709,N,13511.2378,E,0,00,3.7,1776.2,M,0.0,M,,0000*58
3.019615821258567E-307
3.019615821258567E-307
0.9158159230095212
-0.09935553168635876
-0.09935553168635876
0.9049409237379162
36.75
$GPGGA,072612.780,3413.3709,N,13511.2378,E,0,00,3.7,1776.2,M,0.0,M,,0000*52
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
3.019615821258567E-307
0.9141767506017117
$GPGGA,072619.780,3413.3709,N,13511.2378,E,0,00,3.7,1776.2,M,0.0,M,,0000*59
3.019615821258567E-307
javax.microedition.rms.InvalidRecordIDException: No record with id: 58
at java.lang.Throwable.<init>(bci=16)
at java.lang.Throwable.<init>(bci=5)
at java.lang.Exception.<init>(bci=6)
at javax.microedition.rms.RecordStoreException.<init>(bci=6)
at javax.microedition.rms.InvalidRecordIDException.<init>(bci=6)
in virtual method #20 of com.sun.squawk.rms.RecordStoreEntry(bci=35)
in virtual method #22 of com.sun.squawk.rms.RecordStoreEntry(bci=6)
in virtual method #27 of com.sun.squawk.rms.RecordStoreEntry(bci=6)
at javax.microedition.rms.RecordStore.getRecord(bci=20)
at org.sunspotworld.RMS.prepareInput(RMS.java:61)
at org.sunspotworld.RMS.readDouble(RMS.java:121)
at org.sunspotworld.ModeSelection.loop(ModeSelection.java:89)
at org.sunspotworld.SunSpotApplicationAdapter.startApp
(SunSpotApplicationAdapter.java:51)
in virtual method #10 of javax.microedition.midlet.MIDlet(bci=17)
at javax.microedition.midlet.MIDletTunnelImpl.callStartApp(bci=4)
at com.sun.squawk.imp.MIDletMainWrapper.main(bci=378)
in virtual method #95 of com.sun.squawk.Klass(bci=32)
at com.sun.squawk.Isolate.run(bci=414)
at java.lang.Thread.run(bci=17)
in virtual method #47 of com.sun.squawk.VMThread(bci=42)
in static method #3 of com.sun.squawk.VM(bci=6)
桐蔭高校科学部
 
記事: 40
登録日時: 2010年7月23日(金) 09:06

Re: 受信バッファの処理について

投稿記事by yamaguch » 2010年8月14日(土) 20:52

 3.019615821258567E-307

は、仮数部と指数部を使った浮動小数点数の表示方法(詳しくは IEEE 754 で google ってみてください)で

 3.019615821258567 x 10 の -307 乗

を表しています。限りなく 0 に近い数ですね。おそらく、データを記録するときと読み出すときの型が違っているため、こんな小さな数が表示されてしまったのではないかと思います。

実は先の TimerTask を使ったプログラムには問題があります。
それは loop() と TimerTask の両方から rms に書き出している部分です。
これらは異なるスレッドで実行されているため、適切に「排他制御」を行わないと予想外の結果になることがあります。
スレッドの排他制御について調べてみてください。

山口
yamaguch
 
記事: 482
登録日時: 2010年7月06日(火) 17:37

バッファのクリアについて

投稿記事by 桐蔭高校科学部 » 2010年8月16日(月) 12:07

桐蔭高校科学部の松本です。
返信ありがとうございました。

排他制御を行う(自分では行えていると思う)ことで並列してデータを取ることには成功しましたが、処理速度の関係上か、1分ほど連続で起動すると受信バッファがいっぱいになってしまい、強制終了してしまいます。

sunspotにはバッファを空にする命令はありますか。教えて下さい。
桐蔭高校科学部
 
記事: 40
登録日時: 2010年7月23日(金) 09:06

Re: 受信バッファの処理について

投稿記事by yamaguch » 2010年8月16日(月) 15:37

sunspotにはバッファを空にする命令はありますか。教えて下さい。


Sun SPOT のバッファを空にするのは、バッファにあるデータを全部読み出してしまえばいいでしょう。例えば
コード: 全て選択
while (eDemo.availableUART() > 0) {
    eDemo.readUART();
}

で、受信バッファを空にすることができます。ただし、これはせっかく受信したデータを捨ててしまうということですから、問題の本当の解決にはならないでしょう。

排他制御を行う(自分では行えていると思う)ことで並列してデータを取ることには成功しましたが、処理速度の関係上か、1分ほど連続で起動すると受信バッファがいっぱいになってしまい、強制終了してしまいます。


問題は排他制御を行うように修正した結果、書き出しに時間がかかりすぎるようになってしまったということです。これをなんとか短縮すればいいんじゃないですか。

山口
yamaguch
 
記事: 482
登録日時: 2010年7月06日(火) 17:37


Return to Sun SPOT 質問箱

cron