Infrared Link Supported?

This is where you talk about the NXJ hardware related topics such as the brick, sensors, LEGO pieces, etc.

Moderators: imaqine, 99jonathan, roger

User avatar
gloomyandy
leJOS Team Member
Posts: 6020
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Postby gloomyandy » Mon Oct 13, 2008 2:30 pm

Hi,
The addon package does not exist in 0.6 (we have moved things around a little for the next release). However most of the classes probably do. You may need to add extra import statements to fix this. So for now I would remove the import of addon and see how things go. If you get problems look at the 0.6 classes and you should be able to work out what imports you need...

Andy

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Mon Oct 13, 2008 5:56 pm

Unfortunately, just removing the import does not fix the issue: the definition of 'IRLink' does not appear to be in the regular namespace. Is it possible that this class got accidentally left out of the 0.6 release?

-Bill

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Mon Oct 13, 2008 5:58 pm

I should have mentioned in the previous post that I did go to SVN and look at the source. The HEAD version of the IRLink.java source does indeed show this source as being a part of the lejos.nxt.addon package. So unless there is a different version of this class in some other source file I seem to be stuck.

-Bill

User avatar
gloomyandy
leJOS Team Member
Posts: 6020
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Postby gloomyandy » Mon Oct 13, 2008 6:51 pm

Hi Bill,
Yes as I said before the IRLink code is not part of the 0.6 release. That's why I pointed you to the source in svn. What you will need to do is to download a copy of the 0.7 IRlink.java class and add it alongside your own code. To get it to compile you may need to make changes (you will almost certainly need to remove the package statement, and probably change the imports). However with a little bit of work it should be possible to get the 0.7 IRlink code to work with 0.6. If you are not comfortable making those changes you may be better waiting until the 0.7 release is available.... But why not give it a go...

Good luck

Andy

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Mon Oct 13, 2008 7:09 pm

Ah, ok. I did what you suggested, and it works! The only change I had to make was to comment out the import statement.

Thanks much! Just a quick further question: Is there a nightly build or other tag in the repository that we can access to get a snapshot version of the product in case the newest official release has a known bug or other issue?

-Bill

User avatar
gloomyandy
leJOS Team Member
Posts: 6020
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Postby gloomyandy » Mon Oct 13, 2008 7:22 pm

Hi,
Congratulations!

No we don't tag the snapshot, but it does not change that often and what is there will usually work. Basically the snapshot builds are updated by the developers as new features are "released" to the rest of the team. So the snapshot is not the result of an automated build, but the last step in a process that usually involves a reasonable amount of testing. The main purpose of the snapshot is to enable those developers that do not want to build the firmware part of the system to be able to obtain an up to date build that they can use for development of the Java part of the system...

However you do need to take all of it... It is not normally possible to mix bits of the snapshot with a release (unless you do as you have done and take parts of the source)..... Also from time to time it may undergo changes in structure etc. that breaks your existing code... It may also stay broken for a while. If some new change introduces a problem then it will probably only get fixed when and if the team gets a chance to work on it. So if you use the snapshot be prepared to hit problems....

Andy

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Mon Oct 13, 2008 7:27 pm

Thanks!

Getting back to the original topic, I discovered that while the IRLink class does indeed work to control LEGO PF motors, there are some issues.

For instance, I found that I had to include a 200 msec pause between commanding motors to run forwards and commanding them to run backwards. Without the pause the command to run backwards is ignored.

The following sample code may be helpful for others:

---------------------------
IRLink ir = new IRLink(SensorPort.S1);
TouchSensor ts = new TouchSensor(SensorPort.S2);

while (!ts.isPressed()) {
ir.sendPFComboDirect(3, IRLink.PF_FORWARD, IRLink.PF_FORWARD);
}

ir.sendPFComboDirect(3, IRLink.PF_BRAKE, IRLink.PF_BRAKE);
Sound.pause(200);

while (!ts.isPressed()) {
ir.sendPFComboDirect(3, IRLink.PF_BACKWARD, IRLink.PF_BACKWARD);
}

ir.sendPFComboDirect(3, IRLink.PF_BRAKE, IRLink.PF_BRAKE);
-----------------------------

This is my first working code using the IRSeeker, and I am sure there is lots more to discover.

-Bill

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Mon Oct 13, 2008 7:30 pm

Looking at my code, I suspect the reason for the required pause is that there are still queued-up commands from the loop that have not completely executed, and the pause is needed to let them flush out.

-Bill

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Tue Oct 14, 2008 2:44 pm

