Quantcast
Channel: Intel Developer Zone Articles
Viewing all articles
Browse latest Browse all 3384

Intel® Quark™ Microcontroller D2000 - Accelerometer Tutorial

$
0
0

Intel® System Studio for Microcontrollers includes multiple samples to help you get up to speed with its basic functionality and become familiar with the set of Intel® Quark™ Microcontroller Software Interface (QMSI) APIs that work with your board. This example reads and outputs accelerometer data to the serial port, and can optionally use the Intel® Integrated Performance Primitives (Intel IPP) to compute root mean square, variance, and mean for the last 15 Z axis readings.

Requirements

Instructions

1. Connect the FTDI cable for serial output by connecting the cables in the following configuration:

  • Connect GND (black) to the serial to the board's GND pin.
  • Connect TXD (orange) to the serial cable to the board's RX pin.
  • Connect RXD (yellow) to the serial cable to the board's TX pin.

2. If you haven’t already, launch the Intel ® System Studio for Microcontrollers software.

3. Create a project with the "Accelerometer" sample project file, as follows:

a. From the File menu, select New, and then select Intel QMSI/BSP Project. The Create new Intel QMSI/BSP Project dialog box appears.

b. Specify the following values in the Intel QMSI/BSP Project dialog box:

    •  Project Name: Accelerometer

    • Template: hello_world

    •  Intel Quark target: D2000

    •  Create launch configuration: selected (checked)

    •  Connection: USB Onboard

c. Click Finish.

4. Set up your terminal to view sensor output as follows:

a. From the toolbar, click the Terminal button and choose Serial Terminal.

b. Configure the serial connection (defaults):

  • Port: The active port should be displayed.

    Tip: The port will vary depending on the serial hardware used, and there may be more than one listed.

    Linux*: Use the ‘dmesg’ command to view your port status.

    Windows*: Open Device Manager to view the Ports (COM & LPT) status.

  • Baud Rate: 115200
  • Data Bits: 8
  • Parity: None
  • Stop Bits: 1

5. Build and deploy your project.

a. Select the "Accelerometer" project in the Project Explorer.

b. Click the Build button to compile your project.

c. From the Run drop-down list, select "Accelerometer (flashing)".

Note: you can also deploy and debug. From the Debug drop-down list, select "Accelerometer (flashing)".

d. View X, Y, and Z values from the accelerometer in the terminal.

How It Works

The accelerometer sample uses the onboard Bosch BMC150 or Bosch BMI160 accelerometers connected to the microcontroller using the I2C interface, and the RTC (real time clock) integrated in Intel® Quark™ microcontroller. It also uses the integrated UART module for the data output over serial port.

The sample begins with setting up RTC parameters in an rtc configuration structure:

<code>
      rtc.init_val = 0;
      rtc.alarm_en = true;
      rtc.alarm_val = INTERVAL;
      rtc.callback = print_accel_callback;
      rtc.callback_data = NULL;</code>

This configuration enables the RTC alarm, and sets print_accel_callback as the callback function for the RTC alarm. It is used to periodically print accelerometer data.

Next, the code requests an interrupt for the RTC by using a QMSI API call, and also enables the RTC clock:

<code>
      qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);
      /* Enable the RTC. */
      clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);</code>

After that, it configures the accelerometer parameters depending on the accelerometer type (BMC150 or BMI160):

<code>
#if (QUARK_D2000)
      cfg.pos = BMC150_J14_POS_0;
#endif /* QUARK_D2000 */

       /* Initialise the sensor config and set the mode. */
      bmx1xx_init(cfg);
      bmx1xx_accel_set_mode(BMX1XX_MODE_2G);

#if (BMC150_SENSOR)
       bmx1xx_set_bandwidth(BMC150_BANDWIDTH_64MS); /* Set the bandwidth. */
#elif(BMI160_SENSOR)
       bmx1xx_set_bandwidth(BMI160_BANDWIDTH_10MS); /* Set the bandwidth. */
#endif /* BMC150_SENSOR */
</code>

