User Tools

Site Tools


OrbShield concepts and demos

The Basic Orb Sketch

The most basic thing you can do with the OrbShield and a device is to make it appear to the operating system as a USB HID Joystick. The sketch to do this is the BasicJoystick sketch:

#include <orbotron_device.h>
#include <orbotron_buffer.h>
#include <orbotron_translator.h>
#include <chart_3.h>
// change "SpaceOrb360" to 
// SpaceBall4000 for SpaceBall 4000FLX devices
// SpaceBall5000 for SpaceBall 5000 or Magellan SpaceMouse devices
Logical_orbotron orb_buffer( SpaceOrb360 );
Orbotron_translator translator;
Orbotron_device orb_device;
void setup()
  translator.set_sensitivity_table( sensitivity_3_chart );
void loop()
  orbotron_checkinit( orb_buffer, translator, orb_device );
  orbotron_translate( orb_buffer, translator, orb_device );

The loop() function should almost always be the same, but varying the setup function may be important depending on the sensitivity, bindings, polarity, etc you desire.

The default settings (particularly axis assignments and polarity) work for many people. If you are using the SpaceOrb in an “edge” configuration or are using the SpaceBall 4000 in a right-handed configuration, you may need to adjust axis assignments and polarity settings.


The original SpaceOrb only came with six buttons, a serious limitation with most games. However, the OrbShield portrays the SpaceOrb to the host computer as a six-axis, sixteen-button device. It is possible to use the six buttons on the SpaceOrb to seem as if sixteen buttons are available through the use of multiple buttons, a technique known as chording.

When chording is enabled, the two edge buttons on the orb (A and B) are used to select a “page” for the other four buttons (c-f). The assignments work as follows:

if neither A nor B is pressed, C-F are buttons 1-4 If A is pressed, C-F are buttons 5-8 If B is pressed, C-F are buttons 9-12 If A and B are pressed together, C-F are buttons 13-16 To enable chording, insert the following line in the setup() function of your orb sketch:

translator.set_chording( true );

You can examine chording in the BasicJoystick sketch by adding the above line and setting the value to true or false.

SpaceOrb users : Chording is enabled by default for the SpaceOrb 360.

SpaceBall users : It is not suggested to use chording with the SpaceBall 4000FLX at this time. The 4000FLX has twelve buttons already, but the HID reports going to the computer only support sixteen buttons.

Sensitivity and Gain


The SpaceOrb by default has a linear response, meaning that if you push it halfway from center to one edge, the result will be halfway along its possible range.

However, to make the response flatter near the center, the creators of the SpaceOrb preferred a cubic response. This is more easily envisioned with the following figure:

The preferred curve is curve #4 in the above picture. As you can see, near the center the curve is relatively flat, to permit reasonably fine-grained control, but ramps up sharply near the edges for fast movement when necessary.

This curve is called the sensitivity curve. To use the sensitivity curve in your sketches, add the line:

#include "chart_4.h"
At the top of your sketch, and in the setup() function, add:

translator.set_sensitivity_table( sensitivity_4_chart );


You may find that you need even more control over the motion of the orb. If so, you may add gain to your sketch. Gain acts as a 1/10th multiplier or divider for the final value of the orb; for example, if you would ordinarily have moved the orb so that its x-value is halfway from the center to the edge, with a gain of “20” you would have it at full deflection. Positive values of gain amplify the orb’s motion, such that a gain of 30 would be three times normal value; negative values of gain reduce the orb’s motion, such that a gain of -30 would be 1/3 normal value.

To set the global gain of your orb, add the following line to the setup() function of your sketch, changing the value of 30 to your desired value:

translator.set_gain( 30 );

Precision Gain

You may find that you want the orb to be more sensitive during motion, but wish to have it be less sensitive during aiming. To do this, you can use the precision gain feature of the OrbShield.

Precision gain changes the orb’s gain setting to a different value (typically a negative value to damp the orb’s reaction) when a particular button combination is pressed. This button combination is a binary number representing the combination of buttons used to activate precision gain. For example, if you wish to enable precision mode when button A is pressed, you would use a mask of 1 or 0x01. If you wished to enable it with button B pressed, use a mask of 2 or 0x02, or (0x01 « 1). If you wanted to use it only when BOTH button A and button B were pressed, use a mask of 3, or 0x01 || (0x01 «1).

You can enable precision mode in your own sketches by adding the following lines to the setup() function of your sketch:

translator.set_precision_gain( -20 );
translator.set_precision_mask( 0x01 );

You may explore sensitivity, gain, and precision gain in the GainDemo demo sketch. Upload the GainDemo sketch to your orb, open the control panel joystick applet, and move the orb about the X and Y axes; notice that the orb seems to have different sensitivity on the X axis vs the Y axis. Press button 1 and notice that the motion of the two axes changes dramatically.

Keyboard Axis Binding

Many games do not support joysticks, or if they do they do not support six-axis controllers such as the SpaceOrb. To add to the flexibility of the SpaceOrb, we implemented the ability to bind keyboard keypresses to various axes ranges.

