Logging, Exceptions, and Errors
You've written your code, fixed the compiler errors, and yet, the program still isn't behaving as intended. The tools described on this page will help you further debug your program and figure out where in the code things are going wrong.
Logging
You can enable logging to get more debugging information. Turning on logging happens through a Phidget API function. This would happen at the very start of your program, before even initializing your software object or opening it. Logging lets you get feedback from the Phidget libraries about every Phidget API call you make.
In C, turning on logging to the command line would look like:
Phidget_enableLogging(phidgetHandle, PHIDGET_LOG_DEBUG, NULL);
Phidget_disableLogging();
Or in Java:
phidgetHandle.enableLogging(LogLevel.DEBUG, null);
phidgetHandle.disableLogging();
Where phidgetHandle
is the name that you've declared for this particular Phidget. The use of null is to indicate that the output is not to a file (and hence to the command line). Otherwise, the second argument would be a string filename.
There are six different logging levels, ranging from "Give me Everything!" to "Tell me only about critical problems". The level in the examples above - PHIDGET_LOG_DEBUG
- is a medium output level.
CRITICAL = 0x1
- Critical error messages.
- This is the lowest logging level. Errors at this level are generally non-recoverable and indicate either hardware problems, library bugs, or other serious issues.
ERROR = 0x2
- Non-critical error messages.
- Errors at this level are generally automatically recoverable, but may help to track down issues.
WARNING = 0x3
- Warning messages.
- Warnings are used to log behavior that is not necessarily in error, but is nevertheless odd or unexpected.
DEBUG = 0x4
- Debug messages.
- Debug messages are generally used for debugging at Phidgets Inc.
- Note: PHIDGET_LOG_DEBUG messages are only logged in the debug version of the library, regardless of logging level. Thus, these logs should never be seen outside of Phidgets Inc.
INFO = 0x5
- Informational messages.
- Informational messages track key happenings within phidget21 - mostly to do with threads starting and shutting down, and the internal USB code.
VERBOSE = 0x6
- Verbose messages.
- This is the highest logging level. Verbose messages are informational messages that are expected to happen so frequently that they tend to drown out other log messages.
You can also find this list of log levels in the Enumerations section of the Phidget22 API documentation.
Exceptions and Errors
There are two different types of errors that you can use to determine where a problem exists in your program.
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 #9 on a board that only has eight. The function you used to read port 9 would return an error code (in C/C++) or throw an error event (in languages that support exceptions like Java, .NET, 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 try...catch
in languages that support exceptions (e.g., Java, .NET, Python).
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:
int LocalErrorCatcher (int errorCode) {
if (errorCode != 0) { // Everything is okay if errorCode = 0
switch (errorCode) {
case EPHIDGET_INVALIDARG: // example error handler
printf("Invalid arguments sent to function.");
// do other things specific to this error
break;
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));
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 (like the INVALIDARG example), and you can write customized code to do special things reacting to that specific error. This is useful for applications where errors are an inevitability due to (potentially incorrect) user input, and you want to be able to handle and correct them in real-time. The default case only prints a general message, and is more useful for general debugging.
Or in Java, you would try a Phidget function call, and catch any resulting exception that occurs:
try {
device.open();
} catch (PhidgetException exception) {
system.out.println("The description for error " + Integer.toString(exception.getErrorCode()) + " is: ", exception.getDescription());
}
As with the previous example, you could also use a try...catch
statement around the exception.getErrorNumber() and exception.getDescription() functions to catch any errors from those calls.
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), errors are returned using exceptions which will leave you no choice but to catch them, or have your program terminate when the exception occurs.
Be careful when trying to determine what is causing the exception. Depending on how your code is structured, you can have exceptions that claim to be a particular Phidget exception but in fact have originated from non-Phidgets code(for example, a non-Phidgets function called from inside a Phidgets event handler).
Two: An error generated as 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:
int ErrorEventHandler (PhidgetHandle device, void *usrptr, Phidget_ErrorEventCode errorCode, const char *errorDescription) {
printf("The description for error %d is: %s\n", errorCode, errorDescription);
// Do something useful based on the error code
return 0;
}
// At the beginning of your program, hook the Error Event Handler in to receive events
LocalErrorCatcher(
Phidget_setOnErrorHandler((PhidgetHandle) device, ErrorEventHandler, NULL));
You'll note that the ErrorEventHandler 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 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 and the LocalErrorCatcher function are described above.
In Java, it would look like this:
try {
device.addErrorListener((ErrorEvent ee) -> {
System.out.println("Error: " + ee.getDescription());
});
});
} catch (PhidgetException exception) {
system.out.println("The description for error " + Integer.toString(exception.getErrorCode()) + " is: ", exception.getDescription());
}
Like C above, the act of hooking an error listener in to the device can itself generate an error, which should be caught.
These event-type 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 Phidget22 API.
Error Codes
These codes are used within the Error Event. See the Phidget22 API documentation for your device to see which codes can be returned by which functions. These codes can be very generalized so it’s important to look at the accompanying description. These codes are broken down into errors that stem from within the library, errors which are directly reported by Phidget hardware, and errors that occur in your software.
Library Errors
BAD_VERSION
- Version Mismatch Error. Usually means client and host side of a network connection are out of sync.
BUSY
- ???
Device Errors
SUCCESS or OK
- An error state has ended. You can use the
getDescription
method of the error event to get more information.
OVERRUN
- Sampling overrun. Some samples were lost in firmware because a queue filled up.
PACKET_LOST
- Packet(s) were lost. Usually happens when a data event is stalled by the user.
WRAP_AROUND
- A variable has wrapped. For example, the encoder position can wrap from 2,147,483,647 to -2,147,483,648 because of an integer overflow.
OVER_TEMPERATURE
- Over-Temperature condition detected. See description for more details.
OVER_CURRENT
- Over-Current condition detected. See description for more details.
OUT_OF_RANGE
- Out of range condition detected. Usually an input on the board is reporting a value that is outside of the allowed range.
BAD_POWER
- Power supply problem detected. Either the power supply is being overloaded, or it is not powered (ie. not plugged in).
SATURATION
OVER_VOLTAGE
FAILSAFE_CONDITION
VOLTAGE_ERROR
ENERGY_DUMP_CONDITION
OVER_CURRENT_ENDED
OVER_TEMPERATURE_ENDED
OUT_OF_RANGE_ENDED
BAD_POWER_ENDED
OVER_VOLTAGE_ENDED
COMMUTATION_ERROR
Software Errors
These codes are returned by Phidget API functions / thrown as exceptions on errors. See the Phidget22 API for your language to see which codes can be returned by which functions. In C/C++, a return code of 0 indicates success, any other return code is a failure. In languages supporting exceptions, most functions a will return void, and throw an exception on error. All Phidgets functions will return an integer value that corresponds to one of the following cases or 0 which is a success.
EPHIDGET_NOTFOUND = 1
- Phidget not found exception. “A Phidget matching the type and or serial number could not be found.”
- This exception is not currently used externally.
EPHIDGET_NOMEMORY = 2
- No memory exception. “Memory could not be allocated.”
- This exception is thrown when a memory allocation (malloc) call fails in the c library.
EPHIDGET_UNEXPECTED = 3
- Unexpected exception. “Unexpected Error. Contact Phidgets Inc. for support.”
- This exception is thrown when something unexpected happens (more unexpected than another exception). This generally points to a bug or bad code in the C library, and hopefully won’t even be seen.
EPHIDGET_INVALIDARG = 4
- Invalid argument exception. “Invalid argument passed to function.”
- This exception is thrown whenever a function receives an unexpected null pointer, or a value that is out of range. ie setting a motor’s speed to 101 when the maximum is 100.
EPHIDGET_NOTATTACHED = 5
- Phidget not attached exception. “Phidget not physically attached.”
- This exception is thrown when a method is called on a device that is not attached, and the method requires the device to be attached. ie trying to read the serial number, or the state of an output.
EPHIDGET_INTERRUPTED = 6
- Interrupted exception. “Read/Write operation was interrupted.”
- This exception is not currently used externally.
EPHIDGET_INVALID = 7
- Invalid error exception. “The Error Code is not defined.”
- This exception is thrown when trying to get the string description of an undefined error code.
EPHIDGET_NETWORK = 8
- Network exception. “Network Error.”
- This exception is usually only seen in the Error event. It will generally be accompanied by a specific Description of the network problem.
EPHIDGET_UNKNOWNVAL = 9
- Value unknown exception. “Value is Unknown (State not yet received from device, or not yet set by user).”
- This exception is thrown when a device that is set to unknown is read (e.g., trying to read the position of a servo before setting its position).
- Every effort is made in the library to fill in as much of a device’s state before the attach event gets thrown, however, many there are some states that cannot be filled in automatically (e.g., older interface kits do not return their output states, so these will be unknown until they are set).
- This is a quite common exception for some devices, and so should always be caught.
EPHIDGET_BADPASSWORD = 10
- Authorization exception. “Authorization Failed.”
- This exception is thrown during the Error event. It means that a connection could not be authenticated because of a password miss match.
EPHIDGET_UNSUPPORTED = 11
- Unsupported exception. “Not Supported.”
- This exception is thrown when a method is called that is not supported, either by that device, or by the system (e.g., calling setRatiometric on an InterfaceKit that does not have sensors).
EPHIDGET_DUPLICATE = 12
- Duplicate request exception. “Duplicated request.”
- This exception is not currently used.
EPHIDGET_TIMEOUT = 13
- Timeout exception. “Given timeout has been exceeded.”
- This exception is thrown by waitForAttachment(int) if the provided time out expires before an attach happens. This may also be thrown by a device set request, if the set times out (though this should not happen, and would generally mean a problem with the device).
EPHIDGET_OUTOFBOUNDS = 14
- Out of bounds exception. “Index out of Bounds.”
- This exception is thrown anytime an indexed set or get method is called with an out of bounds index.
EPHIDGET_EVENT = 15
- Event exception. “A non-null error code was returned from an event handler.”
- This exception is not currently used.
EPHIDGET_NETWORK_NOTCONNECTED = 16
- Network not connected exception. “A connection to the server does not exist.”
- This exception is thrown when a network specific method is called on a device that was opened remotely, but there is no connection to a server (e.g., getServerID).
EPHIDGET_WRONGDEVICE = 17
- Wrong device exception. “Function is not applicable for this device.”
- This exception is thrown when a method from device is called by another device. ie casting an InterfaceKit to a Servo and calling setPosition.
EPHIDGET_CLOSED = 18
- Phidget closed exception. “Phidget handle was closed.”
- This exception is thrown by waitForAttachment() if the handle it is waiting on is closed.
EPHIDGET_BADVERSION = 19
- Version mismatch exception. “Webservice and Client protocol versions don’t match. Update to newest release.”
- This exception is thrown in the error event when connection to a Phidget Webservice that uses a different protocol version then the client library.
Other Problems
If your Phidget is still not behaving as expected after handling errors and exceptions, have a look at our General Troubleshooting guide to track down the problem.
Further Reading
Phidget Programming Basics - Here you can find the basic concepts to help you get started with making your own programs that use Phidgets.
Data Interval/Change Trigger - Learn about these two properties that control how much data comes in from your sensors.
Using Multiple Phidgets - It can be difficult to figure out how to use more than one Phidget in your program. This page will guide you through the steps.
Polling vs. Events - Your program can gather data in either a polling-driven or event-driven manner. Learn the difference to determine which is best for your application.
Phidget Network Service - Phidgets can be controlled and communicated with over your network- either wirelessly or over ethernet.