/** \brief Inertial sensor data visualizer demo application entry * * This application uses a serial connection to transmit sensor data. The * data is formatted for use by the Atmel Data Visualizer application * running on a remote host. * * Upon entry, the hardware (including processor and sensor board) are * initialized, and the sensor interfaces are established. The application * then transmits a series of special data stream configuration packets, * which tell the remote application the number, type, and labels for * data streams that will subsequently be used. * * After this initialization, the application enters a continuous loop * in which it periodically samples the sensors that are defined and * sends the obtained data values to the remote host in stream data packets. * Each type of sensor measurement uses an interval counter to determine * how often the measurement should be performed and transmitted. */ int main(void) { int led_index = 0; int loop_count = 0; sensor_t accel_dev; /* Accelerometer device */ sensor_t compass_dev; /* Compass/magnetometer device */ sensor_t gyro_dev; /* Gyroscope device */ sensor_data_t accel_data; /* Accelerometer data */ sensor_data_t compass_data; /* Compass data */ sensor_data_t gyro_data; /* Gyroscope data */ sensor_data_t temp_data; /* Temperature data */ /* Initialize the board (Xplained UC3 or XMEGA & Xplained Sensor boards) * I/O pin mappings and any other configurable resources selected in * the build configuration. */ sensor_platform_init(); LED_On(ALL_LEDS); /* Attach descriptors to the defined sensor devices. */ sensor_attach(&accel_dev, SENSOR_TYPE_ACCELEROMETER, 0, 0); sensor_attach(&gyro_dev, SENSOR_TYPE_GYROSCOPE, 0, 0); sensor_attach(&compass_dev, SENSOR_TYPE_COMPASS, 0, 0); if (accel_dev.err || gyro_dev.err || compass_dev.err) { while (true) { /* Error occurred, loop forever */ } } /* Set sensor data output formats */ accel_data.scaled = true; gyro_data.scaled = true; compass_data.scaled = true; temp_data.scaled = true; /* Wait for user to push button before continuing */ LED_Off(ALL_LEDS); do { /* Just blink LED until button is pushed */ LED_Toggle(PROMPT_LED); delay_ms(500); } while (!SWITCH_PRESSED); LED_Off(PROMPT_LED); /* Enable output streams for Atmel Data Visualizer (ADV) */ visual_stream_init(); while (true) { /* Change LED display */ LED_Toggle(led_array [led_index++]); if (led_index >= NUM_BLINK_LEDS) { led_index = 0; } /* Accelerometer data */ if ((loop_count % ACCEL_INTERVAL) == 0) { sensor_get_acceleration(&accel_dev, &accel_data); adv_data_send_3(ACCEL_STREAM_NUM, accel_data.timestamp, accel_data.axis.x, accel_data.axis.y, accel_data.axis.z); } /* Gyroscope data */ if ((loop_count % GYRO_INTERVAL) == 0) { sensor_get_rotation(&gyro_dev, &gyro_data); adv_data_send_3(GYRO_STREAM_NUM, gyro_data.timestamp, gyro_data.axis.x, gyro_data.axis.y, gyro_data.axis.z); } /* Compass/magnetometer data */ if ((loop_count % COMPASS_INTERVAL) == 0) { sensor_get_heading(&compass_dev, &compass_data); adv_data_send_3(COMPASS_STREAM_NUM, compass_data.timestamp, compass_data.heading.direction, compass_data.heading.inclination, compass_data.heading.strength); } /* Temperature data */ if ((loop_count % TEMP_INTERVAL) == 0) { sensor_get_temperature(&gyro_dev, &temp_data); adv_data_send_1(TEMP_STREAM_NUM, temp_data.timestamp, temp_data.temperature.value); } /* Re-send stream initialization if switch pressed */ if (SWITCH_PRESSED) { LED_Off(ALL_LEDS); LED_On(PROMPT_LED); /* Re-send init info */ visual_stream_init(); while (SWITCH_PRESSED) { /* wait until button is released */ } LED_Off(PROMPT_LED); led_index = 0; } loop_count++; } return 0; }
/** Unit test to check that the gyroscope works correctly on the Inertial * One board using the Sensor Platform library. * * \param test Pointer to the unit test case instance */ static void run_sensor_gyro_test(const struct test_case *test) { sensor_t gyro; sensor_data_t gyro_data = { .scaled = true }; configure_sensor_platform(); sensor_attach(&gyro, SENSOR_TYPE_GYROSCOPE, 0, 0); test_assert_false(test, gyro.err, "Error attaching to gyroscope"); delay_ms(50); for (uint8_t i = 0; i < 10; i++) { test_assert_true(test, sensor_get_rotation(&gyro, &gyro_data), "Gyroscope read failed"); test_assert_false(test, gyro.err, "Gyroscope internal error"); delay_ms(2); } } /** Unit test to check that the accelerometer works correctly on the Inertial * One board using the Sensor Platform library. * * \param test Pointer to the unit test case instance */ static void run_sensor_accel_test(const struct test_case *test) { sensor_t accel; sensor_data_t accel_data = { .scaled = true }; configure_sensor_platform(); sensor_attach(&accel, SENSOR_TYPE_ACCELEROMETER, 0, 0); test_assert_false(test, accel.err, "Error attaching to accelerometer"); delay_ms(50); for (uint8_t i = 0; i < 10; i++) { vector3_t accel_data_vect; test_assert_true(test, sensor_get_acceleration(&accel, &accel_data), "Accelerometer read failed"); test_assert_false(test, accel.err, "Accelerometer internal error"); accel_data_vect.x = accel_data.axis.x; accel_data_vect.y = accel_data.axis.y; accel_data_vect.z = accel_data.axis.z; scalar_t accel_mag = vector3_magnitude(&accel_data_vect); test_assert_true(test, (accel_mag > (1000 - 300)) && (accel_mag < (1000 + 300)), "Accelerometer returned value not close to 1000 milli-g: %i", (uint16_t)accel_mag); delay_ms(2); } } /** Unit test to check that the compass works correctly on the Inertial * One board using the Sensor Platform library. * * \param test Pointer to the unit test case instance */ static void run_sensor_compass_test(const struct test_case *test) { sensor_t compass; sensor_data_t compass_data = { .scaled = true }; configure_sensor_platform(); sensor_attach(&compass, SENSOR_TYPE_COMPASS, 0, 0); test_assert_false(test, compass.err, "Error attaching to magnetometer"); delay_ms(50); for (uint8_t i = 0; i < 10; i++) { vector3_t compass_data_vect; test_assert_true(test, sensor_get_heading(&compass, &compass_data), "Compass read failed"); test_assert_false(test, compass.err, "Compass internal error"); compass_data_vect.x = compass_data.heading.direction; compass_data_vect.y = compass_data.heading.inclination; compass_data_vect.z = compass_data.heading.strength; scalar_t compass_mag = vector3_magnitude(&compass_data_vect); test_assert_false(test, (compass_mag == 0), "Compass returned zero data"); delay_ms(2); } } /** Unit test to check that the gyroscope internal temperature sensor works * correctly on the Inertial One board using the Sensor Platform library. * * \param test Pointer to the unit test case instance */ static void run_sensor_temp_test(const struct test_case *test) { sensor_t gyro; sensor_data_t temp_data = { .scaled = true }; configure_sensor_platform(); sensor_attach(&gyro, SENSOR_TYPE_GYROSCOPE, 0, 0); test_assert_false(test, gyro.err, "Error attaching to gyroscope"); delay_ms(50); for (uint8_t i = 0; i < 10; i++) { test_assert_true(test, sensor_get_temperature(&gyro, &temp_data), "Gyroscope temperature read failed"); test_assert_false(test, gyro.err, "Gyroscope internal error"); test_assert_false(test, ((int16_t)temp_data.temperature.value == 0), "Gyroscope returned zero temperature data"); test_assert_false(test, ((int16_t)temp_data.temperature.value > 40), "Gyroscope returned too high temperature data: %d", (int16_t)temp_data.temperature.value); delay_ms(2); } } int main(void) { // Initialize the board and all the peripheral required sysclk_init(); board_init(); stdio_serial_init(CONF_TEST_USART, &usart_serial_options); #if XMEGA pmic_init(); sleepmgr_init(); #endif DEFINE_TEST_CASE(sensor_init_test, NULL, run_sensor_init_test, NULL, "Test sensor initialization"); DEFINE_TEST_CASE(sensor_gyro_test, NULL, run_sensor_gyro_test, NULL, "Test gyroscope read"); DEFINE_TEST_CASE(sensor_accel_test, NULL, run_sensor_accel_test, NULL, "Test accelerometer read"); DEFINE_TEST_CASE(sensor_compass_test, NULL, run_sensor_compass_test, NULL, "Test compass read"); DEFINE_TEST_CASE(sensor_temp_test, NULL, run_sensor_temp_test, NULL, "Test temperature read"); DEFINE_TEST_ARRAY(sensor_tests) = { &sensor_init_test, &sensor_gyro_test, &sensor_accel_test, &sensor_compass_test, &sensor_temp_test }; DEFINE_TEST_SUITE(sensor_suite, sensor_tests, "Common sensor plarform test suite"); test_suite_run(&sensor_suite); while (1) { /* Intentionally left blank */ } }
/** \brief Inertial sensor demo application entry * * After initializing the Xplained platform and sensor boards, this application * attaches descriptors to the accelerometer, gyroscope, and compass devices on * an Xplained inertial sensor board. The sensor data, which is formatted and * printed via printf() after being read, can be viewed with a serial terminal * application on a machine attached to the USB interface on the Xplained * board. */ int main(void) { sensor_t accel; /* Accelerometer device descriptor */ sensor_t compass; /* Magnetic compass device descriptor */ sensor_t gyro; /* Gyroscope device descriptor */ /* Initialize the board (Xplained UC3 or XMEGA & Xplained Sensor boards) * I/O pin mappings and any other configurable resources selected in * the build configuration. */ sensor_platform_init(); /* Attach descriptors to the defined sensor devices */ sensor_attach(&gyro, SENSOR_TYPE_GYROSCOPE, 0, 0); sensor_attach(&accel, SENSOR_TYPE_ACCELEROMETER, 0, 0); sensor_attach(&compass, SENSOR_TYPE_COMPASS, 0, 0); if (gyro.err || accel.err || compass.err) { puts("\rSensor initialization error."); while (true) { /* Error occurred, loop forever */ } } /* Print sensor information */ if (PRINT_BANNER) { static const char *const banner_format = "%s\r\nID = 0x%02x ver. 0x%02x\r\n" "Bandwidth = %d Hz Range = +/- %d\r\n\n"; uint32_t id; uint8_t version; int16_t freq, range; sensor_device_id(&gyro, &id, &version); sensor_get_bandwidth(&gyro, &freq); sensor_get_range(&gyro, &range); printf(banner_format, gyro.drv->caps.name, (unsigned)id, (unsigned)version, freq, range); sensor_device_id(&accel, &id, &version); sensor_get_bandwidth(&accel, &freq); sensor_get_range(&accel, &range); printf(banner_format, accel.drv->caps.name, (unsigned)id, (unsigned)version, freq, range); sensor_device_id(&compass, &id, &version); sensor_get_bandwidth(&compass, &freq); sensor_get_range(&compass, &range); printf(banner_format, compass.drv->caps.name, (unsigned)id, (unsigned)version, freq, range); delay_ms(500); } /* Initialize sensor data descriptors for scaled vs. raw data. */ static sensor_data_t accel_data = {.scaled = SCALED_DATA}; static sensor_data_t compass_data = {.scaled = SCALED_DATA}; static sensor_data_t gyro_data = {.scaled = SCALED_DATA}; static sensor_data_t temp_data = {.scaled = SCALED_DATA}; while (true) { LED_Toggle(ACTIVITY_LED); /* Read sensor values */ sensor_get_acceleration(&accel, &accel_data); sensor_get_rotation(&gyro, &gyro_data); sensor_get_temperature(&gyro, &temp_data); /* Get temp from gyro */ if (SCALED_DATA) { /* Get calculated magnetic heading from compass */ sensor_get_heading(&compass, &compass_data); } else { /* Get raw magnetic field readings (X,Y,Z) */ sensor_get_field(&compass, &compass_data); } /* Print sensor values */ if (SCALED_DATA) { printf("acc = [%5d, %5d, %5d]\r\n", (int16_t)accel_data.axis.x, (int16_t)accel_data.axis.y, (int16_t)accel_data.axis.z); printf("rot = [%5d, %5d, %5d]\r\n", (int16_t)gyro_data.axis.x, (int16_t)gyro_data.axis.y, (int16_t)gyro_data.axis.z); printf("heading %5d, inclination %5d, strength %5d\r\n", (uint16_t)compass_data.heading.direction, (int16_t)compass_data.heading.inclination, (uint16_t)compass_data.heading.strength); printf("T = %d C\r\n\n", (int16_t)temp_data.temperature.value); } else { printf("acc = [%.5x, %.5x, %.5x]\r\n", (uint16_t)accel_data.axis.x, (uint16_t)accel_data.axis.y, (uint16_t)accel_data.axis.z); printf("rot = [%.5x, %.5x, %.5x]\r\n", (uint16_t)gyro_data.axis.x, (uint16_t)gyro_data.axis.y, (uint16_t)gyro_data.axis.z); printf("field = [%.5x, %.5x, %.5x]\r\n", (int16_t)compass_data.axis.x, (int16_t)compass_data.axis.y, (int16_t)compass_data.axis.z); printf("T = %.5x\r\n\n", (uint16_t)temp_data.temperature.value); } delay_ms(500); } return 0; }