How to Use Multiple Phidgets in an Application

An Interface Kit with Joystick, and a Stepper MotorIn many Phidgets projects, more than one Phidget device is required to carry out the necessary functionality. For instance, to have a responsive system that has a motor open a vent when the temperature exceeds a certain limit, you’d need a motor controller and an interface kit with analogue input. It’s also quite common to pair spatial devices and motor controllers in unmanned vehicles, like quadcopters. Some users need more than sixteen digital outputs and inputs, so a couple of 1012 Phidget Interface Kits are needed.

There are a few options for distinguishing between Phidgets in an application. Labels and serial numbers will distinguish between devices where you know these attributes. However, the Phidget Manager provides a more powerful and versatile tool, and it’s part of the Phidget API. The Phidget Manager allows enumeration of all connected devices and notification of device attach and detach events.

Handling Multiple Phidgets

Options like labels and serial numbers can be used when you have multiple Phidgets. There are some advantages to labels, discussed in a previous blog post. The most relevant use for labels, when using multiple Phidgets, is to give each device a meaningful name. Another advantage is that when you need to replace the Phidget device, you can give the replacement the same name as the one that’s petered out, so the program doesn’t need to be re-written. Unfortunately, labels and some label functions aren’t available on all platforms and in all languages.

The preferred method for systems where you will be using multiple Phidgets is the PhidgetManager. The manager is especially useful if you’re expecting the system to operate long enough (or under harsh enough conditions) that the Phidgets will need replacing. The manager is also more versatile than labels. It allows you to check device type, version, status and some other attributes before creating a Phidget object, ensuring that you have the right device.

To explore the Phidget Manager more fully, you can try the HelloWorld programming examples – available for most of the languages we support.

How to use the Device Manager

A Phidget Manager object can detect all Phidgets attached to a system, and it maintains a list of these Phidgets. With this, you can obtain a limited selection of attributes, available from the Phidget Common library, like:

  • type
  • version
  • serial number
  • status
  • label

Some properties of specific Phidgets can also be accessed, like input count, output count and sensor count on the interface kit and motor count on some motor controllers.

After creating and opening the Manager, you can get the list of attached devices. In C, this will look something like this:

    CPhidgetManagerHandle mgr = 0;
    CPhidgetManager_create(&mgr);
    CPhidgetManager_open((CPhidgetManagerHandle) mgr);

  // Allow the Phidgets time to attach</pre>
 sleep(1);

  // Retrieve the list of attached Phidgets from the manager</pre>
 CPhidgetManager_getAttachedDevices(mgr, &devices, &numDevices);

To do the same thing in Java, it will look like this:

  Manager mgr;
  mgr = new Manager();
  try {
      mgr.open();
  } catch (PhidgetException exception) {
      printError(exception.getErrorNumber(), exception.getDescription());
  }

  // Allow the Phidgets time to attach
  Thread.sleep(1000);

  // Retrieve the list of attached Phidgets from the manager
  Vector devices = mgr.getPhidgets();

Because the manager maintains a list of Phidgets objects (as opposed to Phidget Interface Kits or Phidget Motors), you’ll still have to cast them as the more specific class of Phidget to have access to more device-dependant functions. You can get the serial number, or label, from the device in order to open it. For a Phidget Interface Kit, opening it from the Phidget Manager in C will look something like this:

      // Where devices is the array of PhidgetHandle objects
      // and ifkit8 is an uninitialized PhidgetInterfaceKitHandle object
      CPhidget_getSerialNumber((CPhidgetHandle)devices[i], &serialNum);
      ifkit8 = (CPhidgetInterfaceKitHandle)devices[i];
      CPhidgetInterfaceKit_create((CPhidgetInterfaceKitHandle)ifkit8);
      CPhidget_open((CPhidgetHandle)ifkit8, serialNum);
      CPhidget_waitForAttachment((CPhidgetHandle)ifkit8, 10000);

The same thing in Java will look like this:

      // Where devices is a Java Vector of Phidgets objects
      // and ifkit8 is an uninitialized InterfaceKitPhidget object
      serialNumber = ((Phidget)devices.get(i)).getSerialNumber();
      ifkit8 = new InterfaceKitPhidget();
      ifkit8.open(serialNumber);
      ifkit8.waitForAttachment(1000);

