Simulating a Wii remote with a TiltSensor and Bluetooth

Post your NXJ projects, project ideas, etc here!

Moderators: 99jonathan, roger, imaqine

Simulating a Wii remote with a TiltSensor and Bluetooth

Postby lawrie » Sat Nov 17, 2007 2:53 pm

I have just completed a little project to simulate a Wii remote control with a Tilt (Acceleration) sensor and Bluetooth comms.

One NXT has the Tilt sensor attached pointing forwards and acts as the controller. You hold the NXT sideways at an angle to the vertical and use it as a steering wheel. Tilting away from you increases the speed. Tilting backwards decreases the speed and then goes into reverse.

I used the Mindsensors ACCL-Nx-3g3x sensor, but am only using the X and Y Tilt values. It should work with any of the mindsensors or HiTechnic acceleration sensors.

The other NXT uses a Pilot class to steer a wheeled vehicle. It works quite well, but it could do with a bit more work on the programs to achive finer contol.

Here is the controller program. You will need to change the name of your NXT, and make sure you have added it to the Bluetooth devices.

Code: Select all
import java.io.*;
import lejos.nxt.*;
import lejos.nxt.comm.*;

public class TiltController {

   /**
    * Wii like controller for the NXT.
    *
    * Needs two NXTs: one for the controller and one to control.
    */
   public static void main(String[] args) throws Exception {
      TiltSensor controller = new TiltSensor(SensorPort.S1);
      int x, y, z;      
      String name = "NOISY";
      
      LCD.drawString("Connecting ...", 0, 0);
      LCD.refresh();
      
      BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);
      BTConnection btc = Bluetooth.connect(btrd);
      
      LCD.clear();
      LCD.drawString("Connected", 0, 0);
      LCD.refresh();
      
      DataInputStream dis = btc.openDataInputStream();
      DataOutputStream dos = btc.openDataOutputStream();
      
      while(true) {
         x = controller.getXTilt();
         y = controller.getYTilt();
         z = controller.getZTilt();
         
         LCD.drawInt(x, 3,  0, 1);
         LCD.drawInt(y, 3, 0, 2);
         LCD.drawInt(z, 3, 0, 3);
         LCD.refresh();
         
         dos.writeByte(x);
         dos.writeByte(y);
         dos.writeByte(z);
         dos.flush();
         byte ack = dis.readByte();
      }
   }
}


And here is the code for the robot you are controlling. You will need to change the Pilot constructors parameters for your robot.

Code: Select all
import java.io.*;
import lejos.navigation.*;
import lejos.nxt.*;
import lejos.nxt.Motor;
import lejos.nxt.comm.*;

public class RemoteSteer {

   public static void main(String[] args) throws Exception {
      Pilot robot = new Pilot(2.1f,6f,Motor.A, Motor.C,false);
      String connected = "Connected";
        String waiting = "Waiting";
      LCD.drawString(waiting,0,0);
      LCD.refresh();

        BTConnection btc = Bluetooth.waitForConnection();
       
      LCD.clear();
      LCD.drawString(connected,0,0);
      LCD.refresh();   

      DataInputStream dis = new DataInputStream(btc.openInputStream());
      DataOutputStream dos = new DataOutputStream(btc.openOutputStream());

      while (true) {
         
         int x = dis.readByte();
         int y = dis.readByte() & 0xFF;
         int z = dis.readByte() & 0xFF;
         
         dos.writeByte((byte) 0xFF); // Ack
         dos.flush();
               
         LCD.drawInt(x,4, 0,1);
         LCD.drawInt(y,4, 0,2);
         LCD.drawInt(z,4, 0,3);
         
         int speed = (180 - y) * 20;
         
         LCD.drawInt(speed, 5, 0, 4);
         LCD.refresh();
         
         int ax = (x < 0 ? -x : x);
         
         if (speed > 0) {
            robot.setSpeed(speed);
            if (ax < 5) robot.forward();
            else robot.steer(x);
         } else {
            speed = - speed;
            robot.setSpeed(speed);
            robot.backward();
         }   
      }
   }
}
lawrie
leJOS Team Member
 
Posts: 934
Joined: Mon Feb 05, 2007 1:27 pm

Postby esmetaman » Sat Nov 17, 2007 7:18 pm

Good Project lawrie!!!

I tried to test your classes, but one NXT brick when execute TiltController showed the following message:

Java Exception:
Class: 8
Action: 84

I received the same message, few weeks ago when I tried to improve NXTComs.

I deleted all files in my NXT brick and I used Defrag function, but I dont know the cause of this error.
Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby esmetaman » Sat Nov 17, 2007 7:40 pm

