Using addSensorPortListener () in static main [RESOLVED]

This is where you talk about the NXJ software itself, installation issues, and programming talk.

Moderators: 99jonathan, roger, imaqine

Using addSensorPortListener () in static main [RESOLVED]

Postby quack » Sat Jul 21, 2007 5:57 pm

how can I add a SensorPortListener (implemented in my class) in the main method ( a static method)?


I was trying to do this:

Code: Select all
public class Main implements SensorPortListener
{     
    ...
   
    public static void main(String[] args) throws Exception
    {
        SensorPort.S2.addSensorPortListener (this);
       
        while (!Button.ENTER.isPressed ())
        {
            ...
        }
    }

    public void stateChanged (SensorPort aSource, int aOldValue, int aNewValue)

    {
         ...
    }


but I can't because both SensorPort and my implemented SensorPortListener are non-static...


thanks in advance
quack
Novice
 
Posts: 26
Joined: Sun Jul 08, 2007 9:03 pm

Postby lawrie » Sat Jul 21, 2007 9:24 pm

You either use an anonymous class:

SensorPort.addSensorPortListener(new SensorPortListener() {
public void stateChanged (SensorPort aSource, int aOldValue, int NewValue)
{
...
}
});

or you create an instance of the Main class and do :

SensorPort.S2.addSensorPortListener (this);

in a non-static method. You can even do this in the constructor for Main.
lawrie
leJOS Team Member
 
Posts: 909
Joined: Mon Feb 05, 2007 1:27 pm

Postby quack » Sat Jul 21, 2007 9:37 pm

lol. I tried that with the constructor before but forget to create new Main ()...

thanks anyway
quack
Novice
 
Posts: 26
Joined: Sun Jul 08, 2007 9:03 pm

Postby quack » Sat Jul 21, 2007 9:49 pm

Now that i fixed that sensor problem i've another problem. i was hoping you could help me.

this program makes a NXT car moves forward until the distance between returned by the ultrasonic sensor is less than 20. Then the car should stop one of the motors so it could rotateto one side looking for space to move forward..

here's the complete code

Code: Select all
import lejos.nxt.*;

public class Main implements SensorPortListener
{   
    private static boolean move = true;
   
    private int buffSonic = 100;
   
    public Main ()
    {
        SensorPort.S2.addSensorPortListener (this);
    }
   
    public static void main(String[] args) throws Exception
    {
        Main m = new Main ();       
           
        while (!Button.ENTER.isPressed ())
        {
            while (move)
            {
                Motor.B.forward ();
                Motor.C.forward ();
            }
           
            Motor.B.forward ();
            Motor.C.stop ();
        }
    }

