HiTechnic angle sensor

Post your NXJ projects, project ideas, etc here!

Moderators: 99jonathan, roger, imaqine

HiTechnic angle sensor

Postby burti » Sat Apr 02, 2011 12:47 am

Hi.
I was looking for a lejos implementation of the HiTechnic Angle Sensor (http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&key=NAA1030) but did not find one.
Has anybody written one?
If not, you could add my implementation:

Code: Select all
import lejos.nxt.I2CPort;
import lejos.nxt.I2CSensor;

/** Supports the angle sensor of HiTechnic.
 * This Java implementation was based on the NXC implementation on http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&key=NAA1030.
 * Works clockwise, i.e. rotating clockwise increases angle value and rotating counter-clockwise decreases angle value.
 *
 * @author Michael Mirwaldt (epcfreak@gmail.com)<br/>
 * date 2nd April 2011
 */

public class AngleSensor extends I2CSensor {
   
   protected final int HTANGLE_MODE_CALIBRATE = 0x43;
   protected final int HTANGLE_MODE_RESET = 0x52;

   public AngleSensor(I2CPort port, int address, int mode, int type) {
      super(port, address, mode, type);
   }

   public AngleSensor(I2CPort port, int mode) {
      super(port, mode);
   }

   public AngleSensor(I2CPort port) {
      super(port);
   }
   
   /** reads the current angle
    *
    * @return angle. Value lies between 0-359
    */
   public int getAngle() {
      byte buf[] = new byte[2];
      getData(0x42, buf, 2);
      int bits9to2 = buf[0];
      int bit1 = buf[1]&0x01;
      
      // prevent byte with value above 127 to become a negative number when it is converted to an integer
      if(bits9to2 < 0) {
         bits9to2+=256;
      }
      return bits9to2 * 2 + bit1;
   }
   
   /** @see #getAccAngle()
    *
    */
   public long getAccumulatedAngle() {
      return getAccAngle();
   }
   
   /** reads the current accumulated angle
    *
    * @return the current accumulated angle. Value lies between -2147483648 to 2147483647.
    */
   public long getAccAngle() {
      byte buf[] = new byte[4];
      getData(0x44, buf, 4);      
      int bits32to24 = buf[0];
      int bits23to18 = buf[1];
      int bits17to09 = buf[2];
      int bits08to01 = buf[3];
      
      // prevent bytes with values above 127 to become negative numbers when they are converted to integers
      if(bits23to18 < 0) {
         bits23to18+=256;
      }
      if(bits17to09 < 0) {
         bits17to09+=256;
      }
      if(bits08to01 < 0) {
         bits08to01+=256;
      }
      
      return bits32to24*0x1000000 | bits23to18*0x10000 | bits17to09*0x100 | bits08to01;
   }
   
   /** reads the current rotations per minute
    *
    * @return current rotations per minute. Value lies between -1000 to 1000.
    */
   public int getRPM() {
      byte buf[] = new byte[2];
      getData(0x48, buf, 2);   
      int bits17to09 = buf[0];
      int bits08to01 = buf[1];
      
      // prevent byte with value above 127 to become a negative number when it is converted to integers
      if(bits08to01 < 0) {
         bits08to01+=256;
      }
      
      return bits17to09*0x100 | bits08to01;
   }
   
   
   /** @see #getAccAngle()
    *
    */
   public int getRotationsPerMinute() {
      return getRPM();
   }
   
   /** @see #resetAccAngle()
    *
    */
   public void resetAccumulatedAngle() {
      resetAccAngle();
   }
   
   
   /** Reset the rotation count of accumulated angle to zero. 
    * Not saved in EEPORM.
    */
   public void resetAccAngle() {
      sendData(0x41, (byte) HTANGLE_MODE_RESET);
   }
   
   /** Calibrate the zero position of angle.
    * Zero position is saved in EEPROM on sensor.
    * Thread sleeps for 50ms while that is done.
    */
   public void calibrateAngle() {
      sendData(0x41, (byte) HTANGLE_MODE_CALIBRATE);
      try {
         // Time to allow burning EEPROM
         Thread.sleep(50);
      } catch (InterruptedException e) {
         // ignore because it does not seem to cause trouble
      } 
   }
}

I did some tests.
First I just rotated the axle of the angle sensor just for fun with the following program running:
Code: Select all
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.SensorPort;