I discovered the failure:

I tried to detect NXT brick in the brick where I sent TiltController class.

I liked the results lawrie, but It is neccesary to improve the movements to turn left and right.

Good work.
Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby lawrie » Sat Nov 17, 2007 8:27 pm

Yes, control of the steering could be better. I meant it mainly as a proof of concept. I am sure a real project could be made to work better by adjusting timings and values, and the Pilot methods used. It is not too bad at low speed but gets a bit out of control at higher speeds.
lawrie
leJOS Team Member
 
Posts: 934
Joined: Mon Feb 05, 2007 1:27 pm

Postby esmetaman » Sat Nov 17, 2007 9:26 pm

I have integrated your idea with NXTComms in relation to TiltController.

Code: Select all
import lejos.nxt.*;

public class TiltComms {

   /**
    * @param args
    */
   public static void main(String[] args) {

      try{
         TiltSensor ts = new TiltSensor(SensorPort.S1);

         BotSoul bObj = new BotSoul(ts);
         TiltCommsUI UIObj = new TiltCommsUI(bObj,"NXT","NXT");
         UIObj.start();
      }catch(Exception e){
         
      }
   }

}



Code: Select all
import javax.microedition.lcdui.*;
import lejos.nxt.*;

public class TiltCommsUI extends Thread implements CommandListener{

   String NXTWiiVersion = "NXT Wii";
   
   private static final int CMDID_BACK_TO_MAIN    = 1;
   private static final int CMDID_EXIT_APP       = 2;

   private static final Command BACK_COMMAND = new Command(CMDID_BACK_TO_MAIN, Command.BACK, 0);
    private static final Command EXIT_COMMAND = new Command(CMDID_EXIT_APP, Command.STOP, 2);

   private List    menu       = new List("Test Components", Choice.IMPLICIT);
   
   // Main menu items
   private TextBox input       = new TextBox("Your NXT:", "", 16, TextField.ANY);
   private TextBox input2       = new TextBox("Oponent NXT :", "", 16, TextField.ANY);
      
   private Alert    soundAlert    = new Alert("Sound Alert");
   private Alert    exitAlert    = new Alert("Exit");
   
   private Gauge   alertGauge  = new Gauge(null, false, 20, 0);

   
    private Display display;
     
    String NXTName;
    String NXTOponentName;

   private BotSoul _bObj;
   
   public TiltCommsUI(BotSoul bObj){
      NXTName = "NXT";
      NXTOponentName = "NXT";
      input.setText(NXTName);
      input2.setText(NXTOponentName);
      
      _bObj = bObj;
   }

   public TiltCommsUI(BotSoul bObj, String _NXTName,String _NXTOponentName){
      NXTName = _NXTName;
      NXTOponentName = _NXTOponentName;
      input.setText(NXTName);
      input2.setText(NXTOponentName);
      
      _bObj = bObj;
   }   
   
   public void menu(){
      // Create main menu
      menu = new List(NXTWiiVersion, Choice.IMPLICIT);
      menu.append("Set Name", null);
       menu.append("Set Oponent", null);
       menu.append("Connect", null);
       menu.append("NXT Status", null);         
       menu.append("About", null);

       menu.setSelectedIndex(0, true);
       menu.addCommand(EXIT_COMMAND);
       menu.setCommandListener(this);

       input.addCommand(BACK_COMMAND);
       input.setCommandListener(this);

       input2.addCommand(BACK_COMMAND);
       input2.setCommandListener(this);
     
       // Start displaying main menu and handling buttons
       display = Display.getDisplay();
       display.setCurrent(menu);
       display.show(true);      
   }
   
   private void setNXTBrickName(String name){
      if(name.length() >0){
         _bObj.setName(name);
      }
   }
   
   private void showNXTBrickStatus() throws Exception{
      LCD.clear();
      LCD.drawString("Battery / Memory",0,0);
      LCD.drawInt(_bObj.getBattery(),0,1);
      LCD.drawInt(_bObj.getMemory(),0,2);
      LCD.refresh();
   }

   private void showCredits() throws Exception{
      LCD.clear();
      LCD.drawString("Authors:",0,0);
      LCD.drawString("Lawrie &",0,2);
      LCD.drawString("Juan Antonio",0,3);
      LCD.drawString("Brenha. Moral",0,4);
      LCD.drawString("www.lejos.org",0,5);
      LCD.refresh();
   }      
   
