2008年 4月 22日 火曜日
[Sun SPOT(22)] Q: 「まだ購入していないけど Emulator を使って Sun SPOTプログラムを試してみたい!」
以前、こちらのエントリ等でSun SPOT SDK のインストールや SPOT Managerツール、エミュレータの使用方法について紹介したのですが、書いた時点ではこれらのツールは Sun SPOT Java Development Kit (つまり実機)を購入頂いた方のみ使用可能ということで、途中からツールの配布URLを削除していました。
フォーラムや Davidさんのブログでアナウンスされていますが、最新版の Software-only Beta の配布が始まっております。まだ購入していないけどエミュレータを使ってSun SPOTプログラムを試してみたい!という方は、是非 Beta プログラムに参加してみてください!
参加方法は David のブログを参照してください。ブログにあるアドレスにメールを送ればOKです。メールのSubject(件名)に "SDK Beta" と書くのを忘れずに、とのことです。ツールに対する改善点やご要望などのフィードバックも、是非よろしくお願いいたします!
ツールのインストールや設定方法は David のこのエントリでも詳しく紹介されています。
# Sun SPOTアプリケーションをエミュレータで実行中。。。
Posted at 11:29午前 4 22, 2008 by Shuichi Machida in SunSPOT | 投稿されたコメント[2]
[Sun SPOT で"デューク神棚(Duke Temple)" を動かそう(3)] 距離センサー(Distance Sensor)で人を検出して扉を開閉する。
前回のエントリで扉の開閉までできましたので、次は神棚に距離センサーを取り付けて、
# 距離センサーを取り付けたところ↓
前回作成した回路に、距離センサーを追加します。Sun SPOT の 5V、GNDに距離センサーの5V、GNDを、またアナログ入力ピンA0に距離センサーの出力を接続します。
# 接続の図。
# ちょっと拡大。
ちょっと長いですが、プログラムはこんなかんじです↓
扉の開閉を安定させるために、3回以上連続して人を検出した/しなかった時に扉を開閉しています。
| package org.sunspotworld; import com.sun.spot.peripheral.Spot; import com.sun.spot.sensorboard.EDemoBoard; import com.sun.spot.sensorboard.io.IOutputPin; import com.sun.spot.util.*; import java.io.IOException; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; public class TempleDemoSpot extends MIDlet { private DoorController doorController; // 扉開閉制御スレッド protected void startApp() throws MIDletStateChangeException { try { initAndRun(); } catch (IOException ex) { ex.printStackTrace(); } finally { if (doorController != null) { doorController.terminate(); } } } private void initAndRun() throws IOException { new BootloaderListener().start(); Spot.getInstance().getSleepManager().disableDeepSleep(); doorController = new DoorController(); doorController.start(); while (true) { // TODO: // 後でここに処理を追加する Utils.sleep(2000L); } } /** * DoorController クラスは、アナログ入力ピンA0に接続した距離センサーから * 定期的(DETECTION_INTERVAL間隔)に値を取得して、以下の動作を実行します: * o COUNT_THRESHOLD 回連続して10cm~80cmの間に物体を検出した場合に扉を開きます * o COUNT_THRESHOLD 回連続して物体を検出しなかった場合に扉を閉じます */ class DoorController extends Thread { private final long DETECTION_INTERVAL = 1000L; private final int COUNT_THRESHOLD = 3; private TempleManager templeManager; // 神棚の扉の開閉を制御するクラス private DistanceSensor distanceSensor; // 距離計測用クラス private int countInRange; // 連続して物体を検出した回数 private int countOutOfRange; // 連続して物体を検出しなかった回数 private volatile boolean running = true; private boolean doorOpened = false; // 扉の状態(開: true, 閉: false) DoorController() throws IOException { // 大電流出力ピンH0、H1を使用する IOutputPin[] pins = EDemoBoard.getInstance().getOutputPins(); templeManager = new TempleManager( pins[EDemoBoard.H0],pins[EDemoBoard.H1]); // アナログ入力ピンA0を使用する distanceSensor = new DistanceSensor(EDemoBoard.A0); } public void run() { while (running) { try { doDetect(); // 物体の検出を実行 updateDoorStatus(); // 扉の状態(開/閉)を更新 } catch (Exception ex) { ex.printStackTrace(); } Utils.sleep(DETECTION_INTERVAL); } } /* * 物体の検出を実行する */ private void doDetect() throws IOException { // 距離センサーから値を取得 float distance = distanceSensor.getValue(); if (distance >= 10.0f && distance <= 80.0f) { // 物体を検出した updateCountInRange(); } else { // 物体を検出しなかった updateCountOutOfRange(); } } /* * 扉の状態(開/閉)を更新する */ private void updateDoorStatus() { if (countInRange >= COUNT_THRESHOLD) { // 連続COUNT_THRESHOLD回以上物体を検出した if (!isDoorOpened()) { // 扉が閉じているので開く templeManager.openSesame(); setDoorOpened(true); } countInRange = 0; } else if (countOutOfRange >= COUNT_THRESHOLD) { // 連続COUNT_THRESHOLD回以上物体を検出しなかった if (isDoorOpened()) { // 扉が開いているので閉じる templeManager.shutSesame(); setDoorOpened(false); } countOutOfRange = 0; } } private void updateCountInRange() { countInRange++; countOutOfRange = 0; System.out.println("updateCountInRange(countInRange=" + countInRange); } private void updateCountOutOfRange() { countOutOfRange++; countInRange = 0; System.out.println("updateCountOutOfRange(countInRange=" + countOutOfRange); } private boolean isDoorOpened() { return doorOpened; } private void setDoorOpened(boolean doorOpened) { this.doorOpened = doorOpened; } public void terminate() { running = false; } public void destroy() { templeManager.destroy(); } } protected void pauseApp() { } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { if (doorController != null) { doorController.destroy(); } } } |
| package org.sunspotworld; import com.sun.spot.sensorboard.EDemoBoard; import com.sun.spot.sensorboard.io.IScalarInput; import java.io.IOException; public class DistanceSensor { private static final float MAX_VOLTAGE = 3.0f; private IScalarInput input; private int range; public DistanceSensor(int pinId) throws IOException { input = EDemoBoard.getInstance().getScalarInputs()[pinId]; range = input.getRange(); System.out.println("DistanceSensor init: range=" + range); } public float getValue() throws IOException { int value = input.getValue(); float voltage = (float)value / range * MAX_VOLTAGE; System.out.println("A/D value -> " + value + ", voltage -> " + voltage); // calculates the distance float distance = 23.333f / (voltage - 0.236f) - 0.420f; System.out.println("Distance=" + distance); return distance; } } |
| package org.sunspotworld; import com.sun.spot.sensorboard.io.IOutputPin; import com.sun.spot.util.Utils; public class TempleManager { private final long DURATION = 6000L; private IOutputPin out1; private IOutputPin out2; public TempleManager(IOutputPin out1, IOutputPin out2) { this.out1 = out1; this.out2 = out2; stop(1L); } /** * 扉を開く */ public void openSesame() { System.out.println("openSesame()" ); stop(1L); out1.setHigh(); Utils.sleep(DURATION); out1.setLow(); } /** * 扉を閉じる */ public void shutSesame() { System.out.println("shutSesame()" ); stop(1L); out2.setHigh(); Utils.sleep(DURATION); out2.setLow(); } /** * ストップ */ public void stop(long duration) { out1.setLow(); out2.setLow(); Utils.sleep(duration); } public void destroy() { out1.setLow(); out2.setLow(); } } |
それでは実行してみます。
。。。
# デューク登場 
Posted at 12:32午前 4 22, 2008 by Shuichi Machida in SunSPOT | 投稿されたコメント[0]