public class TestAngleSensor {
   public static void main(String[] args) {
      AngleSensor angleSensor = new AngleSensor(SensorPort.S1);
      while(!Button.ENTER.isPressed()) {
         LCD.drawString("angle=" + angleSensor.getAngle() + "         ", 0, 0);
         LCD.drawString("accAngle=" + angleSensor.getAccAngle() + "         ", 0, 1);
         LCD.drawString("RPM=" + angleSensor.getRPM() + "            " , 0, 2);
      }   
      angleSensor.resetAccAngle();
      while(!Button.ESCAPE.isPressed()) {
         LCD.drawString("angle=" + angleSensor.getAngle() + "         ", 0, 0);
         LCD.drawString("accAngle=" + angleSensor.getAccAngle() + "         ", 0, 1);
         LCD.drawString("RPM=" + angleSensor.getRPM() + "            " , 0, 2);
      }   
   }
}

After that I tested the angle sensor with a motor on motor port A and the angle sensor on sensor port 1 with the following program running:
Code: Select all
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.Motor;
import lejos.nxt.SensorPort;

public class TestAngleSensor {
   public static void main(String[] args) {
      AngleSensor angleSensor = new AngleSensor(SensorPort.S1);
      angleSensor.calibrateAngle();
      Motor.A.setSpeed(180);
      Motor.A.backward();
      while(!Button.ENTER.isPressed()) {
         LCD.drawString("angle=" + angleSensor.getAngle() + "         ", 0, 0);
         LCD.drawString("accAngle=" + angleSensor.getAccAngle() + "         ", 0, 1);
         LCD.drawString("RPM=" + angleSensor.getRPM() + "            " , 0, 2);
      }   
   }
}

The program gives me a value of around 30 for RPM which is correct because 180 degrees per sec is one rotation per 2 seconds which results in 30 rotations per minute.
Seems to work fine.
Last edited by burti on Mon Apr 04, 2011 8:22 pm, edited 1 time in total.
burti
Novice
 
Posts: 61
Joined: Thu Jun 25, 2009 11:41 pm

Re: HiTechnic angle sensor

Postby Walt White » Mon Apr 04, 2011 5:41 pm

Hi burti,

Thanks for posting this. I will try it at home sometime during the next few days and hopefully can duplicate your tests.

Walt
Walt White
Novice
 
Posts: 44
Joined: Sun Aug 06, 2006 11:57 pm
Location: California Central Valley

Re: HiTechnic angle sensor

Postby burti » Mon Apr 04, 2011 8:24 pm

Hi Walt,
I want to point out I changed my implementation.
I left out
Code: Select all
if(bits32to24 < 0) {
         bits32to24+=256;
      }

in "public long getAccAngle()".
Please take note of that change.

Michael
burti
Novice
 
Posts: 61
Joined: Thu Jun 25, 2009 11:41 pm

Re: HiTechnic angle sensor

Postby Walt White » Sun Apr 10, 2011 10:32 pm

Michael,

False alarm! I checked my sensors and I have gyro and acceleration, not angle. I'm also very curious about whether any of these will be included in the pending 0.9 release.

I've been working on a line (actually edge) follower using the NXTLineleader sensor and I'm waiting to see it supported in the 0.9 release along with changes to the Motor class. I'm hoping that the updated Motor tutorial will clarify setPower, setSpeed, and/or regulateSpeed for a line following application.

Walt
Walt White
Novice
 
Posts: 44
Joined: Sun Aug 06, 2006 11:57 pm
Location: California Central Valley

Re: HiTechnic angle sensor

Postby kirkpthompson » Mon Apr 11, 2011 5:42 am

Hi Walt et al.

Yes, we have been working on GyroSensor and GyroDirectionFinder classes for 0.9. We also will have accelerometer classes for the HiTechic and Mindsensors accelerometer sensors.

Best,
-K
Leg Godt!
User avatar
kirkpthompson
leJOS Team Member
 
Posts: 304
Joined: Wed Dec 05, 2007 1:27 am
Location: New Mexico, USA

Re: HiTechnic angle sensor

Postby gloomyandy » Mon Apr 11, 2011 10:04 am

Walt White wrote:I've been working on a line (actually edge) follower using the NXTLineleader sensor and I'm waiting to see it supported in the 0.9 release along with changes to the Motor class. I'm hoping that the updated Motor tutorial will clarify setPower, setSpeed, and/or regulateSpeed for a line following application.

Walt


Hi,
The line leader class can be seen here:
http://lejos.svn.sourceforge.net/viewvc ... iew=markup
If you want to use the new classes there really is no need to wait for 0.9 you can use the developer snapshot, not that much will change before 0.9 and any testing you do will be very useful.

I suspect that you may be disappointed with any clarification of motor usage (especially with the line leader). I'll try and explain the problem below:

The main confusion seems to be with setPower. The line leader gives you back a value that can be used to adjust this value and this number comes directly from the firmware on the device. The problem is what exactly does setPower adjust?