   //Event controller
   public void commandAction(Command c, Displayable d){
      NXTName = input.getText();
      NXTOponentName = input2.getText();

      if (c.getCommandId() == CMDID_BACK_TO_MAIN) {

         this.setNXTBrickName(input.getText());

         // Display main menu again
         display.setCurrent(menu);
      } else if (c.getCommandId() == CMDID_EXIT_APP) {
         // Request to exit application
         exitAlert.setType(Alert.ALERT_TYPE_CONFIRMATION);
         exitAlert.setString("Exit " + NXTWiiVersion + "?");
         exitAlert.setCommandListener(this);
         display.setCurrent(exitAlert);
      } else {
         // Handle system commands
         if (d == exitAlert) {
            if (exitAlert.getConfirmation()) {
               display.quit();
            } else {
               display.setCurrent(menu);
            }
         } else if (d == menu) {
            List list = (List) display.getCurrent();
            if (list.getSelectedIndex() == 0) {
               input.setText(NXTName);
               display.setCurrent(input);
            }
            else if (list.getSelectedIndex() == 1) {
               input2.setText(NXTOponentName);
               display.setCurrent(input2);
            }
            else if (list.getSelectedIndex() == 2) {
               try{
                  //Bug detected
                  //this._bObj.controlNXTByTilt(input2.getText());
                  this._bObj.connect(input2.getText());
               }catch(Exception e){
                  LCD.drawString(e.toString(),0,7);
               }
            }
            else if (list.getSelectedIndex() == 3) {
               try{
                  showNXTBrickStatus();
                  Thread.sleep(1000);
               }catch(Exception e){
                  LCD.drawString(e.toString(),0,7);
               }               
            }
            else if (list.getSelectedIndex() == 4) {
               try{
                  showCredits();
                  Thread.sleep(1000);
               }catch(Exception e){
                  LCD.drawString(e.toString(),0,7);
               }               
            }
         }
      }
   }   
   
   //Thread method
    public void run()
    {
        while(true)
        {
            try{               
              this.menu();
           }catch(Exception  e){

           }
        }
    }

}



Code: Select all
import java.io.*;
import lejos.nxt.*;
import lejos.nxt.comm.*;

public class BotSoul {

   private String _botName;
   private int battery;
   private int memory;
   
   private BTUtilities BTUObj;
   
   public BotSoul(){
      BTUtilities BTUObj = new BTUtilities();
   }
   
   private TiltSensor _ts;
   
   public BotSoul(TiltSensor ts){
      BTUtilities BTUObj = new BTUtilities();
      
      _ts = ts;
   }   

   public void setName(String botName){
      _botName = botName;
      BTUObj.setNXTName(botName);
   }

   public String getName(){
      return _botName;
   }

   public int getBattery(){
      battery = Battery.getVoltageMilliVolt();
      return battery;      
   }
   
   public int getMemory(){
      memory = (int)(Runtime.getRuntime().freeMemory());
      return memory;
   }
   
   public void sendCommand(String NXTReceiver){
      try{
         BTUObj.sendCommandExample(NXTReceiver);
      }catch(Exception e){
         LCD.drawString(e.getMessage(),0,7);
      }
   }
   
   public void controlNXTByTilt(String NXTReceiver){
      try{
         BTUObj.controlNXTByTilt(NXTReceiver, this._ts);
      }catch(Exception e){
         LCD.drawString(e.getMessage(),0,7);
      }      
   }
   
   public void connect(String NXTname) throws Exception {
         //TiltSensor controller = new TiltSensor(SensorPort.S1);
         int x, y, z;     
         String name = NXTname; //"NXT";
        
         LCD.drawString("Connecting ...", 0, 7);
         LCD.refresh();
        
         BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);
         BTConnection btc = Bluetooth.connect(btrd);
        
         LCD.clear();
         LCD.drawString("Connected", 0, 0);
         LCD.refresh();
        
         DataInputStream dis = btc.openDataInputStream();
         DataOutputStream dos = btc.openDataOutputStream();
        
         while(true) {
            x = _ts.getXTilt();
            y = _ts.getYTilt();
            z = _ts.getZTilt();
            
            LCD.drawInt(x, 3,  0, 1);
            LCD.drawInt(y, 3, 0, 2);
            LCD.drawInt(z, 3, 0, 3);
            LCD.refresh();
            
            dos.writeByte(x);
            dos.writeByte(y);
            dos.writeByte(z);
            dos.flush();
            byte ack = dis.readByte();
         }
      }   
}



Code: Select all

import java.io.*;
import java.util.*;
import lejos.nxt.*;
import lejos.nxt.comm.*;

public class BTUtilities {

   public BTUtilities(){
      
   }
   
   public void setNXTName(String NXTName){
      Bluetooth.setFriendlyName(getBytes(NXTName));       
   }
   