    public void stateChanged (SensorPort aSource, int aOldValue, int aNewValue)
    {     
        UltrasonicSensor sonic = new UltrasonicSensor (aSource);
       
        if (sonic.getDistance () < 20)
            move = false;
       
        else
            move = true;
    }
}


it compiles fine, but when i run it with the NXT it just keeps moving forwar no matter the distance, and the LCD prints this:

Java Exception:
Class: 5
Method:108

Could you help me with this?


(by the way sorry for my english, i'm portuguese)
quack
Novice
 
Posts: 26
Joined: Sun Jul 08, 2007 9:03 pm

Postby lawrie » Sun Jul 22, 2007 9:25 am

Unfortunately SensorPortListener does not work with I2C sensors like the Ultrasonic sensor. It is designed to work with A/D sensor like the Touch, Light or Sound sensor.

You are better off putting the the call to getDistance in your main loop or creating a new thread with it in or using the Behavior classes in lejos.subsumption.

We have plans to add Listeners for specific sensors like the Ultrasonic sensor, but have not done that yet.

You can see what method your code is getting by linking with the --verbose flag. This will list all the methods in your program with their method number. The exception 5 that you are getting is OUTOFMEMORY. Currently you have to look this up in src/nxtvm/javavm/specialclasses.h.

You are getting an OUTOFMEMORY exception because you keep creating a new UltrasonicSensor object. You should create it once at the start of the program. One way to do that in your program is to add:

private static sonic = new UltraSonicSensor(SensorPort.S2);

at the start of your class.

Finally is is best to put in a delay between calls of getDistance(), e.g.

Thread.sleep(200);

If you call getDistance() too frequently it fails.
lawrie
leJOS Team Member
 
Posts: 909
Joined: Mon Feb 05, 2007 1:27 pm

Postby quack » Sun Jul 22, 2007 12:05 pm

ok. thanks
quack
Novice
 
Posts: 26
Joined: Sun Jul 08, 2007 9:03 pm

Postby wildbill » Sun Mar 02, 2008 9:07 pm

lawrie, please could you expand on your statement above that calls to getDistance will fail if called too frequently?

I installed lejos this weekend and have been trying to program a bot to navigate using three ultrasonic sensors - it looks forward and when it 'sees' something ahead, it uses left and right ultrasonics to choose which side is clearer & then turns that way.

However, it seems to see occasional ghosts ahead of it. I have a separate thread running that reads the distance sensors and displays their values on the LCD. From your remark, I'm wondering if, even though I have the sensor reading code wrapped in a synchronized routine, that the display thread sometimes gets called around the same time as the main thread is checking and causes failure.

I also see that the display routine, when run by itself sometimes fails & gets 255 briefly for a sensor that's usually showing a reasonable value. It only checks every 200ms though. Is there an issue with calling getDistance in rapid succession on different sensors too?

One more issue: all my attempts to use stringbuffer.append cause a crash

Other than that - I'm very pleased with Lejos so far, it's working beautifully.
wildbill
New User
 
Posts: 4
Joined: Sun Mar 02, 2008 8:06 pm

Postby gloomyandy » Sun Mar 02, 2008 10:00 pm

Hi,
The comments about calling getDistance too often no longer apply (if you are using leJOS 0.5). The sensor does sometimes return values of 255, and you also get ghosts. If you are using multiple sensors then you may find that you get interference between them. You may want to use single shot mode so that only one is firing at a time. Sounds like fun!

Could you post some code that shows the problem with append? We'll try and take a look at it...

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

Postby kirkpthompson » Mon Mar 03, 2008 1:30 pm

Along the same lines, how would I use capture() mode? Set the mode (.capture()) and call getDistance()?
User avatar
kirkpthompson
leJOS Team Member
 
Posts: 304
Joined: Wed Dec 05, 2007 1:27 am
Location: New Mexico, USA

Postby gloomyandy » Mon Mar 03, 2008 2:16 pm

In theory yes that is how capture mode is supposed to work. But as the doc says, when I wrote the code for the Ultrasonic class I only had one sensor so was unable to try it out....

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

Ultrasonics issues

Postby wildbill » Sun Mar 09, 2008 4:15 pm

Andy,
My problem has turned out to be unrelated to StringBuffer after all, it was something much more bizarre. I have my sensors initialized as static members in a class that contains nothing but accessor methods. Here's the relevant fragment:

Code: Select all
class Sensors
{
static UltrasonicSensor FrontUS = new UltrasonicSensor(SensorPort.S4);

static public synchronized int GetForwardDistance()
{
   return FrontUS.getDistance();
}

}


I have a thread that uses GetForwardDistance to display what the sensor is reading on the LCD. It crashes with a null pointer exception (Class 8) if I read the sensor too soon. This appears to be because FrontUS is not initialized, indeed, this code indicates that it is null the first time it is checked:

Code: Select all
class ReadSensors extends Thread
{
   boolean Run=true;
   boolean wasnull=false;
   int dist=0;
   public void run()
   {
   while(Run)
     {
     if(Sensors.FrontUS==null)
      wasnull=true;
     else    
       dist=Sensors.GetForwardDistance();
     LCD.drawString("Front:        ", 0, 1);
     LCD.drawInt(Sensors.GetForwardDistance(), 10, 1);
     if(wasnull)
      LCD.drawString("null:        ", 0, 6);
     LCD.refresh();
     try {Thread.sleep(200);} catch(Exception e){}
     }
   }
}


Clearly, I can put the initialization in a routine & call it explicitly, but should I expect this behaviour?

The other issue is the ghost results from the ultrasonic sensors. It's not interference from the other pair, because the problem persists with them disconnected. I didn't notice this when I ran the robot using NXC either - is there some difference in the way lejos reads the sensors?

Martin
wildbill
New User
 
Posts: 4
Joined: Sun Mar 02, 2008 8:06 pm

Postby gloomyandy » Sun Mar 09, 2008 8:00 pm

Hmm, that does not sound right. statics should always be initialized before the first reference. I guess you can work round it for now. When I get chance I'll give it a try with the latest firmware/vm (The are have been a lot of changes since 0.5).

I'm not really sure why you are get more ghost images than with nxc. Are you using the same room, the surfaces of a room/object have a big impact on reflections. The other possibility is that recent versions of leJOS (certainly since 0.5) now power the Ultrasonic sensor at 9v (or as close as you can get to it). Previous versions only used 5v, this means that you get longer range but you may get more reflections. The Lego code normally uses 9v I'm not sure about nxc.... I think you can set the port to operate at 5v by making a call to...
port.setType(TYPE_LOWSPEED);
*After* you have initialized the Ultrasonic class using port. This will give you a shorter range but less ghosting....

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

aha!

Postby wildbill » Mon Mar 10, 2008 12:07 am

Andy,
I think you may have nailed it; I looked back into the nxc code and saw this in the sensor setup which I had copied from nxc examples/docs:

Code: Select all
SetSensorLowspeed(IN_4);


Didn't know what it meant then, but in light of your post it's becoming clear now. I'll try your TYPE_LOWSPEED change and test in the same room and see whether it reverts to the nxc behaviour. Another correlating piece of evidence is that the brick seems to eat batteries faster under lejOS - running the sensors at higher voltage would explain why.

Thanks,
Martin[/code]
wildbill
New User
 
Posts: 4
Joined: Sun Mar 02, 2008 8:06 pm

results

Postby wildbill » Mon Mar 10, 2008 2:02 am

Seems to work differently with the low power setting. More investigation to do, but it's certainly better this way, so thanks for that crucial tip.

Martin
wildbill
New User
 
Posts: 4
Joined: Sun Mar 02, 2008 8:06 pm


Return to NXJ Software

Who is online

Users browsing this forum: Yahoo [Bot] and 7 guests

more stuff