This is best illustrated by an example, demonstrated (among other concepts) in the WASD demo. If you upload this to your SpaceOrb, you will discover on replugging that the X and Y axes now also produce WASD keypresses for motion in first-person shooter games (see below), and that pulling up or pushing down on the Z-axis results in space (jump) or control (duck) keypresses.

The latter is done by first adding some lines above the setup() function which describe the bindings:

PROGMEM Axis_key_binding axis_key_bindings[] =
    { 2, 773, 1023, MOD_CONTROL_LEFT, 0 },
    { 2, 0, 250, 0, KEY_SPACE }

Each line of the structure represents a binding in the form:

{ axis_number, min value, max value, modifiers, keypress }

Remember that the axes of the spaceorb go from 0 to 1023, with 512 the central value.

You must not forget the PROGMEM keyword before the structure! This places the bindings in static flash memory on the Arduino microcontroller where they will not interfere with the program itself.

Once your bindings are created, you must add these lines in the setup() function:

translator.set_axis_key_bindings( axis_key_bindings, 2 );

This sets the key bindings to those you defined above, and lets the OrbDuino software know there are six bindings.

Keyboard Fourway Bindings

Axis bindings as described above are ideal for binding a single axis to keypresses, but have difficulty when binding a plane of movement to keys representing directions of motion.

The reason for this can be easily demonstrated when trying to bind the orb to the WASD keys used by many FPS games for motion. A naive implementation would be to bind the X-axis to A and D, and the Y-axis to W and S as shown below:

This works reasonably well, but leaves a huge “null area” in the centre of the plane, requiring large motions to move. It may seem that the way to fix this is to shrink the size of the null area:

…however, this will not have the desired effect, because now it is almost impossible to, say, walk straight forward without moving to the left or right. What is more desirable is to have keyboard assignments to arcs in the plane:

To do this, the Fourway_keyboard_binding mechanism was created:

struct Fourway_keyboard_binding
  unsigned short axis_x;
  unsigned short axis_y;
  char n;
  char s;
  char e;
  char w;
  long deadzone_radius_squared;

To use it, create a Fourway_keyboard_binding in your arduino code:

const PROGMEM Fourway_keyboard_binding WASD_fourway_binding = { 0, 1, KEY_S, KEY_W, KEY_D, KEY_A, 75*75 };
and in your setup function, include the line:

translator.set_fourway_bindings( &WASD_fourway_binding, 1 );
In the WASD sketch, the X-Y plane is bound to WASD, the usual first-person shooter movement keys.

Keyboard Button Bindings

You can also bind button presses to keyboard events. To understand how these work, examine the WASD demo sketch.

Again, bindings are defined in a similar way, by using structures:

// sets buttons 4-7 to keyboard 1-4 (eg for weapon select)
PROGMEM Button_key_binding button_key_bindings[] =
    { 0x01 << 2, 0, KEY_1 },
    { 0x01 << 3, 0, KEY_2 },
    { 0x01 << 4, 0, KEY_3 },
    { 0x01 << 5, 0, KEY_4 },
In this case, the bindings take the form:

{ button id, modifier, keypress }
You must also add the following line in setup():

translator.set_button_key_bindings( button_key_bindings, 4 );
Again, the number reflects the number of bindings.

In the WASD sketch, buttons 3,4,5,6 are bound to keyboard keys 1,2,3,4.

Mouse Bindings

In the event a game does not accept joystick bindings at all, you may bind SpaceOrb axes to mouse movements and buttons to mouse buttons. Examine the WASD demo sketch to see this in action. With the WASD sketch loaded, your orb’s Rx and Rz axes will move the mouse, while buttons 1 and 2 are the left and right mouse buttons. The third button is available as well.

Binding Axes

To bind orb axes to mouse axes, add lines like the following to the top of your sketch:

PROGMEM Axis_mouse_binding axis_mouse_bindings[] =
    { 0, MOUSE_AXIS_X, 3 },
    { 1, MOUSE_AXIS_Y, 3 }
These bindings take the form:

{ spaceball axis, mouse axis, scale }

For now (0.9b2) scale is a shift; in other words “3” means that the value of the orb axis will be shifted three times to the right (divided by 8) to get the mouse axis value. To reverse the polarity of a mouse binding, negate the value of scale (in other words, if your y-axis is moving opposite the direction you expect, try setting the scale to “-3” instead of “3”)

You must also add the following line to the setup() function:

translator.set_axis_mouse_bindings( axis_mouse_bindings, 2 );

…where “2” is the appropriate number of bindings.

In the WASD sketch, the mouse x/y axes are bound to the orb’s Rz and Rx axes respectively.

Binding Buttons

Binding buttons to mouse buttons is very similar. Add lines like the following to the top of your sketch:

PROGMEM Button_mouse_binding button_mouse_bindings[] =
    { 0x01, 0x01 },
    { 0x01 << 1, 0x01 << 1 },
    { 0x01 << 2, 0x01 << 2 }
These are in the form:

{ spaceorb button, mouse button )
In the WASD sketch, buttons 1 and 2 are bound to mouse buttons 1 and 2.

products/orbotron9000/concepts.txt · Last modified: 2019/11/12 22:00 (external edit)