2008年11月12日水曜日

[SunSPOT]IO制御

このエントリーをはてなブックマークに追加
SunSPOTのIOポートを利用します.
モーターを回します.
2台のSunSPOT端末を利用します.

1台は,SunSPOT端末で,Z軸の傾きをもう一台のSunSPOT端末に送信します.

受信側では,Z軸がプラス方向の場合は,モーターを正回転,マイナス方向の場合には,逆回転させます.

[送信側SunSpotIOSender.java]
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3D;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.sensorboard.peripheral.LEDColor;

import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class SunSpotIOSender extends MIDlet {

private static final int HOST_PORT = 67;
private final int CENTER = 0;
private final int FORWARD = 1;
private final int BACK = -1;
private final double THRESHOLD = 0.6;
private final int NUM = 30;

protected void startApp() throws MIDletStateChangeException {
RadiogramConnection rCon = null;
Datagram dg = null;
double z;

IAccelerometer3D accelerometer = EDemoBoard.getInstance().getAccelerometer();
ITriColorLED[] leds = EDemoBoard.getInstance().getLEDs();

try {
rCon = (RadiogramConnection) Connector.open("radiogram://broadcast:" + HOST_PORT);
dg = rCon.newDatagram(50);  // only sending 12 bytes of data
} catch (Exception e) {
System.err.println("Caught " + e + " in connection initialization.");
System.exit(1);
}

int[] Zdirects = new int[NUM];
int point = 0;
int Ztransmit = CENTER;

while (true) {
try {
z = accelerometer.getTiltZ();

// Z軸判定
if(point == NUM) point = 0;
if(z > THRESHOLD){
Zdirects[point] = FORWARD;
} else if(z < -1 * THRESHOLD){
Zdirects[point] = BACK;
} else {
Zdirects[point] = CENTER;
}
point++;

if(isSameValues(Zdirects)){
if(Zdirects[0] != Ztransmit){
dg.reset();
Ztransmit = Zdirects[0];
dg.writeDouble(Ztransmit);
rCon.send(dg);
if(Ztransmit == FORWARD){
setLEDGreen(leds);
} else if(Ztransmit == BACK){
setLEDRed(leds);
} else {
setLEDOFF(leds);
}
}
}
} catch (Exception e) {
System.err.println("Caught " + e + " while collecting/sending sensor sample.");
}
}
}

private void setLEDRed(ITriColorLED[] leds){
for(int i = 0; 0 < leds.length; i++){
leds[i].setColor(LEDColor.RED);
leds[i].setOn();
}
}

private void setLEDGreen(ITriColorLED[] leds){
for(int i = 0; 0 < leds.length; i++){
leds[i].setColor(LEDColor.GREEN);
leds[i].setOn();
}
}

private void setLEDOFF(ITriColorLED[] leds){
for(int i = 0; 0 < leds.length; i++){
leds[i].setOff();
}
}

private boolean isSameValues(int data[]){
int start = data[0];

for(int i = 1; i < data.length; i++){
if(start != data[i])
return false;
}
return true;
}

protected void pauseApp() {
// This will never be called by the Squawk VM
}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// Only called if startApp throws any exception other than MIDletStateChangeException
}
}
[受信側 SunSpotIOReceiver.java]
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.IDemoBoard;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.sensorboard.peripheral.LEDColor;
import com.sun.spot.sensorboard.io.IIOPin;

import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class SunSpotIOReceiver extends MIDlet {

private static final int HOST_PORT = 67; 
private final int FORWARD = 1;
private final int BACK = -1;

protected void startApp() throws MIDletStateChangeException {
RadiogramConnection rCon = null;
Datagram dg = null;
double Zdirect;

try {
// Open up a server-side broadcast radiogram connection
// to listen for sensor readings being sent by different SPOTs
rCon = (RadiogramConnection) Connector.open("radiogram://:" + HOST_PORT);
dg = rCon.newDatagram(rCon.getMaximumLength());
} catch (Exception e) {
System.err.println("setUp caught " + e.getMessage());
}

// "eDemo"ボードの参照を取得
IDemoBoard eDemo = EDemoBoard.getInstance();

// 汎用入出力ポート(D0)にアクセスするための参照を取得
IIOPin pin0 = eDemo.getIOPins()[EDemoBoard.D0];
IIOPin pin3 = eDemo.getIOPins()[EDemoBoard.D3];
pin0.setAsOutput(true);
pin3.setAsOutput(true);

// eDemoボード上のLEDにアクセスするための参照を取得
ITriColorLED[] leds = eDemo.getLEDs();

while (true) {
try {
// Read sensor sample received over the radio
rCon.receive(dg);
Zdirect = dg.readDouble();

// Zについて
if(Zdirect == FORWARD){
pin0.setHigh();
pin3.setLow();
setLEDGreen(leds);
} else if(Zdirect == BACK){
pin0.setLow();
pin3.setHigh();
setLEDRed(leds);

} else {
pin0.setLow();
pin3.setLow();
setLEDOFF(leds);
}
} catch (Exception e) {
System.err.println("Caught " + e +  " while reading sensor samples.");
}
}
}

private void setLEDRed(ITriColorLED[] leds){
for(int i = 0; 0 < leds.length; i++){
leds[i].setColor(LEDColor.RED);
leds[i].setOn();
}
}

private void setLEDGreen(ITriColorLED[] leds){
for(int i = 0; 0 < leds.length; i++){
leds[i].setColor(LEDColor.GREEN);
leds[i].setOn();
}
}

private void setLEDOFF(ITriColorLED[] leds){
for(int i = 0; 0 < leds.length; i++){
leds[i].setOff();
}
}

protected void pauseApp() {
// This will never be called by the Squawk VM
}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// Only called if startApp throws any exception other than MIDletStateChangeException
}
}
実行結果 IO部分
久々にはんだこてを使いました.
IO部分には,紙などを止めるクリップを使用し,手作り感が満載です.