   public byte[] getBytes(String BTDeviceName){
      byte[] nameBytes = new byte[16];
      
      for(int i=0;i<BTDeviceName.length();i++){
         nameBytes[i] = (byte) BTDeviceName.charAt(i);
      }
      nameBytes[BTDeviceName.length()] = 0;

      return nameBytes;
   }
   
   public void getDeviceList(){
      byte[] cod = {0,0,8,4}; // Toy, Robot
      LCD.clear();
      LCD.drawString("Searching ...", 0, 0);
      LCD.refresh();
      Vector devList = Bluetooth.inquire(5, 10,cod);
      
      if (devList.size() > 0) {
         String[] names = new String[devList.size()];
         
         LCD.clear();
         LCD.drawString("Device List:",0,0);
         for (int i = 0; i < devList.size(); i++) {
            BTRemoteDevice btrd = ((BTRemoteDevice) devList.elementAt(i));
            
            names[i] = btrd.getFriendlyName();
            LCD.drawString(names[i],0,i+1);
         }
         LCD.refresh();
      } else {
         LCD.clear();
         LCD.drawString("no devices", 0, 0);
         LCD.refresh();
         try {
            Thread.sleep(2000);
         }catch (InterruptedException e){}
      }   
   }
   
   public void discoverNXTBricks(){
      byte[] cod = {0,0,8,4}; // Toy, Robot
      LCD.clear();
      LCD.drawString("Searching ...", 0, 0);
      LCD.refresh();
      Vector devList = Bluetooth.inquire(5, 10,cod);
      
      if (devList.size() > 0) {
         String[] names = new String[devList.size()];
         
         LCD.clear();
         LCD.drawString("Device List:",0,0);
         for (int i = 0; i < devList.size(); i++) {
            BTRemoteDevice btrd = ((BTRemoteDevice) devList.elementAt(i));
            
            Bluetooth.removeDevice(btrd);
            Bluetooth.addDevice(btrd);            
            
            names[i] = btrd.getFriendlyName();
            LCD.drawString(names[i],0,i+1);
         }
         LCD.refresh();
      } else {
         LCD.clear();
         LCD.drawString("no devices", 0, 0);
         LCD.refresh();
         try {
            Thread.sleep(2000);
         }catch (InterruptedException e){}
      }      
   }
   
   public void sendCommandExample(String NXTReceiver) throws Exception{
      LCD.drawInt(0,0,5);
      //LCD.drawString("Try to connect...", 0, 6);
      LCD.refresh();
      
      //Bluetooth.
      BTRemoteDevice btrd = Bluetooth.getKnownDevice(NXTReceiver);

      BTConnection btc = Bluetooth.connect(btrd);
      
      //LCD.clear();
      LCD.drawInt(1,0,5);
      //LCD.drawString("                 ",0,6);
      //LCD.drawString("Connected", 0, 6);
      LCD.refresh();
      
      DataInputStream dis = btc.openDataInputStream();
      DataOutputStream dos = btc.openDataOutputStream();
            
      for(int i=0;i<100;i++) {
         try {
            LCD.drawInt(i*30000, 0, 6);
            LCD.refresh();
            dos.writeInt(i*30000);
            dos.flush();         
         } catch (IOException ioe) {
            LCD.drawString("Exception", 0, 7);
            LCD.refresh();
         }
         
         try {
            LCD.drawInt(dis.readInt(),0,7);
            LCD.refresh();
         } catch (IOException ioe) {
         }
      }
      
      try {
         dis.close();
         dos.close();
         btc.close();
      } catch (IOException ioe) {
      }      
   }
   
   public boolean existNXTBrick(String NXTBrickName){
      boolean flagDetected = false;
      
      Vector devList = Bluetooth.getKnownDevicesList();
      if (devList.size() > 0) {
         String[] names = new String[devList.size()];
         for (int i = 0; i < devList.size(); i++) {
            BTRemoteDevice btrd = ((BTRemoteDevice) devList.elementAt(i));
            names[i] = btrd.getFriendlyName();
            if(names[i] == NXTBrickName){
               flagDetected = false;
               break;
            }
         }
      }
      
      return flagDetected;
   }
   
   public void controlNXTByTilt(String NXTReceiver, TiltSensor controller) throws Exception{
         //TiltSensor controller = new TiltSensor(SensorPort.S1);
         int x, y, z;     
         String name = NXTReceiver;
        
         LCD.drawString("Connecting ...", 0, 0);
         LCD.refresh();
        
        
         BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);
         Bluetooth.addDevice(btrd);
         BTConnection btc = Bluetooth.connect(btrd);
        
