Getting Started: Freescale Xtrinisic Sense Board on RPi & KL-25Z

Whenever I think of playing with microcontrollers, I think of blending the line between hardware and software. Low cost embedded systems prototyping development platforms have made tinkering very affordable, and with the wide variety of libraries, even easy. If you have some time, it doesn’t take much to get into it with many resources freely available online.

A lot of the time, the projects are about solving problems or producing interactive solutions, and it’s always my belief that there’s nothing such as too many sensors. With more sensors, your microcontroller has a better sense of its environment, and that enables many opportunities you might not have thought about.

Since the Arduino reached mainstream popularity, a large variety of sensors have been developed as pluggable modules with prices ranging from very inexpensive to moderately expensive. Of course, there are wide variances between sensors and their performance, which is why it’s important to test them out in the intended application.

To that end, element14 has exclusively introduced the Freescale Xtrinsic-Sense board, a MEMS sensor evaluation board. It features three sensors – the MAG3110 High Accuracy 3D Magnetometer, the MMA8491Q +/-8g Digital Accelerometer and the MPL3115A2 50 to 110kPa Absolute Digital Pressure Sensor with Temperature. It is designed for 3.3v I2C-based operation, with digital outputs for interrupt and triggers and is designed to mate with both the Freescale Freedom series of boards, as well as the Raspberry Pi.

It can be had for under AU$12 when on promotion, so I thought I might as well grab one because it’ll give me an excuse to play with my Freescale Freedom FRDM-KL25Z I’ve had for a while.

The Board

The board is provided inside a glossy colour cardboard box. Unfortunately, I threw that out, so no photo of it. Inside, the Xtrinsic-Sense board is provided inside an ESD shielding bag.

DSC_6358

The PCB is nicely silk-screened with black solder resist coating and looks pretty well made. The sensors are all MEMS surface mount type, so it can be quite difficult to use them without the aid of such “breakout” boards. It does, however, mean that they are very low-power, compact and suitable for integration in many different products, such as mobile phones. The three sensors are clearly labelled on the board.

The three sensors are:

  • MAG3110 High Accuracy 3D Magnetometer – up to 80Hz sample rate, up to 10 Gauss
  • MMA8491Q +/-8g Digital Accelerometer – with tilt trigger function, resolution to 1mg/LSB
  • MPL3115A2 50 to 110kPa Absolute Digital Pressure Sensor with Temperature – integrated altitude function with <0.3m resolution, 20-bit pressure, 20-bit altitude, 12-bit temperature, up to 128Hz sample rate

There are two rows of pins which are used to connect the board to the Freedom series of boards, which have an Arduino-like pin arrangement. It might be possible to use this board on a 3.3v Arduino, although I haven’t got one and I haven’t tried. Unfortunately, since the Freedom boards typically include additional rows of expansion, adding this board will cause you to lose access of many of the I/O pins which is a negative.

There is also a double-row of sockets for use with the Raspberry Pi’s I/O header. There is one row of three pins which have the Raspberry Pi’s UART broken out, which comes in handy if you’re using the Model A and are using a serial console. Likewise, because there are no “pass through” sockets, you lose the header by adding the board on. The board itself is slightly wider than the Raspberry Pi, and adds height, so it’s not possible to use it with a case.

There is a hole with a nylon standoff and plastic screw – this standoff allows the board to be supported on the Raspberry Pi and prevents short circuits. In case of using it with the Freedom board, it should be removed.

DSC_6359

The underside doesn’t really have anything too interesting to note.

DSC_6365

The board is also provided with a single-sheet double-sided colour quick-start leaflet. One side gives some details for using it with the Freedom boards including the pin-out, however, the expectation is that there is a demo app pre-loaded on your board (which wasn’t on mine, since I’ve reprogrammed it many times).

The other side is analogous for the Raspberry Pi, however, it has a link to http://www.element14.com/rpimems_sense which is broken. Likewise, the bottom of the Quick Start Guide also has a link to http://www.element14.com/mems_sense which is also broken.

A full manual is available from element14, and a design area gives a few more details about it, however, it’s a bit disconcerting that the printed links just don’t work.