In leJOS 0.9 the answer is very simple. setPower changes the actual percentage of the PWM duty cycle. It only applies to unregulated motors and is in effect used to directly control the amount of power being supplied to the motor. The setPower value has no control of the actual speed of the motor (as this will depend upon a combination of the motor type, the load and the setPower value). For regulated motors then the actual speed is controlled hence we use the setSpeed method and you can set the actual motor speed in degrees per second.

Unfortunately the Lego firmware does things differently it uses the setPower function both for unregulated motor control and regulated motor control. Which raises the question of how does the regulated motor speed (in degrees per second), relate to the setPower value (which is a percentage)? This page:
http://www.philohome.com/nxtmotor/nxtmotor.htm
Provides the answer. Basically if you have no load and sufficient battery power then a setPower value of 100% equates approximately 960 degrees/s 10% will give you 96 degrees/s etc. Because this is a regulated motor lower voltage and increase load will basically impose a maximum speed cut off point (when regulation fails), but below this point the relationship is linear.

Some of the add on devices (like the line leader and the NXT motor mux), basically use the Lego firmware model for motor control, which means that if you want to use them with leJOS the fit may not be perfect.

So this raises a few questions:
1. Why do we do things differently in leJOS
2. Why don't we provide a leJOS like interface to the line leader and the motor mux so thay can be used in a more sensible way with the leJOS motor control system...

The answer to question 1 is that we feel that for a regulated motor you are controlling the speed of the motor and that having a methed call setPower that does not control the power but rather is an indirect way of controlling the speed creates confusion. There are also some issues with the setPower approach. How do you for instance set the motor to run at 100 degrees per second? With the Lego firmware setPower(10) will run at 96, while setPower(11) runs at 105.6... With leJOS setSpeed(100) does exactly what you would expect.

The answer to question 2 is very simple. None of the people that have the above devices have created that interface and more importantly tested it. When I was re-working the motor classes for 0.9 I considered making the NXTMMXMotor class support the RegulatedMotor interface (which would have allowed these motors to be used more easily in place of a standard motor). But I don't have one of those controllers and so had no way of testing this or of evaluating how closely the two regulators match (I suspect they don't match very closely). Perhaps once 0.9 is out a leJOS user that has the devices will contribute code that provides a more leJOS like interface...


Sorry of the length of the above explanation, but I hope you find it of use...

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

Re: HiTechnic angle sensor

Postby Walt White » Mon Apr 11, 2011 10:33 pm

Andy,

Thanks for the thorough and thoughtful reply. I took a closer look at the NXTLineLeader class you referenced and I think I can easily test it the same way I tested ChrisB01's class in this thread.
Since I posted my code for displaying sensor values in the thread above, I have discovered that the number returned by getSteering() changes depending on whether or not you have previously performed a SNAPSHOT calibration. I'll try to remember to include that in future tests.

I don't completely follow your statement
The main confusion seems to be with setPower. The line leader gives you back a value that can be used to adjust this value and this number comes directly from the firmware on the device.
My plan has always been to use that number to adjust setSpeed which seems like a much more precise and useful function anyway.

My confusion was with the accuracy of using setSpeed (as opposed to using setPower) on an unregulated motor in 0.9 based on the 0.85 tutorial:
When might you want to turn off speed regulation?
In some robots, the motor speed should not be constant but changed in response to a sensor reading as for example in a line follower or a balancing robot. If the speed corrections happen frequently, there is no advantage in the regulator thread using CPU cycles in adjusting the motor power to maintain constant speed between adjustments.


Your statement clarifies the concept of "controlled" setSpeed:
For regulated motors then the actual speed is controlled hence we use the setSpeed method and you can set the actual motor speed in degrees per second
and I will continue to use setSpeed on an unregulated motor for my line follower.

Thanks, again.

Walt
Walt White
Novice
 
Posts: 44
Joined: Sun Aug 06, 2006 11:57 pm
Location: California Central Valley

Re: HiTechnic angle sensor

Postby gloomyandy » Tue Apr 12, 2011 9:05 am

Hi,
Sorry about the confusion. What I was trying to say is that the output from the line leader was designed with the standard firmware in mind. So the value is intended to be used with that firmware's setPower interface which takes a value in the range of 0-100, you may need to adjust and scale this value to use it with the leJOS setSpeed interface. In 0.9 we have separate classes for regulated and unregulated use of the NXT motors. This is an attempted to keep the two concepts clearer and avoid the confusion sometimes caused with the old motor class.

All the best

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

Re: HiTechnic angle sensor

Postby lawrie » Wed May 11, 2011 8:27 pm

I have added the AngleSensor class to leJOS. It will be in the 0.9 release.
lawrie
leJOS Team Member
 
Posts: 919
Joined: Mon Feb 05, 2007 1:27 pm


Return to NXJ Projects

Who is online

Users browsing this forum: No registered users and 3 guests

more stuff