なんとか、携帯電話でハニービーを操作できるようになりました。
赤外線が弱いので到達距離は短いですが、
もともと部屋の中で遊ぶものなのでこれでも結構遊べます。
アプリは、こちら、
http://www.netflowers.co.jp/honeybee/
Doja4.1で作ったので、それなりに新しいDoCoMoの携帯電話のみ対応だと思います。
テストは、最近買ったP903iで黄色ハニー(Bバンド)しかやってません。
------HoneyBee.java
import com.nttdocomo.ui.*;
import com.nttdocomo.device.IrRemoteControl;
import com.nttdocomo.device.IrRemoteControlFrame;
import java.io.ByteArrayOutputStream;
public class HoneyBee extends IApplication {
public void start() {
Display.setCurrent(new HoneyBeeCanvas());
}
}
class HoneyBeeCanvas extends Canvas
{
//スロットル
int throttle=0;
//ラダー
int rudder = 0;
//チャンネル
String channel = "A";
//トリム
String trim = "";
/**スクリーンのサイズ*/
int windowWidth,windowHeight;
/**タイマー*/
ShortTimer st,st_ir;
int timer_ID = 100;
int timer_ID_ir = 101;
//IR送信用
int freq = 38; // KHz
int base = 600; // usec
IrRemoteControl irc;
boolean status = false;
String error = "";
public HoneyBeeCanvas()
{
//コンストラクタ
windowWidth = getWidth();
windowHeight = getHeight();
st = ShortTimer.getShortTimer(this,timer_ID,500,false);
st_ir = ShortTimer.getShortTimer(this,timer_ID_ir,200,true);
setSoftLabel(Frame.SOFT_KEY_1,"終了");
irc = IrRemoteControl.getIrRemoteControl();
}
public void paint(Graphics g)
{
g.clearRect(0, 0,windowWidth,windowHeight);
g.setColor(g.getColorOfName(g.BLACK));
g.drawString("スロットル: "+throttle ,0,20);
g.drawString("↑:UP ↓:DOWM ●:停止",30,40);
g.drawString("ラダー : "+rudder ,0,60);
g.drawString("←:左回転 →:右回転",30,80);
g.drawString("チャンネル: "+channel ,0,100);
g.drawString("1:A 2:B 3:C",30,120);
g.drawString("トリム : "+trim ,0,140);
g.drawString("*:左トリム #:右トリム",30,160);
//g.drawString("ERROR : "+error ,0,100);
}
//イベントリスナー
public void processEvent(int type,int param){
if(type==Display.KEY_PRESSED_EVENT){
if(param==Display.KEY_SOFT1){
(IApplication.getCurrentApp()).terminate();
}
if(param==Display.KEY_UP && throttle < 14){
//スロットルアップ
throttle ++;
repaint();
make_ir_data();
}
if(param==Display.KEY_DOWN && throttle > 0){
//スロットルダウン
throttle --;
repaint();
make_ir_data();
}
if(param==Display.KEY_SELECT){
//スロットルオフ
throttle =0;
repaint();
make_ir_data();
}
if(param==Display.KEY_RIGHT && rudder < 3){
//右ラダーをプッシュ
st.stop();
rudder ++;
repaint();
make_ir_data();
}
if(param==Display.KEY_LEFT && rudder > -3){
//左ラダーをプッシュ
st.stop();
rudder --;
repaint();
make_ir_data();
}
if(param==Display.KEY_1){
//1キーをプッシュ
channel = "A";
repaint();
make_ir_data();
}
if(param==Display.KEY_2){
//1キーをプッシュ
channel = "B";
repaint();
make_ir_data();
}
if(param==Display.KEY_3){
//1キーをプッシュ
channel = "C";
repaint();
make_ir_data();
}
if(param==Display.KEY_ASTERISK){
//*キーをプッシュ
trim = "LEFT";
repaint();
make_ir_data();
}
if(param==Display.KEY_POUND){
//#キーをプッシュ
trim = "RIGHT";
repaint();
make_ir_data();
}
}
if(type==Display.KEY_RELEASED_EVENT){
if(param==Display.KEY_RIGHT || param==Display.KEY_LEFT || param==Display.KEY_ASTERISK || param==Display.KEY_POUND){
//右または左ラダーをリリース
try{
st.start();
}catch (Exception e) {}
}
}
if(type == Display.TIMER_EXPIRED_EVENT && param == timer_ID){
//ラダー・トリム用タイマー実行
rudder = 0;
trim ="";
repaint();
make_ir_data();
}
if(type == Display.TIMER_EXPIRED_EVENT && param == timer_ID_ir){
//IR送信用タイマー
make_ir_data();
}
}
public void make_ir_data(){
String source = "";
String s;
//頭に0011
source += "0011";
//A=00 B=01 C=10
if(channel.equals("A")){
source += "00";
}else if(channel.equals("B")){
source += "01";
}else if(channel.equals("C")){
source += "11";
}
//C) メインロータースロットル 0000(小)<------> (大)1110 15段階
s = "0000" + Integer.toBinaryString(throttle);
source += s.substring(s.length()-4,s.length());
//D) トリムスイッチ L=1111 押してない時=0000 R=0001
if(trim.equals("LEFT")){
source += "1111";
}else if(trim.equals("RIGHT")){
source += "0001";
}else{
source += "0000";
}
//E) ラダースティック位置信号
//L3=101 L2=110 L1=111 中立=000 R1=001 R2=010 R3=011
s = "000" + Integer.toBinaryString(rudder);
source += s.substring(s.length()-3,s.length());
//パリティビット計算
s = source + "0";
int p = 0;
for(int i = 0; i < s.length(); i += 2){
p += Integer.parseInt(s.substring(i, i + 2), 2);
}
p &= 0x03;
if(p==0){//送信用パリティデータ生成
source += "11";
} else if(p==1){
source += "01";
} else if(p==2){
source += "10";
} else if(p==3){
source += "00";
}
//G) ストップビット いつも0
source += "0";
System.out.println(source);
send(source);
}
public void send(String source) {
int bit_size = source.length();
//送信用バイトデータの組み立て
//8ビット毎に揃える
for(int i=0;i<source.length()%8;i++){
source += "0";
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for(int i = 0; i < source.length(); i += 8){
int b = Integer.parseInt(source.substring(i, i + 8), 2);
baos.write(b);
}
byte[] data = baos.toByteArray();
irc.setCarrier(10000 / freq / 2, 10000 / freq / 2);
irc.setCode0(IrRemoteControl.PATTERN_HL, base * 1, base * 1);
irc.setCode1(IrRemoteControl.PATTERN_HL, base * 2, base * 1);
IrRemoteControlFrame[] ircf = new IrRemoteControlFrame[1];
IrRemoteControlFrame frame = new IrRemoteControlFrame();
frame.setFrameData(data, bit_size);
frame.setStartHighDuration(0);
frame.setStartLowDuration(0);
frame.setStopHighDuration(0);
frame.setFrameDuration(bit_size * base * 4 / 100 + 60 + 85);
frame.setRepeatCount(IrRemoteControlFrame.COUNT_INFINITE);
ircf[0] = frame;
try{
irc.stop();
Thread.sleep(200);
irc.send(1, ircf,60);
}catch(Exception e){
error = e.toString();
repaint();
}
status = true;
}
}
赤外線が弱いので到達距離は短いですが、
もともと部屋の中で遊ぶものなのでこれでも結構遊べます。
アプリは、こちら、
http://www.netflowers.co.jp/honeybee/
Doja4.1で作ったので、それなりに新しいDoCoMoの携帯電話のみ対応だと思います。
テストは、最近買ったP903iで黄色ハニー(Bバンド)しかやってません。
------HoneyBee.java
import com.nttdocomo.ui.*;
import com.nttdocomo.device.IrRemoteControl;
import com.nttdocomo.device.IrRemoteControlFrame;
import java.io.ByteArrayOutputStream;
public class HoneyBee extends IApplication {
public void start() {
Display.setCurrent(new HoneyBeeCanvas());
}
}
class HoneyBeeCanvas extends Canvas
{
//スロットル
int throttle=0;
//ラダー
int rudder = 0;
//チャンネル
String channel = "A";
//トリム
String trim = "";
/**スクリーンのサイズ*/
int windowWidth,windowHeight;
/**タイマー*/
ShortTimer st,st_ir;
int timer_ID = 100;
int timer_ID_ir = 101;
//IR送信用
int freq = 38; // KHz
int base = 600; // usec
IrRemoteControl irc;
boolean status = false;
String error = "";
public HoneyBeeCanvas()
{
//コンストラクタ
windowWidth = getWidth();
windowHeight = getHeight();
st = ShortTimer.getShortTimer(this,timer_ID,500,false);
st_ir = ShortTimer.getShortTimer(this,timer_ID_ir,200,true);
setSoftLabel(Frame.SOFT_KEY_1,"終了");
irc = IrRemoteControl.getIrRemoteControl();
}
public void paint(Graphics g)
{
g.clearRect(0, 0,windowWidth,windowHeight);
g.setColor(g.getColorOfName(g.BLACK));
g.drawString("スロットル: "+throttle ,0,20);
g.drawString("↑:UP ↓:DOWM ●:停止",30,40);
g.drawString("ラダー : "+rudder ,0,60);
g.drawString("←:左回転 →:右回転",30,80);
g.drawString("チャンネル: "+channel ,0,100);
g.drawString("1:A 2:B 3:C",30,120);
g.drawString("トリム : "+trim ,0,140);
g.drawString("*:左トリム #:右トリム",30,160);
//g.drawString("ERROR : "+error ,0,100);
}
//イベントリスナー
public void processEvent(int type,int param){
if(type==Display.KEY_PRESSED_EVENT){
if(param==Display.KEY_SOFT1){
(IApplication.getCurrentApp()).terminate();
}
if(param==Display.KEY_UP && throttle < 14){
//スロットルアップ
throttle ++;
repaint();
make_ir_data();
}
if(param==Display.KEY_DOWN && throttle > 0){
//スロットルダウン
throttle --;
repaint();
make_ir_data();
}
if(param==Display.KEY_SELECT){
//スロットルオフ
throttle =0;
repaint();
make_ir_data();
}
if(param==Display.KEY_RIGHT && rudder < 3){
//右ラダーをプッシュ
st.stop();
rudder ++;
repaint();
make_ir_data();
}
if(param==Display.KEY_LEFT && rudder > -3){
//左ラダーをプッシュ
st.stop();
rudder --;
repaint();
make_ir_data();
}
if(param==Display.KEY_1){
//1キーをプッシュ
channel = "A";
repaint();
make_ir_data();
}
if(param==Display.KEY_2){
//1キーをプッシュ
channel = "B";
repaint();
make_ir_data();
}
if(param==Display.KEY_3){
//1キーをプッシュ
channel = "C";
repaint();
make_ir_data();
}
if(param==Display.KEY_ASTERISK){
//*キーをプッシュ
trim = "LEFT";
repaint();
make_ir_data();
}
if(param==Display.KEY_POUND){
//#キーをプッシュ
trim = "RIGHT";
repaint();
make_ir_data();
}
}
if(type==Display.KEY_RELEASED_EVENT){
if(param==Display.KEY_RIGHT || param==Display.KEY_LEFT || param==Display.KEY_ASTERISK || param==Display.KEY_POUND){
//右または左ラダーをリリース
try{
st.start();
}catch (Exception e) {}
}
}
if(type == Display.TIMER_EXPIRED_EVENT && param == timer_ID){
//ラダー・トリム用タイマー実行
rudder = 0;
trim ="";
repaint();
make_ir_data();
}
if(type == Display.TIMER_EXPIRED_EVENT && param == timer_ID_ir){
//IR送信用タイマー
make_ir_data();
}
}
public void make_ir_data(){
String source = "";
String s;
//頭に0011
source += "0011";
//A=00 B=01 C=10
if(channel.equals("A")){
source += "00";
}else if(channel.equals("B")){
source += "01";
}else if(channel.equals("C")){
source += "11";
}
//C) メインロータースロットル 0000(小)<------> (大)1110 15段階
s = "0000" + Integer.toBinaryString(throttle);
source += s.substring(s.length()-4,s.length());
//D) トリムスイッチ L=1111 押してない時=0000 R=0001
if(trim.equals("LEFT")){
source += "1111";
}else if(trim.equals("RIGHT")){
source += "0001";
}else{
source += "0000";
}
//E) ラダースティック位置信号
//L3=101 L2=110 L1=111 中立=000 R1=001 R2=010 R3=011
s = "000" + Integer.toBinaryString(rudder);
source += s.substring(s.length()-3,s.length());
//パリティビット計算
s = source + "0";
int p = 0;
for(int i = 0; i < s.length(); i += 2){
p += Integer.parseInt(s.substring(i, i + 2), 2);
}
p &= 0x03;
if(p==0){//送信用パリティデータ生成
source += "11";
} else if(p==1){
source += "01";
} else if(p==2){
source += "10";
} else if(p==3){
source += "00";
}
//G) ストップビット いつも0
source += "0";
System.out.println(source);
send(source);
}
public void send(String source) {
int bit_size = source.length();
//送信用バイトデータの組み立て
//8ビット毎に揃える
for(int i=0;i<source.length()%8;i++){
source += "0";
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for(int i = 0; i < source.length(); i += 8){
int b = Integer.parseInt(source.substring(i, i + 8), 2);
baos.write(b);
}
byte[] data = baos.toByteArray();
irc.setCarrier(10000 / freq / 2, 10000 / freq / 2);
irc.setCode0(IrRemoteControl.PATTERN_HL, base * 1, base * 1);
irc.setCode1(IrRemoteControl.PATTERN_HL, base * 2, base * 1);
IrRemoteControlFrame[] ircf = new IrRemoteControlFrame[1];
IrRemoteControlFrame frame = new IrRemoteControlFrame();
frame.setFrameData(data, bit_size);
frame.setStartHighDuration(0);
frame.setStartLowDuration(0);
frame.setStopHighDuration(0);
frame.setFrameDuration(bit_size * base * 4 / 100 + 60 + 85);
frame.setRepeatCount(IrRemoteControlFrame.COUNT_INFINITE);
ircf[0] = frame;
try{
irc.stop();
Thread.sleep(200);
irc.send(1, ircf,60);
}catch(Exception e){
error = e.toString();
repaint();
}
status = true;
}
}


さっそくアプリ使わせて頂きました。
物凄くコントローラブルでアプリの完成度に驚きました。
プロポが無くても十分ヘリとして飛行できるレベルですね!
新しい楽しみ方が増えて感謝しております。
ハニービーに関するHPを運営しているのですが、
もし宜しければ私のサイトで紹介させて頂けませんでしょうか
※二次配布ではなく、リンクと簡単なレビューなど。
この素晴らしいアプリを仲間に伝えたい気持ちでいっぱいです。
サイト名「ハニービー&ジャイロフォース調整しようぜ!」
http://honeybeegyroforce.web.fc2.com/
よろしくお願いいたします
赤外線の到達距離が微妙ではありますが、
それなりにコントロールできて面白いですね。
アプリの方はそんなすばらしいものでは有りませんが、
ご紹介いただけるのであればどうぞ宜しくお願いいたします。
早速コーナーを設置しトップページへリンクさせて頂きました。
本日掲載のFON ちょっと興味が沸いてきました。
APを無料でもらい、それを会員限定に開放する?プロジェクトなのですね。
良い情報をまた知る事ができました!
FONに調べてこようとおもいます。
ありがとうございました。
携帯で操作してみたい!と思い早速ダウンロードしようと思ったのですが
リンクが切れていてダウンロード出来ませんでした。
スプリクト??の知識も無いのでどうすればいいのかわからなくて・・・
よろしければ、もう一度アップロードしていただけないでしょうか?
ごめんなさい。ホームページのリニューアル時に消えてしまっておりました。
ダウンロード出来るように、リンクを張り直して起きましたので
ご利用くださいませ。