Getting Started with it on the Raspberry Pi

Getting started with the board on the Raspberry Pi necessitates first getting started with a Raspberry Pi. I won’t go through it all, however, my last webinar did go through most of it.

To reiterate, you will need an SDHC 4Gb or larger card of some sort, some way of viewing and controlling the Pi (USB Keyboard and Mouse + HDMI screen, or SSH), network connectivity (Ethernet, or for more advanced users, Wireless) and a suitable power supply to power the whole thing (1A+ USB power supply, good quality USB microB lead).

You will need to write the latest image of Raspbian to your SD card to get it ready for initial configuration as well. If you already have a Raspberry Pi setup to play with, you can skip further ahead to the part where we use git to clone the required code.

Interestingly, I got a bit tired of the “tongue” of the SD card sticking out on my Raspberry Pi, so I opted to go for a microSD adapter and use an old microSD card instead.

DSC_6360                          DSC_6361

Many different styles are available, it’s relatively inexpensive and it’s fairly easy to fit. It’s nice and neat, flush to the edge of the board.

DSC_6362

Of course, you will need to plug the board in! Nothing difficult, just line up the connectors and push down.

DSC_6364

It should look something like this.

DSC_6363

Do watch to ensure the nylon standoff is where it should be, as it keeps the pins “free” and avoids potential short-circuits. Now you’re ready to power-up, and follow the prompts to do the initial raspi-config setup.

Advanced-Settings

I suggest you expand filesystem, change your password, potentially overclock if you need to, ensure SSH is enabled, set the correct keyboard layout (US for Australia), and the correct time-zone and locale.

Once that’s done, you can do a sudo apt-get update and sudo apt-get upgrade to make sure the Raspberry Pi is running with the latest packages.

Now, you will need to grab the code required to interface with the board. All of the code is supplied as Python scripts. You can do this by running:

git clone http://git.oschina.net/embest/rpi_sensor_board

To execute the Python code, you will need to run it as superuser – pre-fix it with sudo. Some of the code has dependencies on other packages, like nginx, which you’ll have to read the full manual to find out. Interestingly, I found a bug with the original code for the temperature sensor. As I wanted to log data with time for barometric pressure in hectopascals (hPa) and temperature, I made a modification to the output format and frequency of updates as well. The differences between mine and the original git code are as follows:

Difference-Versions

decimal-bits-incorrectThe temperature data is provided as two bytes, but is 12-bits. The first byte is the integer portion, the second byte has the decimal portion but only the top four bits are filled with data. Unfortunately, the original code has a bug in the way it handles the decimal part of the temperature – as a result, it gives you the wrong decimal portion.

Unfortunately, initially, I thought there was only three decimal bits until I realized I counted wrong. As a result, there’s twice as many steps with four bits, and the interval between steps is 0.06125 degrees, but the bug with the original code remains.

To run the python script, it’s as simple as typing in sudo python mpl3115a2.py and watching it go.

python

To log the data, you merely have to pipe it into a text file, with extension .csv. After the data has been logged, you can use it for any purpose you desire. This was made from a long-term log, although with a mistake in my code (fixed above) which meant only 11-bits of temperature resolution rather than 12-bits (so really, each step should be halved). There are occasional glitches in the barometric pressure data, maybe due to communications problems.

graphed-data

The temperature is a bit higher than expected, and part of the reason is because the PCB is black and sitting above the CPU. All of the heat from the CPU is affecting the temperature measurement, which can be helped if you add a fan. A slow fan that keeps air moving around the temperature sensor will reduce the error, but not necessarily eliminate it, but I suppose not having any moving parts is nicer. To do this, I might as well use a different platform, with a lower power consumption, meaning no heat problems.

Getting Started with Freedom FRDM-KL25Z and mbed

The Freescale Freedom FRDM-KL25Z is a low cost (on special, it can be below AU$10 as well) ARM Cortex-M0+ based development board which supports many different development platforms. Freescale offers their own CodeWarrior development platform, which is a paid-for platform, however because the Freedom board supports OpenSDA, it is possible to use other platforms with the board.

