General Phidget Programming: Difference between revisions

From Phidgets Support
(Redirected page to Phidget Programming Basics)
 
(93 intermediate revisions by 4 users not shown)
Line 1: Line 1:
__TOC__
#REDIRECT [[Phidget Programming Basics]]
 
This page presents the general '''concepts''' needed to write code for a Phidget.
 
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
 
Small code snippets are provided for each step below.  [[Language - C/C++|C++]] and [[Language - Java|Java]] were selected because Java is a relatively high-level language and C++ is a relatively low level language, thereby showing how specific each language API really is.  So, the most useful resource for the ''actual functions'' would be the API for [[Software Overview#Language Support | your specific language]].  This page is a high-level introduction, by design.
 
 
=== 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 [[Software Overview#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.
 
====Details for Open()====
 
Open will return immediately once called, because it can be called even if the Phidget to be used is not attached to the system. This is known as an asynchronous call. It’s important to understand that most calls on a Phidget will fail if they are calls when the Phidget is not attached - in fact the only calls that are allowed on a detached Phidget are <code>close()</code>, <code>waitForAttachment()</code> and <code>getAttached()</code>.
 
Open is also pervasive. This means that once open has been called, it will constantly try to stay attached to a Phidget. Even if the Phidget is unplugged from the computer and then plugged back in, you will simply get a Detach event, and then an Attach event. It’s a good idea to handle the Detach event in order to avoid calling the Phidget after it has detached.
 
The different types of open(), such as openAny(), openRemote(), etc. can be used with parameters to try and get the first device it can find, open based on its serial number, or even open across the network.  The [[General API|API overview]] lists all of the available modes that open provides, and you can find even more detail in the API for [[Software Overview#Language Support|your specific language]].  If there are more than one of the same type of Phidget attached to a computer, and you use open() with no serial number, there is no way of knowing which Phidget will be opened first.
 
Once a Phidget is opened by an application, it cannot be opened again in another application until closed by the first.  When open and attached in software, no other programs or instances can read data from or change the Phidget. The one exception is if the Phidget is controlled ''only'' over the network with the [[Phidget Webservice]], and not directly.  Then, you can use multiple remote control programs.
 
 
 
=== 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 downloads from the [[Software Overview#Language Support|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 [[#Creating a Software Object|properly created]] Phidget software object, 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 or inputs.  This might be, say, a sensor plugged in to a [[Product - 1018 - PhidgetInterfaceKit 8/8/8 | 1018 - Interface Kit 8/8/8]] used in the code snippets below.  You can do this either by detecting changes via [[#Event Driven Code|event driven code]], or polling for new values via [[#Logic Code|logic code]].
 
'''Details about data handling:'''
 
*When a Phidget is opened, its initial state will be read before it is marked as attached. This allows polling of many properties -- including some data -- even during the Attach event, and anytime afterwards.
 
*If you are handling data using events as described below, the data event functions will fire when the device is plugged in and its initial state is read.
 
*Some properties have default values, but these should not be trusted. Remember: '''always set''', don’t rely on defaults.  Trying to read an uninitialized value with no default will result in an Exception.
 
*Often Phidgets will retain their last state unless power is lost. This can give surprising results as the previous state may not always be what you expect. For example, if you open an InterfaceKit and set an output, this output may stay set even after the Phidget is closed.
 
====Capture Data Change with Events====
 
To capture data changes in sensors or inputs as they happen, you need to use [[#Event Driven Code|event driven code]].
 
Like defining an event function that fires [[#Event Attachment|when the Phidget is plugged in]], you can create functions that automatically run when, for example, a sensor value or input value changes.
 
For example, for an Interface Kit, you can create a function that gets called when a sensor changes.  You would do this '''before''' the Phidget software object has been [[#Opening the Phidget|opened]].
 
In Java, this would look like:
<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.addSensorChangeListener(new SensorChangeListener() {
      public void sensorChanged(SensorChangeEvent sensorEvent) {
          System.out.println("New Value: " + sensorEvent.getValue());
      }
  });
</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=cpp>
  int SensorChangeHandler (CPhidgetHandle device, void *userData, int boardIndex, int newValue) {
      printf("New Value %d from sensor at location %d\n", newValue, boardIndex);
      return 0;
  }
 
  // .....Then, in the main code after creating a Phidget object "device":
  CPhidget_set_OnSensorChange_Handler((CPhidgetHandle) device, SensorChangeHandler, NULL);
</source>
</font>
</div>
 
====Poll for Data Change====
 
To poll for sensor data, or output state, you usually want to look for a '''get...Value''' or '''get...State''' function available in the [[Device List|API for your device]].  Then, you simply set up a loop that get the value of a sensor continuously.
 
To poll your software object, the object must be [[#Opening the Phidget|open]].  This is in contrast to the event-driven method above, where all event functions are declared and attached before opening the object.
 
These code snippets assume <code>device</code> is an [[Product - 1018 - PhidgetInterfaceKit 8/8/8 | Interface Kit 8/8/8]].  For example, in Java, for the Sensor at location 5 on the board:
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
  int val;
  for (int i = 0; i < 10; i++) {
    val = device.getSensorValue(5);
    System.out.println("Value: " + val);
  }
</source>
</font>
</div>
 
Or, in C, for the Sensor at location 5 on the Interface Kit board:
<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(device, 5, &val);
    printf("Value: %d\n", val);
  }
</source>
</font>
</div>
 
 
====Sensors, Input, and Output====
 
Often, your Phidget will be something like an [[Product - 1018 - PhidgetInterfaceKit 8/8/8 | Phidget Interface Kit]] which has either analog inputs (black plug holes), or digital inputs and outputs (green screw attachments), or often both.
 
* To the analog inputs, you can attach various sensors, including sensors for temperature, humidity, light, sound, and so on. 
* To the digital inputs, you can attach various input devices, including switches.
* To the digital outputs, you can attach status tools like LEDs.
 
You use these sensors in software entirely through the software object for the Phidget plugged in to your USB port.  For example, to turn off an LED at output block 1 on on an RFID tag reader, you'll want to set the output at location 1 to "0" (or false).  In C, this would be:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=cpp>
    // Create the RFID software object:
    CPhidgetRFIDHandle device = 0;
    CPhidgetRFID_create(&device);
 
    // Open and handle the attachment of the PhidgetRFID object
    ....
 
    // Then, turn the LED off, passing first the output number, then the new state:
    CPhidgetRFID_setOutputState(device, 1, 0);
</source>
</font>
</div>
 
Or 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>
    // Create the RFID software object:
    RFIDPhidget device = new RFIDPhidget();
 
    // Open and handle the attachment of the RFID object
    ....
 
    // Then, turn the LED off, passing first the output number, then the new state:
    device.setOutputState(1, 0);
</source>
</font>
</div>
 
Getting a digital input would follow the same pattern, except you would use the getOutputState function and you would not pass the function a new output state.
 
Getting an analog input is a little more complicated because:
# You must declare the sensor as one of two types (ratiometric or non-ratiometric)
#* To find out what your sensor is, read the product information [[Device List | for your specific sensor]]
# You must translate the 1-1000 reading that you get from the input into the data that you need (temperature, etc)
#* If the sensor comes from Phidgets, we provide a translation equation in the product information [[Device List | for your specific sensor]]
 
Other than that, reading an analog sensor mirrors reading a digital input.  For example, to obtain the lux from the [[Product - 1127 - PrecisionLightSensor | Precision Light Sensor]], a '''non-ratiometric''' sensor plugged into analog input 5, you would do this in C:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=cpp>
    // Change measurement to non-ratiometric style
    CPhidgetInterfaceKit_setRatiometric(device, 0);
 
    // Get the data from analog input 5
    int sensorValue;
    CPhidgetInterfaceKit_getSensorValue(device, 5, &sensorValue);
 
    // In this case, the measured light lux equals the sensor value.
    int lux = sensorValue;
</source>
</font>
</div>
 
Or in Java:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
    // Change measurement to non-ratiometric style
    device.setRatiometric(0);
 
    // Get the data from analog input 5
    int sensorValue = getSensorValue(5);
 
    // In this case, the measured light lux equals the sensor value.
    int lux = sensorValue;
</source>
</font>
</div>
 
====Learning Everything You Can Do====
 
The things you can do with your particular Phidget are many and varied, so we only include general concepts on this page.
 
You can go one of two places for more information on what functions are available for your specific 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 API for your [[Software Overview#Language Support| specific programming language]], available as a download on each page.
* Read the API overview for your hardware on the page for [[Device List|your specific Phidget]].
 
 
 
=== 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>
 
The <code>close()</code> call removes the lock that [[#Opening the Phidget|open]] put on the Phidget.  Make sure to close your object, so other software can use the Phidget!
 
The close() function also makes sure the thread associated with the Phidget close properly.  Any outstanding writes will block close() until they complete, because writes are guaranteed to complete (unless a device is detached).
 
Also note that a device should be put into a known state before calling close. For example, if a motor controller is driving a motor and close is called, it will continue to drive the motor even though the application has exited. This may or may not be what you want.
 
 
 
===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 device, void *userptr) {
int serialNo;
CPhidget_getSerialNumber(device, &serialNo);
        // Do something according to serialNumber
    }
</source>
</font>
</div>
 
 
 
===Using Phidgets over a Network===
 
Control of a Phidget over a network uses the [[Phidget Webservice]].
 
 
 
== 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 [[Software Overview#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 the Phidget|open]], [[#Attaching the 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 [[Software Overview#Language Support|specific language]] use events if they are supported by the language.
 
Using the [[#Creating a Software Object|create]], [[#Opening the Phidget|open]], [[#Attaching the 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]]
 
Once you have written this code flow, the actual order of events that occur within the program look something like this:
 
[[File:Eventhandler.jpg|160px]]
 
Note that the device itself initiates the function call, by 'firing' the event.  This allows you to update only when events fire, and capture all changes, because the low-level interface is telling you when a change occurs.
 
 
 
==Advanced Concepts==
 
Now that you have the basic [[#Creating a Software Object|create]], [[#Opening the Phidget|open]], [[#Attaching the Phidget|attach]], [[#Do Things with the Phidget|do stuff]], and [[#Close the Phidget|close]] concepts introduced above, there are other useful concepts which will help you design your code to be persistent and stable.
 
 
 
===Threading===
 
Due to the use of events, the Phidget library uses threading extensively.
 
For example:
* Calling <code>open()</code> starts a central thread.
* Closing everything will shut that central thread down (before the final close returns).
* Each device, once attached, starts its own read and write threads.
 
These threads provide the support to perform your typical [[#The Basic Functions|Basic Functions]]:
 
* Triggering of data events come from the context of a device read thread.
* Attach and detach events come from the context of the central thread.
* The central thread looks for device attaches and detached, keeping track of which devices are attached internally, and sending out attach and detach events to Phidgets and Managers.
* Writes are performed asynchronously by the write thread. The write queue is only 1 deep so calling a write function while there is a write pending will block.
 
All Phidget libraries are '''thread safe''', so you don’t need to do any locking on the Phidget objects.
 
 
 
===Exceptions and Errors===
 
There are two different types of errors that you can use to confirm that your program is running correctly.
 
====One: An error generated by a function call====
 
These errors are generated by ''you'' calling a function.  For example, you might try to read analog sensor port number 150 on a board that only has eight.  The function you used to read port 150 would return an error (in C/C++) or throw an error (in event languages like Java or Python). 
 
So, these errors happen ''synchronously'' to function calls, that is, they are returned or thrown right after a function returns.  You can handle these by checking the return values on your functions (in C/C++) or using an error catching method like <code>try...catch</code> in languages that support exceptions (e.g., Java, .NET, Python, AS3).
 
For example, in C, you might write a LocalErrorCatcher function that you can then use on every Phidget function call to detect and deal with errors:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=cpp>
  int LocalErrorCatcher (int errorCode) {
 
      if (errorCode != 0) {  // Everything is okay if errorCode = 0
   
          switch (errorCode) {
            default:
              const char *errorDescription;
              LocalErrorCatcher(
                  CPhidget_getErrorDescription (errorCode, &errorDescription));
              printf("The description for error %d is: %s\n", errorCode, errorDescription);
              break;
          }
      }
      return 0;
  }
 
  // ... Then, later, you would use it on any Phidget function:
  LocalErrorCatcher(
      CPhidget_open((CPhidgetHandle) device, -1));
 
</source>
</font>
</div>
 
Note that:
# The function LocalErrorCatcher uses itself to check for errors on getting an error description. 
# You can handle individual error codes as they are listed in the API.  This only prints a general message.
 
Or in Java, you would try a Phidget function call, and catch any resulting exception that occurs:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
  int serialNumber;
  String name = new String();
 
  try {
    serialNumber = ((Phidget)event.getSource()).getSerialNumber();
    name = ((Phidget)event.getSource()).getDeviceName();
  } catch (PhidgetException exception) {
      System.out.println("Error occurred while getting device information");
  }
 
</source>
</font>
</div>
 
The consequences of not catching this type of error (on ''every'' function) differ by programming language.
In C/C++ these errors must be ''explicitly'' checked for after each function call, otherwise the program will simply continue on in an incorrect state.  In languages that support exceptions (e.g., Java, .NET, Python, AS3), errors are returned using exceptions which will leave you no choice but to catch them, or have your program terminate without warning.
 
====Two: An error generated by an event====
 
These errors are generated by the Phidget library during runtime.  For example, the Phidget device might be experiencing too high a temperature, and trigger an error.  This would not necessarily be due to any one function your program called; rather, the error would appear when the problem appears and would trigger an event.
 
So, these errors happen ''asynchronously'', that is, something happens apart from any function calls and an error event is triggered. You can handle these by setting up an Error Event Handler.
 
In C, this would look like:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=cpp>
  int ErrorEventHandler (CPhidgetHandle device, void *usrptr, int errorCode, const char *errorDescription) {
    printf("Error, Number %d - %s\n", errorCode, errorDescription);
    // Do something useful based on the error code
    return 0;
  }
 
  LocalErrorCatcher(CPhidget_set_OnError_Handler((CPhidgetHandle) device, LibraryErrorHandler, NULL));
</source>
</font>
</div>
 
You'll note that the '''LibraryErrorHandler''' function is what gets called when an error event occurs, and it gives you an opportunity to handle the error. 
 
You'll also note that there is a second function called '''LocalErrorCatcher'''.  This second function handles the return value on the function from setting the  error handler.  We included it here because, as these are examples on how to handle errors, the example would leave a possibly unhandled error without it. This second type of error handling is [[One: An error generated by a function call|described above]].
 
In Java, it would look like this:
 
<div style="background-color: #f3f3f3; border-color: #1c9edb; border-width:1px; border-style: dashed;">
<font size="3">
<source lang=java>
try {
ik.addErrorListener(new ErrorListener() {
public void error(ErrorEvent ee) {
System.out.println(ee);
}
});
 
                } catch (PhidgetException exception) {
                    System.out.println("Error occurred on Detach");
                }
</source>
</font>
</div>
 
These errors are also how a Phidget being run over a network announces bad passwords, lost packets, and other network problems.  Locally, the errors can announce incorrect temperatures, current, and power. So, it is in your best interest to set up an error event handler and take action based on the codes and error types in the API [[Software Overview#Language Support|for your programming language]].
 
 
 
See the [[General API]] or the API for your [[Software Overview#Language Support|specific programming language]] for error code documentation.
 
===Sensitivity and Filtering===
 
Change Triggers are used to filter the number of events that are returned to an Application, by setting a minimum amount of activity before a Change Event is sent to your program.
 
This is a simple hysteresis - a minimum amount of change has to occur since the last event before another event will be fired.
 
If your application is implementing its own filtering, setting the ChangeTrigger to zero will cause all events to fire. Change triggers are generally available only for sensor inputs events. Change triggers are referred to as ''Sensitivity'' in some [[Device List | device specific APIs]].
 
 
 
===Data Rate===
 
Some devices support a user-defined data rate for events.
 
* The data rate is set in milliseconds, with a range from up 1ms to 1000ms, depending on the Phidget.
* Data rates greater then 8ms generally need to be a multiple of 8 (8,16,24,...,496,...,996,1000).
* Data rates lower then 8ms are supported as: 4ms, 2ms, 1ms.
* Data rate is a maximum rate
* Data rate will be superseded by a non-zero sensitivity on devices that support both sensitivity and data rate.
 
See the main page for [[Device List | your specific device]] for more details.

Latest revision as of 20:47, 28 February 2019