I wonder if other forum members have some experiences with the PF commands they would like to share.

My intuition tells me that as a PF driver, IRLink could be greatly improved. For instance, the only PF mode it appears to support is the mode where you need to continually send PF_FORWARD or PF_BACKWARD commands in a loop to keep the motor running. Otherwise the motor stops in a second or two. From reading the LEGO PF documentation, I see that there is a mode where you give it a single command to run forwards or backwards, and the motor will run continually in that direction without further commands until you send a BRAKE or FLOAT command.

This mode is the one I really want: if I have to keep sending commands, I will have to start up a thread just for this purpose, which seems to me to be using a cannon to swat a mosquito.

I am guessing that the hard-coded PF_MODE_COMBO_DIRECT is the culprit here: if a different mode were substituted or more flexibility were added you could get both modes to work. I don't really know enough about the PF commands to see quite how to do this. I am hoping some more knowledgeable person can give me a clue. The bit encoding that PF apparently wants looks pretty weird, and I see that the current IRLink class goes though quite a bit of bit-twiddling to get it right, so a change may be non-trivial.

Anyone want to raise a hand?

Thanks!
-Bill

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Postby wleue » Tue Oct 14, 2008 4:49 pm

For what it's worth, I tried adding a sendPFSinglePinContinuous method and supporting constants to the IRLink class. It compiles fine and does not produce any exceptions or crashes when executed, but neither does it produce the results I intended. Again, perhaps someone with more experience would feel like taking a look, perhaps Lawrie??

-Bill

Code: Select all

/*
Revision 1819 - (download)
Thu Sep 4 21:53:49 2008 UTC (5 weeks, 3 days ago) by lgriffiths
File size: 2711 byte(s)

Renamed lejos.addon as lejos.nxt.addon
 * W. Leue 10/13/08 -- removed the lejos.nxt.addon package def;
 * added sendPFSinglePinContinuous method & supporting constants.
 */

//package lejos.nxt.addon;

import lejos.nxt.I2CPort;
import lejos.nxt.I2CSensor;
import java.util.*;

/**
 * Supports for HiTechnic IRLink - see  http://www.hitechnic.com/.
 *
 * @author Lawrie Griffiths
 *
 */
public class IRLink extends I2CSensor {
  //Registers
  private final static byte TX_BUFFER = 0x40; // 40 to 4C
  private final static byte TX_BUFFER_LEN = 0x4D;
  private final static byte TX_MODE = 0x4E;
  private final static byte TX_BUFFER_FLAG = 0x4F;
  private final static byte TX_MAX_BUFFER_LEN = 13;  // IRLink transmission modes
  private final static byte TX_MODE_RCX = 0;
  private final static byte TX_MODE_TRAIN = 1;
 
  private final static byte TX_MODE_PF = 2;  // PF Modes
 
  public final static byte PF_MODE_COMBO_DIRECT = 1;  // IR PF signal encoding parameters
  public final static byte PF_MODE_SINGLE_PIN_CONTINUOUS = 2;
  public final static byte PF_MODE_SINGLE_PIN_TIMEOUT = 3;
  public final static byte PF_MODE_SINGLE_OUTPUT = 4;
 
  public static final int PF_MOTOR_A = 0;     // PF Single Pin Command Fields
  public static final int PF_MOTOR_B = 1; 
  public static final int PIN_C1 = 0;
  public static final int PIN_C2 = 1; 
  public static final int FUNC_NO_CHANGE = 0;
  public static final int FUNC_CLEAR = 1;
  public static final int FUNC_SET = 2;
  public static final int FUNC_TOGGLE = 3;
 
  private final byte MAX_BITS = TX_MAX_BUFFER_LEN * 8;
  private final byte STOP_START_PAUSE = 7;
  private final byte LOW_BIT_PAUSE = 2;
  private final byte HIGH_BIT_PAUSE = 4;  // PF motor operations
  public static final byte PF_FLOAT = 0;
  public static final byte PF_FORWARD = 1;
  public static final byte PF_BACKWARD = 2;
  public static final byte PF_BRAKE = 3;
  private byte toggle = 0;
  private BitSet bits = new BitSet(MAX_BITS);
  private int nextBit = 0;

  public IRLink(I2CPort port) {
    super(port);
  }

  /**
   * Send commands to both motors.
   * Uses PF Combo direct mode.
   *
   * @param channel the channel number (0-3)
   * @param opA Motor A operation
   * @param opB Motor B operation
   */
  public void sendPFComboDirect(int channel, int opA, int opB) {
    sendPFCommand(channel, PF_MODE_COMBO_DIRECT, (opB << 2) | opA);
  }
 
