Argot. Building a language for Arduinos.

Arduino Blink Tutorial

arduino-argot-blink-1.0.zip

This tutorial provides a very basic demonstration of developing a simple binary protocol to communicate with an Arduino. While it does not use many of the features of Argot, it provides the building blocks from which more complex applications and Argot languages can be built.

The tutorial uses Java for the host language. To run the example you require:

  1. To have read over the Argot quick start example. This provides some good context.
  2. An Arduino capable of running the 'blink' example. Most likely all of them!
  3. Have the Rxtx serial library installed. For OSX I used this native library.
  4. Have Eclipse or other Java IDE to run the software.

To download and setup the project in eclipse, do the following:

  1. Download the file arduino-argot-blink-1.0.zip.
  2. Extract the zip file into your Arduino directory.
  3. In Eclipse select File->Import.
  4. Select "General->Existing Projects into Workspace".
  5. Select "Select root directory" and browse to the directory in your Arduino folder.
  6. Select finish.

To run the example, first open the ArgotBlink.ino file in Arduino and upload it onto your Arduino. Next, in Eclipse run the StartHere class as a Java Application.

The Argot Blink Protocol

The first step with any Argot application is defining the language or protocol to be used to communicate. In this example, a 5-byte packet structure is defined using Argot:

cluster blink;

definition blink.packet 1.0:
{
	@start        #uint8;
	@length       #uint8;
	@command      #uint8;
	@milliseconds #uint16;
};

The visual representation of this packet structure is as follows:

		-----+--------+--------+--------+--------------+-----
		     | 8 bits | 8 bits | 8 bits | 16 bits      |
		-----+--------+--------+--------+--------------+------
		       start    length   command  milliseconds

The start byte signifies to the arduino that this is the start of a packet. If for some reason the Arduino is out of sync with the host, start byte(s) can help it re-align. The next byte is the length of the packet; in this case it is always three. We could add different commands of different lengths later and keep the same format. A length also simplifies the receiving code and makes it more generic. The command byte signifies to the Arduino what action to take. In this case there's only two commands:

  1. Value 0 - Tells the Arduino to change the length of milliseconds to leave the light on.
  2. Value 1 - Tells the Arduino to change the length of milliseconds to leave the light off.

The final 16 bits is the length of time to leave the light on or off. As it is unsigned 16-bit integer, the maximum value can be 65535 (65 seconds). More than enough for this example.

The Java Host

With the packet structure defined, the next step is to create the Packet structure in Java. For this I'm using the Argot Annotation Marshaller. The Annotation marshaller binds each component of Packet to a Java attribute.

@ArgotMarshaller(ArgotMarshaller.Marshaller.ANNOTATION)
public class Packet 
{
	public static final String TYPENAME = "blink.packet";
	
	@ArgotTag("start")
	public int soh;
	
	@ArgotTag("length")
	public int length;
	
	@ArgotTag("command")
	public int command;
	
	@ArgotTag("milliseconds")
	public int milliseconds;

	...
}

The full source code also adds an enumerated Command type to make the code easier to read.

Load and bind the library

In Argot, all data types are stored in a type library. With the data types defined and the object created in Java, the next step is to compile and load the type library.

typeLibrary = new TypeLibrary( );
ArgotCompilerLoader loader = new ArgotCompilerLoader("blink.argot")
{
	public void bind( TypeLibrary library )
	throws TypeException
	{
		library.bind( library.getTypeId(Packet.TYPENAME, "1.0"), Packet.class );
	}
};
typeLibrary.loadLibrary(loader);

Open the stream and write the commands

In this example I'm using a SerialTransport class which wraps the RxTx Serial library and makes it easier to use in Argot. To open a connection, the ports, data rate and timeout is provided. The TypeEndPoint class simply wraps the input and output stream preparing it for use.

SerialTransport transport = new SerialTransport(PORT_NAMES, DATA_RATE, TIME_OUT);
TypeEndPoint endpoint = transport.openLink();

To write the commands to the Serial link, an Argot wrapper is created around the stream with the TypeOutputStream.

TypeMap typeMap = new TypeMap( typeLibrary, new TypeMapperDynamic(new TypeMapperCore(new TypeMapperError())));
TypeOutputStream typeOut = new TypeOutputStream( endpoint.getOutputStream(), typeMap );

Note: The TypeMap is required here, however, it's capabilities are not really being used in this example. More on this in later tutorials.

To write the command to the stream the Packet object is created and written using the TypeOutputStream. Argot handles all the marshalling.

Packet command = new Packet(Command.SET_DELAY_OFF,50);		
typeOut.writeObject( Packet.TYPENAME, command );

The Arduino Code

In this example the focus is on the implementation of writing binary packets on the Java host. On the Arduino side, a hand crafted simple Serial reader has been implemented. The main command handling is handled by the processCommand function.

// Process the command after receiving the complete packet.
void processCommand()
{
  Serial.println("Arduino: Process command message");
  uint8_t command = read_u8();
  uint16_t delay = read_u16();

  if (command == 0)
  {
    Serial.print("Arduino: Received command set delay on: ");
    Serial.println(delay);
    delayOn = delay;
  }
  else
  {
    Serial.print("Arduino: Received command set delay off: ");
    Serial.println(delay);
    delayOff = delay;
  }
}

This reads the command as an uint8 and delay time as uint16 and then changes the delay times accordingly.

The Output

The communication from the Arduino back to the host is used for debug messages. If all goes well, you should see something like the following as output.

Arduino: Argot Blink service started.
Host: Writing command 'set delay off 50'
Host: Sleeping 10 seconds
Arduino: got header character
Arduino: got command length: 3
Arduino: Process command message
Arduino: Received command set delay off: 50
Host: Writing command 'set delay on 1000'
Host: Sleeping 10 seconds
Arduino: got header character
Arduino: got command length: 3
Arduino: Process command message
Arduino: Received command set delay on: 1000
Host: Closing link

Conclusion

This simple example provides the basic building blocks to do more advanced applications and protocols with Argot. Be sure to check back on the web-site regularly to see new examples. If you have any issues or queries please contact david using the email below.