General Phidget Programming: Difference between revisions

From Phidgets Support
(Redirected page to Phidget Programming Basics)
 
(159 intermediate revisions by 4 users not shown)
Line 1: Line 1:
This page presents the general '''concepts''' needed to write code for a Phidget.
#REDIRECT [[Phidget Programming Basics]]
 
By this point, you should have installed the drivers for your [[Software Overview#Operating System Support|operating system]] and the libraries for your [[Software Overview#Language Support|specific programming language]]. 
 
==The Basic Functions==
 
To use your Phidget within code, you'll want to:
# Create a Phidget [[#Creating a Software Object|software <code>object</code>]], which gives you access to the functions specific to that device
# [[#Opening the Phidget|Open the Phidget]] using the <code>object</code>
# Detect when a [[#Attaching the Phidget|Phidget is attached]] (plugged in) by using the <code>object</code>
# Use [[#Do Things with the Phidget|functions that the <code>object</code> provides]], like turning on LEDs, reading sensors, triggering events on data change, etc
# [[#Close the Phidget|Close the <code>object</code>]], when you are done
 
=== Creating a Software Object ===
 
Phidget devices are controlled using software objects.  All software device objects have a common API and set of functions that allow you to '''open''' it, '''close''' it, and set a few listeners to general events such as '''attach''' (plug in), '''detach''' (unplug), and errors. 
 
But when you create an actual software object, it is a software object '''specific''' to your device.
 
For example, in Java:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
 
  // Create a new Accelerometer object
  AccelerometerPhidget device = new AccelerometerPhidget();
 
</source>
</font>
</div>
<br>
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
 
 
  // Create a new RFID device object
  RFIDPhidget device = new RFIDPhidget();
 
</source>
</font>
</div>
 
Or in C:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
 
    // Create a new Accelerometer object
    CPhidgetAccelerometerHandle device = 0;
    CPhidgetAccelerometer_create(&device);
 
</source>
</font>
</div>
<br>
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
 
    // Create a new RFID device object
    CPhidgetRFIDHandle device = 0;
    CPhidgetRFID_create(&device);
 
</source>
</font>
</div>
 
 
Each software object has an API and available functions which are specific to that device.  For example, the RFID device API includes a function to turn on the RFID antenna.  The accelerometer device API includes a function to set the sensitivity on each axis.
 
=== Opening the Phidget ===
 
Phidgets can either be opened when attached directly to a computer, or they can be opened remotely using the [[Phidget Webservice]].  This section deals primarily with opening Phidgets directly.
 
Once you have created your [[#Creating a Software Object|software object]] for your specific type of device, you can call the <code>open()</code> function in your language on that object.  For example, in Java:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
    device.open();
</source>
</font>
</div>
 
Or in C:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
    CPhidget_open((CPhidgetHandle) device, -1);
</source>
</font>
</div>
 
All specific language calls can be found in the API documentation located on each [[#Language Support|individual language page]].
 
The <code>open()</code> function in any language opens the software object for use, not the hardware itself.  Having the software "open" before the hardware means that the software can capture all events, including multiple attach (plug in) and detach (unplug) events for one <code>open()</code> call.
 
=== Attaching the Phidget ===
 
Physically, attaching a Phidget means plugging it in.  In your code, you can detect an attachment either with an '''event''' in [[#Event Driven Code|event-driven programming]], or '''waiting''' for it, in [[#Logic Code|logic programming]].
 
==== Event Attachment ====
 
For example, to use an event to detect attachment in Java:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
  // After creating a Phidget object called "device":
  device.addAttachListener(new AttachListener() {
      public void attached(AttachEvent ae) {
          System.out.println("A new device has been plugged in!");
      }
  });
</source>
</font>
</div>
 
Or to use an event to detect attachment in C:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
  int AttachHandler (CPhidgetHandle device, void *userData) {
      printf("A new device has been plugged in!");
      return 0;
  }
 
  // .....Then, in the main code after creating a Phidget object "device":
  CPhidget_set_OnAttach_Handler((CPhidgetHandle) device, AttachHandler, NULL);
</source>
</font>
</div>
 
Both of the code snippets above do the same thing.  The function <code>AttachHandler(...)</code> is called automatically when a device is plugged in.
 
You will want to attach events (via <code>addAttachListener()</code> above, for example) '''before you open the Phidget object'''.  Otherwise, triggered events may be lost.
 
This method for using events to detect attachment can be expanded to other events and more complex control flow.  Where possible, all example code downloadable from the [[#Language Pages|specific language pages]] shows event-driven programming.
 
==== Wait for Attachment ====
 
Waiting for attachment is a straightforward process.  Your code does not handle events, it simply waits for a device to be plugged in before moving on and doing something else.
 
For example, in Java you wait for attachment on a '''created and open''' software object (called device) like this
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
  // Wait until a device is plugged in
  device.waitForAttachment();
</source>
</font>
</div>
 
Or in C (again, device has been '''created and opened''') :
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
  int result;
  // Wait up to 10000 ms for a device to be plugged in
  if((result = CPhidget_waitForAttachment((CPhidgetHandle) device, 10000))) {
      // No attachment, error
  }
  // Successful attachment
</source>
</font>
</div>
 
So, unlike the event model above, a Phidget software object should be open before waiting for a device to be plugged in.
 
=== Do Things with the Phidget ===
 
After you have a Phidget software object (named, for example, <code>device</code> as above) that is:
*Created
*Properly attached to any events
*Opened
*Attached (plugged in)
 
...Then, you can actually call function to turn LEDs on, change output state, read data from sensors, etc.
 
The thing you probably want to do with your Phidget is read data from its sensors, say, a sensor plugged in to an <span style="color:red;"Interface Kit 8/8/8</span>.  You can do this either
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=cpp>
 
  int val;
  for (int i = 0; i < 10; i++) {
    CPhidgetInterfaceKit_getSensorValue(phid, 0, &val);
    printf("Value: %d\n", val);
  }
 
</source>
</font>
</div>
 
The things you can do with your particular Phidget are many and varied, so you probably want to refer directly to the API for your device. 
 
We provide both documentation on the raw API for each programming language as well as a language-independent description of the calls for each device.
* Read the raw API list on your [[Software Overview#Language Support|your specific programming language]] page, in the Getting Started section.
* Read the high-level API description for your hardware on <span style="color:red;">your specific Phidget device</span> page.
 
=== Close the Phidget ===
 
When you are finished with the Phidget software object at the end of your program, you should close and (in some languages) delete it.
 
For example, in Java:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
  device.close();
  device = null;
</source>
</font>
</div>
 
Or, in C:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
    CPhidget_close((CPhidgetHandle) device);
    CPhidget_delete((CPhidgetHandle) device);
</source>
</font>
</div>
 
 
===Using Multiple Phidgets===
 
Each Phidget has a unique serial number.  Using this serial number, you can use a specific [[General Phidget Programming#Opening the Phidget|open]] call to open by serial number.
 
For example, in Java, this would be:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
    device.open(SerialNumber);
</source>
</font>
</div>
 
Or in C:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
    CPhidget_open((CPhidgetHandle) device, serialNumber);
</source>
</font>
</div>
 
 
 
For each event, you can then check the serial number of the device handed through the event, and act accordingly. 
 
 
For example, in Java, your [[General Phidget Programming#Event Attachment|attach event handler]] might look like this:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
    detachHandler = new DetachListener() {
        public void detached(DetachEvent event) {
            int serialNumber = ((Phidget)event.getSource()).getSerialNumber();
            // Do something according to serialNumber
    }    }
</source>
</font>
</div>
 
Or in C:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
    int AttachHandler(CPhidgetHandle IFK, void *userptr) {
int serialNo;
CPhidget_getSerialNumber(IFK, &serialNo);
        // Do something according to serialNumber
    }
</source>
</font>
</div>
 
== Putting It Together ==
 
User and device actions can be handled by either:
*Letting the program tell you when they happen and then doing something ('''event driven''' code)
*Polling for things to happen then doing something ('''logic''' code)
 
The style of programming you choose (and hence the language you might prefer) would depend on what you want to do with the Phidget.  The two sections, [[#Event Driven Code|Event Driven Code]] and [[#Logic Code|Logic Code]] below give benefits, drawbacks, and general examples of each style.
 
The styles can also mix.  For example, you can take a defined set of steps at first such as turning on an LED or antenna (logic code) and then doing nothing until an output change event is fired (event code).
 
With languages that support both styles, you can mix and match.  For languages that support only logic code (see the [[#Language Support|Language Support Categories]] above) you can only use the logic paradigm style.
 
Examples in pseudo-code are given below for each style type so you can see how your language choice can affect your code design.
 
=== Logic Code ===
 
Logic code has use for:
* Simple, single-device applications
* Non-GUI applications (GUIs usually are event driven)
* The user driving the device rather than listening to it
 
Logic code is relatively easy to design well.  For example, using the [[#Creating a Software Object|create]], [[#Opening a Phidget|open]], [[#Attaching a Phidget|attach]], [[#Do Things with the Phidget|do stuff]], and [[#Close the Phidget|close]] concepts introduced above, logic code to handle a Phidget might be written like this:
 
<br>
 
[[File:logic.png]]
 
<br>
 
Although this design does not explicitly capture every event that fires when data or input changes, by polling the device often enough no data will be lost.
 
However, logic code cannot handle constant, asynchronous events as cleanly as [[#Event Driven Code|event driven code]] can.
 
These designs can be mixed.  So, if you find that in logic code you have a highly complex <code>if</code> loop driving your program, you should consider changing some of it to event driven code.  This type of awkward if-loop might look like this:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=c>
 
  Create Device Software Object
  Open Device
 
  Loop Until Exit Requested {
    if No Device Attached {
        Wait For Attachment until Timeout
        if Wait Timeout Reached {
            break
        } else {
            Initialize Device
        }
    } else {  // Device Is Attached
        if Device Data Type 1 Changed {
            Do Something
        }
        if Device Data Type 2 Changed {
            Do Something Else
        }
        // ... More data change functions here
    }
    Collect User Input
  }
 
  Close Device
  Delete Device
 
</source>
</font>
</div>
 
On the other hand, you can probably see that if your language does not give the option for events, you can use this structure to mimic what events would enable you to do.
 
=== Event Driven Code ===
 
Event driven code allows for clean handling of complex, asynchronous programs:
*Handling multiple Phidgets
*Handling active plugging or unplugging of the Phidget (multiple attach and detach events)
*Working behind a GUI, as many GUIs are already event driven
*Capturing all sensor data - or input and output - without constantly polling
 
''Without'' event driven code, you will need to constantly poll the device to see if any state has changed.  If you poll at a slower rate than your input or output changes, you will not capture all data.
 
However, event driven code is usually not as useful or efficient for:
*Only one open and close event
*Using only one device
*Having the user (or program) ''put'' changes onto the device (in contrast to reading data ''from'' the device)
 
Event driven code is relatively hard to design well.  It may help to draw out a '''flowchart''', '''state machine''', or at least a '''pseudo-code outline''' of your system design and all events you wish to handle before writing code.
 
The code examples given for each [[#Language Support|specific language]] use events if they are supported by the language.
 
Using the [[#Creating a Software Object|create]], [[#Opening a Phidget|open]], [[#Attaching a Phidget|attach]], [[#Do Things with the Phidget|do stuff]], and [[#Close the Phidget|close]] concepts introduced above, event code to handle a Phidget might be written like this:
 
[[File:event.png]]

Latest revision as of 20:47, 28 February 2019