You can then go on to set events handlers (or listeners, etc – depending on what language you’re using) for each device the Manager has connected:

      CPhidgetInterfaceKit_set_OnInputChange_Handler(ifkit8, InputChangeHandler, NULL);
      CPhidgetInterfaceKit_set_OnSensorChange_Handler(ifkit8, SensorChangeHandler, NULL);
      CPhidgetInterfaceKit_set_OnOutputChange_Handler(ifkit8, OutputChangeHandler, NULL);

And in Java:

      ifkit8.addInputChangeListener(new InputChangeListener() {
            public void inputChanged(InputChangeEvent oe) {
                  System.out.println(oe);
            }
      });
      ifkit8.addOutputChangeListener(new OutputChangeListener() {
            public void outputChanged(OutputChangeEvent oe) {
                  System.out.println(oe);
            }
      });
      ifkit8.addSensorChangeListener(new SensorChangeListener() {
            public void sensorChanged(SensorChangeEvent se) {
                  System.out.println(se);
            }
      });

All this that I’ve just demonstrated, creating Phidget objects and setting up handlers, is usually done in an initialization function. You can then respond to input, output and sensor changes of the devices you have attached.

In some languages, like C/C++, you can pass a pointer (for instance, a pointer to another PhidgetHandle object) into event handler functions using the userPtr argument. For instance, if you wanted the motor to activate upon some sensor change, instead of setting userPtr to NULL you could pass in a CPhidgetStepperHandle* like this:

CPhidgetInterfaceKit_set_OnSensorChange_Handler(ifkit8, SensorChangeHandler, &motor);

The SensorChangeHandler function could then look something like this:

int CCONV SensorChangeHandler(CPhidgetInterfaceKitHandle IFK, void *phidgetPtr, int Index, int Value)
{
    int stopped;
    __int64 curr_pos;
    CPhidgetStepperHandle motor = *(CPhidgetStepperHandle *)phidgetPtr;

    if (Index == TEMPERATURE_POSITION)
    {
        CPhidgetStepper_getCurrentPosition (motor, MOTOR_POSITION, &curr_pos);

        if (Value >= 410) // 410 is about 30 degrees celsius
        {
            if (curr_pos < 50) // need to activate the motor
            {
                CPhidgetStepper_setEngaged (motor, MOTOR_POSITION, PTRUE);
                CPhidgetStepper_setTargetPosition (motor, MOTOR_POSITION, 400);

                stopped = PFALSE;
                while(!stopped)
                {
                    CPhidgetStepper_getStopped(motor, MOTOR_POSITION, &stopped);
                }
                CPhidgetStepper_setEngaged (motor, MOTOR_POSITION, PFALSE);
            }
        }
        else if (curr_pos > 50) // value is less than 410 AND motor position is greater than 50
        {
            CPhidgetStepper_setEngaged (motor, MOTOR_POSITION, PTRUE);
            CPhidgetStepper_setTargetPosition (motor, MOTOR_POSITION, 0);

            stopped = PFALSE;
            while(!stopped)
            {
                CPhidgetStepper_getStopped(motor, MOTOR_POSITION, &stopped);
            }
            CPhidgetStepper_setEngaged (motor, MOTOR_POSITION, PFALSE);
        }
    }

    return 0;
}

Unfortunately, most languages don’t support this functionality, but you can program using logic code instead of events, or try global variables accessible by the functions, if your preferred language supports that.

Distinguishing Events

If you are using event-driven code, once you have correctly opened multiple Phidgets of different types, they will have different event handlers and, as a result, you will know which Phidget triggered which event. If you are trying to determine which Phidget triggered the event within general events (such as Attach Events), you can then check the serial number (or device type, label, etc) of the triggering device and act accordingly.

Conclusion

Using the Phidget Manager offers a more robust solution for your application than relying on serial numbers or labels, although both of those latter options are available to you if you just require something quick and easy. Once you have a Phidget Manager check for devices, you can set up each device to behave as you would in any other program, either with event-driven or logic code. When it comes time to replace Phidgets in the system, you don’t need to recompile the code with new serial numbers, just run it from the start and you’re good.

For a lower-level overview of what the Manager does, refer to the documentation on Phidgets.com, and for some more code samples see the Phidget Programming documentation. Finally, as mentioned before, the HelloWorld programming examples (available for most of the languages we support) demonstrate how the manager works.

How are you using multiple Phidgets in your projects and what techniques are you using to get them to work? Please share your strategies in the comments.

Advertisements
About

Math lover. Engineering communicator. Mad-lib enthusiast. Total nerd.

Tagged with: ,
Posted in How-Tos

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: