<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.phidgets.com/docs/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jdecoux</id>
	<title>Phidgets Support - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.phidgets.com/docs/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jdecoux"/>
	<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/Special:Contributions/Jdecoux"/>
	<updated>2026-04-06T11:35:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.8</generator>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34334</id>
		<title>Spatial Guide</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34334"/>
		<updated>2024-01-19T19:58:55Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Introduction to AHRS/IMU */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#seo:|description=Phidget Spatials combine data from accelerometers, magneometers, and gyroscopes into one sensor. This guide explains how the sensors are combined using AHRS, what you can do with this data.}}&lt;br /&gt;
{{#seo:|keywords=accelerometer, gyroscope, magnetometer}}&lt;br /&gt;
&lt;br /&gt;
[[Category:IntroGuide]]&lt;br /&gt;
{{TOC limit|3}}&lt;br /&gt;
&lt;br /&gt;
==Spatial Sensors and Their Uses==&lt;br /&gt;
[[Image:Spatial_Intro.jpg|link=|center]]&lt;br /&gt;
===Introduction to AHRS===&lt;br /&gt;
Spatial sensors from Phidgets use AHRS (Attitude and Heading Reference System) algorithms to combine data from accelerometers, magnetometers and gyroscopes into a calculation of the device’s orientation more precise than could be achieved by any of the sensors individually.&lt;br /&gt;
&lt;br /&gt;
While this process is by no means straightforward, PhidgetSpatial sensors come with built-in AHRS calculations combining data from all three types of sensors out of the box. By using the Phidget Spatial object in your code, you can get a direct reading of the heading of your device, in both Euler angle and Quaternion form.&lt;br /&gt;
&lt;br /&gt;
===Euler Angles===&lt;br /&gt;
[[File:EulerAngles.jpg|330px|link=|thumb|A Representation of Euler Angles]]&lt;br /&gt;
Euler angles are a measure of an object’s orientation in the form of pitch, roll, and yaw angles. The advantage of Euler angles in denoting heading is that they are relatively easy to visualise.&lt;br /&gt;
You can get the Euler angles of your sensor directly from the Phidgets library.&lt;br /&gt;
&lt;br /&gt;
While they are a human-friendly way of denoting overall orientation, we strongly recommend against using Euler angles in post-processing calculations, as they can be susceptible to problems of [https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics gimbal lock]. For applications requiring more adjustments than a simple heading offset, we recommend using quaternions.&lt;br /&gt;
&lt;br /&gt;
===Quaternions===&lt;br /&gt;
[[Image:quarternion.jpg|thumb|link=|A Visualization of Quaternions]]&lt;br /&gt;
For applications that require more complex analysis, PhidgetSpatial devices also provide the orientation of the device using quaternions. Quaternions are a more mathematically complete way of denoting orientation and rotations of a system. For what they lose in intuitiveness, the advantage of quaternions is that they can be used in any number of complex calculations without the risk of the aforementioned gimbal lock.&lt;br /&gt;
&lt;br /&gt;
For most practical purposes, it helps to remember that quaternions are not meant to be visualized, or dealt with directly. Instead, any program or library that uses them will have functions to perform calculations with them behind the scenes. If you don’t yet have such a library in your program, but need to use quaternions, we recommend finding one, rather than wading through the math yourself. In this way, while they are difficult to visualize, you can at least remain comfortable in the knowledge that one does not often need to fully understand quaternions to use them in an application.&lt;br /&gt;
&lt;br /&gt;
Quaternions tend to be the preferred rotation system for programs that deal with 3D objects, like Unity, and their inclusion as an output directly from a PhidgetSpatial is designed to make sensor integration as seamless as possible.&lt;br /&gt;
&lt;br /&gt;
===What Does AHRS Actually Do?===&lt;br /&gt;
The AHRS algorithm on Phidgets uses an accelerometer and a magnetometer to keep track of heading over long timescales. When the device is perceived to be at rest, the heading and gyroscopes are gradually aligned and zeroed to reflect that the device is not moving, and pointed towards combined direction from the magnetometer and accelerometer readings. When the device is in motion, the AHRS algorithm starts relying more heavily on the gyroscope for angular rotations, since the accelerometer may no longer be pointing straight down, and the field from the compass may be in flux. By adjusting how much the device relies on the gyroscope in place of the accelerometer and magnetometer, a smoother and more accurate profile of the device’s orientation can be achieved than by using any of the sensors alone.&lt;br /&gt;
&lt;br /&gt;
===Temperature Stabilization===&lt;br /&gt;
Electronic accelerometers and gyroscopes are sensitive to changes in temperature to a small but measurable degree. For cases where long term accuracy is a priority, some of our Spatial sensors have a temperature stabilization feature which allows the boards to heat themselves up to a pre-defined constant temperature (typically 45 or 50&amp;amp;deg;C) to reduce or eliminate drift due to temperature effects.&lt;br /&gt;
&lt;br /&gt;
When using the temperature stabilization feature, it is very important to wait for the board to be fully heated and settled before use, as the process of heating the board will change the sensor readings as the temperature rises to the target. Phidgets that allow temperature stabilization are calibrated at their target temperature, so the sensors will produce more accurate results once heated.&lt;br /&gt;
&lt;br /&gt;
If you are using a temperature-stabilized spatial sensor, it is also very important to keep the board in its enclosure or otherwise insulated from outside air, as air moving directly over the warmed sensors will cause worse results than if the board was not heated at all.&lt;br /&gt;
&lt;br /&gt;
==Demonstrations Using the Control Panel Example==&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note: &#039;&#039;&#039;If your control panel example does not resemble the following, be sure to update your Phidget Control Panel. &amp;lt;br&amp;gt;If your example still doesn&#039;t match, your Spatial Phidget is likely too old to support built-in AHRS calculations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Spatial_Example_AlignModel.jpg|400px|link=|thumb|Click the &#039;&#039;Align Model&#039;&#039; button to align the AHRS model to your screen]]&lt;br /&gt;
&lt;br /&gt;
The spatial example gives you a way to directly visualize the results from the AHRS algorithm used on Phidget Spatial sensors.  We recommend using this example with the sensor in hand at your desk to help visualize the effectiveness of the algorithm. &lt;br /&gt;
&lt;br /&gt;
The first thing you might notice is that the model doesn’t appear to match the orientation of the spatial in your hand. To make the AHRS model line up with your physical spatial, point the wire at the screen and click Align Model. Your spatial model should now mirror the movements of the spatial in your hand.&lt;br /&gt;
&lt;br /&gt;
The AHRS compass drawing is also provided as a visual indicator of the Heading, independent of the screen location. Notice that the compass bearing indicates north when the left-hand side of the Phidget is pointed north.&lt;br /&gt;
&lt;br /&gt;
If your sensor has a heating option, be sure to check the &#039;&#039;Heating Enabled&#039;&#039; box, and wait until the temperature reading stays green for best results. In your own programs, wait until the temperature reaches 45C, and then if possible give the sensor an additional minute or two to ensure the whole board is evenly heated.&lt;br /&gt;
&lt;br /&gt;
===AHRS Settings===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Settings.jpg|400px|link=|thumb|The AHRS Settings Box]]&lt;br /&gt;
Now we can look at the AHRS settings panel:&lt;br /&gt;
====Algorithm====&lt;br /&gt;
The algorithm setting dictates whether or not the compass is going to be factored into calculations.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;AHRS: &#039;&#039;&#039;When setting Algorithm to AHRS (the default setting) heading is gradually re-aligned with the compass over time, and all headings will be relative to magnetic north. When you Zero the AHRS algorithm, it will forcibly realign the heading to the compass reading.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;IMU: &#039;&#039;&#039;When using IMU, the compass readings are ignored, and a heading of 0° corresponds to the direction the device was facing when it was started, or where it was last zeroed. By clicking the Zero Algorithm button, it will realign all calculations to reference the direction it is currently facing as the new 0° heading.&lt;br /&gt;
&lt;br /&gt;
====Zero Algorithm====&lt;br /&gt;
The Zero Algorithm button centers the algorithm’s heading either on the compass reading or on the direction it is currently facing (see AHRS Mode). The accumulated gyro biases will also be dropped, reverting to the raw (zeroed) gyro measurements. Note that the initial position in AHRS mode can vary by a couple degrees initially, due to noise inherent in the compass measurements. Click &#039;&#039;Zero Algorithm&#039;&#039; a few times now to see this for yourself. This noise will be averaged out by the rest of the algorithm, and it should settle into a consistent position after a couple seconds.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you find the model is drifting more than 2-3 degrees immediately after Zeroing the algorithm (while the spatial is staying still) you may want to try zeroing the gyroscope for better results.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zero Gyro====&lt;br /&gt;
Before zeroing the gyroscope, ensure it is securely at rest. Zeroing the gyroscope will average the gyroscope’s readings for a second or two, and automatically subtract the result from subsequent measurements. This is a way to combat drift in the gyros, and we recommend finding a way to zero the gyros before starting AHRS calculations. The results of zeroing the gyro will only persist for as long as it remains open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If explicitly zeroing the gyro is not practical in your application, you can consider running the AHRS algorithm briefly with a wide &#039;&#039;Angular Velocity Threshold&#039;&#039;, then narrowing said threshold again once the system has a chance to compensate for drift on its own.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===AHRS Parameters===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Parameters.jpg|400px|link=|thumb|The AHRS Parameters Box]]&lt;br /&gt;
The AHRS parameters are used to determine certain characteristics of your system so the AHRS algorithm can make better assumptions about the movement in your system. Each of these parameters will have recommended values as a starting point for your Phidget in a [[#Suggested Parameters|table]] below.&lt;br /&gt;
&lt;br /&gt;
All AHRS settings will apply to a system using the IMU algorithm in exactly the same ways, except the compass readings and related settings will be ignored when using IMU.&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Threshold====&lt;br /&gt;
This is the minimum reading from your gyroscopes that the device will use to assume the device is at rest. While the device assumes it is at rest, it will gradually adjust towards making the current gyro readings the new “zero”, compensating for drift over time. This value can be significantly lower if you have zeroed your gyroscope before zeroing the algorithm, as the pre-existing drift of the gyros will have been accounted for. Otherwise, this value will need to be large enough to overcome any pre-existing offsets in your gyro.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The closer you can set this value to zero, the slower the device needs to turn (or think it’s turning) to stop adjusting the gyro biases. If this value is too high, the gyros can be biased away from what is truly stationary. If this value is too low, the gyros will never adjust their bias, and you will see drift over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Delta Threshold====&lt;br /&gt;
This is the minimum change between gyroscope samples before the gyro stops thinking it’s at rest. You can get a good value for this from the gyroscope example after installing the gyro in your application. Simply open the graphs for all axes, and set this value near the peak-to-peak noise.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too low, the device will never think it&#039;s at rest. If it&#039;s too high, certain vibrations could affect your gyro biases (though the effects of these may also be limited by the Angular Velocity Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Acceleration Threshold====&lt;br /&gt;
The minimum measured acceleration your system will assume it is at rest, minus gravity. This value is also used to determine how much motion is accepted before the device begins to ignore the acceleration vector as a reliable source of “down”, and relies entirely on the gyros for pitch and roll until the device stops again. Again, you can use the noise in the graphs from your accelerometer example to get a baseline of the noise, and choose a value accordingly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too high, your device can adjust to thinking “down” is the wrong direction, or be swayed by fast motions. If this value is too low, the device may never think it is at rest to begin the process of correcting its pitch and roll.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Mag Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to re-adjust the heading 95% of the way to aligning with the compass bearing, for differences in compass bearing and AHRS heading less than 15 degrees. Outside of 15 degrees of error, this is the time it will take the AHRS heading to correct towards the compass bearing by 45 degrees, to help limit adverse effects of interference. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more (but never entirely) resistant to magnetic interference, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the magnetic field readings. If this value is low enough, white noise in your compass readings will begin to show up in your measured heading.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Accel Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to realign your pitch and roll to the acceleration vector, once the device believes it is at rest. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more resistant to acceleration affecting orientation, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the accelerometer readings (limited by the above Acceleration Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Bias Time====&lt;br /&gt;
If the sensor is deemed to be at rest, a “bias” parameter internal to the algorithm is slowly added to the gyroscope to compensate for any drift. Effectively, this will automatically gradually zero the gyro readings internal to the algorithm, reducing or eliminating the effects of drift. The time specified here (in seconds) is the time it takes to adjust the bias parameters to compensate for 95% of the gyro’s offsets once the device is at rest.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The speed the gyros should be biased is a balance between getting a solid average and having the zeroing occur quickly enough that biases can be fully compensated for during short periods or rest.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
[[File:AHRS_Example_Menu.jpg|400px|link=|thumb|The AHRS Example Parameter Selection]]&lt;br /&gt;
To get the best precision we recommend tuning these parameters as best fits your application. However, we have provided some sample values to make a couple demonstrations, and to give you some idea of how to adapt these parameters to certain situations.&lt;br /&gt;
&lt;br /&gt;
To more easily set up these example cases, this dropdown provides a list of settings for generic cases, and demonstrations of how you might adapt these values to certain scenarios.&lt;br /&gt;
&lt;br /&gt;
====General Purpose====&lt;br /&gt;
A set of values selected for your device that should work “well enough” out of the box for simple situations, such as moving the device around with your hand.&lt;br /&gt;
&lt;br /&gt;
====No Gyro====&lt;br /&gt;
To demonstrate why gyroscopes are an essential part of AHRS, we’ve given some settings that will effectively ignore any input from the gyroscopes, and snap to the magnetometer and accelerometer readings alone. You will notice this is incredibly noisy, especially if you start moving the sensor around.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====All Gyro====&lt;br /&gt;
For completeness, we have included a selection to set AHRS to more or less ignore input from the magnetometers and accelerometers. By selecting this sample, you can see how the gyroscopes will drift over time and fast motions, clearly demonstrating the need for the accelerometer and magnetometer to bring the gyros back into alignment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zeroed====&lt;br /&gt;
If you are able to zero your gyroscopes, and your application is relatively free of vibrations, you should be able to use a narrower Angular Velocity Threshold. As a result, you may also be able to relax the &#039;&#039;Mag Time&#039;&#039; and &#039;&#039;Accel Time&#039;&#039; parameters, since you can better trust that the gyroscopes will only be re-biased when they are truly not rotating.&lt;br /&gt;
&lt;br /&gt;
====High Vibrations====&lt;br /&gt;
Regardless of whether or not you can zero your gyroscope, if your system suffers from constant large vibrations, the AHRS thresholds will have to be relaxed to allow the gyros to be biased at all. In doing so, we also raise the &#039;&#039;Accel Time&#039;&#039;, not because we can trust the gyroscopes more in this scenario, but rather because we must trust the accelerometer less. Assuming there is little magnetic noise, &#039;&#039;Mag Time&#039;&#039; can be decreased to snap the heading closer to the magnetic field.&lt;br /&gt;
&lt;br /&gt;
===Suggested Parameters===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&amp;quot;&lt;br /&gt;
!  !! Angular Velocity Threshold !! Angular Vel Delta Threshold !! Acceleration Threshold !! Mag Time !! Accel Time !! Bias Time&lt;br /&gt;
|-&lt;br /&gt;
! MOT1102 || 2.0 || 0.6 || 0.1 || 5 || 5 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Out of the Box&#039;&#039; || 1.0 || 0.1 || 0.05 || 10 || 10 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Heated and Zeroed&#039;&#039; || 0.5 || 0.1 || 0.05 || 120 || 120 || 1.25&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Choosing a Phidget Spatial===&lt;br /&gt;
The Spatial Phidget you use in your application will depend on how accurate certain aspects of your measurement need to be. To simplify the decision, we can narrow this down to various kinds of applicaitons:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Applicaiton !! Phidget&lt;br /&gt;
|-&lt;br /&gt;
| Navigation or Outdoor Usage || [{{SERVER}}/products.php?product_id=MOT0110 MOT0110 PhidgetSpatial Precision 3/3/3]&lt;br /&gt;
|-&lt;br /&gt;
| Gestures and Qualitative Effects || [{{SERVER}}/products.php?product_id=MOT1102 MOT1102 Spatial Phidget]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==FAQ==&lt;br /&gt;
&lt;br /&gt;
===Why does the Euler Angle for pitch never exceed 90 degrees?===&lt;br /&gt;
The Euler Angles provided by the Phidgets library are calculated directly from a corresponding quaternion. They do not take into account past movements, so the orientation of a board that passes 90 degrees in pitch can just as easily be represented by a pitch of less than 90 degrees, with different roll and heading parameters. This is one reason why Euler Angles are not recommended for use in serious calculations, in favor of using the corresponding quaternions.&lt;br /&gt;
&lt;br /&gt;
===Why do the Euler Angle readings stop working as well near 90 degrees of pitch?===&lt;br /&gt;
This is actually a good example of gimbal lock, and why it is not advised to use Euler Angles in calculation. When pitch approaches 90 degrees, the roll and yaw axes start to line up, which makes it hard to distinguish one from the other. In other words, at 90 degrees of pitch, a change in roll could just as easily be a change in heading, and vice-versa. This is another reason we recommend quaternions for all serious calculations.&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34333</id>
		<title>Spatial Guide</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34333"/>
		<updated>2024-01-19T19:57:47Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Introduction to AHRS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#seo:|description=Phidget Spatials combine data from accelerometers, magneometers, and gyroscopes into one sensor. This guide explains how the sensors are combined using AHRS, what you can do with this data.}}&lt;br /&gt;
{{#seo:|keywords=accelerometer, gyroscope, magnetometer}}&lt;br /&gt;
&lt;br /&gt;
[[Category:IntroGuide]]&lt;br /&gt;
{{TOC limit|3}}&lt;br /&gt;
&lt;br /&gt;
==Spatial Sensors and Their Uses==&lt;br /&gt;
[[Image:Spatial_Intro.jpg|link=|center]]&lt;br /&gt;
===Introduction to AHRS/IMU===&lt;br /&gt;
Spatial sensors from Phidgets use AHRS (Attitude and Heading Reference System) or IMU algorithms to combine data from accelerometers, magnetometers and gyroscopes into a calculation of the device’s orientation more precise than could be achieved by any of the sensors individually.&lt;br /&gt;
&lt;br /&gt;
While this process is by no means straightforward, PhidgetSpatial sensors come with built-in AHRS calculations combining data from all three types of sensors out of the box. By using the Phidget Spatial object in your code, you can get a direct reading of the heading of your device, in both Euler angle and Quaternion form.&lt;br /&gt;
&lt;br /&gt;
===Euler Angles===&lt;br /&gt;
[[File:EulerAngles.jpg|330px|link=|thumb|A Representation of Euler Angles]]&lt;br /&gt;
Euler angles are a measure of an object’s orientation in the form of pitch, roll, and yaw angles. The advantage of Euler angles in denoting heading is that they are relatively easy to visualise.&lt;br /&gt;
You can get the Euler angles of your sensor directly from the Phidgets library.&lt;br /&gt;
&lt;br /&gt;
While they are a human-friendly way of denoting overall orientation, we strongly recommend against using Euler angles in post-processing calculations, as they can be susceptible to problems of [https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics gimbal lock]. For applications requiring more adjustments than a simple heading offset, we recommend using quaternions.&lt;br /&gt;
&lt;br /&gt;
===Quaternions===&lt;br /&gt;
[[Image:quarternion.jpg|thumb|link=|A Visualization of Quaternions]]&lt;br /&gt;
For applications that require more complex analysis, PhidgetSpatial devices also provide the orientation of the device using quaternions. Quaternions are a more mathematically complete way of denoting orientation and rotations of a system. For what they lose in intuitiveness, the advantage of quaternions is that they can be used in any number of complex calculations without the risk of the aforementioned gimbal lock.&lt;br /&gt;
&lt;br /&gt;
For most practical purposes, it helps to remember that quaternions are not meant to be visualized, or dealt with directly. Instead, any program or library that uses them will have functions to perform calculations with them behind the scenes. If you don’t yet have such a library in your program, but need to use quaternions, we recommend finding one, rather than wading through the math yourself. In this way, while they are difficult to visualize, you can at least remain comfortable in the knowledge that one does not often need to fully understand quaternions to use them in an application.&lt;br /&gt;
&lt;br /&gt;
Quaternions tend to be the preferred rotation system for programs that deal with 3D objects, like Unity, and their inclusion as an output directly from a PhidgetSpatial is designed to make sensor integration as seamless as possible.&lt;br /&gt;
&lt;br /&gt;
===What Does AHRS Actually Do?===&lt;br /&gt;
The AHRS algorithm on Phidgets uses an accelerometer and a magnetometer to keep track of heading over long timescales. When the device is perceived to be at rest, the heading and gyroscopes are gradually aligned and zeroed to reflect that the device is not moving, and pointed towards combined direction from the magnetometer and accelerometer readings. When the device is in motion, the AHRS algorithm starts relying more heavily on the gyroscope for angular rotations, since the accelerometer may no longer be pointing straight down, and the field from the compass may be in flux. By adjusting how much the device relies on the gyroscope in place of the accelerometer and magnetometer, a smoother and more accurate profile of the device’s orientation can be achieved than by using any of the sensors alone.&lt;br /&gt;
&lt;br /&gt;
===Temperature Stabilization===&lt;br /&gt;
Electronic accelerometers and gyroscopes are sensitive to changes in temperature to a small but measurable degree. For cases where long term accuracy is a priority, some of our Spatial sensors have a temperature stabilization feature which allows the boards to heat themselves up to a pre-defined constant temperature (typically 45 or 50&amp;amp;deg;C) to reduce or eliminate drift due to temperature effects.&lt;br /&gt;
&lt;br /&gt;
When using the temperature stabilization feature, it is very important to wait for the board to be fully heated and settled before use, as the process of heating the board will change the sensor readings as the temperature rises to the target. Phidgets that allow temperature stabilization are calibrated at their target temperature, so the sensors will produce more accurate results once heated.&lt;br /&gt;
&lt;br /&gt;
If you are using a temperature-stabilized spatial sensor, it is also very important to keep the board in its enclosure or otherwise insulated from outside air, as air moving directly over the warmed sensors will cause worse results than if the board was not heated at all.&lt;br /&gt;
&lt;br /&gt;
==Demonstrations Using the Control Panel Example==&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note: &#039;&#039;&#039;If your control panel example does not resemble the following, be sure to update your Phidget Control Panel. &amp;lt;br&amp;gt;If your example still doesn&#039;t match, your Spatial Phidget is likely too old to support built-in AHRS calculations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Spatial_Example_AlignModel.jpg|400px|link=|thumb|Click the &#039;&#039;Align Model&#039;&#039; button to align the AHRS model to your screen]]&lt;br /&gt;
&lt;br /&gt;
The spatial example gives you a way to directly visualize the results from the AHRS algorithm used on Phidget Spatial sensors.  We recommend using this example with the sensor in hand at your desk to help visualize the effectiveness of the algorithm. &lt;br /&gt;
&lt;br /&gt;
The first thing you might notice is that the model doesn’t appear to match the orientation of the spatial in your hand. To make the AHRS model line up with your physical spatial, point the wire at the screen and click Align Model. Your spatial model should now mirror the movements of the spatial in your hand.&lt;br /&gt;
&lt;br /&gt;
The AHRS compass drawing is also provided as a visual indicator of the Heading, independent of the screen location. Notice that the compass bearing indicates north when the left-hand side of the Phidget is pointed north.&lt;br /&gt;
&lt;br /&gt;
If your sensor has a heating option, be sure to check the &#039;&#039;Heating Enabled&#039;&#039; box, and wait until the temperature reading stays green for best results. In your own programs, wait until the temperature reaches 45C, and then if possible give the sensor an additional minute or two to ensure the whole board is evenly heated.&lt;br /&gt;
&lt;br /&gt;
===AHRS Settings===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Settings.jpg|400px|link=|thumb|The AHRS Settings Box]]&lt;br /&gt;
Now we can look at the AHRS settings panel:&lt;br /&gt;
====Algorithm====&lt;br /&gt;
The algorithm setting dictates whether or not the compass is going to be factored into calculations.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;AHRS: &#039;&#039;&#039;When setting Algorithm to AHRS (the default setting) heading is gradually re-aligned with the compass over time, and all headings will be relative to magnetic north. When you Zero the AHRS algorithm, it will forcibly realign the heading to the compass reading.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;IMU: &#039;&#039;&#039;When using IMU, the compass readings are ignored, and a heading of 0° corresponds to the direction the device was facing when it was started, or where it was last zeroed. By clicking the Zero Algorithm button, it will realign all calculations to reference the direction it is currently facing as the new 0° heading.&lt;br /&gt;
&lt;br /&gt;
====Zero Algorithm====&lt;br /&gt;
The Zero Algorithm button centers the algorithm’s heading either on the compass reading or on the direction it is currently facing (see AHRS Mode). The accumulated gyro biases will also be dropped, reverting to the raw (zeroed) gyro measurements. Note that the initial position in AHRS mode can vary by a couple degrees initially, due to noise inherent in the compass measurements. Click &#039;&#039;Zero Algorithm&#039;&#039; a few times now to see this for yourself. This noise will be averaged out by the rest of the algorithm, and it should settle into a consistent position after a couple seconds.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you find the model is drifting more than 2-3 degrees immediately after Zeroing the algorithm (while the spatial is staying still) you may want to try zeroing the gyroscope for better results.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zero Gyro====&lt;br /&gt;
Before zeroing the gyroscope, ensure it is securely at rest. Zeroing the gyroscope will average the gyroscope’s readings for a second or two, and automatically subtract the result from subsequent measurements. This is a way to combat drift in the gyros, and we recommend finding a way to zero the gyros before starting AHRS calculations. The results of zeroing the gyro will only persist for as long as it remains open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If explicitly zeroing the gyro is not practical in your application, you can consider running the AHRS algorithm briefly with a wide &#039;&#039;Angular Velocity Threshold&#039;&#039;, then narrowing said threshold again once the system has a chance to compensate for drift on its own.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===AHRS Parameters===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Parameters.jpg|400px|link=|thumb|The AHRS Parameters Box]]&lt;br /&gt;
The AHRS parameters are used to determine certain characteristics of your system so the AHRS algorithm can make better assumptions about the movement in your system. Each of these parameters will have recommended values as a starting point for your Phidget in a [[#Suggested Parameters|table]] below.&lt;br /&gt;
&lt;br /&gt;
All AHRS settings will apply to a system using the IMU algorithm in exactly the same ways, except the compass readings and related settings will be ignored when using IMU.&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Threshold====&lt;br /&gt;
This is the minimum reading from your gyroscopes that the device will use to assume the device is at rest. While the device assumes it is at rest, it will gradually adjust towards making the current gyro readings the new “zero”, compensating for drift over time. This value can be significantly lower if you have zeroed your gyroscope before zeroing the algorithm, as the pre-existing drift of the gyros will have been accounted for. Otherwise, this value will need to be large enough to overcome any pre-existing offsets in your gyro.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The closer you can set this value to zero, the slower the device needs to turn (or think it’s turning) to stop adjusting the gyro biases. If this value is too high, the gyros can be biased away from what is truly stationary. If this value is too low, the gyros will never adjust their bias, and you will see drift over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Delta Threshold====&lt;br /&gt;
This is the minimum change between gyroscope samples before the gyro stops thinking it’s at rest. You can get a good value for this from the gyroscope example after installing the gyro in your application. Simply open the graphs for all axes, and set this value near the peak-to-peak noise.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too low, the device will never think it&#039;s at rest. If it&#039;s too high, certain vibrations could affect your gyro biases (though the effects of these may also be limited by the Angular Velocity Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Acceleration Threshold====&lt;br /&gt;
The minimum measured acceleration your system will assume it is at rest, minus gravity. This value is also used to determine how much motion is accepted before the device begins to ignore the acceleration vector as a reliable source of “down”, and relies entirely on the gyros for pitch and roll until the device stops again. Again, you can use the noise in the graphs from your accelerometer example to get a baseline of the noise, and choose a value accordingly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too high, your device can adjust to thinking “down” is the wrong direction, or be swayed by fast motions. If this value is too low, the device may never think it is at rest to begin the process of correcting its pitch and roll.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Mag Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to re-adjust the heading 95% of the way to aligning with the compass bearing, for differences in compass bearing and AHRS heading less than 15 degrees. Outside of 15 degrees of error, this is the time it will take the AHRS heading to correct towards the compass bearing by 45 degrees, to help limit adverse effects of interference. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more (but never entirely) resistant to magnetic interference, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the magnetic field readings. If this value is low enough, white noise in your compass readings will begin to show up in your measured heading.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Accel Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to realign your pitch and roll to the acceleration vector, once the device believes it is at rest. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more resistant to acceleration affecting orientation, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the accelerometer readings (limited by the above Acceleration Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Bias Time====&lt;br /&gt;
If the sensor is deemed to be at rest, a “bias” parameter internal to the algorithm is slowly added to the gyroscope to compensate for any drift. Effectively, this will automatically gradually zero the gyro readings internal to the algorithm, reducing or eliminating the effects of drift. The time specified here (in seconds) is the time it takes to adjust the bias parameters to compensate for 95% of the gyro’s offsets once the device is at rest.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The speed the gyros should be biased is a balance between getting a solid average and having the zeroing occur quickly enough that biases can be fully compensated for during short periods or rest.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
[[File:AHRS_Example_Menu.jpg|400px|link=|thumb|The AHRS Example Parameter Selection]]&lt;br /&gt;
To get the best precision we recommend tuning these parameters as best fits your application. However, we have provided some sample values to make a couple demonstrations, and to give you some idea of how to adapt these parameters to certain situations.&lt;br /&gt;
&lt;br /&gt;
To more easily set up these example cases, this dropdown provides a list of settings for generic cases, and demonstrations of how you might adapt these values to certain scenarios.&lt;br /&gt;
&lt;br /&gt;
====General Purpose====&lt;br /&gt;
A set of values selected for your device that should work “well enough” out of the box for simple situations, such as moving the device around with your hand.&lt;br /&gt;
&lt;br /&gt;
====No Gyro====&lt;br /&gt;
To demonstrate why gyroscopes are an essential part of AHRS, we’ve given some settings that will effectively ignore any input from the gyroscopes, and snap to the magnetometer and accelerometer readings alone. You will notice this is incredibly noisy, especially if you start moving the sensor around.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====All Gyro====&lt;br /&gt;
For completeness, we have included a selection to set AHRS to more or less ignore input from the magnetometers and accelerometers. By selecting this sample, you can see how the gyroscopes will drift over time and fast motions, clearly demonstrating the need for the accelerometer and magnetometer to bring the gyros back into alignment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zeroed====&lt;br /&gt;
If you are able to zero your gyroscopes, and your application is relatively free of vibrations, you should be able to use a narrower Angular Velocity Threshold. As a result, you may also be able to relax the &#039;&#039;Mag Time&#039;&#039; and &#039;&#039;Accel Time&#039;&#039; parameters, since you can better trust that the gyroscopes will only be re-biased when they are truly not rotating.&lt;br /&gt;
&lt;br /&gt;
====High Vibrations====&lt;br /&gt;
Regardless of whether or not you can zero your gyroscope, if your system suffers from constant large vibrations, the AHRS thresholds will have to be relaxed to allow the gyros to be biased at all. In doing so, we also raise the &#039;&#039;Accel Time&#039;&#039;, not because we can trust the gyroscopes more in this scenario, but rather because we must trust the accelerometer less. Assuming there is little magnetic noise, &#039;&#039;Mag Time&#039;&#039; can be decreased to snap the heading closer to the magnetic field.&lt;br /&gt;
&lt;br /&gt;
===Suggested Parameters===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&amp;quot;&lt;br /&gt;
!  !! Angular Velocity Threshold !! Angular Vel Delta Threshold !! Acceleration Threshold !! Mag Time !! Accel Time !! Bias Time&lt;br /&gt;
|-&lt;br /&gt;
! MOT1102 || 2.0 || 0.6 || 0.1 || 5 || 5 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Out of the Box&#039;&#039; || 1.0 || 0.1 || 0.05 || 10 || 10 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Heated and Zeroed&#039;&#039; || 0.5 || 0.1 || 0.05 || 120 || 120 || 1.25&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Choosing a Phidget Spatial===&lt;br /&gt;
The Spatial Phidget you use in your application will depend on how accurate certain aspects of your measurement need to be. To simplify the decision, we can narrow this down to various kinds of applicaitons:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Applicaiton !! Phidget&lt;br /&gt;
|-&lt;br /&gt;
| Navigation or Outdoor Usage || [{{SERVER}}/products.php?product_id=MOT0110 MOT0110 PhidgetSpatial Precision 3/3/3]&lt;br /&gt;
|-&lt;br /&gt;
| Gestures and Qualitative Effects || [{{SERVER}}/products.php?product_id=MOT1102 MOT1102 Spatial Phidget]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==FAQ==&lt;br /&gt;
&lt;br /&gt;
===Why does the Euler Angle for pitch never exceed 90 degrees?===&lt;br /&gt;
The Euler Angles provided by the Phidgets library are calculated directly from a corresponding quaternion. They do not take into account past movements, so the orientation of a board that passes 90 degrees in pitch can just as easily be represented by a pitch of less than 90 degrees, with different roll and heading parameters. This is one reason why Euler Angles are not recommended for use in serious calculations, in favor of using the corresponding quaternions.&lt;br /&gt;
&lt;br /&gt;
===Why do the Euler Angle readings stop working as well near 90 degrees of pitch?===&lt;br /&gt;
This is actually a good example of gimbal lock, and why it is not advised to use Euler Angles in calculation. When pitch approaches 90 degrees, the roll and yaw axes start to line up, which makes it hard to distinguish one from the other. In other words, at 90 degrees of pitch, a change in roll could just as easily be a change in heading, and vice-versa. This is another reason we recommend quaternions for all serious calculations.&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34332</id>
		<title>Spatial Guide</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34332"/>
		<updated>2024-01-18T18:40:13Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* AHRS Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#seo:|description=Phidget Spatials combine data from accelerometers, magneometers, and gyroscopes into one sensor. This guide explains how the sensors are combined using AHRS, what you can do with this data.}}&lt;br /&gt;
{{#seo:|keywords=accelerometer, gyroscope, magnetometer}}&lt;br /&gt;
&lt;br /&gt;
[[Category:IntroGuide]]&lt;br /&gt;
{{TOC limit|3}}&lt;br /&gt;
&lt;br /&gt;
==Spatial Sensors and Their Uses==&lt;br /&gt;
[[Image:Spatial_Intro.jpg|link=|center]]&lt;br /&gt;
===Introduction to AHRS===&lt;br /&gt;
Spatial sensors from Phidgets use AHRS (Attitude and Heading Reference System) as a means of combining data from accelerometers, magnetometers and gyroscopes into a calculation of the device’s orientation more precise than could be achieved by any of the sensors individually.&lt;br /&gt;
&lt;br /&gt;
While this process is by no means straightforward, PhidgetSpatial sensors come with built-in AHRS calculations combining data from all three types of sensors out of the box. By using the Phidget Spatial object in your code, you can get a direct reading of the heading of your device, in both Euler angle and Quaternion form.&lt;br /&gt;
&lt;br /&gt;
===Euler Angles===&lt;br /&gt;
[[File:EulerAngles.jpg|330px|link=|thumb|A Representation of Euler Angles]]&lt;br /&gt;
Euler angles are a measure of an object’s orientation in the form of pitch, roll, and yaw angles. The advantage of Euler angles in denoting heading is that they are relatively easy to visualise.&lt;br /&gt;
You can get the Euler angles of your sensor directly from the Phidgets library.&lt;br /&gt;
&lt;br /&gt;
While they are a human-friendly way of denoting overall orientation, we strongly recommend against using Euler angles in post-processing calculations, as they can be susceptible to problems of [https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics gimbal lock]. For applications requiring more adjustments than a simple heading offset, we recommend using quaternions.&lt;br /&gt;
&lt;br /&gt;
===Quaternions===&lt;br /&gt;
[[Image:quarternion.jpg|thumb|link=|A Visualization of Quaternions]]&lt;br /&gt;
For applications that require more complex analysis, PhidgetSpatial devices also provide the orientation of the device using quaternions. Quaternions are a more mathematically complete way of denoting orientation and rotations of a system. For what they lose in intuitiveness, the advantage of quaternions is that they can be used in any number of complex calculations without the risk of the aforementioned gimbal lock.&lt;br /&gt;
&lt;br /&gt;
For most practical purposes, it helps to remember that quaternions are not meant to be visualized, or dealt with directly. Instead, any program or library that uses them will have functions to perform calculations with them behind the scenes. If you don’t yet have such a library in your program, but need to use quaternions, we recommend finding one, rather than wading through the math yourself. In this way, while they are difficult to visualize, you can at least remain comfortable in the knowledge that one does not often need to fully understand quaternions to use them in an application.&lt;br /&gt;
&lt;br /&gt;
Quaternions tend to be the preferred rotation system for programs that deal with 3D objects, like Unity, and their inclusion as an output directly from a PhidgetSpatial is designed to make sensor integration as seamless as possible.&lt;br /&gt;
&lt;br /&gt;
===What Does AHRS Actually Do?===&lt;br /&gt;
The AHRS algorithm on Phidgets uses an accelerometer and a magnetometer to keep track of heading over long timescales. When the device is perceived to be at rest, the heading and gyroscopes are gradually aligned and zeroed to reflect that the device is not moving, and pointed towards combined direction from the magnetometer and accelerometer readings. When the device is in motion, the AHRS algorithm starts relying more heavily on the gyroscope for angular rotations, since the accelerometer may no longer be pointing straight down, and the field from the compass may be in flux. By adjusting how much the device relies on the gyroscope in place of the accelerometer and magnetometer, a smoother and more accurate profile of the device’s orientation can be achieved than by using any of the sensors alone.&lt;br /&gt;
&lt;br /&gt;
===Temperature Stabilization===&lt;br /&gt;
Electronic accelerometers and gyroscopes are sensitive to changes in temperature to a small but measurable degree. For cases where long term accuracy is a priority, some of our Spatial sensors have a temperature stabilization feature which allows the boards to heat themselves up to a pre-defined constant temperature (typically 45 or 50&amp;amp;deg;C) to reduce or eliminate drift due to temperature effects.&lt;br /&gt;
&lt;br /&gt;
When using the temperature stabilization feature, it is very important to wait for the board to be fully heated and settled before use, as the process of heating the board will change the sensor readings as the temperature rises to the target. Phidgets that allow temperature stabilization are calibrated at their target temperature, so the sensors will produce more accurate results once heated.&lt;br /&gt;
&lt;br /&gt;
If you are using a temperature-stabilized spatial sensor, it is also very important to keep the board in its enclosure or otherwise insulated from outside air, as air moving directly over the warmed sensors will cause worse results than if the board was not heated at all.&lt;br /&gt;
&lt;br /&gt;
==Demonstrations Using the Control Panel Example==&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note: &#039;&#039;&#039;If your control panel example does not resemble the following, be sure to update your Phidget Control Panel. &amp;lt;br&amp;gt;If your example still doesn&#039;t match, your Spatial Phidget is likely too old to support built-in AHRS calculations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Spatial_Example_AlignModel.jpg|400px|link=|thumb|Click the &#039;&#039;Align Model&#039;&#039; button to align the AHRS model to your screen]]&lt;br /&gt;
&lt;br /&gt;
The spatial example gives you a way to directly visualize the results from the AHRS algorithm used on Phidget Spatial sensors.  We recommend using this example with the sensor in hand at your desk to help visualize the effectiveness of the algorithm. &lt;br /&gt;
&lt;br /&gt;
The first thing you might notice is that the model doesn’t appear to match the orientation of the spatial in your hand. To make the AHRS model line up with your physical spatial, point the wire at the screen and click Align Model. Your spatial model should now mirror the movements of the spatial in your hand.&lt;br /&gt;
&lt;br /&gt;
The AHRS compass drawing is also provided as a visual indicator of the Heading, independent of the screen location. Notice that the compass bearing indicates north when the left-hand side of the Phidget is pointed north.&lt;br /&gt;
&lt;br /&gt;
If your sensor has a heating option, be sure to check the &#039;&#039;Heating Enabled&#039;&#039; box, and wait until the temperature reading stays green for best results. In your own programs, wait until the temperature reaches 45C, and then if possible give the sensor an additional minute or two to ensure the whole board is evenly heated.&lt;br /&gt;
&lt;br /&gt;
===AHRS Settings===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Settings.jpg|400px|link=|thumb|The AHRS Settings Box]]&lt;br /&gt;
Now we can look at the AHRS settings panel:&lt;br /&gt;
====Algorithm====&lt;br /&gt;
The algorithm setting dictates whether or not the compass is going to be factored into calculations.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;AHRS: &#039;&#039;&#039;When setting Algorithm to AHRS (the default setting) heading is gradually re-aligned with the compass over time, and all headings will be relative to magnetic north. When you Zero the AHRS algorithm, it will forcibly realign the heading to the compass reading.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;IMU: &#039;&#039;&#039;When using IMU, the compass readings are ignored, and a heading of 0° corresponds to the direction the device was facing when it was started, or where it was last zeroed. By clicking the Zero Algorithm button, it will realign all calculations to reference the direction it is currently facing as the new 0° heading.&lt;br /&gt;
&lt;br /&gt;
====Zero Algorithm====&lt;br /&gt;
The Zero Algorithm button centers the algorithm’s heading either on the compass reading or on the direction it is currently facing (see AHRS Mode). The accumulated gyro biases will also be dropped, reverting to the raw (zeroed) gyro measurements. Note that the initial position in AHRS mode can vary by a couple degrees initially, due to noise inherent in the compass measurements. Click &#039;&#039;Zero Algorithm&#039;&#039; a few times now to see this for yourself. This noise will be averaged out by the rest of the algorithm, and it should settle into a consistent position after a couple seconds.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you find the model is drifting more than 2-3 degrees immediately after Zeroing the algorithm (while the spatial is staying still) you may want to try zeroing the gyroscope for better results.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zero Gyro====&lt;br /&gt;
Before zeroing the gyroscope, ensure it is securely at rest. Zeroing the gyroscope will average the gyroscope’s readings for a second or two, and automatically subtract the result from subsequent measurements. This is a way to combat drift in the gyros, and we recommend finding a way to zero the gyros before starting AHRS calculations. The results of zeroing the gyro will only persist for as long as it remains open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If explicitly zeroing the gyro is not practical in your application, you can consider running the AHRS algorithm briefly with a wide &#039;&#039;Angular Velocity Threshold&#039;&#039;, then narrowing said threshold again once the system has a chance to compensate for drift on its own.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===AHRS Parameters===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Parameters.jpg|400px|link=|thumb|The AHRS Parameters Box]]&lt;br /&gt;
The AHRS parameters are used to determine certain characteristics of your system so the AHRS algorithm can make better assumptions about the movement in your system. Each of these parameters will have recommended values as a starting point for your Phidget in a [[#Suggested Parameters|table]] below.&lt;br /&gt;
&lt;br /&gt;
All AHRS settings will apply to a system using the IMU algorithm in exactly the same ways, except the compass readings and related settings will be ignored when using IMU.&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Threshold====&lt;br /&gt;
This is the minimum reading from your gyroscopes that the device will use to assume the device is at rest. While the device assumes it is at rest, it will gradually adjust towards making the current gyro readings the new “zero”, compensating for drift over time. This value can be significantly lower if you have zeroed your gyroscope before zeroing the algorithm, as the pre-existing drift of the gyros will have been accounted for. Otherwise, this value will need to be large enough to overcome any pre-existing offsets in your gyro.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The closer you can set this value to zero, the slower the device needs to turn (or think it’s turning) to stop adjusting the gyro biases. If this value is too high, the gyros can be biased away from what is truly stationary. If this value is too low, the gyros will never adjust their bias, and you will see drift over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Delta Threshold====&lt;br /&gt;
This is the minimum change between gyroscope samples before the gyro stops thinking it’s at rest. You can get a good value for this from the gyroscope example after installing the gyro in your application. Simply open the graphs for all axes, and set this value near the peak-to-peak noise.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too low, the device will never think it&#039;s at rest. If it&#039;s too high, certain vibrations could affect your gyro biases (though the effects of these may also be limited by the Angular Velocity Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Acceleration Threshold====&lt;br /&gt;
The minimum measured acceleration your system will assume it is at rest, minus gravity. This value is also used to determine how much motion is accepted before the device begins to ignore the acceleration vector as a reliable source of “down”, and relies entirely on the gyros for pitch and roll until the device stops again. Again, you can use the noise in the graphs from your accelerometer example to get a baseline of the noise, and choose a value accordingly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too high, your device can adjust to thinking “down” is the wrong direction, or be swayed by fast motions. If this value is too low, the device may never think it is at rest to begin the process of correcting its pitch and roll.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Mag Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to re-adjust the heading 95% of the way to aligning with the compass bearing, for differences in compass bearing and AHRS heading less than 15 degrees. Outside of 15 degrees of error, this is the time it will take the AHRS heading to correct towards the compass bearing by 45 degrees, to help limit adverse effects of interference. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more (but never entirely) resistant to magnetic interference, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the magnetic field readings. If this value is low enough, white noise in your compass readings will begin to show up in your measured heading.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Accel Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to realign your pitch and roll to the acceleration vector, once the device believes it is at rest. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more resistant to acceleration affecting orientation, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the accelerometer readings (limited by the above Acceleration Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Bias Time====&lt;br /&gt;
If the sensor is deemed to be at rest, a “bias” parameter internal to the algorithm is slowly added to the gyroscope to compensate for any drift. Effectively, this will automatically gradually zero the gyro readings internal to the algorithm, reducing or eliminating the effects of drift. The time specified here (in seconds) is the time it takes to adjust the bias parameters to compensate for 95% of the gyro’s offsets once the device is at rest.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The speed the gyros should be biased is a balance between getting a solid average and having the zeroing occur quickly enough that biases can be fully compensated for during short periods or rest.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
[[File:AHRS_Example_Menu.jpg|400px|link=|thumb|The AHRS Example Parameter Selection]]&lt;br /&gt;
To get the best precision we recommend tuning these parameters as best fits your application. However, we have provided some sample values to make a couple demonstrations, and to give you some idea of how to adapt these parameters to certain situations.&lt;br /&gt;
&lt;br /&gt;
To more easily set up these example cases, this dropdown provides a list of settings for generic cases, and demonstrations of how you might adapt these values to certain scenarios.&lt;br /&gt;
&lt;br /&gt;
====General Purpose====&lt;br /&gt;
A set of values selected for your device that should work “well enough” out of the box for simple situations, such as moving the device around with your hand.&lt;br /&gt;
&lt;br /&gt;
====No Gyro====&lt;br /&gt;
To demonstrate why gyroscopes are an essential part of AHRS, we’ve given some settings that will effectively ignore any input from the gyroscopes, and snap to the magnetometer and accelerometer readings alone. You will notice this is incredibly noisy, especially if you start moving the sensor around.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====All Gyro====&lt;br /&gt;
For completeness, we have included a selection to set AHRS to more or less ignore input from the magnetometers and accelerometers. By selecting this sample, you can see how the gyroscopes will drift over time and fast motions, clearly demonstrating the need for the accelerometer and magnetometer to bring the gyros back into alignment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zeroed====&lt;br /&gt;
If you are able to zero your gyroscopes, and your application is relatively free of vibrations, you should be able to use a narrower Angular Velocity Threshold. As a result, you may also be able to relax the &#039;&#039;Mag Time&#039;&#039; and &#039;&#039;Accel Time&#039;&#039; parameters, since you can better trust that the gyroscopes will only be re-biased when they are truly not rotating.&lt;br /&gt;
&lt;br /&gt;
====High Vibrations====&lt;br /&gt;
Regardless of whether or not you can zero your gyroscope, if your system suffers from constant large vibrations, the AHRS thresholds will have to be relaxed to allow the gyros to be biased at all. In doing so, we also raise the &#039;&#039;Accel Time&#039;&#039;, not because we can trust the gyroscopes more in this scenario, but rather because we must trust the accelerometer less. Assuming there is little magnetic noise, &#039;&#039;Mag Time&#039;&#039; can be decreased to snap the heading closer to the magnetic field.&lt;br /&gt;
&lt;br /&gt;
===Suggested Parameters===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&amp;quot;&lt;br /&gt;
!  !! Angular Velocity Threshold !! Angular Vel Delta Threshold !! Acceleration Threshold !! Mag Time !! Accel Time !! Bias Time&lt;br /&gt;
|-&lt;br /&gt;
! MOT1102 || 2.0 || 0.6 || 0.1 || 5 || 5 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Out of the Box&#039;&#039; || 1.0 || 0.1 || 0.05 || 10 || 10 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Heated and Zeroed&#039;&#039; || 0.5 || 0.1 || 0.05 || 120 || 120 || 1.25&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Choosing a Phidget Spatial===&lt;br /&gt;
The Spatial Phidget you use in your application will depend on how accurate certain aspects of your measurement need to be. To simplify the decision, we can narrow this down to various kinds of applicaitons:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Applicaiton !! Phidget&lt;br /&gt;
|-&lt;br /&gt;
| Navigation or Outdoor Usage || [{{SERVER}}/products.php?product_id=MOT0110 MOT0110 PhidgetSpatial Precision 3/3/3]&lt;br /&gt;
|-&lt;br /&gt;
| Gestures and Qualitative Effects || [{{SERVER}}/products.php?product_id=MOT1102 MOT1102 Spatial Phidget]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==FAQ==&lt;br /&gt;
&lt;br /&gt;
===Why does the Euler Angle for pitch never exceed 90 degrees?===&lt;br /&gt;
The Euler Angles provided by the Phidgets library are calculated directly from a corresponding quaternion. They do not take into account past movements, so the orientation of a board that passes 90 degrees in pitch can just as easily be represented by a pitch of less than 90 degrees, with different roll and heading parameters. This is one reason why Euler Angles are not recommended for use in serious calculations, in favor of using the corresponding quaternions.&lt;br /&gt;
&lt;br /&gt;
===Why do the Euler Angle readings stop working as well near 90 degrees of pitch?===&lt;br /&gt;
This is actually a good example of gimbal lock, and why it is not advised to use Euler Angles in calculation. When pitch approaches 90 degrees, the roll and yaw axes start to line up, which makes it hard to distinguish one from the other. In other words, at 90 degrees of pitch, a change in roll could just as easily be a change in heading, and vice-versa. This is another reason we recommend quaternions for all serious calculations.&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34331</id>
		<title>Spatial Guide</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=34331"/>
		<updated>2024-01-18T18:38:22Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Algorithm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#seo:|description=Phidget Spatials combine data from accelerometers, magneometers, and gyroscopes into one sensor. This guide explains how the sensors are combined using AHRS, what you can do with this data.}}&lt;br /&gt;
{{#seo:|keywords=accelerometer, gyroscope, magnetometer}}&lt;br /&gt;
&lt;br /&gt;
[[Category:IntroGuide]]&lt;br /&gt;
{{TOC limit|3}}&lt;br /&gt;
&lt;br /&gt;
==Spatial Sensors and Their Uses==&lt;br /&gt;
[[Image:Spatial_Intro.jpg|link=|center]]&lt;br /&gt;
===Introduction to AHRS===&lt;br /&gt;
Spatial sensors from Phidgets use AHRS (Attitude and Heading Reference System) as a means of combining data from accelerometers, magnetometers and gyroscopes into a calculation of the device’s orientation more precise than could be achieved by any of the sensors individually.&lt;br /&gt;
&lt;br /&gt;
While this process is by no means straightforward, PhidgetSpatial sensors come with built-in AHRS calculations combining data from all three types of sensors out of the box. By using the Phidget Spatial object in your code, you can get a direct reading of the heading of your device, in both Euler angle and Quaternion form.&lt;br /&gt;
&lt;br /&gt;
===Euler Angles===&lt;br /&gt;
[[File:EulerAngles.jpg|330px|link=|thumb|A Representation of Euler Angles]]&lt;br /&gt;
Euler angles are a measure of an object’s orientation in the form of pitch, roll, and yaw angles. The advantage of Euler angles in denoting heading is that they are relatively easy to visualise.&lt;br /&gt;
You can get the Euler angles of your sensor directly from the Phidgets library.&lt;br /&gt;
&lt;br /&gt;
While they are a human-friendly way of denoting overall orientation, we strongly recommend against using Euler angles in post-processing calculations, as they can be susceptible to problems of [https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics gimbal lock]. For applications requiring more adjustments than a simple heading offset, we recommend using quaternions.&lt;br /&gt;
&lt;br /&gt;
===Quaternions===&lt;br /&gt;
[[Image:quarternion.jpg|thumb|link=|A Visualization of Quaternions]]&lt;br /&gt;
For applications that require more complex analysis, PhidgetSpatial devices also provide the orientation of the device using quaternions. Quaternions are a more mathematically complete way of denoting orientation and rotations of a system. For what they lose in intuitiveness, the advantage of quaternions is that they can be used in any number of complex calculations without the risk of the aforementioned gimbal lock.&lt;br /&gt;
&lt;br /&gt;
For most practical purposes, it helps to remember that quaternions are not meant to be visualized, or dealt with directly. Instead, any program or library that uses them will have functions to perform calculations with them behind the scenes. If you don’t yet have such a library in your program, but need to use quaternions, we recommend finding one, rather than wading through the math yourself. In this way, while they are difficult to visualize, you can at least remain comfortable in the knowledge that one does not often need to fully understand quaternions to use them in an application.&lt;br /&gt;
&lt;br /&gt;
Quaternions tend to be the preferred rotation system for programs that deal with 3D objects, like Unity, and their inclusion as an output directly from a PhidgetSpatial is designed to make sensor integration as seamless as possible.&lt;br /&gt;
&lt;br /&gt;
===What Does AHRS Actually Do?===&lt;br /&gt;
The AHRS algorithm on Phidgets uses an accelerometer and a magnetometer to keep track of heading over long timescales. When the device is perceived to be at rest, the heading and gyroscopes are gradually aligned and zeroed to reflect that the device is not moving, and pointed towards combined direction from the magnetometer and accelerometer readings. When the device is in motion, the AHRS algorithm starts relying more heavily on the gyroscope for angular rotations, since the accelerometer may no longer be pointing straight down, and the field from the compass may be in flux. By adjusting how much the device relies on the gyroscope in place of the accelerometer and magnetometer, a smoother and more accurate profile of the device’s orientation can be achieved than by using any of the sensors alone.&lt;br /&gt;
&lt;br /&gt;
===Temperature Stabilization===&lt;br /&gt;
Electronic accelerometers and gyroscopes are sensitive to changes in temperature to a small but measurable degree. For cases where long term accuracy is a priority, some of our Spatial sensors have a temperature stabilization feature which allows the boards to heat themselves up to a pre-defined constant temperature (typically 45 or 50&amp;amp;deg;C) to reduce or eliminate drift due to temperature effects.&lt;br /&gt;
&lt;br /&gt;
When using the temperature stabilization feature, it is very important to wait for the board to be fully heated and settled before use, as the process of heating the board will change the sensor readings as the temperature rises to the target. Phidgets that allow temperature stabilization are calibrated at their target temperature, so the sensors will produce more accurate results once heated.&lt;br /&gt;
&lt;br /&gt;
If you are using a temperature-stabilized spatial sensor, it is also very important to keep the board in its enclosure or otherwise insulated from outside air, as air moving directly over the warmed sensors will cause worse results than if the board was not heated at all.&lt;br /&gt;
&lt;br /&gt;
==Demonstrations Using the Control Panel Example==&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note: &#039;&#039;&#039;If your control panel example does not resemble the following, be sure to update your Phidget Control Panel. &amp;lt;br&amp;gt;If your example still doesn&#039;t match, your Spatial Phidget is likely too old to support built-in AHRS calculations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Spatial_Example_AlignModel.jpg|400px|link=|thumb|Click the &#039;&#039;Align Model&#039;&#039; button to align the AHRS model to your screen]]&lt;br /&gt;
&lt;br /&gt;
The spatial example gives you a way to directly visualize the results from the AHRS algorithm used on Phidget Spatial sensors.  We recommend using this example with the sensor in hand at your desk to help visualize the effectiveness of the algorithm. &lt;br /&gt;
&lt;br /&gt;
The first thing you might notice is that the model doesn’t appear to match the orientation of the spatial in your hand. To make the AHRS model line up with your physical spatial, point the wire at the screen and click Align Model. Your spatial model should now mirror the movements of the spatial in your hand.&lt;br /&gt;
&lt;br /&gt;
The AHRS compass drawing is also provided as a visual indicator of the Heading, independent of the screen location. Notice that the compass bearing indicates north when the left-hand side of the Phidget is pointed north.&lt;br /&gt;
&lt;br /&gt;
If your sensor has a heating option, be sure to check the &#039;&#039;Heating Enabled&#039;&#039; box, and wait until the temperature reading stays green for best results. In your own programs, wait until the temperature reaches 45C, and then if possible give the sensor an additional minute or two to ensure the whole board is evenly heated.&lt;br /&gt;
&lt;br /&gt;
===AHRS Settings===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Settings.jpg|400px|link=|thumb|The AHRS Settings Box]]&lt;br /&gt;
Now we can look at the AHRS settings panel:&lt;br /&gt;
====Algorithm====&lt;br /&gt;
The algorithm setting dictates whether or not the compass is going to be factored into calculations.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;AHRS: &#039;&#039;&#039;When setting Algorithm to AHRS (the default setting) heading is gradually re-aligned with the compass over time, and all headings will be relative to magnetic north. When you Zero the AHRS algorithm, it will forcibly realign the heading to the compass reading.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;IMU: &#039;&#039;&#039;When using IMU, the compass readings are ignored, and a heading of 0° corresponds to the direction the device was facing when it was started, or where it was last zeroed. By clicking the Zero Algorithm button, it will realign all calculations to reference the direction it is currently facing as the new 0° heading.&lt;br /&gt;
&lt;br /&gt;
====Zero Algorithm====&lt;br /&gt;
The Zero Algorithm button centers the algorithm’s heading either on the compass reading or on the direction it is currently facing (see AHRS Mode). The accumulated gyro biases will also be dropped, reverting to the raw (zeroed) gyro measurements. Note that the initial position in AHRS mode can vary by a couple degrees initially, due to noise inherent in the compass measurements. Click &#039;&#039;Zero Algorithm&#039;&#039; a few times now to see this for yourself. This noise will be averaged out by the rest of the algorithm, and it should settle into a consistent position after a couple seconds.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you find the model is drifting more than 2-3 degrees immediately after Zeroing the algorithm (while the spatial is staying still) you may want to try zeroing the gyroscope for better results.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zero Gyro====&lt;br /&gt;
Before zeroing the gyroscope, ensure it is securely at rest. Zeroing the gyroscope will average the gyroscope’s readings for a second or two, and automatically subtract the result from subsequent measurements. This is a way to combat drift in the gyros, and we recommend finding a way to zero the gyros before starting AHRS calculations. The results of zeroing the gyro will only persist for as long as it remains open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If explicitly zeroing the gyro is not practical in your application, you can consider running the AHRS algorithm briefly with a wide &#039;&#039;Angular Velocity Threshold&#039;&#039;, then narrowing said threshold again once the system has a chance to compensate for drift on its own.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===AHRS Parameters===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Parameters.jpg|400px|link=|thumb|The AHRS Parameters Box]]&lt;br /&gt;
The AHRS parameters are used to determine certain characteristics of your system so the AHRS algorithm can make better assumptions about the movement in your system. Each of these parameters will have recommended values as a starting point for your Phidget in a [[#Suggested Parameters|table]] below.&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Threshold====&lt;br /&gt;
This is the minimum reading from your gyroscopes that the device will use to assume the device is at rest. While the device assumes it is at rest, it will gradually adjust towards making the current gyro readings the new “zero”, compensating for drift over time. This value can be significantly lower if you have zeroed your gyroscope before zeroing the algorithm, as the pre-existing drift of the gyros will have been accounted for. Otherwise, this value will need to be large enough to overcome any pre-existing offsets in your gyro.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The closer you can set this value to zero, the slower the device needs to turn (or think it’s turning) to stop adjusting the gyro biases. If this value is too high, the gyros can be biased away from what is truly stationary. If this value is too low, the gyros will never adjust their bias, and you will see drift over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Delta Threshold====&lt;br /&gt;
This is the minimum change between gyroscope samples before the gyro stops thinking it’s at rest. You can get a good value for this from the gyroscope example after installing the gyro in your application. Simply open the graphs for all axes, and set this value near the peak-to-peak noise.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too low, the device will never think it&#039;s at rest. If it&#039;s too high, certain vibrations could affect your gyro biases (though the effects of these may also be limited by the Angular Velocity Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Acceleration Threshold====&lt;br /&gt;
The minimum measured acceleration your system will assume it is at rest, minus gravity. This value is also used to determine how much motion is accepted before the device begins to ignore the acceleration vector as a reliable source of “down”, and relies entirely on the gyros for pitch and roll until the device stops again. Again, you can use the noise in the graphs from your accelerometer example to get a baseline of the noise, and choose a value accordingly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too high, your device can adjust to thinking “down” is the wrong direction, or be swayed by fast motions. If this value is too low, the device may never think it is at rest to begin the process of correcting its pitch and roll.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Mag Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to re-adjust the heading 95% of the way to aligning with the compass bearing, for differences in compass bearing and AHRS heading less than 15 degrees. Outside of 15 degrees of error, this is the time it will take the AHRS heading to correct towards the compass bearing by 45 degrees, to help limit adverse effects of interference. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more (but never entirely) resistant to magnetic interference, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the magnetic field readings. If this value is low enough, white noise in your compass readings will begin to show up in your measured heading.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Accel Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to realign your pitch and roll to the acceleration vector, once the device believes it is at rest. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more resistant to acceleration affecting orientation, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the accelerometer readings (limited by the above Acceleration Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Bias Time====&lt;br /&gt;
If the sensor is deemed to be at rest, a “bias” parameter internal to the algorithm is slowly added to the gyroscope to compensate for any drift. Effectively, this will automatically gradually zero the gyro readings internal to the algorithm, reducing or eliminating the effects of drift. The time specified here (in seconds) is the time it takes to adjust the bias parameters to compensate for 95% of the gyro’s offsets once the device is at rest.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The speed the gyros should be biased is a balance between getting a solid average and having the zeroing occur quickly enough that biases can be fully compensated for during short periods or rest.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
[[File:AHRS_Example_Menu.jpg|400px|link=|thumb|The AHRS Example Parameter Selection]]&lt;br /&gt;
To get the best precision we recommend tuning these parameters as best fits your application. However, we have provided some sample values to make a couple demonstrations, and to give you some idea of how to adapt these parameters to certain situations.&lt;br /&gt;
&lt;br /&gt;
To more easily set up these example cases, this dropdown provides a list of settings for generic cases, and demonstrations of how you might adapt these values to certain scenarios.&lt;br /&gt;
&lt;br /&gt;
====General Purpose====&lt;br /&gt;
A set of values selected for your device that should work “well enough” out of the box for simple situations, such as moving the device around with your hand.&lt;br /&gt;
&lt;br /&gt;
====No Gyro====&lt;br /&gt;
To demonstrate why gyroscopes are an essential part of AHRS, we’ve given some settings that will effectively ignore any input from the gyroscopes, and snap to the magnetometer and accelerometer readings alone. You will notice this is incredibly noisy, especially if you start moving the sensor around.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====All Gyro====&lt;br /&gt;
For completeness, we have included a selection to set AHRS to more or less ignore input from the magnetometers and accelerometers. By selecting this sample, you can see how the gyroscopes will drift over time and fast motions, clearly demonstrating the need for the accelerometer and magnetometer to bring the gyros back into alignment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zeroed====&lt;br /&gt;
If you are able to zero your gyroscopes, and your application is relatively free of vibrations, you should be able to use a narrower Angular Velocity Threshold. As a result, you may also be able to relax the &#039;&#039;Mag Time&#039;&#039; and &#039;&#039;Accel Time&#039;&#039; parameters, since you can better trust that the gyroscopes will only be re-biased when they are truly not rotating.&lt;br /&gt;
&lt;br /&gt;
====High Vibrations====&lt;br /&gt;
Regardless of whether or not you can zero your gyroscope, if your system suffers from constant large vibrations, the AHRS thresholds will have to be relaxed to allow the gyros to be biased at all. In doing so, we also raise the &#039;&#039;Accel Time&#039;&#039;, not because we can trust the gyroscopes more in this scenario, but rather because we must trust the accelerometer less. Assuming there is little magnetic noise, &#039;&#039;Mag Time&#039;&#039; can be decreased to snap the heading closer to the magnetic field.&lt;br /&gt;
&lt;br /&gt;
===Suggested Parameters===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&amp;quot;&lt;br /&gt;
!  !! Angular Velocity Threshold !! Angular Vel Delta Threshold !! Acceleration Threshold !! Mag Time !! Accel Time !! Bias Time&lt;br /&gt;
|-&lt;br /&gt;
! MOT1102 || 2.0 || 0.6 || 0.1 || 5 || 5 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Out of the Box&#039;&#039; || 1.0 || 0.1 || 0.05 || 10 || 10 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Heated and Zeroed&#039;&#039; || 0.5 || 0.1 || 0.05 || 120 || 120 || 1.25&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Choosing a Phidget Spatial===&lt;br /&gt;
The Spatial Phidget you use in your application will depend on how accurate certain aspects of your measurement need to be. To simplify the decision, we can narrow this down to various kinds of applicaitons:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Applicaiton !! Phidget&lt;br /&gt;
|-&lt;br /&gt;
| Navigation or Outdoor Usage || [{{SERVER}}/products.php?product_id=MOT0110 MOT0110 PhidgetSpatial Precision 3/3/3]&lt;br /&gt;
|-&lt;br /&gt;
| Gestures and Qualitative Effects || [{{SERVER}}/products.php?product_id=MOT1102 MOT1102 Spatial Phidget]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==FAQ==&lt;br /&gt;
&lt;br /&gt;
===Why does the Euler Angle for pitch never exceed 90 degrees?===&lt;br /&gt;
The Euler Angles provided by the Phidgets library are calculated directly from a corresponding quaternion. They do not take into account past movements, so the orientation of a board that passes 90 degrees in pitch can just as easily be represented by a pitch of less than 90 degrees, with different roll and heading parameters. This is one reason why Euler Angles are not recommended for use in serious calculations, in favor of using the corresponding quaternions.&lt;br /&gt;
&lt;br /&gt;
===Why do the Euler Angle readings stop working as well near 90 degrees of pitch?===&lt;br /&gt;
This is actually a good example of gimbal lock, and why it is not advised to use Euler Angles in calculation. When pitch approaches 90 degrees, the roll and yaw axes start to line up, which makes it hard to distinguish one from the other. In other words, at 90 degrees of pitch, a change in roll could just as easily be a change in heading, and vice-versa. This is another reason we recommend quaternions for all serious calculations.&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Handling_Errors_and_Logging&amp;diff=33850</id>
		<title>Handling Errors and Logging</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Handling_Errors_and_Logging&amp;diff=33850"/>
		<updated>2023-07-14T18:51:15Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Common Errors */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Programming]]{{Recommended_Flow_Links|{{Flow Page Number|{{PAGENAME}} }} }}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
You&#039;ve written your code, fixed the compiler errors, and yet, the program still isn&#039;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.&lt;br /&gt;
&lt;br /&gt;
==Errors and Error Events==&lt;br /&gt;
&lt;br /&gt;
The Phidget library uses errors and error events to communicate information about potential problems in your program. These can happen in-line in the form of an exception or error code (which generally indicate a problem in the code), and as Error Events (which generally indicate a problem with the Phidget&#039;s environment).&lt;br /&gt;
&lt;br /&gt;
===Errors from Function Calls===&lt;br /&gt;
&lt;br /&gt;
When a call to a Phidgets function fails it will throw an exception (or return an error code, depending on the language). It is important to check each function call for errors, and to catch and handle any errors.&lt;br /&gt;
&lt;br /&gt;
Common causes of this type of error are the Phidget not being attached, or one of the values provided to the function being outside the valid range.&lt;br /&gt;
&lt;br /&gt;
You can handle exceptions and return codes as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
    ch.openWaitForAttachment(5000);&lt;br /&gt;
except PhidgetException as e:&lt;br /&gt;
    print(&amp;quot;Failed to open: &amp;quot; + e.details)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
    ch.open(5000);&lt;br /&gt;
} catch (PhidgetException ex) {&lt;br /&gt;
    System.out.println(&amp;quot;Failed to open: &amp;quot; + ex.getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
    ch.Open(); //open the device&lt;br /&gt;
}&lt;br /&gt;
catch (PhidgetException ex)&lt;br /&gt;
{&lt;br /&gt;
    Console.WriteLine(&amp;quot;Failed to open: &amp;quot; + ex.Description)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C=&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
PhidgetDigitalInputHandle ch;&lt;br /&gt;
PhidgetReturnCode res;&lt;br /&gt;
...    &lt;br /&gt;
res = Phidget_openWaitForAttachment((PhidgetHandle)ch, 5000);&lt;br /&gt;
if (res != EPHIDGET_OK) {&lt;br /&gt;
    char* desc;&lt;br /&gt;
    Phidget_getErrorDescription(res, &amp;amp;desc);&lt;br /&gt;
    printf(&amp;quot;Failed to open: (%d) %s\n&amp;quot;, res, desc);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
JavaScript=&lt;br /&gt;
In JavaScript, there are two types of exceptions to handle. The first is used in synchronous functions only, and handled using the traditional try/catch block:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
     var tmp = ch.state&lt;br /&gt;
}&lt;br /&gt;
catch(err) {&lt;br /&gt;
     console.log(&amp;quot;Failed to get state: &amp;quot; + err.message)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The second type is used for asynchronous functions, which return &amp;quot;promises&amp;quot;, handled using the &#039;await&#039; keyword in addition to a try/catch:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
async function main() {&lt;br /&gt;
    ...&lt;br /&gt;
    try {&lt;br /&gt;
        await ch.open()&lt;br /&gt;
    }&lt;br /&gt;
    catch(err) {&lt;br /&gt;
         console.log(&#039;Error:&#039; + err.message);&lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
When in doubt, check the {{Phidget22API}} to see whether the function you&#039;re checking returns a promise or not.&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The consequences of not handling errors correctly ranges from improper behavior, to the program crashing due to an unhandled exception.  Programs should check for errors on each function call, and handle any errors.&lt;br /&gt;
&lt;br /&gt;
====Error Codes====&lt;br /&gt;
&lt;br /&gt;
Full descriptions of all error codes can be found in the [[Error Code List]] page.&lt;br /&gt;
&lt;br /&gt;
===Error Events===&lt;br /&gt;
&lt;br /&gt;
Error events are asynchronously generated by Phidget devices, and by the Phidget library itself. &lt;br /&gt;
&lt;br /&gt;
These do not necessarily indicate a problem with your program, and often serve as a status update from your device that your program should know. For example, a DistanceSensor might send an OutOfRange error if it does not detect anything in its field of view, or a TemperatureSensor could send a Saturation error indicating its temperature reading is outside the valid range for the sensor.&lt;br /&gt;
&lt;br /&gt;
Error events are also fired when network errors occur, or when the library is unable to handle incoming change events quickly enough (event handlers could be too slow).&lt;br /&gt;
&lt;br /&gt;
We strongly recommend setting up an error event handler for your channels so your program can keep track of these error conditions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
#Declare the event handler&lt;br /&gt;
def onErrorHandler(self, code, description):&lt;br /&gt;
    print(&amp;quot;Code: &amp;quot; + str(code))&lt;br /&gt;
    print(&amp;quot;Description: &amp;quot; + description)&lt;br /&gt;
...&lt;br /&gt;
#Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget&lt;br /&gt;
ch = DigitalInput()&lt;br /&gt;
...&lt;br /&gt;
#Assign the handler that will be called when the event occurs&lt;br /&gt;
ch.setOnErrorHandler(onErrorHandler)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
//Declare the event listener&lt;br /&gt;
public static ErrorListener onError = new ErrorListener() {&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onError(ErrorEvent e) {&lt;br /&gt;
        System.out.println(&amp;quot;Code: &amp;quot; + e.getCode());&lt;br /&gt;
        System.out.println(&amp;quot;Description: &amp;quot; + e.getDescription());&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
...&lt;br /&gt;
//Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget.&lt;br /&gt;
DigitalInput ch;&lt;br /&gt;
...&lt;br /&gt;
//Assign the event listener that will be called when the event occurs&lt;br /&gt;
ch.addErrorListener(onError);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
//Declare the event handler&lt;br /&gt;
void error(object sender, Phidget22.Events.ErrorEventArgs e) {&lt;br /&gt;
    Console.WriteLine(&amp;quot;Code: &amp;quot; + e.Code.ToString());&lt;br /&gt;
    Console.WriteLine(&amp;quot;Description: &amp;quot; + e.Description);&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
//Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget.&lt;br /&gt;
DigitalInput ch;&lt;br /&gt;
...&lt;br /&gt;
//Assign the handler that will be called when the event occurs&lt;br /&gt;
ch.Error += error;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C=&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
//Declare the event handler&lt;br /&gt;
static void CCONV onErrorHandler(PhidgetHandle ph, void *ctx, Phidget_ErrorEventCode code, const char* description) {&lt;br /&gt;
    printf(&amp;quot;Code: %d\n&amp;quot;, code);&lt;br /&gt;
    printf(&amp;quot;Description: %s\n&amp;quot;, description);&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
//Declare your object. Replace &amp;quot;PhidgetDigitalInputHandle&amp;quot; with the handle for your Phidget object.&lt;br /&gt;
PhidgetDigitalInputHandle ch;&lt;br /&gt;
...&lt;br /&gt;
//Assign the handler that will be called when the event occurs&lt;br /&gt;
Phidget_setOnErrorHandler((PhidgetHandle)ch, onErrorHandler, NULL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
JavaScript=&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
// Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget&lt;br /&gt;
const ch = new phidget22.DigitalInput()&lt;br /&gt;
&lt;br /&gt;
// Assign the handler that will be called when the event occurs&lt;br /&gt;
ch.onError = function(code, description) {&lt;br /&gt;
    console.log(&#039;Code: &#039; + code)&lt;br /&gt;
    console.log(&#039;Description: &#039; + description)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Full descriptions of all error event codes can be found in the [[Error Event Code List]] page.&lt;br /&gt;
&lt;br /&gt;
==Logging==&lt;br /&gt;
You can enable logging to get more debugging information. 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 things happening behind the scenes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Devices.Log import *&lt;br /&gt;
from Phidget22.LogLevel import *&lt;br /&gt;
&lt;br /&gt;
Log.enable(LogLevel.PHIDGET_LOG_INFO, &amp;quot;path/to/log/file.log&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
Log.enable(LogLevel.INFO, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
Log.Enable(LogLevel.Info, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C=&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
PhidgetLog_enable(PHIDGET_LOG_INFO, NULL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
JavaScript=&lt;br /&gt;
Client-side logging is not enabled in JavaScript. For library errors, you can check the console, and for communication errors, you can enable logging on the server side. For information on how to enable and access network server logs, see the [[Network Server Troubleshooting]] page.&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; is passed to &amp;lt;code&amp;gt;enable()&amp;lt;/code&amp;gt; in the above examples, the logging system will output to &amp;lt;code&amp;gt;STDERR&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
For a more comprehensive look at the logging system in Phidget22, you can check out the [[Logging Details]] page.&lt;br /&gt;
&lt;br /&gt;
==Common Errors==&lt;br /&gt;
For more information on how to handle common errors, such as sensor data being Out of Range or Invalid, see our page on [[Handling Out Of Range Errors]].&lt;br /&gt;
&lt;br /&gt;
== Other Problems ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Flow_Navigation_Buttons|{{Flow Page Number|{{PAGENAME}} }} }}&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Handling_Errors_and_Logging&amp;diff=33849</id>
		<title>Handling Errors and Logging</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Handling_Errors_and_Logging&amp;diff=33849"/>
		<updated>2023-07-14T18:50:38Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Other Problems */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Programming]]{{Recommended_Flow_Links|{{Flow Page Number|{{PAGENAME}} }} }}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
You&#039;ve written your code, fixed the compiler errors, and yet, the program still isn&#039;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.&lt;br /&gt;
&lt;br /&gt;
==Errors and Error Events==&lt;br /&gt;
&lt;br /&gt;
The Phidget library uses errors and error events to communicate information about potential problems in your program. These can happen in-line in the form of an exception or error code (which generally indicate a problem in the code), and as Error Events (which generally indicate a problem with the Phidget&#039;s environment).&lt;br /&gt;
&lt;br /&gt;
===Errors from Function Calls===&lt;br /&gt;
&lt;br /&gt;
When a call to a Phidgets function fails it will throw an exception (or return an error code, depending on the language). It is important to check each function call for errors, and to catch and handle any errors.&lt;br /&gt;
&lt;br /&gt;
Common causes of this type of error are the Phidget not being attached, or one of the values provided to the function being outside the valid range.&lt;br /&gt;
&lt;br /&gt;
You can handle exceptions and return codes as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
    ch.openWaitForAttachment(5000);&lt;br /&gt;
except PhidgetException as e:&lt;br /&gt;
    print(&amp;quot;Failed to open: &amp;quot; + e.details)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
    ch.open(5000);&lt;br /&gt;
} catch (PhidgetException ex) {&lt;br /&gt;
    System.out.println(&amp;quot;Failed to open: &amp;quot; + ex.getMessage());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
    ch.Open(); //open the device&lt;br /&gt;
}&lt;br /&gt;
catch (PhidgetException ex)&lt;br /&gt;
{&lt;br /&gt;
    Console.WriteLine(&amp;quot;Failed to open: &amp;quot; + ex.Description)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C=&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
PhidgetDigitalInputHandle ch;&lt;br /&gt;
PhidgetReturnCode res;&lt;br /&gt;
...    &lt;br /&gt;
res = Phidget_openWaitForAttachment((PhidgetHandle)ch, 5000);&lt;br /&gt;
if (res != EPHIDGET_OK) {&lt;br /&gt;
    char* desc;&lt;br /&gt;
    Phidget_getErrorDescription(res, &amp;amp;desc);&lt;br /&gt;
    printf(&amp;quot;Failed to open: (%d) %s\n&amp;quot;, res, desc);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
JavaScript=&lt;br /&gt;
In JavaScript, there are two types of exceptions to handle. The first is used in synchronous functions only, and handled using the traditional try/catch block:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
     var tmp = ch.state&lt;br /&gt;
}&lt;br /&gt;
catch(err) {&lt;br /&gt;
     console.log(&amp;quot;Failed to get state: &amp;quot; + err.message)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The second type is used for asynchronous functions, which return &amp;quot;promises&amp;quot;, handled using the &#039;await&#039; keyword in addition to a try/catch:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
async function main() {&lt;br /&gt;
    ...&lt;br /&gt;
    try {&lt;br /&gt;
        await ch.open()&lt;br /&gt;
    }&lt;br /&gt;
    catch(err) {&lt;br /&gt;
         console.log(&#039;Error:&#039; + err.message);&lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
When in doubt, check the {{Phidget22API}} to see whether the function you&#039;re checking returns a promise or not.&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The consequences of not handling errors correctly ranges from improper behavior, to the program crashing due to an unhandled exception.  Programs should check for errors on each function call, and handle any errors.&lt;br /&gt;
&lt;br /&gt;
====Error Codes====&lt;br /&gt;
&lt;br /&gt;
Full descriptions of all error codes can be found in the [[Error Code List]] page.&lt;br /&gt;
&lt;br /&gt;
===Error Events===&lt;br /&gt;
&lt;br /&gt;
Error events are asynchronously generated by Phidget devices, and by the Phidget library itself. &lt;br /&gt;
&lt;br /&gt;
These do not necessarily indicate a problem with your program, and often serve as a status update from your device that your program should know. For example, a DistanceSensor might send an OutOfRange error if it does not detect anything in its field of view, or a TemperatureSensor could send a Saturation error indicating its temperature reading is outside the valid range for the sensor.&lt;br /&gt;
&lt;br /&gt;
Error events are also fired when network errors occur, or when the library is unable to handle incoming change events quickly enough (event handlers could be too slow).&lt;br /&gt;
&lt;br /&gt;
We strongly recommend setting up an error event handler for your channels so your program can keep track of these error conditions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
#Declare the event handler&lt;br /&gt;
def onErrorHandler(self, code, description):&lt;br /&gt;
    print(&amp;quot;Code: &amp;quot; + str(code))&lt;br /&gt;
    print(&amp;quot;Description: &amp;quot; + description)&lt;br /&gt;
...&lt;br /&gt;
#Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget&lt;br /&gt;
ch = DigitalInput()&lt;br /&gt;
...&lt;br /&gt;
#Assign the handler that will be called when the event occurs&lt;br /&gt;
ch.setOnErrorHandler(onErrorHandler)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
//Declare the event listener&lt;br /&gt;
public static ErrorListener onError = new ErrorListener() {&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onError(ErrorEvent e) {&lt;br /&gt;
        System.out.println(&amp;quot;Code: &amp;quot; + e.getCode());&lt;br /&gt;
        System.out.println(&amp;quot;Description: &amp;quot; + e.getDescription());&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
...&lt;br /&gt;
//Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget.&lt;br /&gt;
DigitalInput ch;&lt;br /&gt;
...&lt;br /&gt;
//Assign the event listener that will be called when the event occurs&lt;br /&gt;
ch.addErrorListener(onError);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
//Declare the event handler&lt;br /&gt;
void error(object sender, Phidget22.Events.ErrorEventArgs e) {&lt;br /&gt;
    Console.WriteLine(&amp;quot;Code: &amp;quot; + e.Code.ToString());&lt;br /&gt;
    Console.WriteLine(&amp;quot;Description: &amp;quot; + e.Description);&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
//Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget.&lt;br /&gt;
DigitalInput ch;&lt;br /&gt;
...&lt;br /&gt;
//Assign the handler that will be called when the event occurs&lt;br /&gt;
ch.Error += error;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C=&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
//Declare the event handler&lt;br /&gt;
static void CCONV onErrorHandler(PhidgetHandle ph, void *ctx, Phidget_ErrorEventCode code, const char* description) {&lt;br /&gt;
    printf(&amp;quot;Code: %d\n&amp;quot;, code);&lt;br /&gt;
    printf(&amp;quot;Description: %s\n&amp;quot;, description);&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
//Declare your object. Replace &amp;quot;PhidgetDigitalInputHandle&amp;quot; with the handle for your Phidget object.&lt;br /&gt;
PhidgetDigitalInputHandle ch;&lt;br /&gt;
...&lt;br /&gt;
//Assign the handler that will be called when the event occurs&lt;br /&gt;
Phidget_setOnErrorHandler((PhidgetHandle)ch, onErrorHandler, NULL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
JavaScript=&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
// Declare your object. Replace &amp;quot;DigitalInput&amp;quot; with the object for your Phidget&lt;br /&gt;
const ch = new phidget22.DigitalInput()&lt;br /&gt;
&lt;br /&gt;
// Assign the handler that will be called when the event occurs&lt;br /&gt;
ch.onError = function(code, description) {&lt;br /&gt;
    console.log(&#039;Code: &#039; + code)&lt;br /&gt;
    console.log(&#039;Description: &#039; + description)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Full descriptions of all error event codes can be found in the [[Error Event Code List]] page.&lt;br /&gt;
&lt;br /&gt;
==Logging==&lt;br /&gt;
You can enable logging to get more debugging information. 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 things happening behind the scenes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Devices.Log import *&lt;br /&gt;
from Phidget22.LogLevel import *&lt;br /&gt;
&lt;br /&gt;
Log.enable(LogLevel.PHIDGET_LOG_INFO, &amp;quot;path/to/log/file.log&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
Log.enable(LogLevel.INFO, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
Log.Enable(LogLevel.Info, null);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C=&amp;lt;syntaxhighlight lang=c&amp;gt;&lt;br /&gt;
PhidgetLog_enable(PHIDGET_LOG_INFO, NULL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
JavaScript=&lt;br /&gt;
Client-side logging is not enabled in JavaScript. For library errors, you can check the console, and for communication errors, you can enable logging on the server side. For information on how to enable and access network server logs, see the [[Network Server Troubleshooting]] page.&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; is passed to &amp;lt;code&amp;gt;enable()&amp;lt;/code&amp;gt; in the above examples, the logging system will output to &amp;lt;code&amp;gt;STDERR&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
For a more comprehensive look at the logging system in Phidget22, you can check out the [[Logging Details]] page.&lt;br /&gt;
&lt;br /&gt;
==Common Errors==&lt;br /&gt;
For more information on how to handle common errors, such as sensor data being Out of Range or Invalid, see our page on [[Handling_Out_Of_Range_Errors]].&lt;br /&gt;
&lt;br /&gt;
== Other Problems ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Flow_Navigation_Buttons|{{Flow Page Number|{{PAGENAME}} }} }}&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33848</id>
		<title>Handling Out Of Range Errors</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33848"/>
		<updated>2023-07-14T16:59:15Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Intro */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Intro==&lt;br /&gt;
All new Phidgets have been designed to seamlessly and informatively communicate problems with measured data. This allows you to more easily debug your systems, while ensuring data events from sensors continue at a steady pace. This makes it possible to use data events as a reliable time-base for your system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[Image:OutOfRangeErrorSampleGraph.png|400px|Center|link=|]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To understand the more technical points of this article, we recommend first learning about [[Phidget Programming Basics]].&lt;br /&gt;
&lt;br /&gt;
==Data Events==&lt;br /&gt;
All modern Phidgets guarantee that data events will occur on a channel at the user-defined rate, or will inform you of the actual data rate if it is unable to keep up. This remains true even if the data on the channel is unknown or invalid.&lt;br /&gt;
&lt;br /&gt;
Values from a sensor that are too high or too low to be accurately measured will be capped slightly outside the specified Minimum and Maximum values for the sensor. For example, if a temperature sensor can measure from -30&amp;amp;deg;C to 85&amp;amp;deg;C, you can expect values outside of this range to all read as -31&amp;amp;deg;C and 86&amp;amp;deg;C, respectively. You can monitor for these out-of-range indicators by checking the value from the event against the minimum and maximum values for the sensor.&lt;br /&gt;
&lt;br /&gt;
Values that are strictly unknown for one reason or another, such as a probe being unplugged, will be reported as &#039;&#039;NaN&#039;&#039; in the related event handler.  Be sure your code is robust enough to handle this possibility.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onTemperatureChange(self, temperature):&lt;br /&gt;
    if(math.isnan(temperature)):&lt;br /&gt;
        print(&amp;quot;Temperature is unknown&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;gt; self.getMaxTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too high&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;lt; self.getMinTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too low&amp;quot;)&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Temperature: &amp;quot; + str(temperature))&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnTemperatureChangeHandler(onTemperatureChange)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addTemperatureChangeListener(new &lt;br /&gt;
                  TemperatureSensorTemperatureChangeListener() {&lt;br /&gt;
			public void onTemperatureChange(TemperatureSensorTemperatureChangeEvent e) {&lt;br /&gt;
				try {&lt;br /&gt;
					if(Double.isNaN(e.getTemperature()))&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;gt; temperatureSensor0.getMaxTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;lt; temperatureSensor0.getMinTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
					else&lt;br /&gt;
						System.out.println(&amp;quot;Temperature: &amp;quot; + e.getTemperature());&lt;br /&gt;
				} catch (PhidgetException ex) {&lt;br /&gt;
					System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_TemperatureChange(object sender, Phidget22.Events.TemperatureSensorTemperatureChangeEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor ch = (TemperatureSensor)sender;&lt;br /&gt;
			if (Double.IsNaN(e.Temperature))&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;gt; ch.MaxTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;lt; ch.MinTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
			else&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature: &amp;quot; + e.Temperature);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.TemperatureChange += TemperatureSensor0_TemperatureChange;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Press Enter to Stop&lt;br /&gt;
Temperature: 14.062&lt;br /&gt;
Temperature: 14.056&lt;br /&gt;
Temperature: 14.16&lt;br /&gt;
Temperature: 389.105&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature: 504.21&lt;br /&gt;
Temperature: -198.721&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature: -153.69&lt;br /&gt;
Temperature: 19.306&lt;br /&gt;
Temperature: 17.559&lt;br /&gt;
Temperature: 17.637&lt;br /&gt;
Temperature: 17.629&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature: 15.55&lt;br /&gt;
Temperature: 16.549&lt;br /&gt;
Temperature: 16.978&lt;br /&gt;
Temperature: 17.214&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Polling==&lt;br /&gt;
When polling for data, values that are unknown, too high, or too low will give relevant return codes or exceptions, typically &#039;&#039;&#039;UNKNOWNVALUE&#039;&#039;&#039;, &#039;&#039;&#039;UNKNOWNVALUEHIGH&#039;&#039;&#039;, or &#039;&#039;&#039;UNKNOWNVALUELOW&#039;&#039;&#039; respectively.&lt;br /&gt;
&lt;br /&gt;
In most programming languages (excluding C), specific information about the error will be available to the exception handler to help identify the specifics of the error.&lt;br /&gt;
&lt;br /&gt;
For information on how to see error messages in C, look up &#039;&#039;Phidget_getLastError&#039;&#039; in the API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    for i in range(1, 10):&lt;br /&gt;
        try:&lt;br /&gt;
            print(temperatureSensor0.getTemperature())&lt;br /&gt;
        except PhidgetException as ex:&lt;br /&gt;
            print(&amp;quot;PhidgetException &amp;quot; + str(ex.code) + &amp;quot; (&amp;quot; + ex.description + &amp;quot;): &amp;quot; + ex.details)&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		while(System.in.available() == 0) {&lt;br /&gt;
			try {&lt;br /&gt;
				System.out.println(temperatureSensor0.getTemperature());&lt;br /&gt;
			} catch (PhidgetException ex) {&lt;br /&gt;
				System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
			}&lt;br /&gt;
			Thread.sleep(1000);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			while(Console.KeyAvailable == false)&lt;br /&gt;
			{&lt;br /&gt;
				try&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;Temperature: &amp;quot; + temperatureSensor0.Temperature);&lt;br /&gt;
				}&lt;br /&gt;
				catch (PhidgetException ex)&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;PhidgetException &amp;quot; + ex.ErrorCode +&lt;br /&gt;
                               &amp;quot; (&amp;quot; + ex.Description + &amp;quot;): &amp;quot; + ex.Detail);&lt;br /&gt;
				}&lt;br /&gt;
				System.Threading.Thread.Sleep(1000);&lt;br /&gt;
			}&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
24.041&lt;br /&gt;
24.052&lt;br /&gt;
PhidgetException 60 (Invalid Value - Too High): The value has been measured to be higher than the valid range of the sensor.&lt;br /&gt;
PhidgetException 60 (Invalid Value - Too High): The value has been measured to be higher than the valid range of the sensor.&lt;br /&gt;
222.166&lt;br /&gt;
-132.291&lt;br /&gt;
PhidgetException 61 (Invalid Value - Too Low): The value has been measured to be lower than the valid range of the sensor.&lt;br /&gt;
PhidgetException 61 (Invalid Value - Too Low): The value has been measured to be lower than the valid range of the sensor.&lt;br /&gt;
-132.632&lt;br /&gt;
119.862&lt;br /&gt;
120.613&lt;br /&gt;
PhidgetException 51 (Unknown or Invalid Value): The value is unknown. This can happen right after attach, when the value has not yet been received from the Phidget. This can also happen if a device has not yet been configured / enabled. Some properties can only be read back after being set.&lt;br /&gt;
PhidgetException 51 (Unknown or Invalid Value): The value is unknown. This can happen right after attach, when the value has not yet been received from the Phidget. This can also happen if a device has not yet been configured / enabled. Some properties can only be read back after being set.&lt;br /&gt;
120.045&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Error Events==&lt;br /&gt;
In addition to data events, you can use error event handlers to get specific information about error conditions as they happen. A single error event handler will provide meaningful information in text form about each error condition as it happens. These have been standardized to occur once every second for as long as the error condition persists.&lt;br /&gt;
&lt;br /&gt;
If your system has older Phidgets, this method may be the only way to access additional error information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onError(self, code, description):&lt;br /&gt;
    print(&amp;quot;Code: &amp;quot; + ErrorEventCode.getName(code))&lt;br /&gt;
    print(&amp;quot;Description: &amp;quot; + str(description))&lt;br /&gt;
    print(&amp;quot;----------&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnErrorHandler(onError)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.lang.InterruptedException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addErrorListener(new ErrorListener() {&lt;br /&gt;
			public void onError(ErrorEvent e) {&lt;br /&gt;
				System.out.println(&amp;quot;Code: &amp;quot; + e.getCode().name());&lt;br /&gt;
				System.out.println(&amp;quot;Description: &amp;quot; + e.getDescription());&lt;br /&gt;
				System.out.println(&amp;quot;----------&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_Error(object sender, Phidget22.Events.ErrorEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			Console.WriteLine(&amp;quot;Code: &amp;quot; + e.Code);&lt;br /&gt;
			Console.WriteLine(&amp;quot;Description: &amp;quot; + e.Description);&lt;br /&gt;
			Console.WriteLine(&amp;quot;----------&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
			&lt;br /&gt;
			temperatureSensor0.Error += TemperatureSensor0_Error;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Press Enter to Stop&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGEHIGH&lt;br /&gt;
Description: Temperature is too high to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGEHIGH&lt;br /&gt;
Description: Temperature is too high to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGELOW&lt;br /&gt;
Description: Temperature is too low to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGELOW&lt;br /&gt;
Description: Temperature is too low to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_BADCONNECTION&lt;br /&gt;
Description: Bad Connection: RTD is likely disconnected&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_BADCONNECTION&lt;br /&gt;
Description: Bad Connection: RTD is likely disconnected&lt;br /&gt;
----------&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:OutOfRangeErrorSampleGraph.png&amp;diff=33847</id>
		<title>File:OutOfRangeErrorSampleGraph.png</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:OutOfRangeErrorSampleGraph.png&amp;diff=33847"/>
		<updated>2023-07-14T16:56:25Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33846</id>
		<title>Handling Out Of Range Errors</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33846"/>
		<updated>2023-07-14T16:34:57Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Intro==&lt;br /&gt;
All new Phidgets have been designed to seamlessly and informatively communicate problems with measured data. This allows you to more easily debug your systems, while ensuring data events from sensors continue at a steady pace. This makes it possible to use data events as a reliable time-base for your system.&lt;br /&gt;
&lt;br /&gt;
To understand the more technical points of this article, we recommend first learning about [[Phidget Programming Basics]].&lt;br /&gt;
&lt;br /&gt;
==Data Events==&lt;br /&gt;
All modern Phidgets guarantee that data events will occur on a channel at the user-defined rate, or will inform you of the actual data rate if it is unable to keep up. This remains true even if the data on the channel is unknown or invalid.&lt;br /&gt;
&lt;br /&gt;
Values from a sensor that are too high or too low to be accurately measured will be capped slightly outside the specified Minimum and Maximum values for the sensor. For example, if a temperature sensor can measure from -30&amp;amp;deg;C to 85&amp;amp;deg;C, you can expect values outside of this range to all read as -31&amp;amp;deg;C and 86&amp;amp;deg;C, respectively. You can monitor for these out-of-range indicators by checking the value from the event against the minimum and maximum values for the sensor.&lt;br /&gt;
&lt;br /&gt;
Values that are strictly unknown for one reason or another, such as a probe being unplugged, will be reported as &#039;&#039;NaN&#039;&#039; in the related event handler.  Be sure your code is robust enough to handle this possibility.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onTemperatureChange(self, temperature):&lt;br /&gt;
    if(math.isnan(temperature)):&lt;br /&gt;
        print(&amp;quot;Temperature is unknown&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;gt; self.getMaxTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too high&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;lt; self.getMinTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too low&amp;quot;)&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Temperature: &amp;quot; + str(temperature))&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnTemperatureChangeHandler(onTemperatureChange)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addTemperatureChangeListener(new &lt;br /&gt;
                  TemperatureSensorTemperatureChangeListener() {&lt;br /&gt;
			public void onTemperatureChange(TemperatureSensorTemperatureChangeEvent e) {&lt;br /&gt;
				try {&lt;br /&gt;
					if(Double.isNaN(e.getTemperature()))&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;gt; temperatureSensor0.getMaxTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;lt; temperatureSensor0.getMinTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
					else&lt;br /&gt;
						System.out.println(&amp;quot;Temperature: &amp;quot; + e.getTemperature());&lt;br /&gt;
				} catch (PhidgetException ex) {&lt;br /&gt;
					System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_TemperatureChange(object sender, Phidget22.Events.TemperatureSensorTemperatureChangeEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor ch = (TemperatureSensor)sender;&lt;br /&gt;
			if (Double.IsNaN(e.Temperature))&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;gt; ch.MaxTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;lt; ch.MinTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
			else&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature: &amp;quot; + e.Temperature);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.TemperatureChange += TemperatureSensor0_TemperatureChange;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Press Enter to Stop&lt;br /&gt;
Temperature: 14.062&lt;br /&gt;
Temperature: 14.056&lt;br /&gt;
Temperature: 14.16&lt;br /&gt;
Temperature: 389.105&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature: 504.21&lt;br /&gt;
Temperature: -198.721&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature: -153.69&lt;br /&gt;
Temperature: 19.306&lt;br /&gt;
Temperature: 17.559&lt;br /&gt;
Temperature: 17.637&lt;br /&gt;
Temperature: 17.629&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature: 15.55&lt;br /&gt;
Temperature: 16.549&lt;br /&gt;
Temperature: 16.978&lt;br /&gt;
Temperature: 17.214&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Polling==&lt;br /&gt;
When polling for data, values that are unknown, too high, or too low will give relevant return codes or exceptions, typically &#039;&#039;&#039;UNKNOWNVALUE&#039;&#039;&#039;, &#039;&#039;&#039;UNKNOWNVALUEHIGH&#039;&#039;&#039;, or &#039;&#039;&#039;UNKNOWNVALUELOW&#039;&#039;&#039; respectively.&lt;br /&gt;
&lt;br /&gt;
In most programming languages (excluding C), specific information about the error will be available to the exception handler to help identify the specifics of the error.&lt;br /&gt;
&lt;br /&gt;
For information on how to see error messages in C, look up &#039;&#039;Phidget_getLastError&#039;&#039; in the API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    for i in range(1, 10):&lt;br /&gt;
        try:&lt;br /&gt;
            print(temperatureSensor0.getTemperature())&lt;br /&gt;
        except PhidgetException as ex:&lt;br /&gt;
            print(&amp;quot;PhidgetException &amp;quot; + str(ex.code) + &amp;quot; (&amp;quot; + ex.description + &amp;quot;): &amp;quot; + ex.details)&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		while(System.in.available() == 0) {&lt;br /&gt;
			try {&lt;br /&gt;
				System.out.println(temperatureSensor0.getTemperature());&lt;br /&gt;
			} catch (PhidgetException ex) {&lt;br /&gt;
				System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
			}&lt;br /&gt;
			Thread.sleep(1000);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			while(Console.KeyAvailable == false)&lt;br /&gt;
			{&lt;br /&gt;
				try&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;Temperature: &amp;quot; + temperatureSensor0.Temperature);&lt;br /&gt;
				}&lt;br /&gt;
				catch (PhidgetException ex)&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;PhidgetException &amp;quot; + ex.ErrorCode +&lt;br /&gt;
                               &amp;quot; (&amp;quot; + ex.Description + &amp;quot;): &amp;quot; + ex.Detail);&lt;br /&gt;
				}&lt;br /&gt;
				System.Threading.Thread.Sleep(1000);&lt;br /&gt;
			}&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
24.041&lt;br /&gt;
24.052&lt;br /&gt;
PhidgetException 60 (Invalid Value - Too High): The value has been measured to be higher than the valid range of the sensor.&lt;br /&gt;
PhidgetException 60 (Invalid Value - Too High): The value has been measured to be higher than the valid range of the sensor.&lt;br /&gt;
222.166&lt;br /&gt;
-132.291&lt;br /&gt;
PhidgetException 61 (Invalid Value - Too Low): The value has been measured to be lower than the valid range of the sensor.&lt;br /&gt;
PhidgetException 61 (Invalid Value - Too Low): The value has been measured to be lower than the valid range of the sensor.&lt;br /&gt;
-132.632&lt;br /&gt;
119.862&lt;br /&gt;
120.613&lt;br /&gt;
PhidgetException 51 (Unknown or Invalid Value): The value is unknown. This can happen right after attach, when the value has not yet been received from the Phidget. This can also happen if a device has not yet been configured / enabled. Some properties can only be read back after being set.&lt;br /&gt;
PhidgetException 51 (Unknown or Invalid Value): The value is unknown. This can happen right after attach, when the value has not yet been received from the Phidget. This can also happen if a device has not yet been configured / enabled. Some properties can only be read back after being set.&lt;br /&gt;
120.045&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Error Events==&lt;br /&gt;
In addition to data events, you can use error event handlers to get specific information about error conditions as they happen. A single error event handler will provide meaningful information in text form about each error condition as it happens. These have been standardized to occur once every second for as long as the error condition persists.&lt;br /&gt;
&lt;br /&gt;
If your system has older Phidgets, this method may be the only way to access additional error information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onError(self, code, description):&lt;br /&gt;
    print(&amp;quot;Code: &amp;quot; + ErrorEventCode.getName(code))&lt;br /&gt;
    print(&amp;quot;Description: &amp;quot; + str(description))&lt;br /&gt;
    print(&amp;quot;----------&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnErrorHandler(onError)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.lang.InterruptedException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addErrorListener(new ErrorListener() {&lt;br /&gt;
			public void onError(ErrorEvent e) {&lt;br /&gt;
				System.out.println(&amp;quot;Code: &amp;quot; + e.getCode().name());&lt;br /&gt;
				System.out.println(&amp;quot;Description: &amp;quot; + e.getDescription());&lt;br /&gt;
				System.out.println(&amp;quot;----------&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_Error(object sender, Phidget22.Events.ErrorEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			Console.WriteLine(&amp;quot;Code: &amp;quot; + e.Code);&lt;br /&gt;
			Console.WriteLine(&amp;quot;Description: &amp;quot; + e.Description);&lt;br /&gt;
			Console.WriteLine(&amp;quot;----------&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
			&lt;br /&gt;
			temperatureSensor0.Error += TemperatureSensor0_Error;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
Press Enter to Stop&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGEHIGH&lt;br /&gt;
Description: Temperature is too high to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGEHIGH&lt;br /&gt;
Description: Temperature is too high to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGELOW&lt;br /&gt;
Description: Temperature is too low to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_OUTOFRANGELOW&lt;br /&gt;
Description: Temperature is too low to be accurately measured&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_BADCONNECTION&lt;br /&gt;
Description: Bad Connection: RTD is likely disconnected&lt;br /&gt;
----------&lt;br /&gt;
Code: EEPHIDGET_BADCONNECTION&lt;br /&gt;
Description: Bad Connection: RTD is likely disconnected&lt;br /&gt;
----------&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33845</id>
		<title>Handling Out Of Range Errors</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33845"/>
		<updated>2023-07-14T16:14:00Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Data Events */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Intro==&lt;br /&gt;
All new Phidgets have been designed to seamlessly and informatively communicate problems with measured data. This allows you to more easily debug your systems, while ensuring data events from sensors continue at a steady pace. This makes it possible to use data events as a reliable time-base for your system.&lt;br /&gt;
&lt;br /&gt;
To understand the more technical points of this article, we recommend first learning about [[Phidget Programming Basics]].&lt;br /&gt;
&lt;br /&gt;
==Data Events==&lt;br /&gt;
All modern Phidgets guarantee that data events will occur on a channel at the user-defined rate, or will inform you of the actual data rate if it is unable to keep up. This remains true even if the data on the channel is unknown or invalid.&lt;br /&gt;
&lt;br /&gt;
Values from a sensor that are too high or too low to be accurately measured will be capped slightly outside the specified Minimum and Maximum values for the sensor. For example, if a temperature sensor can measure from -30&amp;amp;deg;C to 85&amp;amp;deg;C, you can expect values outside of this range to all read as -31&amp;amp;deg;C and 86&amp;amp;deg;C, respectively. You can monitor for these out-of-range indicators by checking the value from the event against the minimum and maximum values for the sensor.&lt;br /&gt;
&lt;br /&gt;
Values that are strictly unknown for one reason or another, such as a probe being unplugged, will be reported as &#039;&#039;NaN&#039;&#039; in the related event handler.  Be sure your code is robust enough to handle this possibility.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onTemperatureChange(self, temperature):&lt;br /&gt;
    if(math.isnan(temperature)):&lt;br /&gt;
        print(&amp;quot;Temperature is unknown&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;gt; self.getMaxTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too high&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;lt; self.getMinTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too low&amp;quot;)&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Temperature: &amp;quot; + str(temperature))&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnTemperatureChangeHandler(onTemperatureChange)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addTemperatureChangeListener(new &lt;br /&gt;
                  TemperatureSensorTemperatureChangeListener() {&lt;br /&gt;
			public void onTemperatureChange(TemperatureSensorTemperatureChangeEvent e) {&lt;br /&gt;
				try {&lt;br /&gt;
					if(Double.isNaN(e.getTemperature()))&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;gt; temperatureSensor0.getMaxTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;lt; temperatureSensor0.getMinTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
					else&lt;br /&gt;
						System.out.println(&amp;quot;Temperature: &amp;quot; + e.getTemperature());&lt;br /&gt;
				} catch (PhidgetException ex) {&lt;br /&gt;
					System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_TemperatureChange(object sender, Phidget22.Events.TemperatureSensorTemperatureChangeEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor ch = (TemperatureSensor)sender;&lt;br /&gt;
			if (Double.IsNaN(e.Temperature))&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;gt; ch.MaxTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;lt; ch.MinTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
			else&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature: &amp;quot; + e.Temperature);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.TemperatureChange += TemperatureSensor0_TemperatureChange;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Sample Output=&lt;br /&gt;
Press Enter to Stop&lt;br /&gt;
Temperature: 14.062&lt;br /&gt;
Temperature: 14.056&lt;br /&gt;
Temperature: 14.16&lt;br /&gt;
Temperature: 389.105&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature is too high&lt;br /&gt;
Temperature: 504.21&lt;br /&gt;
Temperature: -198.721&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature is too low&lt;br /&gt;
Temperature: -153.69&lt;br /&gt;
Temperature: 19.306&lt;br /&gt;
Temperature: 17.559&lt;br /&gt;
Temperature: 17.637&lt;br /&gt;
Temperature: 17.629&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature is unknown&lt;br /&gt;
Temperature: 15.55&lt;br /&gt;
Temperature: 16.549&lt;br /&gt;
Temperature: 16.978&lt;br /&gt;
Temperature: 17.214&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Polling==&lt;br /&gt;
When polling for data, values that are unknown, too high, or too low will give relevant return codes or exceptions, typically &#039;&#039;&#039;UNKNOWNVALUE&#039;&#039;&#039;, &#039;&#039;&#039;UNKNOWNVALUEHIGH&#039;&#039;&#039;, or &#039;&#039;&#039;UNKNOWNVALUELOW&#039;&#039;&#039; respectively.&lt;br /&gt;
&lt;br /&gt;
In most programming languages (excluding C), specific information about the error will be available to the exception handler to help identify the specifics of the error.&lt;br /&gt;
&lt;br /&gt;
For information on how to see error messages in C, look up &#039;&#039;Phidget_getLastError&#039;&#039; in the API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    for i in range(1, 10):&lt;br /&gt;
        try:&lt;br /&gt;
            print(temperatureSensor0.getTemperature())&lt;br /&gt;
        except PhidgetException as ex:&lt;br /&gt;
            print(&amp;quot;PhidgetException &amp;quot; + str(ex.code) + &amp;quot; (&amp;quot; + ex.description + &amp;quot;): &amp;quot; + ex.details)&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		while(System.in.available() == 0) {&lt;br /&gt;
			try {&lt;br /&gt;
				System.out.println(temperatureSensor0.getTemperature());&lt;br /&gt;
			} catch (PhidgetException ex) {&lt;br /&gt;
				System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
			}&lt;br /&gt;
			Thread.sleep(1000);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			while(Console.KeyAvailable == false)&lt;br /&gt;
			{&lt;br /&gt;
				try&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;Temperature: &amp;quot; + temperatureSensor0.Temperature);&lt;br /&gt;
				}&lt;br /&gt;
				catch (PhidgetException ex)&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;PhidgetException &amp;quot; + ex.ErrorCode +&lt;br /&gt;
                               &amp;quot; (&amp;quot; + ex.Description + &amp;quot;): &amp;quot; + ex.Detail);&lt;br /&gt;
				}&lt;br /&gt;
				System.Threading.Thread.Sleep(1000);&lt;br /&gt;
			}&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Error Events==&lt;br /&gt;
In addition to data events, you can use error event handlers to get specific information about error conditions as they happen. A single error event handler will provide meaningful information in text form about each error condition as it happens. These have been standardized to occur once every second for as long as the error condition persists.&lt;br /&gt;
&lt;br /&gt;
If your system has older Phidgets, this method may be the only way to access additional error information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onError(self, code, description):&lt;br /&gt;
    print(&amp;quot;Code: &amp;quot; + ErrorEventCode.getName(code))&lt;br /&gt;
    print(&amp;quot;Description: &amp;quot; + str(description))&lt;br /&gt;
    print(&amp;quot;----------&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnErrorHandler(onError)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.lang.InterruptedException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addErrorListener(new ErrorListener() {&lt;br /&gt;
			public void onError(ErrorEvent e) {&lt;br /&gt;
				System.out.println(&amp;quot;Code: &amp;quot; + e.getCode().name());&lt;br /&gt;
				System.out.println(&amp;quot;Description: &amp;quot; + e.getDescription());&lt;br /&gt;
				System.out.println(&amp;quot;----------&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_Error(object sender, Phidget22.Events.ErrorEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			Console.WriteLine(&amp;quot;Code: &amp;quot; + e.Code);&lt;br /&gt;
			Console.WriteLine(&amp;quot;Description: &amp;quot; + e.Description);&lt;br /&gt;
			Console.WriteLine(&amp;quot;----------&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
			&lt;br /&gt;
			temperatureSensor0.Error += TemperatureSensor0_Error;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33821</id>
		<title>Handling Out Of Range Errors</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Handling_Out_Of_Range_Errors&amp;diff=33821"/>
		<updated>2023-07-13T16:05:50Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Created page with &amp;quot;__TOC__ ==Intro== All new Phidgets have been designed to seamlessly and informatively communicate problems with measured data. This allows you to more easily debug your systems, while ensuring data events from sensors continue at a steady pace. This makes it possible to use data events as a reliable time-base for your system.  To understand the more technical points of this article, we recommend first learning about Phidget Programming Basics.  ==Data Events== All mo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Intro==&lt;br /&gt;
All new Phidgets have been designed to seamlessly and informatively communicate problems with measured data. This allows you to more easily debug your systems, while ensuring data events from sensors continue at a steady pace. This makes it possible to use data events as a reliable time-base for your system.&lt;br /&gt;
&lt;br /&gt;
To understand the more technical points of this article, we recommend first learning about [[Phidget Programming Basics]].&lt;br /&gt;
&lt;br /&gt;
==Data Events==&lt;br /&gt;
All modern Phidgets guarantee that data events will occur on a channel at the user-defined rate, or will inform you of the actual data rate if it is unable to keep up. This remains true even if the data on the channel is unknown or invalid.&lt;br /&gt;
&lt;br /&gt;
Values from a sensor that are too high or too low to be accurately measured will be capped slightly outside the specified Minimum and Maximum values for the sensor. For example, if a temperature sensor can measure from -30&amp;amp;deg;C to 85&amp;amp;deg;C, you can expect values outside of this range to all read as -31&amp;amp;deg;C and 86&amp;amp;deg;C, respectively. You can monitor for these out-of-range indicators by checking the value from the event against the minimum and maximum values for the sensor.&lt;br /&gt;
&lt;br /&gt;
Values that are strictly unknown for one reason or another, such as a probe being unplugged, will be reported as &#039;&#039;NaN&#039;&#039; in the related event handler.  Be sure your code is robust enough to handle this possibility.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onTemperatureChange(self, temperature):&lt;br /&gt;
    if(math.isnan(temperature)):&lt;br /&gt;
        print(&amp;quot;Temperature is unknown&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;gt; self.getMaxTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too high&amp;quot;)&lt;br /&gt;
    elif(temperature &amp;lt; self.getMinTemperature()):&lt;br /&gt;
        print(&amp;quot;Temperature is too low&amp;quot;)&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Temperature: &amp;quot; + str(temperature))&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnTemperatureChangeHandler(onTemperatureChange)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addTemperatureChangeListener(new &lt;br /&gt;
                  TemperatureSensorTemperatureChangeListener() {&lt;br /&gt;
			public void onTemperatureChange(TemperatureSensorTemperatureChangeEvent e) {&lt;br /&gt;
				try {&lt;br /&gt;
					if(Double.isNaN(e.getTemperature()))&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;gt; temperatureSensor0.getMaxTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
					else if(e.getTemperature() &amp;lt; temperatureSensor0.getMinTemperature())&lt;br /&gt;
						System.out.println(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
					else&lt;br /&gt;
						System.out.println(&amp;quot;Temperature: &amp;quot; + e.getTemperature());&lt;br /&gt;
				} catch (PhidgetException ex) {&lt;br /&gt;
					System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_TemperatureChange(object sender, Phidget22.Events.TemperatureSensorTemperatureChangeEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor ch = (TemperatureSensor)sender;&lt;br /&gt;
			if (Double.IsNaN(e.Temperature))&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is unknown&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;gt; ch.MaxTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too high&amp;quot;);&lt;br /&gt;
			else if (e.Temperature &amp;lt; ch.MinTemperature)&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature is too low&amp;quot;);&lt;br /&gt;
			else&lt;br /&gt;
				Console.WriteLine(&amp;quot;Temperature: &amp;quot; + e.Temperature);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.TemperatureChange += TemperatureSensor0_TemperatureChange;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Polling==&lt;br /&gt;
When polling for data, values that are unknown, too high, or too low will give relevant return codes or exceptions, typically &#039;&#039;&#039;UNKNOWNVALUE&#039;&#039;&#039;, &#039;&#039;&#039;UNKNOWNVALUEHIGH&#039;&#039;&#039;, or &#039;&#039;&#039;UNKNOWNVALUELOW&#039;&#039;&#039; respectively.&lt;br /&gt;
&lt;br /&gt;
In most programming languages (excluding C), specific information about the error will be available to the exception handler to help identify the specifics of the error.&lt;br /&gt;
&lt;br /&gt;
For information on how to see error messages in C, look up &#039;&#039;Phidget_getLastError&#039;&#039; in the API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import math&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    for i in range(1, 10):&lt;br /&gt;
        try:&lt;br /&gt;
            print(temperatureSensor0.getTemperature())&lt;br /&gt;
        except PhidgetException as ex:&lt;br /&gt;
            print(&amp;quot;PhidgetException &amp;quot; + str(ex.code) + &amp;quot; (&amp;quot; + ex.description + &amp;quot;): &amp;quot; + ex.details)&lt;br /&gt;
        time.sleep(1)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.util.Scanner; //Required for Text Input&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		while(System.in.available() == 0) {&lt;br /&gt;
			try {&lt;br /&gt;
				System.out.println(temperatureSensor0.getTemperature());&lt;br /&gt;
			} catch (PhidgetException ex) {&lt;br /&gt;
				System.out.println(&amp;quot;PhidgetException &amp;quot; + &lt;br /&gt;
                        ex.getErrorCode() + &amp;quot; (&amp;quot; + ex.getDescription() + &amp;quot;): &amp;quot; +&lt;br /&gt;
                        ex.getDetail());&lt;br /&gt;
			}&lt;br /&gt;
			Thread.sleep(1000);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			while(Console.KeyAvailable == false)&lt;br /&gt;
			{&lt;br /&gt;
				try&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;Temperature: &amp;quot; + temperatureSensor0.Temperature);&lt;br /&gt;
				}&lt;br /&gt;
				catch (PhidgetException ex)&lt;br /&gt;
				{&lt;br /&gt;
					Console.WriteLine(&amp;quot;PhidgetException &amp;quot; + ex.ErrorCode +&lt;br /&gt;
                               &amp;quot; (&amp;quot; + ex.Description + &amp;quot;): &amp;quot; + ex.Detail);&lt;br /&gt;
				}&lt;br /&gt;
				System.Threading.Thread.Sleep(1000);&lt;br /&gt;
			}&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Error Events==&lt;br /&gt;
In addition to data events, you can use error event handlers to get specific information about error conditions as they happen. A single error event handler will provide meaningful information in text form about each error condition as it happens. These have been standardized to occur once every second for as long as the error condition persists.&lt;br /&gt;
&lt;br /&gt;
If your system has older Phidgets, this method may be the only way to access additional error information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tabber&amp;gt;&lt;br /&gt;
Python=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=python&amp;gt;&lt;br /&gt;
from Phidget22.Phidget import *&lt;br /&gt;
from Phidget22.Devices.TemperatureSensor import *&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
def onError(self, code, description):&lt;br /&gt;
    print(&amp;quot;Code: &amp;quot; + ErrorEventCode.getName(code))&lt;br /&gt;
    print(&amp;quot;Description: &amp;quot; + str(description))&lt;br /&gt;
    print(&amp;quot;----------&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    temperatureSensor0 = TemperatureSensor()&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.setOnErrorHandler(onError)&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.openWaitForAttachment(5000)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        input(&amp;quot;Press Enter to Stop\n&amp;quot;)&lt;br /&gt;
    except (Exception, KeyboardInterrupt):&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    temperatureSensor0.close()&lt;br /&gt;
&lt;br /&gt;
main()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
Java=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=java&amp;gt;&lt;br /&gt;
import com.phidget22.*;&lt;br /&gt;
import java.lang.InterruptedException;&lt;br /&gt;
&lt;br /&gt;
public class Java_Example {&lt;br /&gt;
&lt;br /&gt;
	public static void main(String[] args) throws Exception {&lt;br /&gt;
		TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.addErrorListener(new ErrorListener() {&lt;br /&gt;
			public void onError(ErrorEvent e) {&lt;br /&gt;
				System.out.println(&amp;quot;Code: &amp;quot; + e.getCode().name());&lt;br /&gt;
				System.out.println(&amp;quot;Description: &amp;quot; + e.getDescription());&lt;br /&gt;
				System.out.println(&amp;quot;----------&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.open(5000);&lt;br /&gt;
&lt;br /&gt;
		//Wait until Enter has been pressed before exiting&lt;br /&gt;
		System.in.read();&lt;br /&gt;
&lt;br /&gt;
		temperatureSensor0.close();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-|&lt;br /&gt;
C#=&lt;br /&gt;
&amp;lt;syntaxhighlight lang=cSharp&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using Phidget22;&lt;br /&gt;
&lt;br /&gt;
namespace ConsoleApplication&lt;br /&gt;
{&lt;br /&gt;
	class Program&lt;br /&gt;
	{&lt;br /&gt;
&lt;br /&gt;
		private static void TemperatureSensor0_Error(object sender, Phidget22.Events.ErrorEventArgs e)&lt;br /&gt;
		{&lt;br /&gt;
			Console.WriteLine(&amp;quot;Code: &amp;quot; + e.Code);&lt;br /&gt;
			Console.WriteLine(&amp;quot;Description: &amp;quot; + e.Description);&lt;br /&gt;
			Console.WriteLine(&amp;quot;----------&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		static void Main(string[] args)&lt;br /&gt;
		{&lt;br /&gt;
			TemperatureSensor temperatureSensor0 = new TemperatureSensor();&lt;br /&gt;
			&lt;br /&gt;
			temperatureSensor0.Error += TemperatureSensor0_Error;&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Open(5000);&lt;br /&gt;
&lt;br /&gt;
			//Wait until Enter has been pressed before exiting&lt;br /&gt;
			Console.ReadLine();&lt;br /&gt;
&lt;br /&gt;
			temperatureSensor0.Close();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/tabber&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=DC_Motor_and_Controller_Guide&amp;diff=33447</id>
		<title>DC Motor and Controller Guide</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=DC_Motor_and_Controller_Guide&amp;diff=33447"/>
		<updated>2023-04-21T16:32:34Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Primer]]&lt;br /&gt;
[[Image:3253.jpg|link=|270px]]&lt;br /&gt;
[[Image:DCC1000.jpg|link=|270px]]&lt;br /&gt;
[[Image:DC Motor Image 3.jpg|link=|270px]]&lt;br /&gt;
{{TOC limit|2}}&lt;br /&gt;
==Introduction==&lt;br /&gt;
[[File:DC Motor and Controller.jpg|link=|200px|thumb|A DC Motor and Phidgets DC Motor Controller]]&lt;br /&gt;
DC Motors are the simplest way to turn electrical power into physical motion.&lt;br /&gt;
&lt;br /&gt;
They can be found in all types of applications, from power tools, to remote control cars, to large industrial machinery.&lt;br /&gt;
&lt;br /&gt;
==Brushless DC Motors vs Regular DC Motors==&lt;br /&gt;
[[File:BLDC Motor and Controller.jpg|link=|200px|thumb|A BLDC Motor and Phidgets BLDC Motor Controller]]&lt;br /&gt;
Brushless DC (BLDC) Motors are similar enough in control principles to DC Motors when using the right Phidgets that they can be treated the same as basic DC Motors for this discussion.&lt;br /&gt;
&lt;br /&gt;
Brushless DC motors tend to have better efficiency, power and longevity than their standard (brushed) counterparts, while simply requiring more wiring. There are more internal complexities, but these differences are handled automatically by using the correct motor controller.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Phidgets brushless DC motor controllers only support sensored BLDC motors, which are the most common type for serious applications.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Basic Principles==&lt;br /&gt;
[[File:DC Motor Basic Image.jpg|link=|200px|thumb|A DC Motor spins when voltage is applied.]]&lt;br /&gt;
At the most basic level, a DC motor spins by applying voltage across the motor terminals. Apply more voltage and the motor spins faster. As the motor gets loaded down, it will be forced to spend more energy fighting the load, and will slow down accordingly.&lt;br /&gt;
&lt;br /&gt;
The force applied by a DC motor at a given voltage reduces as it spins faster. We’ll cover the reasons later, but the result is that for any applied voltage and motor loading, the motor will accelerate to a speed that balances the force required to move the motor.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The graph below shows the relationship between motor voltage and speed of rotation for a motor we tested, captured in the Phidgets Control Panel.&lt;br /&gt;
[[File:DC Motor Simple Control Graph.jpg|link=|500px|center|Controlling a DC Motor]]&lt;br /&gt;
&lt;br /&gt;
==Basic Control==&lt;br /&gt;
In this way, you can control a DC Motor’s speed by adjusting the applied voltage. This can be done using DCMotor Phidgets to drive a motor forwards or backwards at different speeds.&lt;br /&gt;
&lt;br /&gt;
[[File:DC Motor Simple Control.jpg|link=|center|Controlling a DC Motor]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A DC motor controller Phidget allows you to control the relative speed of the motor by setting a fraction of full power to give to the motor. For many applications this is already a good enough approximation of controlling the motor’s speed for basic control.&lt;br /&gt;
&lt;br /&gt;
==Control Methods==&lt;br /&gt;
[[File:DC Motor with Encoder.jpg|link=|200px|thumb|An encoder attached to a DC Motor]]&lt;br /&gt;
You can pair a DC motor with data from any number of sensors to move mechanical systems in various ways. We won’t cover the specifics of how to use them here, but Phidgets users have had success controlling DC motor based systems using a wide array of sensors, from rotation sensors, to draw-wire sensors, to spatial tilt sensors.&lt;br /&gt;
&lt;br /&gt;
The most direct way of measuring the position of your motor with Phidgets is using an encoder interface. For the purposes of this document, an encoder is simply a device that measures position information in a way that digital systems can understand. &lt;br /&gt;
&lt;br /&gt;
DC Motors sold by Phidgets have the option to attach an encoder to measure their rotation, and most Phidget motor controllers have a plug for an encoder built-in. Modern Phidgets motor controllers have built-in features to use this information to produce smooth motion.&lt;br /&gt;
&lt;br /&gt;
==Phidgets Built-In Position Control==&lt;br /&gt;
You can use the built-in encoder input on many recent DC Motor Phidgets to control the position of your system directly, using the MotorPositionController feature provided by Phidgets.&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;{{#ev:youtube|0cQlxNd7dk4|||||rel=0}}&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
This feature allows you to set up your system so you only need to tell the motor where to go with a given speed and acceleration, and it will go there.&lt;br /&gt;
&lt;br /&gt;
==Torque, Current and Power==&lt;br /&gt;
Now that we have covered the basics of using DC motors and how easily they can be controlled with Phidgets, we can cover more in-depth concerns, such as torque curves and power consumption.&lt;br /&gt;
&lt;br /&gt;
[[File:DC Motor Current vs Supply.jpg|link=|200px|thumb|A DC Motor Draws More Current Under Load]]&lt;br /&gt;
A DC Motor’s torque is proportional to the electrical current flowing through it. The more current, the harder the motor pushes to get moving. A higher supply voltage will try to push more current, and allow a higher maximum torque for a given motor.&lt;br /&gt;
&lt;br /&gt;
As a DC motor spins faster, it begins trying to generate its own current to oppose the motion. So long as the motor is powered, this results in a reduced current driving the motor.  Under no load, the motor will spin up to the point where this generated electromotive force (EMF) cancels out the supply, and the system consumes barely any power while spinning as fast as it can.&lt;br /&gt;
&lt;br /&gt;
As the motor gets loaded down, the motor slows allowing more current to flow and generating more torque to fight the load. This tendency of the motor to consume more current at low speeds means that the DC Motor will work harder when it’s weighed down, and when it’s starting up.&lt;br /&gt;
&lt;br /&gt;
[[File:DC Motor Overload.jpg|link=|200px|thumb|Thermal Image of a Stalled DC Motor]]&lt;br /&gt;
Once the motor is loaded down to the point it can no longer spin, it will consume as much current as it can, generating maximum torque, but potentially overheating in the process. Overloading an electric motor to this point is called a “stall” and should be avoided.&lt;br /&gt;
&lt;br /&gt;
To prevent problems caused by this kind of runaway current, Phidgets DC Motor Controllers have a current limiting feature. This can be useful in both preventing overheating and/or automatically limiting the available torque if desired.&lt;br /&gt;
&lt;br /&gt;
==Braking==&lt;br /&gt;
[[File:DC Motor Braking.jpg|link=|200px|thumb|A DC motor can be made to passively resist fast movement]]&lt;br /&gt;
Another result of the electromotive forces (EMF) caused by the spinning motor is that by connecting the motor terminals together when it’s spinning, the motor will produce a current (and thus a force) opposing the rotation of the motor. This method of using the motor’s own rotation against itself is called braking.&lt;br /&gt;
&lt;br /&gt;
When braking, a faster rotation generates a higher EMF, resulting in a higher braking current, and the motor will brake harder when it’s spinning faster.&lt;br /&gt;
&lt;br /&gt;
A DC Motor that is not moving will generate no passive braking, as no motion results in no EMF being generated, and thus no current and no torque.&lt;br /&gt;
&lt;br /&gt;
A Phidgets DC Motor controller can be used to control the braking force applied by your DC motor.&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Braking.jpg&amp;diff=33446</id>
		<title>File:DC Motor Braking.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Braking.jpg&amp;diff=33446"/>
		<updated>2023-04-21T16:31:26Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Overload.jpg&amp;diff=33445</id>
		<title>File:DC Motor Overload.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Overload.jpg&amp;diff=33445"/>
		<updated>2023-04-21T16:31:09Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Current_vs_Supply.jpg&amp;diff=33444</id>
		<title>File:DC Motor Current vs Supply.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Current_vs_Supply.jpg&amp;diff=33444"/>
		<updated>2023-04-21T16:30:57Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_with_Encoder.jpg&amp;diff=33443</id>
		<title>File:DC Motor with Encoder.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_with_Encoder.jpg&amp;diff=33443"/>
		<updated>2023-04-21T16:30:40Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Simple_Control.jpg&amp;diff=33442</id>
		<title>File:DC Motor Simple Control.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Simple_Control.jpg&amp;diff=33442"/>
		<updated>2023-04-21T16:30:23Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Simple_Control_Graph.jpg&amp;diff=33441</id>
		<title>File:DC Motor Simple Control Graph.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Simple_Control_Graph.jpg&amp;diff=33441"/>
		<updated>2023-04-21T16:30:09Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Basic_Image.jpg&amp;diff=33440</id>
		<title>File:DC Motor Basic Image.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Basic_Image.jpg&amp;diff=33440"/>
		<updated>2023-04-21T16:29:54Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:DC Motor Basic Image.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:BLDC_Motor_and_Controller.jpg&amp;diff=33439</id>
		<title>File:BLDC Motor and Controller.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:BLDC_Motor_and_Controller.jpg&amp;diff=33439"/>
		<updated>2023-04-21T16:29:44Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Basic_Image.jpg&amp;diff=33438</id>
		<title>File:DC Motor Basic Image.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Basic_Image.jpg&amp;diff=33438"/>
		<updated>2023-04-21T16:28:09Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_and_Controller.jpg&amp;diff=33437</id>
		<title>File:DC Motor and Controller.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_and_Controller.jpg&amp;diff=33437"/>
		<updated>2023-04-21T16:27:30Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Image_3.jpg&amp;diff=33436</id>
		<title>File:DC Motor Image 3.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:DC_Motor_Image_3.jpg&amp;diff=33436"/>
		<updated>2023-04-21T16:27:09Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=33172</id>
		<title>Spatial Guide</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Spatial_Guide&amp;diff=33172"/>
		<updated>2022-07-19T22:55:40Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Temperature Stabilization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Primer]]&lt;br /&gt;
{{TOC limit|2}}&lt;br /&gt;
&lt;br /&gt;
==Spatial Sensors and Their Uses==&lt;br /&gt;
[[Image:Spatial_Intro.jpg|link=|center]]&lt;br /&gt;
===Introduction to AHRS===&lt;br /&gt;
Phidgets Spatial sensors use AHRS (Attitude and Heading Reference System) as a means of combining data from accelerometers, magnetometers and gyroscopes into a calculation of the device’s orientation more precise than could be achieved by any of the sensors individually.&lt;br /&gt;
&lt;br /&gt;
While this process is by no means straightforward, PhidgetSpatial sensors come with built-in AHRS calculations combining data from all three types of sensors out of the box. By using the Phidget Spatial object in your code, you can get a direct reading of the heading of your device, in both Euler angle and Quaternion form.&lt;br /&gt;
&lt;br /&gt;
===Euler Angles===&lt;br /&gt;
[[File:EulerAngles.jpg|330px|link=|thumb|A Representation of Euler Angles]]&lt;br /&gt;
Euler angles are a measure of an object’s orientation in the form of pitch, roll, and yaw angles. The advantage of Euler angles in denoting heading is that they are relatively easy to visualise.&lt;br /&gt;
You can get the Euler angles of your sensor directly from the Phidgets library.&lt;br /&gt;
&lt;br /&gt;
While they are a human-friendly way of denoting overall orientation, we strongly recommend against using Euler angles in post-processing calculations, as they can be susceptible to problems of [https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics gimbal lock]. For applications requiring more adjustments than a simple heading offset, we recommend using quaternions.&lt;br /&gt;
&lt;br /&gt;
===Quaternions===&lt;br /&gt;
[[Image:quarternion.jpg|thumb|link=|A Visualization of Quaternions]]&lt;br /&gt;
For applications that require more complex analysis, PhidgetSpatial devices also provide the orientation of the device using quaternions. Quaternions are a more mathematically complete way of denoting orientation and rotations of a system. For what they lose in intuitiveness, the advantage of quaternions is that they can be used in any number of complex calculations without the risk of the aforementioned gimbal lock.&lt;br /&gt;
&lt;br /&gt;
For most practical purposes, it helps to remember that quaternions are not meant to be visualized, or dealt with directly. Instead, any program or library that uses them will have functions to perform calculations with them behind the scenes. If you don’t yet have such a library in your program, but need to use quaternions, we recommend finding one, rather than wading through the math yourself. In this way, while they are difficult to visualize, you can at least remain comfortable in the knowledge that one does not often need to fully understand quaternions to use them in an application.&lt;br /&gt;
&lt;br /&gt;
Quaternions tend to be the preferred rotation system for programs that deal with 3D objects, like Unity, and their inclusion as an output directly from a PhidgetSpatial is designed to make sensor integration as seamless as possible.&lt;br /&gt;
&lt;br /&gt;
===What Does AHRS Actually Do?===&lt;br /&gt;
The AHRS algorithm on Phidgets uses an accelerometer and a magnetometer to keep track of heading over long timescales. When the device is perceived to be at rest, the heading and gyroscopes are gradually aligned and zeroed to reflect that the device is not moving, and pointed towards combined direction from the magnetometer and accelerometer readings. When the device is in motion, the AHRS algorithm starts relying more heavily on the gyroscope for angular rotations, since the accelerometer may no longer be pointing straight down, and the field from the compass may be in flux. By adjusting how much the device relies on the gyroscope in place of the accelerometer and magnetometer, a smoother and more accurate profile of the device’s orientation can be achieved than by using any of the sensors alone.&lt;br /&gt;
&lt;br /&gt;
===Temperature Stabilization===&lt;br /&gt;
Electronic accelerometers and gyroscopes are sensitive to changes in temperature to a small but measurable degree. For cases where long term accuracy is a priority, some of our Spatial sensors have a temperature stabilization feature which allows the boards to heat themselves up to a pre-defined constant temperature (typically 45 or 50&amp;amp;deg;C) to reduce or eliminate drift due to temperature effects.&lt;br /&gt;
&lt;br /&gt;
When using the temperature stabilization feature, it is very important to wait for the board to be fully heated and settled before use, as the process of heating the board will change the sensor readings as the temperature rises to the target. Phidgets that allow temperature stabilization are calibrated at their target temperature, so the sensors will produce more accurate results once heated.&lt;br /&gt;
&lt;br /&gt;
If you are using a temperature-stabilized spatial sensor, it is also very important to keep the board in its enclosure or otherwise insulated from outside air, as air moving directly over the warmed sensors will cause worse results than if the board was not heated at all.&lt;br /&gt;
&lt;br /&gt;
==Demonstrations Using the Control Panel Example==&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note: &#039;&#039;&#039;If your control panel example does not resemble the following, be sure to update your Phidget Control Panel. &amp;lt;br&amp;gt;If your example still doesn&#039;t match, your Spatial Phidget is likely too old to support built-in AHRS calculations.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:Spatial_Example_AlignModel.jpg|400px|link=|thumb|Click the &#039;&#039;Align Model&#039;&#039; button to align the AHRS model to your screen]]&lt;br /&gt;
&lt;br /&gt;
The spatial example gives you a way to directly visualize the results from the AHRS algorithm used on Phidget Spatial sensors.  We recommend using this example with the sensor in hand at your desk to help visualize the effectiveness of the algorithm. &lt;br /&gt;
&lt;br /&gt;
The first thing you might notice is that the model doesn’t appear to match the orientation of the spatial in your hand. To make the AHRS model line up with your physical spatial, point the wire at the screen and click Align Model. Your spatial model should now mirror the movements of the spatial in your hand.&lt;br /&gt;
&lt;br /&gt;
The AHRS compass drawing is also provided as a visual indicator of the Heading, independent of the screen location. Notice that the compass bearing indicates north when the left-hand side of the Phidget is pointed north.&lt;br /&gt;
&lt;br /&gt;
If your sensor has a heating option, be sure to check the &#039;&#039;Heating Enabled&#039;&#039; box, and wait until the temperature reading stays green for best results. In your own programs, wait until the temperature reaches 45C, and then if possible give the sensor an additional minute or two to ensure the whole board is evenly heated.&lt;br /&gt;
&lt;br /&gt;
===AHRS Settings===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Settings.jpg|400px|link=|thumb|The AHRS Settings Box]]&lt;br /&gt;
Now we can look at the AHRS settings panel:&lt;br /&gt;
====Algorithm====&lt;br /&gt;
The algorithm setting dictates whether or not the compass is going to be factored into calculations.&lt;br /&gt;
&lt;br /&gt;
*When setting Algorithm to AHRS (the default setting) heading is gradually re-aligned with the compass over time, and all headings will be relative to magnetic north. When you Zero the AHRS algorithm, it will forcibly realign the heading to the compass reading.&lt;br /&gt;
&lt;br /&gt;
*When using IMU, the compass readings are ignored, and a heading of 0° corresponds to the direction the device was facing when it was started, or where it was last zeroed. By clicking the Zero Algorithm button, it will realign all calculations to reference the direction it is currently facing as the new 0° heading.&lt;br /&gt;
&lt;br /&gt;
====Zero Algorithm====&lt;br /&gt;
The Zero Algorithm button centers the algorithm’s heading either on the compass reading or on the direction it is currently facing (see AHRS Mode). The accumulated gyro biases will also be dropped, reverting to the raw (zeroed) gyro measurements. Note that the initial position in AHRS mode can vary by a couple degrees initially, due to noise inherent in the compass measurements. Click &#039;&#039;Zero Algorithm&#039;&#039; a few times now to see this for yourself. This noise will be averaged out by the rest of the algorithm, and it should settle into a consistent position after a couple seconds.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you find the model is drifting more than 2-3 degrees immediately after Zeroing the algorithm (while the spatial is staying still) you may want to try zeroing the gyroscope for better results.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zero Gyro====&lt;br /&gt;
Before zeroing the gyroscope, ensure it is securely at rest. Zeroing the gyroscope will average the gyroscope’s readings for a second or two, and automatically subtract the result from subsequent measurements. This is a way to combat drift in the gyros, and we recommend finding a way to zero the gyros before starting AHRS calculations. The results of zeroing the gyro will only persist for as long as it remains open.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If explicitly zeroing the gyro is not practical in your application, you can consider running the AHRS algorithm briefly with a wide &#039;&#039;Angular Velocity Threshold&#039;&#039;, then narrowing said threshold again once the system has a chance to compensate for drift on its own.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===AHRS Parameters===&lt;br /&gt;
[[File:Spatial_Example_AHRS_Parameters.jpg|400px|link=|thumb|The AHRS Parameters Box]]&lt;br /&gt;
The AHRS parameters are used to determine certain characteristics of your system so the AHRS algorithm can make better assumptions about the movement in your system. Each of these parameters will have recommended values as a starting point for your Phidget in a [[#Suggested Parameters|table]] below.&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Threshold====&lt;br /&gt;
This is the minimum reading from your gyroscopes that the device will use to assume the device is at rest. While the device assumes it is at rest, it will gradually adjust towards making the current gyro readings the new “zero”, compensating for drift over time. This value can be significantly lower if you have zeroed your gyroscope before zeroing the algorithm, as the pre-existing drift of the gyros will have been accounted for. Otherwise, this value will need to be large enough to overcome any pre-existing offsets in your gyro.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The closer you can set this value to zero, the slower the device needs to turn (or think it’s turning) to stop adjusting the gyro biases. If this value is too high, the gyros can be biased away from what is truly stationary. If this value is too low, the gyros will never adjust their bias, and you will see drift over time.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Angular Velocity Delta Threshold====&lt;br /&gt;
This is the minimum change between gyroscope samples before the gyro stops thinking it’s at rest. You can get a good value for this from the gyroscope example after installing the gyro in your application. Simply open the graphs for all axes, and set this value near the peak-to-peak noise.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too low, the device will never think it&#039;s at rest. If it&#039;s too high, certain vibrations could affect your gyro biases (though the effects of these may also be limited by the Angular Velocity Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Acceleration Threshold====&lt;br /&gt;
The minimum measured acceleration your system will assume it is at rest, minus gravity. This value is also used to determine how much motion is accepted before the device begins to ignore the acceleration vector as a reliable source of “down”, and relies entirely on the gyros for pitch and roll until the device stops again. Again, you can use the noise in the graphs from your accelerometer example to get a baseline of the noise, and choose a value accordingly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If this value is too high, your device can adjust to thinking “down” is the wrong direction, or be swayed by fast motions. If this value is too low, the device may never think it is at rest to begin the process of correcting its pitch and roll.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Mag Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to re-adjust the heading 95% of the way to aligning with the compass bearing, for differences in compass bearing and AHRS heading less than 15 degrees. Outside of 15 degrees of error, this is the time it will take the AHRS heading to correct towards the compass bearing by 45 degrees, to help limit adverse effects of interference. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more (but never entirely) resistant to magnetic interference, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the magnetic field readings. If this value is low enough, white noise in your compass readings will begin to show up in your measured heading.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Accel Time====&lt;br /&gt;
The amount of time (in seconds) your system will take to realign your pitch and roll to the acceleration vector, once the device believes it is at rest. The better the gyros in your system, the higher this value can be.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;By setting this value higher your device can become more resistant to acceleration affecting orientation, at the expense of placing more weight on accurate gyroscope readings. By setting this value lower, the device’s orientation will more quickly adjust to the accelerometer readings (limited by the above Acceleration Threshold).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Bias Time====&lt;br /&gt;
If the sensor is deemed to be at rest, a “bias” parameter internal to the algorithm is slowly added to the gyroscope to compensate for any drift. Effectively, this will automatically gradually zero the gyro readings internal to the algorithm, reducing or eliminating the effects of drift. The time specified here (in seconds) is the time it takes to adjust the bias parameters to compensate for 95% of the gyro’s offsets once the device is at rest.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The speed the gyros should be biased is a balance between getting a solid average and having the zeroing occur quickly enough that biases can be fully compensated for during short periods or rest.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
[[File:AHRS_Example_Menu.jpg|400px|link=|thumb|The AHRS Example Parameter Selection]]&lt;br /&gt;
To get the best precision we recommend tuning these parameters as best fits your application. However, we have provided some sample values to make a couple demonstrations, and to give you some idea of how to adapt these parameters to certain situations.&lt;br /&gt;
&lt;br /&gt;
To more easily set up these example cases, this dropdown provides a list of settings for generic cases, and demonstrations of how you might adapt these values to certain scenarios.&lt;br /&gt;
&lt;br /&gt;
====General Purpose====&lt;br /&gt;
A set of values selected for your device that should work “well enough” out of the box for simple situations, such as moving the device around with your hand.&lt;br /&gt;
&lt;br /&gt;
====No Gyro====&lt;br /&gt;
To demonstrate why gyroscopes are an essential part of AHRS, we’ve given some settings that will effectively ignore any input from the gyroscopes, and snap to the magnetometer and accelerometer readings alone. You will notice this is incredibly noisy, especially if you start moving the sensor around.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====All Gyro====&lt;br /&gt;
For completeness, we have included a selection to set AHRS to more or less ignore input from the magnetometers and gyroscopes. By selecting this sample, you can see how the gyroscopes will drift over time and fast motions, clearly demonstrating the need for the accelerometer and magnetometer to bring the gyros back into alignment.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend using these settings in practice.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Zeroed====&lt;br /&gt;
If you are able to zero your gyroscopes, and your application is relatively free of vibrations, you should be able to use a narrower Angular Velocity Threshold. As a result, you may also be able to relax the &#039;&#039;Mag Time&#039;&#039; and &#039;&#039;Accel Time&#039;&#039; parameters, since you can better trust that the gyroscopes will only be re-biased when they are truly not rotating.&lt;br /&gt;
&lt;br /&gt;
====High Vibrations====&lt;br /&gt;
Regardless of whether or not you can zero your gyroscope, if your system suffers from constant large vibrations, the AHRS thresholds will have to be relaxed to allow the gyros to be biased at all. In doing so, we also raise the &#039;&#039;Accel Time&#039;&#039;, not because we can trust the gyroscopes more in this scenario, but rather because we must trust the accelerometer less. Assuming there is little magnetic noise, &#039;&#039;Mag Time&#039;&#039; can be decreased to snap the heading closer to the magnetic field.&lt;br /&gt;
&lt;br /&gt;
===Suggested Parameters===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: center;&amp;quot;&lt;br /&gt;
!  !! Angular Velocity Threshold !! Angular Vel Delta Threshold !! Acceleration Threshold !! Mag Time !! Accel Time !! Bias Time&lt;br /&gt;
|-&lt;br /&gt;
! MOT1102 || 2.0 || 0.6 || 0.1 || 5 || 5 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Out of the Box&#039;&#039; || 1.0 || 0.1 || 0.05 || 10 || 10 || 1.25&lt;br /&gt;
|-&lt;br /&gt;
! MOT0109&amp;lt;br&amp;gt;&#039;&#039;Heated and Zeroed&#039;&#039; || 0.5 || 0.1 || 0.05 || 120 || 120 || 1.25&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Choosing a Phidget Spatial===&lt;br /&gt;
The Spatial Phidget you use in your application will depend on how accurate certain aspects of your measurement need to be. To simplify the decision, we can narrow this down to various kinds of applicaitons:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Applicaiton !! Phidget&lt;br /&gt;
|-&lt;br /&gt;
| Navigation or Outdoor Usage || [{{SERVER}}/products.php?product_id=MOT0109 MOT0109 PhidgetSpatial Precision 3/3/3]&lt;br /&gt;
|-&lt;br /&gt;
| Gestures and Qualitative Effects || [{{SERVER}}/products.php?product_id=MOT1102 MOT1102 Spatial Phidget]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==FAQ==&lt;br /&gt;
&lt;br /&gt;
===Why does the Euler Angle for pitch never exceed 90 degrees?===&lt;br /&gt;
The Euler Angles provided by the Phidgets library are calculated directly from a corresponding quaternion. They do not take into account past movements, so the orientation of a board that passes 90 degrees in pitch can just as easily be represented by a pitch of less than 90 degrees, with different roll and heading parameters. This is one reason why Euler Angles are not recommended for use in serious calculations, in favor of using the corresponding quaternions.&lt;br /&gt;
&lt;br /&gt;
===Why do the Euler Angle readings stop working as well near 90 degrees of pitch?===&lt;br /&gt;
This is actually a good example of gimbal lock, and why it is not advised to use Euler Angles in calculation. When pitch approaches 90 degrees, the roll and yaw axes start to line up, which makes it hard to distinguish one from the other. In other words, at 90 degrees of pitch, a change in roll could just as easily be a change in heading, and vice-versa. This is another reason we recommend quaternions for all serious calculations.&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33120</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33120"/>
		<updated>2022-02-24T19:56:13Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* More Complex Graphing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
[[Image:ChartTypes.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid.&lt;br /&gt;
&lt;br /&gt;
You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search the internet for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33119</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33119"/>
		<updated>2022-02-24T19:55:04Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Fast Fourier Transform (FFT) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
[[Image:ChartTypes.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid.&lt;br /&gt;
&lt;br /&gt;
You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33118</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33118"/>
		<updated>2022-02-24T19:50:09Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Fast Fourier Transform (FFT) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
[[Image:ChartTypes.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33117</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33117"/>
		<updated>2022-02-24T19:48:39Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Other Chart Types */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
[[Image:ChartTypes.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:ChartTypes.jpg&amp;diff=33116</id>
		<title>File:ChartTypes.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:ChartTypes.jpg&amp;diff=33116"/>
		<updated>2022-02-24T19:48:02Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:ChartTypes.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:ChartTypes.jpg&amp;diff=33115</id>
		<title>File:ChartTypes.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:ChartTypes.jpg&amp;diff=33115"/>
		<updated>2022-02-24T19:46:51Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:ChartTypes.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33114</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33114"/>
		<updated>2022-02-24T19:45:37Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Other Chart Types */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
[[Image:ChartTypes.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33113</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33113"/>
		<updated>2022-02-24T19:45:21Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Other Chart Types */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
[[Image:ChartTypes.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:ChartTypes.jpg&amp;diff=33112</id>
		<title>File:ChartTypes.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:ChartTypes.jpg&amp;diff=33112"/>
		<updated>2022-02-24T19:44:34Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33111</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33111"/>
		<updated>2022-02-24T19:41:22Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Filtering */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Filtertype.jpg&amp;diff=33110</id>
		<title>File:Filtertype.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Filtertype.jpg&amp;diff=33110"/>
		<updated>2022-02-24T19:38:01Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:Filtertype.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33109</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33109"/>
		<updated>2022-02-24T19:36:21Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Raw Data Graph */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Chart Length ===&lt;br /&gt;
&lt;br /&gt;
You can adjust the amount of time displayed on your graph by adjusting the Chart Length slider. This can be helpful for setting up your graph to display data on timescales you are most interested in.&lt;br /&gt;
&lt;br /&gt;
[[Image:chartLength.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Longer Graphs ===&lt;br /&gt;
&lt;br /&gt;
If you want to monitor a sensor over a period of hours using the Phidget Control Panel Graphing tool, you can do so by slowing down the &#039;&#039;Data Interval&#039;&#039; of your device, which will increase the amount of time that you can display on the graph.&lt;br /&gt;
&lt;br /&gt;
[[Image:GraphingLongInterval.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|400px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Filtertype.jpg&amp;diff=33108</id>
		<title>File:Filtertype.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Filtertype.jpg&amp;diff=33108"/>
		<updated>2022-02-24T19:35:53Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:Filtertype.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:ChartLength.jpg&amp;diff=33107</id>
		<title>File:ChartLength.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:ChartLength.jpg&amp;diff=33107"/>
		<updated>2022-02-24T19:31:42Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:GraphingLongInterval.jpg&amp;diff=33106</id>
		<title>File:GraphingLongInterval.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:GraphingLongInterval.jpg&amp;diff=33106"/>
		<updated>2022-02-24T19:27:44Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33105</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33105"/>
		<updated>2022-02-24T18:30:04Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Fast Fourier Transform (FFT) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from; is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source; in this case, the signal wire was left disconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33104</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33104"/>
		<updated>2022-02-24T18:27:53Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
== Raw Data Graph ==&lt;br /&gt;
&lt;br /&gt;
The default graph is the Raw Data graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing sensor data in a much more concrete way than just reading numbers from the &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Filtering ===&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
==== Low-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
==== High-Pass Filter ====&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Other Chart Types ==&lt;br /&gt;
&lt;br /&gt;
You can change the Chart Type selection to apply transforms to the data that may provide further insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from- is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source- in this case, the signal wire was left unconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33103</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33103"/>
		<updated>2022-02-24T18:20:42Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Fast Fourier Transform (FFT) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The default graph is the &#039;&#039;&#039;Raw Data&#039;&#039;&#039; graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing a sensor&#039;s behaviour in a much more concrete way than just reading the numbers from the main &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Low-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== High-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Graph Type ==&lt;br /&gt;
&lt;br /&gt;
You can perform a transform on the incoming data to get different graph types that may provide insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this raw voltage data:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-raw.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s just under 1mV of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from- is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:voltage-badConnection-fft.jpg|600px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that a significant fraction of the noise is coming from a 60Hz source- in this case, the signal wire was left unconnected and picking up noise from the power grid. You can increase the graph length to sharpen the frequency spikes, just know this will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Voltage-badConnection-fft.jpg&amp;diff=33102</id>
		<title>File:Voltage-badConnection-fft.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Voltage-badConnection-fft.jpg&amp;diff=33102"/>
		<updated>2022-02-24T18:12:45Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Voltage-badConnection-raw.jpg&amp;diff=33101</id>
		<title>File:Voltage-badConnection-raw.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Voltage-badConnection-raw.jpg&amp;diff=33101"/>
		<updated>2022-02-24T18:12:23Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Lowpass.jpg&amp;diff=33100</id>
		<title>File:Lowpass.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Lowpass.jpg&amp;diff=33100"/>
		<updated>2022-02-24T17:30:32Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:Lowpass.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33099</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33099"/>
		<updated>2022-02-24T17:27:38Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* High-Pass Filter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The default graph is the &#039;&#039;&#039;Raw Data&#039;&#039;&#039; graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing a sensor&#039;s behaviour in a much more concrete way than just reading the numbers from the main &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Low-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== High-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals. As a rule of thumb, be sure the time on the filter is longer than the period of the signal you are interested in, or you will see distortions.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Graph Type ==&lt;br /&gt;
&lt;br /&gt;
You can perform a transform on the incoming data to get different graph types that may provide insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this accelerometer raw data:&lt;br /&gt;
&lt;br /&gt;
[[Image:accel-raw.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s around ±0.002g of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from- is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:accel-fft.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that the noise is mostly coming from something vibrating at 9Hz- in this case, a nearby motor was running. You can increase the graph length to sharpen the frequency spikes, just know it will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33098</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33098"/>
		<updated>2022-02-24T00:42:11Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* High-Pass Filter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The default graph is the &#039;&#039;&#039;Raw Data&#039;&#039;&#039; graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing a sensor&#039;s behaviour in a much more concrete way than just reading the numbers from the main &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Low-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== High-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency components of your signal. This can be used on very short timescales to characterize the high-frequency noise in the system, or it can be used over longer timescales to remove offsets to more easily gauge the scale of periodic signals.&lt;br /&gt;
&lt;br /&gt;
Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to remove low-frequencies and offsets from your data.&lt;br /&gt;
&lt;br /&gt;
[[Image:highpass.jpg|850px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Graph Type ==&lt;br /&gt;
&lt;br /&gt;
You can perform a transform on the incoming data to get different graph types that may provide insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this accelerometer raw data:&lt;br /&gt;
&lt;br /&gt;
[[Image:accel-raw.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s around ±0.002g of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from- is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:accel-fft.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that the noise is mostly coming from something vibrating at 9Hz- in this case, a nearby motor was running. You can increase the graph length to sharpen the frequency spikes, just know it will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Highpass.jpg&amp;diff=33097</id>
		<title>File:Highpass.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Highpass.jpg&amp;diff=33097"/>
		<updated>2022-02-24T00:41:30Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33096</id>
		<title>Control Panel Graphing</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=Control_Panel_Graphing&amp;diff=33096"/>
		<updated>2022-02-24T00:15:18Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: /* Low-Pass Filter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
In the [[Phidget Control Panel]], open the channel for your device and click on the [[Image:plot.jpg|link=]] icon next to the data type that you want to plot. This will open up a new window:&lt;br /&gt;
&lt;br /&gt;
[[Image:plot2.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The default graph is the &#039;&#039;&#039;Raw Data&#039;&#039;&#039; graph. This graph displays the readings from your sensor over time. This can be very helpful in visualizing a sensor&#039;s behaviour in a much more concrete way than just reading the numbers from the main &#039;&#039;&#039;Control Panel Example&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
You can perform filtering on the raw data in order to reduce noise in your graph. &lt;br /&gt;
&lt;br /&gt;
[[Image:filtertype.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
=== Low-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
This filter reduces and removes high frequency components of the graphed data. It&#039;s generally used to smooth out your graph, since high-frequency noise can make a graph harder to read. Select &amp;quot;Low Pass Filter&amp;quot; from the drop down menu and move the slider to select the averaging window. The larger the averaging window, the smoother the line will be.&lt;br /&gt;
&lt;br /&gt;
Note that if your filter is comparable to or longer than the period of the signal you are trying to measure, you will start to filter out the data you want along with the noise.&lt;br /&gt;
&lt;br /&gt;
[[Image:lowpass.jpg|820px|center|link=]]&lt;br /&gt;
&lt;br /&gt;
=== High-Pass Filter ===&lt;br /&gt;
&lt;br /&gt;
Unlike the low-pass filter, this filter is used specifically to look at the high-frequency noise in your signal. Select &amp;quot;High Pass Filter&amp;quot; from the drop down menu to see the noise.&lt;br /&gt;
&lt;br /&gt;
== Graph Type ==&lt;br /&gt;
&lt;br /&gt;
You can perform a transform on the incoming data to get different graph types that may provide insights into your sensor data.&lt;br /&gt;
&lt;br /&gt;
=== Fast Fourier Transform (FFT) ===&lt;br /&gt;
&lt;br /&gt;
The FFT graph type will transform your data into a frequency plot, which can sometimes reveal hidden information about your data. For example, if you look at this accelerometer raw data:&lt;br /&gt;
&lt;br /&gt;
[[Image:accel-raw.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s clear that there&#039;s around ±0.002g of noise in the signal, but just from looking at the raw data it may be unclear where the noise is coming from- is it the sensor itself, or something external? Switching to the FFT plot gives us a clue:&lt;br /&gt;
&lt;br /&gt;
[[Image:accel-fft.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
The FFT plot reveals that the noise is mostly coming from something vibrating at 9Hz- in this case, a nearby motor was running. You can increase the graph length to sharpen the frequency spikes, just know it will take the graph longer to react to changes in the incoming data. &lt;br /&gt;
&lt;br /&gt;
In general, the FFT plot is most useful for analyzing sensor data where frequency has useful real-world implications, such as measuring vibrations of an accelerometer, or checking for 50/60Hz interference form the power grid.&lt;br /&gt;
&lt;br /&gt;
=== Allan Deviation ===&lt;br /&gt;
&lt;br /&gt;
[[Image:gyro-allan.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
Allan Deviation is a very specialized type of graph used to compare noise characteristics between sensors. Interpreting the Allan Deviation plot is outside the scope of this guide, but in general your sensor should be stabilized (e.g. if it&#039;s a spatial, it should be stationary. If it&#039;s a temperature sensor, the ambient temperature should be kept at a static level).&lt;br /&gt;
&lt;br /&gt;
==More Complex Graphing==&lt;br /&gt;
If you need more complex functionality such as logging multiple sensors to the same sheet or performing calculations on the data, you&#039;ll need to write your own program. This graphing tool is intended as a jumping-off point to better understand your sensors individually, so you can get a feel for how to use them in your applications.&lt;br /&gt;
&lt;br /&gt;
The quickest way to get started is to download some [{{SERVER}}/?view=code_samples sample code] for your desired programming language and then search Google for information on logging or plotting data in that language (e.g. &amp;quot;how to log to csv in python&amp;quot;).&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
	<entry>
		<id>https://www.phidgets.com/docs/index.php?title=File:Lowpass.jpg&amp;diff=33095</id>
		<title>File:Lowpass.jpg</title>
		<link rel="alternate" type="text/html" href="https://www.phidgets.com/docs/index.php?title=File:Lowpass.jpg&amp;diff=33095"/>
		<updated>2022-02-24T00:14:14Z</updated>

		<summary type="html">&lt;p&gt;Jdecoux: Jdecoux uploaded a new version of File:Lowpass.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jdecoux</name></author>
	</entry>
</feed>