Post your NXJ projects, project ideas, etc here!
Moderators: roger, 99jonathan, imaqine
by Doug Fane » Mon Jan 30, 2012 1:47 am
I made something that allows you to use one NXT as a remote to control another using buetooth. All the controls and directions are comments in the code. I broke my phone, so I cannot upload pictures or video at the moment, but I will do so as soon as possible. This program works on my NXTs and the setup directions are simply the steps I took to get the devices set up. Please let me know if you have any issues.
The files can be downloaded here:
http://www.tiarbi.com/lejos/RCNXT.zipRCNXT.java
- Code: Select all
/*
************RCNXT***************
* FUNCTION:
* This class allows an nxt rig to act
* as a radio controlled car when used
* with the compatable controller class
*
* SETUP:
* Designed for a four wheeled/tracked setup
* with differential steering ability. Motor A
* powers the left wheel/track and Motor B powers
* the right wheel/track.
*
* USE:
* Run the RCNXT program on the cart vehicle
* before running the controller program on
* the controlling NXT
*
* PACKET INTERPRETATION:
* example packet: 897612
* -Because the packet is positive, the emergency brake is NOT engaged
* -The first two digits (89) control the left motor power
* -The thrid and fourth digits (76) control the right motor power
* -The fifth digit (1) controls the left motor direction
* -A value of 1 indicates backwards spinning
* -The final digit (2) controls the right motor direction
* -A value of 2 indicates forward spinning
* =In this example, the packet tells the cart to spin with the
* left motor spinning backwards at a speed of 89 and the right
* motor spinning forward at a speed of 76
*
* example packet: -348222
* -Because the packet is negative, the emergency brake IS engaged
* -The first two digits (34) control the left motor power
* -The thrid and fourth digits (82) control the right motor power
* -The fifth digit (2) controls the left motor direction
* -A value of 2 indicates forward spinning
* -The final digit (2) controls the right motor direction
* -A value of 2 indicates forward spinning
* =In this example, the packet tells the cart to disengage both
* motors becuase the emergency brake was engaged.
*/
import lejos.nxt.Motor;
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.comm.BTConnection;
import lejos.nxt.comm.Bluetooth;
import java.io.*;
import java.lang.Math;
public class RCNXT {
public static void main(String[] args) throws Exception{
//BEGIN VARIABLE DEFINITIONS
int right = 0; //right motor direction
int left = 0; //left motor direction
int rpower = 0; //right motor power
int lpower = 0; //left motor power
int p = 0; //packet received from controller
//END VARIABLE DEFINITIONS
LCD.clear();
LCD.drawString("Connecting...", 2, 1);
LCD.refresh();
BTConnection btc = Bluetooth.waitForConnection();
LCD.clear();
LCD.drawString("Connected", 2, 1);
DataInputStream dis = btc.openDataInputStream();
Motor.B.flt();
Motor.A.flt();
while(!Button.ESCAPE.isPressed()){
p = dis.readInt(); //gets packet from controller
if (p > 0){
LCD.drawInt(p, 4, 3);
right = p % 10; //right motor direction is the sixth digit
p = p / 10;
left = p % 10; //left motor direction is the fith digit
p = p / 10;
rpower = p % 100; //right motor power is always the third and fourth digit
p = p / 100;
lpower = p; //left motor power is always the first two digits
rpower *= 8;
lpower *= 8; //raw input from throttles is multiplied to match full range of power
LCD.drawInt(right, 1, 4);
LCD.drawInt(left, 3, 4);
LCD.drawInt(rpower, 0, 5);
LCD.drawInt(lpower, 6, 5);
Motor.B.setSpeed((float)rpower);
Motor.A.setSpeed((float)lpower);
if (right == 2){ //(numeral 2) corresponds to forward power
Motor.B.forward();
}
else{
Motor.B.backward(); //(numeral 1) corresponds to backward power
}
if (left == 2){
Motor.A.forward();
}
else{
Motor.A.backward();
}
}
if (p < 0){
Motor.B.flt(); //if the packet is negative, then the emergency brake is in place
Motor.A.flt(); //flt is used in place of stop becuase it responds faster
}
}
Thread.sleep(2000);
LCD.clear();
LCD.drawString("Close Connection", 0, 1);
dis.close();
btc.close();
Thread.sleep(2000);
}
}
Controller.java
- Code: Select all
/*
************RCNXT***************
* FUNCTION:
* This class allows an nxt rig to act
* as a radio controlled car when used
* with the compatable controller class
*
* SETUP:
* Designed for a four wheeled/tracked setup
* with differential steering ability. Motor A
* powers the left wheel/track and Motor B powers
* the right wheel/track.
*
* USE:
* Run the RCNXT program on the cart vehicle
* before running the controller program on
* the controlling NXT
*
* PACKET INTERPRETATION:
* example packet: 897612
* -Because the packet is positive, the emergency brake is NOT engaged
* -The first two digits (89) control the left motor power
* -The thrid and fourth digits (76) control the right motor power
* -The fifth digit (1) controls the left motor direction
* -A value of 1 indicates backwards spinning
* -The final digit (2) controls the right motor direction
* -A value of 2 indicates forward spinning
* =In this example, the packet tells the cart to spin with the
* left motor spinning backwards at a speed of 89 and the right
* motor spinning forward at a speed of 76
*
* example packet: -348222
* -Because the packet is negative, the emergency brake IS engaged
* -The first two digits (34) control the left motor power
* -The thrid and fourth digits (82) control the right motor power
* -The fifth digit (2) controls the left motor direction
* -A value of 2 indicates forward spinning
* -The final digit (2) controls the right motor direction
* -A value of 2 indicates forward spinning
* =In this example, the packet tells the cart to disengage both
* motors becuase the emergency brake was engaged.
*/
import lejos.nxt.Motor;
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.comm.BTConnection;
import lejos.nxt.comm.Bluetooth;
import java.io.*;
import java.lang.Math;
public class RCNXT {
public static void main(String[] args) throws Exception{
//BEGIN VARIABLE DEFINITIONS
int right = 0; //right motor direction
int left = 0; //left motor direction
int rpower = 0; //right motor power
int lpower = 0; //left motor power
int p = 0; //packet received from controller
//END VARIABLE DEFINITIONS
LCD.clear();
LCD.drawString("Connecting...", 2, 1);
LCD.refresh();
BTConnection btc = Bluetooth.waitForConnection();
LCD.clear();
LCD.drawString("Connected", 2, 1);
DataInputStream dis = btc.openDataInputStream();
Motor.B.flt();
Motor.A.flt();
while(!Button.ESCAPE.isPressed()){
p = dis.readInt(); //gets packet from controller
if (p > 0){
LCD.drawInt(p, 4, 3);
right = p % 10; //right motor direction is the sixth digit
p = p / 10;
left = p % 10; //left motor direction is the fith digit
p = p / 10;
rpower = p % 100; //right motor power is always the third and fourth digit
p = p / 100;
lpower = p; //left motor power is always the first two digits
rpower *= 8;
lpower *= 8; //raw input from throttles is multiplied to match full range of power
LCD.drawInt(right, 1, 4);
LCD.drawInt(left, 3, 4);
LCD.drawInt(rpower, 0, 5);
LCD.drawInt(lpower, 6, 5);
Motor.B.setSpeed((float)rpower);
Motor.A.setSpeed((float)lpower);
if (right == 2){ //(numeral 2) corresponds to forward power
Motor.B.forward();
}
else{
Motor.B.backward(); //(numeral 1) corresponds to backward power
}
if (left == 2){
Motor.A.forward();
}
else{
Motor.A.backward();
}
}
if (p < 0){
Motor.B.flt(); //if the packet is negative, then the emergency brake is in place
Motor.A.flt(); //flt is used in place of stop becuase it responds faster
}
}
Thread.sleep(2000);
LCD.clear();
LCD.drawString("Close Connection", 0, 1);
dis.close();
btc.close();
Thread.sleep(2000);
}
}
-
Doug Fane
- New User
-
- Posts: 9
- Joined: Sun Dec 04, 2011 11:20 pm
by Doug Fane » Mon Jan 30, 2012 4:20 pm
UPDATE: I will be releasing a new version shortly with support for a ball shooter to be mounted on the front of the RC cart. I will be re-writing the program so as follows:
Controller.java:
-will now send the numeral 3 in the motor direction digits to indicate the brake being applied to the motor
-will send the packet as a negative integer if the fire ball button is derpressed
RCNXT.java:
-will now interpret a numeral 3 in the motor direction digit to cause an application of the brake to the indicated motor
-will now interpret a negative packet as a command to fire a ball (rotate Motor C exactly 360 degrees at maximum speed)
The updated code is being written now and will be posted after testing (some time tomorrow)
-
Doug Fane
- New User
-
- Posts: 9
- Joined: Sun Dec 04, 2011 11:20 pm
by Doug Fane » Wed Feb 15, 2012 2:24 pm
I know it has been a while, but I cleaned everything up and added shooting functionality. The new instructions are part of the source code.
- Code: Select all
/*
********CONTROLLER*********
* FUNCTION:
* This class allows an NXT to be used
* as a remote to control another NXT
* via bluetooth
*
* SETUP:
* Touch sensors are attached to sensor
* ports 1 and 2. Motors A and B are
* attached in such a way that the user
* can freely turn them.
*
* USE:
* Pair the controller NXT with the desired
* cart NXT. Then turn off both NXTs and
* restart them. Run the RCNXT program on
* the cart NXT, once you see "Connecting..."
* on the cart NXT, run this program on the
* controller.
*
* CONTROLS:
* Touch Sensor 1 controls the Throttle Lock. If
* activated, the two motors will both spin at the
* speed of the left throttle. The right button
* controls the ball launcher. The launcher will
* fire once for every push of the button. The
* center (orange) button acts as the brake.
* pressing once will cause the cart to stop,
* pressing again will return control of the cart
* to the throttles.
*
*/
import lejos.nxt.*;
import lejos.nxt.comm.*;
import java.io.*;
import javax.bluetooth.*;
public class Controller {
public static void main(String[] args) throws Exception {
//BEGIN VARIABLE DEFINITIONS
int lsend = 0; //direction of left motor
int rsend = 0; //direction of right motor
int ltsend = 0; //left motor power
int rtsend = 0; //right motor power
int toSend = 0; //packet sent to RCNXT
int p = 0; //packet received from Cart
int leftThrottleZero = 0;
int rightThrottleZero = 0;
int curLeftThrottle = 0;
int curRightThrottle = 0;
boolean fire = false; //fires a ball
boolean brake = false; //emergency brake
boolean send = false; //checks for change in input
boolean throttleLock = false; //locks the motors at the same speed
boolean leftLock = true; //tells which motor is the master when locked
boolean centerButton = false; //indicates position of center button
InputThread input;
Thread inThread;
TouchSensor leftButton = new TouchSensor(SensorPort.S1);
TouchSensor rightButton = new TouchSensor(SensorPort.S2);
//END VARIABLE DEFINITIONS
LCD.clear();
LCD.drawString("Connecting...", 2, 1);
RemoteDevice bt = Bluetooth.getKnownDevice("NXT"); //connects to RCNXT
if (bt == null){ //checks for non-existant device
LCD.clear();
LCD.drawString("device not found", 0, 1);
Thread.sleep(2000);
System.exit(1);
}
BTConnection btc = Bluetooth.connect(bt);
if (btc == null){ //checks for failedd connection
LCD.clear();
LCD.drawString("connection fail", 0, 1);
Thread.sleep(2000);
System.exit(1);
}
LCD.clear();
LCD.drawString("CONTROLLER ACTIVE", 0, 0);
Thread.sleep(500);
DataOutputStream dos = btc.openDataOutputStream(); //opens stream to RCNXT
DataInputStream dis = btc.openDataInputStream(); //opens import stream to receive data from cart
input = new InputThread(dis);
inThread = new Thread(input);
inThread.start();
LCD.clear();
LCD.drawString("Move throttles to", 0, 0);
LCD.drawString("zero position and", 0, 1);
LCD.drawString("press enter", 0, 2);
LCD.drawString("Tacho count:", 0, 5);
while (!Button.ENTER.isPressed()){
curLeftThrottle = Motor.B.getTachoCount();
curRightThrottle = Motor.C.getTachoCount(); //gets the desired starting position of the throttles
LCD.drawInt(curLeftThrottle, 1, 6);
LCD.drawInt(curRightThrottle, 5, 6);
}
leftThrottleZero = curLeftThrottle;
rightThrottleZero = curRightThrottle;
LCD.clear();
LCD.drawString("Connected", 2, 1);
while(!Button.ESCAPE.isPressed()){
if (Motor.B.getTachoCount() != curLeftThrottle){ //gets the left motor power
curLeftThrottle = Motor.B.getTachoCount();
ltsend = curLeftThrottle - leftThrottleZero;
send = true;
}
if (Motor.C.getTachoCount() != curRightThrottle){ //gets the right motor power
curRightThrottle = Motor.C.getTachoCount();
rtsend = curRightThrottle - rightThrottleZero;
send = true;
}
if (leftButton.isPressed()){ //checks the emergency brake
if (!throttleLock){
throttleLock = true;
send = true;
}
}
else{
if (throttleLock){
throttleLock = false;
send = true;
}
}
if (rightButton.isPressed()){ //checks if the fire button is depressed
if (!fire){
fire = true;
send = true;
}
}
else{
if (fire){
fire = false;
send = true;
}
}
if (Button.RIGHT.isPressed()){
leftLock = false;
send = true;
}
if (Button.LEFT.isPressed()){
leftLock = true;
send = true;
}
if (Button.ENTER.isPressed()){
if (!centerButton){
centerButton = true;
if (brake){
brake = false;
send = true;
}
else{
brake = true;
send = true;
}
}
}
else{
if (centerButton){
centerButton = false;
}
}
if (send){ //sends packet to the RCNXT
toSend = makePacket(ltsend, rtsend, brake, fire, throttleLock, leftLock);
dos.writeInt(toSend);
dos.flush();
send = false;
}
LCD.drawString(" ", 0, 0);
LCD.drawInt(toSend, 0, 0);
LCD.drawString(" ", 0, 2);
if (leftLock){
LCD.drawString("LEFT", 0, 2);
}
else{
LCD.drawString("RIGHT", 0, 2);
}
if (brake){
LCD.drawString("BRAKE", 8, 2);
}
LCD.drawString(" ", 0, 5);
if (throttleLock){
LCD.drawString("LOCK", 0, 5);
}
p = input.readInt();
if (p != 0){
LCD.drawInt(p, 0, 7);
}
}
dos.writeInt(999999);
dos.flush();
LCD.clear();
LCD.drawString("Finished", 0, 1);
Thread.sleep(4000);
dos.close();
btc.close();
}
public static int makePacket(int a, int b, boolean brake, boolean fire, boolean throttleLock, boolean leftLock){
int pak = 0;
int ld = 2; //by default both motors drive forward (numeral 2)
int rd = 2;
if (throttleLock){
if (leftLock){
b = a;
}
else{
a = b;
}
}
if (a < 0){ //if either throttle position is below zero
ld = 1; //then the direction number is changed to backwards (numeral 1)
a *= -1;
}
if (b < 0){
rd = 1;
b *= -1;
}
if (brake){
ld = 3;
rd = 3;
}
if (a > 99){
a = 99; //sets maximum throttle to 99 so that data can be sent with 2 digits
} //this is aceptable because the motors cannot go faster than this anyway
if (b > 99){
b = 99;
}
pak += (a * 10000); //left motor power is always the first two digits (assume a zero for values < 10)
pak += (b * 100); //right motor power is always the third and fourth digits
pak += (ld * 10); //left motor direction is the fifth digit
pak += rd; //right motor direction is the last (sixth) digit
if (fire){
pak *= -1;
fire = false;
}
return pak;
}
}
- Code: Select all
/*
************RCNXT***************
* FUNCTION:
* This class allows an nxt rig to act
* as a radio controlled car when used
* with the compatable controller class
*
* SETUP:
* Designed for a four wheeled/tracked setup
* with differential steering ability. Motor A
* powers the left wheel/track and Motor B powers
* the right wheel/track.
*
* USE:
* Run the RCNXT program on the cart vehicle
* before running the controller program on
* the controlling NXT
*
* PACKET INTERPRETATION:
* example packet: 897612
* -Because the packet is positive, the emergency brake is NOT engaged
* -The first two digits (89) control the left motor power
* -The thrid and fourth digits (76) control the right motor power
* -The fifth digit (1) controls the left motor direction
* -A value of 1 indicates backwards spinning
* -The final digit (2) controls the right motor direction
* -A value of 2 indicates forward spinning
* =In this example, the packet tells the cart to spin with the
* left motor spinning backwards at a speed of 89 and the right
* motor spinning forward at a speed of 76
*
* example packet: -348233
* -Because the packet is negative, a ball will fire
* -The first two digits (34) control the left motor power
* -The thrid and fourth digits (82) control the right motor power
* -The fifth digit (3) controls the left motor direction
* -A value of 3 indicates an applied emergency brake
* -The final digit (3) controls the right motor direction
* -A value of 3 indicates an applied emergency brake
* =In this example, the packet tells the cart to disengage both
* motors becuase the emergency brake is engaged. A single ball will fire
*/
import lejos.nxt.Motor;
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.comm.BTConnection;
import lejos.nxt.comm.Bluetooth;
import java.io.*;
import java.lang.Math;
public class RCNXT {
public static void main(String[] args) throws Exception{
//BEGIN VARIABLE DEFINITIONS
int right = 0; //right motor direction
int left = 0; //left motor direction
int rpower = 0; //right motor power
int lpower = 0; //left motor power
int p = 0; //packet received from controller
int bul = 0;
boolean fire = false; //indicates if Motor C is firing
InputThread input;
Thread inThread;
//END VARIABLE DEFINITIONS
LCD.clear();
LCD.drawString("Connecting...", 2, 1);
LCD.refresh();
BTConnection btc = Bluetooth.waitForConnection();
LCD.clear();
LCD.drawString("Connected", 2, 1);
DataInputStream dis = btc.openDataInputStream();
input = new InputThread(dis);
inThread = new Thread(input);
inThread.start();
DataOutputStream dos = btc.openDataOutputStream();
Motor.B.flt();
Motor.A.flt();
Motor.C.setSpeed(720f);
while(!Button.ESCAPE.isPressed()){
p = input.readInt(); //gets packet from controller
if (p != 0){
if (p == 999999){
System.exit(0);
}
if (p < 0){
p *= -1; //a negative packet indicates a command to fire
fire = true;
}
LCD.drawInt(p, 4, 3);
right = p % 10; //right motor direction is the sixth digit
p = p / 10;
left = p % 10; //left motor direction is the fith digit
p = p / 10;
rpower = p % 100; //right motor power is always the third and fourth digit
p = p / 100;
lpower = p; //left motor power is always the first two digits
rpower *= 8;
lpower *= 8; //raw input from throttles is multiplied to match full range of power
LCD.drawInt(right, 1, 4);
LCD.drawInt(left, 3, 4);
LCD.drawInt(rpower, 0, 5);
LCD.drawInt(lpower, 6, 5);
LCD.drawInt(bul, 3, 7);
Motor.B.setSpeed((float)rpower);
Motor.A.setSpeed((float)lpower);
if (right == 2){ //(numeral 2) corresponds to forward power
Motor.B.forward();
}
else if (right == 1){
Motor.B.backward(); //(numeral 1) corresponds to backward power
}
else{
Motor.B.flt(); //(numeral 3) corresponds to a brake on the motor
}
if (left == 2){
Motor.A.forward();
}
else if (left == 1){
Motor.A.backward();
}
else{
Motor.A.flt();
}
if (fire){
Motor.C.rotate(360, true); //fires the ball and reloads the shooter
bul ++;
fire = false;
}
}
}
LCD.clear();
LCD.drawString("Close Connection", 0, 1);
dis.close();
btc.close();
Thread.sleep(2000);
}
}
- Code: Select all
/**
* @(#)InputThread.java
*
*
* @author
* @version 1.00 2012/2/6
*/
import lejos.nxt.comm.*;
import lejos.nxt.*;
import java.io.*;
public class InputThread implements Runnable{
DataInputStream dis;
int input = 0;
boolean running = true;
public InputThread(DataInputStream d) {
dis = d;
}
public static void main(String[] args){
LCD.drawString("no", 0 , 0);
}
public void run(){
while (running){
try{
input = dis.readInt();
}
catch (IOException e){
}
}
}
public int readInt(){
return input;
}
}
-
Doug Fane
- New User
-
- Posts: 9
- Joined: Sun Dec 04, 2011 11:20 pm
Return to NXJ Projects
Who is online
Users browsing this forum: Google [Bot] and 1 guest