         LCD.clear();
         LCD.drawString("Connected", 0, 0);
         LCD.refresh();
        
         DataInputStream dis = btc.openDataInputStream();
         DataOutputStream dos = btc.openDataOutputStream();
        
         while(true) {
            x = controller.getXTilt();
            y = controller.getYTilt();
            z = controller.getZTilt();
            
            LCD.drawInt(x, 3,  0, 1);
            LCD.drawInt(y, 3, 0, 2);
            LCD.drawInt(z, 3, 0, 3);
            LCD.refresh();
            
            dos.writeByte(x);
            dos.writeByte(y);
            dos.writeByte(z);
            dos.flush();
            byte ack = dis.readByte();
         }      
   }
}


[/code]
Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby esmetaman » Sat Nov 17, 2007 9:34 pm

I noticed that if try to execute the method that connect with another brick, then NXT BRICK crash.

I have a hypothesis in relation this fact:

MAIN CLASS
- thread ui
- thread bot
- class BTUtilites

is it possible due to a memory problem?

try to use the method: this._bObj.controlNXTByTilt in TiltCommsUI.java

Code: Select all
//Bug detected
//this._bObj.controlNXTByTilt(input2.getText());
this._bObj.connect(input2.getText());


I noticed that if you doesnt add another brick in Tilt NXT then Tilt NXT crash.

In BT methods it is neccesary to improve connect method, because if RemoteSteer doesnt run in NXT brick 2, TiltController BRICK think that it is connected with NXT brick 2.

I will try to improve method to turn bot in NXT Brick 2

Can you explain the following statement:

byte ack = dis.readByte();

and

dos.writeByte((byte) 0xFF); // Ack
dos.flush();

Thanks lawrie
Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby esmetaman » Sat Nov 17, 2007 11:01 pm

I have updated TiltComm to send an angle from Compass Sensor to turn left and right:

Code: Select all
import lejos.nxt.*;

public class TiltComms {

   /**
    * @param args
    */
   public static void main(String[] args) {

      try{
         TiltSensor ts = new TiltSensor(SensorPort.S1);
         CompassSensor cmps = new CompassSensor(SensorPort.S2);
         
         BotSoul bObj = new BotSoul(ts,cmps);
         TiltCommsUI UIObj = new TiltCommsUI(bObj,"NXT","NXT");
         UIObj.start();
      }catch(Exception e){
         
      }
   }
}



Code: Select all
import javax.microedition.lcdui.*;
import lejos.nxt.*;

public class TiltCommsUI extends Thread implements CommandListener{

   String NXTWiiVersion = "NXT Wii";
   
   private static final int CMDID_BACK_TO_MAIN    = 1;
   private static final int CMDID_EXIT_APP       = 2;

   private static final Command BACK_COMMAND = new Command(CMDID_BACK_TO_MAIN, Command.BACK, 0);
    private static final Command EXIT_COMMAND = new Command(CMDID_EXIT_APP, Command.STOP, 2);

   private List    menu       = new List("Test Components", Choice.IMPLICIT);
   
   // Main menu items
   private TextBox input       = new TextBox("Your NXT:", "", 16, TextField.ANY);
   private TextBox input2       = new TextBox("Oponent NXT :", "", 16, TextField.ANY);
      
   private Alert    soundAlert    = new Alert("Sound Alert");
   private Alert    exitAlert    = new Alert("Exit");
   
   private Gauge   alertGauge  = new Gauge(null, false, 20, 0);

   
    private Display display;
     
    String NXTName;
    String NXTOponentName;

   private BotSoul _bObj;
   
   public TiltCommsUI(BotSoul bObj){
      NXTName = "NXT";
      NXTOponentName = "NXT";
      input.setText(NXTName);
      input2.setText(NXTOponentName);
      
      _bObj = bObj;
   }

   public TiltCommsUI(BotSoul bObj, String _NXTName,String _NXTOponentName){
      NXTName = _NXTName;
      NXTOponentName = _NXTOponentName;
      input.setText(NXTName);
      input2.setText(NXTOponentName);
      
      _bObj = bObj;
   }   
   
   public void menu(){
      // Create main menu
      menu = new List(NXTWiiVersion, Choice.IMPLICIT);
      menu.append("Set Name", null);
       menu.append("Set Oponent", null);
       menu.append("Connect", null);
       menu.append("NXT Status", null);         
       menu.append("About", null);

       menu.setSelectedIndex(0, true);
       menu.addCommand(EXIT_COMMAND);
       menu.setCommandListener(this);

       input.addCommand(BACK_COMMAND);
       input.setCommandListener(this);

       input2.addCommand(BACK_COMMAND);
       input2.setCommandListener(this);
     
       // Start displaying main menu and handling buttons
       display = Display.getDisplay();
       display.setCurrent(menu);
       display.show(true);      
   }
   
