Quantcast
Channel: SparkFun Tutorials
Viewing all 1123 articles
Browse latest View live

Red Box Robot Hookup Guide

$
0
0

Red Box Robot Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t600

Redbox Robot

Here at SparkFun, we get a lot of compliments on our red boxes. They’re strong, stylish and hard to lose on a messy workbench. But, did you know that they also make pretty great robots? Okay, you can make a robot out of almost any box, but it won’t be as stylish. This kit has everything you need to transform your favorite cardboard box into a robotic buddy!

Cyber Monday Redbox Robot

KIT-14062

Kit Includes:

Covered in This Tutorial

This tutorial will guide you through the assembly, wiring and programming of an obstacle-avoiding robot. You will need to have some basic soldering experience, and you’ll need to cut a few holes in a cardboard box. Beyond that, you shouldn’t need any special tools or technical skill.

Materials Required

Besides the parts included in your kit, you’ll need to following tools:

Suggested Reading

How to Solder - Through-hole Soldering

New to electronics and soldering? Have you soldered before but need a refresher? This tutorial will cover everything you need to know about through-hole soldering.

Motors and Selecting the Right One

Learn all about different kinds of motors and how they operate.

RedStick Hookup Guide

Learn about the SparkFun RedStick, a USB thumb drive-sized Arduino-compatible development platform.

TB6612FNG Hookup Guide

Basic hookup guide for the TB6612FNG H-bridge motor driver.

Building the Chassis

Before we can start to wire our robot, we’ll need to assemble the mechanical parts. Luckily, this robot is about as simple as it gets!

Empty out the box in which your kit came. That box is going to become the body for our robot. The included breadboard has a peel-and-stick backing, so let’s start by sticking that to the topside of the box, along the hinged side of the box, near the center. In order to connect the rest of the parts, you’ll need the strip of double-sided tape that came in your kit. Cut off about an inch of that tape, and use it to stick down the battery pack just below the breadboard, as pictured in the diagram below. Don’t worry about the parts stuck into the breadboard just yet. We’ll get to that after the mechanical portion is assembled.

Top down diagram of the robot chassis

Click image for a closer look

As you can see, there are a few places where it is suggested you cut a hole into the box so wires can be fed through. One hole that you can’t see is underneath the battery case so you can access the power switch on the underside. Otherwise, you could just turn it to “ON” and leave it there. Two other such holes are found on the bottom of the box where we’re going to attach the motors.

If you look at the hobby motors in the kit, you’ll notice that there is an axle running through them so that a wheel can be pressed onto either side. You’ll also notice that the wires are gathered on one side of the motor. It’ll be easiest to wire the motors if you make sure that they’re attached with the wires pointing in toward the middle of the box. Use the remaining length of double-sided tape to mount the motors on the bottom side, front corners of the box. Check out the diagram below for an idea of how it should look.

Heads Up! One side of the motor has a sticker on it. Make sure to remove that sticker before using double-sided tape to mount the motor because this sticker doesn't have as much grip as the tape included in your kit.

Bottom up diagram of the robot chassis

As there are only two motors on this robot, we’ll need to add something on the backside to keep it from just dragging around. In this case, we’re going to use a 10mm LED as a caster. Not only is this a nice, cheap way to keep your robot’s backside off the ground, but it’ll also allow us to add cool lighting effects! You shouldn’t need to glue the LED into place; just poke it through the cardboard and splay the legs out as pictured below. Later, we’ll solder a few wires to this LED, and that should hold it in place.

Diagram illustrating proper LED placement

Once you have all the essentials taped into place, you can add some fun decoration to give your robot a little personality. Below, you can see that I’ve glued down a pair of googly eyes and drawn on a derpy smile with a magic marker.

Completed robot chassis

Wiring the Motors

Now that our robot friend has a body (and maybe even a face) it’s time to start wiring things together. To ease assembly, we’ll be jumping everything together on a breadboard. Before we can do that, though, you’ll need to solder headers to the RedStick and the Motor Driver Board. I won’t cover that process here; if you’re just getting started with soldering, then check out this tutorial. Once everything has headers attached, press the parts into your breadboard as pictured below. Pay close attention to how many rows are free on either side of the breadboard; you’ll need them for the motor connections.

Parts placed on a breadboard

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

Now that everything is in place, let’s add jumper wires to complete our circuit. There’s a spool of solid core wire included in your kit, which you’ll cut into short lengths and strip on either end. We’re going to make a lot of connections here, so the diagram might get messy. To make things easier to follow, I’ve broken it into stages. In case following a diagram isn’t your flavor, I’ve put together a table that outlines all of the connections. You can find it at the end of this section.

Heads Up! I've colored the wiring in these diagrams to make them easier to follow. You only have one color of wire in your kit, but don't worry; the color doesn't matter.

wiring diagram

A quick note about the connections above: the motors and battery pack come with wire leads attached, which you should be able to press directly into the breadboard without having to add your own wire.

wiring diagram

Notice in the diagram above that there are two wires connected to the battery terminals on the RedStick. You may be tempted to connect these wires to VCC and GND instead, but don’t do it! The battery connector actually passes through a booster circuit, so as your batteries drain, the RedStick won’t power down prematurely.

wiring diagram

Motor Driver PinRedStick PinOther
VMBattery +Battery Pack +
VCCVCC
GNDGNDBattery Pack -
A01Left Motor +
A02Left Motor -
B01Right Motor +
B02Right Motor -
PWMA10
AIN24
AIN12
STBYAny VCC connection
BIN15
BIN27
PWMB6
A410mm LED Anode
GND10mm LED Cathode

Making Moves

Now that you’ve made all of the connections you need to get the motors running, let’s get some code on that RedStick to spin our wheels! I’m going to assume for the purposes of this section that you have some experience with Arduino programming and that you’re already set up to load code onto the SparkFun RedStick. If you need a little help getting started, check out this tutorial.

In order to get code onto your RedStick, you will need to either remove it from the breadboard (carefully) or use a USB extension cable to plug it into your computer’s USB port.

The Arduino code below takes advantage of our library. If you are unfamiliar with installing an Arduino library, check out our tutorial.

Download the library using the link below, or grab the latest version from our GitHub repository.

TB6612FNG Arduino Library

This example code will make your robot do a little dance. This is a great way to make sure you’ve wired everything right so far. Besides, we’ve been staring at this thing long enough; it’s about time it did something!

language:c
/******************************************************************
TestRun.ino
TB6612FNG H-Bridge Motor Driver Example code
Michelle @ SparkFun Electronics
8/20/16
https://github.com/sparkfun/SparkFun_TB6612FNG_Arduino_Library

Uses 2 motors to show examples of the functions in the library.  This
causes a robot to do a little 'jig'.  Each movement has an equal and
opposite movement so assuming your motors are balanced the bot should
end up at the same place it started.

Resources:
TB6612 SparkFun Library
*****************************************************************/

// This is the library for the TB6612 that contains the class Motor and all the
// functions
#include <SparkFun_TB6612.h>

// Pins for all inputs, keep in mind the PWM defines must be on PWM pins
// the default pins listed are the ones used on the Redbot (ROB-12097) with
// the exception of STBY which the Redbot controls with a physical switch
#define AIN1 2
#define BIN1 7
#define AIN2 4
#define BIN2 5
#define PWMA 10
#define PWMB 6
#define STBY 9

// these constants are used to allow you to make your motor configuration
// line up with function names like forward.  Value can be 1 or -1
const int offsetA = -1;
const int offsetB = -1;

// Initializing motors.  The library will allow you to initialize as many
// motors as you have memory for.  If you are using functions like forward
// that take 2 motors as arguements you can either write new functions or
// call the function more than once.
Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);

void setup()
{
 //Nothing here
}


void loop()
{
   //Use of the drive function which takes as arguements the speed
   //and optional duration.  A negative speed will cause it to go
   //backwards.  Speed can be from -255 to 255.  Also use of the
   //brake function which takes no arguements.
   motor1.drive(255,1000);
   motor1.drive(-255,1000);
   motor1.brake();
   delay(1000);

   //Use of the drive function which takes as arguements the speed
   //and optional duration.  A negative speed will cause it to go
   //backwards.  Speed can be from -255 to 255.  Also use of the
   //brake function which takes no arguements.
   motor2.drive(255,1000);
   motor2.drive(-255,1000);
   motor2.brake();
   delay(1000);

   //Use of the forward function, which takes as arguements two motors
   //and optionally a speed.  If a negative number is used for speed
   //it will go backwards
   forward(motor1, motor2, 150);
   delay(1000);

   //Use of the back function, which takes as arguments two motors
   //and optionally a speed.  Either a positive number or a negative
   //number for speed will cause it to go backwards
   back(motor1, motor2, -150);
   delay(1000);

   //Use of the brake function which takes as arguments two motors.
   //Note that functions do not stop motors on their own.
   brake(motor1, motor2);
   delay(1000);

   //Use of the left and right functions which take as arguements two
   //motors and a speed.  This function turns both motors to move in
   //the appropriate direction.  For turning a single motor use drive.
   left(motor1, motor2, 100);
   delay(1000);
   right(motor1, motor2, 100);
   delay(1000);

   //Use of brake again.
   brake(motor1, motor2);
   delay(1000);

}

With this code compiled and running on your robot, you’ve made the first step toward bringing your red box to life. You’ve probably noticed, however, that it’s a little clumsy. It just runs right into anything in its path! The next thing we’re going to do is give it the ability to avoid those obstacles…

Avoiding Obstacles

Before we upload fresh code to take advantage of our robot’s ultrasonic sensor, we’ll need to wire the sensor to the RedStick. This sensor only requires four wires to work, and I’ve highlighted them in the diagram below.

wiring diagram

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

Once you’ve added these wires, it’s just a matter of uploading the example code below:

language:c
#include <SparkFun_TB6612.h>

// these constants are used to allow you to make your motor configuration
// line up with function names like forward.  Value can be 1 or -1
const int offsetA = -1;
const int offsetB = -1;

// Pins for all inputs, keep in mind the PWM defines must be on PWM pins
// the default pins listed are the ones used on the Redbot (ROB-12097) with
// the exception of STBY which the Redbot controls with a physical switch
#define AIN1 2
#define BIN1 7
#define AIN2 4
#define BIN2 5
#define PWMA 10
#define PWMB 6
#define STBY 9

// Initializing motors.  The library will allow you to initialize as many
// motors as you have memory for.  If you are using functions like forward
// that take 2 motors as arguements you can either write new functions or
// call the function more than once.
Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);

// Pins
const int TRIG_PIN = 11;
const int ECHO_PIN = 12;

// Anything over 400 cm (23200 us pulse) is "out of range"
const unsigned int MAX_DIST = 23200;

void setup() {

  // Setup all of our pins
  pinMode(TRIG_PIN, OUTPUT);
  digitalWrite(TRIG_PIN, LOW);
  pinMode(2, OUTPUT); digitalWrite(2, LOW);
  pinMode(4, OUTPUT); digitalWrite(4, LOW);
  pinMode(5, OUTPUT); digitalWrite(5, LOW);
  pinMode(7, OUTPUT); digitalWrite(7, LOW);
  pinMode(3, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(A4, OUTPUT);
  digitalWrite(A4, HIGH);

}

void loop() {

  // Start moving forward
  forward(motor1, motor2, 200);

  unsigned long t1;
  unsigned long t2;
  unsigned long pulse_width;
  float cm;

  // Hold the trigger pin high for at least 10 us
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Wait for pulse on echo pin
  while ( digitalRead(ECHO_PIN) == 0 );

  // Measure how long the echo pin was held high (pulse width)
  // Note: the micros() counter will overflow after ~70 min
  t1 = micros();
  while ( digitalRead(ECHO_PIN) == 1);
  t2 = micros();
  pulse_width = t2 - t1;

  // Calculate distance in centimeters.
  cm = pulse_width / 58.0;

  // If an obstacle is detected fewer than 20 centimeters away,
  // run the motors backwards and then coin flip to decide which
  // way to turn before continuing on.
  if(cm<20){back(motor1, motor2, 250); delay(1000);
  if(flip()){left(motor1, motor2, 250);}else{right(motor1, motor2, 250);}
  delay(2500);}

  // Wait at least 60ms before next measurement
  delay(60);
}

// Coinflip function that randomly returns a 1 or 0
bool flip(){

  static uint32_t buf = 0;
  static uint8_t idx = 0;
  if (idx)
  {
    buf >>= 1;
    idx--;
  }
  else
  {
    buf = random();  // refill
    idx = 30;
  }
  return buf & 0x01;

}

If everything is working correctly, your robot should be dodging obstacles. More specifically, if an object comes within 20 centimeters of the front of the robot, the robot will reverse direction and turn randomly before continuing on its way. This is a nice self-preservation instinct for a robot to have. However, if science fiction movies have taught me anything, a small robot needs a cute voice to survive.

The Voice

There’s one more quick connection we’ll need to make before your robot can whistle. Wire one side of the mini speaker to the A4 pin on the RedStick and wire the other side to ground as illustrated below.

wiring diagram

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

The final update that we’re going to make to our code today is to add a fun little function I call “Whistle,” which picks nine random frequencies and beeps them out in quick succession to approximate a sort of wordless interjection. It doesn’t sound like much, but it adds a lot of personality.

language:c
#include <SparkFun_TB6612.h>

// these constants are used to allow you to make your motor configuration
// line up with function names like forward.  Value can be 1 or -1
const int offsetA = -1;
const int offsetB = -1;

// Pins for all inputs, keep in mind the PWM defines must be on PWM pins
// the default pins listed are the ones used on the Redbot (ROB-12097) with
// the exception of STBY which the Redbot controls with a physical switch
#define AIN1 2
#define BIN1 7
#define AIN2 4
#define BIN2 5
#define PWMA 10
#define PWMB 6
#define STBY 9

// Initializing motors.  The library will allow you to initialize as many
// motors as you have memory for.  If you are using functions like forward
// that take 2 motors as arguements you can either write new functions or
// call the function more than once.
Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);

// Pins
const int TRIG_PIN = 11;
const int ECHO_PIN = 12;

// Anything over 400 cm (23200 us pulse) is "out of range"
const unsigned int MAX_DIST = 23200;

void setup() {

  // Setup all of our pins
  pinMode(TRIG_PIN, OUTPUT);
  digitalWrite(TRIG_PIN, LOW);
  pinMode(2, OUTPUT); digitalWrite(2, LOW);
  pinMode(4, OUTPUT); digitalWrite(4, LOW);
  pinMode(5, OUTPUT); digitalWrite(5, LOW);
  pinMode(7, OUTPUT); digitalWrite(7, LOW);
  pinMode(3, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(A4, OUTPUT);
  digitalWrite(A4, HIGH);

}

void loop() {

  // Start moving forward
  forward(motor1, motor2, 200);

  unsigned long t1;
  unsigned long t2;
  unsigned long pulse_width;
  float cm;

  // Hold the trigger pin high for at least 10 us
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Wait for pulse on echo pin
  while ( digitalRead(ECHO_PIN) == 0 );

  // Measure how long the echo pin was held high (pulse width)
  // Note: the micros() counter will overflow after ~70 min
  t1 = micros();
  while ( digitalRead(ECHO_PIN) == 1);
  t2 = micros();
  pulse_width = t2 - t1;

  // Calculate distance in centimeters.
  cm = pulse_width / 58.0;

  // If an obstacle is detected fewer than 20 centimeters away,
  // run the motors backwards and then coin flip to decide which
  // way to turn before continuing on.
  if(cm<20){back(motor1, motor2, 250); whistle(); delay(1000);
  if(flip()){left(motor1, motor2, 250);}else{right(motor1, motor2, 250);}
  delay(2500);}

  // Wait at least 60ms before next measurement
  delay(60);
}

// Coinflip function that randomly returns a 1 or 0
bool flip(){

  static uint32_t buf = 0;
  static uint8_t idx = 0;
  if (idx)
  {
    buf >>= 1;
    idx--;
  }
  else
  {
    buf = random();  // refill
    idx = 30;
  }
  return buf & 0x01;

}

// Make a series of cute random beeping sounds
int whistle(){
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
tone(A2,random(50,400)*10);
delay(100);
noTone(A2);
delay(100);
}

Assuming everything has gone well, your robot should be whistling an adorable little tune every time it encounters an obstacle. Consider it the Mouse Droid for your personal Death Star. Or perhaps it’s the first recruit for your robot army. Or maybe it’s just something to keep you company at home. Hey, whatever floats your boat, we’re not judging.

Resources and Going Further

Your robot is movin' and groovin'… but don’t stop there! You can still add more parts, more code, more personality! Check out the RedBot Experiment Guide for some ideas about what you can do with a simple two-wheeled robot.

Also, if you pimped your bot with some cool googly eyes or glitter, let’s see it! Take a picture and tweet it to @sparkfun

For more robotic fun, check out these other great SparkFun tutorials:

Actobotics Basic Differential Platform

Get started with Actobotics with this simple vehicle. Then expand and customize it for your own evil robot empire.

SparkFun Line Follower Array Hookup Guide

Learn how to connect the RedBot Line Following Sensor Bar to an arduino type microcontroller. Use the example sketches to read data from the bar, and try out a simple line following algorithm.

ReconBot with the Tessel 2

Build a robot with the Tessel 2 that you can control from a browser on your phone or laptop.
New!

Red Box Robot Hookup Guide

Turn an iconic SparkFun red box into an obstacle-avoiding robot.

learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado


Holiday Lights Hookup Guide

$
0
0

Holiday Lights Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t601

Light Up the Holidays

‘Tis the season, let’s get to decorating! Nothing looks as festive as a bunch of bright, colorful lights concentrated into a tight space. And for that, I heartily recommend an addressable LED strip. It’s very bright, super vivid, and easy to hookup. This kit has the bare essentials for adding a strip of LEDs to your holiday shrub, ugly sweater or boring family member.

Cyber Monday Light Up the Holidays

KIT-14060

Kit Includes:

Covered in This Tutorial

This tutorial covers all of the wiring and code necessary to light up a string of addressable LEDs with just a RedStick and a AA Battery Pack.

Required Materials

Besides the parts included in your kit, you’ll need to following tools:

Suggested Reading

If you’ve never worked with addressable LEDs or with the RedStick, we recommend checking out these other guides first.

Battery Technologies

The basics behind the batteries used in portable electronic devices: LiPo, NiMH, coin cells, and alkaline.

Light-Emitting Diodes (LEDs)

Learn the basics about LEDs as well as some more advanced topics to help you calculate requirements for projects containing many LEDs.

WS2812 Breakout Hookup Guide

How to create a pixel string with the WS2812!

RedStick Hookup Guide

Learn about the SparkFun RedStick, a USB thumb drive-sized Arduino-compatible development platform.

Wire Them Up

For the purposes of this tutorial, I’m going to assume that you have some very basic soldering experience. There are only a handful of connections that you’ll need to solder, so this isn’t a bad project to start with However, if you are using this as your introduction to soldering, we strongly suggest reading this tutorial first.

Addressable LED strips like the one in this kit tend to use a standardized 3-pin connector. This makes it easy to chain multiple LED strips together. Because the battery pack included with this project is not going to support a lot more than the 60 included LEDs, you may find it convenient to cut the female connector off the “out” end of the strip and solder it to the RedStick to make your LEDs detachable.

Warning:Make sure you’re cutting the right connector! Look at the little black arrows on the LED strip. You want the connector with the arrow pointing toward it.

arrow

The diagram below illustrates the handful of connections that you’ll need to make. You’ll notice that the red and yellow wires from the LED strip are connected directly to the battery connector. You may be tempted to connect them to the GND and VCC pins on the RedStick, but don’t do that. The VCC pin draws current through the on-board voltage regulator, which isn’t rated for the high current that the LEDs require to operate. If powered from VCC, the regulator will definitely get hot and may fail altogether.

diagram illustrating proper wiring connections

Click image for a closer look

Example Code

Once your LED strip is wired up, you can load some Arduino code onto the RedStick to animate the lights! For our example code, we’ll be making use of Adafruit’s fantastic NeoPixel library.

Click here to download a copy of both the example code, as well as the NeoPixel library. The library is located in the “Adafruit_NeoPixel” folder, and the example code is found in the “WS2812_Breakout_Example” folder.

You’ll need to install the library. For help there, check out our installing Arduino libraries tutorial.

We’ve broken down the example code into a few separate sketches that each have a festive animation. Since this is a holiday kit, I took the liberty of cooking up a few special addition animations as well:

Rainbow Cycle

This one is my favorite of the NeoPixel example animations. It scrolls through the entire rainbow of colors while evenly distributing the color spectrum across the LED strip.

language:c
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(64);
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
rainbowCycle(20);
}

void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Candy Chase

This is a little animation that I worked up based on the “Theater Chase” animation included in the NeoPixel example code. It creates a crawling lights effect in red on a white background, like an animated candy cane!

language:c
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(64);
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
candyChase(100);
}

void candyChase(uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i+q, 255,255,255);    //turn every pixel white
      }
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 255,0,0);    //turn every third pixel red
      }
      strip.show();

      delay(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

Snowflakes

This animation creates an array of randomly twinkling white pixels remenicant of snowfall.

language:c
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(64);
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
    snowflakes(100);
}

void snowflakes(uint8_t wait) {

// Setup the pixel array
int pixel[60];
for(int p=0; p<60; p++){
  pixel[p] = random(0,255);
}

// Run some snowflake cycles
for (int j=0; j<200; j++) {

// Every five cycles, light a new pixel
if((j%5)==0){
  strip.setPixelColor(random(0,60), 255,255,255);
}

// Dim all pixels by 10
for(int p=0; p<60; p++){
  strip.setPixelColor(p, pixel[p],pixel[p],pixel[p] );
  pixel[p] =  pixel[p] - 10;
}
   strip.show();
   delay(wait);
}

}

Iceflakes

Not a real thing, I know… It’s “Snowflakes” but blue instead of white.

language:c
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.setBrightness(64);
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
    iceflakes(100);
}

void iceflakes(uint8_t wait) {

// Setup the pixel array
int pixel[60];
for(int p=0; p<60; p++){
  pixel[p] = random(0,255);
}

// Run some snowflake cycles
for (int j=0; j<200; j++) {

// Every five cycles, light a new pixel
if((j%5)==0){
  strip.setPixelColor(random(0,60), 0,0,255);
}

// Dim all pixels by 10
for(int p=0; p<60; p++){
  strip.setPixelColor(p, 0,0,pixel[p] );
  pixel[p] =  pixel[p] - 10;
}
   strip.show();
   delay(wait);
}

}

Extending Battery Life

The 60 LEDs on your addressable LED strip can drain a lot of batteries really fast. At full brightness, the strip will pull over 2 amps!! With a capacity of only 1.5 amp-hours, the AA batteries included in this kit will only power the strip at full brightness, continuously, for under an hour. If you want to get more bang for your battery-buck, there are a few tricks you can use.

Cap the Brightness

60 LEDs in a linear meter is a lot of LEDs, so running them at full brightness is really… impressive. And mostly unnecessary. Luckily, the NeoPixel library includes a handy function called setBrightness(); which limits the brightness of an LED strip. You’ll notice that the examples in this tutorial all include the line strip.setBrightness(64);, which sets the strip brightness to about 25%. You can set it lower before noticing a huge difference in brightness, so play with that number until you find the right balance between brightness and battery life.

Take a Break

Sometimes a cool lighting effect is more impressive if it isn’t continuous. Try dropping a delay(); into the main loop so that there’s some downtime between animation cycles. Obviously, the less time you leave the LEDs on, the longer your batteries will last.

Cut it Short

Maybe you don’t need 60 LEDs. Maybe 30 would do just fine. You can cut a portion off the end of the strip with a pair of standard craft scissors. Just cut across the copper pads in between the LEDs, and now you have another small strip you could use elsewhere. You can always solder them back together if you change your mind!

Resources and Going Further

Now go forth and add lights to everything! It’s worth noting that the RedStick in this kit is powerful enough to address a lot more than 60 LEDs, but you’ll need to beef up the power supply before you start chaining strips together.

Also, we’d love to see what you did with your light kit! Take a picture and tweet it to @sparkfun.

For more blinky fun, check out these other great SparkFun tutorials:

WS2812 Breakout Hookup Guide

How to create a pixel string with the WS2812!

Das Blinken Top Hat

A top hat decked out with LED strips makes for a heck of a wedding gift.

SparkFun LED Array (8x7) Hookup Guide

Getting started with the Charlieplexed 8x7 LED array.

Cherry MX Switch Breakout Hookup Guide

How to assemble and use the Cherry MX Switch Breakout, allowing you to turn a matrix of mechanical switches into a full-size keyboard!

learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

IoT Hobby Kit Experiment Guide

$
0
0

IoT Hobby Kit Experiment Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t594

Introduction

The Internet of Things (IoT) is the network of connected physical objects, such as vehicles, buildings and people. These objects, or “things,” are often embedded with electronics to include sensors, actuators and microcontrollers that enable the devices to sense the environment around them, log data in real time, communicate with services or other devices, and be remotely controlled.

The SparkFun ESP8266 Thing Dev Board is a microcontroller board with a built-in WiFi radio, which makes it a fantastic development platform for IoT and home automation projects.

SparkFun ESP8266 Thing Dev Board

Lucky for us, we can use the Arduino IDE to program the Thing Dev Board, which makes life easy for programming and configuring our IoT projects. This guide will show you how to set up your Thing Dev Board and construct a few simple (but useful!) connected projects involving logging sensor data and controlling home appliances.

Cyber Monday IoT Hobby Kit

KIT-14061
$49.95

Required Materials

If you don’t have an IoT Hobby Kit, don’t worry! You can put together your own kit with the following parts:

Suggested Reading

We recommend checking out the following guides before diving in with the IoT experiments:

Soldering and Arduino Setup

Soldering

If your ESP8266 Thing Dev Board did not come with pre-soldered headers, you’ll need to attach them yourself. Solder male break-away headers or stackable headers to the Thing Dev Board.

Header pins on the ESP8266 Thing Dev board

Arduino

The ESP8266 community has created a library and bootloader that allows us to program ESP8266 chips and boards using Arduino (see this GitHub repository for more information).

Note: The Arduino IDE is updated regularly, which can result in the ESP8266 library not working properly. As a result, we recommend specifically using v1.6.5 of the Arduino IDE for these experiments.

Once you have the Arduino IDE installed, follow the directions on this page to install the ESP8266 library.

At the end of the installation guide, you should have the Thing Dev Board running the Blink sketch:

Blinky

Configure ThingSpeak

For these examples, we’ll be using ThingSpeak.

ThingSpeak Logo

ThingSpeak is an open source IoT data channel created by MathWorks (the same people who make MATLAB).

ThingSpeak allows us to read and write data to channels, which are logs of numbers, strings, etc. Each channel can have up to eight fields, which are groupings of similar data.

Create an Account

To use ThingSpeak, you’ll need to create an account. Don’t worry; it’s free. Head to ThingSpeak.com. At the top right of the page, click Sign Up.

ThingSpeak signup

Fill out the form and click Create Account. And that’s it! You’ll be presented with a welcome screen where you can make your first channel. We’ll do that in the next section.

Install ThingSpeak Arduino Library

In the Arduino IDE, go to Sketch > Include Library > Manage Libraries… Search for thingspeak and click Install. Note that ThingSpeak library v1.2.1 was used for this guide.

ThingSpeak Arduino library

Experiment 1: Temperature and Humidity Logging

One of the most basic IoT projects is to log data from a sensor to an online channel, and we’re going to do just that. For the first experiment, we’ll capture temperature and humidity data from a sensor and post it to our ThingSpeak channel.

Parts Needed

Hardware Hookup

Connect the RHT03 to the Thing Dev board as shown:

IoT Hobby Kit - Temperature and Humidity Logger

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

Create ThingSpeak Channel

Head to thingspeak.com, sign in, and navigate to Channels > My Channels.

Creating a new channel on ThingSpeak

Click New Channel, and fill out the required information, adding fields 2 and 3 to your channel.

Filling out channel information

Scroll down to the bottom of the page, and click Save Channel.

On the page that follows, copy down your Channel ID number (highlighted in the screenshot below).

Channel ID

Click on API Keys and copy your Write API Key.

Write API Key

The Code

In a new Arduino sketch, copy in the code below (make sure you have the ThingSpeak library installed!). In the code, find the section under // WiFi and Channel parameters, and change <YOUR WIFI SSID>, <YOUR WIFI PASSWORD>, <THINGSPEAK CHANNEL ID>, and <THINGSPEAK WRITE API KEY> to your WiFi network’s name, password, ThingSpeak Channel ID, and Write API Key, respectively.

language:c
/**
 * IoT Kit - Temperature and Humidity Logger
 * Author: Shawn Hymel (SparkFun Electronics)
 * Date: October 30, 2016
 *
 * Log temperature and humidity data to a channel on
 * thingspeak.com once every 20 seconds.
 *
 * Connections:
 *   Thing Dev |  RHT03
 *  -----------|---------
 *      3V3    | 1 (VDD)
 *        4    | 2 (DATA)
 *      GND    | 4 (GND)
 *
 * Development environment specifics:
 *  Arduino IDE v1.6.5
 *  Distributed as-is; no warranty is given.
 */

#include <ESP8266WiFi.h>
#include <SparkFun_RHT03.h>
#include "ThingSpeak.h"

// WiFi and Channel parameters
const char WIFI_SSID[] = "<YOUR WIFI SSID>";
const char WIFI_PSK[] = "<YOUR WIFI PASSWORD>";
unsigned long CHANNEL_ID = <THINGSPEAK CHANNEL ID>;
const char * WRITE_API_KEY = "<THINGSPEAK WRITE API KEY>";

// Pin definitions
const int RHT03_DATA_PIN = 4;
const int LED_PIN = 5;

// Global variables
WiFiClient client;
RHT03 rht;

void setup() {

  // Set up LED for debugging
  pinMode(LED_PIN, OUTPUT);

  // Connect to WiFi
  connectWiFi();

  // Initialize connection to ThingSpeak
  ThingSpeak.begin(client);

  // Call rht.begin() to initialize the sensor and our data pin
  rht.begin(RHT03_DATA_PIN);
}

void loop() {

  // Flash LED to show that we're sampling
  digitalWrite(LED_PIN, LOW);

  // Call rht.update() to get new humidity and temperature values from the sensor.
  int updateRet = rht.update();

  // If successful, the update() function will return 1.
  if (updateRet == 1)
  {

    // The tempC(), tempF(), and humidity() functions can be
    // called after a successful update()
    float temp_c = rht.tempC();
    float temp_f = rht.tempF();
    float humidity = rht.humidity();

    // Write the values to our ThingSpeak channel
    ThingSpeak.setField(1, temp_c);
    ThingSpeak.setField(2, temp_f);
    ThingSpeak.setField(3, humidity);
    ThingSpeak.writeFields(CHANNEL_ID, WRITE_API_KEY);
  }
  else
  {

    // If the update failed, try delaying for some time
    delay(RHT_READ_INTERVAL_MS);
  }

  // Turn LED off when we've posted the data
  digitalWrite(LED_PIN, HIGH);

  // ThingSpeak will only accept updates every 15 seconds
  delay(20000);
}

// Attempt to connect to WiFi
void connectWiFi() {

  byte led_status = 0;

  // Set WiFi mode to station (client)
  WiFi.mode(WIFI_STA);

  // Initiate connection with SSID and PSK
  WiFi.begin(WIFI_SSID, WIFI_PSK);

  // Blink LED while we wait for WiFi connection
  while ( WiFi.status() != WL_CONNECTED ) {
    digitalWrite(LED_PIN, led_status);
    led_status ^= 0x01;
    delay(100);
  }

  // Turn LED off when we are connected
  digitalWrite(LED_PIN, HIGH);
}

Run It!

When you upload and run the Arduino code on the Thing Dev Board, it should connect to your WiFi and begin sending data to ThingSpeak about once every 20 seconds. You’ll see data points appearing in the charts in your channel under the Private View tab.

Viewing logged data in ThingSpeak

Challenge

If you go to the Apps tab and select Plugins, you’ll be able to create an embeddable widget for your data channel. If you’re familiar with HTML, JavaScript and CSS, you can customize these widgets to do things like display a chart with multiple series.

Apps page in ThingSpeak

See if you can create a gauge plugin, modify it so it shows the temperature in Fahrenheit, and display it on your channel.

Google gauge plugin

Experiment 2: IoT Buttons

If you’ve seen Amazon’s IoT Button and wondered what you can use it for, we’ve got some possible solutions for you! First, though, we need to build our own IoT button, but why build one when you can build three?

Parts Needed

Hardware Hookup

Connect the buttons to the Thing Dev board as shown:

IoT Buttons

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

Create IFTTT Applet for Button A (send an email reminder)

If This, Then That (IFTTT) is a free web service that allows you to connect other web services together. For example, you can send yourself an email whenever a certain hashtag on Twitter is used. For this applet, we’ll send ourselves an email reminder whenever we push Button A connected to our Thing Dev Board.

Note: The email address you use to sign up with IFTTT will be the email address used to receive notifications.

To get started, head to ifttt.com, and create a new account. Once signed in, click on your username, and select New Applet.

IFTTT new applet

You’ll be presented with the Applet Maker page. Click on the highlighted + this (the trigger for the event).

alt text

Search for “maker” and click on the Maker icon. This will allow us to receive HTTP requests from other websites (we’ll be sending requests from ThingSpeak).

The first time you click on the Maker channel, you’ll be asked to connect the Maker service to IFTTT. Follow the instructions on the site to do that.

alt text

When you finish connecting to the Maker channel, you’ll be presented with an option to choose the trigger.

alt text

Click on Receive a web request, and name the event “button_a”.

alt text

Click Create trigger, and you’ll be presented with another screen showing your applet creation progress.

alt text

Click on + that to define the action that occurs whenever your “button_a” web request trigger occurs. Search for “email”.

alt text

Click on the Email icon. On the next screen, click Send me an email. Leave the Subject line alone and change the body to:

Reminder: {{Value1}}

{{value1}} is a parameter that we will pass to IFTTT in our web request from ThingSpeak.

alt text

Click Create action. Review your applet, and click Finish.

alt text

We will set up a ThingSpeak channel and ThingHTTP app to send HTTP requests to our IFTTT applet, but for now, let’s create the IFTTT applets for the other two buttons.

Create IFTTT Applet for Button B (text yourself)

Follow the same steps above to set up a new Applet. Label the Event Name as button_b.

alt text

When asked for the That action, search for and choose SMS.

alt text

Click Connect and follow the instructions to connect your cell phone with IFTTT. Choose Send me an SMS and fill out some message to send yourself, like “I found you!”

alt text

Click Create Action and Finish.

Create IFTTT Applet for Button C (post a tweet)

For the final button, we’ll tweet a random number that was generated by the Thing Dev Board. Once again, follow the same steps to create a new applet, and call the Event Name button_c.

alt text

For That, search for and select Twitter.

alt text

When you select Twitter on IFTTT, you’ll be asked to connect your Twitter account. If you don’t have a Twitter account, you can create one at twitter.com.

Fill out the Tweet text with the following:

[{{OccurredAt}}] IoT Button generated a random number: {{Value1}}

Note that we can use variables like {{OccurredAt}} to show when the event happened. These can be found by clicking the + Ingredient button just under the Tweet text.

alt text

Create action, and select Finish.

If you navigate to My Applets, you can see all your applets. The three we just created should be turned on.

alt text

Find Your IFTTT Maker Channel Secret Key

In order to use the Maker Channel on IFTTT, we need to send HTTP GET requests to a special address with your unique secret key, which we’ll refer to as IFTTT_SECRET_KEY when we make our ThingSpeak app. To find it, navigate to My Applets in IFTTT, and click on the Services tab.

alt text

These are the services that you have connected to IFTTT. Click on Maker.

alt text

Click on Settings in the upper-right corner.

alt text

Copy down the string of characters that make up the last section of the URL (shown highlighted in the screenshot). This string is your IFTTT_SECRET_KEY and is unique to your account.

Create ThingSpeak Channel

Head to thingspeak.com, select My Channels, and create a new channel with the following parameters:

  • Name: IoT Buttons
  • Description: Anything you want
  • Field 1: Button A
  • Field 2: Button B
  • Field 3: Button C

alt text

Save the channel, and you should be presented with the dashboard for your channel. Copy down your Channel ID (shown highlighted below). This will be referred to as your CHANNEL_ID later in this tutorial.

alt text

Create ThingSpeak ThingHTTP Actions

Head to thingspeak.com/apps, and select ThingHTTP.

alt text

This will allow us to create a custom HTTP request in order to trigger one of our IFTTT applets. Click New ThingHTTP, and fill out the fields with the following (making sure to replace <IFTTT_SECRET_KEY> with your unique IFTTT Maker Channel Key):

  • Name: IoT Button A
  • URL: https://maker.ifttt.com/trigger/button_a/with/key/<IFTTT_SECRET_KEY>
  • Method: POST
  • Content Type: application/json
  • Body: {“value1”: “Take the dog out at noon!”}

alt text

When called, this action will make an HTTP POST request to ifttt.com with the given body. That body, a JSON object, is then passed along to the action (“THAT”) portion of the IFTTT applet. “value1” matches up with “value1” in the email, so “Take the dog out at noon!” will be added to the body of the email sent to us.

alt text

From there, you can click Save ThingHTTP.

Create another ThingHTTP with the following parameters. Don’t forget to change <IFTTT_SECRET_KEY> with your IFTTT Maker Channel Key.

  • Name: IoT Button B
  • URL: https://maker.ifttt.com/trigger/button_b/with/key/<IFTTT_SECRET_KEY>
  • Method: GET

alt text

Save it, and make a third ThingHTTP with the following, changing <IFTTT_SECRET_KEY> to your IFTTT key and <CHANNEL_ID> to your ThingSpeak Channel ID.

  • Name: IoT Button C
  • URL: https://maker.ifttt.com/trigger/button_c/with/key/<IFTTT_SECRET_KEY>
  • Method: POST
  • Content Type: application/json
  • Body: {“value1”: “%%channel_<CHANNEL_ID>_field_3%%”}

alt text

Click Save ThingHTTP.

Create ThingSpeak React App

Head back to thingspeak.com/apps, and select React. Click New React. We will use React apps to trigger our ThingHTTP app whenever data is posted to each of our channel fields. ThingHTTP will then trigger our custom IFTTT applet.

Fill out the following parameters for the React app:

  • React Name: Button A React
  • Condition Type: Numeric
  • Test Frequency: On Data Insertion
  • Condition (If channel): IoT Buttons (<CHANNEL_ID>)
  • Condition (field): 1 (Button A), is equal to, 1
  • Action: ThingHTTP
  • Action (then perform): IoT Button A
  • Options: Run action each time condition is met

alt text

Save your React app.

alt text

Create a new React app with the following parameters:

  • React Name: Button B React
  • Condition Type: Numeric
  • Test Frequency: On Data Insertion
  • Condition (If channel): IoT Buttons (<CHANNEL_ID>)
  • Condition (field): 2 (Button B), is equal to, 1
  • Action: ThingHTTP
  • Action (then perform): IoT Button B
  • Options: Run action each time condition is met

alt text

Save it, and create a third React app with the following:

  • React Name: Button C React
  • Condition Type: Numeric
  • Test Frequency: On Data Insertion
  • Condition (If channel): IoT Buttons (<CHANNEL_ID>)
  • Condition (field): 3 (Button C), is greater than, 0
  • Action: ThingHTTP
  • Action (then perform): IoT Button C
  • Options: Run action each time condition is met

alt text

Save your React app.

Arduino Code

Now that we have our data channels and IFTTT applet set up, it’s time to program the ESP8266 Thing Dev Board. Open up a new sketch in Arduino and paste in the code below. Change <YOUR WIFI SSID> to your WiFi’s network name, <YOUR WIFI PASSWORD> to your WiFi’s password, <YOUR THINGSPEAK CHANNEL ID> to your CHANNEL_ID, and <YOUR CHANNEL WRITE API KEY> to your ThingSpeak Write API Key (which you can find by going to your ThingSpeak IoT Buttons channel and clicking on the API Keys tab).

language:c
/**
 * IoT Kit - IoT Buttons
 * Author: Shawn Hymel (SparkFun Electronics)
 * Date: October 30, 2016
 *
 * Push one of three buttons to make something happen on the
 * Internet using IFTTT. Button C will generate a random number
 * between 1-100 to post to ThingSpeak.
 *
 * Connections:
 *   Thing Dev |  Button
 *  -----------|---------
 *       4     |    A
 *      12     |    B
 *      13     |    C
 *
 * Development environment specifics:
 *  Arduino IDE v1.6.5
 *  Distributed as-is; no warranty is given.
 */

#include <ESP8266WiFi.h>
#include "ThingSpeak.h"

// WiFi and Channel parameters
const char WIFI_SSID[] = "<YOUR WIFI SSID>";
const char WIFI_PSK[] = "<YOUR WIFI PASSWORD>";
unsigned long CHANNEL_ID = <YOUR THINGSPEAK CHANNEL ID>;
const char * WRITE_API_KEY = "<YOUR CHANNEL WRITE API KEY>";

// Pin definitions
const int BTN_A_PIN = 4;
const int BTN_B_PIN = 12;
const int BTN_C_PIN = 13;
const int LED_PIN = 5;

// Global variables
WiFiClient client;
int last_btn_a = HIGH;
int last_btn_b = HIGH;
int last_btn_c = HIGH;

void setup() {

  // Set up LED for debugging
  pinMode(LED_PIN, OUTPUT);

  // Connect to WiFi
  connectWiFi();

  // Initialize connection to ThingSpeak
  ThingSpeak.begin(client);

  // Seed the random number generator
  randomSeed(analogRead(A0));
}

void loop() {

  int btn_a;
  int btn_b;
  int btn_c;
  int rnd;

  // Look for a falling edge on button A with debounce
  btn_a = digitalRead(BTN_A_PIN);
  if ( (btn_a == LOW) && (last_btn_a == HIGH) ) {
    delay(30);
    if ( digitalRead(BTN_A_PIN) == LOW ) {
      digitalWrite(LED_PIN, LOW);
      ThingSpeak.writeField(CHANNEL_ID, 1, 1, WRITE_API_KEY);
    }
  }
  last_btn_a = btn_a;

  // Look for a falling edge on button B with debounce
  btn_b = digitalRead(BTN_B_PIN);
  if ( (btn_b == LOW) && (last_btn_b == HIGH) ) {
    delay(30);
    if ( digitalRead(BTN_B_PIN) == LOW ) {
      digitalWrite(LED_PIN, LOW);
      ThingSpeak.writeField(CHANNEL_ID, 2, 1, WRITE_API_KEY);
    }
  }
  last_btn_b = btn_b;

  // Look for a falling edge on button C with debounce
  // Randomly choose a number between 1-100 and post it
  btn_c = digitalRead(BTN_C_PIN);
  if ( (btn_c == LOW) && (last_btn_c == HIGH) ) {
    delay(30);
    if ( digitalRead(BTN_C_PIN) == LOW ) {
      digitalWrite(LED_PIN, LOW);
      rnd = random(1, 101);
      ThingSpeak.writeField(CHANNEL_ID, 3, rnd, WRITE_API_KEY);
    }
  }
  last_btn_c = btn_c;

  // Turn off LED
  digitalWrite(LED_PIN, HIGH);
}

// Attempt to connect to WiFi
void connectWiFi() {

  byte led_status = 0;

  // Set WiFi mode to station (client)
  WiFi.mode(WIFI_STA);

  // Initiate connection with SSID and PSK
  WiFi.begin(WIFI_SSID, WIFI_PSK);

  // Blink LED while we wait for WiFi connection
  while ( WiFi.status() != WL_CONNECTED ) {
    digitalWrite(LED_PIN, led_status);
    led_status ^= 0x01;
    delay(100);
  }

  // Turn LED off when we are connected
  digitalWrite(LED_PIN, HIGH);
}

Run It!

Note: IFTTT is often quite busy. As a result, you may experience up to a 15-minute delay between pushing a button and seeing the action happen.

When you run the sketch on your Thing Dev board, you should be able to press one of the buttons. The buttons are as follows:

alt text

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

For example, by pressing button B, you should receive a text on your phone.

Pushing one of the IoT Buttons on the Thing Dev board

When you press button C, the Thing Dev Board will generate a number between 1 and 100 and post it to your Twitter account.

Challenge

See if you can change the Button B functionality so that it will send you the temperature and humidity near the ESP8266 Thing Dev Board to your phone via SMS.

Experiment 3: Appliance Controller

Now that we’ve logged data and pushed some physical buttons to make virtual things happen, it’s time to make physical things happen when something virtual happens. OK, that’s a mouthful, but in essence, we’re going to turn on and off home appliances (120 VAC) from anywhere in the world (assuming we have an internet connection).

To make this work, we’ll have an IFTTT applet send an HTTP request to ThingSpeak to log a value in a data channel. Our ESP8266 Thing Dev Board will poll the ThingSpeak data channel for new values. If it finds one, it will turn the PowerSwitch Tail on or off and then send a request to ThingSpeak to clear the data channel.

Parts Needed

Hardware Hookup

Connect one button and the PowerSwitch Tail to the Thing Dev as shown:

alt text

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

Note: The button is not necessary for remote control of the appliance, but it acts as a manual override in case you lose internet connectivity or one of the services goes down.

Create a ThingSpeak Data Channel

Head to ThingSpeak, and create a new channel. Name it Appliance Controller, and name Field 1 something appropriate (e.g., “Control”). On the channel dashboard, copy down the CHANNEL_ID, as we’ll need it later.

alt text

Get Your API Keys

From your channel’s dashboard, click on the API Keys tab. Copy down the WRITE_API_KEY and READ_API_KEY. We’ll need those later, too.

alt text

We’ll also need our ThingSpeak Account API Key, as that’s used to make delete requests to the data channel. In the top-right corner of ThingSpeak, click Account > My Account. Copy down the API Key found there. We’ll refer to this key as the <THINGSPEAK_ACCOUNT_API_KEY>.

alt text

Create IFTTT Applet

Navigate to IFTTT and create a new applet. For this section, search for weather.

alt text

You’ll be asked to connect the Weather channel. Follow the prompts to set your location to the nearest city. After that, select Sunset as the trigger.

alt text

For that, search for and select the Maker channel. Select Make a web request. Fill out the form with the parameters listed below, making sure to replace <WRITE_API_KEY> with your ThingSpeak Write API Key.

  • URL: https://api.thingspeak.com/update
  • Method: POST
  • Content Type: application/x-www-form-urlencoded
  • Body: api_key=<WRITE_API_KEY>&field1=1

alt text

Click Create action and Finish.

Arduino Code

With our channel and applet configured, let’s make some firmware to run on our ESP8266 Thing Dev. Copy in the code below, changing the parameters in the WiFi and Channel parameters section as noted.

language:c
/**
 * IoT Kit - Appliance Controller
 * Author: Shawn Hymel (SparkFun Electronics)
 * Date: November 11, 2016
 *
 * Set up an IFTTT applet to send an HTTP request to ThingSpeak
 * on a specific event, such as the sun setting. This sketch
 * monitors the channel and turns the attached appliance on or
 * off as requested before clearing the channel. A manual
 * override button can also toggle the appliance.
 *
 * Connections:
 *   Thing Dev | Button | PowerSwitch Tail II
 *  -----------|--------|---------------------
 *        4    |    A   |
 *       15    |        |       1 (+in)
 *      GND    |        |       2 (-in)
 *
 * Development environment specifics:
 *  Arduino IDE v1.6.5
 *  Distributed as-is; no warranty is given.
 */

#include <ESP8266WiFi.h>
#include "ThingSpeak.h"

// WiFi and Channel parameters
const char WIFI_SSID[] = "<YOUR WIFI SSID>";
const char WIFI_PSK[] = "<YOUR WIFI PASSWORD>";
unsigned long CHANNEL_ID = <YOUR THINGSPEAK CHANNEL ID>;
const char * READ_API_KEY = "<YOUR THINGSPEAK READ API KEY>";
const char * ACCOUNT_API_KEY = "<YOUR THINGSPEAK ACCOUNT API KEY>";

// Channel data definitions
const int CHANNEL_ERROR = 0;
const int APPLIANCE_ON = 1;
const int APPLIANCE_OFF = 2;

// Remote site information
const char HTTP_SITE[] = "api.thingspeak.com";
const int HTTP_PORT = 80;

// Pin definitions
const int LED_PIN = 5;
const int BTN_PIN = 4;
const int PST_PIN = 15;

// Global variables
WiFiClient client;
int appliance_state = 0;

void setup() {

  // Set up pins
  pinMode(LED_PIN, OUTPUT);
  pinMode(PST_PIN, OUTPUT);
  digitalWrite(PST_PIN, LOW);

  // Connect to WiFi
  connectWiFi();

  // Initialize connection to ThingSpeak
  ThingSpeak.begin(client);

  // For debugging
  Serial.begin(9600);

  // Send clear request to channel (start fresh)
  if (!clearChannel()) {
    Serial.println("Error connecting to ThingSpeak API");
  } else {
    Serial.println("Connected and listening!");
  }
}

void loop() {

  int val = -1;
  int btn;
  int last_btn = HIGH;
  unsigned long timestamp;
  unsigned long delay_time;

  // See if there was something posted to our channel
  val = ThingSpeak.readIntField(CHANNEL_ID, 1,READ_API_KEY);

  // If there is data on our channel, act on it and clear it
  if ( val > 0 ) {

    // If the value is a 1, turn on appliance
    if ( val == APPLIANCE_ON ) {
      Serial.println("Turning appliance on");
      appliance_state = 1;
      digitalWrite(PST_PIN, appliance_state);

    // If the value is a 2, turn off appliance
    } else if ( val == APPLIANCE_OFF ) {
      Serial.println("Turning appliance off");
      appliance_state = 0;
      digitalWrite(PST_PIN, appliance_state);
    }

    // Clear the data channel
    if ( !clearChannel() ) {
      Serial.println("Error: Could not clear channel!");
    } else {
      Serial.println("Channel cleared");
    }

    // Wait at least 15 seconds before polling the channel again
    delay_time = 15000;

  // No data. Try again later.
  } else {
    delay_time = 5000;
  }

  // Wait the required time before polling again
  timestamp = millis();
  while ( millis() < (timestamp + delay_time) ) {

    // Look for a falling edge on the button to toggle appliance
    btn = digitalRead(BTN_PIN);
    if ( (btn == LOW) && (last_btn == HIGH) ) {
      delay(30);
      if ( digitalRead(BTN_PIN) == LOW ) {
        appliance_state ^= 1;
        digitalWrite(PST_PIN, appliance_state);
      }
    }
    last_btn = btn;
    delay(1);
  }
}

// Attempt to connect to WiFi
void connectWiFi() {

  byte led_status = 0;

  // Set WiFi mode to station (client)
  WiFi.mode(WIFI_STA);

  // Initiate connection with SSID and PSK
  WiFi.begin(WIFI_SSID, WIFI_PSK);

  // Blink LED while we wait for WiFi connection
  while ( WiFi.status() != WL_CONNECTED ) {
    digitalWrite(LED_PIN, led_status);
    led_status ^= 0x01;
    delay(100);
  }

  // Turn LED off when we are connected
  digitalWrite(LED_PIN, HIGH);
}

// Send HTTP DELETE request to clear the channel
bool clearChannel() {

  // Attempt to make a connection to the remote server
  if ( !client.connect(HTTP_SITE, HTTP_PORT) ) {
    return false;
  }

  // Make an HTTP DELETE request
  client.print("DELETE /channels/");
  client.print(String(CHANNEL_ID));
  client.println("/feeds HTTP/1.1");
  client.print("Host: ");
  client.println(HTTP_SITE);
  client.println("Accept: */*");
  client.println("Accept-Encoding: gzip, deflate");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded");
  client.println("Content-Length: 24");
  client.println();
  client.print("api_key=");
  client.println(ACCOUNT_API_KEY);

  return true;
}

Run It!

Save and upload the code to the Thing Dev Board. Plug in the PowerSwitch Tail to an outlet, and plug an appliance (e.g., a lamp) into the PowerSwitch Tail. Now, just wait for sunset (if you don’t want to wait for sunset, you can modify the IFTTT applet to trigger earlier; try the Challenge below).

Remotely turning on an appliance with the ESP8266 Thing Dev and ThingSpeak

Challenge

Download the IFTTT App for your smartphone. See if you can create an IFTTT applet that allows you to remotely turn a device on and off from your smartphone using the DO button.

Resources and Going Further

Monitoring temperature, interacting with web services and remotely controlling physical devices are just the beginning for IoT. These experiments have hopefully given you a taste for some of the things you can do with internet-connected devices. What other projects can you come up with?

Resources

Going Further

Here are some other IoT projects you can use as inspiration:

Photon Remote Water Level Sensor

Learn how to build a remote water level sensor for a water storage tank and how to automate a pump based off the readings!

LED Cloud-Connected Cloud

Make an RGB colored cloud light! You can also control it from your phone, or hook up to the weather!

ESP8266 Powered Propane Poofer

Learn how Nick Poole built a WiFi controlled fire-cannon using the ESP8266 Thing Dev Board!

IoT Industrial Scale

What does a baby elephant weigh? How much impact force does a jump have? Answer these questions and more by building your very own IoT industrial scale using the SparkFun OpenScale.

learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

9DoF Razor IMU M0 Hookup Guide

$
0
0

9DoF Razor IMU M0 Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t567

Introduction

The SparkFun 9DoF Razor IMU M0 combines a SAMD21 microprocessor with an MPU-9250 9DoF (nine degrees of freedom) sensor to create a tiny, re-programmable, multi-purpose inertial measurement unit (IMU). It can be programmed to monitor and log motion, transmit Euler angles over a serial port, or to even act as a step-counting pedometer.

SparkFun 9DoF Razor IMU M0

SEN-14001
$49.95

The 9DoF Razor’s MPU-9250 features three, three-axis sensors – an accelerometer, gyroscope, and magnetometer – which gives it the ability to sense linear acceleration, angular rotation velocity, and magnetic field vector’s. The on-board microprocessor – Atmel’s SAMD21G18A– is an Arduino-compatible, 32-bit ARM Cortex-M0+ microcontroller also featured on the Arduino Zero and SAMD21 Mini Breakout boards.

In addition to pair of IC’s, the 9DoF Razor IMU includes a µSD card socket, LiPo battery charger, power-control switch, and a host of I/O break-outs for project expansion. It comes pre-programmed with example firmware and an Arduino-compatible bootloader, so you can customize the firmware and flash new code over a USB connection.

Covered In This Tutorial

This tutorial serves as both a primary documentation source and getting started guide for the SparkFun 9DoF Razor IMU M0. The first couple of sections document hardware and firmware features of the board, while the latter half of the tutorial demonstrates how to use the Arduino IDE and our MPU-9250 Arduino library to re-program the Razor IMU to your specific needs.

Bill of Materials

The 9DoF Razor IMU M0 comes populated with just about everything you could need to take advantage of the MPU-9250 9DoF sensor. There are just a handful of items – most of which you probably already have in your toolbox – you may need in addition to the board.

A micro-B USB cable can be used to both power and re-program the Razor. But, if you truly want to make the board mobile, you’ll need a single-cell Lithium-polymer (LiPo) battery, which can be recharged by plugging the 9DoF Razor into a USB supply. Additionally, if you want to log data, the 9DoF Razor IMU’s µSD socket supports any µSD card.

Lithium Ion Battery - 400mAh

PRT-13851
$4.95
2
Lithium Ion Battery - 850mAh

PRT-00341
11
USB microB Cable - 6 Foot

CAB-10215
$4.95
7
MicroSD Card with Adapter - 8GB

COM-11609
$13.95
2

Finally, you may need soldering tools and headers or wire, if you want to take advantage of the 9DoF Razor IMU’s I/O and power breakouts.

Hook-Up Wire - Assortment (Stranded, 22 AWG)

PRT-11375
$16.95
12
Female Headers

PRT-00115
$1.5
6
Solder Lead Free - 100-gram Spool

TOL-09325
$7.95
4
Soldering Iron - 30W (US, 110V)

TOL-09507
$9.95
5

Suggested Reading

Feel free to jump right into using and developing on the 9DoF Razor IMU M0 – we’ve tried to make the board as easy to use regardless of you electronics experience level. If you’d like to do some pre-reading, though, here are a few tutorials we might recommend:

Gyroscope

Gyroscopes measure the speed of rotation around an axis and are an essential part in determines ones orientation in space.

Accelerometer Basics

A quick introduction to accelerometers, how they work, and why they're used.

SAMD21 Mini/Dev Breakout Hookup Guide

An introduction to the Atmel ATSAMD21G18 microprocessor and our Mini and Pro R3 breakout boards. Level up your Arduino-skills with the powerful ARM Cortex M0+ processor.

MPU-9250 Hookup Guide

Get up and running with the MPU-9250 9-axis MEMS sensor.

Hardware Overview

The 9DoF Razor IMU M0 is a double-sided assembly, which means there’s a lot going on on both sides of the board. Here’s an overview of what we’ll call the “top” of the board.

Top side of board annotated

While the bottom of the board includes the various connectors, power control switch, and LEDs.

Bottom side of board annotated

Open Source Hardware! The 9DoF Razor IMU M0 is an open-source hardware design. Feel free to download the schematic (PDF), Eagle files (PCB design), or browse the design's history in our GitHub repository.

Powering the 9DoF Razor IMU M0

The Razor IMU is designed to work with either a USB power source or a single-cell Lithium-polymer (LiPo) battery. The black, PH-series JST connector should mate with any of the similar LiPo batteries in our catalog – just make sure they’re single cell (nominal voltage 3.7-4.2V).

LiPo and USB plugged into and powering board

Connect both USB and a LiPo to charge the battery.

If both USB and LiPo battery are plugged into the board simultaneously, the LiPo will charge at a rate of up to 450mA. Charge status is indicated by the yellow charge LED, which will turn off when the battery is fully charged.

450mA Charge Current The maximum charge current is set by an external resistor and is not (easily) modifiable. Safe practices say not to charge your LiPo battery at greater than 1C, which means LiPo's with a capacity below about 450mAh are not recommended for use with this board.

Power from either the USB or LiPo battery sources are regulated down to 3.3V, which is used to power both the SAMD21 and MPU-9250. The regulator has a capacity for about 600mA, which means you should have plenty of current overhead left over, if you want to power other devices from the 3V3-labeled pins.

The VIN, VBAT, and GND pins can be used to supply the 9DoF Razor IMU’s 3.3V regulator, instead of the USB or LiPo JST inputs. Voltage on the VIN pin should not exceed 6V, and the VBAT pin should only be connected to a single-cell LiPo battery.

Finally, the ON/OFF switch, on the bottom side of the board, controls power between both input sources and the rest of the components on the board. While in the “OFF” position, the LiPo battery will still be able to charge, but no other components should be energized.

SAMD21 and Power Supply Pin Breakouts

We’ve broken out as many of the SAMD21’s I/O pins as the 9DoF Razor IMU’s small form factor would allow us. That includes pins 10-13, which can be used as an SPI interface, analog-to-digital converter inputs A0-A4, RX, TX, and the I2C pins, SDA and SCL.

GPIO highlighted

The SDA and SCL pins are on the same I2C bus as the MPU-9250, but that shouldn’t be a problem as long as any additional I2C devices don’t share the IMU’s 7-bit addresses (0x68 and 0x0C).

You can solder headers or wire to these pins, to expand on the board’s features. For example, you can plug a BME280 breakout directly into the I2C port, and add altitude and temperature sensing to your IMU.

BME280 connected via I2C port

A number of our I2C-based breakouts use the same 4-pin footprint, so you can interface them directly!

The SAMD21’s single-wire debug (SWD) port is broken out on the top side of the board as well, in case you want to program the chip with a JTAG debugger. The pinout of this port matches the 10-pin Cortex Debug connector standard. A white “notch” indicates pin 1 of this port.

MPU-9250 Accel/Gyro/Mag Orientation

The orientation of the accelerometer, gyroscope, and magnetometer’s x-, y-, and z-axes are determined by the placement of the MPU-9250. For easy reference, we’ve documented these vectors on the top side of the board.

Note that the magnetometer’s x and y axes are flipped from those of the accelerometer and gyroscope, and the z-axis is inverted as well.

Getting Started With the Example Firmware

In addition to an Arduino bootloader, we’ve also loaded the 9DoF Razor IMU M0 with some example firmware – enough to at least prove that the sensor’s motion tracking works, and even do a little logging to a µSD card. To start using the example firmware, simply plug the Razor IMU into a computer.

9DoF Razor plugged into USB and uSD

After plugging the board in, it should show up as a serial port. On Windows, that looks something like COMX and on Mac, it should look like /dev/tty.usbserial-ABCD12.

Driver Installation

Windows users: The first time you plug the 9DoF Razor IMU M0 into your computer, you may need to install drivers to enable the board's communication device class (CDC) USB profile.

If your board doesn't show up as a COM port, click the button below to download the drivers.

Download the SparkFun SAMD21 Windows Drivers

For help installing the drivers, refer to our instructions in the SAMD21 Breakout hookup guide.

After locating your board’s port, open up a serial terminal and set the baud rate to 115200 bps. The Arduino Serial Monitor works well for this purpose, or you can download one of our recommended terminal programs.

Upon opening the port, your 9DoF Razor IMU should immediately begin spouting out accelerometer, gyroscope, and magnetometer readings.

Example serial monitor screenshot

The format of this default string is:

<timeMS>, <accelX>, <accelY>, <accelZ>, <gyroX>, <gyroY>, <gyroZ>, <magX>, <magY>, <magZ>

The string can be modified by sending any of the following commands:

  • (SPACE) – Pause/resume serial port printing
  • a– Turn accelerometer readings on or off
  • g– Turn gyroscope readings on or off
  • m– Turn magnetometer readings on or off
  • q– Turn quaternion readings on or off (qw, qx, qy, and qz are printed after mag readings)
  • e– Turn Euler angle calculations (pitch, roll, yaw) on or off (printed after quaternions)
  • c– Switch to/from calculated values from/to raw readings
  • r– Adjust log rate in 10Hz increments between 1-100Hz (1, 10, 20, …, 100)
  • A– Adjust accelerometer full-scale range. Cycles between ± 2, 4, 8, and 16g.
  • G– Adjust gyroscope full-scale range. Cycles between ± 250, 500, 1000, 2000 dps.
  • s– Enable/disable SD card logging

All settings are stored in non-volatile memory, so the next time you boot up your 9DoF Razor, it should output the same data you configured it to previously.

In addition to logging to your serial port, the firmware is also designed to log the data to a µSD card, if it’s present. Load one up, and you should end up with IMU log files the next time you plug the SD card into your reader.

The 9DoF Razor IMU's firmware is available in the product's GitHub repository. To upload the firmware, you'll need the SparkFun SAMD21 board definitions and the SparkFun MPU-9250 DMP Arduino library installed on your machine. Which is exactly what we're going to document next...

Installing the 9DoF Razor Arduino Core

The 9DoF Razor IMU M0 is designed around the SAMD21 – the same processor on the Arduino Zero – which means adding Arduino support for the board is just a few clicks away. This section describes the steps you’ll need to take to install the SAMD cores into your Arduino library (that sounds scarier than it actually is).

Update Arduino! This setup requires at least Arduino version 1.6.4 or later. We've tested it on 1.6.12, and would recommend that version of the IDE.

If you're running an older version of Arduino, consider visiting arduino.cc to get the latest, greatest release.

Install Arduino SAMD Boards

First, you’ll need to install a variety of tools, including low-level ARM Cortex libraries full of generic code, arm-gcc to compile your code, and bossa to upload code via the bootloader. These tools come packaged along with Arduino’s SAMD board definitions for the Arduino Zero.

To install the Arduino SAMD board definitions, navigate to your board manager (Tools>Board>Boards Manager…), then find an entry for Arduino SAMD Boards (32-bits ARM Cortex-M0+). Select it, and install the latest version (recently updated to 1.6.8).

Installing the Arduino SAMD boards

Downloading and installing the tools may take a couple minutes – arm-gcc in particular will take the longest, it’s about 250MB unpacked.

Once installed, Arduino-blue “Installed” text should appear next to the SAMD boards list entry.

Install SparkFun Board Definition

Now that your ARM tools are installed, one last bit of setup is required to add support for the SparkFun SAMD boards. First, open your Arduino preferences (File>Preferences). Then find the Additional Board Manager URLs text box, and paste the below link in:

https://raw.githubusercontent.com/sparkfun/Arduino_Boards/9DoF_M0/IDE_Board_Manager/package_sparkfun_index.json

Adding the board manager link

Then hit “OK”, and travel back to the Board Manager menu. You should be able to find a new entry for SparkFun SAMD Boards.

Installing the SparkFun SAMD Boards

This installation should be much faster; you’ve already done the heavy lifting in the previous section.

Select the Board and Serial Port

Once the board is installed, you should see a few new entries in your Tools>Board list, including SparkFun 9DoF Razor IMU M0, under the “SparkFun SAMD (32-bits ARM Cortex-M0+) Boards” menu.

Selecting the SparkFun 9DoF Razor IMU M0

Finally, select your 9DoF Razor’s port, by navigating back up to the Tools>Port menu.

Selecting the port in Arduino

In the next section, we’ll load up the example firmware, so you can customize it and build upon it as you create your own motion-sensing project.

Troubleshooting

If your 9DoF Razor IMU won’t enter the bootloader, or take new code, you can force it into the bootloader by holding the SCL pin LOW on start up. Flip the IMU’s switch off, use a jumper wire to connect SCL to GND, and turn the switch back on. While in the bootloader, the blue pin 13 LED should remain illuminated.

Libraries and Example Firmware

In addition to the SAMD board definitions, the 9DoF Razor IMU M0’s example firmware requires an additional library: the SparkFun MPU-9250 Digital Motion Processing (DMP) library. You can grab the MPU-9250-DMP library from GitHub, or by clicking the link below:

Download the SparkFun MPU-9250 DMP Library

You’ll also need the FlashStorage Arduino library installed on your machine. This library allows your SAMD21’s excess flash memory to substitute for EEPROM – giving it non-volatile memory so it can retain your serial commands.

Download the FlashStorage Arduino Library

The FlashStorage library is optional. Disable it by commenting out the ENABLE_NVRAM_STORAGE line in config.h. Without this library, settings that are changed will not be carried over on restart or power loss.

To install the libraries, unzip the ZIP files, and place the library folders into your Arduino sketchbook. For more help installing Arduino libraries, check out our Installing an Arduino Library tutorial.

Arduino libraries folder with FlashStorage and the MPU-9250-DMP library

After installing the libraries, open Arduino (or close and restart it if it was open).

Download and Upload the Example Firmware

The 9DoF Razor IMU M0’s example firmware can be found in our 9DoF Razor GitHub repository. Or you can click the button below to download it.

Download the 9DoF Razor IMU M0's Example Firmware

The firmware includes a pair of files – the standard .ino file with the main source, and a config.h file, which consists mostly of defines, which you can modify to quickly customize the firmware. Make sure both tabs are open in your Arduino IDE before attempting to compile and upload.

Razor IMU M0 Firmware in the Arduino IDE

If the config.h file isn’t present in your Arduino IDE, you can create a new tab (by clicking the down-arrow in the upper-right corner of the IDE) and copy/paste it in from here.

Once you’ve installed the libraries, loaded the code, and have the SparkFun 9DoF Razor M0 board selected, upload it to your board. You probably won’t see any new behavior on your 9DoF Razor IMU, but it’ll proof that you’ve got everything installed correctly.

Using the MPU-9250 DMP Arduino Library

Here are some quick tips to help you get started writing your own firmware for the 9DoF Razor IMU M0 using the SparkFun MPU-9250 DMP Arduino Library.

Set Up

As with any library, to call it into your sketch you’ll need to include it at the top. You’ll also need to create an object of type MPU9250_DMP– we’ll make one called imu, which will be used throughout the sketch.

language:c
#include <SparkFunMPU9250-DMP.h> // Include SparkFun MPU-9250-DMP library
//#include <Wire.h> // Depending on your Arduino version, you may need to include Wire.h

MPU9250_DMP imu; // Create an instance of the MPU9250_DMP class

Then, in the setup function initialize the MPU-9250 by calling imu.begin(). You can check the return value of this function to ensure that the IMU is correctly connected and was successfully initialized.

language:c
if (imu.begin() != INV_SUCCESS)
{
    while (1)
    {
        // Failed to initialize MPU-9250, loop forever
    }
}

Note that imu.begin()– all of the error-returning functions in this library, in fact – returns a 0 on success. Check for them to return INV_SUCCESS for a more verbose error check.

Configuring the MPU-9250

Once you’ve initialized the MPU-9250, you can configure it to your hearts desire. You can use setSensors to enable/disable specific sensors in the IMU. Disabling the gyroscope and magnetometer, for example, can save loads of power consumption.

language:c
// Use setSensors to turn on or off MPU-9250 sensors.
// Any of the following defines can be combined:
// INV_XYZ_GYRO, INV_XYZ_ACCEL, INV_XYZ_COMPASS,
// INV_X_GYRO, INV_Y_GYRO, or INV_Z_GYRO
imu.setSensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS); // Enable all sensors

You can also set the full-scale range of both the accelerometer and gyroscope using the setAccelFSR and setGyroFSR functions. (The magnetometer only has one possible full-scale range – ±4912 µT.)

language:c
// Use setGyroFSR() and setAccelFSR() to configure the
// gyroscope and accelerometer full scale ranges.
// Gyro options are +/- 250, 500, 1000, or 2000 dps
imu.setGyroFSR(2000); // Set gyro to 2000 dps
// Accel options are +/- 2, 4, 8, or 16 g
imu.setAccelFSR(2); // Set accel to +/-2g

The gyroscope can be set to ranges of ±250, 500, 1000, or 2000 degrees per second (dps), and the accelerometer supports ranges of ±2, 4, 8, or 16 g.

Finally, you can configure the digital low pass filter (DLPF) and sample rate of the sensors:

language:c
// setLPF() can be used to set the digital low-pass filter
// of the accelerometer and gyroscope.
// Can be any of the following: 188, 98, 42, 20, 10, 5
// (values are in Hz).
imu.setLPF(5); // Set LPF corner frequency to 5Hz

// The sample rate of the accel/gyro can be set using
// setSampleRate. Acceptable values range from 4Hz to 1kHz
imu.setSampleRate(10); // Set sample rate to 10Hz

// Likewise, the compass (magnetometer) sample rate can be
// set using the setCompassSampleRate() function.
// This value can range between: 1-100Hz
imu.setCompassSampleRate(10); // Set mag rate to 10Hz

The sample rate of the accelerometer and gyroscope can reach 1kHz, while the maximum sample rate of the magnetometer is 100Hz. The corner frequency of the low-pass filter – which operates on the accelerometer and gyroscope only – can be set to 5, 10, 20, 42, 98, or 188Hz.

Reading from the MPU-9250

Once your IMU is configured to fit your needs, reading from the sensor is as simple as calling imu.update() and checking the ax, ay, az, ax, ay, az, ax, ay, and mz class variables (e.g. imu.ax, imu.gy, imu.mz, etc).

language:c
// Call update() to update the imu objects sensor data. You can specify
// which sensors to update by OR'ing UPDATE_ACCEL, UPDATE_GYRO,
// UPDATE_COMPASS, and/or UPDATE_TEMPERATURE.
// (The update function defaults to accel, gyro, compass, so you don't
// have to specify these values.)
imu.update(UPDATE_ACCEL | UPDATE_GYRO | UPDATE_COMPASS);

The variables can be converted from raw, signed 16-bit values to their sensor’s respective units by passing them to the calcGyro, calcAccel, and calcMag functions:

language:c
float accelX = imu.calcAccel(imu.ax); // accelX is x-axis acceleration in g's
float accelY = imu.calcAccel(imu.ay); // accelY is y-axis acceleration in g's
float accelZ = imu.calcAccel(imu.az); // accelZ is z-axis acceleration in g's

float gyroX = imu.calcGyro(imu.gx); // gyroX is x-axis rotation in dps
float gyroY = imu.calcGyro(imu.gy); // gyroY is y-axis rotation in dps
float gyroZ = imu.calcGyro(imu.gz); // gyroZ is z-axis rotation in dps

float magX = imu.calcMag(imu.mx); // magX is x-axis magnetic field in uT
float magY = imu.calcMag(imu.my); // magY is y-axis magnetic field in uT
float magZ = imu.calcMag(imu.mz); // magZ is z-axis magnetic field in uT

Using the Interrupt or Data-Ready

Instead of constantly polling the update function, you can use the MPU-9250’s interrupt output to tell you when new data is ready. First, in the setup area, you should call enableInterrupt. (Don’t forget to set your Arduino’s interrupt pin as an input as well!)

language:c
#define INTERRUPT_PIN 4 // MPU-9250 INT pin tied to D4
...
void setup()
{
    pinMode(INTERRUPT_PIN, INPUT_PULLUP); // Set interrupt as an input w/ pull-up resistor
    ...
    // Use enableInterrupt() to configure the MPU-9250's
    // interrupt output as a "data ready" indicator.
    imu.enableInterrupt();

    // The interrupt level can either be active-high or low. Configure as active-low.
    // Options are INT_ACTIVE_LOW or INT_ACTIVE_HIGH
    imu.setIntLevel(INT_ACTIVE_LOW);

    // The interrupt can be set to latch until data is read, or as a 50us pulse.
    // Options are INT_LATCHED or INT_50US_PULSE
    imu.setIntLatched(INT_LATCHED);
}

You can set the interrupt’s active level to high or low, and set it to latch until the sensor is read or to send a 50µs pulse.

Once configured, simply read the status of your Arduino’s interrupt pin. If it’s active, you’ll know to update the IMU’s sensors.

language:c
if ( digitalRead(INTERRUPT_PIN) == LOW ) // If MPU-9250 interrupt fires (active-low)
{
    imu.update() // Update all sensor's
    // ... do stuff with imu.ax, imu.ay, etc.
}

Alternatively – if you don’t want to use the interrupt pin – you can check the return value of dataReady, to check if new data is available. This function returns a boolean – true if new data is ready.

language:c
if ( imu.dataReady() ) // If new IMU data is available
{
    imu.update(); // Update all sensor's
    ...
}

Using the Digital Motion Processor

The MPU-9250’s digital motion processor (DMP) allows you to offload tasks like quaternion calculation, step-counting, and orientation-determining off to the IMU.

Configuring the Digital Motion Processor (DMP)

To use any of those functions, you first need to initialize the DMP by calling the dmpBegin function. This should be called after imu.begin().

dmpBegin’s first parameter specifies which features of the DMP you want to enable. It can be an OR’d combination of any of the following:

  • DMP_FEATURE_PEDOMETERPedometer counts steps and the amount of time those steps were taken in.
  • DMP_FEATURE_TAP– Single and/or double-tap detection in any of the three planes.
  • DMP_FEATURE_ANDROID_ORIENT– Detects portrait, landscape, reverse portrait, and reverse landscape orientations.
  • DMP_FEATURE_6X_LP_QUAT– 6-axis (accelerometer and gyroscope) quaternion calculation.
  • DMP_FEATURE_LP_QUAT– Low-power (accelerometer only) quaternion calculation.
  • DMP_FEATURE_GYRO_CALGyroscope calibration. After 8 seconds of no motion, the gyroscope axes are re-calibrated to 0.
  • DMP_FEATURE_SEND_RAW_ACCEL– Sends raw accelerometer data to the DMP’s FIFO buffer.
  • DMP_FEATURE_SEND_RAW_GYRO– Sends raw gyroscope data to the DMP’s FIFO buffer.
  • DMP_FEATURE_SEND_CAL_GYRO– Sends calibrated gyroscope data to the DMP’s FIFO buffer.

Note that the pair of quaternion-calculating features are mutually exclusive – only use one of those features at a time. The same goes for the calibrated and raw gyroscope data gathering features.

A second, optional parameter for dmpBegin is the update rate, which can be anywhere between 4 and 200 Hz. Here’s a quick example, demonstrating how to initialize the DMP to stream accelerometer, calibrated gyroscope, and quaternion data:

language:c
void setup
{
    imu.begin(); // Initialize the MPU-9250.

    // Initialize the digital motion processor
    imu.dmpBegin(DMP_FEATURE_SEND_RAW_ACCEL | // Send accelerometer data
                 DMP_FEATURE_GYRO_CAL       | // Calibrate the gyro data
                 DMP_FEATURE_SEND_CAL_GYRO  | // Send calibrated gyro data
                 DMP_FEATURE_6X_LP_QUAT     , // Calculate quat's with accel/gyro
                 10);                         // Set update rate to 10Hz.
}

Reading from the DMP

The DMP streams its data to the MPU-9250’s 512-byte first-in, first-out (FIFO) buffer, so to get data from the DMP, the FIFO must be updated. You can use the fifoAvailable function, to check how full the FIFO is. Then call dmpUpdateFifo to read from the top of the FIFO.

language:c
if ( imu.fifoAvailable() > 0 ) / Check for new data in the FIFO
{
    // Use dmpUpdateFifo to update the ax, gx, qx, etc. values
    if ( imu.dmpUpdateFifo() == INV_SUCCESS )
    {
        // The following variables will have data from the top of the FIFO:
        // imu.ax, imu.ay, imu.az, -- Accelerometer
        // imu.gx, imu.gy, imu.gz -- calibrated gyroscope
        // and imu.qw, imu.qx, imu.qy, and imu.qz -- quaternions
    }
}

Check out the Examples!

The MPU-9250 DMP library includes a handful of examples, which demonstrate everything from getting raw sensor data from the IMU to using the digital motion processor to track steps or orientation. Check out those examples under the File>Examples>SparkFun MPU-9250 DMP Arduino Library menu as you continue working with the library.

Resources and Going Further

Our GitHub repostiory for the SparkFun 9DoF Razor IMU M0, includes all of our hardware and firmware design files. You can check out the board’s schematic, Eagle PCB layout, or the example firmware over there.

For more on the 9DoF Razor IMU’s MPU-9250, here are a handful of resources worth checking out:

There are plenty of tutorials left, if you need some project inspiration. Check out some of these related tutorials:

Dungeons and Dragons Dice Gauntlet

A playful, geeky tutorial for a leather bracer that uses a LilyPad Arduino, LilyPad accelerometer, and seven segment display to roll virtual 4, 6, 8, 10, 12, 20, and 100 side dice for gaming.

MicroView Digital Compass

Build a portable digital compass using the SparkFun MicroView and the MAG3110 Magnetometer Breakout.

MPL3115A2 Pressure Sensor Hookup Guide

Getting started with this amazing barometric pressure sensor.

Are You Okay? Widget

Use an Electric Imp and accelerometer to create an "Are You OK" widget. A cozy piece of technology your friend or loved one can nudge to let you know they're OK from half-a-world away.

learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

MAX30105 Particle and Pulse Ox Sensor Hookup Guide

$
0
0

MAX30105 Particle and Pulse Ox Sensor Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t577

Introduction

The SparkFun MAX30105 Particle Sensor is a flexible and powerful sensor enabling sensing of distance, heart rate, particle detection, even the blinking of an eye. This tutorial will get you up and running to get the raw data from the sensor.

SparkFun Particle Sensor Breakout - MAX30105

SEN-14045
$12.95

Behind the window on the left, the MAX30105 has three LEDs. On the right is a very sensitive photon detector. The idea is that you obstruct the different LEDs, detecting what light shines back at the detector, and, based on the signature, you can tell the presence of different types of particles or materials (such as oxygenated blood or smoke from a fire).

Close up photo of the MAX30105 sensor

Close up photo of the MAX30105 sensor.

Suggested Materials

You’ll need a handful of extra parts to get the MAX30105 breakout up-and-running. Below are the components used in this tutorial, if you want to follow along.

A microcontroller that supports I2C is required to communicate with the MAX30105 and relay the data to the user. The SparkFun RedBoard or Arduino Uno are popular options for this role, but just about any microcontroller development board should work. (The firmware examples use an Arduino library, if that serves as any extra motivation to use an Arduino.)

SparkFun RedBoard - Programmed with Arduino

DEV-12757
$19.95
108
Arduino Pro Mini 328 - 5V/16MHz

DEV-11113
$9.95
99
Arduino Uno - R3

DEV-11021
$24.95
83
SparkFun SAMD21 Mini Breakout

DEV-13664
$19.95
5
5V Recommended! The MAX30105 can run at 3.3V to 5V and can communicate with 3.3V and 5V microcontrollers. Most USB based development boards have a 5V pin that will power the MAX30105 nicely.

Four or five jumper wires and a breadboard help interface the sensor to your Arduino. To insert the breakout into the breadboard, you’ll need to solder headers or cut jumper wires to the pins. (Don’t forget a soldering iron and solder!)

Breadboard - Self-Adhesive (White)

PRT-12002
$4.95
26
Break Away Headers - Straight

PRT-00116
$1.5
20
Jumper Wires Premium 4" M/M - 20 AWG (30 Pack)

PRT-13870
$1.95
Soldering Iron - 30W (US, 110V)

TOL-09507
$9.95
5

Suggested Reading

The MAX30105 is designed for a handful of uses including Pulse Oximetry. If you’re unfamiliar with optical pulse detection there are some very good app notes from TI and NXP that have great starter information.

The MAX30105 communicates over I2C. We’ve got a great library to make it easy to use. And, we’re going to be using a breadboard to connect the breakout board to the RedBoard. If any of these subjects sound foreign to you, consider browsing through that tutorial before continuing.

How to Solder - Through-hole Soldering

New to electronics and soldering? Have you soldered before but need a refresher? This tutorial will cover everything you need to know about through-hole soldering.

Installing an Arduino Library

How do I install a custom Arduino library? It's easy!

How to Use a Breadboard

Welcome to the wonderful world of breadboards. Here we will learn what a breadboard is and how to use one to build your very first circuit.

I2C

An introduction to I2C, one of the main embedded communications protocols in use today.

MAX30105 Breakout Overview

The MAX30105 has three on-board LEDs (seen on the left). Maxim recommends these LEDs be powered from 5V, but we’ve found the LEDs work fine at 3.3V. The red and IR LEDs are guaranteed to work at 3.3V, but the green LED may need 3.5V. It’s best to try out your board at 3.3V and see if the green LED illuminates.

Close up view of MAX30105

The IC itself runs at 1.8V, so we’ve included the interface logic to allow you to hook the MAX30105 Breakout Board to any board that has 5V, 3.3V, even 1.8V level I/O.

Pin LabelInput/OutputDescription
INTOutputInterrupt, active low
GNDSupply InputGround (0V) supply
5VSupply InputPower supply
SDABi-directionalI2C bus clock line
SCLInputI2C bus clock line

The GND/5V/SDA/SCL pin-out is the standard I2C connection on most of our products. This allows you to easily connect I2C boards to many of our platforms.

The I2C Pins on the MAX30105

There are two jumpers on the back of the PCB:

Rear jumpers on MAX30105 Breakout Board

  • The PU jumper is used on many I2C boards to allow the user to disconnect the 4.7k Ohm pull-up (PU) resistors from the SDA and SCL lines. By default, this jumper is closed meaning there are 4.7k pull-up resistors on SDA and SCL. If this is the only device on the I2C bus, then this jumper should be left closed. If there are multiple I2C devices or breakout boards on the bus with pull-up resistors, then the traces in this jumper should be cut to remove the 4.7k Ohm resistors from the bus. If needed, the jumper can be re-soldered to close it again in the future.

  • The INT jumper is used to control the pull-up resistor on the interrupt pin. The INT jumper is closed by default, which means a 4.7k resistor is pulling up the interrupt pin. The INT pin on the MAX30105 is an open drain pin. If there is only one board on your I2C bus, this jumper should be left closed. If there are multiple boards on the I2C bus sharing a single interrupt pin, this jumper can be cut to disconnect the pull up resistor.

Hardware Hookup

MAX30105 in a fritzing diagram

Four wires is all you need but consider using connecting the board with soldered wires instead of a breadboard!

Because this sensor can be used in a multitude of ways, consider how you’re going to use the MAX30105 before soldering. If you plan to use the sensor for pulse oximetry, we recommend soldering short wires to the board to enable some movement when the sensor is attached to a finger. If you’re more interested in static sensing like particle or air monitoring, consider soldering male headers to the board.

Here’s an example of using jumper wires to make a robust connection to the MAX30105 board.

These jumper wires contain stranded wire, which make them more flexible and less prone to breaking from repeated movement.

Four jumper wires

Pick four different color wires, and cut them to your desired length. We use red, black, yellow and blue to make things easy to identify.

Cut jumper wires

Strip the ends of the wire, and solder them into their various spots. A connection to the INT pin is optional and not needed for the Arduino examples below.

Getting small gauge wires to stay in place can be tough. I like to use sticky tack to hold everything in place while I solder.

Soldering stripped wire using sticky tack

Sticky tack is your friend!

You can pick any colors you want, but using different colors for each pin will make it easier to distinguish between connections.

Soldering wires onto MAX30105

Recommended wire colors: Red-VCC, Black-GND, Yellow-SCL, Blue-SDA

Stranded wire is better at flexing than solid core wire. However, without stress relief, even these stranded wires may break due to lots of flexing.

Stranded wire soldered into place

Wires soldered into place

Adding a bit of hot-glue where the wires meet the PCB will make the board even more robust and resistant to damage when you start “speaking” with your hands.

PCB with hot glue as stress reflief

Using the SparkFun MAX30105 Arduino Library

Let’s get right to it! We’ve written an Arduino library for the MAX30105 and MAX30102 (it should work with the MAX30101 as well), which takes care of all of the I2C communication, bit-shifting, register-writing, and sample-reading. The library supports the MAX30102 (Red and IR LEDs only) and the MAX30105 (Red, IR, and Green LEDs).

The easiest way to install the library is through the Arduino Library manager.

Manage Arduino libraries

Type MAX30105 into the Search box and select the SparkFun Library.

MAX30105 Arduino Library

Click on the SparkFun library to highlight it, then click on the Install button.

MAX30105 Example Menu

Once you’ve downloaded the library, you should see the Example sketches by navigating to

File > Examples > SparkFun MAX3010x Pulse and Proximity Sensor Library > Examples

While you’re there, go ahead and open Example1 Basic Readings.

If you’d rather grab the most recent version of the library from our SparkFun MAX3010x Sensor GitHub repository, you can do that too!

Download the SparkFun MAX3010x Arduino Library

Then follow along with our How to Install an Arduino Library tutorial for help installing the library. If you download the library’s ZIP file, you can use Arduino’s “Add ZIP Library…” feature to install the source and example files with just a couple clicks.

Example 1 - Reading Red/IR/Green

Once you’ve got the library installed, open the Example1 Basic Readings sketch. You can find it under

File > Examples > SparkFun MAX3010x Pulse and Proximity Sensor Library > Examples

Then load it onto your RedBoard or Uno. Open your favorite Serial Terminal to see the printed values.

Screen shot of MAX30105 readings

This example outputs the raw values read by the sensor. With the sensor pointing up, use your hand to hover over the sensor. You should see a change in values as your hand reflects different amounts of light. Note that the IR readings will probably change before the Red and Green readings. IR is better at sensing distance changes.

Completely cover the sensor with your finger. Note the very large readings. This is one of the features that sets the MAX30105 from other reflectance sensors. The IC is capable of reading up to 18-bits or values up to 262,144. An extremely small change in light can be detected!

The MAX30105 is easy to use! Calling particleSensor.getGreen() will take a reading and return the reflected amount of green light.

Example 2 - Presence Sensing

Open the Example2 Presence Sensing sketch, and load it onto your RedBoard or Uno.

IR readings and distance sensing from MAX30105

This example takes a handful of readings during setup and averages them together. It uses this average as a baseline. If the sensor detects a significant change from the average, then “Something is there!” is printed. This is useful when you need to detect if a ball drops through a channel or other photo-gate situations. It’s also handy for testing the range at which the sensor can detect something.

language:c
//Setup to sense up to 18 inches, max LED brightness
byte ledBrightness = 0xFF; //Options: 0=Off to 255=50mA
byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
byte sampleRate = 400; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
int pulseWidth = 411; //Options: 69, 118, 215, 411
int adcRange = 2048; //Options: 2048, 4096, 8192, 16384

particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings

What is this block of code doing?

During setup this code initializes the sensor. There are many different options and configurations for the MAX30105. You can define as many or as few as you’d like. You can also skip them all:

language:c
particleSensor.setup(); //Configure sensor with default settings

The sensor will be configured with the default settings. The default settings work for most applications.

Example 3 - Temperature Sensor

Open the Example3 Temperature Sense sketch, and load it onto your RedBoard or Uno.

Temperature output from MAX3015 sensor

This example outputs readings from the on-board temperature sensor in both Celsius and Fahrenheit. The temp sensor is accurate to +/-1 C but has an astonishing precision of 0.0625 C.

The temperature is used internally by the sensor to calibrate its samples but can be useful if you need a sensitive and fast responding temp sensor.

Example 4 - Heart Beat Plotting

This is where the fun really begins! Hemoglobin reflects IR light really well, and the MAX3015 is capable of detecting such small changes in IR reflectance that it can detect blood flowing through your finger at different rates. Let’s graph it! Open the Example4 HeartBeat Plotter sketch, and load it on your Redboard or Uno.

Arduino v1.6.6 or Higher Required. The Serial Plotter is only available in Arduino versions v1.6.6 or later.

For this demo, you’ll need a rubber band small enough to go through the mounting holes on the breakout.

Rubber band inserted through two holes

Loop the band back onto itself, and pull gently. You want a little bit of pressure holding your finger against the sensor. If the end of your finger turns pale, you’ve tightened too much!

Pulse Oximetry MAX30105 cinched to finger

I'll just hold my finger on the sensor instead...

Humans are bad at applying consistent pressure to a thing. Without a rubber band the pressure varies enough to cause the blood in your finger to flow differently which causes the sensor readings to go wonky. It is best to attach the sensor to your finger using a rubber band or other tightening device.

Graph of heart beat

Graph of IR data - That’s my pulse!

Instructions:

  1. Load code onto Redboard
  2. Attach sensor to your finger with a rubber band
  3. Open Tools->Serial Plotter
  4. Make sure the drop down is set to 115200 baud
  5. Checkout the blips!
  6. Feel the pulse on your neck and watch it mimic the blips

Now that we have seen the blips, Example 5 will try to calculate the time between blips and show us beats per minute (BPM).

Example 5 - HeartRate

Hey! Let's have a brief chat about what this code does. We're going to try to detect heart-rate optically. This is tricky and prone to give false readings. We really don't want to get anyone hurt, so use this code only as an example of how to process optical data. Build fun stuff with our MAX30105 breakout board, but don't use it for actual medical diagnosis.

Open the Example5 HeartRate sketch, and load it on your Redboard or Uno.

Heart rate output

This example runs a filter called the PBA or Penpheral Beat Amplitude algorithm on the IR data. This algorithm is able to pull out the blips from all the noise and calculate the time between blips to get a heart rate. The output is your instantaneous heart rate and your average heart rate (BPM).

As one might expect the human body isn’t as precise as a metronome. The time between pulses can vary quite a bit so this sketch takes a running average of 4 readings to try to smooth out the variance.

Trouble? Try moving the sensor to a different finger. The rubber rand should be snug but not tight. The algorithm takes a few seconds to determine the peaks and troughs, so each time you move the sensor, wait a few seconds for the readings to make sense.

Advanced Functions

The MAX30105 is highly configurable, and there are a large number of functions exposed in the library to the user. Checkout the MAX30105.h file for all the functions, but here are the major ones. Read the MAX30105 datasheet for more information.

The library supports the following functions:

  • .begin(wirePort, i2cSpeed) - If you have a platform with multiple I2C ports, pass the port object when you call begin. You can increase the I2C speed to 400kHz by including I2C_SPEED_FAST when you call .begin() as well.
  • .setup() - Initializes the sensor with various settings. See the Example 2 for a good explanation of the options.
  • .getRed() - Returns the immediate red value
  • .getIR() - Returns the immediate IR value
  • .getGreen() - Returns the immediate Green value
  • .available() - Returns how many new samples are available
  • .readTemperature() - Returns the temperature of the IC in C
  • .readTemperatureF() - Returns the temperature of the IC in F
  • .softReset() - Resets everything including data and configuration
  • .shutDown() - Powers down the IC but retains all configuration
  • .wakeUp() - Opposite of shutDown
  • .setLEDMode(mode) - Configure the sensor to use 1 (Red only), 2 (Red + IR), or 3 (Red + IR + Green) LEDs
  • .setADCRange(adcRange) - Set ADC to be at 2048, 4096, 8192, or 16384
  • .setSampleRate(sampleRate) - Configure the sample rate: 50, 100, 200, 400, 800, 1000, 1600, 3200

Interrupts

  • .getINT1() - Returns the main interrupt group
  • .getINT2() - Returns the temp ready interrupt

Enable/disable individual interrupts. See page 13 and 14 of the datasheet for an explanation of each interrupt:

  • .enableAFULL()
  • .disableAFULL()
  • .enableDATARDY()
  • .disableDATARDY()
  • .enableALCOVF()
  • .disableALCOVF()
  • .enablePROXINT()
  • .disablePROXINT()
  • .enableDIETEMPRDY()
  • .disableDIETEMPRDY()

FIFO

The MAX30105 has a 32 byte FIFO. This allows us do other things on our microcontroller while the sensor is taking measurements. See Example 6 for an explanation of how to poll the FIFO.

  • .check() - Call regularly to pull data in from sensor
  • .nextSample() - Advances the FIFO
  • .getFIFORed() - Returns the FIFO sample pointed to by tail
  • .getFIFOIR() - Returns the FIFO sample pointed to by tail
  • .getFIFOGreen() - Returns the FIFO sample pointed to by tail

Resources and Going Further

For more on the MAX30105 Particle Sensor Breakout Board the Maxim MAX3010x, check out the links below:

How Can You Help?

The MAX30105 is a very powerful sensor but we’ve only scratched the surface of what it’s capable of. If you are an algorithms guru and have a better method for calculating heart rate, or SPO2, or particle detection we would love to hear from you! Please send us a link to your repo, and we’ll include it here.


For more sensor action, check out these other great SparkFun tutorials.

MAG3110 Magnetometer Hookup Guide

Get started with the MAG3110 3-Axis Magnetometer and learn how to make your own digital compass that senses the Earth's magnetic fields.

LSM9DS0 Hookup Guide

How to assemble, connect to, and use the LSM9DS0 -- an accelerometer, gyroscope, and magnetometer all-in-one.

Force Sensitive Resistor Hookup Guide

How to hook a force-sensitive resistor up to an Arduino to measure pressure variances.

Photocell Hookup Guide

Hook a light-sensing photocell up to an Arduino to create an ambient light monitor.

learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Importing Custom Images into Eagle

$
0
0

Importing Custom Images into Eagle a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t606

Introduction

Creating custom artwork on your PCB can be a fun way to personalize your project, add a company logo, or go crazy with pin numbering fonts. In this tutorial, we’ll show you 3 different methods of importing custom images into Eagle. Note that each of the three ways has pros and cons.

Badger custom art on PCB in Eagle

We used Method #1 to import this badger face as a series of polygons in Eagle

We recommend trying Method #1 (SVG to Polygon) first. It is the most complicated, but, if it works, you’ll have a set of polygons for your custom image that are much easier to work with than the lines/rectangles created by methods 2 and 3. If that fails, try method 2 or 3 to import an image as a series of lines, but be warned that having that many shapes can slow down your computer.

Additionally, you can import an image with method 2 or 3 and then trace over them with polygons in Eagle.

Recommended Reading

Before starting with this tutorial, we recommend that you be familiar with the basics of Eagle CAD:

Method 1: SVG to Polygon

Importing a vector graphic directly into Eagle requires a bit of work, but we recommend trying it first because:

  • Manipulating polygons in Eagle after importing is much easier than lots of tiny lines.
  • Using polygons for custom graphics takes less memory and makes panelization much easier.
Note: This method requires Inkscape to work.

Download Inkscape

If you don’t already have it, download and install the latest version of Inkscape. You will need it for this method.

Draw or Import Image

Draw, download, import, etc. your desired image. Make sure it is a single color (we’ll use black) and saved as a vector graphic (e.g. SVG). In this example, we’ll import an SVG image made with Adobe Illustrator.

Note: If your original image is a bitmap, you can also use Inkscape's bitmap tracing tool to make a vector graphic.

Change Image to Standard Size

Click the select tool (F1), and select Edit > Select All in All Layers (Ctrl + Alt + a).

alt text

Click the button to lock the height/width ratio.

alt text

Change the units to mm, and change height to 100.

alt text

Go to File > Document Properties…, select Resize page to content… drop down, and click Resize page to drawing or selection.

alt text

Massage Nodes

Convert the object to a path and select nodes:

  • Path > Object to Path (Shift + Ctrl + c)
  • Object > Ungroup (Shift + Ctrl + g) - Press this a number of times to make sure all objects have been ungrouped
  • Select all nodes with the path editor tool (F2, Ctrl + a)

alt text

Add interpolated nodes and flatten beziers (we want straight lines for the polygon):

  • Extensions > Modify Path > Add Nodes - Leave defaults, click Apply, and close the pop-up window
  • Select the nodes again (F2, Ctrl + a)
  • Extensions > Modify Path > Flatten Beziers - Leave defaults, click Apply, and close the pop-up window

alt text

Cut Closed Loops

Any shapes that have a closed loop or a “hole,” will need to be cut (Eagle doesn’t know how to create a polygon with a hole in it).

Draw a shape, such as a rectangle, that divides the hole.

alt text

Hold Shift, and select both the rectangle and your image. Select Path > Division (Ctrl + /). Repeat this process for any closed loops in your image, such as donuts, outlines, and letters like ‘o’ and ’d'. You should end up with a number of paths that make up your image.

alt text

Select all nodes with the path editor tool (F2, Ctrl + a). Click Path > Break Apart (Shift + Ctrl + k).

alt text

Export as Plain SVG

Click File > Save As, give your exported SVG file a name (make sure you include the .svg suffix!), and select Plain SVG (*.svg) from the Save as type: drop-down menu. Click Save.

alt text

Import SVG as Polygon in Eagle

Download the Eagle-ULPs repository as ZIP. Unzip the directory, and copy the file svg2poly.ulp to the [EAGLE Directory]/ulp directory.

alt text

Start Eagle, and either create a new footprint or open your layout where you want to import the graphic.

If you want to put the image at a particular point, enter the command:

mark

and click where you want the center of the image to appear. Then, run the command (you can change the ratio to whatever you want to scale the image appropriately):

run svg2poly -ratio 0.001

Select your plain SVG image, and it should be drawn on the tDocu layer. If the image does not show up properly, see the Troubleshooting section below.

Import SVG to Eagle custom image

Since these are polygons, you can modify and tweak them as needed to meet your PCB needs. Also, you can change the layer to something else, like tPlace to make it appear in the top silk!

Troubleshooting

If your image does not import correctly (it often doesn’t), there are a few tricks you can do to make it work.

alt text

First, figure out which sections of the image are not importing correctly, and divide them up more using the Cut Closed Loops method above. You can also try cutting closed loops in different ways. Make sure you select all nodes (F2, Ctrl + a) and Path > Break Apart (Shfit + Ctrl + k) before saving as a Plain SVG.

alt text

If certain sections are proving to be problematic, you can try deleting some of the nodes to see if that helps. If you delete nodes, you will need to select nodes in that section (F2) and Extensions > Modify Path > Flatten beziers. You then need to reselect all nodes in the image (F2, Ctrl + a) and Path > Break Apart (Shfit + Ctrl + k) before saving as a Plain SVG.

alt text

If all that fails, you can try manually drawing a new section in Inkscape. Don’t forget to Add Nodes, Flatten Beziers, and Break Apart before saving the new image.

alt text

Method 2: Import DXF

AutoCAD developed the Data Exchange Format (.DXF) to allow for sharing of files between AutoCAD and other programs. Lucky for us, newer versions of Eagle (7.7.0+) can also import DXF files. We can use that to add custom artwork to a layer.

Note: We'll be using Inkscape to prepare the DXF for importing. Also, note that this method results in an outline of the shape, not a complete fill.

Download Inkscape

If you don’t already have it, download and install the latest version of Inkscape. You will need it for this method.

Draw or Import Image

Draw, download, import, etc. your desired image. Make sure it is a single color (we’ll use black) and saved as a vector graphic (e.g. SVG). In this example, we’ll import an image made with Adobe Illustrator and saved as an SVG.

Note: If your original image is a bitmap, you can also use Inkscape's bitmap tracing tool to make a vector graphic.

Change Image to Standard Size

Click the select tool (F1), and select Edit > Select All in All Layers (Ctrl + Alt + a).

alt text

Click the button to lock the height/width ratio.

alt text

Change the units to mm, and change height to 100.

alt text

Go to File > Document Properties…, select Resize page to content… drop down, and click Resize page to drawing or selection.

alt text

Massage Nodes

Convert the object to a path and select nodes:

  • Path > Object to Path (Shift + Ctrl + c)
  • Object > Ungroup (Shift + Ctrl + g) - Press this a number of times to make sure all objects have been ungrouped
  • Select all nodes with the path editor tool (F2, Ctrl + a)

alt text

Add interpolated nodes and flatten beziers (we want straight lines for the polygon):

  • Extensions > Modify Path > Add Nodes - Leave defaults, click Apply, and close the pop-up window
  • Select the nodes again (F2, Ctrl + a)
  • Extensions > Modify Path > Flatten Beziers - Leave defaults, click Apply, and close the pop-up window

alt text

Cut Closed Loops

Any shapes that have a closed loop or a “hole,” you’ll need to cut them (Eagle doesn’t know how to create a polygon with a hole in it).

Draw a shape, such as a rectangle, that divides the hole.

alt text

Hold Shift, and select both the rectangle and your image. Select Path > Division (Ctrl + /). Repeat this process for any closed loops in your image, such as donuts, outlines, and letters like ‘o’ and ’d'. You should end up with a number of paths that make up your image.

alt text

Select all nodes with the path editor tool (F2, Ctrl + a). Click Path > Break Apart (Shift + Ctrl + k).

alt text

Export as DXF

Click File > Save As, give your file a name (make sure to include the .dxf extension!), and select Desktop Cutting Plotter (R13) (*.dxf) from the Save as type: drop-down menu. Click Save.

alt text

Make sure use LWPOLYLINE type of output is selected, and click OK.

alt text

Import DXF in Eagle

Start Eagle, and either create a new footprint or open your layout where you want to import the graphic.

Enter the command

run import-dxf

Click Browse to select your DXF file. Select the target layer, and change the scale as desired.

alt text

Click OK and Run on the pop-up window to import the image. Because the outline is made of lines, you can delete, move, and add lines as needed.

alt text

Method 3: Import BMP

Importing a bitmap into Eagle is probably the easiest method, but the import process draws many rectangles on a separate layer, which can be difficult to modify. It is recommended that you use bitmaps as a template to draw lines or polygons in Eagle.

Warning: Importing bitmaps can slow down computers when preparing Gerbers or panelizing.

Create a Bitmap

Use your favorite drawing program to create a monochrome (black and white) image.

alt text

Save the image as a Monochrome bitmap.

alt text

Import Bitmap

Start Eagle, and either create a new footprint or open your layout where you want to import the graphic.

Run the command:

run import-bmp

Read the pop-up window warning, and click OK. Select your bitmap file, and click Open. Select the black color to be imported, and click OK.

alt text

Scale your image as necessary, and select the desired units (I kept “mil” for this example).

alt text

Click OK and Run script on the pop-up. Your image should be imported on the “200 200bmp” layer as a series of rectangles.

alt text

If you zoom in on the imported image, you’ll see that it is actually made up of a series of rectangle shapes. These can slow down your computer and be a pain to work with if you need to make changes in Eagle, but it is a simple and effective way to get an image into Eagle.

alt text

Resources and Going Further

Try playing with some of the layers in Eagle to make interesting effects in your artwork! For example, in the badger face from the Introduction, the face is on the tPlace (top silk) layer, but the eyes are on the Top (top copper) layer. When the boards are produced, the face is white, but the eyes come out silver, copper, or gold colored (depending on the finish used).

alt text

Resources

Check out these other resources to aid in graphic design on your PCBs.

Going Further

Want to share your custom artwork with others? Check out these tutorials on how to contribute to and make your own public GitHub repositories. What more advanced Eagle tips and Tricks? Learn how to take your design to the next levels with these other great SparkFun Eagle tutorials.

Using GitHub

How to use repositories and GitHub for version control.

Using GitHub to Share with SparkFun

A simple step-by-step tutorial to help you download files from SparkFun's GitHub site, make changes, and share the changes with SparkFun.

Constant Innovation in Quality Control

In this article, we share our recent advancements in quality control. Every new product we design and manufacture here at SparkFun gets a custom testing apparatus that is designed and built in house. Along with making our tests more thorough, we have also made them more efficient and robust.

Making Custom Footprints in EAGLE

This tutorial will show you how to make custom, 1:1 footprint for any IC in EAGLE.

learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

Building an Autonomous Vehicle: The Batmobile

$
0
0

Building an Autonomous Vehicle: The Batmobile a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t589

Answering the Why

Why build an autonomous vehicle for A+PRS?

Smiling big in Batmobile

Test driving the Batmobile

The thrill of taking a corner, extremely low to the ground, with your gut telling you these g-forces are not normal… that’s why we spend countless hours building these silly Power Wheels vehicles. The giggles and grins are unavoidable! These cars are so much fun to drive – and even more fun to race!

Toni the race car driver

In 2016, SparkFun had its eighth annual Autonomous Vehicle Competition. This year saw the introduction of a new rule: you needed to carry a human (or a 20lb dead weight in the form of a watermelon if you were too chicken). To do this, my wife, Alicia, and I modified a Batmobile Power Wheels and combined it with a Razor chassis. The result was an extremely zippy electric go-kart that left a perma-grin on everyone who drove it.

Our goal was to create a vehicle that could quickly and easily switch between human driver and driverless modes so that we could compete in both PRS and A+PRS categories. In the end, Alicia placed a very respectable third place in the driver category, and I did not finish (DNF) in the autonomous category, running into numerous hay bales.

This tutorial attempts to document a six-month build process for an Autonomous + Power Racing Series (A+PRS) vehicle. Every autonomous vehicle is unique, and the requirements of each will vary from build to build.

Batmobile with top off

Materials

You can see our overall budget, including a list of components and vendors here.

A+PRS Batmobile Material Spreadsheet


You can get all the code from our repo here.

A+PRS Batmobile GitHub Repository


Chassis

The AVC rules stipulate that you cannot spend more than $500 on your total budget and that you have to stay within certain size restrictions. We started trolling craigslist to see what was out there and immediately found a plethora of free or cheap “broken” Power Wheels. When a Batmobile for $25 popped up, we quickly snagged it.

Dusty Batmobile

Dusty with dog hair and dead spiders – it’s perfect!

The primary failure of all used Power Wheels is a dead battery. The Batmobile was no different; as soon as we put in a new 12V SLA (Sealed Lead Acid), it happily, albeit slowly, drove around. There is nothing magical about “Power Wheels” branded batteries; get the right voltage (usually 12V, sometimes 6V), and you can use almost any battery you’d like. While the stock chassis was capable of moving adults weighing in at around 200lbs, we knew it wouldn’t handle racing, so we decided to find a metal chassis to sit underneath.

Many PRS and AVC competitors are talented enough to weld their own chassis together. DIY welding is a great way to save money, but it may take weeks of fabrication. Because we planned to enter the autonomous field, we decided to find a ready-made chassis and spend our time building and debugging the autonomous bits.

Razor Drifter in box

Note the size of the motor and battery. Those are about to get much larger.

Razor is known for their kick scooters, but they’re in the electric go-kart market as well. We found a Razor Drifter Open Box for $165. The Drifter had the steering, brakes, wheels and chassis sorted out for us! Additionally, the Drifter came with a stock 24V battery, 250W motor and 250W motor controller.

Putting on a Hat

Once we had the Power Wheels and the Razor chassis, we had to combine the two.

A Power Wheels meets a Drifter

A Power Wheels meets a Drifter

At some point you have to get out the reciprocating saw and severely modify your beautiful Power Wheels. We laid the Batmobile over the Razor and proceeded to chop off all the bits that got in the way.

Combined Batmobile

Seats? Where we’re going, we don’t need seats!

Pleasingly, the Batmobile sits on top of the chassis under its own structural support. We didn’t need to add all-thread or other standoffs. Even though they don’t do anything, we reattached the original wheels just so it looked extra wacky.

Motor and Motor Control

New larger motor on chassis

Moar!

In 2016, A+PRS allowed 48V systems, so the first thing we did was remove the 24V motor and install a 1,000W 48V/21A motor. The PRS rules limit any system to 1,400W, so we could have gone larger had budget constraints not been kicking in fast. New mounting holes were drilled into the chassis, and a different gear had to be mounted to the end of the motor. But it all went well. The stock chassis even included a chain tensioner that proved invaluable!

The MY1020 48V motor we used is common on the PRS circuit and performed great. However, our original 1,000W motor controller (you should already be able to tell what’s coming) did not do so well. Our first tests of the 48V system in an open parking lot worked great until the motor controller overheated and failed. And when MOSFET-based motor controllers fail, they fail unsafe, meaning our vehicle decided to go to 100 percent throttle and stay there. This is why we have safety switches! Alicia and I were able to kill the vehicle before anyone got hurt.

This failure should have been prevented: a motor controller should be rated for at least 2 times what you calculate your maximum load will be. In our case, if we wanted to control a 1kW motor, we should have been using a motor controller rated to a constant 2kW load. Luckily, the A+PRS rules don’t require you to record how much money you spent (and burned up); you have to report only what is on the vehicle as it rolls on race day.

Larger 5kW motor controller

The new, larger 5kW motor controller

We quickly located a larger, 5kW motor controller (this one even had reverse!) and got it on order. This larger motor controller has been working swimmingly ever since. Find a motor controller with reverse. You’ll be tempted to drive your souped-up Power Wheels in weird places (like the SparkFun inventory aisles), and a reverse gear allows for hilarious 5-point turns.

Brakes

Small Drum Brake

Go-kart drum brakes on eBay

The Razor chassis had the classic drum brake, perhaps the weakest link of the Razor. While the stock brake was probably the appropriate size for a 75lb child with stock 24V batteries, our brakes got really squishy once we added an additional 125lbs of meat bag, batteries and plastic bits. We rarely, if ever, used the brakes during races, but the PRS rules stipulate that your qualifying lap must end with the driver crossing the finish line and braking to a stop:

At the end of the hot lap, your car will have to come to a complete stop within 18ft of when its transponder crossed the start/finish line. Deliberately skidding, swerving or spinning out is not an acceptable method of braking for the brake test.

Alicia had to do an impressive combination of hard braking, swerving, skidding and sliding with such a dramatic flair that she wooed the judges into not noticing how dodgy our brakes were. We’ll have disc brakes installed before we roll in the 2017 race.

Batteries

Batteries installed on chassis

Battery holder welded onto the front of the chassis

As part of the motor upgrade, we needed to increase the battery voltage to 48V. To save money, we reused the super common batteries that came with the 24V Razor chassis. Razor was smart; they looked at the SLA (Sealed Lead Acid) battery industry and picked the most common size. This just happened to be the same battery that goes into nearly every UPS on the planet. We purchased two additional UPS-size batteries (way cheaper than buying Razor-brand batteries) and wired them in series.

4 batteries combined into one unit

Four batteries combined in series

Taping the cells together and adding a bead of hot glue between the cells made the pack nicely rigid. A low-cost, polarized, high-current connector finished off the pack. We had an old strap lying around that made all the difference in the world; it’s a lot more comfortable carrying the pack one-handed by its handle than with two hands underneath.

Polarized high current connector

Avoid fires and other bad things. Use polarized connectors for your batteries.

Wire

Soldering large gauge wire

Soldering large-gauge wire

We originally spec’d out some really nice, super flexible silicone-sheathed 8AWG wire for power distribution. I don’t think we would do this again; 10AWG would have been fine, and probably even 12AWG. As 8-gauge is far less common, the wire and connectors are more expensive, and the larger gauge wire takes a lot more soldering heat – it’s just a pain to work with. If you need the current capacity, go for it, but for our extremely zippy, 48V 20A vehicle, 8-gauge wire was overkill.

If you decide to use super flexible, large gauge wire, spend some time on the internet reading about how to solder this type of wire.

The best technique I found:

  • Make sure you’ve got heat shrink in place
  • Turn your soldering iron up to 425C (way hotter than the 325C usually needed)
  • Push the ends of wire together
  • Wrap tightly with 30AWG wire wrap wire
  • Liberally apply flux
  • Heat and insert lots of solder until the joint turns silver

Here’s a good video demonstrating this technique:

Kill Switch

We documented how to build a wireless kill switch while making margaritas. It was a ton of fun, so we’ll skip the bits of the wireless kill switch system here.

Smiling girl in power wheels

Zroooommmm!

In addition to the wireless disconnect, we had a large, red mushroom kill switch that disconnected the battery with a pleasing and authoritative“thunk.” Pulling up on the mushroom button reconnects the battery to the system.

Mushroom kill switch on vehicle

Batman logo or Bitman logo?

As a pleasant bonus feature, the mushroom kill switch got rid of the nasty sparks. When connecting the battery to the motor controller, there was such an inrush of current into the capacitors and electronics that the connector would spark. Once we got the kill switch installed, we could connect/disconnect batteries without these sparks.

Large gauge power connector

Connector between kill switch and power bus

The top of the Batmobile was easily removed, but because it had the kill switch installed we needed a way to disconnect it easily from the power bus. We found a great high-power connector in a dead server UPS. These are often called “winch connectors”, because they are higher current. With this connector, we are able to quickly disconnect the kill switch and remove the top when we need to get at the inside of the vehicle.

Control Electronics

Main controller board

Power converters, motor kill relays, steering relays, locomotion controller and wireless communication

The control electronics are complex. We had a total of seven microcontrollers on this beast, plus three used in the distance sensors for a total of 216 bits of processing power. The system operated on an I2C bus with the brain sending commands to the locomotion controller and LCD and receiving data from the sensors.

Wiring inside the Batmobile

The wiring underneath the Batmobile cover

For a previous 2010 AVC entry, I did everything on a single microcontroller. This made coding and debugging a challenge. On our 2016 entry, we focused each sub-system to do one thing very well.

The subsystems are broken down as follows:

  • Brain Controller: A SAMD21 Mini was used to communicate with and process all the data from the distance sensors, GPS and compass, and to send out commands to control throttle and steering. It monitored a start switch and relayed debug information to an LCD.
  • Locomotion Controller: An Arduino Pro Mini read the throttle, steering position, brake switch and autonomous rocket switch. It controlled motor speed and the linear actuator for steering.
  • Wireless Kill Switch: An Arduino Pro Mini lived in the wireless kill switch, a requirement for the autonomous part of our Batmobile. To learn more about the wireless controller, check out our tutorial on how to build a wireless kill switch.
  • A dedicated Arduino Pro Mini controlled the relays for the wireless kill switch system.
  • Debug LCD: We counted our LCD screen as a microcontroller since it has an Arduino in it.
  • Sensor Combinator: A SAMD21 Mini polled the serial GPS and I2C compass.
  • Laser Controller: A SAMD21 Mini controlled the three serial-based laser distance sensors, combined the relevant information and responded to requests from the Brain.
  • Three STM32s were the brains within the laser distance sensors.

Control Electronics - Brain

Controller and reverse knob

The Brain is a SAMD21 Mini. It sends commands over the I2C bus to the locomotion controller and debug LCD.

4-pin JST connector at the top of the image: We used a 4-wire bus (5V, GND, SDA, SCL) for communication and had various taps throughout the bus to allow devices to be attached. This worked really well and allowed for devices to be moved around when needed.

4-pin JST connector to the left: This was four wires to the button. To tell the vehicle to begin navigating under autonomous control, we used a metal momentary push button that illuminates when everything is online and happy. The human presses the button twice, and the car commences racing.

Big gray handle: This was the original forward and reverse knob that we reused to control the direction switch on the motor controller (two pins when shorted together caused one direction, when open caused the other direction).

The massive and poorly written control code for the Brain can be found here.

EEPROM for Waypoints

The SAMD21 does not have internal EEPROM. Because we needed to store GPS waypoints and other configuration data to non-volatile memory, we used an external I2C EEPROM. Yes, you can use something called emulated EEPROM on the SAMD21, but, every time you reprogram the board, you will overwrite anything previously stored in emulated EEPROM. The external EEPROM made it much easier to store and recall waypoints and settings without having to mash together in the main control code.

Control Electronics - Locomotion

Locomotion Controller PCB

Locomotion Controller hooked up

Note the polarized connectors and prodigious labeling! You DO NOT want to be guessing what gets plugged into where at 11 p.m. before race day. The Locomotion Controller code is available here, and the PCB layout here.

Because we eventually wanted this beast to be autonomous, we needed to put a controller in the middle between the throttle and the motor controller. We used an Arduino Pro Mini that did a huge variety of sensing and control:

  • Read the throttle
  • Output analog voltage to the motor controller
  • Read the brake switch
  • Read the steering position
  • Controlled the linear steering actuator
  • Read the human/robot control switch
  • Received and responded to control commands over I2C

Panic button and third switch

Don’t panic

The controller would monitor the rocket switch and brake switch. If a human ever pressed the brakes or turned off the rocket switch, the controller would go into safety shutdown and ignore any commands from the brain.

12V linear actuator on desk

Steering was controlled using a 12V linear actuator over-voltaged to 24V for extra speed. Two relays controlled the forward/backward motion.

Trimpot on rack and pinion steering

Steering position was obtained by cutting a hex wrench to about 1” and inserting that wrench into the bolt that rotates with the wheel. The wrench was then connected to a 10k trimpot using adhesive-lined heat shrink – this trick is known as the “poor man’s coupler:” a 3-wire ribbon connected the trimpot back to the locomotion controller. It worked well, but we had to keep the analog signal wire away from the power bus; otherwise, bad noise got into the ADC readings.

Actuator on chassis

Chassis with the Batmobile raised to see the steering actuator

For future vehicles, we’re going to change this setup. It worked well enough, but once the bolt connected the actuator to the steering, you couldn’t drive the car; only the computer could. So rather than driving the car to the start line, we had to carry this 75lb beast. So painful. In the future, we plan to find a back-drivable actuator or maybe drive-by-wire.

Control Electronics - Displays

Throttle and displays

Throttle and displays

We cut notches in a 1” tube of PVC and mounted two displays in the Batmobile. The center display is the power meter. Nearly every A+PRS and PRS competitor used these super low-cost power meters to show the battery voltage. We had some issues with it, but it worked well enough. In the end, we noticed the drop in vehicle speed (indicating battery drain) long before we noticed the display was indicating a lower pack voltage. But, it did help us make decisions about when to pit (never!) because the nominal 48V pack voltage was dropping down to 42V where we could begin to damage the SLA.

The display on the right is the 20x4 character debug LCD. It’s basically a souped-up version of our 20x4 SerLCD display (it’s a prototype product, coming soon to a theater near you!).

Control Electronics - Sensors

GPS and compass connected to SAMD21

GPS+Compass connected to SAMD21

The Sensor Combinator is a SAMD21 Mini that monitors a GPS receiver and an I2C compass. We decided to use a SAMD21 because it can be configured to have multiple hardware serial and I2C ports. This is needed if you want to isolate I2C devices from the main bus. We wanted the Brain to ask for the heading and get the heading; the Sensor Combinator took care of the low-level I2C function of the compass and heading calculations. Similarly, the Combinator listened to the serial stream from the u-blox based GPS module and parsed out all the needed Latitude/Longitude/SIV information.

The code for the Sensor Combinator can be found here.

Control Electronics - Lasers

Batmobile with top off

Laser tape measures seen on the front of the car, wrapped in foil

We hacked three laser tape measures in order to get distance to any objection front, left or right of the car. Laser tape measures are getting cheaper, and while the read rate (3Hz at the best of times) is not great for LIDAR, it’s fast enough for basic, low-cost autonomy.

Lasers wired to controller

Laser Controller at front of car

Unfortunately, the laser tape measures threw off enough RF to interfere with our GPS module, so we wrapped the lasers in foil. These sensors deserve their own tutorial, which will be written soon.

PCB with connectors

Laser Controller with labels

Again we chose the SAMD21 Mini to help us control and combine the serial information coming from the three sensors. The Laser Controller would send the pertinent control strings to the tape measures and monitor the responses, combining them into distances for left/right/center. The Brain would request these values from the Laser Controller over I2C.

Note the prodigious amounts of labels and polarized connectors (JSTs work great!). This system required lots of debugging but worked well because we were able to quickly disconnect and reconnect various aspects of the system.

The code for the Laser Controller can be found here.

Problems

As with any project, we had a large number of problems and hurdles to overcome along the way. Here are a few that really hurt.

EMI and GPS

The Laser tape measures caused significant interference with GPS reception. We eventually moved the GPS module to the rear of the car, which improved positional accuracy. However, the motor caused interference with the compass.

DC Motor EMF

DC motors produce a ton of electromagnetic noise. We originally had the 48V battery powering the entire car. However, when the motor would kick on, it would cause enough ripple to make the Brain glitch and reset. We tried powering the I2C bus separately, but, because the Locomotion Controller needed to be attached to the motor controller, a GND connection had to be shared. The noise eventually found its way over the I2C bus. In the future we will optically isolate the I2C bus.

Lack of EEPROM

Because the SAMD21 doesn’t have internal EEPROM, we were unable to store GPS waypoints on the board. We fixed this by using an I2C-based EEPROM.

Switching Steering Between Driver/Driverless

It was difficult to attach and detach the linear actuator from the rack and pinion steering. Once the actuator was attached to the steering, a driver could not actively steer (for example, to the starting line). This could be fixed with a different actuator that could be back-driven, or we could go full monty and detach the steering column from the steering and have it control a trimpot that, in turn, controls the linear actuator (drive by wire).

Tips / Best Practices

Pig tails in air in a turn

Tip 1) Start early– These vehicles take a large amount of time. Get together with friends and start hacking. It’s a great labor of love, and drifting in a 15mph go-kart will make you giggle.

Tip 2) Get reverse– Get a motor controller with reverse. It will make it so you can drive your car where you want it instead of carrying your car where you need it.

Tip 3) Use connectors!– I’ve written about using connectors a few times. Use polarized connectors and a label maker to make it clear what plugs in where.

Tip 4) Size your motor and motor controller correctly– We blew our motor controller because it was underrated. A friend of ours smoked his motor because he was pushing too much current. Pick your system voltage and current, and then double the ratings wherever you can.

Tip 5) Beware of interference– These vehicles can pull 30 amps or more when accelerating, which can cause large electromagnetic fields. Keep unshielded cables and sensitive sensors away from power wires.

Tip 6) Wireless control and sensor logging– After you pick up your 75lb vehicle and drag it to the start line for the fifth time, you’ll understand the need for remote control. Create a wireless system that allows you to take over control of the vehicle from afar so you can drive it where you need it. And transmit the sensor data so you can see what the vehicle is doing.

Nathan with pigtails in Batmobile

Hope you enjoyed reading! See you at next year’s AVC!


learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

HIH-4030 Humidity Sensor Hookup Guide

$
0
0

HIH-4030 Humidity Sensor Hookup Guide a learn.sparkfun.com tutorial

Available online at: http://sfe.io/t591

Introduction

The SparkFun HIH-4030 Humidity Sensor Breakout measures relative humidity (%RH) from Honeywell’s HIH-4030 humidity sensor. The breakout allows you to connect the analog output of the sensor directly to an ADC on a microcontroller.

SparkFun Humidity Sensor Breakout - HIH-4030

SEN-09569
$16.95
3

Voltage applied to the supply pins should be within 4-5.8 VDC, and optimally at 5V. The sensor will typically only consume about 200μA.

This tutorial serves as a introduction to the HIH-4030 and the SparkFun Humidity Sensor Breakout. It covers both the hardware and firmware requirements of the breakout to start receiving relative humidity (%RH) measurements as well as documenting example wiring, Arduino code and using the sensor in conjunction with a thermometer.

As we step through the Hookup Guide, you’ll find it useful to have the HIH-4030 Datasheet on hand.

HIH-4030 Datasheet

Required Materials

To get the humidity sensor up and running, you’ll need the following parts. Further in the tutorial, you’ll learn how to incorporate a temperature sensor, specifically SparkFun’s Digital Temperature Sensor Breakout - TMP-102, for properly determining relative humidity (%RH). Note that adding a temperature sensor is optional, but its use will be highlighted in this tutorial.

Suggested Reading

Before getting started with the HIH-4030, you should ensure you are familiar with the following topics:

Voltage, Current, Resistance, and Ohm's Law

Learn about Ohm's Law, one of the most fundamental equations in all electrical engineering.

Analog to Digital Conversion

The world is analog. Use analog to digital conversion to help digital device interpret the world.

Logic Levels

Learn the difference between 3.3V and 5V devices and logic levels.

Analog vs. Digital

This tutorial covers the concept of analog and digital signals, as they relate to electronics.

Hardware Overview

The RH sensor uses a laser trimmed, thermoset polymer capacitive sensing element with on-chip integrated signal conditioning. The sensing element’s multilayer construction provides excellent resistance to most application hazards such as condensation, dust, dirt, oils and common environmental chemicals.

Protective Tape Removal

The HIH-4030 comes with a protective tape on the cover (sensing face). This tape is kept in place during our soldering process here at SparkFun. When you receive your HIH-4030 Breakout, you’ll want to remove the protective tape.

HIH-4030 Tape Removal

Protective Tape Removal

Reference: Installation Instructions for the HIH-4030/4031 Humidity Sensors
Useful tool to aid in this process: ESD Safe Tweezers

  • Use proper Electrostatic Discharge (ESD) protection
  • Use finger cots to ensure that no foreign debris falls into the filter, sensor cover or die
  • Remove protective tape according to the diagram below
  • alt text

    Pinout

    The three pin breakouts on the HIH-4030 Breakout board make it easy to measure relative humidity (%RH) as an analog voltage.

    HIH-4030 Pinout

    PinDescription
    GNDGround
    OUTVoltage Output
    5VSupply Voltage (5V)

    Voltage applied to the supply pins should be within 4-5.8VDC, optimally at 5V, making it perfect to power with your 5V / GND connections on your microcontroller shield like an Arduino or SparkFun Redboard. The data pin can be connected to an analog input of an Arduino, XBee, RaspberryPi, or any other IO device. The HIH-4030 has a low-power design. The sensor will typically only consume about 200μA.

    Humidity Sensor Re-Conditioning

    Humidity Sensors make use of a conductive polymer to measure relative humidity. If that polymer gets too dry (or over-saturated) the sensor won't function properly, but that can be reversed.

    Any humidity sensors on our designs are put them through a re-conditioning procedure to ensure that they keep their factory calibration. If you expose your sensor to a really dry environment for a prolonged period of time (or saturate it in a very humid environment) you may have to run it through the same process.

    Hardware Hookup

    This product comes with the HIH-4030 soldered onto the breakout board. The pins of the 3-pin header are spaced by 0.1".

    alt text

    Before you can insert the HIH-4030 Breakout into a breadboard, you’ll need to solder either wires or a 3-pin header to the GND, OUT, and 5V on-board connections. If you plan on breadboarding, we recommend straight male headers. Here, right angle headers were used, which is another viable option.

    HIH-4030 Breakout and Breadboard

    Example Circuit with HIH-4030 Only

    With the HIH-4030 Breakout, all you need is three wires between your microcontroller and the breakout board: Power, Ground, and Analog Output. This is a simplified circuit that should only be used to get your Humidity Sensor up and running. Here is an example hookup diagram demonstrating how to connect the board up to a SparkFun RedBoard:

    Wiring Diagram HIH-4030

    Example Circuit with TMP102 Temperature Sensor

    Determining Relative Humidity (RH%) requires knowing an accurate temperature. The previous circuit example does not utilize this feature, therefore, it will be necessary to to use your HIH-4030 Breakout in conjunction with a Temperature Sensor. For this Hookup Guide, we have used the TMP102 Breakout.

    SparkFun Digital Temperature Sensor Breakout - TMP102

    SEN-11931
    5.9500$3.45
    7

    The TMP102 is a digital sensor that communicates over I2C, has a resolution of 0.0625°C, and is accurate up to 0.5°C. There is no on-board voltage regulator, so supplied voltage should be between 1.4 to 3.6V. Do not hook up the TMP102 VCC to 5V. You’ll want to use 3.3V on your Arduino or SparkFun RedBoard for this connection. As an additional resource, refer to the TMP102 datasheet.

    You'll notice from the figure below, found on page three of the HIH-4030 sensor datasheet, the recommended operating temperature is between -40 and 85 °C (or -40 and 185 °F). If the operating zone lies outside either the recommended temperature or humidity extreme, the sensor is only specified to be accurate for 50 hours or less.

    Operating Environment

    Since this is an I2C device, the connections you’ll be most concerned with is the SDA (Data) and SCL (Clock) pins on either an Arduino or SparkFun RedBoard. Here is an example hookup diagram demonstrating how to connect the HIH-4030 Breakout with a TMP102 Digital Temperature Sensor board up to a SparkFun RedBoard:

    Wiring Diagram HIH-4030 with TMP-102

    Click the image for a closer look.

    Using the SparkFun HIH-4030 Arduino Library

    We’ve written an Arduino library for the HIH-4030, which takes care of all your user specifications and calculating of formula found in the datasheet. Grab the most recent version of the library from our SparkFun_HIH4030_Arduino_Library GitHub repository:

    Download the SparkFun HIH-4030 Arduino Library

    If you need any help with the installation process, check out the How to Install an Arduino Library tutorial. If you download the library’s ZIP file, you can use Arduino’s “Add ZIP Library…” feature to install the source and example files.

    Adding Library

    Using the HIH4030_HumiditySensor_Example

    Once you’ve downloaded the library, open the HIH4030_HumiditySensor_Example by navigating to File>Examples>SparkFun Humidity Sensor Breakout - HIH4030>HIH4030_HumiditySensor_Example:

    Open Example Program

    You’ll also want to make sure your board and port are correctly set in the Arduino IDE window before uploading the code:

    Board, Port and Upload

    Once the upload is complete, you can click over to the Serial Monitor. Make sure the baud rate is set to 9600 bps, and you should begin to see the Tempearture, Sensor Voltage, Relative Humidity and True Relative Humidity scroll across the screen:

    Serial Monitor Output

    Customizing Settings in Code

    Initialization

    To begin, make sure you include the SparkFun_HIH4030.h library. If using a temperature sensor, you’ll need to include Wire.h the Arduino I2C library:

    language:c
    #include <SparkFunDS1307RTC.h>
    #include <Wire.h>

    Temperature Sensor Settings

    The code by default is using a static value for the temperature reading.

    language:c
    // Are You Using a Temperature Sensor? 1 = YES / 0 = NO
    int tempSensor = 0;

    You can change the temp variable from 25 degrees Celsius to any desired value to see how it affects the Relative Humidity (RH%).

    Static Temperature Value

    It’s important to remember that True Relative Humidity (RH%) requires a known temperature for accurate measurement. As an example, the previous section, Hardware Hookup, demonstrated how to wire both the SparkFun Humidity Sensor Breakout - HIH-4030 and Digital Temperature Sensor Breakout - TMP102. However, you can also use other Temperature Sensors available on the SparkFun storefront: One-Wire Ambient Temperature Sensor - MAX31820, Temperature Sensor - TMP36, One Wire Digital Temperature Sensor - DS18B20, SparkFun Infrared Temperature Breakout - TMP006.

    If you are utilizing a Temperature Sensor, you’ll want to modify the following code from the default 0 to a 1:

    alt text

    Humidity Sensor Settings

    Two things that need to be defined for the SparkFun_HIH4030 Library is the Analog I/O Pin the HIH-4030 Sensor OUT is connected to and the voltage being supplied to the HIH-4030 Sensor. If your setup reflects the Hardware Hookup section, you can leave the values as is.

    language:c
    // Analog IO Pin Connected to OUT
    #define HIH4030_OUT A0
    
    // Supply Voltage - Typically 5 V
    #define HIH4030_SUPPLY 5
    

    Looking Inside the SparkFun_HIH4030 Library

    vout( ) function

    Since the output of the HIH-4030 Humidity Sensor is nearly linear, the analogRead() function is used and mapped to the correct range. This is where the value you defined for the Supply Voltage in your HIH4030_HumiditySensor_Example code comes into play.

    language:cpp
    // Read value from the sensor and convert to voltage value
    float HIH4030::vout() {
        return (float)(analogRead(pin)) * supply / 1023;
    }

    getSensorRH( ) function

    From the HIH-4030 Datasheet, a Voltage output equation is given on page 2.

    VOUT Equation

    With the previous vout() function and defined supply voltage, sensor RH can be calculated.

    language:cpp
    // Convert sensor reading into Relative Humidity (RH%)
    //  using equation from Datasheet
    // VOUT = (VSUPPLY)(0.0062(SENSOR RH) + 0.16),
    //  typical at 25 degrees Celsius
    
    float HIH4030::getSensorRH() {
        return ((vout() / (.0062 * supply)) - 25.81);
    }
    

    getTrueRH( ) function

    The True Relative Humidity euqation is also given on page 2 of the HIH-4030 Datasheet which includes temperature compensation.

    True RH Equation

    Aforementioned, True Relative Humidity required a known temperature for accurate measurement. The getTrueRH(float temperature) function will take the value of either your static temperature or sensor measurement, whichever is applicable, and calculate True RH.

    language:cpp
    // Get True Relative Humidity (RH%) compensated
    //  with Static Temperature or Measured Temperature
    // TRUE RH = (SENSOR RH)/(1.0546 - 0.00216T), T in degrees Celsius
    
    float HIH4030::getTrueRH(float temperature) {
        return getSensorRH() / (1.0546 - (0.00216 * temperature));
    }
    

    Resources and Going Further

    For more on the HIH-4030 Humidity Sensor, check out the links below:

    Need some inspiration for your next project? Check out some of these related tutorials:

    Photon Remote Water Level Sensor

    Learn how to build a remote water level sensor for a water storage tank and how to automate a pump based off the readings!

    Weather Station Wirelessly Connected to Wunderground

    Build your own open source, official Wunderground weather station that updates every 10 seconds over Wifi via an Electric Imp.

    Humidity-sensing LED Flower

    How about that humidity? This tutorial shows how to add sensing capability to the 21st Century Fashion Kit's RGB flower project.

    Environmental Monitoring with the Tessel 2

    Build an air-conditioner monitoring device to collect environment information and store it in the cloud.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado


    Logging Data to Google Sheets with the Tessel 2

    $
    0
    0

    Logging Data to Google Sheets with the Tessel 2 a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t557

    Introduction

    My family just became the proud new owners of an upright piano. This piano was owned by my wife’s grandmother and is somewhat of a family heirloom. It comes with great emotional value, and it’s only natural that we want to take care of it. After moving the piano into our house (not an easy task), my wife made the important call to “the piano guy” to talk about tuning it, cleaning it and general care.

    piano

    I was sitting close by and overheard the mentions of “temperature swing” and “humidity range.” If either fell within a certain range, the piano would need to be placed in a certain spot in the room versus another. Upon hearing this, a smile crept across my face, recognizing the birth of a new project. In fact, my wife literally told the man over the phone, “Temperature range? My husband can take care of figuring that out for you, and we will let you know.” He is going to get more than he bargained for!

    Thus, I set about using the Johnny-Five Inventor’s Kit to log the temperature and humidity of the room.

    Logging is Never a Question of Why, but How!

    Collecting data in a reliable and useful way is always a challenge. When it comes to embedded electronics/computers, the challenge is not so much a matter of collecting a large volume of data as it is the challenge of storage size, formatting the data output and post processes.

    This tutorial will focus on collecting data using a Tessel 2 and a single sensor that comes in the Johnny-Five Inventor’s Kit to monitor and log the air temperature and humidity in the piano room in my house.

    As you will see in this project, managing data collection, formatting that data and processing it can be simplified by using Node.js and leveraging the huge community that supports it through its package manager called NPM.

    We will look at two different ways to log this data, format it and bring it into Google Sheets to be able to graph it and share it easily with others.

    More Than One Way to Skin a Cat

    As with any electronics project, there is more than one way to do this! We are going to look at two different approaches to accomplish the same task using the Tessel 2. The main difference between the two methods being whether or not you have a WiFi/network connection.

    This has been written as a “choose your own adventure” of sorts when it comes to the firmware for this project. One way is to use the file system and a USB drive; the other is to use an IoT service called IFTTT. Each script has its own section that will break down the code for you, and then we will tie up any loose ends.

    Internet-Connected Method

    IFTTT Logo

    If you have a connection to a the internat, either through WiFi or Ethernet, you can use the node module for If This Then That (IFTTT) to build an IFTTT recipe to send data to a Google Sheet using the Maker Channel. This is the preferred method if you are in a situation where you have network connection, as you will be able to view the data from your Google account in real time and see changes almost immediately.

    Local, Offline Method

    local version

    The second way to do the same thing but with a little more work on your part, is to set up the Tessel 2 to log the data to a USB mass storage device and then periodically pull the data from it and manually add it to a Google Sheet. This is obviously more work on your part, but in cases where there is poor or no network connection, it’s a great alternative.

    Hardware Overview

    Required Materials

    We designed this project so that you could build it from the Johnny-Five Inventors Kit, which includes everything you will need with the exception of a USB mass storage device. Almost everyone has a “thumb drive” laying around, and this is a perfect use for it. If you don’t have one on hand, we have added a microSD card and USB reader to the parts list below. Either will work just fine!

    If you don’t have a Johnny-Five Inventors Kit on hand, here is a wish list of parts so that you can buy them all separately.

    The Tessel 2

    !The Tessel 2 Development Board

    The Tessel 2 is an open-source development board. It runs JavaScript and supports npm, which means scripts to control it can be built with Node.js. It’s a platform for experimenting, tinkering, prototyping and producing embedded hardware, perfect for the Internet of Things.

    The BME280

    BME280 pic

    The SparkFun BME280 Atmospheric Sensor Breakout is an easy way to measure stuff about the atmosphere around you: pressure, humidity and air temperature. All of this is combined into a petite package, called a breakout board.

    The 3.3V breakout is power-efficient, using as little as 5µA (that’s 1/1000000 of an amp!) when idling and less than 1mA when it’s taking measurements.

    In this experiment you will work with the BME280 to read the temperature, pressure and humidity of the room as well as your altitude based off of the atmospheric pressure. Finally, you will use your BME280 as the heart of a web-based weather dashboard application.

    USB Thumb Drive

    thumb drive

    There isn’t much to be said about these little storage drives. You can find one pretty much anywhere. For the purposes of this project, we would recommend one that is smaller so that handling the project and fitting it into an enclosure isn’t cumbersome.

    Preflight Check

    If this is your first time using your Tessel 2 you will need to do a little setup first. Have no fear; it is relatively painless and shouldn’t take more than 20 minutes or so to install software and get you up and running! Check out the Getting Started with the Tessel 2 Guide to walk you through the process of:

    • Installing the required software to develop for the Tessel 2
    • Installing the T2-CLI tool
    • Setting up the Tessel 2
    • Creating a project directory (folder)
    • Running a blink script to make sure it is working

    Getting Started with the Tessel 2

    October 12, 2016

    Get your Tessel 2 up and running by blinking and LED, the Hello World of embedded electronics.

    Node.js Native Modules and NPM

    If you have had experience with the Tessel 2, then you know that it is programmed with JavaScript and the Johnny-Five framework to be able to control the Input/Output (I/O) on the board. If you have never programmed with JavaScript before or the Tessel 2, we highly recommend that you check out the Johnny-Five Inventor’s Kit Experiment Guide for a more in-depth explanation and exploration.

    To get you started with this specific project, let’s create a project directory as covered in the preflight check and install all of the needed node modules that we will use. We can do this through our console by using these commands:

    language:console
    mkdir loggerProject;
    cd loggerProject;
    npm init -y;
    npm install johnny-five tessel-io node-ifttt-maker;

    These commands do the following in order:

    1. Create a directory (folder) called loggerProject
    2. Change directory, or move into loggerProject
    3. Initiate an npm project within loggerProject that creates a package.json file.
    4. Install the needed libraries, which in this case are johnny-five, tessel-io and node-ifttt-maker using npm install. These will be placed in a directory called node_modules

    With your setup complete, you are ready to set out on your new adventures of logging data!

    Building the Circuit

    Despite your method for logging the data, your circuit will be the same, with the exception of adding a USB storage device to one of the USB ports on the Tessel 2 for the offline method.

    Build the BME280 Circuit

    alt text

    Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

    This circuit is faily simple. Attach the BME280 breakout board to the breadboard so that it spans the center notch. Connect the BME280’s SCL (clock) pin to Tessel’s Port A, Pin 0. Connect the SDA (data) pin to the Tessel’s Port A, Pin 1. Connect 3.3V to the Tessel’s 3.3V pin and GND to GND.

    Testing the BME280

    Before we move on to the larger project, let’s take a second to test the BME280 to make sure it’s up and running. From the command line, create a new file called bmeTest.js by typing the following command:

    touch bmeTest.js

    Open your favorite code editor, and navigate to your bmeTestjs file to edit it. Type—or copy and paste—the following JavaScript code into your bmeTest.js file:

    language:javascript
    var Tessel = require("tessel-io");
    var five = require("johnny-five");
    var board = new five.Board({
      io: new Tessel()
    });
    
    board.on("ready", () => {
      var monitor = new five.Multi({
        controller: "BME280"
      });
    
      monitor.on("change", function() {
        console.log("thermometer");
        console.log("  celsius      : ", this.thermometer.celsius);
        console.log("  fahrenheit   : ", this.thermometer.fahrenheit);
        console.log("  kelvin       : ", this.thermometer.kelvin);
        console.log("--------------------------------------");
    
        console.log("barometer");
        console.log("  pressure     : ", this.barometer.pressure);
        console.log("--------------------------------------");
    
        console.log("altimeter");
        console.log("  feet         : ", this.altimeter.feet);
        console.log("  meters       : ", this.altimeter.meters);
        console.log("--------------------------------------");
      });
    });

    Type—or copy and paste—the following into your terminal:

    t2 run bme.js

    What You Should See

    alt text

    This is going to print a lot of data to your console, very quickly—so quickly that you likely won’t be able to make sense of it! Go ahead and exit the program by typing Command-C or Control-C. This will stop the script so you can read the output.

    Code to Note

    Once the board has emitted the ready event, hardware inputs are ready for interaction, so the first thing that occurs is an instantiation of a Multi object. Multi objects represent two or more components, usually sensors, that are packaged together and exposed via a single register. Multi and IMU (Inertial Measurement Unit) boards that combine multiple movement sensors like accelerometers, gyroscopes, etc.) are very similar; the latter is used for non-motion-related packages.

    language:javascript
    var monitor = new five.Multi({
      controller: "BME280"
    });

    Now that we have a monitorMulti instance, the next thing to do is register an event handler to be invoked whenever changes are detected in the sensor readings:

    language:javascript
    monitor.on("change", function() {
      // ...
    });

    Within that handler, we’re logging all of the relevant data properties for this multicomponent package:

    language:javascript
    console.log("thermometer");
    console.log("  celsius      : ", this.thermometer.celsius);
    console.log("  fahrenheit   : ", this.thermometer.fahrenheit);
    console.log("  kelvin       : ", this.thermometer.kelvin);
    console.log("--------------------------------------");
    
    console.log("barometer");
    console.log("  pressure     : ", this.barometer.pressure);
    console.log("--------------------------------------");
    
    console.log("altimeter");
    console.log("  feet         : ", this.altimeter.feet);
    console.log("  meters       : ", this.altimeter.meters);
    console.log("--------------------------------------");

    … which is a lot of data and will likely overwhelm the terminal, so be ready to type Command-C or Control-C to end the program.

    OK, everything works! Let’s now explore how to log all of this data!

    Firmware: Logging Data with `fs`

    Node.js has a number of built in-modules to keep your project as modular and streamlined as possible. You can find the whole list of the modules available to you in the documentation for Node.js. Since Node is so modular, you still have to require even the modules that are included in the core itself.

    The module that we are going to put to good use for logging to the USB drive is the File System module, or fs for short. This module enables you to interact with, modify, add and remove files on your computer’s file system (in this case your Tessel’s).

    The Concept

    The functionality of this project can be explained as such. We want the Tessel 2 to do the following things:

    1. Create a .csv (comma separated value) file on the USB drive.
    2. Read the values from the sensors using Johnny-Five and store them locally as variables.
    3. Build a string that formats the values the way we would like them for easily importing into a spreadsheet.
    4. Append the .csv file with the logging string we created.
    5. Rinse (set the string back to “”) and repeat for the give data event frequency!

    First of all, let’s head over to your terminal. In your working project directory, create a new JavaScript file called usbLog.js by entering the following command:

    touch usbLog.js

    The Code

    You can now navigate to your new file in your text editor and copy and paste the following script into that file. Make sure you save after you have done that.

    language:javascript
    //require the file system module
    var fileSys = require('fs');
    //require the modules for hardware I/O
    var five = require('johnny-five');
    var t2 = require('tessel-io');
    
    //create a new board object with io set to Tessel
    var board = new five.Board({
      io: new t2()
    });
    
    //create a date object
    var date = new Date();
    //create a filePath string for location of USB drive.
    var filePath = "/mnt/dev/sda0/" + String(date.now())+ '.csv';
    //create a CSV header string to be added at the begining of the log.
    var headerString = "Date,Air Temperature(F),Relative Humidity(%),Soil Moisture"
    //create an empty logString
    var logString = "";
    //define the interval of logging in minutes, change this if you so choose.
    const interval= 5;
    //create a new file using the appendFileSync to keep things sychronous.
    //create the variables for data as globals
    var temp, humidity, moist;
    
    //create the csv file with given path and append the header
    fileSys.appendFileSync(filePath,headString,(error)=>{
      //if you get an error, log a message
      if(error){
         console.log('error setting up log file!');
      }
    });
    
    //when the board is ready...
    board.on('ready', ()=>{
      //create a new multi object called atmos for the BME280
      var atmos = new five.Multi({
        controller: 'BME280',
        freq: (interval*60000)
      });
    
      //when atmos gets 'data'...
      atmos.on('data', ()=>{
        //store temperature and humidity
        temp = this.thermometer.fahrenheit;
        humidity = this.hygometer.relativeHumidity;
    
        logString = date.toISOString()+','+temp+','+humidity+','+moisture+'\n'
      //append the log file with the logString
      fileSys.appendFileSync(filePath,logSting,(error)=>{
         //if error, log message
         if(error){
          console.log('error logging to file!');
        }
        //else reset the logString to blank
        else{
          logString = '';
        }
      });
      });
    
    });
    

    Save your script, and insert your USB Thumb drive into a USB port in your Tessel 2. We recommend using the top USB drive because there are a number of thumb drives that may be wide enough to block the micro USB port you need to power the board, but your USB may work in the bottom one just fine. It doesn’t change how anything functions.

    alt text

    Once you have inserted your USB thumb drive and saved your script as usbLog.js, go ahead and deploy your code to your Tessel by running the following command in your console:

    t2 run usbLog.js

    Let the script run for a while while putting your finger over the BME280.

    The Tessel will log values once every five minutes, so let it run for a good long while. Eat a cookie, read a magazine, lie back and relax while the Tessel does all of the work. Or you can change the logging interval for testing purposes.

    Once you can’t stand it anymore and you want to get your hands on your data, go ahead and remove the USB storage device from the Tessel, and insert it into a computer.

    alt text

    An external drive should become visible; go ahead and open it. You should be greeted with a single file on your device, which should have a name of a very long number with a file extension of .csv. Open the file, and it should contain your data in CSV format!

    alt text

    With that you are ready to import the data into your Google Sheets file, but let’s pause for a bit and dive into what makes this code work!

    Code to Note

    Before we move on to the Google Sheets portion of this project, let’s take a deeper look into the code and how this was accomplished using Node.js and Johnny-Five.

    language:javascript
    var fileSys = require('fs');

    Node.js is super modular; to do even simple things, many times you have to include native modules that come with Node.js. File System, or fs, is one of those modules. It is used any time you want to use other files in conjunture with your node project.

    language:javascript
    var five = require('johnny-five');
    var t2 = require('tessel-io');
    
    //create a new board object with io set to Tessel
    var board = new five.Board({
      io: new t2()
    });
    

    When using Johnny-Five with single board computers (SBCs) you have to install and require a secondary module for working with that specific SBC’s I/O pins. In this case we are working with the Tessel 2, so we need to require the tessel-io module that we installed during setup. Then, when we create a board object, we specify the io of the board as a new t2().

    language:javascript
    var date = new Date();

    If you have used any JavaScript before, you may be familiar with the Date object. We use it in this script to create a time stamp for our data, and even the log file name is based off of now() method, which retrieves the number of seconds since January 1, 1970, 00:00:00 UTC. Most importantly we use the toISOString() method to produce a user-friendly time and date stamp for our data-logging string.

    language:javascript
    fileSys.appendFileSync(filePath,headString,(error)=>{
      //if you get an error, log a message
      if(error){
         console.log('error setting up logging file!');
      }
    });

    To write data to the log file, we use the appendFileSync() method of the fs module. This takes two arguments: the first is the file path to the file you want to append (or add to), and the second is the data you want to append to the file as a string. You can find out more about the method and the differences between the synchronous and asynchronous versions of the method in the fs documentation.

    We use this method twice! The first time writes the .csv header to the file at the very beginning of the script. Later we use it inside of the setInterval() function to log the individual lines of data every five minutes.

    language:javascript
      //when atmos gets 'data'...
      atmos.on('data', ()=>{
        //store temperature and humidity
        temp = this.thermometer.fahrenheit;
        humidity = this.hygometer.relativeHumidity;
    
        logString = date.toISOString()+','+temp+','+humidity+','+moisture+'\n'
      //append the log file with the logString
      fileSys.appendFileSync(filePath,logSting,(error)=>{
         //if error, log message
         if(error){
          console.log('error logging to file!');
        }
        //else reset the logString to blank
        else{
          logString = '';
        }
      });
      });

    Each sensor object has an event attached to it. In this case we are using the ‘data’ event. This event happens at a given time interval, which is controlled by the freq option in the board setup. In this case we set freq: (interval*60000). So, every five minutes or 5*60000 milliseconds the ‘data’ event gets called. When the data event is received by the sensor object, the event is triggered, and we then store the sensor values in the variables temp and humidity.

    Every five minutes a new string gets built by concatenating the date string and the data points from the two variables, which are then terminated with a newline character (\n).

    The string is then appended to the file, and, if there is no error in the process, the logString is reset to a blank string. This is then repeated every five minutes.

    Getting the Data into Sheets

    Now we have data in not so user-friendly CSV format … now what? Google Sheets to the rescue! If you have been under a rock for the past 10 years and haven’t heard that Google has an online suite of office tools at your disposal, today is the day we rectify that problem. The spreadsheet program is called “Sheets.”

    If you don’t have a Google account, no problem. It’s easy to sign up for one, and it’s free! Once you are signed in to your Google account, click on the apps icon, which is the little grid of squares in the upper righthand corner. Select Sheets from that list.

    alt text

    From there, you will be greeted with a number of options for what to do in Sheets. You want to just create a blank sheet for now. Click on “blank” once in the program.

    alt text

    A new Sheets project will open. Select File > Import…. This will bring up a dialog box that you will need to use to navigate to your external USB drive and the .csv file that is on it. Select the file, and click Open.

    alt text

    alt text

    From there you will get a slew of options about how you would like to import the data. We actually preformatted the data when we collected it, so this is all done. Go ahead and click through this window.

    alt text

    Your data will now appear as a sheet as shown! Wahoo, data in a table!

    alt text

    From here, it is a few simple steps to building a graph.

    Using your cursor, select the Create Graph button, and it will bring up the graph options. You can select your graph type, and it will give you a preview of what it will look like. I selected a line graph:

    alt text

    Once you are happy with your graph selection, accept your graph. It will then show up in your sheet, where you can move it around and resize it.

    alt text

    With that you are done! You can do all sorts of further calculations and other graphs using Sheets. Or if there is something that you are missing and you’d prefer to use Microsoft Excel or another Office tool chain, feel free; they are all about as simple to import data into. The downside of doing this is that you have to make a new sheet or copy and paste data into this one every time you want to update it. This is where IFTTT comes into play!

    Firmware: Logging with IFTTT

    Now that you have been logging data locally and then physically transferring it to your computer and then into Google Sheets, it is now time to simplify the process using IFTTT and the Maker Channel.

    Maker Channel logo

    If you have never heard of If This Then That (IFTTT), it is a simplified software and web automation tool. It allows you, the user, to build what are called recipes, which consist of two channels, or services, and a trigger. Basically, as the name implies, if (this happens) then (do something). The things that happen or do something are different connected web apps such as Google Drive, Slack, Twitter and Facebook – or even your Android phone. IFTTT allows you to connect all of these services in a simple way to harness the web to do work for you!

    The Concept

    This project is going to use IFTTT to do a lot of the work that we physically had to do in the File System version of this project. We will connect the Tessel 2 and its data to a Google Sheet using the IFTTT Maker Channel to send the data to sheets and populate the sheet in real time. Let’s take a deeper dive into how this works!

    The IFTTT Maker Channel works through making web requests. Web requests are essentially a way for you to ask a server for information. We can use this to our advantage and make a statement through making a request. Let’s look at an example to make this a little clearer. Here is a web request URL used by the Maker Channel:

    https://maker.ifttt.com/trigger/{event}/with/key/hhpANc1sDCoGpQ0-DfnbR_6g2WKLxwKSYvZDIRVGz5I?value1=123&value2=hello&value3=world

    Let’s break this into chunks and make sense of it.

    The first part probably looks familiar to you: https://maker.ifttt.com/. This is the domain (ifttt) with a subdomain of maker. This is the structure of all websites. If you want to navigate to Google, you type www.google.com (google is the domain).

    The second part is a little trickier. It looks like this: /triger/{event}/with/key/. This is stating a category of the domain (trigger) and a subcategory, which is {event}, and other subcategories of /with/key. These are all used to categorize what is happening. Basically we are causing a trigger with a name of {event} followed by the key.

    The string of random numbers and letters is a private and unique key, the one used to start the trigger. It is assigned to you when you sign up for the Maker Channel. This allows for unique and safe events to be triggered without someone accidentally triggering someone else’s project.

    The final part of this puzzle is the query string ?value1=123&value2=hello&value3=world. A query string is the part of a URL that allows a request to look for specific data. Again, this is us making a statement through asking a question because we know what the server is looking for in terms of the questions asked. The Maker Channel allows us to send up to three different variables in this way, and they are named value1, value2 and value3. These values can be a string, a number, a Boolean state … as long as it is data, you can store it in one of these three buckets. The query string starts with a question mark (?), and each query value is separated by an ampersand (&).

    Phew, that is a lot to take in! The good thing is that IFTTT does a lot for us, and there is also a Node.js module to help us on the code side of things. Let’s build the recipe first!

    The IFTTT Recipe

    Open a new browser window, and navigate to https://ifttt.com.

    alt text

    If you haven’t signed up for IFTTT, you can do so at this point. Don’t worry; we will wait for you.

    Once you have signed up, you can start to build a recipe. You can start by clicking on the “Channels” menu button at the top of the page and then searching the channels for “Maker.”

    alt text

    When you find the Maker Channel, select it. You will end up on the landing page for the Maker Channel. To use the Maker Channel, you have to connect your IFTTT account to it. Cclick on the ‘Connect’ button.

    alt text

    Once your account is connected you will be assigned a key. This key will be really important as we start to use the Maker Channel. You can always come back to your account to copy and paste the key, but you can also copy and paste it into a text document for now.

    Now, let’s create a recipe! Click on the ‘Create Recipe’ Button, and you will be confronted with the fun ‘If This Then That’ interface. The ‘This’ is a hyperlink. Click on it.

    alt text

    Search for and find the Maker Channel again, and select it. You only have one option in terms of triggers for the Maker Channel, to make a web request. Select that trigger.

    alt text

    From here, you name your trigger. We named ours ‘DataLog’.

    alt text

    When you accept a name, you will then get to select the ‘That’ of your recipe.

    alt text

    Search for ‘Google Drive’ for your ‘That’ event (it should be one of a few options).

    alt text

    Unlike the Maker trigger, where you only had a single option, the That for Google Drive has a number of options. You want to select the ‘Add Row to Spreadsheet’ option.

    alt text

    Ok, we are almost done! This next step allows you to name your spreadsheet and do some formatting of what the different columns of data will be. We will make a slight modification to the standard format by removing the event name from the rows, as this would be redundant and useless information for this example.

    alt text

    With that, the recipe is complete, and you should now be looking at an overview page.

    alt text

    This page will be accessible to you any time you come back to your IFTTT account under your recipes. You can then modify it as needed later on. Bam! You are done with your first IFTTT recipe! Now, let’s write some code to put it to good use.

    The Code

    How are we going to integrate JavaScript with IFTTT?

    You may have guessed it – there is module for that!

    We will be using the node-ifttt-maker module to make it as easy as possible to make web requests from the Tessel 2. First thing, we have to install the module into our project directory. If you haven’t done so already, open up your terminal and navigate to your loggerProject directory. To install the module, type the following command:

    npm install node-ifttt-maker

    At this point, you don’t need to install any other modules, as we have already installed johnny-five and tessel-io with our preflight check. You can now create a script for this project by typing the following into the terminal prompt:

    touch iftttLog.js

    With the file created, go ahead and open it in your text editor and type – or copy and paste – the following code into the file:

    language:javascript
    var five = require('johnny-five');
    var t2 = require('tessel-io');
    
    var IFTTT = require('node-ifttt-maker');
    
    var ifttt = new IFTTT('<YOUR MAKER KEY>');
    
    var board = new five.Board({
      io: new t2()
    });
    
    var temp, humidity;
    const interval = 5;
    board.on('ready',()=>{
      var atmos = new five.Multi({
        controller: 'BME280',
        freq: (interval*60000)
      });
    
    
      atmos.on('data', ()=>{
        temp = this.thermometer.fahrenheit;
        humidity = this.hygometer.relativeHumidity;
    
        var reqInfo= {
          event: 'gardenLog',
          method: 'GET',
          params: {
              'value1': temp,
              'value2': humidity,
           }
        }
    
      ifttt.request(reqInfo, (error)=> {
          if (err) {
            console.log(error);
          }
          else {
            console.log('---OK---');
          }
        });
      });
    });

    Make sure you save this file!

    Open up your terminal window, and navigate to the project folder for this project to deploy the script to your Tessel 2. Type the following command to do so:

    t2 run iftttLog.js

    If everything is set up correctly, you should be greeted with the REPL prompt, and, in five minutes, you should get a ---OK--- logged. This should repeat every five minutes. Make dinner, sit back and crack open a cold one, or play a video game for a while to build up a few logs.

    While you are building up a body of data in the ethers of your Google Drive, let’s take a closer look at the code that you just ran.

    Code to Note

    language:javascript
    var IFTTT = require('node-ifttt-maker');
    var ifttt = new IFTTT('<YOUR MAKER KEY>');

    As with all Node.js modules, you need to require the node-ifttt-maker module. You then create an ifttt object of the IFTTT class, and you pass your maker key as a string to this. This is really nice because you only need to include your key once, and only once.

      language:javascript
      var reqInfo= {
      event: 'pianoLog',
      method: 'GET',
      params: {
          'value1': temp,
          'value2': humidity,
          }
       }

    The Johnny-Five code is all the same from the previous version of this project. The main difference between the two scripts is what happens in the atmos.on() method. In this script, we create an object that contains all of the IFTTT web request information. This includes the event name as a string (pianoLog) and the method for making the request (do not change this from GET). It also includes the three parameters we want to log as value1, value2 (You can pass up to 3 values using the IFTTT Maker channel, for this example with are only using 2). We define each of these as the two variables temp and humidity, and they will be updated with those variable values each time the data event is fired. Building the object in this way will keep the actual request method cleaner and allows for a more straightforward way of defining things.

      language:javascript
      ifttt.request(reqInfo, (error)=> {
          if (err) {
            console.log(error);
          }
          else {
            console.log('---OK---');
          }
      });

    The actual ifttt.request() method is pretty simple. You pass the reqInfo object that you just defined previously and then a callback that we use for error checking. If there is an error, it will log the error to the console, otherwise it logs ---OK--- to the console and the web request was successful!

    Viewing Your Data in Sheets

    You can now navigate to your Google Drive. In your Drive, you should now have a folder that is called IFTTT. Navigate to IFTTT, and open the Maker folder inside of that. You should now have a Sheets document named pianoLog or whatever you named your event.

    piano project

    Open your pianoLog sheet, and your logs should be visible in the spreadsheet similar to the following screen capture (with the exception of my notes where my kids decided to be smart and unplug the project):

    alt text

    You can now go through a similar process of graphing. This is similar to the USB drive method of logging in terms of graphing this data or using other analysis tools. Here is a the graph of my data over a few days of logging the data.

    alt text

    Final Touches

    There are a number of things still to cover in terms of deploying this project. Here are a few thoughts that we have found work well for the Tessel 2.

    Enclosures

    If you are going to put this project outside for any length of time, you will need some sort of weatherproof enclosure so that you don’t leave the Tessel and the circuits you built in the elements (nothing good will come of that).

    We have built a number of projects with the Tessel that use our Big Red Box enclosure. It has plenty of room, has a gasket edge and is weatherproof. It has plenty of space for the Tessel, a breadboard and batteries.

    redbox image

    If you are in a hurry, or if you are going to be leaving the project outside for a shorter period of time, a Ziploc bag or Tupperware container works really well as a makeshift enclosure.

    image of tupperware enclosure

    Powering Your Project

    Powering a remote project is always tricky and probably the most difficult hurdle to overcome. Your easiest way to power the project is from a 5V USB wall adapter plugged into an outdoor power outlet, if you have one nearby. This will give it a consistent power supply as long as there is power to the outlet.

    image of wall wart

    Your next option in terms of simplicity is a consumer USB LiPo rechargeable battery. These are becoming cheaper and cheaper these days, to the point where we find them as give-aways at events and in gift bags. The larger the battery in terms of milliamp hours, the better!

    image of battery

    Probably the most technical way of running this project long term would be to build a LiPo battery solar charging system with a 5V DC/DC converter, a sunny buddy and a good-sized LiPo battery and solar panel, but that may be for another day and another tutorial. ;)

    SparkFun Sunny Buddy - MPPT Solar Charger

    PRT-12885
    $24.95
    4
    Lithium Ion Battery - 6Ah

    PRT-13856
    $29.95
    4
    Solar Panel - 3.5W

    PRT-13782
    $39
    SparkFun DC/DC Converter Breakout

    BOB-09370
    $29.95
    3

    Resources and Going Further

    Exploring IFTTT

    Whether you stick with this project to log weather data indoors, or are leaving it out in the woods collecting data for your next biology course, we highly recommend exploring the different channels on IFTTT and playing around with different recipes. You might be surprised what you can accomplish by just exploring and playing around with different channels.


    For more Tessel fun, check out these other great SparkFun tutorials.

    Experiment Guide for the Johnny-Five Inventor's Kit

    Use the Tessel 2 and the Johnny Five Inventors kit to explore the world of JavaScript enabled hardware through 14 awesome experiments!

    ReconBot with the Tessel 2

    Build a robot with the Tessel 2 that you can control from a browser on your phone or laptop.

    Environmental Monitoring with the Tessel 2

    Build an air-conditioner monitoring device to collect environment information and store it in the cloud.

    Sunrise Machine with the Tessel 2

    Are you to sleepy to enjoy a sunrise on a brisk morning? Yeah...us too! No worries, with a Webcam, a Tessel 2 and a bit of code you can sleep in and catch the sunrise at your leisure with the Sunrise Machine.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    MicroView Hookup Guide

    $
    0
    0

    MicroView Hookup Guide a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t477

    Introduction

    The SparkFun MicroView is the first chip-size Arduino-compatible module that lets you see what your Arduino is thinking by using a built-in Organic Light-Emitting Diode (OLED) display. In the heart of MicroView, there is an ATMEL ATmega328P and a 64x48 pixel OLED display, together with other passive components that allow the MicroView to operate without any external components other than a power supply. It fits nicely into a breadboard to make prototyping easy. The MicroView also has a full-featured Arduino library to simplify programming the module.

    SparkFun MicroView - OLED Arduino Module

    DEV-12923
    $39.95
    34

    This guide will cover everything you need to know about the MicroView, including hardware information, quick-start experiments, library installation and usage, and advanced information such as making your own MicroView font.

    Required Materials

    The MicroView is a stand-alone system. However, you will need an external programmer to upload new code to the MicroView. The MicroView USB programmer is sold separately, so you can purchase one programmer while purchasing as many MicroView modules as you need. If you do not have one already, you will need a MicroView USB programmer to follow along with this tutorial.

    SparkFun MicroView - USB Programmer

    DEV-12924
    $14.95
    5

    In addition to the MicroView and the USB programmer, you will need a few basic electronic components. Here is a complete list of the parts used in this tutorial.

    Note that the USB extension cord is not necessary; the MicroView USB programmer can plug directly into a USB port. However, your USB port may be difficult to access, may be too tightly spaced for the programmer, or may result in the MicroView appearing upside down to you. In these instances, the USB extension cable comes in very handy. We carry both a 1.5-foot version and a 6-foot version.

    Suggested Reading

    If you have never worked with the Arduino development environment before or need a refresher, you may find the following links useful.

    Installing an Arduino Library

    How do I install a custom Arduino library? It's easy!

    What is an Arduino?

    What is this 'Arduino' thing anyway?

    Installing Arduino IDE

    A step-by-step guide to installing and testing the Arduino software on Windows, Mac, and Linux.

    How to Install FTDI Drivers

    How to install drivers for the FTDI Basic on Windows, Mac OS X, and Linux.

    MicroView Overview

    Let’s first familiarize ourselves with the MicroView and its pins. Below you’ll find a list of specifications as well as a graphical datasheet detailing the function(s) of each pin.

    microview

    Hardware Specifications

    • Input Voltage: 3.3VDC–16VDC
    • Display: 64x48 OLED Display
    • Microcontroller: ATmega328P
    • Operating Voltage: 5V
    • Digital I/O Pins: 12 (of which 3 provide PWM output)
    • Analog Input Pins: 6
    • Flash Memory: 32KB
    • SRAM: 2KB
    • EEPROM: 1KB
    • Clock Speed: 16MHz

    Pin Configuration

    The MicroView has 16 “physical pins” that map to corresponding “Arduino pins” that can be referenced from within your Arduino sketch. For example, physical Pin 2 maps to the Arduino’s Analog Pin A5.

    pinout

    Pinout of MicroView on its side. The top of the MicroView is on the right. (Click image for closer look.)

    The pin numbering for the MicroView increments as you move counter-clockwise.

    The MicroView’s physical Pin 1 is denoted by a dot on the underside of the MicroView.

    alt text

    For more details on each pin’s function, please refer to the ATmega328P Datasheet.

    Quick Start Tutorials

    The MicroView comes with preinstalled code to get you learning right out of the box without having to do any programming. Using just a few components, you can learn the ins and outs of the MicroView.

    Setting Up Your MicroView

    Identify Pin 1 of MicroView based on the following diagram, or refer back to the MicroView Overview section.

    alt text

    In this guide, when there is a reference for Pin X of MicroView, it is referring to the above diagram’s pin number. For example, connect Pin 5 and Pin 8 of the MicroView.

    First-Time Electronics Users

    If this is your first time experimenting with electronics, you may want to read these other guides first.

    How to Use a Breadboard

    Welcome to the wonderful world of breadboards. Here we will learn what a breadboard is and how to use one to build your very first circuit.

    Resistors

    A tutorial on all things resistors. What is a resistor, how do they behave in parallel/series, decoding the resistor color codes, and resistor applications.

    Light-Emitting Diodes (LEDs)

    Learn the basics about LEDs as well as some more advanced topics to help you calculate requirements for projects containing many LEDs.

    Polarity

    An introduction to polarity in electronic components. Discover what polarity is, which parts have it, and how to identify it.

    MicroView with USB Programmer

    The quickest way to get started is to use the USB programmer.

    Insert the MicroView to the USB programmer. Then connect the female end of the USB extension cable to the factory USB programmer.

    alt text

    Note that it is much easier to connect a USB extension cable if the MicroView is inserted into the end of the breadboard.

    Connect the male end of the USB extension cable to the computer. The MicroView will power on, and the demo will start.

    MicroView without USB Programmer

    If you would like to use the MicroView without the USB Programmer, you will need the following (please note that the 9V battery and snap connector will need to be purchased separately):

    Connect the required parts based on the diagram below. Plug in the battery connectors last. Once plugged in, the 9V battery will power the MicroView through the VIN pin (PIN 1).

    alt text

    As soon as the MicroView is powered, the demo will start.

    Learn How to Use MicroView

    The MicroView comes pre-programmed with a few simple built-in tutorials to help you get use to inserting jumper wires, resistors and an LED. Skip these tutorials if you are already familiar with them. They will begin after the visual demo.

    Note: The following examples are based on MicroView without the USB Programmer, if you have the USB Programmer, please ignore the battery, red jumper and black jumper. The MicroView gets its power supply from the USB Programmer via the USB cable connected to the computer.

    Simple Tutorial 1

    Follow the instruction displayed on the MicroView, and connect PIN 5 and PIN 8 of the MicroView with a jumper using the following diagram as reference:

    alt text

    Once you have successfully connected PIN 5 and PIN 8 of the MicroView, a “Well done!” message will be displayed. To proceed to the next simple tutorial, remove the jumper.

    Simple Tutorial 2

    Follow the instruction displayed on the MicroView, and connect PIN 3 and PIN 8 of the MicroView with a jumper using the following diagram as reference:

    alt text

    Once you have successfully connected PIN 3 and PIN 8 of the MicroView, a “Well done!” message will be displayed. To proceed to the next simple tutorial, remove the jumper.

    Simple Tutorial 3

    Follow the instruction displayed on the MicroView, and connect PIN 2 and PIN 8 of the MicroView with a jumper using the following diagram as reference:

    alt text

    Once you have successfully connected PIN 2 and PIN 8 of the MicroView, a “Well done!” message will be displayed. To proceed to the next simple tutorial, remove the jumper.

    Simple Tutorial 4

    Follow the instruction displayed on the MicroView, and connect PIN 4 and PIN 8 of the MicroView with a 330&ohm; resistor using the following diagram as reference:

    alt text

    Once you have successfully connected PIN 4 and PIN 8 of the MicroView with the resistor, a “Well done!” message will be displayed. To proceed to the next simple tutorial, remove the resistor.

    Simple Tutorial 5

    Follow the instruction displayed on the MicroView, and connect PIN 4 and PIN 8 of the MicroView with a 10K&ohm; resistor using the following diagram as reference:

    alt text

    Once you have successfully connected PIN 4 and PIN 8 of the MicroView with the resistor, a “Well done!” message will be displayed. To proceed to the next simple tutorial, remove the resistor.

    Simple Tutorial 6

    Follow the instruction displayed on the MicroView, connect PIN 5 and PIN 8 of the MicroView with a 330&ohm; resistor using the following diagram as reference:

    alt text

    With the resistor still at the same place, insert an LED with both of the pins at PIN 4 and PIN 5 of MicroView respectively using the following diagram as reference.

    alt text

    Note: LEDs are polarized components. Make sure you insert the LED in the correct orientation.

    The MicroView is able to detect if the LED is inserted with the correct polarity, and it will begin blinking the LED.

    If the LED does not blink, remove the LED and turn the pins the other way round and connect them to PIN 4 and PIN 5 of the MicroView.

    With that, you are now ready to upload code and begin building the experiments in this guide.


    If you would like to load the Demo Sketch back on to the MicroView after you have uploaded any other code, you can find the MicroViewDemo.ino sketch in the MicroView Library Examples.

    demo

    MicroView Library Installation

    The following section will cover all of the instructions to install the MicroView library and get started using the MicroView with the Arduino IDE.

    In order to get your MicroView up and running, there a few easy steps you will need to follow:

    1. Download the FTDI drivers
    2. Install Arduino software and MicroView library
    3. Select the right board
    4. Run your first sketch

    Driver Installation

    If you have never used an Arduino or Arduino-compatible device on your computer before, you’ll likely need to install the drivers for the FTDI chip located on the MicroView USB programmer board. If you have never installed an FTDI driver before, please visit our FTDI driver installation tutorial. Once successfully installed, your MicroView should show up as a valid COM port in the Arduino IDE under Tools -> Ports.

    On a Mac or Linux machine, it will appear as /dev/cu.usbserialXXXXXX, where the X’s are some specific characters and numbers.


    On Windows, it will appear as COMXX, where the X’s are a specific number.

    Once you have finished the FTDI driver installation, you will need to prepare your MicroView to be inserted into the computer’s USB port.

    If you’re using the USB programmer, insert the MicroView into the USB programmer now. Be sure to align Pin 1 of the MicroView with Pin 1 of the USB programmer. Once you have inserted the MicroView into the USB programmer, you can insert the USB programmer into the USB port of the computer as pictured below. If your computer does not have a right-sided USB port, please use a USB Cable Extension to extend the USB port to the front so that you can easily work with the MicroView.

    alt text


    As an alternative to the USB programmer, you can use a 5V FTDI Basic breakout or 5V FTDI cable instead. Connect the FTDI Basic breakout board as shown below, and you are ready to go.

    alt text

    Install Arduino IDE and the MicroView Library

    If you have not installed the Arduino IDE already, now is the time to do so. Visit our Installing Arduino IDE tutorial for detailed instructions.

    Download the library using the Arduino Library Manager (found in all versions of the Arduino IDE from v1.6.4 and on).

    Click Sketch -> Include Library -> Manger Libraries to open the Library Manger. Once open, type “microview” in the search field. Install the SparkFun MicroView library by clicking on the library and then clicking the install button. Once installed, there should be a blue “installed” indicator next to the library.

    Library Manger

    You should now be able to find all the MicroView examples in your Arduino IDE sketchbook.

    examples

    Board Selection

    Once the Arduino IDE is up and running, you’ll need to select the correct board. Luckily, the MicroView is supported as an Arduino Uno variant, meaning no extra .brd files need to be installed to use the MicroView. Select Arduino Uno under Tools -> Boards.

    board selection


    In the Arduino IDE under Tools -> Ports, select the correct COM port. This is the port that was found in the Driver Installation section.

    alt text


    For advanced users who like to see MicroView as a board by itself in the IDE, add the following board definition to the boards.txt file. Depending on your setup, the boards.txt file is usually located in the arduino-version\hardware\arduino folder. Replace arduino-version with the right folder name for the Arduino version installed in your computer.

    uview.upload.tool=avrdude
    uview.bootloader.tool=avrdude
    uview.name=MicroView
    uview.upload.protocol=arduino
    uview.upload.maximum_size=32256
    uview.upload.speed=115200
    uview.bootloader.low_fuses=0xff
    uview.bootloader.high_fuses=0xde
    uview.bootloader.extended_fuses=0x05
    uview.bootloader.path=optiboot
    uview.bootloader.file=optiboot_atmega328.hex
    uview.bootloader.unlock_bits=0x3F
    uview.bootloader.lock_bits=0x0F
    uview.build.mcu=atmega328p
    uview.build.f_cpu=16000000L
    uview.build.core=arduino
    uview.build.variant=standard

    With the drivers and library installed and the correct settings selected in the Arduino IDE, it’s time to run our first program on the MicroView. The “Hello, World” sketch in the next section will be the first code we upload to the MicroView.

    Example 1 - Hello, World!

    The “Hello, World” sketch is common for programming of all types. For most embedded electronics, blinking an LED is the equivalent of printing out a “Hello, World” string. However, since the MicroView has its own display, we can actually print “Hello, World” to the screen as our first program.

    Copy the following code, paste it into the Arduino IDE and click upload. Alternatively, you can open the HelloWorld sketch found under File -> Examples -> SparkFun MicroView -> Learning Kit -> HelloWorld.

    language:c
    #include <MicroView.h>
    
    void setup() {
        uView.begin();              // start MicroView
        uView.clear(PAGE);          // clear page
        uView.print("Hello, World!");   // display string
        uView.display();
    }
    
    void loop () {}
    

    Once uploaded, you should see “Hello, World” print out on the OLED screen.

    Congratulations! You just uploaded your first MicroView sketch!

    Let’s see what else we can program.

    Example 2 - Basic Drawing

    In this example, we’re going to try some basic drawing. This sketch demonstrates the MicroView’s many drawing functions, including pixels, lines, circles and rectangles.

    It also introduces the setCursor() function, which allows you to move the cursor and print text or draw shapes at different locations other than the origin (0,0).

    Copy the following code, paste it into the Arduino IDE and click upload.

    language:c
    #include <MicroView.h>
    
    void setup() {
        uView.begin();
        uView.clear(PAGE);      // clear the page buffer
    }
    
    void loop() {
        uView.line(0,0,64,48);
        uView.circle(32,24,10);
        uView.rect(10,10,20,20);
        uView.pixel(50,5);
        uView.setCursor(0,40);
        uView.print(" MicroView");
        uView.display();        // display current page buffer
    }

    Once uploaded, you should see various images appear on the display.

    Check out the MicroView Class Reference page for more information on drawing.

    Example 3 - Widgets

    This example introduces one of the MicroView’s most powerful programming tools: the widget. This sketch uses both the MicroViewSlider and the MicroViewGauge. These widgets are useful for displaying information from sensors, timers or other hardware, such as buttons or knobs.

    Copy the following code, paste it into the Arduino IDE and click upload.

    language:c
    #include <MicroView.h>
    
    MicroViewWidget *widget,*widget2;
    
    void setup() {
        uView.begin();
        uView.clear(PAGE);
        widget= new MicroViewGauge(32,30,0,100);// draw Gauge widget at x=32,y=30,min=0, max=100
        widget2= new MicroViewSlider(0,0,0,100);// draw Slider widget at x=0,y=0,min=0, max=100
    }
    
    void loop() {
        for(int i=0; i<=100;i++) {
            widget->setValue(i);    // give a value to widget
            widget2->setValue(i);
            uView.display();        // display current page buffer
        }
    }

    Once uploaded, you should see a slider widget and a gauge widget run through the values 0–100 in a repeated loop.

    Check out the MicroView Class Reference page for more information on widgets.

    Example 4 - Drawing Bitmaps

    This last example shows how to draw bitmap images to the MicroView. This is useful for creating splash screens of company logos, making sprites or just creating fun graphics for displaying information.

    Before we can call the drawBitmap() function, we first need an image to draw. Remember, the screen resolution on the MicroView is 64x48 pixels, so images larger than that will not display correctly. To get a correctly sized image, there are a few methods:

    1. Create a blank image in your favorite drawing program (Inkscape, Photoshop, Paint, etc.), setting the canvas size to 64x48 pixels. You can then draw your image by hand.
    2. Find an appropriately sized image on the Internet.
    3. Use a program to take an image and convert it to a bitmap.

    Detailed instruction on how to make bitmap images is beyond the scope of this tutorial.

    Once you have a bitmap, it’s time to convert it into an array that the MicroView can understand. You can use programs such as LCD Assitant (Windows only) or this homebrew conversion program (any OS that runs processing), created by SparkFun customer George Beckstein to convert your image into an array. With your array created, paste it into your code. Be sure to name it appropriately. Then call your array inside the drawBitmap() function.

    language:c
    #include <MicroView.h>
    
    
    //------------------------------------------------------------------------------
    // File generated by LCD Assistant
    // http://en.radzio.dxp.pl/bitmap_converter/
    //------------------------------------------------------------------------------
    //This is the array that holds the Bitmap image. The easiest way to convert a bmp
    //to an array is to use the LCD Assistant linked above.
    uint8_t bender [] = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF, 0x5F, 0x5F, 0x5F, 0x5F,
    0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
    0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F,
    0x5F, 0xDF, 0xBF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xF9, 0xFE, 0x07, 0x01, 0x00, 0x00, 0xF8, 0xFE, 0xFF,
    0xFF, 0xFF, 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
    0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8,
    0x00, 0x00, 0x01, 0x07, 0xFE, 0xF9, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF9, 0xE7, 0xDC, 0xB0, 0xA0, 0x40, 0x41, 0x47, 0x4F,
    0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x4F, 0x47, 0x43, 0x40, 0x40, 0x40, 0x40,
    0x43, 0x47, 0x4F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x4F, 0x47, 0x43, 0x40,
    0x40, 0xA0, 0xB0, 0xDE, 0xE7, 0xF9, 0xFE, 0x1F, 0x0F, 0x07, 0x73, 0x79, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,
    0xBF, 0x5F, 0xEF, 0x0F, 0xEF, 0xEF, 0xDF, 0xDF, 0x1F, 0xDF, 0xDF, 0xDF, 0xDF, 0x1F, 0xDF, 0xDF,
    0xDF, 0xDF, 0xDF, 0x1F, 0xDF, 0xDF, 0xDF, 0xEF, 0x0F, 0xEF, 0xDF, 0xBF, 0x7F, 0xFF, 0xFF, 0xFF,
    0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xBE, 0x9C, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
    0xB7, 0x6F, 0xEE, 0x00, 0xDE, 0xDE, 0xDE, 0xDD, 0x00, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0xDD, 0xDD,
    0xDD, 0xC5, 0xC1, 0x00, 0xC9, 0xC5, 0xC1, 0x01, 0xC8, 0xC4, 0x42, 0x80, 0xC0, 0xE8, 0xE4, 0xE2,
    0xE0, 0xE0, 0xEF, 0xEF, 0xE6, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFB, 0xF8, 0xFB, 0xFB, 0xFB, 0xFB, 0xF8, 0xFB, 0xFB,
    0xFB, 0xFB, 0xFB, 0xF8, 0xFB, 0xFD, 0xFD, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
    };
    
    
    void setup() {
        uView.begin();
        uView.clear(PAGE);
    
    
        uView.drawBitmap(bender);
        uView.display();
    }
    
    void loop() {
    }
    

    Once this is uploaded, you should be greeted by a familiar fictional character.


    There are several other example sketches included with the MicroView library. Try loading some of these other examples and figuring out what the code is doing.

    demo

    OLED Memory Map

    This section goes into more detail about how the OLED screen functions and how the MicroView library works with the screen’s controller. Read on to get a better understanding of how the MicroView prints and draws to the OLED screen.


    The SSD1306 is the controller built into the MicroView’s OLED display. It has flexible yet complex segment and common drivers. Vast knowledge on memory addressing is required in order to use the SSD1306 controller.

    MicroView’s library was written to hide away the complexities of the SSD1306 controller so that users can issue simple commands to control the display. Although the SSD1306 has a built-in RAM (memory) for the screen, when connected using the SPI method, the ATmega328P is not able to read the RAM (memory) of the SSD1306. Therefore, the software will not be able to manipulate the screen buffer to perform mathematical operations.

    MicroView’s library overcomes this by allocating 384 bytes ( (64x48)/8 bits) of memory from ATmega328P as buffer. The library can now manipulate the screen buffer and then perform a bulk transfer from the ATmega328P’s memory to the internal memory of the SSD1306 controller.

    The 384 bytes of screen buffer are declared in MicroView’s library as

    language:c
    static uint8_t screenmemory [] = {.total 384 bytes of data..};

    and are arranged in a linear form representing the following 64x48 pixel coordinate system.

    microview coordinates

    Based on the above illustration, for example, if a user wished to plot a pixel at the position of the black dot, where X=10 and Y=2, the user would issue the following command:

    language:c
    uView.pixel(10,2);

    This command would then calculate the exact location of the screen buffer and set a BIT in the corresponding BYTE to the X,Y position.

    memory map

    Diagram showing how a linear screen buffer in the ATmega328P aligns with the OLED pixels.

    data bits

    Diagram showing the BITs in a BYTE of the screen buffer corresponding to the OLED’s X,Y position.

    Based on the above illustration, a pixel turned on at X=2 and Y=3 means BYTE 2 of the screen buffer has data of 0x08 (hex).

    Two pixels at X=2,Y=3 and X=2,Y=2 turned on means BYTE 2 of the screen buffer has data of 0x0c (hex).

    The following C code shows a pixel-by-pixel way to draw a straight line of 5 pixels starting from 10,2 to 10,6.

    language:c
    uView.pixel(10,2);
    uView.pixel(10,3);
    uView.pixel(10,4);
    uView.pixel(10,5);
    uView.pixel(10,6);

    The MicroView library allows you to draw lines by specifying the start and end coordinates. The above line could be drawn with this simple one-line command:

    language:c
    uView.line(10,2,10,6);

    In order for the library to perform extremely fast mathematical operations on the screen buffer (more than 100 frames per second), calls to the drawing functions within the MicroView library do not immediately transfer the contents of screen buffer to the SSD1306 controller. A display() command is required to instruct the library to perform the bulk transfer from the screen buffer to the SSD1306 controller:

    language:c
    uView.display();

    This function takes the whole screen buffer in the ATmega328P and transfers it (via SPI bus, programmed at 8Mhz) to the internal memory of the SSD1306. As soon as the memory is being transferred, the pixels corresponding to the screen buffer will show up on the OLED display.

    Creating Fonts for MicroView

    Though there are several different fonts that come programmed into the MicroView, you have the option to create your own fonts! Read on to find out how to do so.


    In the OLED Memory Map section, we covered how the MicroView library allocates 384 bytes of RAM as screen buffer from ATmega328P to perform graphic operations before transferring this block of memory to the SSD1306 OLED controller’s memory. The following diagram shows how two 5x8 pixel characters are drawn on the screen buffer.

    5x8 font mapping

    From the diagram, the “O” character appeared on ROW0, and took up 5 bytes of RAM from the screen buffer in the following order:

    BYTE0 = 0x7e
    BYTE1 = 0x81
    BYTE2 = 0x81
    BYTE3 = 0x81
    BYTE4 = 0x7e

    Character “A,” which was shown on ROW1, took up 5 bytes of RAM from the screen buffer in the following order:

    BYTE64 = 0xfc
    BYTE65 = 0x22
    BYTE66 = 0x21
    BYTE67 = 0x22
    BYTE68 = 0xfc

    A 8x16 font will take up 16 bytes of RAM from the screen buffer as shown in the next diagram:

    8x16 font mapping

    With the 8x16 font using RAM from screen buffer’s ROW0 and ROW1, the data of the above diagram will occupy the screen buffer’s BYTE0 – BYTE7 and BYTE64 – BYTE71.

    BYTE0 = 0xf8
    BYTE1 = 0xfc
    BYTE2 = 0x06
    BYTE3 = 0x03
    BYTE4 = 0x03
    BYTE5 = 0x06
    BYTE6 = 0xfc
    BYTE7 = 0xf8
    BYTE64 = 0xff
    BYTE65 = 0xff
    BYTE66 = 0x06
    BYTE67 = 0x06
    BYTE68 = 0x06
    BYTE69 = 0x06
    BYTE70 = 0xff
    BYTE71 = 0xff

    Manually plotting fonts and text is very tedious! It’s much easier to use the font-printing functions within the MicroView library. Displaying text in MicroView is as simple as: uView.print("Hello");

    Although MicroView’s library includes four different types of font, these fonts might not suit your needs. By following these steps, you can make your own fonts and include them within the MicroView library:

    1. Convert fonts to bitmap.
    2. Generate font source file from bitmap.
    3. Add font source file to MicroView library.

    Converting Fonts to Bitmap

    Once we understand how a character is being mapped to the MicroView’s screen buffer, we can choose to manually draw a font to the screen buffer or, alternatively, we can use software to convert a computer’s font to bitmap and then convert the bitmap into C char definition used by the MicroView library.

    We have had good results using Codehead’s Bitmap Font Generator to convert a font into a bitmap. If you have had success with using other tools, please let us know, and we’ll update this article.

    Codehead_Bitmap_Font_Generator

    Let’s quickly run through a few simple steps to convert a computer’s font into a bitmap. Assuming we need the numbers 0 to 9 of the Courier font in 12x24 pixels, the following steps will generate the required bitmap:

    1. Select “Courier” from the Font Details dropdown combo box.
    2. Enter 48 as the Cell Height.
    3. Enter 12 as the Cell Width.
    4. Enter 128x32 as the Image Size (this Image Size need to be larger than 12x24x10(number of characters) ).
    5. Enter 48 as the Start Character (48 ASCII code is the number 0).
    6. Enter 200% as the Zoom.

    Codehead_Too_Much_Space

    From the generated result, it is clear that there is too much space on the left of the numbers and the glyphs are not taking full advantage of the 12x48 pixel cells.

    Let’s further improve the font:

    • Enter or slowly increase Font Height to a suitable value—in this case, 26
    • Adjust the Position (X,Y) using the arrow button with option “Adjust All” selected (in this case, X=-4, Y=-1)

    After the adjustment, we should see the following result:

    Codehead_Center_Cell

    This result is almost perfect except there is still empty space on the right of the “9” glyph and at the bottom of all the numbers. We can’t further improve the font spacing in Codehead Font Generator because it doesn’t allow custom image sizes, so we’ll correct the font in an image editor later.

    Click File, then Export Bitmap (BMP), save the file as 12x24Font.bmp.

    Using an image editor like Photoshop or GIMP, open the 12x24Font.bmp file, then make a selection to crop a 120x24 frame from the image.

    Codehead_Crop

    If you want a WHITE text on BLACK background, you will need to INVERT the color now.

    Save the image and then proceed to next step. You can also save the hassle by downloading the 12x24Font.bmp already prepared by us.

    You have now successfully created a customized bitmap font!

    Generating Font Source File from Bitmap

    In order to convert the font from bitmap to C char definition, we will be using LCD Assistant. Run LCD Assistant and load the 12x24Font.bmp file previously saved.

    LCD_Assistant

    Make sure that following options are correct:

    • Picture preview is the right bitmap.
    • Byte Orientation has Vertical selected.
    • Width is 120, and Height is 24.
    • Include Size not selected.
    • Size Endianness has Little selected.
    • Pixels/byte is 8.
    • Table name is 12x14Font (can be any name).

    Once all the options are correctly selected, click File, then save the output and type in the filename as 12x24Font.h.

    Using a text file editor, open 12x24Font.h.

    Locate

    language:c
    const unsigned char 12x24Font [] = {

    and replace with

    language:c
    #ifndef FONT12X24_H
    #define FONT12X24_H
    #include <avr/pgmspace.h>
    static const unsigned char font12x24 [] PROGMEM = {
    // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
        12,24,48,10,1,20,

    FONT MAP WIDTH is basically the WIDTH of the BITMAP file used to generate the fonts. In this situation, the WIDTH of the BITMAP file is 120. So the HIGH number is 1, and the LOW number is 20.

    Then replace

    language:c
    };

    with

    language:c
    };
    #endif

    You should get the following result:

    language:c
    //------------------------------------------------------------------------------
    // File generated by LCD Assistant
    // http://en.radzio.dxp.pl/bitmap_converter/
    //------------------------------------------------------------------------------
    
    #ifndef FONT12X24_H
    #define FONT12X24_H
    #include <avr/pgmspace.h>
    static const unsigned char font12x24 [] PROGMEM = {
        // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
        12,24,48,10,1,20,
        0x1F, 0x1F, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x1F, 0x1F, 0xFF, 0xFF, 0x9F, 0x9F, 0x9F, 0x9F,
        0x07, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x9F, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
        0x1F, 0x1F, 0xFF, 0xFF, 0x9F, 0x9F, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x1F, 0x1F, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x07, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x07, 0xE7, 0xE7,
        0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0x7F, 0x7F, 0x9F, 0x9F, 0xE7, 0xE7, 0xE7, 0xE7,
        0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x87, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x07, 0x07, 0xFF, 0xFF,
        0x1F, 0x1F, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x1F, 0x1F, 0xFF, 0xFF, 0x1F, 0x1F, 0xE7, 0xE7,
        0xE7, 0xE7, 0xE7, 0xE7, 0x1F, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0x7F, 0x7F, 0x9F, 0x9F, 0xE7, 0xE7, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xE7, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0xFF, 0xFF, 0x1F, 0x1F, 0x61, 0x61, 0x7E, 0x7E, 0x00, 0x00,
        0x7F, 0x7F, 0xFF, 0xFF, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x1F, 0x1F, 0xFF, 0xFF,
        0x00, 0x00, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x1F, 0x1F, 0xE1, 0xE1, 0xFE, 0xFE, 0xFF, 0xFF, 0x18, 0x18, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
        0x18, 0x18, 0xFF, 0xFF, 0xF8, 0xF8, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x00, 0x00, 0xFF, 0xFF,
        0xF8, 0xF8, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xF8, 0xF8, 0xFF, 0xFF, 0xE7, 0xE7, 0xE7, 0xE7,
        0xE0, 0xE0, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xE1, 0xE1, 0xE6, 0xE6, 0xE7, 0xE7, 0xE7, 0xE7,
        0xE7, 0xE7, 0xFF, 0xFF, 0xF9, 0xF9, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xF8, 0xF8, 0xFF, 0xFF,
        0xFE, 0xFE, 0xFE, 0xFE, 0xE6, 0xE6, 0xE0, 0xE0, 0xE6, 0xE6, 0xFF, 0xFF, 0xF9, 0xF9, 0xE7, 0xE7,
        0xE7, 0xE7, 0xE7, 0xE7, 0xF8, 0xF8, 0xFF, 0xFF, 0xF8, 0xF8, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7,
        0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xE1, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xF8, 0xF8, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7,
        0xE7, 0xE7, 0xF9, 0xF9, 0xFE, 0xFE, 0xFF, 0xFF,
    };
    #endif

    You have now successfully converted the bitmap font to a C header file!

    Adding the Font Source File to MicroView Library

    Move the edited 12x24Font.h file to MicroView’s library folder. You should be able to see the 12x24Font.h in the same folder as the rest of the MicroView’s files.

    Move_Font_To_Library

    Using a text file editor, open MicroView.cpp, and perform the following steps:

    Locate

    language:c
    // Add header of the fonts here.  Remove as many as possible to conserve FLASH memory.

    Add after this line

    language:c
    #include <12x24Font.h>

    Locate

    language:c
    // Change the total fonts included
    #define TOTALFONTS      7

    Change to

    language:c
    // Change the total fonts included
    #define TOTALFONTS      8

    Locate

    language:c
    const unsigned char *MicroView::fontsPointer[]={
        font5x7
        ,font8x16
        ,sevensegment
        ,fontlargenumber
        ,space01
        ,space02
        ,space03
    };

    Change to

    language:c
    const unsigned char *MicroView::fontsPointer[]={
        font5x7
        ,font8x16
        ,sevensegment
        ,fontlargenumber
        ,space01
        ,space02
        ,space03
        ,font12x24
    };

    The font that we have just added is at the 7th position starting from position 0 (font5x7) in the MicroView::fontsPointer array; therefore, the new font is now fontType 7. Save MicroView.cpp once you have made your changes.

    Run the following sketch to test your new font:

    language:c
    #include <MicroView.h>
    
    void setup() {
      uView.begin();
      uView.clear(PAGE);
      uView.setFontType(7);
      uView.print("1234");
      uView.display();
    }
    
    void loop () {
    }
    

    You have now successfully hacked MicroView’s library to add your own custom font!

    MicroView Class Reference

    Below you will find a complete list of available MicroView classes that can be called in your code.

    Initialization

    • void begin(void)—Initialization of MicroView Library.Setup IO pins for SPI port then send initialization commands to the SSD1306 controller inside the OLED.

    • void end (void)—Power off the OLED display. Reset display control signals and prepare the SSD1306 controller for power off, then power off the 3.3V regulator.

    Display Actions, Settings and Orientation

    • void display(void)—Transfer display memory. Bulk move the screen buffer to the SSD1306 controller’s memory so that images/graphics drawn on the screen buffer will be displayed on the OLED.

    • void clear(* uint8_t mode)—Clear screen buffer or SSD1306’s memory. To clear GDRAM inside the LCD controller, pass in the variable mode = ALL and to clear screen page buffer pass in the variable mode = PAGE.

    • void clear(* uint8_t mode, * uint8_t c)—Clear or replace screen buffer or SSD1306’s memory with a character. To clear GDRAM inside the LCD controller, pass in the variable mode = ALL with c character and to clear screen page buffer, pass in the variable mode = PAGE with c character.

    • void invert(boolean inv)—Invert display. The WHITE color of the display will turn to BLACK, and the BLACK will turn to WHITE.

    • void contrast(* uint8_t contrast)—Set contrast. OLED contrast value from 0 to 255. Note: Contrast level is not very obvious.

    • void setCursor(* uint8_t x, * uint8_t y)—Set cursor position. MicroView’s cursor position to x,y.

    • void flipVertical(boolean flip)—Vertical flip. Flip the graphics on the OLED vertically.

    • void flipHorizontal(boolean flip)—Horizontal flip. Flip the graphics on the OLED horizontally.

    • uint8_t getLCDWidth(void)—The width of the LCD return as byte.

    • uint8_t getLCDHeight(void)—The height of the LCD return as byte.

    Display Scrolling

    • void scrollRight(* uint8_t start, * uint8_t stop)—Right scrolling. Set row start to row stop on the OLED to scroll right. Refer to OLED Memory Map section for explanation of the rows.

    • void scrollLeft(* uint8_t start, * uint8_t stop)—Left scrolling. Set row start to row stop on the OLED to scroll left. Refer to OLED Memory Map section for explanation of the rows.

    • void scrollVertRight(* uint8_t start, * uint8_t stop)—Right vertical scrolling. Set column start to row stop on the OLED to scroll right. Refer to OLED Memory Map section for explanation of the columns.

    • void scrollVertLeft(* uint8_t start, * uint8_t stop)—Left vertical scrolling. Set column start to row stop on the OLED to scroll left. Refer to OLED Memory Map section for explanation of the columns.

    • void scrollStop(void)—Stop the scrolling of graphics on the OLED.

    Font Functions

    • uint8_t getFontWidth(void)—Get font width. The current font’s width return as byte.

    • uint8_t getFontHeight(void)—Get font height. The current font’s height return as byte.

    • uint8_t getTotalFonts(void)—Get total fonts. Return the total number of fonts loaded into the MicroView’s flash memory.

    • uint8_t getFontType(void)—Get font type. Return the font type number of the current font.

    • uint8_t setFontType(* uint8_t type)—Set font type. Set the current font type number (i.e., changing to different fonts based on the type provided).

    • uint8_t getFontStartChar(void)—Get font starting character. Return the starting ASCII character of the current font; not all fonts start with ASCII character 0. Custom fonts can start from any ASCII character.

    • uint8_t getFontTotalChar(void)—Get font total characters. Return the total characters of the current font.

    Drawing Pixels

    • void pixel(* uint8_t x, * uint8_t y)—Draw pixel. Draw pixel using the current fore color and current draw mode in the screen buffer’s x,y position.

    • void pixel(* uint8_t x, * uint8_t y, * uint8_t color, * uint8_t mode)—Draw pixel with color and mode. Draw color pixel in the screen buffer’s x,y position with NORM or XOR draw mode.

    Drawing Lines

    • void line(* uint8_t x0, * uint8_t y0, * uint8_t x1, * uint8_t y1)—Draw line using current fore color and current draw mode from x0,y0 to x1,y1 of the screen buffer.

    • void line(* uint8_t x0, * uint8_t y0, * uint8_t x1, * uint8_t y1, * uint8_t color, * uint8_t mode)—Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.

    • void lineH(* uint8_t x, * uint8_t y, * uint8_t width)—Draw horizontal line using current fore color and current draw mode from x,y to x+width,y of the screen buffer.

    • void lineH(* uint8_t x, * uint8_t y, * uint8_t width, * uint8_t color, * uint8_t mode)—Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.

    • void lineV(* uint8_t x, * uint8_t y, * uint8_t height)—Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.

    • void lineV(* uint8_t x, * uint8_t y, * uint8_t height, * uint8_t color, * uint8_t mode)—Draw vertical line using color and mode from x,y to x,y+height of the screen buffer.

    Drawing Rectangles

    • void rect(* uint8_t x, * uint8_t y, * uint8_t width, * uint8_t height)—Draw rectangle using current fore color and current draw mode from x,y to x+width,y+height of the screen buffer.

    • void rect(* uint8_t x, * uint8_t y, * uint8_t width, * uint8_t height, * uint8_t color, * uint8_t mode)—Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.

    • void rectFill(* uint8_t x, * uint8_t y, * uint8_t width, * uint8_t height)—Draw filled rectangle using current fore color and current draw mode from x,y to x+width,y+height of the screen buffer.

    • void rectFill(* uint8_t x, * uint8_t y, * uint8_t width, * uint8_t height, * uint8_t color, * uint8_t mode)—Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.

    Drawing Circles

    • void circle(* uint8_t x, * uint8_t y, * uint8_t radius)—Draw circle with radius using current fore color and current draw mode at x,y of the screen buffer.

    • void circle(* uint8_t x, * uint8_t y, * uint8_t radius, * uint8_t color, * uint8_t mode)—Draw circle with radius using color and mode at x,y of the screen buffer.

    • void circleFill(* uint8_t x0, * uint8_t y0, * uint8_t radius)—Draw filled circle with radius using current fore color and current draw mode at x,y of the screen buffer.

    • void circleFill(* uint8_t x0, * uint8_t y0, * uint8_t radius, * uint8_t color, * uint8_t mode)—Draw filled circle with radius using color and mode at x,y of the screen buffer. Uses the Bresenham circle algorithm with a few modifications to paint the circle without overlapping draw operations.

    MISC Drawing

    • void drawChar(* uint8_t x, * uint8_t y, * uint8_t c)—Draw character c using current color and current draw mode at x,y.

    • void drawChar(* uint8_t x, * uint8_t y, * uint8_t c, * uint8_t color, * uint8_t mode)—Draw character c using color and draw mode at x,y.

    • void drawBitmap(void)—Draw bitmap image stored elsewhere in the program to the OLED screen.

    • void setColor(* uint8_t color)—Set the current draw’s color. Only WHITE and BLACK available.

    • void setDrawMode(* uint8_t mode)—Set current draw mode with NORM or XOR.

    MicroViewWidget

    • MicroViewWidget(uint8_t newx, uint8_t newy, int16_t min, int16_t max)—MicroView widget parent class. The MicroViewWidget class is the parent class for child widget like MicroViewSlider and MicroViewGauge.

    • uint8_t getX()—Get widget x position.

    • uint8_t getY()—Get widget y position.

    • void setX(uint8_t newx)—Set widget x position.

    • void setY(uint8_t newy)—Set widget y position.

    • int16_t getMinValue()—Return the minimum value of the widget.

    • int16_t getMaxValue()—Return the maximum value of the widget.

    • int16_t getValue()—Return the current value of the widget.

    • void setMinValue(int16_t min)—Set minimum value. The minimum value of the widget is set to the variable passed in.

    • void setMaxValue(int16_t max)—Set maximum value. The maximum value of the widget is set to the variable passed in.

    • void setValue(int16_t val)—The current value of the widget is set to the variable passed in, and the widget is drawn with the new value.

    • void setValue(int16_t val, boolean doDraw)—The current value of the widget is set to the variable passed in. The widget is drawn with the new value if the doDraw argument is true.

    • uint8_t getValLen()—Return the number of characters that would be printed using uView.print(value) for the current value.

    • uint8_t getMaxValLen()—Return the maximum number of characters that would be printed using uView.print(value) for the current value range.

    • virtual void draw()—Draw widget value overridden by child class.

    • virtual void drawFace()—Draw widget face overridden by child class.

    • void reDraw()—MicroView Widget reDraw routine. Redraws the widget.

    • void drawNumValue(int16_t value)—Draw a signed decimal numeric value at the current cursor location. The value is right justified with leading spaces, within a field the length of the maximum possible for the widget’s value range.

    MicroViewGauge

    • MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max)—MicroViewGauge class initialization. Initialize the MicroViewGauge widget with default style.

    • MicroViewGauge(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty)—Initialize the MicroViewGauge widget with style WIDGETSTYLE0 or WIDGETSTYLE1. Add WIDGETNOVALUE to the style to suppress displaying the numeric value (e.g., WIDGETSTYLE0 + WIDGETNOVALUE).

    • void draw(void)—Draw widget value. Convert the current value of the widget and draw the ticker representing the value.

    • void drawFace(void)—Draw widget face. Draw image/diagram representing the widget’s face.

    MicroViewSlider

    • MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max)—MicroViewSlider class initialization. Initialize the MicroViewSlider widget with default style.

    • MicroViewSlider(uint8_t newx, uint8_t newy, int16_t min, int16_t max, uint8_t sty)—Initialize the MicroViewSlider widget with style WIDGETSTYLE0 or WIDGETSTYLE1 or WIDGETSTYLE2 (like 0, but vertical) or WIDGETSTYLE3 (like 1, but vertical). Add WIDGETNOVALUE to the style to suppress displaying the numeric value (e.g., WIDGETSTYLE0 + WIDGETNOVALUE).

    • void draw(void)—Draw widget value. Convert the current value of the widget and draw the ticker representing the value.

    • void drawFace(void)—Draw widget face. Draw image/diagram representing the widget’s face.

    MISC Under-the-Hood Functions

    • void checkComm(void)—Listen for serial command. Instruct the MicroView to check for serial command from the UART.

    • virtual size_t write(* uint8_t)—Override Arduino’s Print. Arduino’s print overridden so that we can use uView.print().

    • void data(* uint8_t c)—SPI data. Send 1 data byte via SPI to SSD1306 controller.

    • void setColumnAddress(* uint8_t add)—Set SSD1306 column address. Send column address command and address to the SSD1306 OLED controller.

    • void setPageAddress(* uint8_t add)—Set SSD1306 page address. Send page address command and address to the SSD1306 OLED controller.

    • void doCmd(* uint8_t index)—Parse command. Command stored in serCmd array will be parsed to performed draw functions.

    • void command(* uint8_t c)—Send 1 command byte.

    • void command(* uint8_t c1, * uint8_t c2)—Send 2 command bytes.

    • void command(* uint8_t c1, * uint8_t c2, * uint8_t c3)—Send 3 command bytes.

    • uint8_t * getScreenBuffer(void)—Get pointer to screen buffer. Return a pointer to the start of the RAM screen buffer for direct access.

    MVSPIClass Reference (MicroView SPI)

    • static void begin()—SPI Initialization. Set up SCK, MOSI, SS and DC pins for SPI transmission.

    • static void end()—End SPI.

    • static void wait()—Wait for SPI serial transfer complete.

    • static void transfer(byte _data)—Transfer data byte via SPI port.

    • static void packetBegin()—Set up to begin a SPI packet transmit. Set up SPI for transmitting. Prepare the SPI interface for transmitting 1 or more bytes of commands and/or data.

    • static void packetEnd()—End an SPI packet transmission:

      • Wait for the last byte to finish being transmitted.
      • Set DC to command mode (even if already set that way, just in case).
      • Set SS high.
      • Disable SPI mode (causing SCK and MOSI to go low).
    • static void attachInterrupt()

    • static void detachInterrupt()

    • static void setBitOrder(uint8_t)—Set SPI port bit order with LSBFIRST or MSBFIRST.

    • static void setDataMode(uint8_t)—Set the SPI data mode: clock polarity and phase. mode - SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3.

    • static void setClockDivider(uint8_t)—Set the clock divider of the SPI; default is 4Mhz.

      • rate: SPI_CLOCK_DIV2 SPI_CLOCK_DIV4 SPI_CLOCK_DIV8 SPI_CLOCK_DIV16 SPI_CLOCK_DIV32 SPI_CLOCK_DIV64 SPI_CLOCK_DIV128

    Resources and Going Further

    Check the links below for more information about the MicroView.


    Now that you have a basic understanding of how the MicroView works, what will you create? Need some inspiration?

    Learn the ins and outs of electronics using the MicroView with the SparkFun Inventor’s Kit for MicroView.

    SparkFun Inventor's Kit for MicroView

    February 27, 2015

    The SparkFun Inventor's Kit for MicroView follows our tried and true inventor's kit model, bringing you 11 simple yet fun experiments to introduce you to the SparkFun MicroView.

    Build your own digital compass that displays the current heading on the MicroView.

    MicroView Digital Compass

    October 24, 2016

    Build a portable digital compass using the SparkFun MicroView and the MAG3110 Magnetometer Breakout.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Mini GPS Shield Hookup Guide

    $
    0
    0

    Mini GPS Shield Hookup Guide a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t578

    Introduction

    The Mini GPS Shield is a mini version of the SparkFun GPS Logger Shield. While the GPS Logger Shield was designed to work with the Arduino RedBoard, the Mini GPS Shield was designed to work with the Arduino Mini/Micro boards.

    SparkFun Mini GPS Shield

    GPS-14030
    $12.95

    Just like its big brother, the Mini GPS Shield equips your Arduino Mini with access to a GPS module and µSD memory card socket for data logging. The board also uses a level shifter, so there’s no need to worry about the logic voltage of your Arduino Mini.

    Check out the video below to see the Mini GPS Shield in action.

    Required Materials

    For this guide, you’ll need the following:

    The wish list above has the 5V Arduino Pro Mini, but the 3.3V Pro Mini, Pro Micro, SAMD21 Mini, or ANY of our Arduino Mini form factor boards will work just as well.

    Suggested Reading

    If you have never worked with the Arduino Pro Mini or similar platforms before, we suggest having a look at the following tutorials before continuing.

    What is an Arduino?

    What is this 'Arduino' thing anyway?

    Installing Arduino IDE

    A step-by-step guide to installing and testing the Arduino software on Windows, Mac, and Linux.

    How to Install FTDI Drivers

    How to install drivers for the FTDI Basic on Windows, Mac OS X, and Linux.

    Using the Arduino Pro Mini 3.3V

    This tutorial is your guide to all things Arduino Pro Mini. It explains what it is, what it's not, and how to get started using it.

    If you have never worked with GPS before, have a look at our GPS Basics tutorial.

    Hardware Overview

    Let’s go over the Mini GPS Shield in detail.

    board overview

    The Mini GPS Shield will work with any of our Arduino Mini boards. The board uses 3.3V logic, however the logic level converter on the shield allows you to use 5V boards just as easily.

    Connecting the GPS

    The shield comes with a 6-pin JST connector to connect the GP-735 GPS module. If you already have a GPS module, the JST pins are broken out and labeled to allow you to use just about any GPS module that works down to 3.3V.

    NOTE: The RX and TX labels correspond to the data direction on the board. RX should be connected to the GPS TX pin and TX should be connected to the GPS RX pin.

    highlight

    Using the LED

    One of the problems of GPS is the time it takes to get your first position reading. Each module is different, but a typical GPS fix takes around 30 seconds. Another downfall is getting a strong enough signal from the the satellites in orbit, which can increase the time it takes to get a position fix. Because of the uncertainty in the time it takes to get a position fix, we included an LED attached to digital pin 7. We’ll see in the code below, how to use the LED to illuminate when we have locked in a position.

    Software or Hardware Serial?

    The GP-735 has a UART that makes communicating with the GPS very easy. Unfortunately, in many cases, the UART is tied up sending debug messages back to our computer. To get around this, we used software serial. Software serial, gives your microcontroller a software defined UART so you can communicate to your GPS while still sending the messages back to your computer. There are other times where you may need to use only the hardware serial, for example if your microcontroller is low on program memory. For this reason, we made switching between hardware and software serial easy, by including a switch that’s labeled HW-UART for hardware serial on digital pins 0 and 1, and SW-UART for software serial on digital pins 4 and 5. You can learn more about serial communication here.

    GPS Power Saving

    The Mini GPS Shield was designed to work with the GP-735 GPS module. If you want to save power, you can pull digital pin 6 LOW, and it will disable power to the GPS. To enable power, you can either pull digital pin 6 HIGH or leave it floating.

    The GP-735 does not have accessible non-volatile memory. This means that when you disconnect power, any settings (baud rate, update rate, etc) will not be saved. If you don’t want to reconfigure these settings every time, you’ll need to use a backup battery. The backup battery won’t be used in the examples below, but, if you need to use it, those pins are labeled VBATT along with a “+” and “-” corresponding to the respective pins. The voltage of VBATT should be between 1.5V and 3.5V.

    To Snap or not to Snap

    You may have noticed the v-score next to the microSD connector. If you need the board to be as small as possible and aren’t planning on using a microSD card, you can easily remove the extra board material by providing a little bit of force to bend the board and snap it off. If you are going to use an SD card, we recommend leaving it on so an accidental bump won’t damage or dislodge your microSD card.

    Snapped board

    Hardware Hookup

    Before you can attach your shield, you will need to solder some headers to both the GPS Shiled and the Arduino Pro Mini. We recommend soldering female headers to the Pro Mini and straight male headers for the shield.

    Attaching the shield to an Arduino Mini, is very easy but there is one thing to keep in mind: standard Arduino boards, like the SparkFun RedBoard, have pin offsets that make plugging a shield into the board simple, while the mini boards have symmetrical pins, which means it’s very easy to plug the shield in the wrong way. Plugging the shield in backwards won’t damage either board, but it is something that could be easy to overlook.

    The orientation of the shield is pictured below. The correct orientation has the GPS connector on the same side as the USB or FTDI connection and the microSD card over the crystal or reset button.

    Board orientation

    Arduino Examples

    Now that we have everything connected, lets get started with some code. Before we start writing code though, we do need to install a library to parse the GPS messages. If you haven’t worked with downloading Arduino libraries before or you just need a quick refresh, check out our tutorial on installing Arduino libraries. The library we need is called TinyGPS++ from Mikal Hart, you can download and install the libary from the link below.

    TinyGPS++ Library

    Now that we have the library installed, let’s look at the code.

    In this first example, we’ll test our our GPS and make sure we’re able to get a signal from the satellites.

    language:c
    /******************************************************************************
    Mini_GPS_Shield_Serial_Example.ino
    Example using the Mini GPS Shield with the GP-735
    Alex Wende @ SparkFun Electronics
    October 12th 2016
    ~
    
    This sketches uses the Mini GPS Shield with the
    GP-735 (https://www.sparkfun.com/products/13670). The Arduino reads the data
    from the GPS module on the defined software serial pins, and prints data on
    to the serial window.
    
    Resources:
    SoftwareSerial.h (included with Arduino IDE)
    TinyGPS++.h
    
    Development environment specifics:
    Arduino 1.0+
    Hardware Version 10
    
    This code is beerware; if you see me (or any other SparkFun employee) at
    the local, and you've found our code helpful, please buy us a round!
    
    Distributed as-is; no warranty is given.
    ******************************************************************************/
    
    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>
    
    #define RX_PIN  4 // GPS TX
    #define TX_PIN  5 // GPS RX
    #define LED_PIN 7 // GPS Fix LED
    #define GPS_BAUD  9600  // GP-735 default baud rate
    
    TinyGPSPlus gps;
    
    SoftwareSerial ss(RX_PIN,TX_PIN);
    
    void setup() {
      Serial.begin(115200); // Begin serial communication with computer
      ss.begin(GPS_BAUD); // Begin serial communication with GPS
    
      pinMode(LED_PIN,OUTPUT);
    
      Serial.println("Date       Time        Latitude   Longitude   Alt    Course Heading Speed");
      Serial.println("(MM/DD/YY) (HH/MM/SS)     (deg)       (deg)  (ft)                   (mph)");
      Serial.println("-------------------------------------------------------------------------");
    }
    
    void loop() {
      char gpsDate[10];
      char gpsTime[10];
    
      if(gps.location.isValid()){ // GPS has a fix
        digitalWrite(LED_PIN,HIGH); // Turn LED on
    
        sprintf(gpsDate,"%d/%d/%d", gps.date.month(),gps.date.day(),gps.date.year()); // Build date string
        sprintf(gpsTime,"%d/%d/0%d", gps.time.hour(),gps.time.minute(),gps.time.second());  // Build time string
    
        Serial.print(gpsDate);
        Serial.print('\t');
        Serial.print(gpsTime);
        Serial.print('\t');
        Serial.print(gps.location.lat(),6);
        Serial.print('\t');
        Serial.print(gps.location.lng(),6);
        Serial.print('\t');
        Serial.print(gps.altitude.feet());
        Serial.print('\t');
        Serial.print(gps.course.deg(),2);
        Serial.print('\t');
        Serial.println(gps.speed.mph(),2);
      }
      else  // GPS is looking for satellites, waiting on fix
      {
        digitalWrite(LED_PIN,LOW);  // Turn LED off
        Serial.print("Satellites in view: ");
        Serial.println(gps.satellites.value());
      }
      smartDelay(1000);
    }
    
    // Delay ms while still reading data packets from GPS
    static void smartDelay(unsigned long ms)
    {
      unsigned long start = millis();
      do
      {
        while(ss.available())
        {
          gps.encode(ss.read());
        }
      } while(millis() - start < ms);
    }

    Our second example is very similar to our first example. In this example though, instead of displaying the GPS data in just the serial window, we’ll also log the data to a microSD card. Note that this example makes use of the built-in SD library in the Arduino IDE.

    language:c
    /******************************************************************************
    Mini_GPS_Shield_Data_Log_Example.ino
    Example using the Mini GPS Shield with the GP-735
    Alex Wende @ SparkFun Electronics
    October 12th 2016
    ~
    
    This sketches uses the Mini GPS Shield with the
    GP-735 (https://www.sparkfun.com/products/13670) and a microSD card. The
    Arduino reads the data from the GPS module on the defined software serial
    pins, and saves the data to a SD card.
    
    Resources:
    SoftwareSerial.h (included with Arduino IDE)
    SD.h (included with Arduino IDE)
    SPI.h (included with Arduino IDE)
    TinyGPS++.h
    
    Development environment specifics:
    Arduino 1.0+
    Hardware Version 10
    
    This code is beerware; if you see me (or any other SparkFun employee) at
    the local, and you've found our code helpful, please buy us a round!
    
    Distributed as-is; no warranty is given.
    ******************************************************************************/
    
    #include <SPI.h>
    #include <SD.h>
    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>
    
    #define RX_PIN  4 // GPS TX
    #define TX_PIN  5 // GPS RX
    #define LED_PIN 7 // GPS Fix LED
    #define CHIP_SELECT 10  // uSD card
    #define GPS_BAUD  9600  // GP-735 default baud rate
    
    TinyGPSPlus gps;
    File myFile;
    SoftwareSerial ss(RX_PIN,TX_PIN);
    
    void setup() {
      Serial.begin(115200); // Begin serial communication with computer
      ss.begin(GPS_BAUD); // Begin serial communication with GPS
    
      pinMode(LED_PIN,OUTPUT);
    
      Serial.print("Initializing SD card...");
    
      // see if the card is present and can be initialized:
      if (!SD.begin(CHIP_SELECT)) {
        Serial.println("Card failed, or not present");
        // don't do anything more:
        return;
      }
      Serial.println("card initialized.");
    
      myFile = SD.open("data.txt", FILE_WRITE); // Create or open a file called "data.txt" on the SD card
      if(myFile)
      {
        if(myFile.size() == 0)  // Only create the header if there isn't any data in the file yet
        {
          myFile.println("Date\t\tTime\t\tLatitude\tLongitude\tAlt\tCourse\tSpeed");
          myFile.println("MM/DD/YYYY\tHH/MM/SS\tdeg\t\tdeg\t\tft\t\tmph");
          myFile.println("-------------------------------------------------------------------------------------");
        }
        myFile.close(); // Close the file to properly save the data
      }
      else {
        // if the file didn't open, print an error:
        Serial.println("error opening test.txt");
      }
    }
    
    void loop() {
      char gpsDate[10], gpsTime[10];
    
      if(gps.location.isValid()){ // GPS has a fix
        digitalWrite(LED_PIN,HIGH); // Turn LED on
        myFile = SD.open("data.txt", FILE_WRITE); // Open file "data.txt"
        if(myFile)
        {
          // Get date and time
          sprintf(gpsDate,"%d/%d/%d", gps.date.month(),gps.date.day(),gps.date.year());
          if(gps.time.second() < 10){
            sprintf(gpsTime,"%d/%d/0%d", gps.time.hour(),gps.time.minute(),gps.time.second());
          }
          else
          {
            sprintf(gpsTime,"%d/%d/%d", gps.time.hour(),gps.time.minute(),gps.time.second());
          }
    
          // Save data to SD card
          myFile.print(gpsDate);
          myFile.print('\t');
          myFile.print(gpsTime);
          myFile.print('\t');
          myFile.print(gps.location.lat(),6);
          myFile.print('\t');
          myFile.print(gps.location.lng(),6);
          myFile.print('\t');
          myFile.print(gps.altitude.feet());
          myFile.print('\t');
          myFile.print(gps.course.deg(),2);
          myFile.print('\t');
          myFile.println(gps.speed.mph(),2);
    
          // Print GPS data to serial window
          Serial.print(gpsDate);
          Serial.print('\t');
          Serial.print(gpsTime);
          Serial.print('\t');
          Serial.print(gps.location.lat(),6);
          Serial.print('\t');
          Serial.print(gps.location.lng(),6);
          Serial.print('\t');
          Serial.print(gps.altitude.feet());
          Serial.print('\t');
          Serial.print(gps.course.deg(),2);
          Serial.print('\t');
          Serial.println(gps.speed.mph(),2);
        }
    
        myFile.close(); // Close the file to properly save the data
      }
      else  // GPS is looking for satellites, waiting on fix
      {
        digitalWrite(LED_PIN,LOW);  // Turn LED off
        Serial.print("Satellites in view: ");
        Serial.println(gps.satellites.value());
      }
    
      smartDelay(1000);
    }
    
    // Delay ms while still reading data packets from GPS
    static void smartDelay(unsigned long ms)
    {
      unsigned long start = millis();
      do
      {
        while(ss.available())
        {
          gps.encode(ss.read());
        }
      } while(millis() - start < ms);
    }

    Troubleshooting Tips

    If you’re testing your GPS inside, make sure you’re next to a window. One of the problems with GPS is the radio waves have a difficult time passing through roofs and ceilings, so, the closer the GPS is to being outside, the better. If you still aren’t reading from enough satellites to get a position fix, try pointing the GPS antenna in a different direction.

    Due to the symmetrical pins of the mini boards, installing the shield backwards is an easy mistake to make. The correct orientation has the GPS connector on the same side as the USB or FTDI connection and the microSD card over the crystal and reset button. See the Hardware Hookup section for a picture of the correct orientation.

    If you are unable to access the SD card, make sure your card is installed with the pins facing down and that you’ve initialized the SD card’s chip select as pin 10 when you call SD.begin(CHIP_SELECT).

    Resources and Going Further

    For more information about the Mini GPS Shield, check out the links below:

    Going Further

    Now that you’ve got the Mini GPS Shield up and running, what project are you going to use this shield for? Need a little inspiration? Check out some of these tutorials!

    • GPS Wall Clock– This project uses a GPS module to create a wall clock that you never need to set!
    • GPS Differential Vector Pointer– In this tutorial you’ll learn how to use GPS receivers to have two objects, a base and a target, point towards one another. This can be used to aim sensors, antennas, lasers, etc. from one object to another over long distances.

    MG2639 Cellular Shield Hookup Guide

    Learn how to equip your Arduino with an MG2639 Cell Shield and use it to send SMS or TCP via GPRS.

    GPS Differential Vector Pointer

    Use GPS to have two objects, a base and a target, point towards one another. This can be used to aim a directional antenna (or in the case of this project, a laser) from one object to the other object at a distance that is only limited by your ability to provide the base station with the target's GPS location.

    GPS Logger Shield Hookup Guide

    How to assemble and hookup the SparkFun GPS Logger Shield. Never lose track of your Arduino again!
    New!

    Building an Autonomous Vehicle: The Batmobile

    Documenting a six-month project to race autonomous Power Wheels at the SparkFun Autonomous Vehicle Competition (AVC) in 2016.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Night-Light Pennant with LilyMini ProtoSnap

    $
    0
    0

    Night-Light Pennant with LilyMini ProtoSnap a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t579

    Introduction

    In this project we’ll control LEDs using the LilyMini ProtoSnap. With the code stored on the LilyMini, our projects can now have more advanced behaviors, and interactions are even reprogrammable. We’ll sew the LilyPad components on a pennant shape and customize the theme and decoration.

    Design and build time: 3 - 4 hours

    alt text

    This is Project 4 from the LilyPad Sewable Electronics Kit, take a look at the other projects in the kit:

    Suggested Reading

    If this is your first sewable electronics project, we recommend you read our LilyPad Basics tutorial.

    New!

    LilyPad Basics: E-Sewing

    December 16, 2016

    Learn how to use conductive thread with LilyPad components.

    For a primer on the LilyMini ProtoSnap, check out this detailed guide.

    New!

    LilyMini ProtoSnap Hookup Guide

    December 16, 2016

    Explore the LilyPad LilyMini ProtoSnap and learn how to use it.

    Materials and Tools

    Let’s go over all of the things you’ll need to sew your project together.

    LilyPad Sewable Electronics Kit

    KIT-13927
    $99.95

    Items included in the LilyPad Sewable Electronics Kit:

    alt text

    You will also need:

    • Pen, marker, or chalk
    • Scissors
    • Hot glue gun (with extra glue)
    • Optional: Craft supplies for decorating (feathers, sequins, buttons, etc.)

    Planning Your Project

    For this project, we’ll be using the Night-Light Pennant template (download below or use the templates included with your kit). If needed, download and print the provided template. Right-click the image below and choose “Save Link As” to download the template to your computer.

    alt text

    Right-click and choose “Save Link As” or click image to download PDF

    Follow along with the circuit diagram on the template, or design your own layout and shape on a piece of paper. Trace onto the felt, and cut. We’ll add the LilyMini and the pieces from the ProtoSnap to a customized pennant to hang on a wall or sew into a project.

    alt text

    Working With ProtoSnap

    Like other LilyPad ProtoSnap boards, the LilyMini ProtoSnap has all of its pieces wired together, enabling you to test the circuit’s function before you sew.

    The LilyMini board has a small push button to turn it on/off, located between sew tabs 3 and 4. With the battery installed, press and release the button quickly to start up the LilyMini. The LED on the LilyMini (between sew tabs 1 and 2) will turn green when it is on and the battery has a charge, or it will turn red if the battery is getting low, then fade off. To power down the LilyMini, press the button again.

    Once powered, the LEDs on the ProtoSnap should all be on, and the LilyMini’s LED will glow white (Mode 1). Press the LilyPad Button to cycle through modes, which use the light sensor to affect the behavior of the LEDs. Use your hand to cover the light sensor, and observe what happens to the two pairs of LEDs – when the light level is low, the behavior of the LEDs changes. Press the button again to switch to the next mode.

    alt text

    LilyMini ProtoSnap Modes

    ModeColorBehavior
    1WhiteAll LEDs on.
    2MagentaLEDs fade in and out in a breathing pattern. When the light sensor is covered, LEDs fade faster.
    3CyanLEDs off. When the light sensor is covered, LEDs will twinkle.

    Understanding Your Circuit

    The LilyMini is a small computer that can store information and commands to control different sensors and boards connected to it. Programmable boards like the LilyMini are called microcontrollers. The LilyMini has been programmed in advance with a set of behaviors called code.

    Outputs

    Press the small button between tabs 3 and 4 to turn on your LilyMini on and off. Notice that in this circuit on the LilyMini LEDs behave in a different way. Unlike in our previous circuits, LEDs are not connected directly to the battery. These LEDs are connected to the LilyMini, which uses code to send power to each of its numbered tabs at different times – this is how the light patterns are created. The LEDs are outputs – components that receive information from a microcontroller and send it out into the world.

    alt text

    Other examples of outputs in circuits are motors, sound creators (such as a buzzer), and displays (e.g., monitors, LCD displays).

    Inputs

    The light sensor and button are inputs – components that gather information from the world and relay it to the microcontroller. The LilyMini reads information from the inputs connected to it and makes decisions in the code based on the values it receives. The LilyMini switches modes when the button is pressed. In modes 2 and 3, when the light value from the light sensor falls below a certain level, the LilyMini tells the LEDs to twinkle. When the light level rises again, the LilyMini tells the LEDs to return to the original behavior.

    alt text

    Arranging Your Circuit

    Carefully snap the pieces of the ProtoSnap apart. Use a set of pliers or diagonal cutters if you are having trouble snapping the pieces apart.

    alt text

    Discard the non-sewable pieces and scraps. You will end up with seven LilyPad pieces: the LilyMini with battery, four LilyPad LEDs, a LilyPad Button Board, and a LilyPad Light Sensor. We will be labeling the LEDs A, B, C, and D in the circuit diagram to help keep track of them while we stitch the circuit. LEDs A and B will be the first pair, and LEDs C and D will be the second pair.

    Arrange the pieces on the felt according to the diagram (or your own custom design). Carefully securing each piece with a dab of glue. Double check the orientation of the LilyPad pieces against the diagram or template before gluing.

    alt text

    To help you plan your stitch lines, draw your circuit onto the felt with chalk or a washable marker.

    Stitching It Together

    If you need help sewing with conductive thread this tutorial covers the basics.

    STEP 1:

    We’ll begin by stitching a connection between the LilyMini and the LilyPad light sensor. The light sensor board has three connections: sensor (S), positive (+), and negative (–). Use conductive thread to connect Tab 1 on the LilyMini to the (S) tab on the light sensor with three loops at each tab. Don’t worry about connecting the + and - tabs; we’ll do that later.

    alt text

    STEP 2:

    Next, we’ll connect the LilyMini to the LilyPad Button Board. With a new piece of thread, sew three to four loops around Tab 2 of the LilyMini, and then continue stitching to connect one side of the button. Tie and cut.

    alt text

    STEP 3:

    Tab 3 on the LilyMini will connect to two LEDs: A and B. With a new piece of thread, connect Tab 3 to the positive (+) of LED A. Continue stitching to connect (+) of LED B, making three loops at each tab.

    alt text

    STEP 4:

    We’ll repeat this process with a new piece of thread to connect Tab 4 on the LilyMini to the positive tabs of LEDs C and D.

    alt text

    STEP 5:

    With a new piece of thread, stitch the positive tab of the LilyMini to the positive tab (+) of the light sensor using three to four loops on each tab and a running stitch between. Tie, and cut.

    alt text

    STEP 6:

    Finally, we’ll stitch all the negative connections together and back to the negative tab on the LilyMini. This will require a much longer piece of thread than in other steps – about 2.5 feet.

    Begin at the negative (-) sew tab on the light sensor, and continue stitching along the outside edge of the project, connecting the negative tab of each piece (LEDs A, B, C, and D), ending at the negative (-) tab of the LilyMini.

    alt text

    After all the stitching is complete, turn the project over, and trim any loose thread tails before testing.

    Installing Your Battery and Testing

    Insert the coin cell battery into the LilyMini’s battery holder with the positive (+) side facing up. Press the power button on the LilyMini; all four LEDs should light up (Mode 1). Press the LilyPad button to switch between modes. Cover the light sensor in each mode to check the stitches are connecting to the sensor. If so, remove the battery and continue to the Finishing Touches section.

    alt text

    How to place a battery in a LilyMini’s Battery Holder.

    Troubleshooting

    With any electronics project, there are times you will have to troubleshoot if your circuit isn’t working. If your circuit isn’t lighting up, try a new battery or check that your project is switched on. Check your sewing for any loose threads or ends that may be touching other parts of your circuit and causing a short circuit. Learn more about troubleshooting your project in the LilyPad Basics: E-Sewing tutorial.

    Finishing Touches

    After checking the function of the circuit, it’s time to customize your pennant. Adding light-colored felt over the LEDs can hide the boards and diffuse the light. If covering the light sensor with a felt decoration, make sure to cut a hole above the sensor so it is not blocked/covered.

    alt text

    Here are a few examples of finished pennants with creative themes:

    Resources and Going Further

    These tutorials will guide you through more advanced projects and concepts:

    Insulation Techniques for e-Textiles

    Learn a few different ways to protect your conductive thread and LilyPad components in your next wearables project.

    Planning a Wearable Electronics Project

    Tips and tricks for brainstorming and creating a wearables project.

    Choosing a LilyPad Arduino for Your Project

    Not sure which LilyPad Arduino is right for you? We'll discuss the features of each and help you decide.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    LilyMini ProtoSnap Hookup Guide

    $
    0
    0

    LilyMini ProtoSnap Hookup Guide a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t569

    Overview

    The LilyMini ProtoSnap is a great way to get started learning about creating interactive e-textile circuits before you start sewing. Read on for a description of the board’s pre-programmed behaviors and how to snap it apart for use in a project.

    LilyPad LilyMini ProtoSnap

    DEV-14063
    $14.95

    Like other LilyPad ProtoSnap boards, the LilyMini ProtoSnap has all of its pieces wired together, enabling you to test the circuit’s function before you sew. At the center of the board is a pre-programmed LilyMini microcontroller connected to a LilyPad Light Sensor, LilyPad Button, and two pairs of LilyPad LEDs.

    Suggested Reading

    If this is your first e-textile project, take a look at some of our beginner tutorials.

    Planning a Wearable Electronics Project

    Tips and tricks for brainstorming and creating a wearables project.

    LilyPad Light Sensor Hookup Guide

    How to hook up the LilyPad Light Sensor as well as some project ideas and example code.
    New!

    LilyPad Basics: E-Sewing

    Learn how to use conductive thread with LilyPad components.

    Hardware Overview and Features

    The LilyMini ProtoSnap includes six LilyPad components connected to a LilyMini by silver pathways called traces. After breaking the ProtoSnap into individual pieces, we will replace these pathways with conductive thread stitch lines. For easy reference, each piece on the ProtoSnap has a nearby label with its name and the LilyMini sew tab to which it is connected.

    alt text

    LilyPad Component:Connected to LilyMini Sew Tab: Description:
    LilyPad Light Sensor (S)1LilyMini receives ambient light level input from light sensor.
    LilyPad Button2LilyMini receives button press input to change modes.
    2 LilyPad LEDs (+)3A pair of LEDs controlled by LilyMini modes.
    2 LilyPad LEDs (+)4A second pair of LEDs controlled by LilyMini modes.
    LilyPad Light Sensor (+)+LilyMini provides power to the Light Sensor.
    All components (-)-All components share a common ground connection back to the LilyMini.

    Powering the LilyMini ProtoSnap

    The LilyMini board, at the center of the ProtoSnap, has a built-in battery holder that will hold a 20mm CR2032 Coin Cell Battery. The board can also be powered through the micro USB port. If both are present, the USB cable takes priority. When the LilyMini is being powered via the cable, no power is drawn from the battery.

    alt text

    Slide the battery into the LilyMini's battery holder with the + labeled side facing up. Be careful not to break the LilyPad pieces apart while inserting or removing the battery. To remove the battery, use a non-conductive item (pen caps or pencils work well) to gently push the battery out. Some LilyMini ProtoSnaps may ship with a battery pull tab, remove this before using.

    To turn on the LilyMini, locate the small push button labeled ON between sew tabs 3 and 4. With the battery installed (or USB cable connected) press and release the button quickly to start up the LilyMini. To turn the LilyMini off, press the button a second time.

    alt text

    A built-in LED between sew tabs 1 and 2 is used as an indicator light when powered on. The LED will briefly flash green upon start up if the battery has enough charge to power the board or flash red if the battery is too low and will not power the circuit. The LilyMini does not include a battery charging circuit, when the LED flashes red we recommend installing a new battery for best performance.

    alt text

    Exploring the Sample Circuit

    The LilyMini ProtoSnap ships with pre-loaded code that uses all the LilyPad pieces connected to it. This sample code has three modes, which can be selected by pressing the LilyPad Button on the bottom-left side of the ProtoSnap (see in the chart below). The built-in LED on the LilyMini will change color to indicate which mode has been selected.

    alt text

    LilyMini ProtoSnap Modes

    ModeColorBehavior
    1WhiteAll LEDs on.
    2MagentaLEDs fade in and out in a breathing pattern. When the light sensor is covered, LEDs fade faster.
    3CyanLEDs off. When the light sensor is covered, LEDs will twinkle.

    Try It Out

    Press the button to switch modes. In modes 2 and 3, when the light value from the light sensor falls below a certain level, the LilyMini tells the LEDs to change behavior (breathe or twinkle). When the light level rises again, the LilyMini tells the LEDs to return to the original behavior.

    alt text

    Stitching into a Project

    Carefully snap the pieces of the ProtoSnap apart to prepare for sewing. Use a set of pliers or diagonal cutters if you are having trouble snapping the pieces apart. Discard the non-sewable pieces and scraps.

    alt text

    Arrange the LilyPad pieces on your project and secure with a small dab of hot glue or fabric glue, making sure not to cover the holes in the sew tabs. Double check the orientation of the LilyPad pieces against your diagram (or template if using a SparkFun design) before gluing. To help you plan your stitch lines, draw your circuit onto the felt with chalk or a washable marker.

    alt text

    The image above is an example of a project diagram using the LilyMini ProtoSnap. For instructions and downloadable template, visit the Night-Light Pennant tutorial.

    After arranging the circuit, carefully connect each LilyPad component to the LilyMini with conductive thread.

    If you need help sewing with conductive thread this tutorial covers the basics.

    Resources and Going Further

    Looking for project inspiration? The Night-Light Pennant project from the LilyPad Sewable Electronics Kit uses the LilyMini ProtoSnap.

    LilyPad Sewable Electronics Kit

    KIT-13927
    $99.95

    These tutorials will guide you through additional projects and concepts:

    Insulation Techniques for e-Textiles

    Learn a few different ways to protect your conductive thread and LilyPad components in your next wearables project.

    Planning a Wearable Electronics Project

    Tips and tricks for brainstorming and creating a wearables project.

    Choosing a LilyPad Arduino for Your Project

    Not sure which LilyPad Arduino is right for you? We'll discuss the features of each and help you decide.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Light-Up Plush

    $
    0
    0

    Light-Up Plush a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t471

    Introduction

    For this project, we’ll try individually controlling the LEDs in an e-textile circuit. We’ll explore two ways of controlling the flow of current to an LED using a button and switch while we craft a creative plush creature.

    Design and build time: 2 - 3 hours

    light-up plush

    This is Project 3 from the LilyPad Sewable Electronics Kit, take a look at the other projects in the kit:

    Suggested Reading

    If this is your first sewable electronics project, we recommend you read our LilyPad Basics tutorial.

    New!

    LilyPad Basics: E-Sewing

    December 16, 2016

    Learn how to use conductive thread with LilyPad components.

    Materials and Tools

    Let’s go over all of the things you’ll need to sew your project together.

    LilyPad Sewable Electronics Kit

    KIT-13927
    $99.95

    Items included in the LilyPad Sewable Electronics Kit:

    alt text

    You will also need:

    • Pen, marker, or chalk
    • Scissors
    • Hot glue gun (with extra glue)
    • Optional: Craft supplies for decorating (feathers, sequins, buttons, etc.)

    Planning Your Project

    For this project, we’ll be using the Light-Up Plush template (download below or use the template included with your kit). If needed, download and print the provided template. Right-click the image below and choose “Save Link As” to download the template to your computer.

    alt text

    Right-click and choose “Save Link As” or click image to download PDF

    Trace and cut out the plush template shape on a piece of felt. To hide your stitches entirely, cut out an extra half-piece of felt (as shown) to place on top of your finished plush (see Finishing Touches).

    alt text

    Working with ProtoSnap

    If you are using individual LilyPad components instead of the E-Sewing ProtoSnap, you will not be able to follow along with the experiment in the next section exactly, but read along to learn more about buttons and switches.

    We’ll use the LilyPad pieces in the circuit to turn different LEDs on and off. Using the E-Sewing ProtoSnap, we’ll examine how buttons and switches behave differently, then snap the pieces apart and build them into a plush creature with light-up features.

    Before we arrange our circuit on the felt, with the battery installed, slide the battery holder switch to the ON position.

    alt text

    Understanding Your Circuit

    Buttons and switches are electronic components that control the flow of electricity through a circuit. The circuit is closed when current is allowed through by turning on a switch or pressing a button. When a piece of the circuit is disconnected by turning a switch or button off, it is an open circuit.

    LilyPad Slide Switch

    The LilyPad Slide Switch has a small switch labeled ON/OFF. When the toggle is moved to the ON position, the two sew tabs on the switch are connected, allowing current to flow through and close the circuit. When moved to OFF, parts inside the switch move away from each other and open the circuit (disconnecting it). It helps to visualize switches as drawbridges for electricity – when the bridge is up (open), nothing can cross over. When it is down (closed), the pathway is reconnected, and electricity can flow along the original path.

    alt text

    LilyPad Button

    The LilyPad Button Board is also a type of switch. When you press the button in the middle of the board, it connects the two sew tabs and allows current to flow through. When you let go of the button, the connection is opened again, and the button springs back into place. This button is an example of a momentary switch – it is only active when an action is applied.

    This is slightly different from the slide switch, which is an example of a maintained switch, meaning its state remains the same until changed.

    alt text

    Learn more about buttons and switches in our Switch Basics tutorial.

    Arranging Your Circuit

    Carefully snap apart the connected components on the E-Sewing ProtoSnap panel. Discard the non-sewable pieces and scraps. You will end up with six LilyPad pieces: a battery holder with battery, three LEDs, a button, and a switch.

    alt text

    Arrange the pieces on the felt according to the diagram below. Make sure to check the orientation of the LilyPad LEDs before you stitch them together. The positive tabs of the LED connect to the button or switch, and the negative tabs connect to the negative tab on the battery holder. When your circuit design is finalized, use a dab of glue on the back of each component to attach them to the felt.

    alt text

    For this project, we’ll be arranging the pieces slightly differently from on the E-Sewing ProtoSnap. To avoid any crossed conductive thread, we are connecting (+) with both the button and the switch instead of having two separate paths to the battery holder. When creating circuits with e-textiles, both the electrical properties of the circuit and aesthetic decisions are part of the design process.

    This project has a lot of stitching. If you want to hide the stitches, use a layer of felt or decorations over the thread after you’ve finished your circuit (see Finishing Touches section), or use a hidden stitch (see our E-Sewing Basics tutorial).

    Stitching It Together

    If you need help sewing with conductive thread this tutorial covers the basics.

    STEP 1:

    Cut a long piece of conductive thread, thread the needle, and tie a knot at the end. Begin sewing at the positive sew tab on the battery holder closest to the fold or “feet” on the felt cutout. Remember to use three to four loops around each tab as you sew.

    Use a running stitch or hidden stitch (see E-Sewing Basics for these techniques) to connect the positive sew tab on the battery board to the closest sew tab on the switch. Sew three to four loops around the switch’s sew tab to secure, then tie a knot and cut.

    alt text

    STEP 2:

    With a new piece of thread, connect the other side of the switch to the positive sew tabs of the top two LEDs and end with three to four loops on the closest tab of the button. Tie and cut.

    alt text

    STEP 3:

    With a new piece of thread, begin at the other side of the button and stitch three to four loops around the sew tab. Continue stitching to the positive side of the last LED, ending with three to four loops.

    Tie and cut.

    alt text

    STEP 4:

    Finally, we’ll stitch all the negative connections. With a new piece of thread, stitch three to four loops on the negative (–) sew tab of the first LED and connect to the negative tabs on the other LEDs, ending at the negative tab of the battery holder as shown. Make sure to loop three to four times on each connection.

    alt text

    After all the stitching is complete, turn the project over, and trim any loose thread tails before testing.

    Installing Your Battery and Testing

    Insert the coin cell battery into the battery holder with the positive (labeled +) side facing up. Test the button and switch to make sure the LEDs light up. If they do, remove the battery and continue to the Finishing Touches section.

    alt text

    How to place a battery in a LilyPad Battery Holder.

    Troubleshooting

    With any electronics project there are times you will have to troubleshoot if your circuit isn’t working. If your circuit isn’t lighting up, try a new battery or check that your project is switched on. Check your sewing for any loose threads or ends that may be touching other parts of your circuit and causing a short circuit. Learn more about troubleshooting your project in the LilyPad Basics: E-Sewing tutorial.

    Finishing Touches

    Conductive thread can be part of the visual design, or hidden. To hide stitches, add a layer of felt on top with cutouts to allow the LEDs to shine through and to access the button and switch.

    alt text

    Once you’ve finished testing, it’s time to make the plush three-dimensional. Remove the battery, and fold the felt at the connected points (feet) at the bottom so the LilyPad components are on the outside. Using non-conductive sewing or embroidery thread (or a glue gun) seal all but 2 inches at the top of the plush; we will add fiberfill stuffing in this opening.

    alt text

    Push the fiberfill stuffing into the hole to fill the plush. Use your fingers or a pencil to fill up the arms and legs. The stuffing will give the plush its shape in addition to acting as an insulator for the conductive thread stitching on the inside. Stitch the opening closed with embroidery or sewing thread to finish the project.

    alt text

    You can now use craft supplies such as glitter, paint, or other decorative accents to enhance the plush or hide your LEDs and stitching. To protect the battery holder and battery, you can make a small flap of felt to cover the pieces and secure with velcro for easy access.

    Here are a few examples of creative decorations on finished plush projects:

    Resources and Going Further

    Looking for another project? Let’s move on to Project 4: Night-Light Pennant in the LilyPad Sewable Electronics Kit.

    New!

    Night-Light Pennant with LilyMini ProtoSnap

    December 16, 2016

    Use the pre-programmed LilyMini ProtoSnap to make an interactive pennant that reacts to ambient light levels.

    These tutorials will guide you through more advanced projects and concepts:

    Insulation Techniques for e-Textiles

    Learn a few different ways to protect your conductive thread and LilyPad components in your next wearables project.

    Planning a Wearable Electronics Project

    Tips and tricks for brainstorming and creating a wearables project.

    Choosing a LilyPad Arduino for Your Project

    Not sure which LilyPad Arduino is right for you? We'll discuss the features of each and help you decide.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    LilyPad Basics: E-Sewing

    $
    0
    0

    LilyPad Basics: E-Sewing a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t581

    What Are Sewable Electronics?

    Sewable electronics combine traditional craft processes (sewing, fashion design, and textile design) with electrical engineering, computer science, and hardware skills.

    With sewable electronics, you can create e-textiles (electronic textiles), which are often wearable, flexible projects that look less like traditional electronics and more like craft and art projects. Many e-textile projects replace wiring with flexible conductive materials such as conductive thread and fabric. For the projects in this guide, we will be sewing circuits together with conductive thread.

    Suggested Reading

    If you are new to circuits as a concept, you may want to have a look at some of the tutorials below before continuing.

    What is a Circuit?

    Every electrical project starts with a circuit. Don't know what a circuit is? We're here to help.

    Voltage, Current, Resistance, and Ohm's Law

    Learn about Ohm's Law, one of the most fundamental equations in all electrical engineering.

    What is Electricity?

    We can see electricity in action on our computers, lighting our houses, as lightning strikes in thunderstorms, but what is it? This is not an easy question, but this tutorial will shed some light on it!

    Polarity

    An introduction to polarity in electronic components. Discover what polarity is, which parts have it, and how to identify it.

    What Is LilyPad?

    The LilyPad system is a set of sewable electronic pieces designed to help you build soft, sewable, interactive e-textile projects. Using LilyPad pieces is a great way to experiment with electronics through the lens of crafting. Each LilyPad piece has large conductive sew tabs for easy sewing and a rounded shape so as not to snag fabric or cut thread.

    alt text

    The LilyPad system was designed by Leah Buechley while pursuing her Ph.D. in computer science at the University of Colorado Boulder. The commercial version of the kit, which launched in 2007, was collaboratively designed by Leah and SparkFun Electronics. You can learn more about LilyPad at SparkFun.com/LilyPad.

    alt text

    LilyPad Creator Leah Buechley

    For more LilyPad tutorials check out our E-Textiles category

    To browse LilyPad products visit the LilyPad section of the SparkFun catalog

    ProtoSnap Components

    Some LilyPad pieces come in a ProtoSnap configuration, which means all of the individual components – such as LEDs, battery holder, switches, buttons, etc. – are attached to one another in a single functioning circuit board. This allows you to easily program your circuit to do what you want before embedding it in your project. ProtoSnap boards are designed to be easily snapped apart into individual pieces when you’re ready to begin creating LilyPad projects.

    ProtoSnap - LilyPad Development Board

    DEV-11262
    $59.95
    4
    ProtoSnap - LilyPad Development Simple

    DEV-11201
    $49.95
    ProtoSnap - LilyTwinkle

    DEV-11590
    $19.95
    1
    LilyPad LilyMini ProtoSnap

    DEV-14063
    $14.95

    This is slightly different than LilyPad products that come in a panel configuration. The LilyPad LEDs are attached together, but not in a functional circuit. You will need to snap them apart before sewing into a circuit.

    LilyPad LED Red (5pcs)

    DEV-14013
    $3.95
    LilyPad LED Yellow (5pcs)

    DEV-14014
    $3.95
    LilyPad Rainbow LED (6 Colors)

    DEV-13903
    $4.95
    LilyPad LED White (5pcs)

    DEV-13902
    $3.95

    What Is Conductive Thread?

    Conductive Thread is a specialty thread made with stainless steel fibers. It can be used instead of copper wiring to connect LilyPad (or other e-textile) pieces together to create circuits.

    If you are using a LilyPad kit such as the LilyPad Sewable Electronics Kit, you will have a conductive thread bobbin available to use.

    SparkFun carries a few conductive thread options:

    Conductive Thread - 60g (Stainless Steel)

    DEV-11791
    $41.95
    8
    Conductive Thread Bobbin - 30ft (Stainless Steel)

    DEV-10867
    $2.95
    3
    Conductive Thread Bobbin - 12m (Smooth, Stainless Steel)

    DEV-13814
    $3.95

    Sewing with Conductive Thread

    Most LilyPad projects use conductive thread to complete electrical circuits. The following sections will introduce you to some basic sewing techniques as well as a few special pointers for using conductive thread to build working circuits. Even if you’re already familiar with using a needle and thread, this section may still be useful to you, specifically where it pertains to sewing with LilyPad parts.

    alt text

    Securing Your Components

    Each LilyPad piece has large holes with conductive silver pads called sew tabs. These tabs are designed to give you plenty of room to pass a needle and thread through the hole several times. Before you begin stitching your circuit, identify the sew tabs you would like to connect, and orient them so they are easily accessible in your design. If following along with SparkFun templates, the pieces will have a specific location on the design for both ease of sewing and visual appeal.

    alt text

    We recommend using a small dot of hot glue (preferred) or fabric glue to attach each LilyPad piece to the fabric to keep it from moving while you sew. Make sure not to accidentally seal up the holes in the sew tabs.

    Glue LEDsPlace LEDs

    To help plan where the stitches will go, you can use a marker to draw lines between the components.

    Draw Lines

    Threading a Needle

    Cut a piece of conductive thread approximately 2 feet long. Push one end of the thread through the eye (opening) of the needle and pull through, leaving a tail of about 5 inches.

    alt text

    Before you begin sewing your project, you will need to tie a knot at the long end of the thread to prevent you from completely pulling it through the fabric. You can tie a simple overhand or square knot. The next sections will explain a few other knot methods.

    Starter Knot

    A starter knot is a method of starting your stitch with a knot directly on your fabric.

    alt text

    Quilter’s Knot

    The slightly more advanced quilter’s knot is a way to tie a quick, secure knot on the thread. After some practice, this knot can be tied very quickly.

    alt text

    Connecting To LilyPad Sew Tabs

    We’ll stitch conductive thread around LilyPad sew tabs in our circuits to connect the pieces together. It’s important that you make three to four loops each time you connect your thread around an empty sew tab and pull the thread snug with each pass. This ensures you have made a strong electrical and physical connection between the thread and the sew tab. Pull loops tight before continuing your stitch.

    alt text

    Sewing Basics

    After sewing loops around a sew tab, a running stitch will enable you to connect LilyPad pieces together with a continuous length of conductive thread. Follow these steps:

    Push the needle through the fabric about ¼" in the direction of your stitch path.

    alt text

    Pull the slack of the thread through so it sits flush with the fabric.

    alt text

    Push the needle back up through the fabric another ¼" along the stitch path.

    alt text

    Pull the slack of the thread through so it sits flush with the fabric.

    alt text

    Repeat this process to travel along the path to the next LilyPad piece you want to connect to, keeping stitches evenly spaced.

    alt text

    Running vs. Hidden Stitch

    In a basic running stitch, the stitching will be even on both sides of the fabric.

    alt text

    To hide the stitches so that they are not seen on the outside of the project, make a longer stitch on the back of the project and a very small stitch on the front of the project. This method is called a “hidden stitch.”

    alt text

    As you sew, flip your fabric over every so often to make sure the conductive thread isn’t getting knotted or tangled. If you are just starting out with sewing, your stitching may take some practice before it feels comfortable or easy. Remember to be patient with yourself and take your time while stitching. If your thread breaks, you can stitch onto existing conductive thread to continue the electrical connection.

    Connecting LilyPad Pieces

    Both running and hidden stitches will enable you to connect LilyPad components together with a single length of conductive thread. To connect two LilyPad pieces, continue stitching after completing three to four loops around the sew tab.

    alt text

    alt text

    Connecting Multiple LilyPad Pieces

    To connect more than two LilyPad pieces, instead of trimming your thread and starting over, continue stitching to the next piece, make three to four loops, and repeat as necessary. There is no need to use a new length of thread if the pieces will share a connection.

    alt text

    alt text

    Finishing Your Connection

    When you have completed connecting components, use a finishing knot. Thread tails can cause electrical shorts, so be sure to trim your thread afterward.

    alt text

    Checking for Conductive Thread Short Circuits

    Watch out for any loose threads or knot tails in your project. If any piece of the conductive thread from the positive (+) side of your circuit accidentally touches the negative (–) side, it can cause a short circuit. A short circuit connects the battery to itself and bypasses the rest of your project causing an unwanted amount of current draw from the battery. Stitching directly over stitches in another part of the circuit can also cause a short.

    alt text

    It’s important that your stitches do not cross over each other or touch other parts of the circuit. The batteries used in these projects shouldn’t burn or shock you if they short circuit (although they may heat up), but higher voltage projects or power sources could be dangerous.

    alt text

    Installing Your Battery and Testing Your Finished Circuit

    Once all your pieces are connected with conductive thread, your finished circuit needs a power source. Install your coin cell battery, positive (+) side up, into the battery holder. The image below shows how to place a battery in a LilyPad Coin Cell Battery Holder.

    alt text

    After completing the conductive thread connections, switch your circuit on, and see what it can do! If the circuit fails to work, you may have a short, a loose connection, a reversed component, or even something as simple as a dead battery.

    When you turn on the battery holder switch, current flows through the conductive thread to the other parts of your circuit.

    alt text

    Read more about current flow and electricity here:

    Or continue on to Project 1: Glowing Pin of the LilyPad Sewable Electronics Kit to build your own circuit.

    Troubleshooting

    As you work on e-sewing projects, you may encounter problems such as loose connections that keep LEDs from lighting or cause your circuit to malfunction. Most LilyPad tutorials have a troubleshooting section to help you identify and solve problems with your circuit.

    Circuit only working sometimes? Check for loose connections.

    If the conductive thread is not making a tight connection to the LilyPad piece’s sew tabs, current will not be able to flow through consistently. If the project moves, the conductive thread may pull away from the sew tab and disconnect the circuit. To fix, pull stitching tight with tweezers or a needle if possible. You may also sew over the top of existing thread to create more tension and hold the thread securely to a sew tab.

    alt text

    Circuit not working? Double check your polarity.

    Some LilyPad components are polarized, meaning electric current can only flow through them in one direction. If sewn into the circuit incorrectly, they will not function. Double check the labeled sew tabs before you stitch to make sure they are oriented correctly.

    alt text

    Other issues to check for:

    • Make sure the switch on your battery holder is in the ON position.
    • Check to see if your battery is dead. You can do so with a multimeter. Try installing a spare battery.
    • If following a project template, double check that the components are connected together in the right configuration

    If you are still having trouble, you can use a multimeter to check for continuity or issues with your circuit. Our How To Use a Multimeter tutorial will help you get started.

    Click here to view a pdf of Troubleshooting pages from the LilyPad Sewable Electronics Kit.

    Caring For Your Project

    Unlike copper wire, which has a coating, conductive thread is uninsulated. This means the thread behaves like bare wire and can accidentally short circuit if stray strands come in contact with each other.

    alt text

    To avoid any accidental short circuits after the project is stitched and tested, we recommend covering the thread with a thin layer of fabric glue, fabric paint, or an additional layer of fabric. This is especially important for projects that are wearable or three-dimensional. Never work on a metal surface when using conductive thread. For more detailed insulation instructions, take a look at this tutorial:

    Insulation Techniques for e-Textiles

    January 22, 2015

    Learn a few different ways to protect your conductive thread and LilyPad components in your next wearables project.

    Cleaning Your Project

    If your project gets dirty, remove the battery and carefully hand wash with mild detergent. Let your project air dry; a dryer can damage the LilyPad pieces or stitching.

    Resources and Going Further

    Ready to start stitching some circuits? Check out these projects from the LilyPad Sewable Electronics Kit:

    New!

    Light-Up Plush

    Craft a light-up plush with LilyPad LEDs controlled by pressing a button and sliding a switch in the creature's hands.
    New!

    Night-Light Pennant with LilyMini ProtoSnap

    Use the pre-programmed LilyMini ProtoSnap to make an interactive pennant that reacts to ambient light levels.
    New!

    Glowing Pin

    Create a quick and easy piece of e-textile art using a LilyPad LED, battery holder, conductive thread, and coin cell battery.
    New!

    Illuminated Mask

    Use LilyPad LEDs, a switched battery holder, and coin cell battery to make a fun light up mask for your next costume party.

    These tutorials will guide you through more advanced projects and concepts:

    Soft Circuits: LED Feelings Pizza

    Here we will learn how to say how you feel with pizza. Electric pizza.

    Dungeons and Dragons Dice Gauntlet

    A playful, geeky tutorial for a leather bracer that uses a LilyPad Arduino, LilyPad accelerometer, and seven segment display to roll virtual 4, 6, 8, 10, 12, 20, and 100 side dice for gaming.

    Twinkling Trick or Treat Bag

    Make a light up goodie bag with conductive thread, LEDs, and the LilyTwinkle!

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado


    Illuminated Mask

    $
    0
    0

    Illuminated Mask a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t582

    Introduction

    E-Textiles are a great way to add flair to your clothing and costumes, but crafting on a garment can be a challenge for your first project. Making an accessory is a great way to explore sewing circuits on a smaller scale.

    For this project, we’ll be using multiple LEDs in a circuit to create an illuminated mask. Rather than stitching just one LED to the battery holder (as we did in the Glowing Pin project), we’ll use a parallel circuit to connect all of the LEDs to the battery.

    Design and build time: 1 - 2 hours

    alt text

    This project is part of the LilyPad Sewable Electronics Kit, take a look at the other projects in the kit:

    Suggested Reading

    If this is your first sewable electronics project, we recommend you read our LilyPad Basics tutorial.

    New!

    LilyPad Basics: E-Sewing

    December 16, 2016

    Learn how to use conductive thread with LilyPad components.

    Materials and Tools

    Let’s go over all of the things you’ll need to sew your project together.

    LilyPad Sewable Electronics Kit

    KIT-13927
    $99.95

    Items included in the LilyPad Sewable Electronics Kit:

    alt text

    You will also need:

    • Pen, marker, or chalk
    • Scissors
    • Hot glue gun (with extra glue)
    • Optional: Craft supplies for decorating (feathers, sequins, buttons, etc.)

    Planning Your Project

    For this project we’ll be using the Illuminated Mask templates (download below or use the templates included with your kit). If needed, download and print the provided template. Right-click the image below and choose “Save Link As” to download the template to your computer.

    alt text

    Right-click and choose “Save Link As” or click image to download PDF

    There are two template pieces: a top layer and a bottom layer. Hold the top layer template up to your face to check for fit, and make any adjustments to the eye or nose shapes before tracing onto felt.

    Using a pen or marker, trace the template shapes onto the felt. Both templates will fit on one piece of felt, but feel free to mix and match colors for your design. The electronics will attach to the top layer, while the bottom layer will be used to give the mask extra support. Set aside the bottom layer for now.

    alt text

    Understanding Your Circuit

    To light up the mask, we will be connecting the LEDs to the battery holder with conductive thread using a parallel circuit layout. In a parallel circuit, components are connected to get the same amount of power running through them. Each LED in the mask will shine as brightly as the others by sharing a connection to the battery. Most of the e-textiles projects we make use parallel circuits.

    alt text

    Learn more about parallel circuits and e-textiles in our Multiple LED Circuits tutorial.

    Arranging Your Circuit

    Gather three LEDs (snap off of an LED panel if needed). Use the template as a guide to arrange your components on the felt, securing each piece with a dab of glue on the back to hold it in place. Double check that the (+) ends of the LEDs line up with the (+) tab of the battery holder.

    alt text

    Glue is hard to get a needle through and can interfere with making a strong electrical connection, so try not to get any in the sew tabs.

    You can use a pen or marker to draw lines from one LilyPad piece to another to provide a path to follow when you stitch. For an erasable option, try disappearing ink pens or chalk.

    alt text

    Stitching It Together

    If you need help sewing with conductive thread this tutorial covers the basics.

    STEP 1:

    Cut a long piece of conductive thread, thread the needle, and tie a knot at the end. Sew your first connection: starting from the positive sew tab of the battery holder, connect each of the three LEDs with a running stitch and three loops of conductive thread around each positive (+) sew tab. Tie and cut your thread.

    Finish your line of stitching by tying a finishing knot on the last (+) sew tab and trimming any excess thread.

    alt text

    STEP 2:

    With a new piece of thread, repeat the process for the negative side of the circuit – connecting the three LEDs’ negative sew tabs to one another and, finally, the negative sew tab on the battery holder. Tie a finishing knot, and trim any excess thread.

    alt text

    Installing Your Battery and Testing

    Insert the coin cell battery into the battery holder with the positive, labeled as (+), side facing up. Slide the switch to ON to see the LEDs light up. Remove the battery, and then continue to the Finishing Touches section.

    alt text

    How to place a battery in a LilyPad Battery Holder.

    Troubleshooting

    With any electronics project, there are times you will have to troubleshoot if your circuit isn’t working. If your circuit isn’t lighting up, try a new battery or check that your project is switched on. Check your sewing for any loose threads or ends that may be touching other parts of your circuit and causing a short circuit. Learn more about troubleshooting your project in the LilyPad Basics: E-Sewing tutorial.

    Finishing Touches

    After you’ve checked your circuit, it’s time to get creative with adding some details to the mask. With the battery removed, glue the second layer of felt on the back of the mask to add some extra stability and insulate the back of the circuit.

    alt text

    Next, cut small holes on either side of the mask with scissors or a hole punch, and tie the elastic to hold the mask on.

    alt text

    Add craft supplies such as glitter, paint, or other decorative accents to enhance or hide your LEDs and stitching. If you want to cover the battery holder on the front of the mask, feathers or big buttons can add pizzazz and hide the board. Make sure you leave an opening so you can replace the battery when necessary.

    Here are a few examples of creative decorations on finished masks:

    Resources and Going Further

    Looking for another project? Let’s move on to Project 2: Light-Up Plush in the LilyPad Sewable Electronics Kit.

    New!

    Light-Up Plush

    December 16, 2016

    Craft a light-up plush with LilyPad LEDs controlled by pressing a button and sliding a switch in the creature's hands.

    These tutorials will guide you through more advanced projects and concepts:

    Insulation Techniques for e-Textiles

    Learn a few different ways to protect your conductive thread and LilyPad components in your next wearables project.

    Planning a Wearable Electronics Project

    Tips and tricks for brainstorming and creating a wearables project.

    Choosing a LilyPad Arduino for Your Project

    Not sure which LilyPad Arduino is right for you? We'll discuss the features of each and help you decide.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Glowing Pin

    $
    0
    0

    Glowing Pin a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t580

    Introduction

    In this project, we’ll create a wearable pin using conductive thread to connect a LilyPad LED to a battery holder. Follow along by drawing your own design on a piece of fabric, or download and print one of SparkFun’s designs.

    Design and build time: 30 minutes — 1 hour

    glowing pin

    This is Project 1 from the LilyPad Sewable Electronics Kit, take a look at the other projects in the kit:

    Suggested Reading

    If this is your first sewable electronics project, we recommend you read our LilyPad Basics tutorial.

    New!

    LilyPad Basics: E-Sewing

    December 16, 2016

    Learn how to use conductive thread with LilyPad components.

    Materials and Tools

    Let’s go over all of the things you’ll need to sew your project together.

    LilyPad Sewable Electronics Kit

    KIT-13927
    $99.95

    Items included in the LilyPad Sewable Electronics Kit:

    alt text

    You Will Also Need:

    • Pen, marker, or chalk
    • Fabric to draw a design on or printable fabric (optional)
    • Scissors
    • Hot glue gun (with extra glue)
    • Printer if you are downloading and printing one of SparkFun’s pin designs

    Planning Your Project

    For this project, we’ll be using the Glowing Pin template (download below or use the template included with your kit). If needed, download and print the provided template. We've also provided some color and black and white designs to use with printable fabric for the top layer of the pin. Right-click the images below and choose “Save Link As” to download the template to your computer.

    alt text

    Right-click and choose “Save Link As” or click image to download PDF

    Printable Fabric Designs:

    alt textalt text

    Right-click and choose “Save Link As” or click image to download PDF

    After downloading a design, follow the directions on the package of your printable fabric to print them out. Feel free to create a larger pin by scaling the downloadable designs, if you’d like more room to work with or for a real statement piece.

    Trace the pin template on white felt and cut out. We’ll be building our circuit on the felt piece, then adding a decorative layer of fabric with designs on top of it. Trace and cut a slightly larger circle or SparkFun design out of thin fabric (or design your own out of felt) for the top layer of the pin.

    alt text

    Understanding Your Circuit

    This project is an example of a basic circuit– an electrical loop that travels from a power source along a path (called a trace) to a component (or components) that uses the electricity to function, and then back to the power source. For our project, we’ll use an LED (Light-Emitting Diode). When this loop is completed by stitching the pieces together with conductive thread traces, electricity from the power source is able to flow from the positive (+) side of the battery through to the LED (lighting it up) and back to the negative (–) side of the battery. This electric flow is called current. As you build projects with LilyPad pieces, you will learn different ways to design conductive thread circuits and experiment with additional pieces that help control or use the flow of electricity.

    alt text

    Take a look at the LED and battery holder. Notice that the silver sew tabs are labeled either positive or negative. Many electronic components have polarity, meaning electric current can only flow through them in one direction.

    alt text

    If hooked up incorrectly, they will not light up. The batteries in this kit are also polarized; they have a positive and negative side. Always check the labels on LilyPad pieces to make sure they are correctly oriented before sewing together a circuit.

    alt text

    Arranging Your Circuit

    Position the battery holder with the ON/OFF switch to the left side and the bottom two sew tabs close to the bottom edge of the felt. Use a small dot of hot glue in the center of the holder to attach it to the felt, as shown. Gluing the battery holder on this way leaves room for placing the LilyPad LED on the felt.

    alt text

    Remember: Glue is great for keeping your components in place, but it can interfere with your circuit. Try to keep glue clear of sew tabs.

    While planning the LED’s placement, note that it will need to be slightly above the center or toward the top half of the fabric so it doesn’t touch or overlap the battery holder.

    If you are using one of SparkFun’s pre-made designs, hold the design over the felt, and use a fabric marker or chalk to mark where the LED should be placed to shine through. Gather one LED (snap off of an LED panel if needed).

    Before attaching the LED, rotate it so the (+) and (–) symbols on the LED board align with the (+) and (–) symbols on the battery holder’s sew tabs. Use a small dab of hot glue on the center of the front of the board to secure to the felt. Be careful not to cover the holes with glue – we’ll need those to sew through later.

    alt text

    Stitching It Together

    If you need help sewing with conductive thread, this tutorial covers the basics.

    STEP 1:

    Cut a long piece of conductive thread, thread the needle, and tie a knot at the end. Now, it’s time to connect the LED to the battery holder with the conductive thread. One line of stitching will connect the positive (+) side of the battery holder to the positive end of the LED. A second line of stitching will connect the negative (–) sides of the boards and complete the circuit.

    alt text

    STEP 2:

    Finish your first line of stitching by tying a finishing knot on the sew tab and trimming your excess thread.

    alt text

    Don’t forget! You’ll need to tie a new knot at the end of your thread before you begin the next section of stitching.

    STEP 3:

    Repeat the process with a new piece of thread to connect the negative side of the battery holder to the negative end of the LED. Be careful not to let the stitches touch the path used for the positive connections, as that would cause a short circuit. Trim any thread tails before testing. Now, the circuit is complete!

    alt text

    Installing Your Battery and Testing

    Insert the coin cell battery with the positive side facing up, labeled as (+), into the opening on the battery holder across from the ON/OFF switch. Turn on the switch to allow current to flow through the circuit. Turn off the switch when not in use to prolong battery life.

    alt text

    How to place a battery in a LilyPad Battery Holder..

    Troubleshooting

    With any electronics project, there are times you will have to troubleshoot if your circuit isn’t working. If your circuit isn’t lighting up, try a new battery or check that your project is switched on. Check your sewing for any loose threads or ends that may be touching other parts of your circuit and causing a short circuit. Learn more about troubleshooting your project in the LilyPad Basics: E-Sewing tutorial.

    Finishing Touches

    alt text

    With the battery removed, use a hot glue gun or thread to attach your fabric design over your felt circle so the LED shines through. Draw a design on the fabric, if you’d like (or see design templates in the Planning Your Project step). Turn the project over, and attach an adhesive pin back to finish up your wearable art!

    alt text

    Here are a few examples of creative glowing pins:

    Resources and Going Further

    Looking for another project? Let’s move on to Project 2: Illuminated Mask in the LilyPad Sewable Electronics Kit.

    New!

    Illuminated Mask

    December 16, 2016

    Use LilyPad LEDs, a switched battery holder, and coin cell battery to make a fun light up mask for your next costume party.

    These tutorials will guide you through more advanced projects and concepts:

    Insulation Techniques for e-Textiles

    Learn a few different ways to protect your conductive thread and LilyPad components in your next wearables project.

    Planning a Wearable Electronics Project

    Tips and tricks for brainstorming and creating a wearables project.

    Choosing a LilyPad Arduino for Your Project

    Not sure which LilyPad Arduino is right for you? We'll discuss the features of each and help you decide.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Powering LilyPad LED Projects

    $
    0
    0

    Powering LilyPad LED Projects a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t435

    Introduction

    One of the most commonly asked questions when getting started with e-textiles is “How many LEDs can I put in my project?” In this guide, we will cover conductive thread’s resistance and how that affects powering LEDs, calculations to predict battery and power requirements, and some construction tips.

    alt text

    Suggested Reading

    If any of the following topics sound unfamiliar to you, we recommend checking out the corresponding tutorial before continuing.

    If this is your first time working with e-textiles, we recommend starting with this tutorial:

    New!

    LilyPad Basics: E-Sewing

    December 17, 2016

    Learn how to use conductive thread with LilyPad components.

    Conductive Thread Resistance

    One of the most important things to consider when building a wearable project is the resistance of conductive thread. Unlike copper wire, which has very little resistance, conductive thread’s resistance will vary depending on the metal used to make the thread and the thickness of the thread. Most conductive threads list resistance in Ohms/Ft. The lower this number is, the better, because less resistance means more electricity can get through to the components used in your project.

    alt text

    The basic electrical property Ohm’s Law states that running an electrical current through a material high in resistance causes the voltage to drop. The higher the current, the greater the voltage drop. This means that even though a LiPo battery powering your LilyPad may put out 3.7 volts, by the time it gets through the thread to your components, it may drop to 3.0 volts or less.

    Many electrical components, such as LEDs, need a certain voltage to function properly. For example, in a project with LilyPad LEDs if the voltage drops below 3 volts, a blue LED will stop working, followed by the green and finally the red. To get full-color output from RGB LEDs like the LilyPad RGB LED Board, you should always try to run at 3 volts or above.

    Forward voltages of LilyPad LEDs

    LilyPad LEDForward Voltage
    Blue3.2 Volts
    Green3.2 Volts
    Pink2.5 Volts
    Purple (retired)2.8 Volts
    Red2.0 Volts
    White3.3 Volts
    Yellow2.0 Volts

    Forward voltages of LilyPad RGB LEDs:

    LilyPad LEDRed LED Forward VoltageGreen LED Forward VoltageBlue LED Forward Voltage
    LilyPad Tri-Color LED2.0 Volts3.5 Volts3.5 Volts
    LilyPad Pixel Board2.2 Volts3.4 Volts3.4 Volts

    To minimize voltage drop, we’ll need to decrease the resistance of the power connections. There are a few ways to do this:

    • Keep the length of the power connections as short as possible. Because the resistance increases with length, if you reduce the length, you’ll reduce the resistance.

    • Reduce the resistance of the thread itself. Thicker thread has a lower resistance than thinner thread, and using multiple strands at a time reduces the resistance even further.

    TIP:
    Use a non conductive thread to stitch bundled thread (either placed together or braided) to your base fabric. Leave enough open spaces in the stitching so you are able to stitch conductive thread to the larger thread bundle when connecting components. This video from e-textile expert Lynne Bruning shows this technique at around the 4:10 mark:

    Conductive Thread Alternatives:

    For large projects that require thread to travel long distances, projects with a lot of power-hungry pieces such as a large amount of LilyPad Pixel Boards, or in spots where thread may break under stress, here are some alternatives that work well for wearables:

    Conductive Ribbon

    Conductive Ribbon - 3-Conductor (1 yard)

    DEV-10172
    $5.95

    Specialty nylon ribbon with flexible stranded wire woven into it is a great alternative to conductive thread with low resistance. You will need to solder to the tinsel within the ribbon in order to use in a project.

    Conductive Fabric Traces

    Conductive Fabric - 12"x13" MedTex130

    DEV-10070
    $29.95
    Conductive Fabric - 12"x13" Ripstop

    DEV-10056
    $11.95
    4

    You can create your own low resistance traces using thin strips of conductive fabric. We recommend using iron-on adhesive to attach to fabric or ribbon, then using conductive thread to hand stitch components to the traces.

    alt text

    Don’t forget to insulate the fabric traces as you would conductive thread.

    Stranded Wire

    Ribbon Cable - 6 wire (15ft)

    CAB-10646
    $2.95
    2

    Another alternative is to switch from conductive thread to traditional wire. Wire has a much lower resistance than thread, allowing you to use more LEDs than a conductive thread circuit. You’ll have to switch from sewing to soldering, but it’s easy to solder wires to the same sew tabs to which you would normally connect thread.

    Wire is prone to breaking if it is flexed repeatedly. For wearable projects that require maximum flexibility, use stranded wire (not solid), and look for special silicone-jacketed wire that is extremely flexible. For projects that will be washed, water may wick into exposed stranded wire, becoming trapped and potentially corroding it over time. Apply a small dab of silicone sealant to the cut ends of the wire to prevent this from happening.

    If you have never soldered before or worked with wire, we recommend visiting the following tutorials.

    How to Solder - Through-hole Soldering

    This tutorial covers everything you need to know about through-hole soldering.

    Working with Wire

    How to strip, crimp and work with wire.

    How Long Will My Project Run on Battery Power?

    To figure out how long your project will run on battery power, you need to know two things: how much current your project uses and the capacity of your battery.

    You can measure exactly how much current your project uses by measuring it with a multimeter, but we can also make a pretty accurate guess by looking at the LED datasheets and doing some math.

    A typical LilyPad LED uses 20mA of current at full brightness. Multiply that by the number of LEDs you’re using, add 10mA for the LilyPad that’s running everything, and you’ll have an estimate of your average current draw.

    Example:
    A project with 10 LilyPad LEDs controlled by a LilyPad Arduino

    20mA * 10 + 10mA = 210mA

    A single LilyPad Pixel Board will use 40mA when it’s set to white (all three internal LEDs fully on). For a worst-case estimate, you could multiply that by the number of pixels in your project.

    However, you’ll probably be displaying different colors on your LilyPad Pixel Boards and turning them off entirely at times. The resistance in the threads will also drop the voltage, meaning the LilyPixels will run slightly dimmer and use less current. Usually, it’s safe to halve the above estimate, which gives us 20mA.

    For more detailed information on working with LilyPad Pixel Boards, take a look at our LilyPad Pixel Board Hookup Guide.

    Battery Capacity

    Now, let’s look at the battery. Battery capacity is given in milliamp-hours (mAh). This number tells you how many milli-amps (mA) a full battery can provide for one hour before it’s empty. The e-Textiles Battery that comes with most LilyPad Arduino kits has a 110mAh capacity. For many projects, especially ones with a large number of LEDs, you will probably want to use a higher capacity battery for a longer run time.

    To find out how long a battery will last, use this formula:
    Hours = Battery mAh / Project mA

    Let's use the calculation above to see how long a 110mAh battery will power the project we used in the last example:

    0.52 hrs = 110mAh / 210mA

    Thus, an e-Textile battery will only power the project for approximately half an hour. Here’s an instance where a larger capacity battery would make sense, if the project needs to operate for a long time, such as during an event or showcase. The trade-off is that a higher capacity battery is also physically larger – make sure to plan accordingly for proper battery storage/attachment on your project to reduce strain on the wires and fabric.

    Here are some typical runtimes for various SparkFun batteries and numbers of LilyPad LEDs/LilyPixels:

    Number of LEDs1251020
    Battery NameBattery mAhHours of Operation
    Polymer Lithium Ion Battery - 40mAh401.30.80.40.20.1
    E-Textiles Battery - 110mAh (2C Discharge)1103.72.21.00.50.3
    Coin Cell Battery - 20mm (CR2032) * 2508.35.02.31.2.61
    Polymer Lithium Ion Battery - 400mAh40013.38.03.61.91.0
    Polymer Lithium Ion Battery - 850mAh85028.317.07.74.02.1
    Polymer Lithium Ion Battery - 1000mAh100033.320.09.14.82.4
    Polymer Lithium Ion Battery - 2000mAh200066.740.018.29.54.9
    Polymer Lithium Ion Battery - 6Ah6000200.0120.054.528.614.6

    * Note: the Coin Cell Battery is non-rechargeable.

    Resources and Going Further

    Ready to start stitching some circuits? Check out these projects from the LilyPad Sewable Electronics Kit:

    New!

    Light-Up Plush

    Craft a light-up plush with LilyPad LEDs controlled by pressing a button and sliding a switch in the creature's hands.
    New!

    Night-Light Pennant with LilyMini ProtoSnap

    Use the pre-programmed LilyMini ProtoSnap to make an interactive pennant that reacts to ambient light levels.
    New!

    Glowing Pin

    Create a quick and easy piece of e-textile art using a LilyPad LED, battery holder, conductive thread, and coin cell battery.
    New!

    Illuminated Mask

    Use LilyPad LEDs, a switched battery holder, and coin cell battery to make a fun light up mask for your next costume party.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Lessons in Algorithms

    $
    0
    0

    Lessons in Algorithms a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t604

    Introduction

    Earlier this year, Nathan Seidle, founder of SparkFun, created the Crowdsourcing Algorithms Challenge (aka, the Speed Bag Challenge). After numerous fantastic entries, one was chosen. The winner, Barry Hannigan, was asked to write up his process involved in solving this problem. This article is Barry’s winning approach to solving real-world problems, even when the problem is not tangibly in front of you.

    Firmware Resources

    You can view Barry’s code by clicking the link below.


    Barry's Speed Bag Challenge GitHub Repo


    As the winner of Nate’s Speed Bag Challenge, I had the wonderful opportunity to meet with Nate at SparkFun’s headquarters in Boulder, CO. During our discussions, we thought it would be a good idea to create a tutorial describing how to go about solving a complex problem in an extremely short amount of time. While I’ll discuss specifics to this project, my hope is that you’ll be able to apply the thought process to your future projects—big or small.

    Where to Start

    In full-fledged software projects, from an Engineer’s perspective, you have four major phases:

    • Requirements
    • Design
    • Implementation
    • Test

    Let’s face it; the design and coding is what everyone sees as interesting, where their creative juices can flow and the majority of the fun can be had. Naturally, there is the tendency to fixate on a certain aspect of the problem being solved and jump right in designing and coding. However, I will argue that the first and last phase can be the most important in any successful project, be it large or small. If you doubt that, consider this: my solution to the speed bag problem was designed wickedly fast, and I didn’t have a bag to test it on. But, with the right fixes applied in the end, the functionality was tested to verify that it produced the correct results. Conversely, a beautiful design and elegant implementation that doesn’t produce the required functionality will surely be considered a failure.

    I didn’t mention prototype as a phase, because depending on the project it can happen in different phases or multiple phases. For instance, if the problem isn’t fully understood, a prototype can help figure out the requirements, or it can provide a proof of concept, or it can verify the use of a new technology. While important, prototyping is really an activity in one or more phases.

    Getting back to the Speed Bag Challenge, in this particular case, even though it is a very small project, I suggest that you spend a little time in each of the four areas, or you will have a high probability of missing something important. To get a full understanding of what’s required, let’s survey everything we had available as inputs. The web post for the challenge listed five explicit requirements, which you can find here. Next, there was a link to Nate’s Github repository that had information on the recorded data format and a very brief explanation of how the speed bag device would work.

    In this case, I would categorize what Nate did with the first speed bag counter implementation as a prototype to help reveal additional requirements. From Nate’s write-up on how he built the system, we know it used an accelerometer attached to the base of a speed bag and that the vibration data samples about every 2ms are to be used to count punches. We also now know that applying a polynomial smoothing function and looking for peaks above a threshold doesn’t accurately detect punches.

    While trying not to be too formal for a small project, I kept these objectives (requirements) in mind while working the problem:

    • The algorithm shall be able to produce the correct number of hits from the recorded data sets
    • The solution shall be able to run on 8-bit and 32-bit micros
    • Produce documentation and help others learn from the solution put forth
    • Put code and documents in a public repository or website
    • Disclose the punch count and the solution produced for the Mystery data sets
    • Accelerometer attached to top of speed bag base, orientation unknown except +Z is up -Z is down
    • Complex data patterns will need more than polynomial filtering; you need to adjust to incoming data amplitude variations—as Nate suspects, resonance is the likely culprit
    • You have 15 days to complete (Yikes!)

    Creating the Solution

    As it goes in all projects, now that you know what should be done, the realization that there isn’t enough time sets in. Since I didn’t have the real hardware and needed to be able to visually see the output of my algorithm, I started working it out quickly in Java on my PC. I built in a way to plot the results of the waveforms on my screen. I’ve been using NetBeans for years to do Java development, so I started a new speed bag project. I always use JFreeChart library to plot data, so I added it to my project. Netbeans has a really good IDE and built-in GUI designer. All I had to do was create a GUI layout with a blank panel where I want the JFreeChart to display and then, at run time, create the JFreeChart object and add it to the panel. All the oscilloscope diagrams in this article were created by the JFreeChart display. Here is an image from my quick and dirty oscilloscope GUI design page.

    NetBeans IDE

    This algorithm was needed in a hurry, so my first pass is to be very object oriented and use every shortcut afforded me by using Java. Then, I’ll make it more C like in nature as I nail down the algorithm sequence. I jumped right in and plotted the X, Y and Z wave forms as they came from the recorded results. Once I got a look at the raw data, I decided to remove any biases first (i.e., gravity) and then sum the square of each waveform and take the square root. I added some smoothing by way of averaging a small number of values and employed a minimum time between threshold crossings to help filter out spikes. All in all, this seemed to make the data even worse on the plot. I decided to throw away X and Y, since I didn’t know in what orientation it was mounted and if it would be mounted the same on different speed bag platforms anyway. To my horror, even with just the Z axis, it still just looked like a mess of noise! I’m seeing peaks in the data way too close together. Only my minimum time between thresholds gate is helping make some sense of the punch count, but there really isn’t anything concrete in the data. Something’s not adding up. What am I missing?

    Below is an image of the runF1 waveform. The blue signal is the filtered z axis, and the red line is a threshold for counting punches. As I mentioned, if it weren’t for my 250ms minimum between punch detections, my counter would be going crazy. Notice the way I have introduced two 5 millisecond delays in my runF1() processing so thresholding would be a little better if the red line were moved to the right by 10 milliseconds. I’ll talk more about aligning signals later in this article, but you can see in this image how time aligning signals is crucial for getting accurate results.

    First filter with many peaks

    The blue signal is the filtered z axis, and the red line is a threshold for counting punches.

    If you look at the virtual oscilloscope output, you can see that between millisecond 25,000 and 26,000, which is 1 second in time, there are around nine distinct acceleration events. No way Nate is throwing nine punches in a second. Exactly how many punches should I expect to see per second? Back to the drawing board. I need another approach. Remember humility is your friend; if you just rush in on your high horse you usually will be knocked off it in a hurry.

    Understand the Domain

    Typically the requirements are drafted in the context of the domain of the problem that’s being solved, or some design aspects are developed from a requirement with domain knowledge applied. I don’t know the first thing about boxing speed bags, so time to do some Googling.

    The real nugget I unearthed was that a boxer hits a speed bag, and it makes three contacts with the base: once forward (in punch direction), then it comes all the way back (opposite of punch direction) and strikes the base, and then it goes all the way forward again striking the base (in punch direction). Then the boxer punches it on its way back toward the boxer. This actually gives four opportunities to generate movement to the base, once from the shock of the boxer contacting the bag, and then three impacts with the base.

    Now, what I see on the waveforms makes more sense. There isn’t a shock of the bag hitting the base once per punch. My second thought was how many punches can a boxer throw at a speed bag per second. Try as I might, I could not find a straight answer to this question. I found lots of websites with maximum shadow boxing punches and actual punches being thrown maximums but not a maximum for a speed bag. Time to derive my own conclusion: I thought about how far the speed bag must travel per punch and concluded that there must be a minimum amount of force to make the bag travel the distance it needs to impact the base three times. Since I’m not a boxer, all I could do is visualize hitting the bag as slowly as possible and it making three contacts. I concluded from the video in my mind’s eye that it would be difficult to hit a bag less than twice per second. OK, that’s a minimum; how about a maximum? Again, I summoned my mind’s eye video and this time moved my fist to strike the imaginary bag. I concluded with the distance the bag needed to travel and the amount of time to move a fist in and out of the path of the bag that about four per second is all that is possible, even with a skilled boxer. OK, it’s settled. I need to find events in the data that are happening between 2 and 4 hertz. Time to get back to coding and developing!

    Build a little, Test a little, Learn a lot

    While everyone’s brain works a little differently, I suggest that you try an iterative strategy, especially when you are solving a problem that does not have a clearly defined methodology going into it. I also suggest that when you feel you are ready to make a major tweak to an algorithm, you make a copy of the algorithm before starting to modify the copy, or start with an empty function and start pulling in pieces of the previous iteration. You can use source control to preserve your previous iteration, but I like having the previous iteration(s) in the code so I can easily reference it when working on the next iteration. I usually don’t like to write more than 10 or 20 lines of code without at minimum verifying it complies, but I really want to run it and print something out as confirmation that my logic and assumptions are correct. I’ve done this my entire career and will usually complain if I don’t have target hardware available to actually run what I’m coding. Around 2006, I heard a saying from a former Rear Admiral:

    Build a little, Test a little, Learn a lot.

    -Wayne Meyers, Rear Admiral, U.S. Navy

    I really identify with that statement, as it succinctly states why I always want to keep running and testing what I’m writing. It either allows you to confirm your assumptions or reveals you are heading down the wrong path, allowing you to quickly get on the right path without throwing away a lot of work. This was yet another reason that I chose Java as my prototype platform, as I could quickly start running and testing code plus graph it out visually, in spite of not having the actual speed bag hardware.

    Additionally, you will see in the middle of all six runFx() functions there is code that keeps track of the current time in milliseconds and verifies that the time stamp delta in milliseconds has elapsed or it sleeps for 1 millisecond. This allowed me to watch the data scroll by in my Java plotting window and see how the filtering output looks. I passed in X, Y and Z acceleration data along with an X, Y and Z average value. Since I only used Z data in most algorithms, I started cheating and sending in other values to be plotted, so it’s a little confusing when looking at the graphs of one through five since they don’t match the legend. However, plotting in real time allowed me to see the data and watch the hit counter increment. I could actually see and feel a sense of the rhythm into which the punches were settling and how the acceleration data was being affected by the resonance at prolonged constant rhythm. In addition to the visual output using the Java System.out.println() function, I can output data to a window in the NetBeans IDE.

    If you look in the Java subdirectory in my GitHub repository, there is a file named MainLoop.java. In that file, I have a few functions named run1() through run6(). These were my six major iterations of the speed bag algorithm code.

    Here are some highlights for each of the six iterations.

    runF1

    runF1() used only the Z axis, and employed weak bias removal using a sliding window and fixed amplification of the filtered Z data. I created an element called delay, which is a way to delay input data so it could be aligned later with output of averaged results. This allowed the sliding window average to be subtracted from Z axis data based on surrounding values, not by previous values. Punch detection used straight comparison of amplified filter data being greater than average of five samples with a minimum of 250 milliseconds between detections.

    runF2

    runF2() used only Z axis, and employed weak bias removal via a sliding window but added dynamic beta amplification of the filtered Z data based on the average amplitude above the bias that was removed when the last punch was detected. Also, a dynamic minimum time between punches of 225ms to 270ms was calculated based on delta time since last punch was detected. I called the amount of bias removed noise floor. I added a button to stop and resume the simulation so I could examine the debug output and the waveforms. This allowed me to see the beta amplification being used as the simulation went along.

    runF3

    runF3() used X and Z axis data. My theory was that there might be a jolt of movement from the punching action that could be additive to the Z axis data to help pinpoint the actual punch. It was basically the same algorithm as RunF2 but added in the X axis. It actually worked pretty well, and I thought I might be onto something here by correlating X movement and Z. I tried various tweaks and gyrations as you can see in the code lots of commented out experiments. I started playing around with what I call a compressor, which took the sum of five samples to see if it would detect bunches of energy around when punches occur. I didn’t use it in the algorithm but printed out how many times it crossed a threshold to see if it had any potential as a filtering element. In the end, this algorithm started to implode on itself, and it was time to take what I learned and start a new algorithm.

    runF4

    In runF4(), I increased the bias removal average to 50 samples. It started to work in attenuation and sample compression along with a fixed point LSB to preserve some decimal precision to the integer attenuate data. Since one of the requirements was this should be able to run on 8-bit microcontrollers, I wanted to avoid using floating point and time consuming math functions in the final C/C++ code. I’ll speak more to this in the components section, but, for now, know that I’m starting to work this in. I’ve convinced myself that finding bursts of acceleration is the way to go. At this point, I am removing the bias from both Z and X axis then squaring. I then attenuate each, adding the results together but scaling X axis value by 10. I added a second stage of averaging 11 filtered values to start smoothing the bursts of acceleration. Next, when the smoothed value gets above a fixed threshold of 100, the unsmoothed combination of Z and X squared starts getting loaded into the compressor until 100 samples have been added. If the compressor output of the 100 samples is greater than 5000, it is recorded as a hit. A variable time between punches gate is employed, but it is much smaller since the compressor is using 100 samples to encapsulate the punch detection. This lowers the gate time to between 125 and 275 milliseconds. While showing some promise, it was still too sensitive. While one data set would be spot on another would be off by 10 or more punches. After many tweaks and experiments, this algorithm began to implode on itself, and it was once again time to take what I’ve learned and start anew. I should mention that at this tim I’m starting to think there might not be a satisfactory solution to this problem. The resonant vibrations that seem to be out of phase with the contacts of the bag just seems to wreak havoc on the acceleration seen when the boxer gets into a good rhythm. Could this all just be a waste of time?

    runF5

    runF5()’s algorithm started out with the notion that a more formal high pass filter needed to be introduced rather than an average subtracted from the signal. The basic premise of the high pass filter was to use 99% of the value of new samples added to 1% of the value of average. An important concept added towards the end of runF5’s evolution was to try to simplify the algorithm by removing the first stage of processing into its own file to isolate it from later stages. Divide and Conquer; it’s been around forever, and it really holds true time and time again. I tried many experiments as you can see from the many commented out lines in the algorithm and in the FrontEndProcessorOld.java file. In the end, it was time to carry forward the new Front End Processor concept and start anew with divide and conquer and a need for a more formal high pass filter.

    runF6

    With time running out, it’s time to pull together all that has been learned up to now, get the Java code ready to port to C/C++ and implement real filters as opposed to using running averages. In runF6(), I had been pulling together the theory that I need to filter out the bias on the front end with a high pass filter and then try to use a low pass filter on the remaining signal to find bursts of acceleration that occur at a 2 to 4 Hertz frequency. No way was I going to learn how to calculate my own filter tap values to implement the high and low pass filters in the small amount of time left before the deadline. Luckily, I discovered the t-filter web site. Talk about a triple play. Not only was I able to put in my parameters and get filter tap values, I was also able to leverage the C code it generated with a few tweaks in my Java code. Plus, it converted the tap values to fixed point for me! Fully employing the divide and conquer concept, this final version of the algorithm introduced isolated sub algorithms for both Front End Processor and Detection Processing. This allowed me to isolate the two functions from each other except for the output signal of one becoming the input to the other, which enabled me to focus easily on the task at hand rather than sift through a large group of variables where some might be shared between the two stages.

    With this division of responsibility, it is now easy to focus on making the clear task of the Front End Processor to remove the bias values and output at a level that is readily acceptable for input into the Detection Processor. Now the Detection processor can clearly focus on filtering and implementing a state machine that can pick out the punch events that should occur between 2 and 4 times per second.

    One thing to note is that this final algorithm is much smaller and simpler than some of the previous algorithms. Even though its software, at some point in the process you should still do a technique called Muntzing. Muntzing is a technique to go back and look at what can be removed without breaking the functionality. Every line of code that is removed is one less line of code that can have a bug. You can Google Earl “Madman” Muntz to get a better understanding and feel for the spirit of Muntzing.

    Final output of DET

    Final output of DET

    Above is the visual output from runF6. The Green line is 45 samples delayed of the output of the low pass filter, and the yellow line is an average of 99 values of the output of the low pass filter. The Detection Processor includes a detection algorithm that detects punches by tracking min and max crossings of the Green signal using the Yellow signal as a template for dynamic thresholding. Each minimum is a Red spike, and each maximum is a Blue spike, which is also a punch detection. The timescale is in milliseconds. Notice there are about three blue spikes per second inside the 2 to 4Hz range predicted. And the rest is history!

    Algorithm Components

    Here is a brief look at each type of component I used in the various algorithms.

    Delay

    This is used to buffer a signal so you can time align it to some other operation. For example, if you average nine samples and you want to subtract the average from the original signal, you can use a delay of five samples of the original signal so you can use values that are itself plus the four samples before and four samples after.

    Attenuate

    Attenuation is a simple but useful operation that can scale a signal down before it is amplified in some fashion with filtering or some other operation that adds gain to the signal. Typically attenuation is measured in decibels (dB). You can attenuate power or amplitude depending on your application. If you cut the amplitude by half, you are reducing it by -6 dB. If you want to attenuate by other dB values, you can check the dB scale here. As it relates to the Speedbag algorithm, I’m basically trying to create clear gaps in the signal, for instance squelching or squishing smaller values closer to zero so that squaring values later can really push the peaks higher but not having as much effect on the values pushed down towards zero. I used this technique to help accentuate the bursts of acceleration versus background vibrations of the speed bag platform.

    Sliding Window Average

    Sliding Window Average is a technique of calculating a continuous average of the incoming signal over a given window of samples. The number of samples to be averaged is known as the window size. The way I like to implement a sliding window is to keep a running total of the samples and a ring buffer to keep track of the values. Once the ring buffer is full, the oldest value is removed and replaced with the next incoming value, and the value removed from the ring buffer is subtracted from the new value. That result is added to the running tally. Then simply divide the running total by the window size to get the current average whenever needed.

    Rectify

    This is a very simple concept which is to change the sign of the values to all positive or all negative so they are additive. In this case, I used rectification to change all values to positive. As with rectification, you can use a full wave or half wave method. You can easily do full wave by using the abs() math function that returns the value as positive. You can square values to turn them positive, but you are changing the amplitude. A simple rectify can turn them positive without any other effects. To perform half wave rectification, you can just set any value less than zero to zero.

    Compression

    In the DSP world Compression is typically defined as compressing the amplitudes to keep them in a close range. My compression technique here is to sum up the values in a window of samples. This is a form of down-sampling as you only get one sample out each time the window is filled, but no values are being thrown away. It’s a pure total of the window, or optionally an average of the window. This was employed in a few of the algorithms to try to identify bursts of acceleration from quieter times. I didn’t actually use it in the final algorithm.

    FIR Filter

    Finite Impulse Response (FIR) is a digital filter that is implemented via a number of taps, each with its assigned polynomial coefficient. The number of taps is known as the filter’s order. One strength of the FIR is that it does not use any feedback, so any rounding errors are not cumulative and will not grow larger over time. A finite impulse response simply means that if you input a stream of samples that consisted of a one followed by all zeros, the output of the filter would go to zero within at most the order +1 amount of 0 value samples being fed in. So, the response to that single sample of one lives for a finite amount of samples and is gone. This is essentially achieved by the fact there isn’t any feedback employed. I’ve seen DSP articles claim calculating filter tap size and coefficients is simple, but not to me. I ended up finding an online app called tFilter that saved me a lot of time and aggravation. You pick the type of filter (low, high, bandpass, bandstop, etc) and then setup your frequency ranges and sampling frequency of your input data. You can even pick your coefficients to be produced in fixed point to avoid using floating point math. If you’re not sure how to use fixed point or never heard of it, I’ll talk about that in the Embedded Optimization Techniques section.

    Embedded Optimization Techniques

    Magnitude Squared

    Mag Square is a technique that can save computing power of calculating square roots. For example, if you want to calculate the vector for X and Z axis, normally you would do the following: val = sqr((X * X) + (Y * Y)). However, you can simply leave the value in (X * X) + (Y * Y), unless you really need the exact vector value, the Mag Square gives you a usable ratio compared to other vectors calculated on subsequent samples. The numbers will be much larger, and you may want to use attenuation to make them smaller to avoid overflow from additional computation downstream.

    I used this technique in the final algorithm to help accentuate the bursts of acceleration from the background vibrations. I only used Z * Z in my calculation, but I then attenuated all the values by half or -6dB to bring them back down to reasonable levels for further processing. For example, after removing the bias if I had some samples around 2 and then some around 10, when I squared those values I now have 4 and 100, a 25 to 1 ratio. Now, if I attenuate by .5, I have 2 and 50, still a 25 to 1 ratio but now with smaller numbers to work with.

    Fixed Point

    Using fixed point numbers is another way to stretch performance, especially on microcontrollers. Fixed point is basically integer math, but it can keep precision via an implied fixed decimal point at a particular bit position in all integers. In the case of my FIR filter, I instructed tFilter to generate polynomial values in 16-bit fixed point values. My motivation for this was to ensure I don’t use more than 32-bit integers, which would especially hurt performance on an 8-bit microcontroller.

    Rather than go into the FIR filter code to explain how fixed point works, let me first use a simple example. While the FIR filter algorithm does complex filtering with many polynomials, we could implement a simple filter that outputs the same input signal but -6dB down or half its amplitude. In floating point terms, this would be a simple one tap filter to multiply each incoming sample by 0.5. To do this in fixed point with 16 bit precision, we would need to convert 0.5 into its 16-bit fixed point representation. A value of 1.0 is represented by 1 * (216) or 65,536. Anything less than 65536 is a value less than 1. To create a fixed point integer of 0.5, we simply use the same formula 0.5 * (216), which equals 32,768. Now we can use that value to lower the amplitude by .5 of every sample input. For example, say we input into our simple filter a sample with the value of 10. The filter would calculate 10 * 32768 = 327,680, which is the fixed point representation. If we no longer care about preserving the precision after the calculations are performed, it can easily be turned back into a non-fixed point integer by simply right shifting by the number of bits of precision being used. Thus, 327680 >> 16 = 5. As you can see, our filter changed 10 into 5 which of course is the one half or -6dB we wanted out. I know 0.5 was pretty simple, but if you had wanted 1/8 the amplitude, the same process would be used, 65536 * .125 = 8192. If we input a sample of 16, then 16 * 8192 = 131072, now change it back to an integer 131072 >> 16 = 2. Just to demonstrate how you lose the precision when turning back to integer (the same as going float to integer) if we input 10 into the 1/8th filter it would yield the following, 10 * 8192 = 81920 and then turning it back to integer would be 81920 >> 16 = 1, notice it was 1.25 in fixed point representation.

    Getting back to the FIR filters, I picked 16 bits of precision, so I could have a fair amount of precision but balanced with a reasonable amount of whole numbers. Normally, a signed 32-bit integer can have a range of - 2,147,483,648 to +2,147,483,647, however there now are only 16 bits of whole numbers allowed which is a range of -32,768 to +32,767. Since you are now limited in the range of numbers you can use, you need to be cognizant of the values being fed in. If you look at the FEPFilter_get function, you will see there is an accumulator variable accZ which sums the values from each of the taps. Usually if your tap history values are 32 bit, you make your accumulator 64-bit to be sure you can hold the sum of all tap values. However, you can use a 32 bit value if you ensure that your input values are all less than some maximum. One way to calculate your maximum input value is to sum up the absolute values of the coefficients and divide by the maximum integer portion of the fixed point scheme. In the case of the FEP FIR filter, the sum of coefficients was 131646, so if the numbers can be 15 bits of positive whole numbers + 16 bits of fractional numbers, I can use the formula (231)/131646 which gives the FEP maximum input value of + or - 16,312. In this case, another optimization can be realized which is not to have a microcontroller do 64-bit calculations.

    Walking the Signal Processing Chain

    Delays Due to Filtering

    Before walking through the processing chain, we should discuss delays caused by filtering. Many types of filtering add delays to the signal being processed. If you do a lot of filtering work, you are probably well aware of this fact, but, if you are not all that experienced with filtering signals, it’s something of which you should be aware. What do I mean by delay? This simply means that if I put in a value X and I get out a value Y, how long it takes for the most impact of X to show up in Y is the delay. In the case of a FIR filter, it can be easily seen by the filter’s Impulse response plot, which, if you remember from my description of FIR filters, is a stream of 0’s with a single 1 inserted. T-Filter shows the impulse response, so you can see how X impacts Y’s output. Below is an image of the FEP’s high pass filter Impulse Response taken from the T-Filter website. Notice in the image that the maximum impact on X is exactly in the middle, and there is a point for each tap in the filter.

    Impulse response from T-Filter

    Below is a diagram of a few of the FEP’s high pass filter signals. The red signal is the input from the accelerometer or the newest sample going into the filter, and the blue signal is the oldest sample in the filter’s ring buffer. There are 19 taps in the FIR filter, so they represent a plot of the first and last samples in the filter window. The green signal is the value coming out of the high pass filter. So, to relate to my X and Y analogy above, the blue signal is X and the green signal is Y. The blue signal is delayed by 36 milliseconds in relation to the red input signal, which is exactly 18 samples at 2 milliseconds. This is the window of data that the filter works on and is the Finite amount of time X affects Y.

    Delayed Signal Example

    Notice the output of the high pass filter (green signal) seems to track changes from the input at a delay of 18 milliseconds, which is 9 samples at 2 milliseconds each. So, the most impact from the input signal is seen in the middle of the filter window, which also coincides with the Impulse Response plot where the strongest effects of the 1 value input are seen at the center of the filter window.

    It’s not only a FIR that adds delay. Usually, any filtering that is done on a window of samples will cause a delay, and, typically, it will be half the window length. Depending on your application, this delay may or may not have to be accounted for in your design. However, if you want to line this signal up with another unfiltered or less filtered signal, you are going to have to account for it and align it with the use of a delay component.

    Front End Processor

    I’ve talked at length about how to get to a final solution and all the components that made up the solution, so now let’s walk through the processing chain and see how the signal is transformed into one that reveals the punches. The FEP’s main goal is to remove bias and create an output signal that smears across the bursts of acceleration to create a wave that is higher in amplitude during increased acceleration and lower amplitude during times of less acceleration. There are four serial components to the FEP: a High Pass FIR, Attenuator, Rectifier and Smoothing via Sliding Window Average.

    The first image is the input and output of the High Pass FIR. Since they are offset by the amount of bias, they don’t overlay very much. The red signal is the input from the accelerometer, and the blue is the output from the FIR. Notice the 1g of acceleration due to gravity is removed and slower changes in the signal are filtered out. If you look between 24,750 and 25,000 milliseconds, you can see the blue signal is more like a straight line with spikes and a slight ringing on it, while the original input has those spikes but meandering on some slow ripple.

    FEP Highpass In Out

    Next is the output of the attenuator. While this component works on the entire signal, it lowers the peak values of the signal, but its most important job is to squish the quieter parts of the signal closer to zero values. The image below shows the output of the attenuator, and the input was the output of the High Pass FIR. As expected, peaks are much lower but so is the quieter time. This makes it a little easier to see the acceleration bursts.

    FEP Atten Out

    Next is the rectifier component. Its job is to turn all the acceleration energy in the positive direction so that it can be used in averaging. For example, an acceleration causing a positive spike of 1000 followed by a negative spike of 990 would yield an average of 5, while a 1000 followed by a positive of 990 would yield an average of 995, a huge difference. Below is an image of the Rectifier output. The bursts of acceleration are slightly more visually apparent, but not easily discernable. In fact, this image shows exactly why this problem is such a tough one to solve; you can clearly see how resonant shaking of the base causes the pattern to change during punch energy being added. The left side is lower and more frequent peaks, the right side has higher but less frequent peaks.

    FEP Rectifier Out

    The 49 value sliding window is the final step in the FEP. While we have done subtle changes to the signal that haven’t exactly made the punches jump out in the images, this final stage makes it visually apparent that the signal is well on its way of yielding the hidden punch information. The fruits of the previous signal processing magically show up at this stage. Below is an image of the Sliding Window average. The blue signal is its input or the output of the Rectifier, and the red signal is the output of the sliding window. The red signal is also the final output of the FEP stage of processing. Since it is a window, it has a delay associated with it. Its approximately 22 samples or 44 milliseconds on average. It doesn’t always look that way because sometimes the input signal spikes are suddenly tall with smaller ringing afterwards. Other times there are some small spikes leading up to the tall spikes and that makes the sliding window average output appear inconsistent in its delay based on where the peak of the output shows up. Although these bumps are small, they are now representing where new acceleration energy is being introduced due to punches.

    FEP Final Out

    Detection Processor

    Now it’s time to move on to the Detection Processor (DET). The FEP outputs a signal that is starting to show were the bursts of acceleration are occurring. The DET’s job will be to enhance this signal and employ an algorithm to detect where the punches are occurring. The first stage of the DET is an attenuator. Eventually, I want to add exponential gain to the signal to really pull up the peaks, but, before doing that, it is important to once again squish down the lower values towards zero and lower the peaks to keep from generating values too large to process in the rest of the DET chain. Below is an image of the output from the attenuator stage, it looks just like the signal output from the FEP, however notice the signal level peaks were above 100 from the FEP, and now peaks are barely over 50. The vertical scale is zoomed in with the max amplitude set to 500 so you can see that there is a viable signal with punch information.

    FEP Atten Out

    With the signal sufficiently attenuated, it’s time to create the magic. The Magnitude Square function is where it all comes together. The attenuated signal carries the tiny seeds from which I’ll grow towering Redwoods. Below is an image of the Mag Square output, the red signal is the attenuated input, and the blue signal is the mag square output. I’ve had to zoom out to a 3,000 max vertical, and, as you can see, the input signal almost looks flat, yet the mag square was able to pull out unmistakable peaks that will aid the detection algorithm to pick out punches. You might ask why not just use these giant peaks to detect punches. One of the reasons I’ve picked this area of the signal to analyze is to show you how the amount of acceleration can vary greatly as you can see the peak between 25,000 and 25,250 is much smaller than the surrounding peaks, which makes pure thresholding a tough chore.

    DET Mag Square

    Next, I decided to put a Low Pass filter to try to remove any fast changing parts of the signal since I’m looking for events that occur in the 2 to 4 Hz range. It was tough on T-Filter to create a tight low pass filter with a 0 to 5 Hz band pass as it was generating filters with over 100 taps, and I didn’t want to take that processing hit, not to mention I would then need a 64-bit accumulator to hold the sum. I relaxed the band pass with a 0 to 19 Hz range and the band stop at 100 to 250 Hz. Below is an image of the low pass filter output. The blue signal is the input, and the red signal is the delayed output. I used this image because it allows the input and output signal to be seen without interfering with each other. The delay is due to 6 sample delay of the low pass FIR, but I have also introduced a 49 sample delay to this signal so that it is aligned in the center of the 99 sample sliding window average that follows in the processing chain. So it is delayed by a total of 55 samples or 110 milliseconds. In this image, you can see the slight amplification of the slow peaks by their height and how it is smoothed as the faster changing elements are attenuated. Not a lot going on here but the signal is a little cleaner, Earl Muntz might suggest I cut the low pass filter out of the circuit, and it might very well work without it.

    Low pass delayed DET

    The final stage of the signal processing is a 99 sample sliding window average. I built into the sliding window average the ability to return the sample in the middle of the window each time a new value is added and that is how I produced the 49 sample delayed signal in the previous image. This is important because the detection algorithm is going to have 2 parallel signals passed into it, the output of the 99 sliding window average and the 49 sample delayed input into the sliding window average. This will perfectly align the un-averaged signal in the middle of the sliding window average. The averaged signal is used as a dynamic threshold for the detection algorithm to use in its detection processing. Here, once again, is the image of the final output from the DET.

    DET Final Out

    In the image, the green and yellow signals are inputs to the detection algorithm, and the blue and red are outputs. As you can see, the green signal, which is a 49 samples delayed, is aligned perfectly with the yellow 99 sliding window average peaks. The detection algorithm monitors the crossing of the yellow by the green signal. This is accomplished by both maximum and minimum start guard state that verifies the signal has moved enough in the minimum or maximum direction in relation to the yellow signal and then switches to a state that monitors the green signal for enough change in direction to declare a maximum or minimum. When the peak start occurs and it’s been at least 260ms since the last detected peak, the state switches to monitor for a new peak in the green signal and also makes the blue spike seen in the image. This is when a punch count is registered. Once a new peak has been detected, the state changes to look for the start of a new minimum. Now, if the green signal falls below the yellow by a delta of 50, the state changes to look for a new minimum of the green signal. Once the green signal minimum is declared, the state changes to start looking for the start of a new peak of the green signal, and a red spike is shown on the image when this occurs.

    Again, I’ve picked this time in the recorded data because it shows how the algorithm can track the punches even during big swings in peak amplitude. What’s interesting here is if you look between the 24,750 and 25,000 time frame, you can see the red spike detected a minimum due to the little spike upward of the green signal, which means the state machine started to look for the next start of peak at that point. However, the green signal never crossed the yellow line, so the start of peak state rode the signal all the way down to the floor and waited until the cross of the yellow line just before the 25,250 mark to declare the next start of peak. Additionally, the peak at the 25,250 mark is much lower than the surrounding peaks, but it was still easily detected. Thus, the dynamic thresholding and the state machine logic allows the speed bag punch detector algorithm to “Roll with the Punches”, so to speak.

    Final Thoughts

    To sum up, we’ve covered a lot of ground in this article. First, the importance of fully understanding the problem as it relates to the required end item along with the domain knowledge needed to get there. Second, for a problem of this nature creating a scaffold environment to build the algorithm was imperative, and in this instance, it was the Java prototype with visual display of the signals. Third, was implement for the target environment, on a PC you have wonderful optimizing compilers for powerful CPUs with tons of cache, for a microcontroller the optimization is really left to you. Use every optimization trick you know to keep processing as quick as possible. Fourth, iterative development can help you on problems like this. Keep reworking the problem while folding in the knowledge you are learning during the development process.

    When I look back on this project and think about what ultimately made me successful, I can think of two main things. Creating the right tools for the job was invaluable. Being able to see how my processing components were affecting the signal was really invaluable. Not only plotting the output signal, but having it plot in realtime, allowed me to fully understand the acceleration being generated. It was as if Nate was in the corner punching the bag, and I was watching the waveform roll in on my screen. However, the biggest factor was realizing that in the end I am looking for something that happens 2 to 4 times per second. I latched on to that and relentlessly pursued how to translate the raw incoming signal into something that would show those events. There was nothing for me to Google to find that answer. Remember knowledge doesn’t really come from books, it gets recorded in books. First, someone had to go off script and discover something and then it becomes knowledge. Apply the knowledge you have and can find, but don’t be afraid to use your imagination to try what hasn’t been tried before to solve an unsolved problem. So remember in the future, metaphorically when you come to the end of the paved road. Will you turn around looking for a road already paved ,or will you lock in the hubs and keep plowing ahead to make your own discovery. I wasn’t able to just Google how to count punches with an accelerometer, but now someone can.


    For more informational fun, check out these other great SparkFun write-ups.

    Nest Protect Teardown

    See the inner-workings of the new Nest Protect in this SparkFun Teardown.

    How Lithium Polymer Batteries are Made

    We got the opportunity to tour the Great Power Battery factory. Checkout how LiPos are made!

    Teardown: DDC Mobile X900

    Nate picked up a bricktastic phone in China. Let's take it apart!!!

    Alternative Arduino Interfaces

    We admit the Arduino IDE isn't for everyone. Here are some other options for programming your Arduino boards, including web interfaces and graphical programming languages.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    LIS3DH Hookup Guide

    $
    0
    0

    LIS3DH Hookup Guide a learn.sparkfun.com tutorial

    Available online at: http://sfe.io/t596

    Introduction

    The LIS3DH is a triple axis accelerometer you can use to add translation detection to your project. It would be classified as a 3DoF, or 3 Degrees of Freedom. Inertial Measurement Units (or IMUs), such as the LSM9DS1; the LSM6DS3; or the LSM303C, can provide additional space location data such as gyroscopic or magnetometric. This IC operates under the same principals but gives a few analog inputs to play with, and it has some build in movement detection abilities.

    SparkFun Triple Axis Accelerometer Breakout - LIS3DH

    SEN-13963
    $4.95

    This guide presents the basics of plugging it into a processor, using the Arduino library to get acceleration data live or by FIFO collection, and describes the library usage.

    Required Materials

    To follow along, you’ll need the following materials:

    The LIS3DH is a 3.3V device! Supplying voltages greater than ~3.6V can permanently damage the IC. As long as your Arduino has a 3.3V supply output, and you're OK with using I2C; you shouldn't need any extra level shifting. But, if you want to use SPI, you may need a level shifter.

    A logic level shifter is required for any 5V-operating Arduino (UNO, RedBoard, Leonardo, etc). If you use a 3.3V-based ‘duino – like the Arduino Pro 3.3V or 3.3V Pro Mini– there is no need for level shifting.

    Suggested Reading

    If you’re not familiar with some of the concepts below, we recommend checking out that tutorial before continuing on.

    Also, the following ST documents are helpful for advanced users:

    Hardware Overview and Assembly

    There are a few different methods with which you can use the LIS3DH.

    The top side of the board has the LIS3DH sensor, some bypass caps and pull-up resistors.

    board pinout

    The pin connections

    This table gives more information as to each pins functionality. The serial port can be connected as either SPI or I2C, and it uses the same physical pins for both. To get going, just wire up your choice of interface, supply 3.3v, and ground. Note that you will not need to use all the pins no matter which communication method you choose.

    Connection
    GroupNameDirectionDescriptionI2CSPI
    Serial!CSIChip select (for SPI)NC!CS
    SDOOData output (MISO for SPI)NCMISO
    SCLIData clockSCLSCK
    SDA/SDII/OData in (SDA for I2C, MOSI for SPI)SDAMOSI
    InterruptsI1OPrimary int has FIFO + motionOptional MCU
    I2OSecondary int has motionOptional MCU
    ADCA1IAnalog inOptional
    A2IAnalog inOptional
    A3IAnalog in (unused for temp readings)Optional
    PowerVCCI3.3V inputSupply
    GNDIGround connection (either PTH)Supply

    On the bottom, there are two jumpers that correspond to the I2C address and pull-up enable.

    alt text

    The following options are available:

    • The I2C Address Jumper– Bridge to use alternate address 0x18, otherwise leave open for 0x19. Leave open for SPI use.
    • The I2C Pull-up Enable– Closed by default, this connects a pull-up resistor between the I2C lines and VCC. This generally doesn’t interfere with SPI operation, but, if less power consumption is required, carefully cut the copper traces.

    Working with a Breadboard

    This sensor works nicely with a breadboard for easy connection, and, because it gives some mass to the accelerometer, it more closely matches what might be expected from a project or cellphone.

    To add headers, break off two 6-pin lengths of 0.1 inch male headers, and set them into a breadboard to use as a soldering jig.

    alt text

    Two rows of headers placed and ready to solder.

    Drop the breakout board onto the pins, and solder down the rows.

    alt text

    Soldering on the rows of pins.

    Congratulations! You’re now ready to connect the sensor to a microcontroller of your choosing.

    Getting the Arduino Library

    The examples in the guide use the Arduino IDE and a RedBoard to communicate with the LIS3DH.

    To get the Arduino library, download from Github, or use the Arduino Library Manager.

    Download the Github Repository

    Visit the GitHub repository to download the most recent version of the library, or click the link below:

    Download the Arduino Library

    Library Manager

    For help installing the library, check out our How To Install An Arduino Library tutorial.

    If you don’t end up using the manger, you’ll need to move the SparkFun_LIS3DH_Arduino_Library folder into a libraries folder within your Arduino sketchbook.

    Example: I2C, analog, and interrupts

    The first circuit allows a RedBoard to talk to the LIS3DH over I2C and provides connections on the interrupt and ADC pins. If you don’t need them, just connect power, ground, and communication pins, and ignore the interrupt and ADC examples.

    Use these two pictures as a guide for building the circuit.

    alt text

    The circuit built on a RedBoard

    alt text

    The connections shown in Fritzing

    Basic Accelerometer Data Collection:

    Start with just the basic accelerometer sketch, also called “MinimalistExample” from the library. This will periodically samples the sensor and displays data as number of Gs detected. Remember, the vertical axis will read 1G while sitting at rest.

    language:c
    #include "SparkFunLIS3DH.h"
    #include "Wire.h"
    #include "SPI.h"
    
    LIS3DH myIMU; //Default constructor is I2C, addr 0x19.
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      delay(1000); //relax...
      Serial.println("Processor came out of reset.\n");
    
      //Call .begin() to configure the IMU
      myIMU.begin();
    
    }
    
    
    void loop()
    {
      //Get all parameters
      Serial.print("\nAccelerometer:\n");
      Serial.print(" X = ");
      Serial.println(myIMU.readFloatAccelX(), 4);
      Serial.print(" Y = ");
      Serial.println(myIMU.readFloatAccelY(), 4);
      Serial.print(" Z = ");
      Serial.println(myIMU.readFloatAccelZ(), 4);
    
      delay(1000);
    }
    

    Example output:

    Processor came out of reset.
    
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    

    When run, the sketch will display data in Gs to the serial terminal. Every second, the data is collected and printed.

    Using the ADC

    To try out the analog inputs, load the example called “ADCUsage”, or copy paste from the following section. This example also shows some of the additional settings that can be applied within the begin() function.

    language:c
    #include "SparkFunLIS3DH.h"
    #include "Wire.h"
    #include "SPI.h"
    
    LIS3DH myIMU; //Default constructor is I2C, addr 0x19.
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      delay(1000); //relax...
      Serial.println("Processor came out of reset.\n");
    
      myIMU.settings.adcEnabled = 1;
      //Note:  By also setting tempEnabled = 1, temperature data is available
      //on ADC3.  Temperature *differences* can be read at a rate of
      //1 degree C per unit of ADC3
      myIMU.settings.tempEnabled = 0;
      myIMU.settings.accelSampleRate = 50;  //Hz.  Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
      myIMU.settings.accelRange = 2;      //Max G force readable.  Can be: 2, 4, 8, 16
      myIMU.settings.xAccelEnabled = 0;
      myIMU.settings.yAccelEnabled = 0;
      myIMU.settings.zAccelEnabled = 0;
    
      //Call .begin() to configure the IMU
      myIMU.begin();
    
    }
    
    void loop()
    {
      //Get all parameters
      Serial.print("\nADC:\n");
      Serial.print(" 1 = ");
      Serial.println(myIMU.read10bitADC1());
      Serial.print(" 2 = ");
      Serial.println(myIMU.read10bitADC2());
      Serial.print(" 3 = ");
      Serial.println(myIMU.read10bitADC3());
    
      delay(300);
    }
    

    Example output:

    Processor came out of reset.
    
    
    ADC:
     1 = 1020
     2 = 522
     3 = 506
    
    ADC:
     1 = 1020
     2 = 544
     3 = 516
    
    ADC:
     1 = 1020
     2 = 540
     3 = 517
    

    The sketch prints the three ADC values every 300ms. Move the knob to see how the values change and how the effective voltage range is somewhat in the middle of the full range. Move the wire from on ADC pin to another to see that the controlled value changes.

    Using the Interrupt Pins

    Interrupt behavior is highly configurable and is thus omitted as basic library functions. Instead, LIS3DH registers are directly written in accordance with the datasheet.

    An example is provided that has the relevant registers configured with comments in a template function that can be copied into a project and modified. Run the example named IntUsage, which will throw an interrupt on one pin when an exceeded acceleration is detected and a pulse on the other when a tap is detected.

    Example: SPI and FIFO usage

    The second method in which to communicate with the LIS3DH is with the SPI interface. The SPI interface operates at 3.3v, so use a logic level converter or a MCU that operates at 3.3V. Use the following pictures to help build the circuit.

    alt text

    The circuit built on a RedBoard

    alt text

    The connections shown in Fritzing

    Basic Accelerometer Data Collection:

    SPI is not the default configuration, so you’ll have to pass extra information to the library by constructing with parameters. Modify “MinimalistExample” by changing LIS3DH myIMU; to LIS3DH myIMU(SPI_MODE, 10); for SPI mode with the !CS pin connected to pin 10.

    The modified “MinimalistExample” is listed here:

    language:c
    #include "SparkFunLIS3DH.h"
    #include "Wire.h"
    #include "SPI.h"
    
    LIS3DH myIMU(SPI_MODE, 10); // constructed with parameters for SPI and cs pin number
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      delay(1000); //relax...
      Serial.println("Processor came out of reset.\n");
    
      //Call .begin() to configure the IMU
      myIMU.begin();
    
    }
    
    
    void loop()
    {
      //Get all parameters
      Serial.print("\nAccelerometer:\n");
      Serial.print(" X = ");
      Serial.println(myIMU.readFloatAccelX(), 4);
      Serial.print(" Y = ");
      Serial.println(myIMU.readFloatAccelY(), 4);
      Serial.print(" Z = ");
      Serial.println(myIMU.readFloatAccelZ(), 4);
    
      delay(1000);
    }
    

    Example output:

    Processor came out of reset.
    
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    
    Accelerometer:
     X = -0.1481
     Y = -0.1361
     Z = 0.9768
    

    When run, the sketch will display data in Gs to the serial terminal. Every second, the data is collected and printed.

    FIFO usage:

    The SPI bus can operate faster than I2C, so for high speed data collections where periodic sampling is required, SPI is advisable.

    alt text

    This graph was made by taking the output of the example and copy-pasting it into a spreadsheet program, then creating a chart. During the data collection, the sensor was moved about a foot back and forth on each axis.

    language:c
    #include "SparkFunLIS3DH.h"
    #include "Wire.h"
    #include "SPI.h"
    
    LIS3DH myIMU(SPI_MODE, 10); //Constructing with SPI interface information
    //LIS3DH myIMU(I2C_MODE, 0x19); //Alternate constructor for I2C
    
    uint32_t sampleNumber = 0; //Used to make CSV output row numbers
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      delay(1000); //relax...
      Serial.println("Processor came out of reset.\n");
    
      myIMU.settings.adcEnabled = 0;
      //Note:  By also setting tempEnabled = 1, temperature data is available
      //instead of ADC3 in.  Temperature *differences* can be read at a rate of
      //1 degree C per unit of ADC3 data.
      myIMU.settings.tempEnabled = 0;
      myIMU.settings.accelSampleRate = 10;  //Hz.  Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
      myIMU.settings.accelRange = 2;      //Max G force readable.  Can be: 2, 4, 8, 16
      myIMU.settings.xAccelEnabled = 1;
      myIMU.settings.yAccelEnabled = 1;
      myIMU.settings.zAccelEnabled = 1;
    
      //FIFO control settings
      myIMU.settings.fifoEnabled = 1;
      myIMU.settings.fifoThreshold = 20;  //Can be 0 to 31
      myIMU.settings.fifoMode = 1;  //FIFO mode.
      //fifoMode can be:
      //  0 (Bypass mode, FIFO off)
      //  1 (FIFO mode)
      //  3 (FIFO until full)
      //  4 (FIFO when trigger)
    
      //Call .begin() to configure the IMU (except for the fifo)
      myIMU.begin();
    
      Serial.print("Configuring FIFO with no error checking...");
      myIMU.fifoBegin(); //Configure fifo
      Serial.print("Done!\n");
    
      Serial.print("Clearing out the FIFO...");
      myIMU.fifoClear();
      Serial.print("Done!\n");
      myIMU.fifoStartRec(); //cause fifo to start taking data (re-applies mode bits)
    
    }
    
    void loop()
    {
      //float temp;  //This is to hold read data
      //uint16_t tempUnsigned;
      //
      while(( myIMU.fifoGetStatus() & 0x80 ) == 0) {};  //Wait for watermark
    
      //Now loop until FIFO is empty.
      //If having problems with the fifo not restarting after reading data, use the watermark
      //bits (b5 to b0) instead.
      //while(( myIMU.fifoGetStatus() & 0x1F ) > 2) //This checks that there is only a couple entries left
      while(( myIMU.fifoGetStatus() & 0x20 ) == 0) //This checks for the 'empty' flag
      {
          Serial.print(sampleNumber);
          Serial.print(",");
          Serial.print(myIMU.readFloatAccelX());
          Serial.print(",");
          Serial.print(myIMU.readFloatAccelY());
          Serial.print(",");
          Serial.print(myIMU.readFloatAccelZ());
          Serial.println();
          sampleNumber++;
      }
    
    }
    

    Example output:

    Processor came out of reset.
    
    Configuring FIFO with no error checking...Done!
    Clearing out the FIFO...Done!
    0,-0.15,-0.14,1.04
    1,-0.17,-0.12,1.02
    2,-0.21,-0.10,0.95
    3,-0.21,-0.10,1.01
    4,-0.22,-0.12,1.07
    5,-0.17,-0.12,0.99
    6,-0.12,-0.15,0.96
    7,-0.18,-0.12,0.94
    8,-0.19,-0.10,0.98
    9,-0.20,-0.14,1.04
    10,-0.19,-0.12,0.99
    11,-0.20,-0.10,0.95
    12,-0.21,-0.12,1.06
    13,-0.14,-0.12,0.98
    14,-0.10,-0.11,0.95
    15,-0.12,-0.10,0.94
    16,-0.14,-0.09,0.90
    ...
    

    Notice that the output produces batches of data periodically. Even though the data waits to be collected, it is still sampled periodically. The data is collected when the FIFO is past the watermark configured in the line myIMU.settings.fifoThreshold = 20;.

    Extra Examples and Arduino Library Reference

    The following examples are included in the Arduino library:

    • ADCUsage - Demonstrates analog in reads and has notes about temperature collection
    • FifoExample - Demonstrates using the built-in buffer to burst-collect data - Good demonstration of settings
    • FullSettingExample - Shows all settings, with non-used options commented out
    • IntUsage - shows configuration of interrupt bits
    • LowLevelExample - Demonstrates using only the core driver without math and settings overhead
    • MinimalistExample - The easiest configuration
    • MultiI2C - Using two LIS3DHs over I2C
    • MultiSPI - Using two LIS3DHs over SPI

    Library Usage

    Take the following steps to use the library

    • construct an object in the global space with one of these constructions
      • No parameters – I2C mode at address 0x19
      • I2C_MODE, address
      • SPI_MODE, pin number
    • With in begin, set the .settings. values
    • run .begin()

    Example:

    language:c
    LIS3DH myIMU; //This creates an instance the library object.
    
    void setup()
    {
        myIMU.settings.adcEnabled = 1;
        myIMU.settings.tempEnabled = 0;
        myIMU.settings.accelSampleRate = 50;  //Hz.  Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
        myIMU.settings.accelRange = 2;      //Max G force readable.  Can be: 2, 4, 8, 16
        myIMU.begin();
    }
    

    Settings

    The main LIS3DH class has a public member, which is named settings. To configure settings, use the format myIMU.settings.accelSampleRate = (...);. Then, call .begin() to apply.

    Settings contains the following members:

    • uint8_t adcEnabled– Set to 1 to enable ADCs
    • uint8_t tempEnabled– Set to 1 to override ADC3 with delta temperature information
    • uint16_t accelSampleRate– Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
    • uint8_t accelRange– Max G force readable. Can be: 2, 4, 8, 16
    • uint8_t xAccelEnabled– Set to 1 to enable x axis
    • uint8_t yAccelEnabled– Set to 1 to enable y axis
    • uint8_t zAccelEnabled– Set to 1 to enable z axis
    • uint8_t fifoEnabled– Set to 1 to enable FIFO
    • uint8_t fifoMode– Can be 0x0,0x1,0x2,0x3
    • uint8_t fifoThreshold– Number of bytes read before watermark is detected (0 to 31)

    Functions

    Advanced programmers: The LIS3DH class inherits the LIS3DHCore, which can be used to communicate without all these functions, so you can write your own. This class is not covered in this hookup guide.

    uint8_t begin( void );

    Call after providing settings to start the wire or SPI library as indicated by construction and runs applySettings(). Returns 0 for success.

    void applySettings( void );

    This configures the IMU’s registers based on the contents of .settings.

    int16_t readRawAccelX( void );

    int16_t readRawAccelY( void );

    int16_t readRawAccelZ( void );

    These functions return axis acceleration information as a 16 bit, signed integer.

    float readFloatAccelX( void );

    float readFloatAccelY( void );

    float readFloatAccelZ( void );

    These functions call the Raw functions, then apply math to convert to a float expressing acceleration in number of Gs.

    uint16_t read10bitADC1( void );

    uint16_t read10bitADC2( void );

    uint16_t read10bitADC3( void );

    These functions return the ADC values read from the pins. Values will be 10 bit and the detectable range is about 0.9V to 1.8V.

    Note: When tempEnabled == 1, ADC3 reads as an unreferenced temperature in degrees C. Read twice and calculate the change in temperature.

    void fifoBegin( void );

    This enables the FIFO by writing the proper values into the FIFO control reg, and control reg 5. This does not start the data collection to the FIFO, run fifoStartRec() when ready.

    Sample rate depends on data rate selected in .settings.

    void fifoClear( void );

    This reads all data until the status says none is available, discarding the data. Use to start with new data if the FIFO fills with old data.

    void fifoStartRec( void )

    This enables FIFO data collection. Run this before starting to check if data is available.

    After fifoStartRec is used, data from the X, Y, Z registers is not real time, but is the next available sample.

    uint8_t fifoGetStatus( void )

    This returns the FIFO status byte. The contents of the byte are as follows:

    • bit 7: Watermark exceeded
    • bit 6: FIFO has overflowed
    • bit 5: FIFO is empty
    • bit 4 through 0: Number of samples available (0 to 31)

    void fifoEnd( void );

    This stops the FIFO and returns the device to regular operation.

    Resources and Going Further

    You should now have a basic understanding of how to use the LIS3DH, but if you need some more information check out the following links:

    Going Further

    Need a little inspiration? Check out some of these other great SparkFun tutorials.

    Simon Tilts Assembly Guide

    This tutorial will guide you through assembling your Simon Tilts PTH Kit.

    Are You Okay? Widget

    Use an Electric Imp and accelerometer to create an "Are You OK" widget. A cozy piece of technology your friend or loved one can nudge to let you know they're OK from half-a-world away.

    MMA8452Q Accelerometer Breakout Hookup Guide

    How to get started using the MMA8452Q 3-axis accelerometer -- a solid, digital, easy-to-use acceleration sensor.

    TB6612FNG Hookup Guide

    Basic hookup guide for the TB6612FNG H-bridge motor driver.

    learn.sparkfun.com |CC BY-SA 3.0 | SparkFun Electronics | Niwot, Colorado

    Viewing all 1123 articles
    Browse latest View live


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