Such development platforms include Keil MDK-ARM (paid with limited Lite edition for free), IAR (paid), Atollic (paid), CrossWorks (paid), CooCox (open, free), Arrow Cloud Connect (web based, free) and mbed (web based, free). Of the list of platforms, I decided to go with mbed for this quick exploration as it has a very extensive library for me to use.

General platform-related information is here. In order to use the Freedom board with it, you will need to flash the mbed firmware in bootloader mode following these instructions. If you ever need to restore the original OpenSDA/debug firmware to the board, you will need to follow a very similar process with the firmware from PEMicro’s OpenSDA download area here.

Once the bootloader is flashed, then you can plug it in with the OpenSDA port and it should come up as a drive. Double-click on mbed.htm and register or sign in for an account and login. The mbed compiler is a development environment which works completely within your browser, “in the cloud”.

mbedhtm

It’s easier than I expected to get started, because someone has already set-up a demonstration project which illustrates how to work with the board under mbed. You can import this project and use it as a basis for your own by clicking on Import and searching for xtrinsic. Double click on the one that appears. It’s not my project, so credit goes to JP PANG.

importxtrinsic

Once imported, you can look at the code by double clicking and navigating within the tree. The over-arching file is main.cpp, which you should examine closely as it teaches you a little about using the libraries and customizing it for your own needs.

The code actually accesses the accelerometer and touch sensors on the KL-25Z as well, so that’s why there’s “more” data than expected.

If you’d like to get going, you should click the compile button and download the .bin file. This will be used later to program the board.

Of course, there comes the time where you need to plug the board onto your Freedom board, being especially careful about the alignment of the pins. If you mistake the alignment and are off by one pin, the board may not perform correctly or be damaged.

DSC_6371

Double check this side, as it’s where the input voltage is coming from.

DSC_6373

Because my headers are slightly off, as I soldered them myself with no support ages back, the board bows slightly, but this is normal. The nylon stand-off has been removed to allow the board to sit correctly.

DSC_6370

It’s nice they chose black – it even matches the black KL-25Z board. Once plugged in properly, now comes the time to actually program the board. Connect the board through the OpenSDA plug into your computer and copy the downloaded .bin file to the new drive. After it completes, you can hit the reset button and the program will be running.

To see the data, you will need to set up a special serial driver for your mbed device. Once installed, you can use HyperTerminal and open up the serial port at 9600bps and see the data from the board.

hyperterm

Likewise, you can choose to log the data and make a graph from it, as well as modify the code to customize it to your liking.

Recycling an old Set Top Box LED Display as a Temperature and Barometric Pressure Display

I don’t like wasting things, so I tend to even go to lengths of disassembling and desoldering things from PCBs within old dead electronics devices. In this case, I managed to salvage a multiplexed four-digit seven-segment LED display from an old dead satellite TV tuner. Funnily, it looks something like this three-digit version salvaged from a dead standard-definition set-top box …

DSC_6588

When things are salvaged, there’s never any guarantees or information available, so a quick probing with a multimeter is necessary to establish the internal connections. I also decided to plan out how it would be connected to the Freedom board, labelled with the ports.

LED-display-pinout-traceAfter a few hours, it’s all soldered up and all that’s needed is to code. An hour later, the code is done too … and it’s not pretty. I decided to have it refresh the display with the temperature for about 0.5s, then with the barometric pressure for about 0.5s, then take a new set of data. I also decided to let it push the data out on USB as well, so it can still be used to log via USB and terminal. The code itself treats positive and negative temperatures equally – no sign is displayed on the LED display.

#include "mbed.h"
#include "MPL3115A2.h"
#include <cstdlib>
#include <iostream>

// Multiplexed 4-digit 7-segment display
DigitalOut anode_1(PTE20);
DigitalOut anode_2(PTE23);
DigitalOut anode_3(PTE29);
DigitalOut anode_4(PTC1);
DigitalOut seg_A(PTE21);
DigitalOut seg_B(PTE30);
DigitalOut seg_C(PTB3);
DigitalOut seg_D(PTB1);
DigitalOut seg_E(PTB0);
DigitalOut seg_F(PTE22);
DigitalOut seg_G(PTC2);
DigitalOut seg_DP(PTB2);