   private void setNXTBrickName(String name){
      if(name.length() >0){
         _bObj.setName(name);
      }
   }
   
   private void showNXTBrickStatus() throws Exception{
      LCD.clear();
      LCD.drawString("Battery / Memory",0,0);
      LCD.drawInt(_bObj.getBattery(),0,1);
      LCD.drawInt(_bObj.getMemory(),0,2);
      LCD.refresh();
   }

   private void showCredits() throws Exception{
      LCD.clear();
      LCD.drawString("Authors:",0,0);
      LCD.drawString("Lawrie Griffiths",0,2);
      LCD.drawString("Juan Antonio",0,3);
      LCD.drawString("Brenha Moral",0,4);
      LCD.drawString("www.lejos.org",0,5);
      LCD.refresh();
   }      
   
   //Event controller
   public void commandAction(Command c, Displayable d){
      NXTName = input.getText();
      NXTOponentName = input2.getText();

      if (c.getCommandId() == CMDID_BACK_TO_MAIN) {

         this.setNXTBrickName(input.getText());

         // Display main menu again
         display.setCurrent(menu);
      } else if (c.getCommandId() == CMDID_EXIT_APP) {
         // Request to exit application
         exitAlert.setType(Alert.ALERT_TYPE_CONFIRMATION);
         exitAlert.setString("Exit " + NXTWiiVersion + "?");
         exitAlert.setCommandListener(this);
         display.setCurrent(exitAlert);
      } else {
         // Handle system commands
         if (d == exitAlert) {
            if (exitAlert.getConfirmation()) {
               display.quit();
            } else {
               display.setCurrent(menu);
            }
         } else if (d == menu) {
            List list = (List) display.getCurrent();
            if (list.getSelectedIndex() == 0) {
               input.setText(NXTName);
               display.setCurrent(input);
            }
            else if (list.getSelectedIndex() == 1) {
               input2.setText(NXTOponentName);
               display.setCurrent(input2);
            }
            else if (list.getSelectedIndex() == 2) {
               try{
                  //Bug detected
                  //this._bObj.controlNXTByTilt(input2.getText());
                  this._bObj.connect(input2.getText());
               }catch(Exception e){
                  LCD.drawString(e.toString(),0,7);
               }
            }
            else if (list.getSelectedIndex() == 3) {
               try{
                  showNXTBrickStatus();
                  Thread.sleep(1000);
               }catch(Exception e){
                  LCD.drawString(e.toString(),0,7);
               }               
            }
            else if (list.getSelectedIndex() == 4) {
               try{
                  showCredits();
                  Thread.sleep(1000);
               }catch(Exception e){
                  LCD.drawString(e.toString(),0,7);
               }               
            }
         }
      }
   }   
   
   //Thread method
    public void run()
    {
        while(true)
        {
            try{               
              this.menu();
           }catch(Exception  e){

           }
        }
    }

}



Code: Select all

import java.io.*;
import lejos.navigation.*;
import lejos.nxt.*;
import lejos.nxt.comm.*;

public class BotSoul {

   private String _botName;
   private int battery;
   private int memory;
   
   private BTUtilities BTUObj;
   
   /*
    * CONSTRUCTORS
    *
    */
   
   public BotSoul(){
      BTUtilities BTUObj = new BTUtilities();
   }
   
   private TiltSensor _ts;
   
   public BotSoul(TiltSensor ts){
      BTUtilities BTUObj = new BTUtilities();
      
      _ts = ts;
   }

   CompassSensor _cmps;
   
   public BotSoul(TiltSensor ts,CompassSensor cmps){
      BTUtilities BTUObj = new BTUtilities();
      
      _ts = ts;
      _cmps = cmps;
   }   
   
   private Pilot _p;
   
   public BotSoul(Pilot p){      
      _p = p;
   }   
   
   /*
    * PUBLIC METHODS
    *
    */
   
   public void setName(String botName){
      _botName = botName;
      BTUObj.setNXTName(botName);
   }

   public String getName(){
      return _botName;
   }

   public int getBattery(){
      battery = Battery.getVoltageMilliVolt();
      return battery;      
   }
   
   public int getMemory(){
      memory = (int)(Runtime.getRuntime().freeMemory());
      return memory;
   }
   