  public void sendPFSinglePinContinuous(int channel, int output, int pin, int function) {
    sendPFCommand(channel, PF_MODE_SINGLE_PIN_CONTINUOUS, (output << 3) | (pin << 2) | function);
  }

  private void sendPFCommand(int channel, int mode, int data) {
    byte nibble1 = (byte) ((toggle << 3) | channel);
    byte lrc = (byte) (0xF ^ nibble1 ^ mode ^ data);
    int pfData = (nibble1 << 12) | (mode << 8) | (data << 4) | lrc;

    clearBits();
    nextBit = 0;
    setBit(STOP_START_PAUSE); // Start
    for (int i = 15; i >= 0; i--) {
      setBit(((pfData >> i) & 1) == 0 ? LOW_BIT_PAUSE : HIGH_BIT_PAUSE);
    }
    setBit(STOP_START_PAUSE); // Stop
    toggle ^= 1;
    byte[] pfCommand = new byte[TX_MAX_BUFFER_LEN + 3];

    for (int i = 0; i < MAX_BITS; i++) {
      boolean bit = bits.get(i);
      int byteIndex = i / 8;
      int bitVal = (bit ? 1 : 0);
      pfCommand[byteIndex] |= (bitVal << (7 - i % 8));
    }

    pfCommand[13] = TX_MAX_BUFFER_LEN;
    pfCommand[14] = TX_MODE_PF;
    pfCommand[15] = 1;

    sendData(TX_BUFFER, pfCommand, TX_MAX_BUFFER_LEN + 3);
  }

  private void setBit(int pause) {
    bits.set(nextBit++);
    nextBit += pause;
  }

  private void clearBits() {
    for (int i = 0; i < MAX_BITS; i++) {
      bits.clear(i);
    }
  }
}

LasseD
New User
Posts: 4
Joined: Sat Jun 14, 2008 9:43 am

Postby LasseD » Wed Oct 15, 2008 10:28 pm

wleue wrote:I wonder if other forum members have some experiences with the PF commands they would like to share.

(...)

Anyone want to raise a hand?

Thanks!
-Bill


Take a look at post #5 in this very thread. I made some changes to the class in order to support single output direct. This is without interrupts.

I will soon receive a new sensor and can continue testing.

lawrie
leJOS Team Member
Posts: 965
Joined: Mon Feb 05, 2007 1:27 pm

Postby lawrie » Mon Oct 20, 2008 9:41 pm

You can copy the IRLink class into your own program and remove the package statement, or wait for the 0.7 release.

wleue
New User
Posts: 23
Joined: Tue May 15, 2007 8:55 pm
Location: Albany, NY
Contact:

Once again, IR device support in latest leJOS

Postby wleue » Wed Sep 16, 2009 12:46 pm

It has been almost a year since I played with the HiTech IR transceiver with leJOS. In version 0.6, I was able to establish communications with a PF IR reciever, but only when using continuous commands. I tried hacking the driver so that set-and-forget commands would work, but was not successful.

I am wondering whether non-continuous IR modes now work in the new version of leJOS? This would be similar to the way the Emerald Night works using the new LEGO IR controller: it is not necessary to send a continuous stream of IR commands in order to keep the train running: commands only need be sent to start, stop, or change speed/direction.

Thanks!
-Bill

lawrie
leJOS Team Member
Posts: 965
Joined: Mon Feb 05, 2007 1:27 pm

Postby lawrie » Fri Sep 25, 2009 8:25 pm

I have not touched the IRLink class since I originally wrote it. If I get some time, I will look at it again, to see if I can add more modes and commands.

aprendiendo
New User
Posts: 15
Joined: Thu Dec 06, 2007 12:37 pm
Contact:

Postby aprendiendo » Tue Oct 06, 2009 8:55 pm

First of all, thanks for yor great tool. I think it's the best option to program the NXT, and there are other very good and interesting tools, like pbLua or RobotC.

And now, the question...

To use the IRLink class with a RC train, Is it as easy as create a new parameter in the signature of

Code: Select all

private void sendPFCommand(int channel, int mode, int data)


an call it with one of the existing IRLink transmission modes constants?

private final static byte TX_MODE_RCX = 0;
private final static byte TX_MODE_TRAIN = 1;
private final static byte TX_MODE_PF = 2;

Well, and, wisely, change the method name :)

Thanks in advance.


Return to “NXJ Hardware”

Who is online

Users browsing this forum: No registered users and 1 guest