[SunSPOT]3D加速度の取得

このエントリーをはてなブックマークに追加
Sun Microsystems社が開発したSunSPOTをいじってみました.
SunSPOT(http://jp.sun.com/products/software/sunspot/)


SunSPOTの端末で取得したXYZ軸方向の加速度をBaseStationに転送し,ホストPC上でグラフ化します.
グラフ化にはJFreeChartを使用しました.
JFreeChart(http://www.jfree.org/jfreechart/)

[端末側SunSPOT AccelationOnSunSpot.java]
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.io.j2me.radiogram.*;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3D;
import com.sun.spot.util.Utils;

import javax.microedition.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class AccelationOnSunSpot extends MIDlet {

private static final int HOST_PORT = 67;

protected void startApp() throws MIDletStateChangeException {
RadiogramConnection rCon = null;
Datagram dg = null;
IAccelerometer3D accelerometer = EDemoBoard.getInstance().getAccelerometer();


try {
rCon = (RadiogramConnection) Connector.open("radiogram://broadcast:" + HOST_PORT);
dg = rCon.newDatagram(50);  // only sending 12 bytes of data
} catch (Exception e) {
System.err.println("Caught " + e + " in connection initialization.");
System.exit(1);
}

double x,y,z;

while (true) {
try {
x = accelerometer.getAccelX();
y = accelerometer.getAccelY();
z = accelerometer.getAccelZ();

dg.reset();
dg.writeDouble(x);
dg.writeDouble(y);
dg.writeDouble(z);
rCon.send(dg);

Utils.sleep(100);
} catch (Exception e) {
System.err.println("Caught " + e + " while collecting/sending sensor sample.");
}
}
}

protected void pauseApp() {
// This will never be called by the Squawk VM
}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// Only called if startApp throws any exception other than MIDletStateChangeException
}
}


[ホスト側BaseStation AccelationOnDesktop.java]
import com.sun.spot.io.j2me.radiogram.*;
import javax.microedition.io.*;

import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import java.awt.Font;

public class AccelationOnDesktop extends JFrame implements Runnable{
private static final int HOST_PORT = 67;
private Thread th;
private TimeSeries XSeries;
private TimeSeries YSeries;
private TimeSeries ZSeries;

public AccelationOnDesktop(){
initChart();

th = new Thread(this);
th.start();
}

public void initChart(){

//create DataSeries object
XSeries = new TimeSeries("X", Millisecond.class);
YSeries = new TimeSeries("Y", Millisecond.class);
ZSeries = new TimeSeries("Z", Millisecond.class);

TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(XSeries);
dataset.addSeries(YSeries);
dataset.addSeries(ZSeries);

DateAxis domainAxis = new DateAxis("Time");
domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);

ValueAxis rangeAxis = new NumberAxis("Acceleration");

XYItemRenderer renderer = new StandardXYItemRenderer();
renderer.setToolTipGenerator(StandardXYToolTipGenerator.getTimeSeriesInstance());

XYPlot plot = new XYPlot(dataset,domainAxis,rangeAxis,renderer);
plot.getRenderer().setToolTipGenerator(StandardXYToolTipGenerator.getTimeSeriesInstance());

JFreeChart chart = new JFreeChart("XYZ Acceleration", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
LegendTitle legend = chart.getLegend();
legend.setItemFont(new Font("Ariel", Font.BOLD, 20));
ChartPanel cPanel = new ChartPanel (chart);

this.add(cPanel);
}

public void run() {
RadiogramConnection rCon = null;
Datagram dg = null;
double x,y,z;

try {
rCon = (RadiogramConnection) Connector.open("radiogram://:" + HOST_PORT);
dg = rCon.newDatagram(rCon.getMaximumLength());
} catch (Exception e) {
System.err.println("setUp caught " + e.getMessage());
}


while (true) {
try {
rCon.receive(dg);
x = dg.readDouble();
y = dg.readDouble();
z = dg.readDouble();

XSeries.add(new Millisecond(), x);
YSeries.add(new Millisecond(), y);
ZSeries.add(new Millisecond(), z);  
} catch (Exception e) {
System.err.println("Caught " + e +  " while reading sensor samples.");
}
}
}

public static void main(String[] args) throws Exception {
AccelationOnDesktop aod = new AccelationOnDesktop();
aod.setSize(600,300);
aod.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aod.setVisible(true);
}
}

実行結果