   public void sendCommand(String NXTReceiver){
      try{
         BTUObj.sendCommandExample(NXTReceiver);
      }catch(Exception e){
         LCD.drawString(e.getMessage(),0,7);
      }
   }
   
   public void controlNXTByTilt(String NXTReceiver){
      try{
         BTUObj.controlNXTByTilt(NXTReceiver, this._ts);
      }catch(Exception e){
         LCD.drawString(e.getMessage(),0,7);
      }      
   }
   
   public void connect(String NXTname) throws Exception {
      //TiltSensor controller = new TiltSensor(SensorPort.S1);
      int x, y, z;
      int a;
      String name = NXTname; //"NXT";
     
      LCD.drawString("Connecting ...", 0, 7);
      LCD.refresh();
     
      BTRemoteDevice btrd = Bluetooth.getKnownDevice(name);
      BTConnection btc = Bluetooth.connect(btrd);
     
      LCD.clear();
      LCD.drawString("Connected", 0, 0);
      LCD.refresh();
     
      DataInputStream dis = btc.openDataInputStream();
      DataOutputStream dos = btc.openDataOutputStream();
           
      while(true) {
         x = _ts.getXTilt();
         y = _ts.getYTilt();
         z = _ts.getZTilt();
         
         a = (int) _cmps.getDegreesCartesian();
         
         LCD.drawInt(x, 3, 0, 2);
         LCD.drawInt(y, 3, 0, 3);
         LCD.drawInt(z, 3, 0, 4);
         LCD.drawInt(a, 3, 0, 6);
         LCD.refresh();
         
         dos.writeByte(x);
         dos.writeByte(y);
         dos.writeByte(z);
         dos.writeByte(a);
         dos.flush();
         byte ack = dis.readByte();
      }
   }
   
   public void setSpeed(int speed){
      _p.setSpeed(speed);
   }

   public void forward(){
      _p.forward();
   }   

   public void backward(){
      _p.backward();
   }   
   
   public void setSteer(int speed){
      _p.steer(speed);
   }
   
   public void rotate(int angle){
      _p.rotate(angle);
   }
}

Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby esmetaman » Sun Nov 18, 2007 12:07 am

I have updated the thread that it manage data from TiltComms

Code: Select all
import lejos.nxt.*;
import lejos.nxt.comm.*;
import java.io.*;

public class RemoteReceiverListener extends Thread{

   private String MESSAGE_AWAITING = "Awaiting";
   private String MESSAGE_CONNECTED = "Connected";
   
   //private Boolean NXT_CONNECTED = false;
   
   private Thread _MENU;
   
   private BTConnection btc;
   
   private InputStream is;
   private OutputStream os;
   private DataInputStream dis;
   private DataOutputStream dos;
   
   private BotSoul _bObj;
   
   public RemoteReceiverListener()throws Exception{
      
   }   

   public RemoteReceiverListener(BotSoul bObj)throws Exception{
      _bObj = bObj;
   }   
   
   private void showMessage(String message){
      //.clear();
      LCD.drawString(message,0,1);
      LCD.refresh();
   }
   
    public void run()
    {
       try{
          String connected = "Connected";
          String waiting = "Waiting";
          LCD.drawString(waiting,0,0);
        LCD.refresh();
      
        BTConnection btc = Bluetooth.waitForConnection();
         
        LCD.clear();
        LCD.drawString(connected,0,0);
        LCD.refresh();   

         DataInputStream dis = new DataInputStream(btc.openInputStream());
         DataOutputStream dos = new DataOutputStream(btc.openOutputStream());
   
         int oldAngle = 0;
         boolean flagRunOnce = false;
   
         int speed = 0;
        
         while (true) {
                   
            int x = dis.readByte();
            int y = dis.readByte() & 0xFF;
            int z = dis.readByte() & 0xFF;
            int a = dis.readByte() & 0xFF;
            
            if(flagRunOnce == false){
               oldAngle = a;
               flagRunOnce = true;
            }
                    
            dos.writeByte((byte) 0xFF); // Ack
            dos.flush();
             
            //Si no hay giro
            //if((y <=15) && (y >=240)){
            
               if((x >= 0) && (x<=125)){
                  _bObj.forward();
                 
                  //125 -> 100
                  //x -> ?
                  speed = (int)((x*100) / 125)*30;
                  _bObj.setSpeed(speed);
               }else{
                  _bObj.backward();
                 
                  //255 -> 100
                  //x -> ?
                  speed = (int)((x*100) / 255)*30;
                  _bObj.setSpeed(speed);
         
               }
            //}else{
               if((y >= 0) && (y<=125)){
                  if(y >=15){
                     _bObj.stop();
                     _bObj.rotate(y);
                     _bObj.forward();
                  }
               }else{
                  if(y <=240){
                     _bObj.stop();
                     _bObj.rotate(y-255);
                     _bObj.forward();
                  }
               }
            //}
            
            LCD.drawInt(x,4, 0,1);
            LCD.drawInt(y,4, 0,2);
            LCD.drawInt(z,4, 0,3);
            LCD.drawInt(a,4, 0,4);
            LCD.drawInt(speed, 5, 0, 6);
            LCD.refresh();
            
         }
   
    }catch(Exception ex){
       
    }
    }
}


Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby lawrie » Sun Nov 18, 2007 8:37 am

