Mini Maestro 18 and Java

Hi,
today I received my Mini Maestro 18-channel and I immediately connected it to my pc.
The driver and the Control Center are working. I can move the servos without problems.
Now I want to controll it with my java program:

public void send(int channel, int position){
        try{
          outputStream.flush();
          outputStream.write((byte) 0xFF);
          Thread.sleep(50);
          outputStream.write((byte) channel);
          Thread.sleep(50);
          outputStream.write((byte) position);
        }catch(Exception e){}
}

I call the method send():
send(0,200);

While connecting the green LED flashes but the servo doesn’t move. What is wrong ?

greetings from germany

Hello,

That part of the code might work, but the delays are unnecessary and you should not ignore exceptions if you want to know what is going wrong.

Most likely you are connecting to the wrong COM port, or your Maestro is in the wrong serial mode. Can you explain how you selected these options?

-Paul

Hi,
i removed the delays and changed the COM-Port and now it works great.
I post my source code for others who are searching for java based programming:

I used the RXTX JAVA Communication API (http://www.rxtx.org).

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.io.OutputStream;
import java.util.Enumeration;


public class ServoController{

	private CommPortIdentifier serialPortId;
	private Enumeration enumComm;
	private SerialPort serialPort;
	private OutputStream outputStream;
	private int baudrate = 9600;
	private String portName = "COM4";

	public ServoController(){
            if(openSerialPort(portName)){
                  moveAround();
            }else{
                  System.out.println("Connection failed !");
            }
	}

        public void moveAround(){
            try{
                while(true){
                    send(0, 2400);
                    Thread.sleep(1000);
                    for(int i = 2400; i < 8800; i+= 10){
                        send(0, i);
                        Thread.sleep(2);
                    }
                    Thread.sleep(1000);
                }
            }catch(InterruptedException ex){
                closePort();
            }
        }

	public boolean openSerialPort(String portName){
            boolean foundPort = false;
            enumComm = CommPortIdentifier.getPortIdentifiers();
            while(enumComm.hasMoreElements()) {
                    serialPortId = (CommPortIdentifier) enumComm.nextElement();
                    if(portName.contentEquals(serialPortId.getName())) {
                            foundPort = true;
                            break;
                    }
            }
            if(!foundPort)
                    return false;

            try{
                serialPort = (SerialPort) serialPortId.open(this.getClass().getName(),2000);
                outputStream = serialPort.getOutputStream();
                serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            }catch(Exception e){
                return false;
            }
            return true;
	}

	public void closePort(){
            serialPort.close();
	}

	public void send(int channel, int position){
            String pos = Integer.toBinaryString(position);
            String buf = "";
            for(int i = 0; i < 14 - (pos.length()); i++)
                buf += "0";
            pos = buf + pos;

            try{
                outputStream.flush();
                outputStream.write((byte) 0x84);
                outputStream.write((byte) channel);
                outputStream.write((byte) Integer.parseInt(pos.substring(7,14), 2));
                outputStream.write((byte) Integer.parseInt(pos.substring(0,7), 2));
            }catch(Exception e){
                System.out.println(e.getMessage());
            }
	}

        public static void main(String[] args){
            new ServoController();
        }
}

But I have a new question: how can I turn on/off the red LED over the COM-Port ?

Okay, I am happy that it is working for you now. What does “Comport Api is RXTX” mean?

We do not have a serial command for turning the red LED on and off. However, you could use the Command 0xA7 together with the following pair of subroutines to do this:

sub my_led_on
  led_on
  quit

sub my_led_off
  led_off
  quit

-Paul

Great, it works.

I use the following code:

public void led(boolean on){
            try{
                outputStream.flush();
                outputStream.write((byte) 0xA7);
                if(on){
                    outputStream.write((byte) 0x00);
                }else{
                    outputStream.write((byte) 0x01);
                }
            }catch(Exception e){}
        }

led(true); // turns it on
led(false); // turns it off

Thank you for help.

Great!

-Paul

Hallo tobi, hallo paul,

the code above does not working for me on the ubuntu box. I renamed the devices /dev/ttyACM0 and /dev/ttyACM1 to /dev/USB0 and /devUSB1 because the RXTXComm lib dos not recognizes ttyACM prefixed ports. While sending the green led flashes, but the servo does not move. I tried with both renamed devices. What could be wrong?

Here is another code, this one does not work for me too. The commands are sent without any exceptions but the servos doesn’t response:

// we use the library from rxtx.org for communication with serial port
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class PololuSerialExample {
	public PololuSerialExample() {
		super();
	}

	static void listPorts() {
		java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier
				.getPortIdentifiers();
		while (portEnum.hasMoreElements()) {
			CommPortIdentifier portIdentifier = portEnum.nextElement();
			System.out.println(portIdentifier.getName() + " - "
					+ getPortTypeName(portIdentifier.getPortType()));
		}
	}

	static String getPortTypeName(int portType) {
		switch (portType) {
		case CommPortIdentifier.PORT_I2C:
			return "I2C";
		case CommPortIdentifier.PORT_PARALLEL:
			return "Parallel";
		case CommPortIdentifier.PORT_RAW:
			return "Raw";
		case CommPortIdentifier.PORT_RS485:
			return "RS485";
		case CommPortIdentifier.PORT_SERIAL:
			return "Serial";
		default:
			return "unknown type";
		}
	}

	public static void main(String[] args) {

		// We renamed /dev/ttyACM0 to /dev/ttyUSB0 because the rxtx.org library
		// doesn't recognize devices prefixed by ttyACM.
		String portName = "/dev/ttyUSB0";

		// Contents of this test file after program end:
		// FF 00 00 FF 01 00 ... FF 05 00
		// FF 00 7F FF 01 7F ... FF 05 7F
		// FF 00 FE FF 01 FE ... FF 05 FE
		// ...
		String fileName = "/tmp/bytes.bin";

		try {

			listPorts();

			CommPortIdentifier portIdentifier = CommPortIdentifier
					.getPortIdentifier(portName);
			if (portIdentifier.isCurrentlyOwned()) {
				System.out.println("Error: Port is currently in use");
			} else {
				CommPort commPort = portIdentifier.open("Owner", 2000);
				if (commPort instanceof SerialPort) {

					// we create a output stream for serial port:
					SerialPort serialPort = (SerialPort) commPort;
					serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
							SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
					OutputStream serialStream = serialPort.getOutputStream();

					// we create a file output steam for test purposes
					File file = new File(fileName);
					OutputStream fileStream = new FileOutputStream(file);

					// We try to move servos to min, middle and max
					// positions
					byte command = (byte)0xFF; 
					for (int position = 0; position < 255; position += 127) {
						// Our servos are on the channels 0 and 1 (on the
						// power connector side) but we send to all
						for (int servo = 0; servo < 6; servo++) {

							// write some info on the console
							String message = String.format(
									"Writing command=%d servo=%d, psition=%d",
									command, servo, position);
							System.out.println(message);

							// we create a byte sequence to send
							byte[] bytes = new byte[] { (byte) command,
									(byte) servo, (byte) position };

							// while writing the green led flashes
							serialStream.flush();
							serialStream.write(bytes);
							fileStream.write(bytes);
						}
						Thread.sleep(1000); // wait a half second
					}
					commPort.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Hello,

What serial mode is your Maestro configured to?

-Paul

Hallo Paul,

thx for reply. I reconfigured the serial port with MaestroControlCenter as follows:

Serial mode: USB Dual Port
Enable CRC: false
Device Number: 0
Mini SSC offset: 0
Timeout: 0
Newer sleep: false

With this settings my code works as expected!

thx

Wladimir

Welp… I’m retarded…
(netbeans 6.9.1, rxtx api with the rxtxcom and serial.dll dropped in the right bin and ext locations, winXP sp3)
I’m also trying to complie tobi’s java example for a meastro 6channel and have gotten no joy.
I get one flash from the green led but no servo movement and another single flash from the led upon closing the program.
Within device manager, the command port is listed on com3 and ttl is com4, I’ve tried both with the same results.
Using the usccmd --getconfig FILE shows Serial mode: USB Dual Port, Enable CRC: false,Device Number: 0,Mini SSC offset: 0,Timeout: 0, Newer sleep: false.
I’ve spent most of my time looking at the commport method but any comport detection examples I run always list com3 and com4

My questions are vague but I’m hoping they lead to something significant: What would you guys recommend I really look at as the most likely breakdown?
is outputStream.write((byte) 0x84 the appropiate “format” for a 6 channel?
Thanks for any input, I could use any guidance you guys can offer.
SteveZ

Have you added the RXTX libary correctly in netbeans ?
Are there any errors ?

I followed the instructions for netbeans in the wikirxtx org page and got no errors when I compiled. I comfirmed the correct install with a commport test which correctly identified the two usb/com ports. It doesn’t set off any exceptions, making it all the way to the outputstream.write calls… it’ll println(serialportid.getname())… not sure whatelse to look at. But thank you for posting the code in the first place tobi… very cool!

Do you call the moveAround() method ? Does the green LED flashes while the program is running ?

Try to put the code in a .jar file (F11 in netbeans).
Then copy the two .dll files in the same directory and the lib folder with RXTXcomm.jar.

Hello catfishez,

Can you move servos with the Maestro Control Center? You did not mention having any servo power connected. Is it possible that you forgot that? In any case, I recommend using the Maestro Control Center for debugging rather than watching for movement.

-Paul

I’ve put the serial and parallel.dll in the same directory and the rxtxcomm.jar in the lib as you instructed and nothing…
Now this question is going to get me laughed at but may illustrate the root of my problem… I’ve complied the code from post three which as I understood, called moveAround() from serialController, which cycles the servo in a loop… Is there still a need to call moveAround()? If “yes” then I’ve got some serious understanding ahead of me… Insights?
The green led flashed once at the start of the program and once when closed… no flashing inbetween, while the loop is running.

Paul, Yes power is connected via the bat pins and full control (servo movement) can be had with either MCC or the UscCmd…

Oh and thanks for the help sofar guys, I know it can be tediuos holding noobs’ hands while they figure out the simple stuff but you have my graditute

Hi there, can anyone tell me how to rename the ttyACM0 to ttyUSB0?
Do i really have to use udevadm and add the rules to the /etc/udev/rules.d?
It’s a bit confusing…

Thanks

Hello, John.

I don’t know the proper way to rename COM ports from ttyACM* to ttyUSB*, but you could try using “ln -s …” to make a symbolic link from ttyUSB99 to one of the ttyACM ports and maybe that will be good enough. I haven’t tried this so I don’t know if it will work.

–David

Ok thanks, i allready solved that problem by checking the device attributes with udevadm info and i added a file with rules adding a symbolic link to ttyACM0 to ttyUSB0 in /etc/udev/rules.d .
By the way i think i’ve tryed that approach and didn’t work for me on ubuntu 10.04.