The cfs.pos parameter is used to configure the accelerometer address for the BMC150 accelerometer. The Intel® Quark™ Microcontroller D2000 Developer Kit board has a jumper that allows changing the address. The BMC150_J14_POS_0 is the default (no jumper, I2C address 0x10) configuration.

Next, the main() function sets up the RTC configuration, thus enabling the RTC alarm:

<code>
       /* Start the RTC. */
      qm_rtc_set_config(QM_RTC_0, &rtc);</code>

A while loop is used to wait for the defined number of samples from the accelerometer to be read and printed to the serial console output:

<code>
       /* Wait for the correct number of samples to be read. */
       while (!complete)
       ;</code>

Each time the 125-millisecond interval is reached and the RTC alarm is triggered, the following accel_callback function is invoked. The accel data structure defined at the start of the function is passed into the bmx1xx_read_accel function, which populates it with the current accelerometer data read. If this read is successful, the accelerometer data is printed to the serial console output; otherwise, an error message is printed.

<code>
/* Accel callback will run every time the RTC alarm triggers. */
static void accel_callback(void *data)
{
       bmx1xx_accel_t accel = {0};

       if (0 == bmx1xx_read_accel(&accel)) {
              QM_PRINTF("x %d y %d z %d\n", accel.x, accel.y, accel.z);
       } else {
              QM_PUTS("Error: unable to read from sensor");
       }</code>

Next, if IPP is enabled, it prints the statistics for the Z axis by calling the print_axis_stats function. (See the print_axis_stats function description, below.)

<code>
#if (__IPP_ENABLED__)
       print_axis_stats(accel.z);
#endif /* __IPP_ENABLE__ */</code>

The callback function checks whether the defined number of samples have been read; if not, the RTC alarm is reset and the count is incremented, otherwise the complete variable is set to true.

<code>
       /* Reset the RTC alarm to fire again if necessary. */
       if (cb_count < NUM_SAMPLES) {
              qm_rtc_set_alarm(QM_RTC_0,
                            (QM_RTC[QM_RTC_0].rtc_ccvr + INTERVAL));
              cb_count++;
       } else {
              complete = true;
       }</code>

Note that the application by default reads 500 samples (NUM_SAMPLES) before exiting.

Finally, when the complete variable is set to true, the while loop exits and the applications prints a final statement to the serial console output, and exits.

<code>
       QM_PUTS("Finished: Accelerometer example app");

       return 0;
}
</code>

The print_axis_stats function uses the Intel IPP (Intel® Integrated Performance Primitives) library to print the statistics of the last 15 (set by NUM_SAMPLES) Z axis readings.

First, it updates the samples array with the new Z axis sample, and if needed, updates the samples count:

<code>
static void print_axis_stats(int16_t value)
{
       static uint32_t index = 0;
       static uint32_t count = 0;
       float32_t mean, var, rms;

       /* Overwrite the oldest sample in the array. */
       samples[index] = value;
       /* Move the index on the next position, wrap around if necessary. */
       index = (index + 1) % SAMPLES_SIZE;

       /* Store number of samples until it reaches SAMPLES_SIZE. */
       count = count == SAMPLES_SIZE ? SAMPLES_SIZE : count + 1;
</code>

Next, it calculates and prints root mean square, variance, and mean values for the collected samples:

<code>
/* Get the root mean square (RMS), variance and mean. */
       ippsq_rms_f32(samples, count, &rms);
       ippsq_var_f32(samples, count, &var);
       ippsq_mean_f32(samples, count, &mean);

       QM_PRINTF("rms %d var %d mean %d\n", (int)rms, (int)var, (int)mean);
}</code>

Code

/*
* Copyright (c) 2016, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*     this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*     this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
* 3. Neither the name of the Intel Corporation nor the names of its
*     contributors may be used to endorse or promote products derived from this
*     software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/*
* QMSI Accelerometer app example.
*
* This app will read the accelerometer data from the onboard BMC150/160 sensor
* and print it to the console every 125 milliseconds. The app will complete
* once it has read 500 samples.
*
* If the app is compiled with the Intel(R) Integrated Performance Primitives
* (IPP) library enabled, it will also print the Root Mean Square (RMS),
* variance and mean of the last 15 samples each time.
*/