// Onboard RGB LED
DigitalOut rled(LED_RED);
DigitalOut gled(LED_GREEN);
DigitalOut bled(LED_BLUE);

// Enable Serial Output over USB for Logging Purposes
Serial pc(USBTX, USBRX);
MPL3115A2 mpl(PTE0, PTE1, 0x60<<1);
DigitalOut enMMA8491(PTA13);

// Define segment data
int data_A[] = {1,0,1,1,0,1,1,1,1,1};
int data_B[] = {1,1,1,1,1,0,0,1,1,1};
int data_C[] = {1,1,0,1,1,1,1,1,1,1};
int data_D[] = {1,0,1,1,0,1,1,0,1,1};
int data_E[] = {1,0,1,0,0,0,1,0,1,0};
int data_F[] = {1,0,0,0,1,1,1,0,1,1};
int data_G[] = {0,0,1,1,1,1,1,0,1,1};

int pressurehPa = 0;
int temperature100 = 0;
int refr=0;
int dig1 = 0;
int dig2 = 0;
int dig3 = 0;
int dig4 = 0;

int main()
{
    using namespace std;
    rled = 1;
    gled = 1;
    bled = 1;    
    enMMA8491 = 0;
    float mplPres = .0, mplTemp = .0;
    mpl.Oversample_Ratio(OVERSAMPLE_RATIO_128);    
    mpl.Barometric_Mode();
    
    while(true) {
        // INFINTE LOOP
        mplTemp = mpl.getTemperature();
        mplPres = mpl.getPressure();
        cout << "MPL3115: " << mplPres << " " << mplTemp << "\n\r" << endl;
        
        refr = 0;
        if (mplTemp <0) {
          temperature100 = mplTemp*-100;
        } else {
          temperature100 = mplTemp*100;
        }
        
        dig1 = temperature100 / 1000;
        dig2 = temperature100 / 100 - dig1*10;
        dig3 = temperature100 / 10 - dig1*100 - dig2*10;
        dig4 = temperature100 - dig1*1000 - dig2*100 - dig3*10;
        
        anode_1=0;
        anode_2=0;
        anode_3=0;
        anode_4=0;
               
        // DISPLAY WORKING
        while(refr<100) {
           // DISPLAY 1
           seg_A=!data_A[dig1];
           seg_B=!data_B[dig1];
           seg_C=!data_C[dig1];
           seg_D=!data_D[dig1];
           seg_E=!data_E[dig1];
           seg_F=!data_F[dig1];
           seg_G=!data_G[dig1];
           seg_DP = 1;
           anode_1=1;           
           wait_ms(3);
           anode_1=0;
           // DISPLAY 2
           seg_A=!data_A[dig2];
           seg_B=!data_B[dig2];
           seg_C=!data_C[dig2];
           seg_D=!data_D[dig2];
           seg_E=!data_E[dig2];
           seg_F=!data_F[dig2];
           seg_G=!data_G[dig2];
           seg_DP = 0;      
           anode_2=1;         
           wait_ms(3);
           anode_2=0;                    
           // DISPLAY 3
           seg_A=!data_A[dig3];
           seg_B=!data_B[dig3];
           seg_C=!data_C[dig3];
           seg_D=!data_D[dig3];
           seg_E=!data_E[dig3];
           seg_F=!data_F[dig3];
           seg_G=!data_G[dig3];
           seg_DP = 1;      
           anode_3=1;          
           wait_ms(3); 
           anode_3=0;                   
           // DISPLAY 4
           seg_A=!data_A[dig4];
           seg_B=!data_B[dig4];
           seg_C=!data_C[dig4];
           seg_D=!data_D[dig4];
           seg_E=!data_E[dig4];
           seg_F=!data_F[dig4];
           seg_G=!data_G[dig4];
           seg_DP = 1;      
           anode_4=1;
           wait_ms(4); 
           anode_4=0;                     
           refr=refr+1; 
        }
        refr = 0;
        pressurehPa=mplPres/100;
        dig1 = pressurehPa / 1000;
        dig2 = pressurehPa / 100 - dig1*10;
        dig3 = pressurehPa / 10 - dig1*100 - dig2*10;
        dig4 = pressurehPa - dig1*1000 - dig2*100 - dig3*10;
        
        anode_1=0;
        anode_2=0;
        anode_3=0;
        anode_4=0;
        seg_DP=1; 
                          
        // DISPLAY WORKING
        while(refr<100) {
           // DISPLAY 1
           seg_A=!data_A[dig1];
           seg_B=!data_B[dig1];
           seg_C=!data_C[dig1];
           seg_D=!data_D[dig1];
           seg_E=!data_E[dig1];
           seg_F=!data_F[dig1];
           seg_G=!data_G[dig1];                                                     
           anode_1=1;           
           wait_ms(3);
           anode_1=0;
           // DISPLAY 2
           seg_A=!data_A[dig2];
           seg_B=!data_B[dig2];
           seg_C=!data_C[dig2];
           seg_D=!data_D[dig2];
           seg_E=!data_E[dig2];
           seg_F=!data_F[dig2];
           seg_G=!data_G[dig2];     
           anode_2=1;         
           wait_ms(3);
           anode_2=0;                    
           // DISPLAY 3
           seg_A=!data_A[dig3];
           seg_B=!data_B[dig3];
           seg_C=!data_C[dig3];
           seg_D=!data_D[dig3];
           seg_E=!data_E[dig3];
           seg_F=!data_F[dig3];
           seg_G=!data_G[dig3];    
           anode_3=1;          
           wait_ms(3); 
           anode_3=0;                   
           // DISPLAY 4
           seg_A=!data_A[dig4];
           seg_B=!data_B[dig4];
           seg_C=!data_C[dig4];
           seg_D=!data_D[dig4];
           seg_E=!data_E[dig4];
           seg_F=!data_F[dig4];
           seg_G=!data_G[dig4];    
           anode_4=1;
           wait_ms(4); 
           anode_4=0;                     
           refr=refr+1; 
        }
    }
    return 0;
}