Can you explain the following statement:

byte ack = dis.readByte();

and

dos.writeByte((byte) 0xFF); // Ack
dos.flush();


It is a good idea to acknowledge data that is sent, by sending an "Ack" message back to the sender. If you don't do this the sender is likely to send data faster than the receiver can process it, and comms buffers will fill up. I am not sure that the leJOS Bluetooth code copes with streaming data without acknowledgments to slow it down. You may lose data if you do not use acknowledgements or other replies.
lawrie
leJOS Team Member
 
Posts: 934
Joined: Mon Feb 05, 2007 1:27 pm

Postby lawrie » Sun Nov 18, 2007 8:52 am

I noticed that if you doesnt add another brick in Tilt NXT then Tilt NXT crash.

In BT methods it is neccesary to improve connect method, because if RemoteSteer doesnt run in NXT brick 2, TiltController BRICK think that it is connected with NXT brick 2.

I will try to improve method to turn bot in NXT Brick 2


You must run the receiver program (RemoteSteer) first. The leJOS menu program waits for a connection over Bluetooth and treats data that it receives as LCP commands. This is how it implements program upload etc. If you run TiltController when the receiver brick is running the menu, the connection will succeed, but the reeceiver brick will interpret all the data sent as LCP commands and will probably throw an exception.

This is a bug in Connect() which I plan to fix in the next release. Currently it interprets any replies it gets from a connect request as success - even failure replies. This means that if the target brick does not exist or if it has not been added to the Device menu on the sender machine, then successful connection will be reported, even when the connection has failed. I don't think this happens if the receiver brick is just switched off - in this case the sender just hangs trying to connect.
lawrie
leJOS Team Member
 
Posts: 934
Joined: Mon Feb 05, 2007 1:27 pm

Postby esmetaman » Sun Nov 18, 2007 1:20 pm

Hi,

Lawrie, thanks for your advice with ack sentence. ack is used as flag to know that it is the moment to send another command.

I have tried my code, but I have noticed that in some moment the communication broke. I am going to test a timer thread that use a shared variable between timer thread and Tilt thread to maintain the communication.

If system detect that in 10 seconds, doesnt receive any communication, ack for example then close the communication and try to reconnect. this mechanics will try to do in receiver, in RemoteListener thread.

can you explain this code:

Code: Select all
            int y = dis.readByte() & 0xFF;
            int z = dis.readByte() & 0xFF;


I would like to know the meaning of 0xFF

Next week I will try to show photos and video with system.

Thanks
Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby esmetaman » Sun Nov 18, 2007 1:28 pm

I don't think this happens if the receiver brick is just switched off - in this case the sender just hangs trying to connect.


Hi Lawrie,

I tested now this behavior. When NXT Brick tries to connect with NXT Brick 2, althougth this one is off, NXT Brick change the state to connected. It is a pity.

Un abrazo
Juan Antonio Breña Moral
http://www.juanantonio.info/lejos-ebook/
https://github.com/jabrena/livingrobots
http://www.iloveneutrinos.com/
User avatar
esmetaman
Advanced Member
 
Posts: 311
Joined: Wed Sep 13, 2006 12:16 am
Location: Madrid, Spain

Postby lawrie » Sun Nov 18, 2007 10:12 pm

can you explain this code:


int y = dis.readByte() & 0xFF;
int z = dis.readByte() & 0xFF;



dis.readByte() returns a signed byte value from -128 to +127. The & 0xFF turns it into an integer value from 0-255.
lawrie
leJOS Team Member
 
Posts: 934
Joined: Mon Feb 05, 2007 1:27 pm

Postby PatrickLismore » Thu Nov 22, 2007 9:24 pm

brilliant project, well impressed
User avatar
PatrickLismore
Active User
 
Posts: 81
Joined: Tue Oct 16, 2007 7:28 pm
Location: Prague


Return to NXJ Projects

Who is online

Users browsing this forum: No registered users and 1 guest

more stuff