#include
#if (__IPP_ENABLED__)
#include
#endif
#include "clk.h"
#include "qm_interrupt.h"
#include "qm_isr.h"
#include "qm_rtc.h"
#include "qm_uart.h"
#include "bmx1xx/bmx1xx.h"

#define INTERVAL (QM_RTC_ALARM_SECOND >> 3) /* 125 milliseconds. */
#define NUM_SAMPLES (500)
#if (__IPP_ENABLED__)
/* Number of samples to use to generate the statistics from. */
#define SAMPLES_SIZE (15)
#endif /* __IPP_ENABLED__ */

static volatile uint32_t cb_count = 0;
static volatile bool complete = false;

#if (__IPP_ENABLED__)
static float32_t samples[SAMPLES_SIZE];

static void print_axis_stats(int16_t value)
{
       static uint32_t index = 0;
       static uint32_t count = 0;
       float32_t mean, var, rms;

       /* Overwrite the oldest sample in the array. */
       samples[index] = value;
       /* Move the index on the next position, wrap around if necessary. */
       index = (index + 1) % SAMPLES_SIZE;

       /* Store number of samples until it reaches SAMPLES_SIZE. */
       count = count == SAMPLES_SIZE ? SAMPLES_SIZE : count + 1;

       /* Get the root mean square (RMS), variance and mean. */
       ippsq_rms_f32(samples, count, &rms);
       ippsq_var_f32(samples, count, &var);
       ippsq_mean_f32(samples, count, &mean);

       QM_PRINTF("rms %d var %d mean %d\n", (int)rms, (int)var, (int)mean);
}
#endif /* __IPP_ENABLE__ */

/* Accel callback will run every time the RTC alarm triggers. */
static void accel_callback(void *data)
{
       bmx1xx_accel_t accel = {0};

       if (0 == bmx1xx_read_accel(&accel)) {
              QM_PRINTF("x %d y %d z %d\n", accel.x, accel.y, accel.z);
       } else {
              QM_PUTS("Error: unable to read from sensor");
       }

#if (__IPP_ENABLED__)
       print_axis_stats(accel.z);
#endif /* __IPP_ENABLE__ */

       /* Reset the RTC alarm to fire again if necessary. */
       if (cb_count < NUM_SAMPLES) {
              qm_rtc_set_alarm(QM_RTC_0,
                            (QM_RTC[QM_RTC_0].rtc_ccvr + INTERVAL));
              cb_count++;
       } else {
              complete = true;
       }
}

int main(void)
{
       qm_rtc_config_t rtc;
       bmx1xx_setup_config_t cfg;

       QM_PUTS("Starting: Accelerometer example app");

       /* Configure the RTC and request the IRQ. */
       rtc.init_val = 0;
       rtc.alarm_en = true;
       rtc.alarm_val = INTERVAL;
       rtc.callback = accel_callback;
       rtc.callback_data = NULL;

       qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);

       /* Enable the RTC. */
       clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);

#if (QUARK_D2000)
       cfg.pos = BMC150_J14_POS_0;
#endif /* QUARK_D2000 */

       /* Initialise the sensor config and set the mode. */
       bmx1xx_init(cfg);
       bmx1xx_accel_set_mode(BMX1XX_MODE_2G);

#if (BMC150_SENSOR)
       bmx1xx_set_bandwidth(BMC150_BANDWIDTH_64MS); /* Set the bandwidth. */
#elif(BMI160_SENSOR)
       bmx1xx_set_bandwidth(BMI160_BANDWIDTH_10MS); /* Set the bandwidth. */
#endif /* BMC150_SENSOR */

       /* Start the RTC. */
       qm_rtc_set_config(QM_RTC_0, &rtc);

       /* Wait for the correct number of samples to be read. */
       while (!complete)
              ;

       QM_PUTS("Finished: Accelerometer example app");

       return 0;
}

 


Viewing all articles
Browse latest Browse all 3384

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>