The result works as I expect, although due to the voltage and current drive limitations of the KL25Z, the LEDs are not very bright. I had even taken liberties of trying to pull a little more than the 4mA per pin limit, reasoning that I’m not using most of the other pins. The slight asymmetric refresh time is because the last digit of my display has been worn out a bit more than the others, and adding a little time to that digit compensates for it. To improve the brightness, a little more work could be put in to buffer the LEDs through something like a NAND gate package set up as an inverter, with the logic levels inverted in the code (i.e. data instead of !data). It’s still not a bad result, given that this project was conceived, built, coded and tested all within a few hours.

xtrinsic-LED-display

For example, here, it’s telling us the barometric pressure is 1013hPa, with a temperature of 19.18 degrees C.

Conclusion

If anything, this board is great value for money. It’s got three high-performance digital sensors on it for under AU$12. Even if you use it as a precision barometer and thermometer, it’s pretty cool, but there is so much more to explore if you have the imagination to put the sensors to good use.

Its design is quite interesting in being compatible with both the Raspberry Pi and the Freescale Freedom Board series, however, it does obscure many of the I/O ports making expansion for other projects difficult.

It did give me a good excuse to play with my KL-25Z and get started on mbed … so all in all, it’s good fun for lunch money!

About lui_gough

I’m a bit of a nut for electronics, computing, photography, radio, satellite and other technical hobbies. Click for more about me!

This entry was posted in Electronics and tagged , , , , . Bookmark the permalink.

3 Responses to Getting Started: Freescale Xtrinisic Sense Board on RPi & KL-25Z

  1. markkulix says:

    What is the point in the original code at lines 72-75? Totally useless.

    • lui_gough says:

      I suspect the code was incorrectly written by the Embest people, and it is yet another example of *incorrect* handling of the 12-bits packed into two-bytes. Since I haven’t used Altitude mode myself, I didn’t even bother looking at that code, although a look at the datasheet will tell you what sort of data handling is required (which should be in some way similar to the changes I made for the temperature code).

      – Gough

  2. John says:

    The broken links mentioned above now seem to be working.

    John

Error: Comment is Missing!