Showing posts with label leJOS NXJ. Show all posts
Showing posts with label leJOS NXJ. Show all posts

Monday, March 24, 2014

Controlling NXT Robot From the Keyboard with leJOS NXJ

Bad GUI for robot control
(UPDATE: So this was all well and good as a proof of concept but we found when we brought the motors into the mix the motors were too slow to respond to direct commands. We learned a lot in the process, though.)

I worked up a proof of concept in leJOS NXJ I'll be teaching my high school robotics students soon for a method of controlling a

Monday, November 18, 2013

Programming TETRIX Servos With leJOS NXJ

The last time I taught my high school robotics class I used RobotC to program TETRIX servos. The RobotC API provides the functions servoValue, servo, and servoChangeRate. From the documentation we learned that the only way you can be sure not to push your servo against a physical barrier and damage it is to avoid setting it to a position it can't reach. The easy programming also allowed us to avoid learning about how servos really work. leJOS NXJ has tools for dealing with servos that afford a much better learning experience, in my opinion. The leJOS API provides setRange(), setAngle(), setPulseWidth(), getAngle(), and getPluseWidth(). At the very least you will need to call setRange and setAngle on servos. That's because setAngle depends on a range of movement having been set with setRange. With leJOS it behooves you to set servos to a safe range of movement before moving it around, and to do so you have to understand something about how pulse width modulation makes servos run. Two articles do an excellent job explaining how to servos work , one from Jameco Electronics and one from Science Buddies. But there is still a gap of information when it comes to using the setRange and setAngle methods. The documentation provides the following:

public void setRange(int microsecLOW, int microsecHIGH, int travelRange) "Set the allowable pulse width operating range of this servo in microseconds and the total travel range. Default for pulse width at instantiation is 750 & 2250 microseconds. Default for travel is 200 degrees. " The parameters are defined as follows:
microsecLOW - The low end of the servos response/operating range in microseconds
microsecHIGH - The high end of the servos response/operating range in microseconds
travelRange - The total mechanical travel range of the servo in degrees
To better understand what these values mean I created some diagrams that make clear the function of each parameter.
The minimum and maximum PWM allowed are 750 and 2250, but if you use these  you are in danger of hitting the robot.
If the servo horn is attached such that the servo's physical stops are tilted the arm can hit the robot even with a safe min and max PWM range.
The third argument to setRange sets the number of programmable positions  between the min and max limits.
Setting the travelRange to 10, for example, will greatly reduce the precision it is capable of.

Monday, October 14, 2013

Music class for use with leJOS NXJ playNote and playTone methods

As an exercise I've written a Music class that makes writing NXT melodies easier by allowing note values to be passed instead of frequencies. I used this page as a reference: http://www.phy.mtu.edu/~suits/notefreqs.html. Any suggestions are appreciated. I hope someone finds it useful! Here's a little vid: http://blogs.hewittnet.org/robotics/files/2013/10/IMG_1008.mov

import lejos.nxt.Sound;
public class Music {
    private static String[] notes = { "C3", "C#3", "Db3", "D3", "D#3", "Eb3",
            "E3", "F3", "F#3", "Gb3", "G3", "G#3", "Ab3", "A3", "A#3", "Bb3",
            "B3", "C4", "C#4", "Db4", "D4", "D#4", "Eb4", "E4", "F4", "F#4",
            "Gb4", "G4", "G#4", "Ab4", "A4", "A#4", "Bb4", "B4", "C5", "C#5",
            "Db5", "D5", "D#5", "Eb5", "E5", "F5", "F#5", "Gb5", "G5", "G#5",
            "Ab5", "A5", "A#5", "Bb5", "B5", "C6" };
    private static float[] frequency = { 130.81f, 138.59f, 138.59f, 146.83f,
            155.56f, 155.56f, 164.81f, 174.61f, 185.0f, 185.0f, 196.0f,
            207.65f, 207.65f, 220.0f, 233.08f, 233.08f, 246.94f, 261.63f,
            277.18f, 277.18f, 293.66f, 311.13f, 311.13f, 329.63f, 349.23f,
            369.99f, 369.99f, 392.0f, 415.3f, 415.3f, 440.0f, 466.16f, 466.16f,
            493.88f, 523.25f, 554.37f, 554.37f, 587.33f, 622.25f, 622.25f,
            659.26f, 698.46f, 739.99f, 739.99f, 783.99f, 830.61f, 830.61f,
            880.0f, 932.33f, 932.33f, 987.77f, 1046.5f };
    /**
     * method uses playTone method
     * @param note is a String representation of the musical note in range C3-C6. See notes[] for allowed values
     * @param duration is note duration in ms
     */
    public void musicTone(String note, int duration) {
        for (int i = 0; i < notes.length; i++) {
            if(note.equals(notes[i])) {
                Sound.playTone((int)frequency[i], duration);
                Sound.pause(duration);
            }
        }
    }
    /**
     * method uses playNote method with Sound.XYLOPHONE as instrument argument
     * @param note is a String representation of the musical note in range C3-C6. See notes[] for allowed values
     * @param duration
     */
    public void musicXylo(String note, int duration) {
        for (int i = 0; i < notes.length; i++) {
            if(note.equals(notes[i])) {
                Sound.playNote(Sound.XYLOPHONE,(int)frequency[i], duration);
            }
        }
    }
    /**
     * method uses playNote method with Sound.PIANO as instrument argument
     * @param note is a String representation of the musical note in range C3-C6. See notes[] for allowed values
     * @param duration
     */    
    public void musicPiano(String note, int duration) {
        for (int i = 0; i < notes.length; i++) {
            if(note.equals(notes[i])) {
                Sound.playNote(Sound.PIANO,(int)frequency[i], duration);
            }
        }
    }
    /**
     * method uses playNote method with Sound.FLUTE as instrument argument
     * @param note is a String representation of the musical note in range C3-C6. See notes[] for allowed values
     * @param duration
     */        
    public void musicFlute(String note, int duration) {
        for (int i = 0; i < notes.length; i++) {
            if(note.equals(notes[i])) {
                Sound.playNote(Sound.FLUTE,(int)frequency[i], duration);
            }
        }
    }
}
Here is an example implementation of the class:

import lejos.nxt.Sound;

public class MusicTest {
    private static String[] melody = { "C4", "D4", "E4", "C4", 
        "E4", "C4",    "E4"};

    public static void main(String[] args) {
        Music music = new Music();
        for (int i = 0; i < melody.length; i++) {
            music.musicPiano(melody[i], 300);
            System.out.println(melody[i]);
        }
        Sound.pause(300);
        for (int i = 0; i < melody.length; i++) {
            music.musicTone(melody[i], 300);
            System.out.println(melody[i]);
        }
    }
}