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

Proto Pedal Chassis Hookup Guide

$
0
0

Proto Pedal Chassis Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The Proto Pedal chassis comes with the holes required to interface the PCB, but since different pedal designs use different types of controls, we’ve left drilling holes for the controls to the builder. This guide will take you through laying out and drilling holes, then painting the chassis.

alt text

We’ll be drilling a chassis to match the digital Proto Pedal example, which shows an application using a Teensy 3.2 and an Audio Adapter with the Proto Pedal and Proto Pedal Chassis.

Materials

Required:

  • The Proto Pedal and Chassis
  • A twist drill bit (not spade) that matches the desired hole diameter
  • A pilot drill of about 1/8 inch. Make sure it’s sharp and fresh!
  • A few drill bits between to step up to the desired size.
  • Ruler
  • Center punch (a large metal screw and hammer will work)
  • Variable speed hand drill, wired or cordless
  • Clamps, vice, holders
  • Some scrap wood blocks
  • A pencil

Also Recommended:

  • Thin circular file (needle or chain sharpening file)
  • Speed square
  • Combination square / scribe
  • Spring loaded center punch
  • Isopropyl Alcohol / Acetone
  • Paint

Recommended Reading

Laying Out The Holes

Before drilling, we need to figure out where to locate the holes.

This is an exercise in three-dimensional thinking. We need to account for the location of the controls on the panel, as well as the clearance above and below. Above the surface of the pedal, you’ll probably want to leave some room around the controls, so you can grab them. Inside the chassis, you need to consider where the internal portion of the control will be located, especially in relation to the taller components on the PCB.

Rough Layout

In this example, we wanted to put five potentiometers on the chassis. We simply moved the knobs around on top of the chassis until we reached a reasonable arrangement. Notice that we’re leaving clearance for the TRS jacks.

alt text

Laying out the knobs

We had the circuit board nearby to use as a reference, to help see where internal objects are are located. We also had the assembled stack of Teensy 3.2 and Audio Adapter nearby, which we test fit several times as we worked. This allowed us to recognize that the stack doesn’t stand much above the board, leaving vertical space to place a pot over it.

alt text

Tracing the knob outlines

With the knobs in rough proximity of their ultimate destinations, we traced them in pencil, making circles on the box.

More Precise Layout

With the knobs removed, we measured the location of their centers from the top edge of the box. We averaged the measurements, so the holes would be in reasonable alignment.

Here we’ve marking a line 2 ½ inches from the top edge, using a combination square to insure a consistent distance. If you don’t have a square, you can carefully measure two points and draw a line between them.

alt text

Setting the vertical alignment

The top row is an inch closer to the edge, at 1 ½ inches.

alt text

Do this for each row.

With the lines for the rows drawn, we’ll move on to the horizontal position of each pot within the rows.

alt text

Center your rule to a common overlap to identify center

We decided to center these knobs, so we set the ruler on the box such that the edges aligned the same number of subdivisions past the last whole inch, or a little more than ¼ inch, at 9 ¼ and 5 ¾. Now, the 8 ½ inch mark is centered horizontally and we can count subdivisions out from there to make sure the holes are equally spaced.

The top row holes were marked ½ way between the marks in the bottom row, resulting in a regular “M” shape.

Notice that the rough knob outlines are no longer accurate to the center marks. The outlines were just eye-balled on for aesthetics, while the measured marks insure accuracy.

Punching

Punch the center of each hole. This will help guide the drill bit.

If you’ve never seen a spring loaded center punch before, they’re really cool. Just press down until the internal spring is sprung, and it leaves a mark behind. You can get these at most hardware stores.

alt text

Using a spring loaded punch

Or if you don’t have a center punch, use a large screw and a hammer. Big pan heads work well, but wood deck screws or drywall screws are too pointy.

alt text

Using a screw for a punch

Now let’s get to the real action!

Drilling

When you’re happy with your center punch marks, it’s time to start drilling.

Drilling Metal

When drilling metal, it’s important to start with a small pilot hole, and work progressively up to the desired size. For these holes, they’ll be 5/16 inch for the 10k linear potentiometers. Each successive hole should be 25% to 50% larger than it’s predecessor.

alt text

This diagram shows the maximum overlap desired.

When drilling metal, use a moderately slow speed, and reasonable pressure. A drill that’s too fast can cause the bit to overheat, and is more dangerous if you lose control.

Preparation

Before drilling, solidly secure the workpiece with a vice or a clamp.

alt text

Preparing to drill

Here, three bits have been selected and the piece is clamped. You may think you can just hold the piece down with your hand, but more often than not it will wedge on the drill bit and spin around, whacking your hand and causing injury (and perhaps damaging the workpiece). Also, use scrap wood to protect the piece from marring, and to provide something soft for the drill bits to crash into when they break through.

Drilling

Start with a small pilot hole. This is the most important drill as it will guide the other holes.

alt text

Carefully align the pilot holes

A challenge with using a hand drill is maintaining perpendicularly to the work surface. As a reference, set a square on the piece and use it as a visual guide. Before you start drilling, hold the drill where you think it should go and move your head around like an owl to see that you’ve got good alignment from all angles.

When you’re ready, drill with a medium speed and decent pressure. The bit should produce a constant stream of waste material. If it seems like it’s just spinning, doublecheck you’re not in reverse, try adding more pressure, or slow the drill speed.

Double check alignment! After drilling the pilot holes, check that they are aligned as they should be. If not, you can use a thin file to make the hole oblong and bring the geometric center back in line, and the next bit should correct the offset. With sharp bits and good perpendicular alignment, this shouldn'tbe required.

After the pilot holes are complete, move up to the next larger bit, and use it to enlarge each hole. As you move to larger and larger bits, less speed should be required.

alt text

Progressing through the selected drill bits, enlarging the holes

After an intermediate hole, we can drill the final hole, 5/16 inch.

alt text

The final size is being drilled here.
The drill has been stopped partway through to show the overlap detail (lower right).

The drilled holes frequently have a sharp burr around the edge. If you like, you can bevel the edges with a chamfer tool, or clean them up with a file. It’s not required, but will get rid of the sharp edges.

alt text

Cleaning up the edges

Notes for Potentiometers

The potentiometers have an alignment / retention boss. You can either drill an extra hole to retain it, or trim it off with a pair of side cutters.

alt text

Removing the bosses.

Extra holes for the Teensy

For the Teensy based digital pedal, we’re going to add a couple extra holes. The first is one on the side of the chassis for the USB connector, plus a second smaller hole in the top of the pdeal, so we can reach the manual-load button.

As with our initial layout, we’re going to do it empirically, using the final parts to gauge where the holes need to be. We started with the USB port, measuring on the left side of the enclosure.

Programming Port

First, choose the location of the programming hole based on where you want the Teensy to be in the pedal. Use the circuit board as a guide, aligning the ¼ inch jack shoulders to the inside plane.

alt text

Using the board as a guide for hole placement

Approximate the height of the hole by holding the circuit board where it will sit when assembled, and cross the previous mark.

alt text

Aligning the height of the hole

Then, punch a center point, and move on to drilling.

We going all the way up to our largest drill, to accommodate the USB plug molding, making 4 drills overall. This time, were using a vice to hold the workpiece, again using blocks of wood to protect it.

alt text

Preparing to drill

As before, we’re working progressively up to the larger drills.

alt text

Here the pilot hole is being enlarged. I like to allow more overlap on the smaller drills.

Since this hole is larger, there will be two intermediate drills.

alt text

The second oversize closer to the first size.

Watch the quality of the waste material. It’s a good sign that speeds and pressures are correct when the waste forms into curls rather than little chips. Also, it can be seen here that the overlap is quite small for this large bit. Otherwise, the bit would have a great tendency to catch when getting close to being through.

alt text

Drilling the final USB hole.

Once the drilling is complete, we want to chamfer the edges of the hole. The chamfer is more important for this hole, because the sharp edge won’t be covered with a control. This time, the hole is as large as the bit were were chamfering with before, so we have to do it manually, with a file.

alt text

Deburring with a file

Reset Switch

We used a similar triangulation process for the hole for the button. Here, there’s a mark where it should be, but that is underneath a knob. The hole was moved outside of the knob outlines, and will have to be used at a slight angle.

alt text

Center punching the button hole

Since this hole is smaller, we didn’t need to step through as many drills.

Painting

alt text

For a finishing touch, you can paint your pedal. We’ve chosen to try out a couple Rust-Oleum oil-based enamels, which have wildly different properties based on the color, and a spray job using red Krylon Shimmer spray paint, with a clear overcoat.

alt text

Cleaning the workpiece

Start by cleaning the case with acetone or isopropyl alcohol. This removes oils and pencil marks.

alt text

Make sure to not touch clean areas!

The liquid paint was applied using a foam applicator wedge.

alt text

Use scrap wood to catch extra paint

Painting can be a messy process, and you’re likely to get some on your work surface. You can protect against paint slop with a drop cloth, or other scrap materials, such as wood, or cardboard.

alt text

Allowing to dry

You can paint the faces of the screws too, if you wish, but try not to get any into the threaded holes, or they may be difficult to drive.

Painting Results

alt text

You can see that the red paint tended to pile up and stay streaky, and needs to be sanded and coated again. This paint should probably be used with a sprayer or thinned out. The black leveled well and could be sanded to a decent finish, but the red refused to level as can be seen above. The Shimmer paint was pretty much fabulous.

Resources and Going Further

Don’t know what to put in your case? Try these!

Have fun decorating and labeling your new proto pedal, and rock on!




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


TB6612FNG Hookup Guide

$
0
0

TB6612FNG Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The TB6612FNG is an easy and affordable way to control motors. The TB6612FNG is capable of driving two motors at up to 1.2A of constant current. Inside the IC, you’ll find two standard H-bridges on a chip allowing you to not only control the direction and speed of your motors but also stop and brake. This guide will cover in detail how to use the TB6612FNG breakout board. The library for this guide will also work on the RedBot Mainboard as well since it uses the same motor driver chip.

SparkFun Motor Driver - Dual TB6612FNG (1A)

ROB-09457
$8.95
14
SparkFun RedBot Mainboard

ROB-12097
$49.95
4
SparkFun Motor Driver - Dual TB6612FNG (with Headers)

ROB-13845
$9.49

Required Materials

To follow along with the motor driver example in this tutorial, here are the basic components you will need:

Suggested Reading

Before continuing with this guide, you may want to check out any topics from the list below that sound unfamiliar.

Electric Power

An overview of electric power, the rate of energy transfer. We'll talk definition of power, watts, equations, and power ratings. 1.21 gigawatts of tutorial fun!

Polarity

An introduction to polarity in electronic components. Discover what polarity is, which parts have it, and how to identify it.

Motors and Selecting the Right One

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

Selecting the Right Motor Driver

Before we get started, let’s talk about how to find a motor driver for your needs.

The first step is to figure out what type of motors you are using and to research their specifications. Picking a motor driver for a motor that is not powerful enough isn’t helpful. Also, keep in mind there are different motor types (stepper, DC, brushless), so make sure you are looking for the correct type of motor driver.

You will need to spec your motor driver and make sure its current and voltage range are compatible with your motor(s).

First, you need to make sure your motor driver can handle the rated voltage of your motors. While you can usually run motors a bit above their ratings, it tends to reduce the lifespan of the motor.

Current draw is the second factor. Your motor driver needs to be capable of driving as much current as your motors will pull. As a general rule, go straight to the stalled current number for a motor (the current draw present when you are holding the motor still). A motor will pull the maximum current when it is stalled. Even if you don’t plan on stalling your motor in your project, this is a safe number to use. If your motor driver can’t handle that much current, then it is time to find a new motor driver (or motor). You may also notice motor drivers often have max continuous current and max peak current listed. These specs are worth noting depending on your application and how much stress your motor will endure.

This guide covers the TB6612FNG motor driver which has a supply range of 2.5V to 13.5V and is capable of 1.2A continuous current and 3.2A peak current (per channel), so it works pretty well with most of our DC motors. If the TB6612FNG does not fit your project’s specifications, check out our various other motor driver boards.

Big Easy Driver

ROB-12859
$19.95
18
SparkFun AutoDriver - Stepper Motor Driver (v13)

BOB-13752
$36.95
SparkFun Servo Trigger

WIG-13118
$16.95
4
SparkFun Servo Trigger - Continuous Rotation

WIG-13872
$19.95

Selection of Motor Drivers

As with any board, there are other things to consider such as the logic voltage, which is basically the voltage it uses to talk to your microcontroller, and heat dissipation. While these things definitely need to be considered, they are relatively easy to fix with things like level shifters and heat sinks. However, if your motor is trying to pull more current than your driver can handle, there isn’t much you can do to fix it.

Board Overview

Let’s discuss the pinout for the TB6612FNG breakout. We basically have three types of pins: power, input, and output, and they are all labeled on the back of the board.

Image of the back of the board

Back of the board

Each pin and its function is covered in the table below.

Pin LabelFunctionPower/Input/Output
Notes
VMMotor VoltagePowerThis is where you provide power for the motors (2.2V to 13.5V)
VCCLogic VoltagePowerThis is the voltage to power the chip and talk to the microcontroller (2.7V to 5.5V)
GNDGroundPowerCommon Ground for both motor voltage and logic voltage (all GND pins are connected)
STBYStandbyInputAllows the H-bridges to work when high (has a pulldown resistor so it must actively pulled high)
AIN1/BIN1Input 1 for channels A/BInputOne of the two inputs that determines the direction.
AIN2/BIN2Input 2 for channels A/BInputOne of the two inputs that determines the direction.
PWMA/PWMBPWM input for channels A/BInputPWM input that controls the speed
A01/B01Output 1 for channels A/BOutputOne of the two outputs to connect the motor
A02/B02Output 2 for channels A/BOutputOne of the two outputs to connect the motor

Now, for a quick overview of how to control each of the channels. If you are using an Arduino, don’t worry about this too much as the library takes care of all of this for you. If you are using a different control platform, pay attention. When the outputs are set to High/Low your motor will run. When they are set to Low/High the motor will run in the opposite direction. In both cases, the speed is controlled by the PWM input.

In1In2PWMOut1Out2Mode
HHH/LLLShort brake
LHHLHCCW
LHLHLShort brake
HLHHLCW
HLLLLShort brake
LLHOFFOFFStop

Don’t forget STBY must be high for the motors to drive.

Hardware Setup

For this demo, we’ll use a small chassis with the included motors and wheels as well as an Arduino Pro Mini.

The first step is to find a power supply. While it is best to find one that will work with the motors and logic, that is not always possible. Sometimes your motors want 24V, but your microcontroller only wants 5V. In that case, it is probably easiest to use 2 power supplies. For this demo, we’ll be using the 4xAA battery holder that comes with the Actobitty chasis. The battery holder should output 6V since each alkaline AA battery is 1.5V (NiMH AAs are only 1.2V). The Arduino Pro Mini can handle up to about 12V on the RAW power line, which it will regulate down to 5V.

The next step is to connect everything using your preferred project platform. We’re using a piece of the snappable protoboard with female headers, so we can just plug in the motor driver and Arduino Pro Mini. If you are using different pins, or a different microcontroller, remember that the PWM pins of the motor driver need to be PWM pins on your microcontroller.

alt text

Here is a Fritzing diagram showing how all the connections were made.

alt text

Here is the final project assembled on the Actobitty chassis.

Library and Example Code

Final step is uploading the code. First we must download and install the 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

Once the library is installed, you can find the example code under File->Examples->TB6612, and upload the code to your Arduino. We’ll get into the code in a minute. In the mean time, you can see it goes through a few basic commands to get you familiar with the library. Keep in mind, in the example code, each command has another command immediately after it that does the opposite and should bring it back to home should your robot should run too far away (I was able to run mine on a notebook without it falling off).

Library Functions

Here we have a basic library. There are two main parts. First, you can send commands like forward, and it will propel your bot forward. This means the right wheel is going clockwise and the left wheel is going counterclockwise. Which way is clockwise and which is counterclockwise depends on which wire of your motor is connected to which of the inputs. This means the forward function might not actually propel the robot forward the first time. You can swap the motor wires if you want, but that is often not possible. The easier solution is to fix this in the software. Near the top of the example code, you will see two constants labeled offset. You can change this from 1 to -1 to swap the configuration of that motor.

language:c
// 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;

The second part of the library is individual motor control. If you are not driving a robot, controls such as forward are not useful, and you probably don’t want the two motors tied together like that. The library will let you make as many instances of motors as you want (or have memory for). This means if you have three TB6612FNGs, you can control six motors individually.

language:c
// Pins for all inputs, keep in mind the PWM defines must be on PWM pins
#define AIN1 2
#define BIN1 7
#define AIN2 4
#define BIN2 8
#define PWMA 5
#define PWMB 6
#define STBY 9

Looking at the example code you will see we start with a lot of defines. This is basically a spot to let you tell the code to which pins you hooked things up. As mentioned earlier you can also play with the constants to switch directions of the motors. Afterwards we initialize the motors, by sending those constants to the function Motor(). This initialization also takes care of all the pinModes. This actually leaves us with nothing to do in the setup function. We could give it a few commands we want to only do once, but we chose to put all the commands in the loop function.

language:c
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);

}

Finally we hit our good friend loop(). Here is where we are testing out the different functions. As you can see some functions take our two motors as arguments like forward(motor1, motor2) and back(motor1, motor2), while other functions are part of the Motor class and are called using commands like motor1.drive(speed).

language:c
// Constructor. Mainly sets up pins.
Motor(int In1pin, int In2pin, int PWMpin, int offset, int STBYpin);

// Drive in direction given by sign, at speed given by magnitude of the
//parameter.
void drive(int speed);

// drive(), but with a delay(duration)
void drive(int speed, int duration);

//currently not implemented
//void stop();           // Stop motors, but allow them to coast to a halt.
//void coast();          // Stop motors, but allow them to coast to a halt.

//Stops motor by setting both input pins high
void brake();

//set the chip to standby mode.  The drive function takes it out of standby
//(forward, back, left, and right all call drive)
void standby();

//Takes 2 motors and goes forward, if it does not go forward adjust offset
//values until it does.  These will also take a negative number and go backwards
//There is also an optional speed input, if speed is not used, the function will
//use the DEFAULTSPEED constant.
void forward(Motor motor1, Motor motor2, int speed);
void forward(Motor motor1, Motor motor2);

//Similar to forward, will take 2 motors and go backwards.  This will take either
//a positive or negative number and will go backwards either way.  Once again the
//speed input is optional and will use DEFAULTSPEED if it is not defined.
void back(Motor motor1, Motor motor2, int speed);
void back(Motor motor1, Motor motor2);

//Left and right take 2 motors, and it is important the order they are sent.
//The left motor should be on the left side of the bot.  These functions
//also take a speed value
void left(Motor left, Motor right, int speed);
void right(Motor left, Motor right, int speed);

//This function takes 2 motors and and brakes them
void brake(Motor motor1, Motor motor2);

Resources and Going Further

With that, you should have the basic knowledge to get started with your next motor-moving project. For more information on the TB6612FNG motor Driver, check out the links below.

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

Shapeoko Assembly Guide

A guide for attaching the Stepoko Add-on kit to a Shapeoko Mechanical kit.

Servo Trigger Programming Guide

Looking under the hood of the Servo Trigger -- using the development environment and some finer details of the firmware.
New!

Getting Started with the AutoDriver - v13

SparkFun's AutoDriver is a powerful tool for controlling stepper motors. Here's how to use it.
New!

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

DeadOn RTC Breakout Hookup Guide

$
0
0

DeadOn RTC Breakout Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The SparkFun DeadOn RTC Breakout is a simple breakout board for the DS3234 real-time clock (RTC) IC. The DS3234 can accurately keep track of seconds, minutes, hours, days, months, and years, so your microcontroller doesn’t have to. It even features a pair of configurable alarms. The DeadOn RTC is perfect for clocks, calendars, or any other time-keeping project.

SparkFun DeadOn RTC Breakout - DS3234

BOB-10160
$19.95
11

Communication between a microcontroller and DS3234 is achieved using a four-wire SPI interface. When it’s not powered via a primary source, the chip can be set to run on a backup battery – keeping its programmed time for many years to come.

This tutorial serves as a general introduction to the DS3234 and the SparkFun DeadOn RTC Breakout. It covers both the hardware and firmware requirements of the breakout – documenting both example wiring and Arduino code for the chip.

Suggested Materials

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

A microcontroller that supports SPI is required to communicate with the DS1307 and relay the RTC’s 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 example code in this tutorial uses an Arduino library, if that serves as any extra motivation to go with an Arduino.)

Arduino Pro Mini 328 - 5V/16MHz

DEV-11113
$9.95
95
SparkFun RedBoard - Programmed with Arduino

DEV-12757
$19.95
106
Arduino Uno - R3

DEV-11021
$24.95
80
Pro Micro - 5V/16MHz

DEV-12640
$19.95
31

Six or seven jumper wires and a breadboard help interface the RTC to your Arduino. And to insert the breakout into the breadboard, you’ll need to solder headers 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

Finally, the DeadOn RTC Breakout does not include a 12mm Coin Cell Battery. Plugging a coin cell in will afford your RTC years-and-years of time-keeping goodness.

Coin Cell Battery - 12mm (CR1225)

PRT-00337
$1.95
2

Suggested Reading

The SparkFun DeadOn RTC Breakout is a very beginner-friendly breakout board. There are, however, still a few concepts you should be familiar with. If any of the tutorial titles below sound foreign to you, consider giving them a look-through:

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!

Serial Peripheral Interface (SPI)

SPI is commonly used to connect microcontrollers to peripherals such as sensors, shift registers, and SD cards.

What is an Arduino?

What is this 'Arduino' thing anyway?

Hardware Overview

The DeadOn RTC Breakout surrounds the DS3234 with all of the components it needs to count time, communicate, and maintain power. The communication and power pins are all broken out to a single, 7-pin header. The top side of the board houses the IC itself and a couple passives to support it:

DeadOn RTC Module top

While the bottom side of the breakout labels the pins and mounts the 12mm coin cell battery holder:

DeadOn RTC Module bottom

Pinout

The seven pin breakouts on the board provide access to the communication interface, power supply, and the square-wave/interrupt output of the DS3234:

Pin LabelInput/OutputDescription
GNDSupply InputGround (0V) supply
VCCSupply InputDS3234 VCC power supply input
SQWOutputConfigurable square-wave output
Alarm 1 and/or Alarm 2 interrupt output
CLKInput SPI clock input
MISOOutputSPI master in, slave out
MOSIInputSPI master out, slave in
SSInputSPI active-low chip select

CLK, MISO, MOSI, and SS make up the DS3234’s SPI interface. All four need to be connected to your microcontroller’s I/O pins to allow communication between the chips. Use of the multi-talented SQW pin is optional, but it can come in very handy if you’re using alarms or need an extra time-keeping output. More on that and the power supply pins below.

Powering the DS3234

The Deadon RTC breakout board does not include any voltage regulation, so power supplied to the “VCC” pin should be kept within the DS3234’s (wide) recommended operating range: 2.0 to 5.5V. Fortunately, the breakout should work with either 3.3V or 5V development boards!

The chip is designed to be as low-power as possible. While its powered at 5V, during communication bursts, the chip may consume upward of 400-700µA, but it will usually run closer to 120µA. When the primary power supply is removed and the chip is running off its backup battery, it will consume around 2µA.

Assuming it has capacity of 47mAh, a fully charged 12mm coin cell battery can keep the DS3234 running for up to 2.68 years, if the chip consumes an average 2µA!

(47mAh / 2µA = 23500 hours = 979.17 days = 2.68 years)

Alarms and the SQW (Square Wave)/ Alarm Interrupt Output Pin

One of the DS3234’s most unique features is its pair of configurable alarms: appropriately named “Alarm 1” and “Alarm 2.” The higher-resolution alarm 1, can be set to trigger on any second, minute, hour, and/or day/date combination, while alarm 2 can monitor anything from minutes to days/dates. With every second that passes, the DS3234 compares the time with any alarms that may be set. If everything matches, the chip sets a flag to indicate that one, or both, of the alarms has triggered.

Aside from its SPI pins, the DS3234 also features a very versatile pin, labeled “SQW.” This pin can be configured as either a square wave output (with output frequencies ranging from 1Hz to 8.192kHz), or as an active-low interrupt output, indicating an alarm has been triggered.

In order to use the SQW pin as an output or interrupt, it must be connected to a pull-up resistor. A 10kΩ resistor, connected between SQW and VCC, or your microcontroller’s internal pull-up resistors should do the job.

Hardware Hookup

Before you can insert the DeadOn RTC Breakout into a breadboard, or otherwise connect it to your microcontroller, you’ll need to solder something to the 7-pin header. If you plan on breadboarding with the chip, we recommend straight male headers. Female headers or even a few strips of wire are other good options.

If you’re soldering headers, you may want to insert the pins into the “top” side of the board – maintaining access to the battery and a good view of the labels.

Soldering the headers

Conveniently, the header’s shroud is about the same height as the DS3234, so it shouldn’t interfere with breadboard-plugging.

Inserting the Battery

The DeadOn RTC Breakout does not ship with a 12mm coin cell, but the battery is recommended – without it, the RTC will lose track of time whenever power is lost. When inserting the battery, make sure the “+” sign is facing up – it should touch the top of the battery holder.

Inserting the battery

Hopefully you won’t have to remove and replace that battery for a good many years!

Example Circuit

The DS3234’s SPI interface means, to interface with the chip, you’ll need at least six wires between your microcontroller and the breakout board: power, ground, master-in/slave-out (MOSI), master-out/slave-in (MISO), serial clock (SCLK), and slave-select (SS).

Here is an example hookup diagram demonstrating how to hook the board up to an Arduino Uno. The diagram also connects SQW to the Arduino, using the pin as an interrupt output. This wire is optional, but you’ll have to (very slightly) modify the example code if it’s not connected.

Fritzing diagram

Using the SparkFun DS3234 Arduino Library

We’ve written an Arduino library for the DS3234, which takes care of all of the SPI communication, bit-shifting, register-writing, and clock-managing; it even sets the time of your RTC automatically! Grab the most recent version of the library from our SparkFun_DS3234_RTC_Arduino_Library GitHub repository, or click the link below:

Download the SparkFun DS3234 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.

Installing a library from ZIP file

Using the DS3234_RTC_Demo Example

Once you’ve downloaded the library, open the DS3234_Demo by navigating to File>Examples>SparkFun DS3234 Real Time Clock (RTC)>DS3234_RTC_Demo:

alt text

If you don’t have the SQW pin connected – used in this example as the alarm interrupt – comment out the #define INTERRUPT_PIN 2 line, toward the top of the sketch. The loop will instead poll the DS3234 for the alarm status.

Make sure your board and port are set correctly and upload! Then click over to the Serial Monitor. Make sure the baud rate is set to 9600 bps, and you should begin to see the seconds fly by:

Serial monitor example output

The alarms are configured to ring every thirty seconds – alarm 2 triggering at the top of the minute, and alarm 1 triggering at 30-seconds on the minute.

Using the SparkFun DS3234 Arduino Library

The example demonstrates almost all of the DS3234’s functionality. Here’s a quick primer on how to incorporate the library into your project:

Initialization

To begin, make sure you include the SparkFunDS3234RTC.h library. Above that, you’ll need to include SPI.h the Arduino SPI library:

language:c
#include <SPI.h>
#include <SparkFunDS3234RTC.h>

The DS3234 library defines an object conveniently named rtc to access all of the functions and data of the RTC module. To initialize the RTC, begin by calling the rtc.begin(<cs_pin>) function in your setup() area:

language:c
#define DS13074_CS_PIN 10

void setup()
{
    ...
    rtc.begin(DS13074_CS_PIN);
    ...
}

The begin() function takes one parameter – the SPI slave-select pin, “SS.” In our example circuit we connected SS to Arduino pin 10, though it can be connected to any other pin.

Setting the Time

Once the RTC is initialized, you can set the RTC’s time. There are a few options here. We recommend using either the rtc.autoTime() function, which sets the RTC’s clock your computer’s date and time (based on the time of compilation), or rtc.setTime(<second>, <minute>, <hour>, <day>, <date>, <month>, <year>), which allows you to precisely set the clock.

The demo example defaults to using rtc.autoTime(), which sets your RTC’s time and date to your computer’s time and date. It may end up being a handful of seconds off, as time continues ticking while the code is uploaded.

Set and Forget!

Once the RTC's time and date register have been set – using either the autoTime or setTime functions – you may never have to set the clock again!

Consider commenting out the autoTime or setTime entirely once you've perfectly configured the clock.

If you want to manually set the time, use the setTime() function. For example:

language:c
// Set to 13:37:42 (1:37:42 PM)
int hour = 13;
int minute = 37;
int second = 42;
// Set to Monday October 31, 2016:
int day = 2; // Sunday=1, Monday=2, ..., Saturday=7.
int date = 31;
int month = 10;
int year = 16;

rtc.setTime(second, minute, hour, day, date, month, year);
12-Hour Mode

The RTC defaults to 24-hour mode, but does support 12-hour mode with an AM/PM bit. If you’d like to use 12-hour mode, simply call rtc.set12Hour() (or rtc.set24Hour() to switch back to 24-hour mode).

To set the time in 12-hour mode, an extra parameter – AM or PM– should be added after ther `hour` variable. For example:

setTime(14, 42, 7, PM, 1, 28, 12, 16); // Set time to 7:42:14 PM, Sunday December, 28
setTime(14, 42, 7, PM, 1, 28, 12, 16); // Set time to 7:42:14 PM, Sunday December, 28

Reading the Time

Once the clock is set, it will automatically begin incrementing second-by-second, minute-by-minute, year-by-year. To read the time and date values, begin by calling rtc.update(). This will command the DS3234 to read all of its data registers in one, fell swoop.

After the RTC data is updated, you can read those updated values by calling rtc.hour(), rtc.minute(), rtc.second(), etc. For example:

language:c
rtc.update(); / Update RTC data

// Read the time:
int s = rtc.second();
int m = rtc.minute();
int h = rtc.hour();

// Read the day/date:
int dy = rtc.day();
int da = rtc.date();
int mo = rtc.month();
int yr = rtc.year();

“Day” is the “day of the week”, e.g. Sunday, Monday, Tuesday… rtc.day() returns an integer between 1 and 7, where 1 is Sunday and 7 is Saturday (sorry week-starts-on-Monday truthers). Alternatively, you can call rtc.dayChar() or rtc.dayStr(), which return a character or full-string representation of the day of the week.

Setting/Reading Alarms

The DS3234’s pair of alarms can be set with the setAlarm1(<second>, <minute>, <hour>, <date>, <day/date>) and setAlarm2(<minute>, <hour>, <date>, <day/date>) functions. Alarm 1’s resolution can go as low as seconds, while Alarm 2 is limited to minutes.

All variables in the setAlarm functions are optional. If they’re not explicitly set, a variable will default to 255, and will be masked out of the alarm checking. An alarm triggers whenever any of its non-masked-out variables exactly match the current time and/or day/date.

Here are a few alarm-setting examples, to show off how the functions can be used:

language:c
// With no values passed, the alarms will trigger every second/minute:
setAlarm1(); // Alarm 1 triggers every second
SetAlarm2(); // Alarm 2 triggers every minute
// With one value passed, the alarms will trigger on second/minute matches:
setAlarm1(25); // Alarm 1: whenever SECONDS are 25 (e.g. 2:01:25, 2:02:25, etc...)
setAlarm2(45); // Alarm 2: whenever MINUTES are 45 (e.g. 13:45, 14:45, etc...)
// With two values passed, alarms will trigger on second/minute or minute/hour matches:
setAlarm1(19, 15); // Alarm 1: whenever SECONDS are 19 and MINUTES 15 (e.g. XX:15:19)
setAlarm2(0, 30); // Alarm 2: midnight:30
// Three values passed: Alarm 1 triggers at specific time, Alarm 2 triggers at time/day-of-month
setAlarm1(17, 33, 19); // Alarm 1: 19:33:17 (7:33:17 PM)
setAlarm2(0, 1, 2); // Alarm 2: 1:00 on the 2nd day of the month
// Four values passed:  Alarm 1 triggers at specific time/day-of-month, Alarm 2 triggers at time/day-of-week
setAlarm1(11, 11, 11, 19); // Alarm 1: 11:11:11 on the 19th day of the month
setAlarm2(17, 7, 1, true); // Alarm 2: 7:17:00 on a Monday (1)
// If last parameter in alarm 1 or alarm 2 is true, it will alarm on a weekday match
setAlarm1(4, 5, 6, 7, true); // Alarm 1: 6:05:04 on Saturday (7)
Alarming in 12-Hour Mode

If you're using the DS3234 in 12-hour mode, you'll need to add an AM or PM after the `hour` variable. For example:

setAlarm1(45, 30, 2, PM); // Set alarm 1 for 2:30:45 PMsetAlarm2(0, 6, AM; // Set alarm 2 for 6:00 AM
setAlarm1(45, 30, 2, PM); // Set alarm 1 for 2:30:45 PM setAlarm2(0, 6, AM); // Set alarm 2 for 6:00 AM

To monitor the state of either alarm, call the rtc.alarm1() and rtc.alarm2() functions. These will check a status flag in the DS3234 and return true if the alarm has triggered.

language:c
if (rtc.alarm1())
    Serial.println("ALARM 1 is triggered!");
if (rtc.alarm2())
    Serial.println("ALARM 2 is triggered!");

Finally, to use the SQW pin as an interrupt, call the rtc.enableAlarmInterrupt(); function. The interrupt is active-low, which means you’ll want to pull the pin high through a resistor (or an internal pull-up). When the pin reads low, an interrupt has occurred, which means its time to read either/both of the alarm() functions.


For more on using the SparkFun DS3234 Arduino Library consider reading through the header file, which documents all of the Arduino sketch-available functions.

Resources & Going Further

For more on the DeadOn RTC Breakout and the Maxim DS3234, check out the links below:

Now that your Arduino is ticking away the seconds, what project are you going to create with the DeadOn RTC? Need some inspiration, check out some of these related tutorials:

Reaction Timer

Demonstrate mental chronometry with this simple reaction timer!

Alphanumeric GPS Wall Clock

This is a GPS controlled clock - a clock you truly never have to set! Using GPS and some formulas, we figure out what day of the week and if we are in or out of daylight savings time.

Adding a Timed Button to a Project

This tutorial will walk you through making a timed power controller for interactive projects. You will learn how to add an on button that will provide power to your project for an amount of time and then turn off again.
New!

Real Time Clock Module Hookup Guide

A quick introduction to the DS1307 RTC module and a hookup guide for the SparkFun Breakout.

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

Real Time Clock Module Hookup Guide

$
0
0

Real Time Clock Module Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The SparkFun Real Time Clock Module is a simple breakout board for the DS1307 real-time clock (RTC). It can accurately keep track of seconds, minutes, hours, days, months, and years for almost a decade, so your microcontroller doesn’t have to. It’s the perfect component for clocks, calendars, or any other time-keeping project.

SparkFun Real Time Clock Module

BOB-12708
$14.95
6

The IC on the SparkFun RTC Module is the Maxim DS1307. It features a two-wire I2C interface and even includes a square wave output pin. Plus, with a battery backup, the DS1307 can keep time for almost a decade or more (typically 17 years)!

This tutorial serves as a general introduction to the DS1307 and the SparkFun Real Time Clock Module. It covers both the hardware and firmware requirements of the breakout – documenting both example wiring and Arduino code for the chip.

Suggested Materials

You’ll need a handful of extra parts to get the RTC Module 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 DS1307 and relay the RTC’s 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.)

Arduino Pro Mini 328 - 5V/16MHz

DEV-11113
$9.95
95
SparkFun RedBoard - Programmed with Arduino

DEV-12757
$19.95
106
Arduino Uno - R3

DEV-11021
$24.95
80
Pro Micro - 5V/16MHz

DEV-12640
$19.95
31
5V Recommended! The DS1307 should nominally be powered at a voltage around 5V. It doesn't support 3.3V. If your development board runs at 3.3V, you may need to do some level-shifting to get the module communicating.

Four or five jumper wires and a breadboard help interface the RTC Module to your Arduino.To insert the breakout into the breadboard, you’ll need to solder headers 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

The RTC Module does include a 12mm Coin Cell Battery. You shouldn’t need one for a long while, but if you want to stock up on the lithium batteries, the option is there.

Suggested Reading

The SparkFun RTC Module is a very beginner-friendly breakout board. There are, however, still a few concepts you should be familiar with. If any of the tutorial titles below sound foreign to you, consider giving them a look-through:

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!

What is an Arduino?

What is this 'Arduino' thing anyway?

I2C

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

Hardware Overview

The RTC Module surrounds the DS1307 with all of the components it needs to count time, communicate, and maintain power. The communication and power pins are all broken out to a single, 5-pin header, with pin labels on the top side of the board.

RTC Module Breakout top view

The bottom side of the breakout consists almost entirely of the 12mm coin cell battery holder.

RTC Module Breakout bottom view

Pinout

The five pin breakouts on the board provide access to the communication interface and allow you to supply the chip’s primary power source.

Pin LabelInput/OutputDescription
SDABi-directionalI2C bus data line
SCLInputI2C bus clock line
SQWOutputConfigurable square-wave output
GNDSupply InputGround (0V) supply
5VSupply InputDS1307 VCC power supply input.

Powering the DS1307

The RTC module breakout board does not include any voltage regulation, so power supplied to the “5V” pin should be kept within the DS1307’s recommended operating range: 4.5 to 5.5V.

The chip is designed to be as low-power as possible. During communication bursts, the chip may consume upward of 1.5mA, but it will run at closer to 200µA.

When the primary power supply is removed and the chip is running off its backup battery, it will consume between 300-800nA (depending on whether the SQW pins is configured as an output).

Assuming it has capacity of 47mAh, a fully charged 12mm coin cell battery can keep the DS1307 running for up to 17.88 years if the chip consumes its minimum 300nA!

(47mAh / 300nA = 156666.67 hours = 6527.78 days = 17.87 years)

Using the SQW (Square Wave) Output Pin

Aside from its I2C pins, the DS1307 also features a configurable square wave output pin – SQW. This pin can be configured to produce one of six signals, or it can be turned off.

SQW StateDescription
1 HzSquare wave at 1Hz
4.096 kHzSquare wave at 4.096 kHz
8.192 kHzSquare wave at 8.192 kHz
32.768 kHzSquare wave at 32.768 kHz
0Pin driven LOW (0V)
1Pin driven high (5V)

In order to use the SQW pin as an output driver, it must be connected to a pull-up resistor. A 10kΩ resistor, connected between SQW and 5V, should do the job.

I2C Pull-Up Resistor Disable

A small 3-way jumper, located on the top side of the board (below the brown-ish capacitor) is connects the on-board 4.7kΩ pull-up resistors to the 5V supply. If you need to deactivate these pull-ups, the jumper can be cleared — effectively removing the resistors from the circuit.

A little bit of solder wick and a touch of your soldering iron should remove the jumper's solder blob.

alt text

Pull-up resistor solder jumper

Hardware Hookup

Before you can insert the RTC Module into a breadboard, or otherwise connect it to your microcontroller, you’ll need to solder something to the 5-pin header. If you plan on breadboarding with the chip, we recommend straight male headers. Female headers or even a few strips of wire are other good options.

Headers can be assembled on either side of the board – one will give you easy view of the pin labels, the other easy access to the coin cell. If you choose the label-view, you may need to add a little air gap between the header shroud and the board, so the header/breadboard can clear the height of the coin cell.

Headers soldered to breakout

Breadboards can make a great “third hand” while you’re soldering these headers – especially in this case, where you need to take the height of the battery holder into consideration.

Example Circuit

The DS1307’s I2C interface means, to interface with the chip, all you need is four wires between your microcontroller and the breakout board: power, ground, data, and clock. The SQW pin can optionally be wired to the Arduino and used as a pulse-counter.

Here is an example hookup diagram demonstrating how to connect the board up to an SparkFun RedBoard:

RTC Module example fritzing diagram

Using the SparkFun DS1307 Arduino Library

We’ve written an Arduino library for the DS1307, which takes care of all of the I2C communication, bit-shifting, register-writing, and clock-managing; it even sets the time of your RTC automatically! Grab the most recent version of the library from our SparkFun_DS1307_RTC_Arduino_Library GitHub repository:

Download the SparkFun DS1307 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.

Adding library via ZIP file

Using the DS1307_RTC_Demo Example

Once you’ve downloaded the library, open the DS1307_Demo by navigating to File>Examples>SparkFun DS1307 Real Time Clock (RTC)>DS1307_RTC_Demo:

Opening the example file

Once the demo’s loaded, make sure your board and port are set correctly – no modifications required – and upload! Then click over to the Serial Monitor. Make sure the baud rate is set to 9600 bps, and you should begin to see the seconds fly by:

Example serial monitor output

Using the SparkFun DS1307 Arduino Library

The example demonstrates almost all of the DS1307’s functionality. Here’s a quick primer on how to incorporate the library into your project:

Initialization

To begin, make sure you include the SparkFunDS1307RTC.h library. Above that, you’ll need to include Wire.h the Arduino I2C library:

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

The DS1307 library defines an object conveniently named rtc to access all of the functions and data of the RTC module. To initialize the RTC, begin by calling the rtc.begin() function in your setup() area:

language:c
void setup()
{
    ...
    rtc.begin();
    ...
}

Setting the Time

Once the RTC is initialized, you can set the time in the clock. There are a few options here. We recommend using either the rtc.autoTime() function, which sets the RTC’s clock your computer’s date and time (based on the time of compilation), or rtc.setTime(second, minute, hour, day, date, month, year), which allows you to precisely set the clock.

The demo example defaults to using rtc.autoTime(), which sets your RTC’s time and date to your computer’s time and date (may be a dozen seconds off).

Set and Forget!

Once the RTC's time and date register have been set – using either the autoTime or setTime functions – you may never have to set the clock again!

Consider commenting out the autoTime or setTime entirely once you've perfectly configured the clock.

If you want to manually set the time, use the setTime() function. For example:

language:c
// Set to 13:37:42 (1:37:42 PM)
int hour = 13;
int minute = 37;
int second = 42;
// Set to Monday October 31, 2016:
int day = 2; // Sunday=1, Monday=2, ..., Saturday=7.
int date = 31;
int month = 10;
int year = 16;

rtc.setTime(second, minute, hour, day, date, month, year);
12-Hour Mode

The RTC defaults to 24-hour mode, but does support 12-hour mode with an AM/PM bit. If you’d like to use 12-hour mode, simply call rtc.set12Hour() (or rtc.set24Hour() to switch back to 24-hour mode).

To set the time in 12-hour mode, an extra parameter – AM or PM– should be added after ther `hour` variable. For example:

setTime(14, 42, 7, PM, 1, 28, 12, 16); // Set time to 7:42:14 PM, Sunday December, 28
setTime(14, 42, 7, PM, 1, 28, 12, 16); // Set time to 7:42:14 PM, Sunday December, 28

Reading the Time

Once the clock is set, it will automatically begin incrementing second-by-second, minute-by-minute, etc. To read the time and date values, begin by calling rtc.update(). This will command the DS1307 to read all of its data registers in one, fell swoop.

After the RTC data is updated, you can read those updated values by calling rtc.hour(), rtc.minute(), rtc.second(), etc. For example:

language:c
rtc.update(); / Update RTC data

// Read the time:
int s = rtc.second();
int m = rtc.minute();
int h = rtc.hour();

// Read the day/date:
int dy = rtc.day();
int da = rtc.date();
int mo = rtc.month();
int yr = rtc.year();

“Day” is as in “day of the week”, e.g. Sunday, Monday, Tuesday… rtc.day() returns an integer between 1 and 7, where 1 is Sunday and 7 is Monday (sorry week-starts-on-Monday truthers). Alternatively, you can call rtc.dayChar() or rtc.dayStr(), which return a character or full-string representation of the day of the week.


For more on using the SparkFun DS1307 Arduino Library consider reading through the header file, which documents all of the Arduino sketch-available functions.

Resources & Going Further

For more on the Real Time Clock Module and the Maxim DS1307, check out the links below:

Now that your Arduino is ticking away the seconds, what project are you going to create with the RTC Module? Need some inspiration, check out some of these related tutorials:

Reaction Timer

Demonstrate mental chronometry with this simple reaction timer!

Alphanumeric GPS Wall Clock

This is a GPS controlled clock - a clock you truly never have to set! Using GPS and some formulas, we figure out what day of the week and if we are in or out of daylight savings time.

Adding a Timed Button to a Project

This tutorial will walk you through making a timed power controller for interactive projects. You will learn how to add an on button that will provide power to your project for an amount of time and then turn off again.
New!

DeadOn RTC Breakout Hookup Guide

An introduction to the DS3234 real-time clock (RTC), example wiring diagrams, and an Arduino library!

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

IoT Industrial Scale

$
0
0

IoT Industrial Scale a learn.sparkfun.com tutorial

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

Introduction

scale jump test

What does a baby elephant weigh?* How much impact force does a jump have?? How can you tell if a rain barrel is full without looking inside??? Answer all these questions and more by building your very own Internet of Things (“IoT”) industrial scale using the SparkFun OpenScale board!

This project is intended for folks with a lil' bit of background using Arduino or other microcontrollers. But, whether this is your first or 137th project, check out the links in the Suggested Reading section below (and throughout the tutorial) or leave a comment if you have any questions!

Read time: ~ 15 min.

Build time: Approx. 2 - 3 hours

alt text

*To weigh a baby elephant, you might need to be a zookeeper or otherwise have an elephant friend.. but you could always weigh Fido and/or kitty!

Required Materials

To follow along and build your own scale, all the parts used have been listed for your convenience.

Electronics

To make the system wireless:

All these parts can be found in the wish list below.

Scale and Casing

  • Terminal blocks (5)
  • Three (3) M3 screws per load cell (total of 12)
  • One (1) project case (to protect the electronics)
  • One (1) base board, and one (1) top board (for the scale platform)
    • My base board was ~ 16" x 16" and my top board was ~ 12" x 14".
    • Both boards should be sturdy and not flex or dent.
  • Wood slats to frame the sides of the top board to hold it in place.
  • Four (4) feet for base

Suggested Reading

Before getting started with this project, you may want to read up on some of the components and tools used throughout.

Serial Terminal Basics

This tutorial will show you how to communicate with your serial devices using a variety of terminal emulator applications.

OpenScale Applications and Hookup Guide

OpenScale allows you to have a permanent scale for industrial and biological applications. Learn how to use the OpenScale board to read and configure load cells.

Getting Started with Load Cells

A tutorial defining what a load cell is and how to use one.

Photon Development Guide

A guide to the online and offline Particle IDE's to help aid you in your Photon development.

As usual, don’t forget to read the Datasheet for the Load Cells and any other components you with to use in your project.

Measuring Weight

How Do We Measure Weight??

load sensor

Strain gauges! Also called load sensors, strain gauges measure electrical resistance changes in response (and proportional) to, well, strain! Strain is how much an object deforms under an applied force, or pressure (force per area). Check out this super awesome tutorial for more info on how strain gauges work.

Usually what you’ll find in a bathroom scale is a load cell, which combines four strain gauges in a wheatstone bridge. This project uses four disc compression load cells rated at 200 kg, like the one pictured above.

OpenScale Overview

OpenScale

The OpenScale is a specialized board that allows a user to easily read and configure all types of load cells and strain gauges. It’s designed for constant loads, includes an on-board temperature sensor, and is particularly helpful for places that are tricky to get to (e.g. under a beehive or conveyor belt).

The OpenScale combines an HX711 load cell amplifier with an ATmega328P, so you can program it just like an Arduino (Arduino Uno, specifically). The OpenScale uses TTL serial communication at 9600bps 8-N-1 to transmit and receive data. It comes with software that allows it to be controlled in, and print data to, the Arduino IDE serial monitor.

Here’s the GitHub page for the OpenScale, which includes the Eagle schematic files.

Build the Electronics

Schematic:

Fritzing diagram

Part 1: Connect the Load Cells!

terminal block

Load cells have four signal wires:

  • Red: Excitation+ (E+) or VCC
  • Black: Excitation- (E-) or ground
  • White: Output+ (O+), Signal+ (S+)+ or Amplifier+ (A+)
  • Green (or blue): Output- (O-), Signal- (S-), or Amplifier (A-)

They also have bare (or yellow) grounding wires to block outside (electromagnetic) noise.

connect to scale

Connect all five load cell wires in parallel to the OpenScale terminal blocks with the corresponding labels. You might need to switch the green and white load cell wires– check this by adding weight to the load cells. If the weight is decreasing, switch the wire orientation.

Since the OpenScale terminal blocks are somewhat cramped with four load cells, external connectors are recommended. I used the terminal blocks pictured above. If you have a case for the electronics, remember to put the connectors INSIDE the case before connecting them to the load cells (not speaking from experience or anything..).

Part 2: Connect the OpenScale to a Data Logger!

In addition to printing, reading, and gathering data from the Arduino serial monitor (see “Reading Load Cells!”), we can add a Photon microcontroller to connect to WiFi and upload the measurements to the Internet!

close up

Connect the OpenScale “Serial Out” ground (“GND”) port to the Photon GND, and the OpenScale “TX” port to the Photon “RX” port. If your data logger needs power, connect the OpenScale 5V port to the data logger Vin port. That’s it!

Build the Base and Case

LoadCellsMounting

  1. Plan out, measure, and mark location of load cells.

    Load cells should be at least 1" in from the top platform board sides and installed equidistant and on the same plane (aka same height) with each other.

    PlasticStencilDrilling

    Each load cell needs three M3 type screws, which requires fairly precise measurements. I opted for a quick & easy solution: make a plastic stencil that marks the load cell outline and the location of the screw holes. The plastic I used was cut from a discarded strawberry container (yay, free and upcycled!).

  2. Drill holes for load cell screws and attach load cells to base board.

    base feet
  3. Attach feet to base.

    BaseWall
  4. Secure the scale platform.

    Place platform on top of the load cells. Attach wood slats to sides of base with wood glue and/or screws to secure the platform in place laterally, but not vertically. AKA, be sure that there is no resistance to the board pushing downward.

    Add brackets on opposite sides for a more secure hold.

  5. Place electronics into project box container (or tupperware) and drill holes for cables.

    final
  6. Admire your handiwork!

Reading the Load Cells

Connect the OpenScale

calibration

One of the awesome features of the OpenScale program is that it outputs data to the Arduino IDE serial monitor (9600bps). That means all you need to do is plug in your OpenScale via USB, select the appropriate board (Arduino Uno) and port, and you can read the load cell data directly from the Arduino Serial Monitor or another preferred terminal program. More info on how to do this here.

Enter ‘x’ to bring up the OpenScale settings menu. Entering ‘x’ again leaves the menu and the OpenScale will start printing data!

serial monitor

Note: If you are connected to another microcontroller, the OpenScale does not send data when in the menu mode.

Calibrate

Before we gather any data, we need to calibrate the OpenScale to get accurate measurements. It’s also recommended to re-calibrate the system every few weeks (or days) to avoid creep (slow change in reading over time).

To calibrate the scale:

  1. Remove all weights (except the platform).
  2. Open the OpenScale menu and select ‘2’ to open the calibration setting.
  3. Place a (known) weight on the scale and adjust the calibration factor using ‘+’ and ‘-’ until the scale reads out the calibration weight within a reasonable margin in error.*

Also, the load cell output varies with temperature (‘cause heat causes expansion), so we need to keep the system at a constant temperature. If you wanna get fancy, you can also use different calibration factors at different temperatures (or temperature ranges)..

*My experimental uncertainty was about +/- 5 lbs.

Tare

Each time you power up the OpenScale, you’ll need to tare it. This is an easy process, but it means you need to connect the OpenScale directly to a laptop and open the settings menu.

To tare the scale, remove all weights. Input ‘1’ in the OpenScale menu, wait for it to finish taring, then exit the menu and check that the output is close to zero (+/- 5 lbs). If the reading is still off, taring again should fix the problem – if not, check that the load cell grounding wires are properly connected to ground.

Remove Trigger

We also need to remove the serial trigger from the OpenScale. Do this by going to the menu, inputting ’t', and turning the serial trigger to OFF.

Customizing the OpenScale

You can change various other settings on the OpenScale using the serial monitor, including units (lbs/kg), print rate, decimal places, etc. You can adjust, or peruse, the entire OpenScale program by downloading it from GitHub!

Program the Photon

Write a program for the Photon that will read in the serial output data from the OpenScale and push it to the IoT platform of your choice.

Or you can use/modify my code :) Here’s the GitHub repository for the IoT scale, or just copy and paste the code from here:

IoT Industrial Scale Code


This program reads data from the OpenScale and pushes it to ThingSpeak (also prints it to the Photon serial monitor). ThingSpeak is super easy (and free!) to set up, the only downside is that it only allows data to be posted every 15s.

What you need to do to make the program work for your setup:

variables to change

Click for a closer look.

  1. Include your WiFi SSID (network name) and your WiFi password in lines 53 & 54, and lines 69 & 70.

  2. Set up a ThingSpeak channel!.

    thingspeak channel setup
    1. Name the channel and write a brief description.
    2. Include at least one field name. If you want to push more data, like temperature or a timestamp, include those corresponding fields.
    3. Save the channel!
  3. Copy the “Channel ID” number and the “Write API Key” and input them into lines 84 & 85.

    API keys

Read through the comments in the program code for more information on how the program works.

Test and Refine

test and refine

Prototype complete! Have your favorite human or animal stand (or awkwardly lay..) on the scale to check that it works as expected.

final

Check thoroughly to see if there is anything that needs to be fixed, secured, and/or improved. During my build process I noticed that a lot of the wood I was using to test would get dented by the load cells, resulting in inaccurate readings.

Lessons Learned and Next Steps

jump test

The original goal of my scale was to use it as an impact force plate to gather data on the forces due to jumping (specifically in parkour). Alas, the OpenScale is intended for constant loads and the fastest print rate is 505 ms, which is too slow to get accurate readings on impact force.

Fortunately, we can still use the scale to gather very general data and use this design as a foundation for future versions. Some quick and well-timed preliminary testing by a professional jumper (~165 lbs) resulted in the following readings:

data

This shows a single jump, where the landing corresponds to the highest reading (~ 230 lbs), and the point just before that (~ 135 lbs) is when his feet were in the air. (The weight decrease + little blip after the the peak is when he was stepping off the scale.)

In addition to an updated program to print data faster, I’ll need waaay more data and a consistent, controlled procedure to actually determine any kind of reasonable relationship between impact force, jump height, and weight. Also, the top platform was a bit dented after these tests, so I’ll need a sturdier wood, or metal, scale platform.

Overall, this was a cool proof-of-concept and an informative preliminary test! Plus, there are tons of other practical uses for this simple Internet-connected scale!

Educator Extension

Beyond being a great hands-on project for computer science, engineering, and electronics courses, this is a handy experimentation tool for physics classrooms! Use it to illustrate the difference between weight and mass, demonstrate how acceleration relates to force, or use the on-board temperature sensor to estimate the mathematical relationship between thermal expansion and load cell output.

More Applications:

  • Use the system to measure the weight of a rain barrel and notify you when it is full.
  • Make a bathroom scale that keeps track of your weight (or your animal’s weight).
  • Monitor the weight of your Halloween candy to be sure that no one is sneaking some from under your nose.

Happy building!

Marley

For more IoT SparkFun tutorial fun, check out the links below:

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!

Photon Weather Shield Hookup Guide

Create Internet-connected weather projects with the SparkFun Weather Shield for the Photon.

Photon Remote Temperature Sensor

Learn how to build your own Internet-connect, solar-powered temperature collection station using the Photon from Particle.

Hazardous Gas Monitor

Build a portable gas monitor to check for dangerous levels of hazardous gases.

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

Getting Started with the Tessel 2

$
0
0

Getting Started with the Tessel 2 a learn.sparkfun.com tutorial

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

What is the Tessel 2?

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 (IoT).

Tessel 2

DEV-13841
$44.95

OK, So What’s a Development Board?

Development boards are platforms for prototyping and building embedded systems. At the heart of (most) development boards is a microcontroller, which combines a processor and memory with I/O capabilities. Microcontrollers like the one on the Tessel 2 provide a collection of GPIO (General Purpose Input Output) pins for connecting input and output devices. The pins on the microcontroller itself — a chip — are small, too small for human fingers to work with easily (plus you’d need to solder things to them). Instead, development boards connect these GPIO pins to pin sockets that are easy to plug things into.

Other common features of boards play a supporting role: connections for programming and communicating with the board, status lights, reset buttons and power connections.

Powerful boards like the Raspberry Pi and Tessel are sometimes also called Single-Board Computers (SBCs).

Tessel 2’s Features

The Tessel is a mighty little board. Some of Tessel 2’s nifty goodies include:

  • 2 USB ports (you can connect cameras or flash storage, for example)
  • 10/100 ethernet port
  • 802.11 b/g/n WiFi
  • 580MHz Mediatek router-on-a-chip (you can turn your Tessel 2 into an access point!)
  • 48MHz SAMD21 coprocessor (for making I/O faster)
  • 64MB DDR2 RAM, 32MB of flash (lots of space for your programs and stuff)

Working with Tessel 2

Tessel has a set of Command Line Interface (CLI) tools for setting up and working with the Tessel 2 board. You’ll install these and do a one-time setup provisioning of your Tessel.

You can write scripts for the Tessel 2 in any text editor, using JavaScript and including npm modules as you desire. A one-line terminal command deploys and executes your script on the Tessel.

Inputs and Outputs

There are two primary sets of pins on the Tessel 2: Port “A” and Port “B”. Each port has 10 pins: two for power (3.3V and ground) and eight GPIO pins.

The Tessel 2's GPIO pins: Port A and Port B

Some pins support different features.

Powering the Board

There are multiple ways to power the Tessel 2. We’ll start by using the included USB cable.

Over USB

Power over USB

Connecting to the board directly with USB will allow you to easily modify any circuits and redeploy code from the comfort of your desk, without having to retrieve your project. This is also handy when you don’t have access to the local network (for deploying code over WiFi).

USB Wall Charger

USB wall charger

Once you have completely set up and provisioned your Tessel 2, you can deploy code through your local WiFi network. At some point you’ll itch to make your Tessel free of wires and tethering, but it still needs power. We supplied a 5V USB charger in the Johnny-Five Inventor’s Kit (J5IK) so you can place your project in a semi-remote location around your home or office and deploy code from anywhere on your local network.

USB Battery Pack

Battery Pack

USB battery packs are becoming quite popular as swag and giveaways at events. We collect them like candy because they allow us to power projects with minimal consideration to power management circuitry. If you have one of these handy, just use the included USB cable to plug the Tessel 2 into your battery, and away you go! That’s it – simple as pie.

Board Details

The Tessel 2 has two IO modules, Port A and Port B. Each port has 8 GPIO (general-purpose I/O) pins. Here’s their naming conventions and what all of them do.

alt text

Pin Naming Conventions

The pins on the Tessel 2 are broken out across the two different ports. The naming conventions in code will be referenced with the port letter first and then the pin number of that port. The port letter is not case sensitive! As an example, the first pin on port A would be referred to as pin a0 or A0. Use this table as a reference in terms of the naming of pins.

PortPin NumberJohnny-Five Name
A0“a0” or “A0”
A1“a1” or “A1”
A2“a2” or “A2”
A3“a3” or “A3”
A4“a4” or “A4”
A5“a5” or “A5”
A6“a6” or “A6”
A7“a7” or “A7”
B0“b0” or “B0”
B1“b1” or “B1”
B2“b2” or “B2”
B3“b3” or “B3”
B4“b4” or “B4”
B5“b5” or “B5”
B6“b6” or “B6”
B7“b7” or “B7”

Pin Capabilities: What Each Pin Can Do

The pins of each port have different functionalities available to them.

Other things to know:

  • All eight numbered pins, both ports (16 total), can be used as GPIO.
  • Pins 4 and 7 on Port A support analog-to-digital input. All pins on Port B support analog input.
  • Pins 5 and 6 on both ports support Pulse-Width Modulation (PWM).
  • Pins 0 and 1 on both ports can be used for I2C serial communication.
  • Serial TX/RX (hardware UART) is available on both port, pins 5 (TX) and 6 (RX).
  • Port B, Pin 7: Supports digital-to-analog conversion (DAC)

The two ports are essentially duplicates, with the following exceptions:

  • Port B: All numbered pins can be used for analog input.
  • Port B, Pin 7: Supports DAC.

For exhaustive details, see the pin functionality reference chart below:

PortPin NumberDigital I/OSCLSDATXRXAnalog InAnalog OutInterruptPWM
A0
A1
A2
A3
A4
A5
A6
A7
B0
B1
B2
B3
B4
B5
B6
B7

Software Setup

Let’s prepare the software side of things so you’re ready to do the experiments in this guide. You’ll need to have a few things installed, and you’ll want to set up a project area for your JavaScript programs. So, don’t skip ahead!

Installing Needed Things

You’re going to need:

  • A text editor
  • Node.js
  • A terminal application

Installing a Text Editor: Atom

You will need a text editor in which to edit and save your JavaScript files. This means a plain text editor, not a Word document. If you’ve already got one – like SublimeText, Notepad++, vim, etc. – then groovy. If not, go ahead and install Atom.

atom text editor logo

If you have never used a text editor to write JavaScript, HTML, etc., we recommend using Atom. Atom is a free and open source text editor that works on all three major operating systems. It is lightweight and, when you get comfortable, it’s hackable!

Download Atom by heading to the Atom website.

alt text

Installing Node.js

node.js logo

Node.js is a JavaScript runtime– that is, it’s software that can execute your JavaScript code. Node.js has special features that support some of the best potentials of the JavaScript programming language, like event-driven, non-blocking I/O. npm is Node’s package manager. It’s a giant repository of encapsulated bits of reusable, useful code – called modules– that you can use in your programs. npm will get installed for you when you install Node.js.

alt text

Installing Node.js is a straightforward download-and-double-click process. Head on over to the Node.js website. Heads up: You’ll want to select the “LTS” version for download (LTS stands for Long-Term Support). At time of writing, LTS is v4.4.5:

alt text

Using a Terminal: Command Line Basics

Working with the Tessel is just like doing web development. But if you’re not familiar with web development, you might want to take a minute or two to get comfortable with some key tools of the trade: the command line, which is the “terminal” where you execute commands, and the text editor, where you work on and save your programs. Tessel’s site has a great resource to help you get started with terminal.

In the context of this tutorial, things that should be run in the command line look like this:

hello i am a command line command!

You’ll see this when you get to the first experiment. But, don’t skip ahead; you’ll need the tools we install in the next step.

Setting up a Project Working Area

Take a moment to set up a working area (directory) where you can put the programs for your Johnny-Five Inventor’s Kit (J5IK). You’ll also need to initialize the new project with npm and install needed npm modules for both Johnny-Five and Tessel.

You can accomplish all of this by typing (or copying and pasting) the following commands in a terminal:

mkdir j5ik;
cd j5ik;
npm init -y;
npm install johnny-five tessel-io;

Running these commands will generate some output in your terminal. If everything goes smoothly, you’ll see some output about edits to a package.json file, and some additional output as npm installs the needed modules. You may also see a few WARN statements about missing description or repository field. Don’t worry; nothing’s broken.

An example of the kind of output you’ll see (though yours will differ in some particulars):

Wrote to /your/path/j5ik/package.json:
{"name": "j5ik","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\"&& exit 1"
  },"keywords": [],"author": "","license": "ISC"
}

j5ik@1.0.0 /your/path/j5ik
├── johnny-five
└── tessel-io
npm WARN j5ik@1.0.0 No description
npm WARN j5ik@1.0.0 No repository field.

Hardware Setup

It’s time to get your Tessel 2 set up. The steps we’ll walk through now include:

  1. Installing the t2-cli software tool
  2. Connecting the Tessel 2 with a USB cable
  3. Finding, renaming and provisioning the Tessel
  4. Updating the Tessel’s firmware

Installing the Command Line Tool

Note to Linux users:
  • If you are making a global installation on a Linux computer, be sure to add sudo in front of your npm installation command!
  • Some Linux distributions require a few more library installs for `t2-cli` to work! Please install the libraries with the following command: apt-get install libusb-1.0-0-dev libudev-dev. You can find further documentation here.

You interact with the Tessel 2 using a Command Line Interface (CLI) tool called t2-cli. This tool can be installed using npm (the Node.js package manager, which gets installed automatically with Node.js).

Type the following into your terminal:

npm install t2-cli -g

The -g piece of that command (a flag) is important; this will tell npm to install the package globally, not just in the current project or directory.

The installation will take a few moments, and you will see a bunch of stuff scroll by that looks sort of like this:

alt text

Troubleshooting

Note: If you see any warnings or errors when trying to install `t2-cli`, the first thing to check is your Node.js version. To do this, type the following command in your terminal:
node --version

You’re aiming for the LTS (Long-Term Support) version of Node.js, which at time of writing is v4.4.5. Learn more about how to upgrade and manage node versions with nvm.

Setting up your Tessel!

Now, time to get your hands dirty and get things up and running! Connect your Tessel 2 to your computer and give it about 30 seconds to boot up.

alt text

Once your Tessel 2 has booted (the blue LED will be steady instead of blinking), type the following command in your terminal:

t2 list

The t2-cli tool will look for connected Tessels. Tessels can be connected by USB or over WiFi, but for now it should spot your single, USB-connected Tessel. You’ll see something like this:

alt text

Success! You can now communicate with your Tessel 2!

Naming Your Tessel 2

Giving your Tessel 2 a name is not required to use it, but it’s fun and friendly. To name your Tessel 2 use the following command:

t2 rename [name]

For example, we renamed our Tessel 2 “Bishop” by typing the following:

t2 rename bishop

The t2-cli tool will respond with the following output:

alt text

Double-check it!

t2 list

alt text

Connecting Your Tessel 2 to the Internet

If you’ve ever configured and connected other embedded systems to the internet, the simplicity of this should make you grin.

You’ll need to be connected to your local WiFi network first. To connect your Tessel to a WiFi network, type the following command into your terminal:

t2 wifi -n [SSID] -p [password]

Replace [SSID] with the name of your wireless network (careful, it’s case-sensitive!) and [password] (well, I bet you can figure that out!).

You’ll see some output that looks something like the following:

INFO Looking for your Tessel...
INFO Connected to bishop.
INFO WiFi Enabled.
INFO WiFi Connected. SSID: your-network-ssid, password: your-network-password, security: psk2

That’s it – simple as pie!

You can do a bunch of other stuff with your Tessel and network connectivity. Tessel’s website has in-depth documentation on WiFi connection options.

Troubleshooting

Note: Like Kindles and some Androids, Tessel 2s don’t play nice with 5GHz WiFi networks.

Provision Your Tessel 2

Your Tessel exists, has a name, and is connected to your WiFi network. The next step is to provision the Tessel. That creates a secure, trusted connection between your computer and the Tessel, whether it’s connected by wire or over the air (WiFi). You’ll need to do this before you can deploy code to the Tessel.

Type the following command in your terminal:

t2 provision

You’ll see something like:

INFO Looking for your Tessel...
INFO Connected to bishop.
INFO Creating public and private keys for Tessel authentication...
INFO SSH Keys written.
INFO Authenticating Tessel with public key...
INFO Tessel authenticated with public key.

Verify it worked:

t2 list

You’ll see your Tessel twice! That’s because it’s connected via USB and WiFi.

INFO Searching for nearby Tessels...
USB bishop
LAN bishop

Great! We have one last setup step.

Update Your Tessel 2

The Tessel community is constantly improving the software and firmware for the Tessel 2. It’s likely that in the time between your Tessel 2’s manufacture and now, the firmware has been updated. To update your Tessel, type the following command in your terminal:

t2 update

The update process can last some time, so I would recommend a snack break or checking up on some news feeds while this happens. When the update is finished you will get the command prompt back, and you are all ready to go with your Tessel 2!

Blinking an LED with Johnny-Five and JavaScript

Making an LED (Light-Emitting Diode) blink is the most basic “Hello, World!” exercise for hardware, and is a great way to familiarize yourself with a new platform. In this experiment, you’ll learn how to build a basic LED circuit and use Johnny-Five with your Tessel 2 to make the LED blink and pulse. In doing so, you’ll learn about digital output and Pulse Width Modulation (PWM).

Perhaps you’ve controlled LEDs before by writing Arduino sketches (programs). Using Johnny-Five + Node.js to control hardware is a little different, and this article will illustrate some of those differences. If you’re totally new to all of this — not to worry! You don’t need any prior experience.

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 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, here is an example of a blink script using Node.js and Johnny-Five.

language:javascript
var Tessel = require("tessel-io");
var five = require("johnny-five");

var board = new five.Board({
  io: new Tessel()
});

board.on("ready", () => {
  var led = new five.Led("L2");
  led.blink(500);
});

To make sure that everything is up and running on your Tessel 2, let’s create a project directory as we did in the software setup portion, install the required Node.js modules and add this file to our directory. We can do this through our console by using these commands:

mkdir myProject;
cd myProject;
npm init -y;
npm install johnny-five tessel-io;
touch blink.js;

These commands do the following in order:

  1. Create a directory (folder) called myProject
  2. Change directory, or move into myProject
  3. Initiate an npm project within myProject, which creates a package.json
  4. Install the needed libraries, which in this case are johnny-five and tessel-io, using npm to install them for us; these will be placed in a directory called node_modules
  5. Create a blank file called blink.js in the myProject directory using the touchcommand

With that complete, open your favorite text editor (one choice is atom) and navigate to your blink.js file. Copy and paste the blink code above into your file and save it.

From here you can run blink.js by navigating to your myProject directory and typing the following command in your terminal prompt:

t2 run test.js

Your terminal should output some information that will look similar to this…

image of term output

Then the REPL prompt should appear…

image of term output

… and one of your onboard LEDs should be blinking…

Success! Your Tessel 2 is up and running, and you have taken your first step into JavaScript-based robotics and IoT applications. Go forth and hack away with your newfound superpower.

Resources for Going Further

Check out these project tutorials using the Tessel 2

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!
New!

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!

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.

Check out this Experiment Guide

Useful Links


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

ReconBot with the Tessel 2

$
0
0

ReconBot with the Tessel 2 a learn.sparkfun.com tutorial

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

Let's Build a Robot!

alt text

You are about to build a robot that you can control from a browser on your phone or laptop. You can guide the robot by looking through the robot’s “eyes” (first-person-view, or FPV), because it’s going to stream live video for you so you can see what’s in front of it. You can pilot your robot around corners and into nooks and crannies, chase your cat, entertain guests or just bonk it into a chair leg over and over again—it’s all up to you!

The browser-based controls emulate a thumb-pad joystick, hearkening back to the tactile controls of radio-controlled (RC) cars. The virtual joystick for our robot controls both direction and speed. It’ll snap back to center (and the robot will stop moving) when it’s not being actively dragged and held.

Your robot will be independent of wires and external connections: you’ll control it over your local WiFi network, and we’ll use a USB power bank to give it juice.

alt text

Preflight Check

If this is your first time experimenting with the Tessel 2, there are a few things you gotta do first! We recommend reading through our Getting Started with the Tessel 2 before diving into this project. We promise, it wont take that long.

New!

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.

Dive Deeper into the Tessel 2

The entire Johnny-Five Inventor’s Kit Experiment Guide is great stuff if you’re starting out with the Tessel 2. Pertinent experiments for this tutorial include Experiment 4: Reading a Push Button and Experiment 8: Driving an RGB LED.

Experiment Guide for the Johnny-Five Inventor's Kit

June 28, 2016

Use the Tessel 2 and the Johnny Five Inventors kit to explore the world of JavaScript enabled hardware through 14 awesome experiments!

Materials

To build our robot, you’ll need the following parts:

Additional Supplies

Meet the Supporting Hardware

Shadow Chassis and Wheels

The SparkFun Shadow Chassis is an economic and straightforward platform for constructing a robot. It comes as a kit that has a bunch of parts—our robot will use many, but not all of the parts in the kit.

alt text

The chassis will be the “body” of our robot, a frame to which we can attach motors, wheels, a camera, and our robot’s other components.

Camera

While creating the robot, we experimented with several different USB cameras and ultimately settled on the Creative Live! Cam Sync HD 720P Webcam. While we’ll admit the product name is quite a mouthful, we like this camera because:

  1. It’s reliable: this camera is a work horse—you’ll see.
  2. It’s easy to mount and position: the clip for mounting this camera to a monitor or similar vertical surface is perfectly suited for easy attachment to the top panel of Shadow Chassis (as you’ll see below).

Battery Pack

You’ll be powering the bot with any adequate USB power bank; the iXCC 8000mAh Compact Power Bank (Amazon) is inexpensive and handy.

Build It

To construct the robot, we’ll put the chassis partially together and wire up a motor circuit. Then we’ll install the robot’s software and test the motors before completing the chassis construction.

Constructing the Chassis Base

Connect Motor Mounts

Each of the robot’s two motors will have two supporting plastic mounts from the Shadow Chassis kit: one near the front of the motor and one at the back. When attached, the motor mounts will look like this:

alt text

The back mounts are easy to attach—they just slide on. The front mounts require a quarter-turn to attach. Start by positioning the front mount as shown in the photo below, taking care not to pinch the motor’s wires underneath the mount. Note the position of the motor’s protruding white plastic axle to help you orient the motor.

alt text

Now, rotate the mount counter-clockwise 90 degrees until it clicks into place around the motor. After it’s secured, it should be positioned as in the photo below:

alt text

Now you can construct the chassis base:

alt text

  1. Connect the mounted motors to the chassis by snapping the mounts into the chassis base. Pay attention to the orientation. The wires should be on the inside and the rear mounts of the motor should be toward the front of the robot (at the top in the preceding photo).
  2. Connect the struts at each of the four corners. Push hard to snap into place. Attach an extra support piece at the front of the robot for stability.
  3. Attach the wheels to the motor axles.
  4. Flip the base over and attach the little semicircular support nubbin from the Shadow Chassis kit near the back end of the robot (toward bottom left of the following photo)

alt text

Some more views of the chassis base (this version has black motors):

alt text

alt text

Attach the Camera

With the top panel in hand—that’s the other big piece in the Shadow Chassis kit—loop one of the Hook and Loop Fastening Cable Ties Velcro ties through the two oblong cut-outs positioned between the wheel mounts:

alt text

alt text

Next, place the top panel (shiny side down) in front of you. Cut a piece of two-sided tape or mounting tape, approximately half the length of the bottom side of the camera clip (or full length, it’s up to you) and attach to the camera clip, like so:

alt text

Then flip the camera over and fasten it to the rough side of the top panel. Use the Velcro tie to wrap the camera’s USB cable:

alt text

Make sure the front “lip” of the camera clip is flush with the edge of the top panel, and that the camera lens itself is centered:

alt text

Cut another piece of double sided tape and attach to one side of the USB battery:

alt text

Remove the adhesive paper from the other side of the tape, and place the battery on the top panel:

alt text

Attach the Breadboard

Now for a shocking twist: set the top assembly aside and grab the bottom assembly and then carefully remove the adhesive strip paper from the breadboard (we’re going to reuse it) and place the breadboard over the hole in the front section of the bottom panel. (As it turns out, most people never remove this adhesive cover strip!).

alt text

Turn the bottom assembly over and press the paper backing onto the adhesive surface that’s exposed through the hole. Turns out they are the same size! Using a sharp utility knife, trim off the excess paper.

alt text

Once trimmed, the underside of the chassis base should like this:

alt text

Wire the Motor Driver Circuit

Turn the bottom assembly right-side-up and insert the Motor Driver breakout onto the breadboard, as shown here:

alt text

Wire in the Motor Driver, by following the diagram here:

alt text

Start by making the breadboard connections (we’ll connect to the Tessel 2 in a few moments). As you assemble, your work should look similar to following image:

motor driver circuit on breadboard

Connecting the Tessel 2

Position the Tessel 2 near the rear of the robot on the bottom panel and complete the connections for the motor driver.

alt text

alt text

To help you verify your wiring, review the following tables:

MotorWire Driver Pin
LeftBlackAO1
LeftRedAO2
RightBlackBO2
RightRedBO1

MotorTessel PinDriver PinColor In Diagram
LeftPort A, Pin 5PWMABlue
LeftPort A, Pin 4AIN2Green
LeftPort A, Pin 3AIN1Yellow
RightPort B, Pin 5PWMBBlue
RightPort B, Pin 4BIN2Green
RightPort B, Pin 3BIN1Yellow

The SparkFun Motor Driver Breakout, view of reverse side

Above: the pins of the SparkFun Motor Driver Breakout board. Note that this view is of the bottom of the board. As attached to your breadboard, connections will be flipped left-to-right.

Prepping and Testing the Robot

Before you secure all of your connections and put the top on your robot, put the chassis aside for a few minutes, and install the robot’s software. You’ll want to test to make sure your motors run in the expected directions before putting it all together. Trust us. We speak from experience.

Installing the Robot’s Software

Get the Software

If you have git installed and feel comfortable using that tool, open your terminal and run:

git clone https://github.com/bocoup/j5ik-reconbot-tessel-edition.git;
cd j5ik-reconbot-tessel-edition;
npm install;

If git is not your thing, you can also download the project as a zip file:

Reconbot Project Folder

You can always find the most up to date content at in the GitHub repository as well.

Extract the contents however you prefer, then open your terminal and navigate to the extracted project directory.

Install the Software

From your project directory, run:

npm install;

…And that should do it! Go ahead and open the project directory in your preferred editor, and familiarize yourself with the location of each file. The structure should look something like this:

language:console
.
├── app
│   ├── index.html
│   ├── pep.js
├── lib
│   └── rover.js
├── node_modules
│   ├── express
│   ├── johnny-five
│   ├── socket.io
│   └── tessel-io
├── index.js
├── install.js
├── package.json
└── video.sh
Installing mjpg-streamer on the Tessel

Next, install needed video software on your Tessel.

To support one of the most important components of this project—an efficient video stream over a Wireless LAN connection—you’ll need to install mjpg_streamer. To do that, you could SSH to the board and manually install it by using opkg (Open PacKaGe Management, a package manager for embedded Linux)—but instead you’ll use another JavaScript program! Yay!

In the project’s directory, there’s a script called install.js—this contains our installation operations. Feel free to open and read the contents of that file if you’re curious how it works. You can type—or copy and paste—the following command into your terminal:

t2 run install.js

Hit enter and let the script run to completion. The result should look similar to the following:

alt text

Testing the Motors

Now’s the time to make any needed adjustments to the motor driver circuit. Double-check the “Pre-Flight Check” above to make sure your Tessel is prepped and powered. You may want to use the (USB micro) wall adapter to power the motors during this step.

Warning: Be ready for motion! Lift your robot off of the ground before executing `motors.js`—motors are going to spin! Remember, the breadboard end of the robot chassis is the front of the robot (helpful for determining which direction the motors should be rotating).

With your Tessel and robot chassis base ready and off the ground, type—or copy and paste—the following command in your terminal:

t2 run motors.js

This script will cause the robot’s motors to run alternately forward and backward, accelerating from slow to top speed. A console log message will let you know which way the motors should be turning at any given time.

Troubleshooting Motor Connections

Don’t freak out if one (or both) of your motors is spinning in the wrong direction. If your left motor is spinning the wrong way, swap the red and black connections on the motor driver’s A01 and A02 pins. If the right motor is misbehaving, swap the red and black connections on B01 and B02.

If your script crashes suddenly or your Tessel becomes unresponsive, double-check to make sure that you are providing the motors with enough power—remember, the Tessel’s USB connection to your computer cannot provide enough current. You’ll need to use the DC adapter or a standalone USB power bank.

Finishing the Robot's Construction

Onward! Secure the Tessel 2 to the lower chassis with wire ties, and use a piece of scotch tape across the pin headers on the Tessel 2 to hold the wires in place so they don’t jiggle out of place when the robot is roving. Connect the USB camera to either of the USB host inputs:

alt text

Align the top assembly over the bottom assembly and snap it into place. The camera should be on the breadboard end of the chassis.

alt text

Give your assembled Reconbot: Tessel 2 Edition a turn and admire your handiwork:

alt text

alt text

alt text

Nice looking robot, eh?

Running the Robot

Warning: Be ready for motion! Pick your bot up off the ground when you run this so it doesn't roll away unexpectedly.

Now all you need to do is run:

t2 run index.js

Once the program is started, the console should print out an IP address that you can open in your web browser

alt text

Visit that IP address in a web browser on the same WiFi network, and you should see streaming video from your robot and be able to control it using the thumb joystick!

If you’re curious about how the robot actually works, read on!

How the Robot Works

The software for this project is similar in structure to the software in the Johnny-Five Inventors Kit Guide Experiment 10: Using the BME280—if you haven’t read that guide, we suggest doing so now and working through that experiment. That will help to familiarize you with how we will be using Web Sockets in the robot’s application.

The robot’s code is composed of two main “chunks”:

  1. Client code. This code runs inside a web browser (on your laptop or phone, e.g.) and consists of an HTML page and some JavaScript. The client code is responsible for displaying the robot’s streaming video, as well as the display and behavior of the steering controls. The HTML and JavaScript that make up the client code are delivered to your web browser by the server code when you connect to the Tessel. The client code is contained within the app/ directory of the project.
  2. Server code. This Node.js application code runs on the Tessel when you execute t2 run index.js. The server code creates a web server to respond to requests from web browsers. It starts a process that streams video from the webcam and makes it available for browsers that connect. It also takes incoming steering data from the browser-based controls and translates it into speed and direction of the robot’s motors (wheels).

How the Web Interface Works (The Client Code)

The client code—which executes in your browser—is responsible for rendering the controls, showing the streaming video and sending steering and speed instructions to the server.

The client application’s user interface is a single HTML file (app/index.html). The important parts of this file are:

  • An <img> element to display the mjpg-streamer“video stream”. This img is sized so that the video stream fills the browser’s viewport.
  • A <canvas> element to display the touch-driven virtual thumb-stick.
  • JavaScript (inline in a <script> tag) to draw the shapes of the controls into the canvas, capture and process interaction events (e.g. touch) and send socket messages containing axis value payloads to the server application.

How Steering Works

The virtual thumbstick is designed in a way that hearkens back to traditional radio-controlled (RC) transmitters. Take a look at a “real” RC transmitter control:

And our version:

Interacting with the thumbstick causes a message to be sent over the connected socket to the server. This message contains an object representing a point { x, y } for the coordinates (relative to the thumbstick) last touched. Values for both x (left-right) and y (up-down) axes are between -100 and 100.

        (X, Y)

-100,   0,100    100,
100              100
  \       |       /
   \      |      /
    \     |     /
     \    |    /
      \   |   /
       \  |  /
        \ | /
         \|/
-100,-----+-------100,
  0      /|\       0
        / | \
       /  |  \
      /   |   \
     /    |    \
    /     |     \
   /      |      \
  /       |       \
-100,   0,-100   100,
-100            -100

On the server, this point object is used to compute an angle, which is then used to find a “turn coefficient”, which is then used to calculate how much “turn” to apply to the motors. Yay, trigonometry!

How the Server Code Works

The code that runs on your Tessel is a Node.js application. It:

  • hosts an HTTP server. This is what will serve the HTML page and the streaming video you’ll see in your browser when you connect to the Tessel. Using the built-in module http, as well as the popular third-party web framework module express, the server code serves static content (HTML and JavaScript) as well as routing requests for /video to support the streaming video.
  • hosts a web socket. Remember, the virtual thumbstick in the browser will be sending data messages about its position to the server so that the robot’s direction and speed can be controlled. The code combines uses the socket.io module to pull this off.
  • controls the robot hardware itself. As the server receives axis data on the web socket, it passes these values along to an update(...) method on an object that is controlling the robot itself (an instance of a class called Rover.

Let’s take a look at the supporting cast—a script that fires up a video-streaming process and a class (Rover) for controlling the robot’s movements.

How the Video is Streamed

video.sh is a one-line shell script for running mjpg-streamer—it starts the streaming video and makes it available at port 8080 on the Tessel.

How the Robot Controls its Motors

lib/rover.js contains a class called Rover, which encapsulates the logic for actually moving the two-wheeled robot around. Most of Rover’s functionality is within a method called update(...). update(...) takes in axis information (direction and speed information from the controller) and converts that into the right kind of motor motion.

There’s a bunch of trigonometry in update(...) and we don’t want to make you glaze over completely (though, by all means, explore the source code if you’re curious!). It does the heavy lifting of calculating and converting angles, computing “move” and “turn” values, scaling values to the correct speed and updating the motors.

How it all Fits Together

index.js is the script that pulls it all together. It uses video.sh and the Rover class and handles setting up a web server, a web application and a web socket. This is the script you’ll run on the Tessel using t2 run (or t2 push). Here is the script in its entirety (and then we’ll break it down):

language:javascript"use strict";

// Built-in Dependencies
const cp = require("child_process");
const Server = require("http").Server;
const os = require("os");
const path = require("path");

// Third Party Dependencies
const Express = require("express");
const five = require("johnny-five");
const Socket = require("socket.io");
const Tessel = require("tessel-io");

// Internal/Application Dependencies
const Rover = require("./lib/rover");

// Build an absolute path to video.sh
// Set permissions and spawn the video stream
const video = path.join(__dirname, "video.sh");
cp.exec(`chmod +x ${video}`, (error) => {
  if (error) {
     console.log(`Error setting permissions: ${error.toString()}`);
     return;
  }
  cp.spawn(video);
});

// Application, Server and Socket
const app = Express();
const server = new Server(app);
const socket = new Socket(server);

// Configure express application server:
app.use(express.static(path.join(__dirname, "app")));
app.get("/video", (request, response) => {
  response.redirect(`http://${request.hostname}:8080/?action=stream`);
});

// Start the HTTP Server
const port = 80;
const listen = new Promise(resolve => {
  server.listen(port, resolve);
});

// Initialize the Board
const board = new five.Board({
  sigint: false,
  repl: false,
  io: new Tessel()
});

board.on("ready", () => {
  const rover = new Rover([
    // Left Motor
    { pwm: "a5", dir: "a4", cdir: "a3" },
    // Right Motor
    { pwm: "b5", dir: "b4", cdir: "b3" },
  ]);

  console.log("Reconbot(T2): Initialized");
  socket.on("connection", connection => {
    console.log("Reconbot(T2): Controller Connected");
    connection.on("remote-control", data => {
      rover.update(data.axis);
     });
  });

  listen.then(() => {
    console.log(`http://${os.hostname()}.local`);
    console.log(`http://${os.networkInterfaces().wlan0[0].address}`);

    process.on("SIGINT", () => {
      server.close();
      process.exit();
    });
  });
});
Breaking down index.js

The very first thing we encounter is a Use Strict Directive—this informs the JavaScript engine that this code conforms to a safe subset of JavaScript. It will also appear at the beginning of the lib/rover.js:

language:javascript"use strict";
Getting our Dependencies in Order

This is the program’s “setup” stage, and we need to organize and require all of the application’s dependencies: built-in node modules, third-party packages and our own modules:

language:javascript
// Built-in Dependencies
const cp = require("child_process");
const Server = require("http").Server;
const os = require("os");
const path = require("path");

// Third Party Dependencies
const Express = require("express");
const five = require("johnny-five");
const Socket = require("socket.io");
const Tessel = require("tessel-io");

// Internal/Application Dependencies
const Rover = require("./lib/rover");
Starting up the Streaming Video

Before the program tries to spawn (execute) a process for streaming video, it makes sure the video script itself (video.sh) is executable by adjusting the file’s permissions with the Unix chmod command. Sometimes when files get moved around between systems, these file permissions can change unexpectedly—we want to make sure that video script is executable. Once that’s taken care of, the video process is spawned.

language:javascript
// Build an absolute path to video.sh
// Set permissions and spawn the video stream
const video = path.join(__dirname, "video.sh");
cp.exec(`chmod +x ${video}`, (error) => {
  if (error) {
    console.log(`Error setting permissions: ${error.toString()}`);
    return;
  }
  cp.spawn(video);
});
Starting the Web Server and Web Socket

We’ll be using a web application framework called Express to provide the logic necessary to support what our web server does:

language:javascript
const app = Express();

We’ll need a web server (via Node’s built-in http module) to handle delegating incoming requests to our application:

language:javascript
const server = new Server(app);

And a web socket hosted by that http server:

language:javascript
const socket = new Socket(server);

Most of what our web application needs to deliver is static content: an HTML document, specifically. For that, we can use Express' static“middleware”. Long story short, the following makes it so clients (i.e. browsers) can request and successfully receive files that live under the app/ directory:

language:javascript
app.use(Express.static(path.join(__dirname, "app")));

But the app does need to do one fancy thing. When the browser requests /video, our app redirects it to the specific URL where the streaming video was made available by video.sh:

language:javascript
// Configure express application server:
app.use(Express.static(path.join(__dirname, "app")));
app.get("/video", (request, response) => {
  response.redirect(`http://${request.hostname}:8080/?action=stream`);
});

Finally, we’ll fire up the web server so it’s listening on port 80 (default HTTP port):

language:javascript
// Start the HTTP Server
const port = 80;
const listen = new Promise(resolve => {
  server.listen(port, resolve);
});
Initializing the Tessel Board

Note: If this is your first exposure to using the Johnny-Five Board class to represent the state of the Tessel 2’s board, we recommend you read (at the least) Experiment 1: Blink an LED for a little background.

This Board instantiation looks a little different from other Johnny-Five Tessel examples. We’re explicitly disabling the automatic REPL (interactive console). We also tell the board not to respond in its default way to SIGINT events. SIGINT is a signal sent by Unix-based systems when a process is interrupted, like when you type ctrl-C after using the t2 run command. We’ll shortly define how we do want the robot to respond if the process is interrupted.

language:javascript
// Initialize the Board
const board = new five.Board({
  sigint: false,
  repl: false,
  io: new Tessel()
});

When the board emits the ready event, the Tessel 2’s hardware is ready for interaction.

language:javascript
board.on("ready", () => {
  // ... Let's go!
});
Creating the Rover Object

Within the "ready" event handler, we can be confident that the Tessel hardware is ready to go. The next step is to instantiate an object of the Rover. When we instantiate a Rover, we need to give it some information about the motors attached to the board. Each motor has three relevant pin connections: pwm (pulse-width modulation), dir (direction) and cdir (counter-direction). You can read more about this in the documentation for Johnny-Five’s Motor class. The pin numbers correspond to how the pins on the motor driver are connected to the Tessel.

language:javascript
const rover = new Rover([
  // Left Motor
  { pwm: "a5", dir: "a4", cdir: "a3" },
  // Right Motor
  { pwm: "b5", dir: "b4", cdir: "b3" },
]);

Phew! Now the robot is ready to rock. A message is logged that says “Reconbot(T2): Initialized”:

language:javascript
console.log("Reconbot(T2): Initialized");
Handling socket connection events

When you open the robot’s controlling web page in a browser, it will trigger a "connection" event on the web socket. The "connection" handler logs a message confirming the connection and sets up an event handler for "remote-control" events. Remote control events are fired when new axis data is sent from the thumbstick controls. This axis data gets passed on to the rover.

language:javascript
socket.on("connection", connection => {
  console.log("Reconbot(T2): Controller Connected");
  connection.on("remote-control", data => {
    rover.update(data.axis);
  });
});

That’s it for hardware interaction control! The next few lines helpfully show the URL for your robot’s controlling web page. Remember how we turned off default SIGINT handling? Here’s where we circle back and define how we do want SIGINT events to be handled—making sure to close the web server before exiting the process.

language:javascript
listen.then(() => {
  console.log(`http://${os.hostname()}.local`);
  console.log(`http://${os.networkInterfaces().wlan0[0].address}`);
  process.on("SIGINT", () => {
    server.close();
    process.exit();
  });
});

Deployment And Operation of the Robot

It’s time to deploy and run the software on our robot—which also means it’s time to drive!

Whenever you’re ready, go ahead and type—or copy and paste—the following command into your terminal:

t2 run index.js

Once the program is deployed and started, you will see the URL of the controller application displayed:

alt text

Go ahead and open that URL in a browser on your mobile device or laptop. If your friend is positioned directly in front of the bot, you might see something like this:

alt text

Note: The left and right arrows located in the upper corners will swap the virtual thumb stick from one side of the screen to other.

While they will see this:

alt text

Resources and Going Further

For some extra fun, you could implement the following.

  • Instead of relying on an existing Wireless LAN, use the Tessel 2’s built-in Access Point support. Remember that your control device will have to connect to the Tessel 2’s Access Point network in order to access the controller application in the browser.
  • Deploy your software to the Tessel 2’s flash memory with the following command:

t2 push index.js

this way your program will be automatically started when the Tessel 2 boots.

You can find all the files for the Reconbot at the GitHub repository.

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!
New!

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

Sunrise Machine with the Tessel 2

$
0
0

Sunrise Machine with the Tessel 2 a learn.sparkfun.com tutorial

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

Introduction

Some time ago, I began to have a hankering to be able to automatically photograph or film the sunrise wherever I may happen to be. I liked the idea of a little machine that could determine when the sun would rise in my location and take some time lapse images of it. Thus was born the idea of a Sunrise Machine.

The Sunrise Machine can, based on your latitude and longitude, automatically record the sunrise at your location using a basic USB webcam. It captures still images over time and creates time-lapse movies from them in MPEG-4 and animated-GIF formats. If you choose, it can also tweet those resulting GIFs on your behalf. You can configure it to record different day-sun events—sunset, solar noon, the start of the golden hour, even nautical twilight. You don’t have to tweet the results, if that’s not your thing, and you can always create a manual time-lapse video at any time by pressing a button. All still images and videos are stored for you on a USB thumb drive.

The Sunrise Machine

I built an enclosure for my Sunrise Machine out of an old book. However, you can put yours in whatever you like, or not bother with an enclosure at all.

The Sunrise Machine open

Preflight Check

If this is your first time experimenting with the Tessel 2, there are a few things you should be familiar with first! We recommend reading through our Getting Started with the Tessel 2 guide before diving into this project.

New!

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.

Dive Deeper into the Tessel 2

The entire Johnny-Five Inventor’s Kit Experiment Guide is full of great information if you’re starting out with the Tessel 2. Pertinent experiments for this tutorial include Experiment 4: Reading a Push Button and Experiment 8: Driving an RGB LED.

Experiment Guide for the Johnny-Five Inventor's Kit

June 28, 2016

Use the Tessel 2 and the Johnny Five Inventors kit to explore the world of JavaScript enabled hardware through 14 awesome experiments!

Materials

The Johnny-Five Inventor’s Kit includes most of the electronic components you need to build the Sunrise Machine.

Johnny-Five Inventor's Kit

KIT-13847
$124.95
6

In addition to the items in the kit, you’ll need a USB camera, such as the Creative Live! Cam Chat HD (Amazon), and a USB thumb drive.

If you do not have a Johnny-Five Inventor’s Kit or would rather purchase the parts you’ll need for this project separately, you can do so using the lists below:

Addition Supplies

Setup

Twitter Logo

If you’d like your Sunrise Machine to be able to tweet, you’ll need to obtain Twitter API credentials. You’ll have to fill out a little form, but the use of the API is free. Once you’re signed up, you’ll have access to an API/developer dashboard. You’ll need to find the following four things to make your Sunrise Machine talk to Twitter:

  • Consumer Key
  • Consumer Secret
  • Access Token (Key)
  • Access Token (Secret)

Access Token (Key) and Access Token (Secret) may need to be generated (you just to have to click a button to do it). Each of the four credentials are long strings. Copy and paste them somewhere safe.

For my Sunrise Machine, I created an entirely new Twitter user, but you can use your main Twitter account if you prefer. Or, if Twitter isn’t your thing, you can disable it completely with a configuration value (more on that soon).

Webcams and Calibration

In the course of building the Sunrise Machine, I discovered that some webcams require a period of “warmup” before capturing stills so that they can calibrate the correct exposure. This usually takes 2-3 seconds. Without calibration “warmup”, images taken of bright scenes—like outside—would result in all-white images. Yikes! The Sunrise Machine’s software can automatically calibrate your webcam before capturing images to help you get the best images possible. You can disable this feature if you like (see the configuration section below).

USB and the Tessel

Working with a USB thumb drive and USB camera on a Tessel is eerily easy.

For the thumb drive: make sure it is formatted as Fat32 or something similar (MS-DOS FAT, ExFat—not Mac OS Extended). The Sunrise Machine will write files (images, movies and GIFs) directly to your thumb drive. If you’re curious, a mounted USB thumb drive can be accessed at /mnt/sda1 on the Tessel’s file system. Use the t2 root command if you want to ssh in to your Tessel and have a look around the filesystem—the Tessel 2 runs OpenWRT Linux.

Similarly, plugging in a USB webcam to a Tessel makes the device available at /dev/video0.

The Tessel and Time

The Tessel 2 isn’t an independent timekeeper. Once the Tessel has power and its OpenWRT Linux boots, it will attempt to connect to an NTP (Network Time Protocol) server to obtain the current time. There are a couple of things to note about this. One, dates and times on the Tessel are UTC times—it doesn’t know about your local timezone. Second, the Tessel can’t tell what time it is at all if it does not have a network connection (i.e. if it’s only tethered to your computer over USB but is not connected to your LAN).

The command t2 list will show you all nearby Tessels and how they are connected, e.g. for my Tessel, which I’ve named ichabod after a local early settler of my town named, improbably, Ichabod Onion:

$ t2 list INFO Searching for nearby Tessels... USB ichabod LAN ichabod

ichabod is, in this case, connected both to my USB port and my local WiFi network. Good. It’ll know what time it is. In UTC, at least.

Build It

Now you’re ready to put your Sunrise Machine’s components together.

alt text

  1. Plug in a USB thumb drive to one of the Tessel 2’s USB ports.
  2. Plug in a USB webcam to the other USB port on the Tessel 2.
  3. Wire up the circuit containing a pushbutton and an RGB LED as shown in the wiring diagram.

Program It

Get the Software

If you have git installed and feel comfortable using that tool, open your terminal and run:

git clone https://github.com/bocoup/j5ik-sunrise-machine;
cd j5ik-sunrise machine;
npm install;

If git is not your thing, you can also download the project as a zip file:

Sunrise Machine Project Folder

You can always find the most up to date content at in the GitHub repository as well.

Extract the contents however you prefer. Open your terminal, and navigate to the extracted project directory.

Install the Software

First, install some dependencies. In your project directory, run the command:

npm install

Configuration: config.js

The only code changes you’ll need to make from the supplied code with the Sunrise Machine are in its configuration. Copy the included config.js.example file to a new file named config.js:

language:javascript
module.exports = {
  lat                : 43.34, // Your latitude (This is Vermont)
  long               : -72.64, // Your longitude (This is Vermont)
  utcOffset          : '-04:00', // Your timezone relative to UTC
  autoSchedule       : 'sunrise', // Any property from `suncalc` or `false` to disable
  postToTwitter      : true, // `true` will create posts of GIFs
  tweetBody          : 'It is a beautiful day!', // Text tweeted with GIFs
  consumer_key       : '', // Twitter
  consumer_secret    : '', // Twitter
  access_token_key   : '', // Twitter
  access_token_secret: '', // Twitter
  captureFrequency   : 30, // in seconds (default one image every 30s)
  captureCount       : 20, // number of stills per montage
  calibrateCamera    : 3, // length of camera calibration (default 3s)
  statusLED          : true, // Enable RGB status LED? false will turn it off
  basedir            : '/mnt/sda1/captures', // where files get stored
  dateFormat         : 'ddd MMM DD, YYYY HH:mm:ss',
};

This configuration object is organized such that the properties you’re most likely to change are near the top.

  • You’ll want to change, at the very least, the lat and long values to the coordinates of where you are located.
  • To account for the Tessel 2’s proclivity for UTC, you can provide a utcOffset value. -04:00 is the offset for daylight savings time on the east coast of the U.S. (EDT)—four hours “behind” UTC. This setting isn’t critical—the dates used by the Tessel to figure out to record will still be accurate, but if you want logging and folder names for your images and movies to use your local time zone (i.e. not UTC), change this value.
  • autoSchedule can be set to any of suncalc’s sun event names, or can be set to false to disable scheduled recording (you can always trigger manual movies by pressing the Sunrise Machine’s pushbutton).
  • If you enable postToTwitter, you’ll need to fill in the Twitter API credentials that follow.
  • I encourage you to experiment with the value of calibrateCamera. If you find that your camera is taking great stills without calibration, you can save power and time by disabling calibration (set this property to 0 or false to turn it off).
  • You can disable the statusLED if you like. This can save power and your nerves if you find the light or blinking annoying (or it is reflecting off a window during capture or something).

At this point, your Sunrise Machine is configured and ready. If you’re in a hurry, you can skip to the Run It! section.

Exploring the Code

When the Sunrise Machine’s code is complete, your project directory will look like this:

language:console
├── av.js
├── config.js
├── node_modules
├── recording.js
├── index.js
└── tweet.js

config.js is the configuration file you just created. node_modules is where the project’s dependencies—installed above—live.

The other components of the Sunrise Machine are:

  • tweet.js, which integrates with the Twitter API and can upload animated GIFs
  • recording.js, which provides a class that encapsulates the tasks of a time-lapse recording session (scheduling still capture, kicking off the processing of stills into movies, etc.)
  • av.js, which contains lower-level code to execute the capture and processing of images and video
  • index.js, which is the code that controls the Tessel’s inputs and outputs and pulls it all together. This is the script you’ll run on your Tessel.

We encourage you to dig into the module files and see how the pieces all fit together, if you’re curious!

Capturing and Processing Video with the Tessel 2: av.js

The image capture, video building and animated-GIF creating powers of the Sunrise Machine are significantly influenced by the existing tessel-av module, which is a great starting place for grabbing still images or streaming video. Like tessel-av, the Sunrise Machine’s image-capture code takes advantage of the cross-platform ffmpeg software, which is available for you already on your Tessel. No installation or configuration needed!

ffmpeg is a hugely-powerful command-line tool that can encode and decode (and transcode and mux and demux and stream and filter and play and and and) a dizzying array of different kinds of audio and video. Just learning how to put together commands to do simple video capture and storage can take a while (trust me).

Keep in mind that the Tessel 2 is able to do all this despite its mere 64MB of RAM. It’s quite a trooper.

av.js spawns ffmpeg processes using Node.js' built-in child_process module. The av module contains an appropriately-titled ffmpeg function. The ffmpeg function spawns an ffmpeg child process with the arguments provided and returns a Promise:

language:javascript
function ffmpeg (opts) {
  opts.unshift('-v', 'fatal'); // Comment this line to see ffmpeg logging
  const ffmpegProcess = cp.spawn('ffmpeg', opts);
  return new Promise((resolve, reject) => {
    ffmpegProcess.on('exit', code => {
      if (code != 0) {
        console.error(code);
        reject(code);
      } else {
        resolve();
      }
    });
    ffmpegProcess.stderr.on('data', data => {
      console.log(data.toString()); // Logging when not suppressed
    });
  });
}

Each of the four exported functions (calibrate, captureStill, videoFromStills and animatedGIFFromVideo) are intended to fulfill one AV task by invoking the ffmpeg function with the needed arguments. These functions also return a Promise. Here’s a condensed view of the rest of the av.js module:

language:javascript
// "Calibrate" a camera for `duration` seconds by letting it output to /dev/null
module.exports.calibrate = function (duration) {
  const videoArgs = [ /* ffmpeg arguments needed to calibrate camera */ ];
  return ffmpeg(videoArgs).then(() => '/dev/null');
};

// Capture a single still image at 320x240 from the attached USB camera
module.exports.captureStill = function (filepath) {
  const captureArgs = [ /* ffmpeg arguments needed to capture a still */];
  return ffmpeg(captureArgs).then(() => filepath);
};

// Build an MP4 video from a collection of JPGs indicated by `glob`
module.exports.videoFromStills = function (glob, outfile) {
  const stillArgs = [ /* ffmpeg arguments needed to create a video from stills */];
  return ffmpeg(stillArgs).then(() => outfile);
};

// Create an animated GIF from an MP4 video. First, generate a palette.
module.exports.animatedGIFFromVideo = function (videofile, outfile) {
  const paletteFile = '/tmp/palette.png';
  const paletteArgs = [ /* arguments needed to create a color palette */ ];
  return ffmpeg(paletteArgs).then(() => {
    const gifArgs = [ /* arguments needed to create an animated GIF */ ];
    return ffmpeg(gifArgs).then(() => outfile);
  });
};

Arguments are cobbled together in each function. Here’s the entirety of the captureStill function, for instance:

language:javascript
// Capture a single still image at 320x240 from the attached USB camera
module.exports.captureStill = function (filepath) {
  const captureArgs = [
    '-y', // Overwrite
    '-s', '320x240', // maximum resolution the Tessel 2's memory can handle
    '-r', '15', // Framerate
    '-i', '/dev/video0', // Mount location of video camera
    '-q:v', '2', // Quality (1 - 31, 1 is highest)
    '-vframes', '1', // Total number of frames in the "video"
    filepath
  ];
  return ffmpeg(captureArgs).then(() => filepath);
};

Note that the animatedGIFFromVideo function is a two-step process that first creates a palette from a movie and subsequently creates an animated GIF from the movie based on that palette. GIFs are restricted to 256 colors, so using an intelligently-generated palette can result in a higher-quality GIF.

Tweeting Animated GIFS: tweet.js

tweet.js uses the twitternpm package to communicate with the Twitter API, making the several API calls necessary to upload an animated GIF. Once the GIF is uploaded, it posts a tweet containing the GIF. It exports a function, tweetGIFindex.js can call this function to tweet a GIF.

Taking Care of Details: recording.js

The JavaScript class exported by recording.js, Recording, encapsulates some of the tasks of managing a time-lapse recording session, like naming of files and managing timeouts between captures. A Recording instance can be started with its start method and canceled with its cancel method. The Recording handles the rest, invoking specific functions in the av module to accomplish tasks like calibration, capturing stills and building movies and GIFs.

Where it all Happens: index.js

We’ve met the supporting cast. Now let’s walk through, in entirety, index.js, which is the script you’ll run directly on your Tessel to make the Sunrise Machine go! Here it is, with lots of comments.

language:javascript
/* require external dependencies */
const five      = require('johnny-five'); // Johnny-Five!
const Tessel    = require('tessel-io'); // J5 I/O plugin for Tessel boards
const suncalc   = require('suncalc'); // For calculating sunrise/set, etc., times
const Moment    = require('moment'); // For wrangling Dates because otherwise ugh
// Require other modules from sunriseMachine's code:
const config    = require('./config');
const Recording = require('./recording');
const tweetGIF  = require('./tweet');

// Instantiate a new `Board` object for the Tessel
const board = new five.Board({
  io: new Tessel() // Use the Tessel-IO plugin
});

// Instantiate some variables for later
var currentRecording, scheduled;

board.on('ready', () => { // Here we go. The board is ready. Let's go!
  // Instantiate J5 component objects: a pushbutton and RGB status LED
  const button    = new five.Button('A2');
  const statusLED = new five.Led.RGB(['A5', 'A6', 'B5']);
  // When the button is `press`ed, invoke the `toggle` function
  button.on('press', toggle);
  // Put the sunrise machine in standby mode
  standBy();

  // Put the sunrise machine in standby. Schedule the next recording if needed
  function standBy () {
    currentRecording      = null;       // There is no active recording. Explicitly.
    const scheduleDetails = schedule(); // See if there is a recording to schedule
    // If there is a scheduled recording, `scheduled` will be a Node Timeout object
    // if `scheduled` is falsey, there is nothing scheduled, so put the SM in regular standby
    const nextStatus      = (scheduled) ? 'scheduled' : 'standby';
    // Set the sunrise machine's status and log any message returned by
    // the schedule function
    setStatus(nextStatus, scheduleDetails);
  }

  // button `press` callback. Start a manual recording, or cancel an in-progress recording
  function toggle () {
    if (currentRecording) { // if currentRecording is truthy, there is an in-progress recording
      currentRecording.cancel(); // so, cancel it
    } else { // otherwise, start a new recording
      record('Manual recording');
    }
  }

  function schedule () { // Schedule to record next autoSchedule event
    if (!config.autoSchedule) { // auto-scheduling is disabled in config
      return 'Nothing to schedule! Sunrise machine in manual mode';
    }
    const eventName    = config.autoSchedule;
    const now          = Moment();
    // Using noon explicitly when querying about sun events adds a level
    // of safety; using times near the start or end of the day can kick up
    // some unexpected results sometimes.
    const noonToday    = Moment().hour(12).minute(0);
    const noonTomorrow = Moment().add(1, 'days').hour(12).minute(0);

    // Ask `suncalc` for the times of various sun events today, at the
    // lat/long defined in the config
    var sunEvents = suncalc.getTimes(noonToday.valueOf(),
      config.lat, config.long);
    var eventDate, delta;

    if (!sunEvents.hasOwnProperty(eventName)) { // Invalid value for config.autoSchedule
      return `Not scheduling: ${eventName} is not a known suncalc event`;
    }

    if (sunEvents[eventName].getTime() < now.valueOf()) {
      // The event has already happened for today. Check when tomorrow's is...
      sunEvents = suncalc.getTimes(noonTomorrow.valueOf(),
        config.lat, config.long);
    }

    // Using the config.utcOffset value to bring the date into local timezone
    // Note that the actual date underneath is not changing, just its representation
    eventDate = Moment(sunEvents[eventName]).utcOffset(config.utcOffset);
    // How long is the event from now, in milliseconds?
    delta = eventDate - now;
    if (!scheduled) { // Don't reschedule if already scheduled
      // Schedule the recording by setting a timeout for the number of milliseconds
      // until the event
      scheduled = setTimeout(() => {
        record(`Automatic ${eventName} recording`); // Kick off a recording
        scheduled = null; // Unset scheduled because we're done here
      }, delta);
    }
    return `Scheduled for ${eventName}: ${eventDate.format(config.dateFormat)}`;
  }

  // Kick off a time-lapse recording!
  function record (name) {
    if (currentRecording) {
      log('Another recording session already in progress');
      return false;
    }
    // Create a new Recording object to do some heavy lifting for us
    const recording = new Recording(name, config);
    // Bind to a bunch of events on the Recording. Several of these update
    // the SM's status and/or log a message:
    recording.once('start', () => {
      setStatus('recording', `${recording.name} starting`);
    });
    recording.on('calibrate', () => setStatus('calibrating'));
    recording.on('capture:start', () => setStatus('capturing'));
    recording.once('cancel', () => log(`${recording.name} canceled`));

    // When one of the stills in a session is successfully captured, take note!
    recording.on('capture:done',  (filepath, images, totalnum) => {
      setStatus('recording',
        `Oh, snap! Captured ${images.length} of ${totalnum}`);
    });
    // When the stills are captured and the movies made, Tweet the result
    // if config indicates it should be done
    recording.once('done', videoFile => {
      if (config.postToTwitter) {
        tweetGIF(config, videoFile, config.tweetBody);
      }
      log(`${recording.name} complete`);
    });
    // Once the Recording exits, put the SM back in standby (this will
    // cause the next recording to get scheduled, if needed)
    recording.once('exit', standBy);

    // Start the recording!
    recording.start();

    // Reference this Recording as the SM's currentRecording
    currentRecording = recording;
    return recording;
  }

  // Indicate the sunrise machine's "status" by changing the state of the
  // RGB LED and optionally logging a message
  function setStatus (status, msg) {
    if (!config.statusLED) return; // Leave it alone if it's not enabled
    statusLED.stop().on(); // Stop any blinking that may be going on
    switch (status) {
      case 'standby':
        statusLED.color('blue');
        break;
      case 'scheduled':
        statusLED.color('green');
        break;
      case 'recording':
        statusLED.color('yellow');
        break;
      case 'calibrating':
        statusLED.color('orange').blink(500);
        break;
      case 'capturing':
        statusLED.color('red').blink(250);
        break;
      default:
        // Hmmm, I don't understand this status :)
        statusLED.color('purple').blink(1000);
        break;
    }
    if (msg) {
      log(msg);
    }
  }

  // This log function could be altered to log to a file, e.g.
  function log (msg) {
    const now = Moment().utcOffset(config.utcOffset).format(config.dateFormat);
    console.log(`${now}:
      ${msg}`);
  }
});

Run it

Run the sunrise machine by using the following command:

t2 run index.js

That will deploy the index.js code and all of its needed dependencies to your Tessel.

Resources and Going Further

You can find all the files for the Reconbot at the GitHub repository.

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!
New!

ReconBot with the Tessel 2

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

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


Proto Pedal Chassis Hookup Guide

$
0
0

Proto Pedal Chassis Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The Proto Pedal chassis comes with the holes required to interface the PCB, but since different pedal designs use different types of controls, we’ve left drilling holes for the controls to the builder. This guide will take you through laying out and drilling holes, then painting the chassis.

alt text

We’ll be drilling a chassis to match the digital Proto Pedal example, which shows an application using a Teensy 3.2 and an Audio Adapter with the Proto Pedal and Proto Pedal Chassis.

Materials

Required:

  • The Proto Pedal and Chassis
  • A twist drill bit (not spade) that matches the desired hole diameter
  • A pilot drill of about 1/8 inch. Make sure it’s sharp and fresh!
  • A few drill bits between to step up to the desired size.
  • Ruler
  • Center punch (a large metal screw and hammer will work)
  • Variable speed hand drill, wired or cordless
  • Clamps, vice, holders
  • Some scrap wood blocks
  • A pencil

Also Recommended:

  • Thin circular file (needle or chain sharpening file)
  • Speed square
  • Combination square / scribe
  • Spring loaded center punch
  • Isopropyl Alcohol / Acetone
  • Paint

Recommended Reading

Laying Out The Holes

Before drilling, we need to figure out where to locate the holes.

This is an exercise in three-dimensional thinking. We need to account for the location of the controls on the panel, as well as the clearance above and below. Above the surface of the pedal, you’ll probably want to leave some room around the controls, so you can grab them. Inside the chassis, you need to consider where the internal portion of the control will be located, especially in relation to the taller components on the PCB.

Rough Layout

In this example, we wanted to put five potentiometers on the chassis. We simply moved the knobs around on top of the chassis until we reached a reasonable arrangement. Notice that we’re leaving clearance for the TRS jacks.

alt text

Laying out the knobs

We had the circuit board nearby to use as a reference, to help see where internal objects are are located. We also had the assembled stack of Teensy 3.2 and Audio Adapter nearby, which we test fit several times as we worked. This allowed us to recognize that the stack doesn’t stand much above the board, leaving vertical space to place a pot over it.

alt text

Tracing the knob outlines

With the knobs in rough proximity of their ultimate destinations, we traced them in pencil, making circles on the box.

More Precise Layout

With the knobs removed, we measured the location of their centers from the top edge of the box. We averaged the measurements, so the holes would be in reasonable alignment.

Here we’ve marking a line 2 ½ inches from the top edge, using a combination square to insure a consistent distance. If you don’t have a square, you can carefully measure two points and draw a line between them.

alt text

Setting the vertical alignment

The top row is an inch closer to the edge, at 1 ½ inches.

alt text

Do this for each row.

With the lines for the rows drawn, we’ll move on to the horizontal position of each pot within the rows.

alt text

Center your rule to a common overlap to identify center

We decided to center these knobs, so we set the ruler on the box such that the edges aligned the same number of subdivisions past the last whole inch, or a little more than ¼ inch, at 9 ¼ and 5 ¾. Now, the 8 ½ inch mark is centered horizontally and we can count subdivisions out from there to make sure the holes are equally spaced.

The top row holes were marked ½ way between the marks in the bottom row, resulting in a regular “M” shape.

Notice that the rough knob outlines are no longer accurate to the center marks. The outlines were just eye-balled on for aesthetics, while the measured marks insure accuracy.

Punching

Punch the center of each hole. This will help guide the drill bit.

If you’ve never seen a spring loaded center punch before, they’re really cool. Just press down until the internal spring is sprung, and it leaves a mark behind. You can get these at most hardware stores.

alt text

Using a spring loaded punch

Or if you don’t have a center punch, use a large screw and a hammer. Big pan heads work well, but wood deck screws or drywall screws are too pointy.

alt text

Using a screw for a punch

Now let’s get to the real action!

Drilling

When you’re happy with your center punch marks, it’s time to start drilling.

Drilling Metal

When drilling metal, it’s important to start with a small pilot hole, and work progressively up to the desired size. For these holes, they’ll be 5/16 inch for the 10k linear potentiometers. Each successive hole should be 25% to 50% larger than it’s predecessor.

alt text

This diagram shows the maximum overlap desired.

When drilling metal, use a moderately slow speed, and reasonable pressure. A drill that’s too fast can cause the bit to overheat, and is more dangerous if you lose control.

Preparation

Before drilling, solidly secure the workpiece with a vice or a clamp.

alt text

Preparing to drill

Here, three bits have been selected and the piece is clamped. You may think you can just hold the piece down with your hand, but more often than not it will wedge on the drill bit and spin around, whacking your hand and causing injury (and perhaps damaging the workpiece). Also, use scrap wood to protect the piece from marring, and to provide something soft for the drill bits to crash into when they break through.

Drilling

Start with a small pilot hole. This is the most important drill as it will guide the other holes.

alt text

Carefully align the pilot holes

A challenge with using a hand drill is maintaining perpendicularly to the work surface. As a reference, set a square on the piece and use it as a visual guide. Before you start drilling, hold the drill where you think it should go and move your head around like an owl to see that you’ve got good alignment from all angles.

When you’re ready, drill with a medium speed and decent pressure. The bit should produce a constant stream of waste material. If it seems like it’s just spinning, doublecheck you’re not in reverse, try adding more pressure, or slow the drill speed.

Double check alignment! After drilling the pilot holes, check that they are aligned as they should be. If not, you can use a thin file to make the hole oblong and bring the geometric center back in line, and the next bit should correct the offset. With sharp bits and good perpendicular alignment, this shouldn'tbe required.

After the pilot holes are complete, move up to the next larger bit, and use it to enlarge each hole. As you move to larger and larger bits, less speed should be required.

alt text

Progressing through the selected drill bits, enlarging the holes

After an intermediate hole, we can drill the final hole, 5/16 inch.

alt text

The final size is being drilled here.
The drill has been stopped partway through to show the overlap detail (lower right).

The drilled holes frequently have a sharp burr around the edge. If you like, you can bevel the edges with a chamfer tool, or clean them up with a file. It’s not required, but will get rid of the sharp edges.

alt text

Cleaning up the edges

Notes for Potentiometers

The potentiometers have an alignment / retention boss. You can either drill an extra hole to retain it, or trim it off with a pair of side cutters.

alt text

Removing the bosses.

Extra holes for the Teensy

For the Teensy based digital pedal, we’re going to add a couple extra holes. The first is one on the side of the chassis for the USB connector, plus a second smaller hole in the top of the pdeal, so we can reach the manual-load button.

As with our initial layout, we’re going to do it empirically, using the final parts to gauge where the holes need to be. We started with the USB port, measuring on the left side of the enclosure.

Programming Port

First, choose the location of the programming hole based on where you want the Teensy to be in the pedal. Use the circuit board as a guide, aligning the ¼ inch jack shoulders to the inside plane.

alt text

Using the board as a guide for hole placement

Approximate the height of the hole by holding the circuit board where it will sit when assembled, and cross the previous mark.

alt text

Aligning the height of the hole

Then, punch a center point, and move on to drilling.

We going all the way up to our largest drill, to accommodate the USB plug molding, making 4 drills overall. This time, were using a vice to hold the workpiece, again using blocks of wood to protect it.

alt text

Preparing to drill

As before, we’re working progressively up to the larger drills.

alt text

Here the pilot hole is being enlarged. I like to allow more overlap on the smaller drills.

Since this hole is larger, there will be two intermediate drills.

alt text

The second oversize closer to the first size.

Watch the quality of the waste material. It’s a good sign that speeds and pressures are correct when the waste forms into curls rather than little chips. Also, it can be seen here that the overlap is quite small for this large bit. Otherwise, the bit would have a great tendency to catch when getting close to being through.

alt text

Drilling the final USB hole.

Once the drilling is complete, we want to chamfer the edges of the hole. The chamfer is more important for this hole, because the sharp edge won’t be covered with a control. This time, the hole is as large as the bit were were chamfering with before, so we have to do it manually, with a file.

alt text

Deburring with a file

Reset Switch

We used a similar triangulation process for the hole for the button. Here, there’s a mark where it should be, but that is underneath a knob. The hole was moved outside of the knob outlines, and will have to be used at a slight angle.

alt text

Center punching the button hole

Since this hole is smaller, we didn’t need to step through as many drills.

Painting

alt text

For a finishing touch, you can paint your pedal. We’ve chosen to try out a couple Rust-Oleum oil-based enamels, which have wildly different properties based on the color, and a spray job using red Krylon Shimmer spray paint, with a clear overcoat.

alt text

Cleaning the workpiece

Start by cleaning the case with acetone or isopropyl alcohol. This removes oils and pencil marks.

alt text

Make sure to not touch clean areas!

The liquid paint was applied using a foam applicator wedge.

alt text

Use scrap wood to catch extra paint

Painting can be a messy process, and you’re likely to get some on your work surface. You can protect against paint slop with a drop cloth, or other scrap materials, such as wood, or cardboard.

alt text

Allowing to dry

You can paint the faces of the screws too, if you wish, but try not to get any into the threaded holes, or they may be difficult to drive.

Painting Results

alt text

You can see that the red paint tended to pile up and stay streaky, and needs to be sanded and coated again. This paint should probably be used with a sprayer or thinned out. The black leveled well and could be sanded to a decent finish, but the red refused to level as can be seen above. The Shimmer paint was pretty much fabulous.

Resources and Going Further

Don’t know what to put in your case? Try these!

Have fun decorating and labeling your new proto pedal, and rock on!




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

Environmental Monitoring with the Tessel 2

$
0
0

Environmental Monitoring with the Tessel 2 a learn.sparkfun.com tutorial

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

Introduction

In the world of tomorrow, everything in our homes will be connected. The Internet of Things (IoT) is the real-world manifestation of that vision. The world of IoT includes network-connected appliances that have not, until now, had any such sophisticated capabilities.

The Nest product line, which started with intuitive smart thermostats and is expanding into other products, is one set of offerings in a growing market of so-called “smart home” offerings. Amazon’s Echo, which combines several home integration aspects into a single platform, is another.

Our Own Smart Monitoring Device

There are many types of smart-home systems. Some remotely control a home device, like automatically turning lights on or off at certain times. Others optimize the behaviors of home systems, perhaps switching a home’s electrical supply between solar and grid power at different times of the day or season.

In this tutorial, we’ll hone in on the monitoring aspect of smart systems. We’re going to build an air-conditioning monitoring device to collect information and store it in the cloud.

Our monitoring device will be able to detect the following over time:

  • Whether the air conditioner is ON or OFF
  • Temperature
  • Relative humidity
  • Air pressure

Data points from the sensors in the device will be uploaded to and stored in Sparkfun’s Phant-powered data.sparkfun.com service.

Preflight Check

If this is your first time experimenting with the Tessel 2, there are a few things you gotta do first! We recommend reading through our Getting Started with the Tessel 2 before diving into this project. We promise, it wont take that long.

New!

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.

Dive Deeper into the Tessel 2

The entire Johnny-Five Inventor’s Kit Experiment Guide is great stuff if you’re starting out with the Tessel 2.

Experiment Guide for the Johnny-Five Inventor's Kit

June 28, 2016

Use the Tessel 2 and the Johnny Five Inventors kit to explore the world of JavaScript enabled hardware through 14 awesome experiments!

Getting Started with Phant(data.sparkfun.com)

If you’ve never worked with the data.sparkfun.com service before, the guide below will help you get started making your own stream for collecting data.

Pushing Data to Data.SparkFun.com

July 8, 2014

A grab bag of examples to show off the variety of routes your data can take on its way to a Data.SparkFun.com stream.

Materials

To build the monitoring device, you’ll need the following parts:

Parts to Source Elsewhere

Meet the Supporting Hardware

Non-Invasive Current Sensor

The non-invasive current sensor has a “jaw” that clamps around a wire. It can read the amount of current flowing through the wire without the wire itself having to be modified (ergo, non-invasive). By plugging the air conditioner into the extension cord and then using the current sensor to detect how much current is going through the extension cord, we’ll be able to tell when the AC is running.

The current sensor’s output is a current much lower, but linearly related to, the current it’s sensing.

Non-Invasive Current Sensor

TRRS Breakout

The non-invasive current sensor has a connector that looks like an audio jack on one end. It is a TRS (Tip-Ring-Sleeve) connector, shown on the left side of the diagram below. You may also have seen TRRS connectors (Tip-Ring-Ring-Sleeve, right side of diagram), which are commonly used for handsfree headsets. The TRRS breakout makes each of the pieces of a TRRS connector (the tip, each of the two rings and the sleeve) accessible. The TRRS breakout will allow us to easily connect to the tip and the sleeve of the current sensor’s connector so we can read its values.

TRRS

Build It

Let’s begin by assembling the environment monitoring device!

Start by plugging the BME280 into the breadboard so that it straddles the DIP support ravine (notch) that runs vertically down the middle of the breadboard. Next, connect the BME280 to the Tessel 2 with jumper wires as shown in the wiring diagram:

BME280Tessel 2
GNDGND
3.3V3.3V
SCLPort A, Pin 0
SDAPort A, Pin 1

voltage divider

Add the current sensor’s voltage divider circuit.

alt text

Here’s a closer look at the voltage divider circuit:

This voltage divider circuit “conditions” the output of the current sensor so that it is constrained to a range of input voltages that can be read by the Tessel 2 (0 - 3.3V). If you’d like to learn more about the technical details, you can read about the circuit it is based on, described in the article CT [Current Transformer] Sensors — Interfacing with an Arduino, OpenEnergyMonitor.org.

CT Circuit

The final circuit should look like this:

alt text

Next, you’ll need a sharp utility knife and a safe, clean cutting surface. On your surface, lay the Air Conditioner Extension Cord flat, and use the utility knife to separate one of the three joined sections of wire. Make the cut approximately 3 to 4 inches long—just long enough to put the current sensor’s top “jaw” through and safely clip it together.

alt text

WARNING: If you expose ANY wire during this process, immediately discard the entire extension cord and start over with an uncut cord. We recommend purchasing two of these just in case. Exposed wire will put you at risk of fire or electrocution.

Program It

Create A Cloud Data Stream

The application that we’re going to create will post data reported by the BME280 and Non-Invasive Current Sensor circuit from the Tessel to data.sparkfun.com (that’s why this application does require a connection to the internet).

Before we get started with our own program, you’ll need to create a new data stream on data.sparkfun.com so that you can send data to it from the monitoring device. You’ll need to obtain the public and private keys for this data stream for use in the configuration of the air-conditioning monitor’s code later.

Create a new “data stream”. You’ll want to fill the form in with something similar to this:

alt text

When you’ve completed the form, click “Save” and you’ll be brought to a screen that looks like this:

alt text

Below that section and at the bottom of that page, you will see an option to send the keys to an email address—I recommend doing this before you proceed.

alt text

Create A New Project And Install Dependencies

You should already have a j5ik directory—creating it is part of the Tessel software setup process. Use a terminal application to go to that directory, and then:

cd ../;
mkdir environment-monitor;
cd environment-monitor;
npm init -y;
npm install johnny-five tessel-io got;

This is going to change (cd) to the parent directory of j5ik/ and create an all new directory called environment-monitor. Once created, it will then change into environment-monitor/ and initialize a new project workspace with npm init -y. The last line will install the modules johnny-five, tessel-io and got into this project. The got module provides “Simplified HTTP requests” and describes itself as:

A nicer interface to the built-in http module.

It supports following redirects, promises, streams, retries, automagically handling gzip/deflate and some convenience options

which is perfect for our project’s needs!

Application Overview

There are four main files for our application, and they will be created in the root of the project (i.e. the environment-monitor/ directory):

  • current.js: a module that exports a class called Current. Current represents a Non-Invasive Current Sensor and inherits from Johnny-Five’s Sensor class.
  • ac.js: a module that exports a class called AC which represents an Air Conditioner. AC inherits from Current.
  • config.js: your application-specific configuration
  • index.js: the application itself

Class Heirarchy Overview

The next portion of this tutorial is dedicated to writing the software that will run our environment monitor. The bulk of this work will be spent creating cleanly separable classes that will be layered together in our application:

alt text

Writing the Current Sensor Class

Current is a class that will extend Johnny-Five’s Sensor class. Open your favorite code editor, create a file called current.js and save it in the environment-monitor/ directory. Type—or copy and paste—the following JavaScript code into your current.js file:

language:javascript"use strict";
const five = require("johnny-five");

class Current extends five.Sensor {
  constructor(pin) {
    super(pin);

    let aref = this.io.aref || 4.4;
    let cCount = 0;
    let sCount = 0;
    let lastSampleI = 0;
    let sampleI = 0;
    let lastFilteredI = 0;
    let filteredI = 0;
    let offsetI = 0;
    let sumSqI = 0;
    let rmsI = 0;
    // Turn Ratio: 100A:0.05mA
    //             2000:1
    // Burden: 100Ω
    // Calibration: 2000 / 100 = 20
    let calibration = 20;
    let ratioI = calibration * (aref / 1023);
    let last = Date.now();
    let isCalibrated = false;

    this.on("data", () => {
      let now = Date.now();

      if (now > last + 1000) {
        // Calculate Root Mean Squared Current (Amps = I)
        rmsI = ratioI * Math.sqrt(sumSqI / sCount);
        sumSqI = 0;
        sCount = 0;
        last = now;

        if (isCalibrated) {
          this.emit("measurement", rmsI);
        } else {
          if (cCount === 5) {
            this.emit("calibrated");
            isCalibrated = true;
          } else {
            cCount++;
          }
        }
      } else {
        lastSampleI = sampleI;
        sampleI = this.value;
        offsetI = offsetI + ((sampleI - offsetI) / 1023);
        filteredI = sampleI - offsetI;
        sumSqI += filteredI * filteredI;
        sCount++;
      }
    });
  }
}
module.exports = Current;

Exploring the Current Class

To provide a measurement of current in Amps, Current’s data handler function needs to consider a number of individual data samples taken during a 1-second sampling cycle. Computations need to be performed on individual samples, and, at the end of each sampling cycle, a root mean squared current (rmsI) is calculated. Current objects then emit a measurement event and pass the rmsI along to anything that might be listening. rmsI is what we’re after here—it represents the current going through the wire.

The first line of the Current module contains a Use Strict Directive to inform the JavaScript engine that this code conforms to a safe subset of JavaScript. "use strict"; appears at the top of every code file for the air conditioning monitor, so I won’t dive into it again:

language:javascript"use strict";

Next, the module requires its only dependency: the johnny-five module:

language:javascript
const five = require("johnny-five");

Immediately following that, a new class, Current, is declared. Current extends the Sensor class provided by Johnny-Five. Sensor provides all of the base mechanics needed to implement a specific analog input sensor. Current will extend Sensor and provide some things to support our current sensor.

Current’s constructor (the method that is invoked when a new Current object is created) defines a single formal parameter, pin. pin gets passed as an argument to the parent class' constructor (that is, the constructor on Sensor) when super(...) is invoked. Sensor takes care of setting up an analog input on the pin indicated:

language:javascript
class Current extends five.Sensor {
  constructor(pin) {
    super(pin);
    // ...
  }
}

After the call to super(...), a long list of let variable declarations follows. Don’t worry if these don’t make a lot of sense yet:

language:javascript
let aref = this.io.aref || 4.4;
let cCount = 0;
let sCount = 0;
let lastSampleI = 0;
let sampleI = 0;
let lastFilteredI = 0;
let filteredI = 0;
let offsetI = 0;
let sumSqI = 0;
let rmsI = 0;
// Turn Ratio: 100A:0.05mA
//             2000:1
// Burden: 100Ω
// Calibration: 2000 / 100 = 20
let calibration = 20;
let ratioI = calibration * (aref / 1023);
let last = Date.now();
let isCalibrated = false;

All right, let’s look at what some of these mean:

  • aref: the value of the particular board’s analog reference, which is the top end of the voltage that the board expects in the analog input range. For the Tessel, we know this is +3.3V, but other boards have different aref values (e.g. Arduino Uno is +5V). this.io.aref should contain the analog reference for whatever board Johnny-Five is running on currently.
  • cCount: track the number of “calibration” cycles that have passed. Calibration is set to occur over 5 1000-ms cycles—that is, the first 5 seconds of the instance’s lifetime will be used for calibration.
  • sCount: track the number of samples collected in each 1000ms sampling cycle.
  • lastSampleI/sampleI: the value of the previous and present Amps (current, or I) value.
  • lastFilteredI, filteredI, offsetI, sumSqI: Used within individual sampling computations.
  • rmsI: the calculated root mean squared (RMS) Amps value for the sampling cycle.
  • calibration/ratioI: calculated calibration and Amps ratio based on turn ratio—a characteristic of the current sensor’s hardware—and burden resistor—100Ω in our circuit. More technical details).
  • last: tracks the last time a sampling cycle completed.
  • isCalibrated: initially false; will become true once the calibration cycles are complete.

Next, we define a handler function for "data" events. These "data" events are defined within the super class five.Sensor. The only operation that occurs at the “top level” of this function execution context is to take note of the exact date and time (let now = Date.now()). data events fire frequently, about once every 25 milliseconds (this is the default sampling frequency of Johnny-Five’s Sensor class).

language:javascript
this.on("data", () => {
  let now = Date.now();
  // ...
});

From there, the operations choose a fork in the road. There are two primary conditional paths:

language:javascript
if (now > last + 1000) {
  // This code is executed if 1 second (1000 ms) has passed since
  // the last time this path was taken.
  // It represents the end of a sample cycle.
} else {
  // This code is executed every time the handler
  // function is invoked unless it's the end of a cycle.
  // It performs computations on the data sample
}

The first path handles execution when a full sampling cycle—1000ms or 1 second—is complete.

First the rmsI is calculated for this sampling cycle, then resets some variables (sumSqI and sCount). The value of last is assigned to the value of now; this will result in starting a new sampling cycle when the data handler is next invoked.

language:javascript
// Calculate (Amps = I)
rmsI = ratioI * Math.sqrt(sumSqI / sCount);
sumSqI = 0;
sCount = 0;
last = now;

If the instance is done calibrating (isCalibrated), then it can emit a "measurement" event with the value of the rmsI for the sampling cycle. Otherwise it continues calibration.

language:javascript
if (isCalibrated) {
  this.emit("measurement", rmsI);
} else {
  if (cCount === 5) {
    this.emit("calibrated");
    isCalibrated = true;
  } else {
    cCount++;
  }
}

That’s the end of the fork that handles the end of a sampling cycle. The other fork—the second primary condition—occurs almost every time the data handler is invoked, every time it’s invoked and it’s not the end of a sampling cycle.

This fork performs several computations on the most recent current value read from the sensor. The calculations here are ported from OpenEnergyMonitor.org’s “EmonLib”.

This second fork evaluates a single sensor reading. It increments the sCount (sample count) by 1 in order to track the total number of samples collected within a single sampling cycle. It then performs some calcuations on the current value, with an eye toward ultimately being able to produce a rmsI value for the entire sampling cycle.

language:javascript
lastSampleI = sampleI;
sampleI = this.value;
offsetI = offsetI + ((sampleI - offsetI) / 1023);
filteredI = sampleI - offsetI;
sumSqI += filteredI * filteredI;
sCount++;

Back out in the top-level scope, the very last line exports the Current class object so that it can be used by other code modules. I’ll skip mentioning this when looking at the code in other modules for the air conditioning monitor.

language:javascript
module.exports = Current;

Writing the AC Class

Open your favorite code editor, create a file called ac.js and save it in the environment-monitor/ directory. Type—or copy and paste—the following JavaScript code into your ac.js file:

language:javascript"use strict";
const Current = require("./current");

class AC extends Current {
  constructor(setup) {
    super(setup.pin);

    let isActive = false;

    this.on("measurement", rmsI => {
      if (Math.round(rmsI) < setup.minimumI) {
        isActive = false;
        return;
      }

      isActive = true;
    });

    Object.defineProperty(this, "isActive", {
      get() {
        return isActive;
      },
    });
  }
}
module.exports = AC;

Exploring the AC Class

The AC class has only one dependency—the Current class we just created.

language:javascript"use strict";
const Current = require("./current");

Just like with the Current class, the next step is to declare a new class called AC, which extends the Current class. Instances of the AC class will forward the value of setup.pin along to super(...) during instantiation.

language:javascript
class AC extends Current {
  constructor(setup) {
    super(setup.pin);
    // ...
  }
}

After the call to super(...), a let variable named isActive is declared and assigned an initial value of false. This will be used to track whether or not the air conditioner is active or not. (The air conditioner might be switched on all the time, but we only want to know when it’s actually actively cooling).

language:javascript
let isActive = false;

Next, we register a "measurement" event handler, which receives the rmsI value as an argument. To determine if the air conditioner is active or not…

the handler first checks if the rounded rmsI is less than the value of setup.minimumI, which the application specifies as the “minimum amps flowing when the air conditioner is active”. If it that condition evaluates to true, then that means that the air conditioner is inactive, so set isActive to false and return immediately. If that condition does not evaluate to true, that is: the value of the rounded rmsI is greater than or equal to the “minimum amps flowing when the air conditioner is active”, then set isActive to true. Note that isActive is still the let variable declared outside of the event handler.

The "measurement" event handler’s job is to determine whether the air conditioner is active. It determines this by looking at the value of rmsI (the root mean squared Amps of the sample), which it receives as an argument. The setup object passed to the AC constructor includes a minimumI property. setup.minimumI defines the minimum Amps flowing when the air conditioner is active. If rmsI is less than that value, then the air conditioner is not presently active (isActive = false). Otherwise, we can deduce that it is (isActive = true).

language:javascript
this.on("measurement", rmsI => {
  var roundRmsI = Math.round(rmsI);

  if (roundRmsI < setup.minimumI) {
    isActive = false;
    return;
  }

  isActive = true;
});

A bit about scope. isActive is declared within the function execution context of the AC class' constructor. So is the "measurement" handler function, so code within it can access isActive. However, isActive isn’t accessible directly on AC instances yet—for example, if you had an AC instance called ac, there is no ac.isActive property—yet.

What we can do is define an accessor property, also called a “getter”, to expose the value of isActive on AC instance objects.

language:javascript
Object.defineProperty(this, "isActive", {
  get() {
    return isActive;
  },
});

Note that we’re only defining a “getter”, not a “setter”. You can check the value of ac.isActive, but if you tried to set the value (ac.isActive = true), you wouldn’t be able to (it’d throw TypeError: Cannot set property isActive of #<AC> which has only a getter). While this kind of protection isn’t strictly necessary, it’s important to me that I impart my preference for tamper-proof hardware state representations in my software.

Creating the Configuration Module

Before move onto discussing the actual application code, we have one last supporting module file to create: config.js.

This module contains a single export, an object containing properties whose values are relevant configuration for our application.

The interval property defines how frequently, in milliseconds, new data is sent to data.sparkfun.com. I’ve specified 10 seconds, but you may change this to whatever best suits your version of the application. Take care to replace [Phant Public Key] and [Phant Private Key] with the values generated when you created your data stream. If you followed my advice earlier, you will already have an email containing those values.

language:javascript
module.exports = {
  interval: 10000,
  phant: {
    public: "[Phant Public Key]",
    private: "[Phant Private Key]",
  },
};

Writing the Environment Monitor Application

Open your favorite code editor, create a file called index.js and save it in the environment-monitor/ directory. Type—or copy and paste—the following JavaScript code into your index.js file:

language:javascript"use strict";
const AC = require("./ac");
const config = require("./config");
const five = require("johnny-five");
const got = require("got");
const Tessel = require("tessel-io");

const board = new five.Board({
  io: new Tessel()
});

board.on("ready", () => {
  const url = `http://data.sparkfun.com/input/${config.phant.public}.json`;
  const payload = {
    body: null,
    headers: {"Phant-Private-Key": config.phant.private, // <-- don't publish this!
    }
  };
  const ac = new AC({
    pin: "A7",
    minimumI: 1
  });
  // Once the AC instance is calibrated,
  // setup the BME280 and report status to phant
  // according to the specified interval.
  ac.on("calibrated", () => {
    let env = new five.Multi({
      controller: "BME280",
    });
    board.loop(config.interval, () => {
      if (env.isReady) {
        payload.body = {
          celsius: env.thermometer.celsius,
          humidity: env.hygrometer.relativeHumidity,
          pressure: env.barometer.pressure,
          acactive: Number(ac.isActive),
        };
        got.post(url, payload);
      }
    });
  });
});

Exploring the Application Code

As you’ve seen twice already in this tutorial, the first thing we do is require the modules that our application depends on. This time, we’re requiring got, johnny-five, tessel-io, as well as our own ac.js and config.js module files.

language:javascript"use strict";
const AC = require("./ac");
const config = require("./config");
const five = require("johnny-five");
const got = require("got");
const Tessel = require("tessel-io");

If you’ve previously read any or all of the Experiment Guide for the Johnny-Five Inventor’s Kit, then the next part will look familiar. To quote from the guide itself:

Johnny-Five supports many kinds of development boards. The support for some boards is built right in to Johnny-Five, but others — including Tessels — rely on external plugins encapsulated in modules. That’s why the code requires the tessel-ionpm module. Here, we tell Johnny-Five to use a Tessel object for IO when communicating with the board.

language:javascript
const board = new five.Board({
  io: new Tessel()
});

Next, a "ready" event handler is registered for the board instance (which represents the Tessel 2 itself). The "ready" event will be emitted when Johnny-Five and Tessel-IO have completed their respective initialization phases and the board is ready to interact with.

Before we start interacting with the hardware, there are two const declarations that get created. The value of url will be passed directly to got.post(...) and represents the API endpoint for posting data to your data stream, while the value of the payload.body property will be updated with the present environment values to send to data.sparkfun.com.

language:javascript
const url = `http://data.sparkfun.com/input/${config.phant.public}.json`;
const payload = {
  body: null,
  headers: {"Phant-Private-Key": config.phant.private, // <-- don't publish this!
  }
};

Now we get to see our AC class in action! The program instantiates a new AC instance object and assigns it to ac. If you look back at the AC class constructor definition, you’ll see that it accepts a setup argument, an object. The pin property of the setup object will get forwarded on to Current and then on to Sensor to tell Johnny-Five which pin the component is connected to. The minimumI value represents the minimum amount of current, in Amps, that the air conditioner uses when active.

language:javascript
const ac = new AC({
  pin: "A7",
  minimumI: 1
});

Immediately following the instantiation, the program registers a "calibrated" event with ac. Remember that AC inherits from Current? That means that the ac instance object will emit all of the events that come from its super class object as well. Very useful!

language:javascript
ac.on("calibrated", () => {
  // ...
});

The "calibrated" event will fire once near the beginning of the ac instance’s lifetime, and when it does, the program will treat that as an indication that all systems are “go”.

The next step is instantiate a new five.Multi object, specifying "BME280" as controller. The Multi class is used to represent components that provide data from multiple sensors, each of which is represented by a Johnny-Five component class. In this case, an instance of Multi for a BME280 will itself contain instances of:

  • Altimeter
  • Barometer
  • Hygrometer
  • Thermometer

…all four of these sensors are packaged on the BME280. By making use of the Multi class, you can wrangle all four sensors with one component object.

language:javascript
const env = new five.Multi({
  controller: "BME280",
});

In the Johnny-Five Inventors Kit Guide Experiment 10: Using the BME280, you learned how to respond to "data" events from the BME280Multi instance by creating a handler that forwarded values on to the browser via a WebSocket provided by socket.io.

In this example, I’d like to show you how to interact with sensors by simply waiting for them to be “ready” and then accessing data directly from the instance object’s properties. The program will use the board.loop(...) method, check if the Multi instance (env, which is short for “environment”) is “ready”; if it is, then it will post data to our data stream:

language:javascript
const env = new five.Multi({
  controller: "BME280",
});
board.loop(config.interval, () => {
  if (env.isReady) {
    payload.body = {
      celsius: env.thermometer.celsius,
      humidity: env.hygrometer.relativeHumidity,
      pressure: env.barometer.pressure,
      acactive: Number(ac.isActive),
    };
    got.post(url, payload);
  }
});

And that’s it!

Run It

Once all of this is saved in the right files and in the right directories, type—or copy and paste—the following into your terminal:

t2 run index.js

Once it’s running, open your browser to https://data.sparkfun.com/streams/[Phant Public Key] and refresh it the browser as often as you’d like to see the data appear in your public stream. The stream that I created for this project is available here: https://data.sparkfun.com/streams/wp063JWw94CmL10wYw1W , which I exported to Analog.io and captured a portion that shows my own air conditioner going inactive, followed by a the temperature in the apartment rising until the air conditioner becomes active again.

alt text

alt text

alt text

When you’re ready to deploy it full time, push the project into the Tessel 2’s flash memory by using the command:

t2 push index.js

Resources and Going Further

You can find all the files for the Envirinmental MOnitor at the GitHub repository.

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!
New!

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!

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

MAG3110 Magnetometer Hookup Guide

$
0
0

MAG3110 Magnetometer Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The SparkFun MAG3110 Triple Axis Magnetometer is a breakout board for the 3-axis magnetometer from NXP/Freescale. It is a low power (1.95V to 3.6V) device that communicates over I2C. It outputs data in two’s complement with values ranging from -30,000 to +30,000 and has a full-scale range of ±1000µT.

This sensor allows you to quickly detect surrounding magnetic fields. This data can be used to create a digital compass or even sense strong magnetic fields from transformers!

SparkFun Triple Axis Magnetometer Breakout - MAG3110

SEN-12670
$14.95
2

We will explore the functions of the MAG3110 sensor and get up and running using the SparkFun MAG3110 Arduino library and example code.

Required Materials

The required materials varies depending on how you want to use the sensor. You will notice this sensor’s supply can only go up to 3.6V. If you try to communicate with this sensor using a 5V Arduino or similar platform you could permanently damage the chip! To use this with 5V logic devices, you must use a bi-directional logic level converter.

Fortunately, SparkFun offers a few inexpensive options. This part is recommended.

Please note you will also need a low voltage source to power this sensor if your Arduino does not have an on-board regulator. You may want to use something like this 3.3V Low-Dropout Regulator (LDO)

For the rest of the items you will need, see the wish list below.

Suggested Reading

Before embarking upon this guide, you may want to familiarize with any of the topics below.

Hardware Overview

MAG3110 Details:

  • 3 magnetic field channels
  • 1.95V to 3.6V supply voltage
  • Full-scale range of ±1000 µT
  • Sensitivity of 0.10 µT
  • Output data rates up to 80Hz
  • I2C Serial Interface

Pull-up Resistors

As with other SparkFun breakout boards using I2C, this sensor features on-board pull-up resistors to make getting started quick and easy. However, you may need to disconnect these pull-ups when using other devices on the I2C bus that also have these pull-ups. You can disconnect these by using some solder wick to remove the solder from the pads on the front of the board highlighted in the image below.

MAG3110 Pull-up Pad

Pin Functions

MAG3110 Pins

The MAG3110 breakout doesn’t have many pins, which makes it very easy to hookup! You just need to give it a supply voltage up to 3.6V(VCC), ground (GND), and the I2C bus lines for communication. These are the SDA and SCL pins.

SymbolDescription
VCCSupply Voltage (1.95V to 3.6V)
GNDMust be connected to ground
SDASerial Data pin for I2C Communication
SCLSerial Clock pin for I2C Communication
INTInterrupt pin -- high when new data is ready

You may notice there is one last pin – the INT pin. This stands for INTerrupt. Inside the MAG3110 there is a register that can tell you if the sensor has new data for you to read. The INT pin is hard-wired to this register and outputs a logic high when new data is ready. When you read data from the sensor this register is automatically cleared to 0.

While you can just continuously read values from the sensor regardless of whether it’s new, this is inefficient both in terms of power and processor cycles. A better way is to trigger reading data when this pin goes high. But if all you want to do is get a reading and don’t care about efficiency, then don’t worry about connecting this pin!

If you are an advanced user, the INT pin can be setup by using an external interrupt. Note that I found this difficult to achieve without weird results. I believe the Arduino Wire (I2C) or Serial libraries use interrupts and it conflicts with this. If you are using a different platform, it may work better.

Hardware Assembly

As mentioned before, if you are using this sensor with a 5V Arduino or other microcontroller, you will need to have a logic level converter between the microcontroller and the sensor.

If you are unsure how to hook up a logic level converter, see this guide.

You will also need to step down the supply voltage to a suitable level for this sensor. Some microcontrollers (like the Arduino Micro and SparkFun RedBoard) have built in 3.3V regulators that you can use to power the MAG3110!

As an example, here is how to connect the MAG3110 sensor to a SparkFun RedBoard.

The pins should be connected as follows:

RedBoard PinLogic Converter PinMAG3110 Pin
3.3VLVVCC
GNDGNDGND
5VHV-
SDAHV1-
SCLHV2-
-LV1SDA
-LV2SCL

Here is this circuit laid out on a breadboard:

fritzing diagram

Click the image for a closer look.

If you’re not using a SparkFun RedBoard, the only pins that will change are the SDA and SCL. For other Arduino boards, SDA and SCL are:

BoardI2C Pins
Uno, EthernetA4 (SDA), A5 (SCL)
Mega256020 (SDA), 21 (SCL)
Leonard/Micro2 (SDA), 3 (SCL)
Due20 (SDA), 21 (SCL), SDA1, SCL1

SparkFun MAG3110 Library

SparkFun has created a library to make it easier to get readings from the MAG3110 sensor. It also has code to calibrate the sensor and obtain magnetic north headings!

Note: The calibration and magnetic north readings only work if the magnetometer is oriented level with the z axis pointing up or down! Obtaining magnetic north independent of orientation requires the use of an accelerometer to know which way is down and more complex math.

You can download the library here along with example code. You can find the latest library and example files in the GitHub repository for this library. Not sure how to install an Arduino library? Check out this guide!

SparkFun MAG3110 Magnetometer Arduino Library

There are a variety of functions beyond basic readings. To learn more, browse through the included examples in the library. You can also look at the library source code. We’ll go over a few of the basic commands in this guide.

Using the Library

Once you have the library installed, open the included example SparkFun-MAG3110-Basic.ino.

This sketch is bare-bones way of reading data from the MAG3110.

language:c
#include <SparkFun_MAG3110.h>

MAG3110 mag = MAG3110(); //Instantiate MAG3110

void setup() {
  Serial.begin(9600);

  mag.initialize(); //Initializes the mag sensor
  mag.start();      //Puts the sensor in active mode
}

void loop() {

  int x, y, z;
  //Only read data when it's ready
  if(mag.dataReady()) {
    //Read the data
    mag.readMag(&x, &y, &z);

    Serial.print("X: ");
    Serial.print(x);
    Serial.print(", Y: ");
    Serial.print(y);
    Serial.print(", Z: ");
    Serial.println(z);

    Serial.println("--------");
  }
}

Calling mag.initialize() sets up the sensor and checks whether a MAG3110 is connected properly. If mag.error is true, the Arduino was unable to talk to the MAG3110! When initialized, the magnetometer is set to standby mode with all offsets set to 0. To put the magnetometer in active mode and start sampling, simply write mag.start()

You can check whether any new data is ready using the mag.dataReady() function. This will return true if new data is available.

You can read all three axes using the mag.readMag() function. Don’t be afraid of the & symbol! This simply means we are giving the address of the variables to the function so that they can be filled with the data. If this seems confusing, you might want to read about pointers.

If you run this sketch and open up Tools->Serial Monitor, you should see the following:

serial output

Other functions can be seen in the SparkFun-MAG3110-Other.ino sketch:

language:c
#include <SparkFun_MAG3110.h>

MAG3110 mag = MAG3110(); //Instantiate MAG3110

void setup() {
  Serial.begin(9600);

  mag.initialize();
  //This line makes the output data rate a lot slower
  //Output Data Rate = 1.25Hz
  //Oversampling Ratio = 32
  //This means it takes 32 samples and averages the results
  if(!mag.error) //You can use this to check if there was an error during initialization.
  {
    mag.setDR_OS(MAG3110_DR_OS_1_25_32);
    mag.start();
  }

  //You can set your own offsets without calibration
  //mag.setOffset(MAG3110_X_AXIS, -100);
  //mag.setOffset(MAG3110_Y_AXIS, 300);
  //mag.setOffset(MAG3110_Z_AXIS, -300);

  //You can read the sensor's offset by calling:
  //int offset = mag.readOffset(MAG3110_X_AXIS);

  //You can obtain system information by calling any of the following:
  //mag.isActive(); //Tells you whether the mag sensor is active or in standby
  //mag.isRaw(); //Tells you if the mag sensor is outputting raw data or not
  //mag.isCalibrated(); //Tells you if the mag sensor has been calibrated
  //mag.isCalibrating(); //Tells you if the mag sensor is currently being calibrated
  //uint8_t mode = mag.getSysMode(); //Reads the SYSMOD register. See the datasheet for more information

  //This will reset the sensor to default values
  //It sets the offsets to 0, flags it as uncalibrated, and sets the device to standby mode
  //The Output Data Rate and Oversampling ratio will also be set to 80 and 16 respectively (see datasheet)
  //mag.reset();

  //This will disable the use of user offsets
  //User offsets are enabled by default but are initialized to 0
  //mag.rawData(true);
}

void loop() {

  float xf, yf, zf;
  //Only read data when it's ready
  if(mag.error)
    Serial.println("Could not connect to MAG3110 Sensor!");
  if(mag.dataReady()) {
    mag.readMicroTeslas(&xf, &yf, &zf); //This divides the values by 10 to get the reading in microTeslas

    Serial.print("X: ");
    Serial.print(xf);
    Serial.print(", Y: ");
    Serial.print(yf);
    Serial.print(", Z: ");
    Serial.println(zf);

    Serial.println("--------");
  }
}

A few functions to point out from the example above:

mag.setDR_OS() - This functions allows you to set the MAG3110’s Output Data Rate (ODR) and Over-sampling Ratio (OSR). The output data rate tells you how many new datasets the MAG3110 will provide in one second. For example, an output data rate of 80 (the default) will give you 80 new readings per second. The over-sampling ratio tells the MAG3110 how many samples to average together for one reading. For example, with an OSR of 16 the MAG3110 will take 16 measurements, average the results together, and give you one averaged result.

These two variables are related, and you can find more about this setting in the datasheet. The library includes defined settings for this that follow this format: MAG3110_DR_OS_80_16. This will give you an ODR of 80Hz and an OSR of 16.

mag.setOffset(axis, offset) - This allows you to set your own offsets in case you have calibration data saved. You can choose which axis to change using these defined constants: MAG3110_X_AXIS, MAG3110_Y_AXIS, MAG3110_Z_AXIS.

mag.readOffset(axis) - This allows you to get the offsets the MAG3110 is using. You could use this function to save the offsets after calibration!

Note: If you want to fully save calibration data, you will have to save mag.x_scale and mag.y_scale. These are both float values that are calculated during calibration. Be sure to only modify these values when you have saved calibration data or you may have to recalibrate! You can also directly set mag.calibrated to true if you manually calibrate the sensor

mag.isActive() - Tells you whether the mag sensor is active or in standby

mag.isRaw() - Tells you if the mag sensor is outputting raw data or not

mag.isCalibrated() - Tells you if the mag sensor has been calibrated

mag.isCalibrating() - Tells you if the mag sensor is currently being calibrated

mag.getSysMode() - Reads the SYSMOD register. See the datasheet for more information

mag.rawData(boolean) - This sets whether the MAG3110 will output raw (non-user corrected) or offset data. Giving the function a true value will set the data to raw output, and vice-versa.

mag.readMicroTeslas() - This gives data in µTeslas. It really just divides the normal output by 10 since this is the scale the MAG3110 uses.

There are additional functions shown in other example sketches included with the library. A few of these are:

mag.readRegister(address) - This allows you to read any register of the MAG3110. Read the datasheet for more information. The library has all registers mapped in the format MAG3110_REGISTER_NAME.

mag.writeRegister(address, value) - This allows you write a value to any register of the MAG3110. Be careful if you aren’t sure what you’re doing! You might change settings you didn’t mean to!

mag.triggerMeasurement() - When the MAG3110 is in standby, this triggers a single measurement to take place. It lets you save power by keeping the device mostly inactive and only take data when you need to. Be aware this single-shot reading may be less accurate than active mode reading since the signal takes time to settle. See the datasheet for more information. If you want to learn how to do triggered measurements, see the included example “SparkFun-MAG3110-Triggered”.

You can also do triggered measurements while in active mode. This is more advanced and is covered in the datasheet.

Calibration

All these functions are great… but what if you need to find a portal to The Upside Down? You need a heading! This sensor and library allow you to obtain the magnetic north heading very easily!

Note that this only works when the sensor is level with the z-axis pointing straight up or down. The heading will be relative to the positive x-axis (ie: the x-axis arrow silkscreened on the board points to magnetic north).

magnetic north

To find out how to use the library’s calibration, open up the included example sketch, SparkFun-MAG3110-Calibration.ino.

When you run the sketch, you will see unadjusted readings in the Serial output for the first 5 to 10 seconds. During this period, you must rotate the MAG3110 360 degrees while keeping it level!. This allows our sketch to get its bearings.

The reason for calibration is that your surroundings may have static magnetic fields that offset the MAG3110 readings. For example, if you have something magnetic near the sensor this will add an offset to the sensor’s readings.

This calibration code will center the x and y-axis readings around 0 or about there. The z-axis is not calibrated with this library. This calibration works by taking a bunch of readings and trying to find the minimum and maximum values for the x and y axes. It then uses these min and max values to calculate an offset and a scaling factor. The calibration code is based off of this code found here.

A Honeywell application note detailing how the heading is calculated can be found here.

language:c
#include <SparkFun_MAG3110.h>

MAG3110 mag = MAG3110(); //Instantiate MAG3110

void setup() {
  Serial.begin(9600);

  mag.initialize(); //Initialize the MAG3110
}

void loop() {

  int x, y, z;

  if(!mag.isCalibrated()) //If we're not calibrated
  {
    if(!mag.isCalibrating()) //And we're not currently calibrating
    {
      Serial.println("Entering calibration mode");
      mag.enterCalMode(); //This sets the output data rate to the highest possible and puts the mag sensor in active mode
    }
    else
    {
      //Must call every loop while calibrating to collect calibration data
      //This will automatically exit calibration
      //You can terminate calibration early by calling mag.exitCalMode();
      mag.calibrate();
    }
  }
  else
  {
    Serial.println("Calibrated!");
  }
  mag.readMag(&x, &y, &z);

  Serial.print("X: ");
  Serial.print(x);
  Serial.print(", Y: ");
  Serial.print(y);
  Serial.print(", Z: ");
  Serial.println(z);

  Serial.print("Heading: ");
  Serial.println(mag.readHeading());

  Serial.println("--------");

  delay(100);
}

Note a few things about the calibration functions.

Setting the MAG3110 to calibration mode (ie: using mag.enterCalMode()) will set it to the highest output data rate and enter active mode. You will need to set your desired ODR and OSR after calibration, and enter standby if you wish. If you just want to simply read values, you can leave these settings alone.

When calibrating, you must call mag.calibrate() every loop cycle. This allows the code to sample the MAG3110 readings and find the minimum and maximum values.

The calibration mode will automatically exit after some time but at least 5 seconds. If this is too long, you can terminate the calibration earlier by calling mag.exitCalMode(). Please note that the calibration may be offset if you do not calibrate enough!

If you have not calibrated the MAG3110, calling mag.readHeading() will only give you 0! Otherwise, it will show values ranging from -180 to +180. When the heading is 0, the x-axis is pointing towards magnetic north (see the diagram from before).

As mentioned before, if you want to manually calibrate the MAG3110 using previously obtained calibration values, you need to do a few things: Save the offsets using mag.readOffset(), and save the scaling floats, mag.x_scale and mag.y_scale. When reloading this calibration, you have to use mag.setOffset() and write the old scaling factors back to mag.x_scale and mag.y_scale. For completeness, update the mag.calibrated value to true as well. Note that as the calibration data becomes outdated, recalibration is recommended.

Alternative Applications

Aside from sensing magnetic north, this sensor has a few other uses. Many high power electronics create magnetic fields of their own. With this sensor, you can see this disturbance.

An example sketch is included with the library called SparkFun-MAG3110-Magnitude.ino. This sketch first calibrates the sensor and then outputs serial data of the magnitude of the scaled x and y-axes. Recall the magnitude of a vector is:

In this case a3 is 0 since we do not take the z-axis into account.

Once the sketch is running and calibration has completed, open up the Tools->Serial Plotter in the Arduino IDE (only available in the newest versions of the Arduino IDE). If you put the sensor near a microwave and then warm something up, you will see some noise on the signal.

microwaves

Notice the electromagnetic interference caused by simply heating up my frozen burrito.

And, if you put a fridge magnet near the sensor, you will see large spike! Be careful though, the sensor has maximum limits of magnetic field strength it can be exposed to without damage.

magnet

Each spike represents the approach of a fridge magnet

Resources and Going Further

This is a nifty little sensor for orientation, but you may want to go beyond the simple compass that this library allows. You can use an accelerometer in conjunction with this device to create a tilt-compensated compass. SparkFun has a variety of accelerometers available, including the ADXL345.

To get you started in the right direction, here are a few application notes that go into more detail about this:

You can also check out my project using this guide and the MAG3110, the Digital Compass.

New!

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

MicroView Digital Compass

$
0
0

MicroView Digital Compass a learn.sparkfun.com tutorial

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

Introduction

In this tutorial you will learn how to use a MAG3110 3-axis magnetometer to make a portable digital compass! This project will also use the SparkFun MicroView to display the heading.

Digital Compass

If you haven’t checked it out already, go see the new MAG3110 Hookup Guide to learn how this device works!

Required Materials

This project uses the MAG3110 magnetometer to sense magnetic north along with the SparkFun Microview to display and control the whole show. If you don’t have one, you will need a MicroView Programmer as well to upload code to the MicroView.

Since the MicroView is a 5V logic device and the MAG3110 is lower voltage device, you will also need a Bi-Directional Logic Converter to facilitate communication between them. Be careful, if you hook them up directly to each other, you could damage the MAG3110 sensor!

I chose to make the whole thing battery-powered, so I could walk around with it. I used SparkFun’s Power Cell - LiPo Charger/Booster and an 850mAh LiPo Batter. However, feel free to keep it tethered to your computer over USB if you don’t want to get the extra parts.

You can build the whole thing on a breadboard or use SparkFun’s nifty snappable protoboard for a more permanent project.

For most of these parts, you may have to solder on male headers for use with a breadboard. See the suggested reading below for tips on how to do this!

The wish list below contains most of the parts you’ll need to follow along.

Suggested Reading

Before embarking upon this guide, you may want to familiarize with any of the topics below.

Hardware Hookup

It might seem complicated, but there are only a few basic blocks of the circuit: power, brains, the level-shifter, and the sensor.

Powering your circuit

If you aren’t using battery power you can just ignore the PowerCell. Be sure to only power the MAG3110 with 3.3V. If you give it 5V, it might get damaged! The MicroView has an internal 3.3V regulator, but unfortunately it isn’t pulled out to the pins. Instead, you can use an external 3.3V LDO regulator. See the datasheet for how to hook this up (it’s really simple!).

The PowerCell features a selectable voltage output – either 5V (default) or 3.3V. In order to use it with our project, we need to change the output to 3.3V. There is a solder jumper that selects this. Use some solder wick to remove the solder, and bridge the center pad and the pad that says “3.3V”.

PowerCell Voltage Jumper

Make sure your solder pad looks like this to select 3.3V output.

If you are still unsure about your connection, see the PowerCell Quickstart Guide.

With either method, make sure to check the voltage output of your power source using a multimeter before you hook anything up to it!

Wiring up the MicroView

The MicroView has an internal 5V boost regulator. This means you can give it lower supply voltages (down to 3.3V) and it will boost them up to the 5V it needs. This makes it very easy to power our MicroView from the 3.3V output of the PowerCell.

Conveniently, the MicroView brings this 5V out to an external pin for use in other parts of our circuit. This is good because we need it to use the logic level shifter.

Recall the pinout of the MicroView:

microview pinout

Connect the 3.3V source to the VIN pin of the MicroView, and connect the GND pin to ground. Voila! The MicroView has power.

Connecting the level shifter

The level shifter allows higher voltage (5V) logic devices to talk to lower voltage (3.3V) logic devices without damage or miscommunication. For more information on logic levels, see this guide, and, to learn more about how to hook up the level shifter, see this guide

Here’s the level shifter we will be using:

level shifter

Notice there’s a high voltage side and a low voltage side. Connect the high voltage source, “HV”, to the 5V pin of the MicroView, and connect GND to ground.

For the low voltage side, connect LV to 3.3V and GND to ground.

I2C Communication

The MAG3110 sensor communicates over I2C. This protocol is nice because it only requires two wires between the devices. Namely, SDA (serial data) and SCL (serial clock). From the pinout shown before, you can see the MicroView has SCL and SDA on pins 2 and 3, respectively.

We only have to shift these two outputs, so connect the SCL and SDA of the MicroView to HV1 and HV2 of the level shifter.

Wiring the MAG3110 Sensor

The MAG3110 sensor is a 3-axis magnetometer that can be used to sense the strength of magnetic fields. This data can be used to find magnetic north! Check out the MAG3110 hookup guide for more on how to use this sensor!

The MAG3110 breakout only has a few pins we need to connect.

MAG3110 Pins

The MAG3110 can only handle voltages up to 3.6V, so be sure to connect VCC to 3.3V and not 5V. The GND pin goes to ground, and SCL and SDA should go to LV1 and LV2 of the level shifter. Make sure you don’t have SCL or SDA swapped around on either side of the level shifter or you won’t be able to talk to the sensor.

Completed Circuit

The circuit should now be complete. Make sure to check your connections before you plug in the battery.

If you chose to use USB power (using the MicroView Programmer) and an external 3.3V regulator, this circuit is found below. Don’t worry too much about the capacitors, they’re just filtering capacitors recommended by the regulator’s datasheet.

USB Powered Digital Compass

If you used the more portable battery-based PowerCell circuit, you can follow this circuit shown below.

Battery Powered Digital Compass

MicroView Sketch

Now that the circuit is complete, it’s time to program the MicroView! If you haven’t already, go check out the MAG3110 Hookup Guide, and download the SparkFun MAG3110 Arduino library. This library makes it super easy to use the MAG3110 sensor and includes the example digital compass sketch we’re about to use.Not sure how to install an Arduino library? Check out this guide!.

SparkFun MAG3110 Magnetometer Arduino Library

Once the library is installed, you can find the code for the digital compass under Examples → SparkFun MAG3110 Magnetometer Breakout Arduino Library → SparkFun_DigitalCompass.

alt text

The code is basically the example calibration code and also manages the sprite rendering.

Getting Sprites on the MicroView

Rendering sprites on the MicroView can be a bit of a challenge. I wrote a small Processing sketch to convert bitmaps to hex code that can be displayed more easily on the MicroView. It’s not very polished but you can download that using the link below, or you can find the Files in the MAG3110 Arduino Library GitHub repo.

uView Image Converter

You may need to install the Processing sDrop library. If you need help with Processing, see this guide.

When you run the sketch, a virtual MicroView will appear on your screen. Drag any bitmap file (up to 64X48 pixels) into the virtual MicroView and it will convert it to hex. Note that all the pixels need to be white or black. You should see a preview in the virtual MicroView.

Copy the hex output from the Processing console, and copy it into your code. You can now load this hex into the MicroView screen buffer, and it should display it properly. You may need to format the hex (and get rid of extra commas) for it to compile properly.

Understanding and Running the Sketch

In the beginning of the code, you will see a lot of the word PROGMEM. Since this sketch uses a lot of sprites, the regular memory couldn’t hold all of them. This keyword is part of a library that lets you store certain variables in memory.

The rest of the code follows the example calibration sketch for the MAG3110 Library. If you want to know more about calibrating the MAG3110, see the hookup guide linked to earlier. The heading I get from this I had to offset by 90 degrees since the MicroView and the MAG31110 x-axis were pointing in different directions.

When you first start running the sketch, you will need to calibrate the MAG3110 by spinning it 360 degrees a few times while keeping it level.

Based on the heading, the code loads a different sprite onto the MicroView.

Compass GIF

Once calibrated, you should have a working digital compass!

Resources and Going Further

There are a many more cool projects you can make with the MAG3110 sensor. If you combine the MAG3110 with a few other sensors, you can make a variety of projects that involve location and orientation sensing.

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

Vernier Photogate

Vernier Photogate Timer -- using the Serial Enabled LCD Kit.

T5403 Barometric Pressure Sensor Hookup Guide

T5403 Barometric Pressure Sensor Hookup Guide

LilyPad Light Sensor Hookup Guide

How to hook up the LilyPad Light Sensor as well as some project ideas and example code.

MPU-9250 Hookup Guide

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

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

Vox Imperium: Stormtrooper Voice Changer

$
0
0

Vox Imperium: Stormtrooper Voice Changer a learn.sparkfun.com tutorial

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

Introduction

The Empire’s finest have a distinct nasal and mechanical voice when talking through their intercoms. As you work diligently on that Stormtrooper costume and apply for the 501st, you can up your armor game by including a voice changer.

Stormtrooper helmet

There are pre-built solutions available for budding Stormtrooper cadets, but most are bulky and sometimes require wiring outside the helmet. However, with a little bit of coding and wiring, you can build your own inside a helmet using SparkFun parts.

Required Materials

In this tutorial, we’ll build the voice changer on a breadboard for testing. Each helmet will be different, so the wiring will have to be adjusted. The parts list below details what you’ll need for the breadboard prototype.

Note that from the resistor kit you’ll need:

  • 1x 2.2kΩ
  • 1x 4.7kΩ

Suggested Reading

We suggest you be familiar with the following before embarking upon this tutorial:

Hardware Hookup

Prep Connectors

Note: This part is optional if you do not plan to connect things to a breadboard. Skip to the Fritzing section to see how to wire things up if you plan to put the components directly into a helmet without headers.

To start, solder headers onto the Teensy and Prop Shield. You’ll also want to solder female headers to the edge pins on the Teensy, the edge pins on the Prop Shield, and the Prop Shield’s audio out port.

Headers on Teensy and Prop Shield

Cut and strip six lengths of wire, each about 6 inches long. Solder them to the speakers (note that you’ll need to splice two wires to one for each positive and negative terminal).

Wires on the speakers

Fritzing Wire Diagram

Connect the components as shown in the breadboard. Follow the wires if you plan to put this into a helmet.

Note: You can also stack the Teensy on top of the Prop Shield and solder header pins between them. The wiring diagram is meant to show which connections are needed if you plan to wire them separately.

Vox Imperium Fritzing wiring diagram

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

Audio System Design

One of the coolest tools for developing on the Teensy is the PJRC Audio System Design Tool. With it, you can drag and drop blocks that correspond to various components on the Teensy, like the ADC and DAC, in addition to useful functions like filters. After connecting them with “patch cords,” you can export the whole thing as Arduino code. Pretty sweet.

Feel free to try it out and replicate the block diagram.

Note: You don't actually have to recreate the block diagram; the code in The Code section already has the necessary audio pieces built in.

Vox Imperium Audio System Design Tool

Doing a basic microphone-to-speaker pass through requires simply connecting the ADC to the DAC. To add features, we’ll need to put blocks in between those two.

Stormtrooper voices are marked by a nasal sound that can easily be accomplished by turning the treble way up and turning the bass way down. To accomplish this in the Design Tool, we’ll use a state variable filter with a corner frequency set to 2000 Hz. Frequencies below that are considered “bass” (for a voice), and frequencies above that are “treble.” By separating the low and high frequencies, we can put them back into a mixer and play with the individual gain. In the code, we’ll set the treble gain to 0.25 (so as not to blow out the amplifier) and bass to 0.01 (we want it pretty much gone). You can play with any of the GAIN parameters in the code to adjust the volume and treble/bass mix.

You’ll also notice that we added a biquad filter right after the ADC. We ultimately want to use this as a low-pass filter to reduce feedback we might get between the microphone and speakers. However, if we enable it in the code, it reduces the quality of the sound, as we effectively filter out most of the voice frequencies we want. Feel free to play with the FEEDBACK_SUPPRESSION and LOWPASS_CUTOFF parameters in the code to try setting the low-pass filter to an acceptable frequency.

The peak is an analysis block that gives us a measure of the amplitude of the audio signal. We use this to determine when someone is talking into the microphone. Play with the SQUELCH_CUTOFF parameter to adjust the volume where the Teensy begins playing sound through the speakers.

playFlashRaw allows us to play a raw audio file that has been loaded into the Prop Shield’s serial flash memory. We’ll upload the “click” and “static burst” sounds and play them whenever a user starts or finishes talking. Change the BEGIN_CLICK parameter to choose whether to play the click sound at the start, and change END_SOUND to choose whether to play a randomly chosen click or static burst at the end of talking.

Click the export button to get the necessary Arduino code. You can just copy it into a sketch!

If you want to try the other blocks, feel free to drag them in and connect some patch cables. To really get some distorted sound, I recommend the Bitcrusher (details for each audio block can be found on the righthand side of the Audio System Design Tool).

Sound Clips

To play the quintessential Stormtrooper “click” and “static burst” sounds, we need to rip them from a sound clip, convert them to a raw format and load them into the Prop Shield’s serial flash memory.

Convert Sound Clips to Raw

Note: You can skip this section if you choose. The raw sound clips can be found in the GitHub repository.

Find a Stormtrooper sound clip, like this one. Download it and open it with an editing program, like Audacity.

Make sure the project is set to 44.1kHz, highlight the portion of the clip you want (we’ll highlight the “click” noise) and crop it (Trim Audio in Audacity).

Audio editing in Audacity

Export the clip (File > Export Audio…), name the new file click.raw and adjust the file options to:

  • Save as type: Other uncompressed files
  • Header: RAW (header-less)
  • Encoding: Signed 16-bit PCM

Export raw audio file from audacity

Repeat this process for the static burst sound, which we named break.raw.

Upload Sound Clips to Prop Shield

Before you begin this part, make sure you have Teensyduino installed in the Arduino development environment. This tutorial was tested using Arduino 1.6.9.

Now that we have the raw sound clips, we need to upload them to the Teensy. To do that, we’ll use the TeensyTransfer Tool.

Download the TeensyTransfer repository as a ZIP file. Open a new Arduino sketch and select Sketch > Include Library > Add .ZIP Library. Find and select the TeensyTransfer-master.zip file. This will install the TeensyTransfer library.

Open File > Examples > TeensyTransfer-master > teensytransfertool.

In Tools, select:

  • Board: Teensy 3.2 / 3.1
  • USB Type: Raw HID
  • CPU Speed: 96 MHz optimized (overclock)
  • Port: <Your Teensy’s Port>

Uploading teensytransfertool

Upload the sketch to the Teensy. Find the downloaded TeensyTransfer-master.zip file and unzip it. Go to TeensyTransfer-master/extras and unzip the pre-compiled teensytransfer program for your operating system:

  • teensytransfer.gz for Linux
  • teensytransfer.mac.zip for OS X
  • teensytransfer.zip for Windows

Open a command prompt, navigate to the TeensyTransfer-master/extras/teensytransfer directory and run the program to upload the raw audio clips to the Prop Shield’s flash memory:

cd <Downloads directory>TeensyTransfer-master/extras/teensytransfer
teensytransfer -w <GitHub directory>/Vox_Imperium/sfx/click.raw
teensytransfer -w <GitHub directory>/Vox_Imperium/sfx/break.raw

You can check if the transfer worked by entering teensytransfer -l, and the tool should output the files found on the serial flash memory.

Using the TeensyTransfer tool to upload sound clips to the Teensy Prop Shield

The Code

Create a new Arduino sketch and copy in the code:

language:c
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=255,182
AudioFilterBiquad        biquad1;        //xy=394,182
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=535,319
AudioFilterStateVariable filter1;        //xy=558,189
AudioAnalyzePeak         peak1;          //xy=559,255
AudioMixer4              mixer1;         //xy=710,196
AudioOutputAnalog        dac1;           //xy=844,196
AudioConnection          patchCord1(adc1, biquad1);
AudioConnection          patchCord2(biquad1, 0, filter1, 0);
AudioConnection          patchCord3(biquad1, peak1);
AudioConnection          patchCord4(playFlashRaw1, 0, mixer1, 2);
AudioConnection          patchCord5(filter1, 0, mixer1, 0);
AudioConnection          patchCord6(filter1, 2, mixer1, 1);
AudioConnection          patchCord7(mixer1, dac1);
// GUItool: end automatically generated code

// Parameters
const bool DEBUG = false;
const bool BEGIN_CLICK = true;  // Play click on voice start
const bool END_SOUND = true;    // Play click/burst on voice end
const bool FEEDBACK_SUPPRESSION = false;  // Enables input filter
const unsigned int LOWPASS_CUTOFF = 2200; // Hz
const unsigned int CROSSOVER_FREQ = 2000; // Filter center freq
const float BASS_GAIN_ON = 0.01;
const float BASS_GAIN_OFF = 0.0;
const float TREBLE_GAIN_ON = 0.25;    // Voice output volume
const float TREBLE_GAIN_OFF = 0.0;
const float SFX_GAIN = 0.5;           // Sound clip volume
const float SQUELCH_CUTOFF = 0.10;    // Voice threshold
const int HYSTERESIS_TIME_ON = 20;    // Milliseconds
const int HYSTERESIS_TIME_OFF = 400;  // Milliseconds

// Pins
const int FLASH_CS = 6;               // Serial flash chip select
const int AMP_ENABLE = 5;             // Amplifier enable pin

// On/Off state machine states
typedef enum volState {
  QUIET,
  QUIET_TO_LOUD,
  LOUD,
  LOUD_TO_QUIET,
} VolState;

// Global variables
elapsedMillis fps; // Sample peak only if we have available cycles
VolState state = QUIET;
unsigned long timer;

void setup() {

  if ( DEBUG ) {
    Serial.begin(9600);
  }

  // Initialize amplifier
  AudioMemory(20);
  dac1.analogReference(EXTERNAL); // much louder!
  delay(50);                      // time for DAC voltage stable
  pinMode(AMP_ENABLE, OUTPUT);

  // wait up to 10 seconds for Arduino Serial Monitor
  unsigned long startMillis = millis();
  if ( DEBUG ) {
    while ( !Serial && ( millis() - startMillis < 10000 ) );
  }

  // Butterworth lowpass filter (reduces audio feedback)
  if ( FEEDBACK_SUPPRESSION ) {
    biquad1.setLowpass(0, LOWPASS_CUTOFF, 0.707);
  } else {
    biquad1.setLowpass(0, 8000, 0.707);
  }

  // Configure the State Variable filter
  filter1.frequency(CROSSOVER_FREQ);
  filter1.resonance(0.707);

  // Adjust gain into the mixer
  mixer1.gain(0, BASS_GAIN_OFF);
  mixer1.gain(1, TREBLE_GAIN_OFF);
  mixer1.gain(2, SFX_GAIN);

  // Initialize serial flash
  if ( !SerialFlash.begin(FLASH_CS) ) {
    if ( DEBUG ) {
      Serial.println( "Unable to access SPI Flash chip" );
    }
  }

  // Use the time since boot as a seed (I know, not great, but
  // the audio toolbox took away my analogRead)
  int seed = micros() % 32767;
  if ( DEBUG ) {
    Serial.print("Seed: ");
    Serial.println(seed);
  }
  randomSeed(seed);

  if ( DEBUG ) {
    Serial.println("Finished init");
  }
}

void loop() {

  if ( (fps > 24) && peak1.available() ) {

    // State machine
    switch ( state ) {

      // Wait until the mic picks up some sound
      case QUIET:
        if ( peak1.read() > SQUELCH_CUTOFF ) {
          timer = millis();
          state = QUIET_TO_LOUD;
        }
        break;

      // If sound continues, play sound effect
      case QUIET_TO_LOUD:
        if ( peak1.read() <= SQUELCH_CUTOFF ) {
          state = QUIET;
        } else {
          if ( millis() > timer + HYSTERESIS_TIME_ON ) {

            if ( DEBUG ) {
              Serial.println("ON");
            }

            // Turn on amp, play sound, turn on mic
            digitalWrite(AMP_ENABLE, HIGH);
            if ( BEGIN_CLICK ) {
              playFile("click.raw");
            }
            mixer1.gain(0, BASS_GAIN_ON);
            mixer1.gain(1, TREBLE_GAIN_ON);

            // Go to next state
            state = LOUD;
          }
        }
        break;

      // Filter mic input and play it through speakers
      case LOUD:
        if ( peak1.read() <= SQUELCH_CUTOFF ) {
          timer = millis();
          state = LOUD_TO_QUIET;
        }
        break;

      // If no sound for a time, play click or burst
      case LOUD_TO_QUIET:
        if ( peak1.read() > SQUELCH_CUTOFF ) {
          state = LOUD;
        } else {
          if ( millis() > timer + HYSTERESIS_TIME_OFF ) {

            if ( DEBUG ) {
              Serial.println("OFF");
            }

            // Play a random sound
            if ( END_SOUND ) {
              if ( random(2) ) {
                playFile("click.raw");
              } else {
                playFile("break.raw");
              }
            }

            // Turn off mic and amp
            digitalWrite(AMP_ENABLE, LOW);
            mixer1.gain(0, BASS_GAIN_OFF);
            mixer1.gain(1, TREBLE_GAIN_OFF);
            state = QUIET;
          }
        }
        break;

      // You really shouldn't get here
      default:
        break;
    }
  }
}

// Play a sound clip from serial flash
void playFile( const char* filename ) {

  if ( DEBUG ) {
    Serial.print("Playing file: ");
    Serial.print(filename);
  }

  // Start playing the file
  playFlashRaw1.play(filename);

  // A brief delay for the library read info
  delay(5);

  // Wait for the file to finish playing
  while ( playFlashRaw1.isPlaying() );

  if ( DEBUG ) {
    Serial.println("...done");
  }
}

Make sure the board has the following settings:

  • Board: Teensy 3.2 / 3.1
  • USB Type: Serial
  • CPU Speed: 96 MHz optimized (overclock)
  • Port: <Your Teensy’s Port>

Upload the Vox Imperium to the Teensy

Upload the sketch to the Teensy, and you’re ready to join the Imperial Army!

Run It!

Whenever you speak into the microphone, you’ll hear a click followed by a nasal version of your voice. When you stop talking, the Teensy will play a click or a static burst. You can disable the initial click by changing BEGIN_CLICK to false, and you can disable the ending sound by changing END_SOUND to false.

You can also plug a LiPo battery into the Power Cell to power the whole contraption.

Powering the Vox Imperium off a battery

Resources and Going Further

This project is meant to be hacked! Try changing some of the variables in the Parameters section of the code to see if you can get the voice to sound the way you want. You can also import the block diagram into the Audio System Design Tool by copying in everything before the // GUItool: end automatically generated code line and clicking Import in the Audio System Design Tool. Add some new blocks and really distort your voice!

Here’s an example of the project wired into a Scout Trooper helmet:

Project Resources:

For more fun audio projects, check out these tutorials:

RN-52 Bluetooth Hookup Guide

A hookup guide to get you started with the RN-52 Audio Bluetooth Module Breakout Board.

Sound Detector Hookup Guide

The Sound Detector is a microphone with a binary output. This guide explains how it works and how you can use it in your projects.

MP3 Trigger Hookup Guide V24

Incorporate sound into your next project easily with the MP3 Trigger.
New!

Vox Imperium: Stormtrooper Voice Changer

Add some flair to your buckethead uniform by changing your voice. By using a Teensy 3.2 and Prop Shield, you can remove the bass from your voice and add the requisite clicks and static bursts. Now you too can exclaim how these aren't the droids you're looking for.

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

TEMT6000 Ambient Light Sensor Hookup Guide

$
0
0

TEMT6000 Ambient Light Sensor Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

Light sensors have all sorts of practical uses in the modern era, most notably in devices with auto-brightness for their screens and in digital cameras to adjust exposure. With the Ambient Light Sensor Breakout, it’s be a breeze to interface with the TEMT6000 Light Sensor so you can bring the ability to detect light levels to any project.

SparkFun Ambient Light Sensor Breakout - TEMT6000

BOB-08688
$4.95
3

As the name suggests, the TEMT6000 Light Sensor will detect the brightness of its surroundings. While there are many properties of light that can help us categorize its brightness, the TEMT6000 measures illuminance (measured in lux (lx), often denoted Ev). Don’t worry if illuminance is new to you though, the TEMT6000 is very intuitive to use: brighter = more current, darker = less current.

In this guide, we’ll show you how to quickly get the ambient light sensor breakout up and running, then discuss some of the more technical details of how it functions. After that, we’ll show you how to use it to make a practical DIY nightlight!

Required Materials

Here’s what you’ll need to follow along with this guide:

Suggested Reading

  • Check out our Light Tutorial for more information on the technical properties of light. An intuitive understanding of light should be enough to make use of the TEMT6000, but, if you’re looking for more precise applications, this is worth the read.
  • This sensor is a phototransistor. Knowing how transistors work will be helpful in using the TEMT6000.
  • A voltage divider circuit is used to create a usable signal from the light sensor for a microcontroller. A basic understanding of voltage dividers is recommended.
  • To read the voltage coming from the voltage diverer circuit, an Analog to Digital Converter (ADC) will be necessary. This tutorial will show how to read the voltage on the ADC found on an Arduino microcontroller.
  • We recommend soldering some male header-pins to your TEMT6000 breakout to make it easier to use, so be sure to read our Soldering Tutorial for details on good soldering practice.
  • Knowing more about the TEMT6000 itself couldn’t hurt, so here’s a link to its datasheet.

Hardware Overview

As you can see from the image below, the TEMT6000 is about as simple as it gets when it comes to breakout boards. The three pins broken out are labeled on the top of the board.

breakout

The function of each pin can be found in the table below.

SymbolDescription
SIGOutput Voltage from the divider circuit
GNDGND (0V)
VCCCollector Voltage (should not exceed 6V)

Being a phototransistor, this sensor acts just like any other NPN transistor– the greater the incoming light on the Base, the the more current that can flow from the Collector to the Emitter. Only light that falls within the visible spectrum (390–700 nm) will alter the Base. Infrared, ultraviolet, or any other light we can’t directly see will have no effect on the sensor.

This sensor can handle voltages from both 5V and 3.3V devices.

To make taking light measurements as easy as possible, this sensor has been designed into a voltage divider circuit. The TEMT600 acts as one of the resistors in the divider, and, as the light hitting it changes, so too does the voltage on the SIG pin. To read that voltage, simply connect the SIG pin on the TEMT6000 to any analog to digital conversion pin on your microcontroller.

schematic

The TEMT6000 Breakout schematic.

The voltage value returned from the SIG pin will vary depending on what voltage is being used to power the sensor and depending on the resolution of your ADC.

Hardware Assembly

First, let’s fire up our light sensor and start collecting readings from it.

We recommend soldering male header-pins to the breakout to make it simpler to prototype with:

headers

The rest is just plugging parts into the RedBoard. Start by taking any basic LED of your preferred color and placing its anode leg (the long leg) into a pin whose label is followed by a ~. This mark on the RedBoard means the pin supports pulse-width modulation (PWM), which is just a technical way of saying we can control the voltage output of the pin digitally; in this case it lets us control the apparent brightness of our LED. We want this because our LED is going to show us the relative brightness of the world through the eyes of our TEMT6000. If you’re using a different board, be sure to read its documentation closely to see which of its pins support PWM. Place the other leg into ground (GND).

We used pin 11 on the RedBoard because it is the PWM pin closest to a ground pin. Thus, we didn’t have to deform our LED’s legs too much. This is the pin we’ll be using in the sample code, so be sure to modify that constant if you’re using a different physical pin.

Next comes the light sensor breakout. Start by connecting the female ends of some male-to-female jumper cables to the pins we soldered to it earlier. Connect VCC on the sensor to the 5V pin on the RedBoard, GND to GND, and SIG to any analog pin (we’ll be using A0 in the sample code). Use the table below to aid in wiring.

TEMT6000 PinArduino Pin
SIGA0
GNDGND
VCC5V

Here’s a diagram of how the circuit should look:

Fritzing Diagram

Programming

Now we’re finished with the hookup, it’s time to upload some.

Note: This example assumes you are using the latest version of the Arduino IDE on your desktop. If this is your first time using Arduino, please review our tutorial on installing the Arduino IDE. If you have not previously installed an Arduino library, please check out our installation guide.

Using the mini-b USB cable, hook the RedBoard up to a computer with the Arduino IDE installed. Select the appropriate COM port, select Sparkfun RedBoard as your target device, and then upload the following code:

language:c
#define LEDPIN 11         //LED brightness (PWM) writing
#define LIGHTSENSORPIN A0 //Ambient light sensor reading

void setup() {
  pinMode(LIGHTSENSORPIN,  INPUT);
  pinMode(LEDPIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  float reading = analogRead(LIGHTSENSORPIN); //Read light level
  float square_ratio = reading / 1023.0;      //Get percent of maximum value (1023)
  square_ratio = pow(square_ratio, 2.0);      //Square to make response more obvious

  analogWrite(LEDPIN, 255.0 * square_ratio);  //Adjust LED brightness relatively
  Serial.println(reading);                    //Display reading in serial monitor
}

Once everything’s uploaded, your LED should respond to the relative brightness that’s exposed to the TEMT6000. Here’s how the end result should look:

action GIF

Try oscillating the TEMT6000 towards the RedBoard’s green “ON” LED to see the change.

How Light Detection Works

Now that our sensor is working, let’s take a more in-depth look at what is going on inside the senor. As mentioned earlier, the TEMT6000 measures illuminance. If you’re unfamiliar with illuminance, it is a measure of the total quantity of visible light emitted by a source (referred to as luminous flux, measured in lumens (lm)) divided by an area in square meters. More notationally, 1 lx = 1 lm/m². Along with these, there are other properties of light that are unfortunately all named using the same Latin root for light, so it can be hard to keep them straight. Here’s a diagram to hopefully elucidate the differences:

light diagram

Diagram depicting the nuances between the various measurements of light.

Why does the TEMT6000 measure illuminance? In most practices, measuring the intensity of light without factoring in distance is very difficult, and puzzled early astronomers for a long time. In short, there is apparent magnitude (how bright a source appears) and absolute magnitude (how bright the source actually is). Two sources of different absolute magnitudes can have the same apparent magnitude depending on their distance from the observer.

For example, if you have a bright source far away and a dim source very close, they can appear to have the same brightness because the brighter source’s light will have to dissipate over a larger volume. This is why the sensor will read a smaller value if you move the same source of light farther away from it, essentially increasing the amount of space that the same amount of light has to fill between the source and the sensor (i.e. reducing the illuminance, as you’re dividing by a larger surface area of the light-sphere generated by the source).

Here is a graphical relationship between the current (in µA) and illuminance of the immediate vicinity perceived by the sensor:

sensor graph

Found in the TEMT6000 datasheet.

The TEMT6000 only recognizes light with wavelengths in the range of 390–700 nm, which roughly covers the entire spectrum of visible light. In other words, this won’t pick up infrared, ultraviolet, or any other light we can’t directly see.

Here’s a table of the typical illuminance from common sources of visible light:

illuminance

Lux Wikipedia article / CC BY

Now that we understand the TEMT6000 a little better, let’s use it in something more interesting and build ourselves a night light that turns itself on and off!

Example Project: Night Light

Required Materials

We’ll be reusing a lot of parts from before. In fact, the only difference is we’re upping the ante and using an RGB LED instead of a single color LED! Nevertheless, here’s a list of everything you’ll need:

Hookup

Since we’re reusing a lot of the same parts, they’re mostly going to occupy the same pins on the RedBoard: VCC on the breakout should connect to 5V on the RedBoard, GND to GND, and SIG to A0.

TEMT6000 PinArduino Pin
SIGA0
GNDGND
VCC5V

The main difference is now we have an RGB LED that has twice as many legs, but the idea is still the same. The longest leg on a common anode RGB LED is going to be the pin that goes to the GND pin. Most Arduino boards have a group of three consecutive PWM pins, and these happen to be pretty close to a GND. If the legs on your LED aren’t bent too bad, you should be able to see which is the second longest leg—that’s the cathode for the red LED, and that should go to pin 9. Plug the remaining two legs into pins 10 and 11 in the orientation they appear to go in easiest. Use the image below, if you can’t tell the difference between the legs.

RGB Polarity

This table should clarify, which pins are connected.

RGB LED PinArduino Pin
Red CathodePin D9
Common AnodeGND
Green CathodePin D10
Blue CathodePin D11

Here’s what the setup should look like once everything is plugged in:

Fritzing diagram

Programming

The code for this one is going to look a little different. The challenge is that we want to cycle through all the colors without being stuck in a loop and unable to read light values until the loop is done. The way around this is to use a function that will take a variable that counts and returns a color based on how far that variable has counted. This way, for every “count” (cycle of the loop) we have time to stop and check our TEMT6000 for a reading. There are some other little tricks that are explained in the comments.

The drill for uploading the code is the same as before.

language:c
#define LS_PIN A0  //Light Sensor pin
#define R_PIN  9   //Red pin
#define G_PIN  10  //Green pin
#define B_PIN  11  //Blue pin
#define POWER  4   /* Power to raise the ratio of read-value to largest read-value.
                    * Higher is less likely to be on during the day,
                    * but too high and it may not turn on once it's night.*/

#define TIME  500 /* The amount of milliseconds before taking a step through the color function.
                   * Higher values = slower transitions between colors.*/

uint16_t  _max =  0;  //Holds the largest brightness reading so far.
byte      count = 0;  //Keeps track of where we are on the color spectrum
float     ratio = 0;  //Stores the ratio of current brightness to largest recorded brightness.

void setup() {
  pinMode(LS_PIN,  INPUT);  //Reading in
  pinMode(R_PIN,  OUTPUT);  //Writing out*
  pinMode(G_PIN,  OUTPUT);  //*
  pinMode(B_PIN,  OUTPUT);  //*
  Serial.begin(9600);
}

void loop() {
  float reading = analogRead(LS_PIN); //Take brightness reading
  if (reading > _max) _max = reading; //See if it's the brightest so far

  /* Calculate the ratio between the reading and the max, raise the power, and average it with
   * the last reading to get our ratio but minimize flickering. */
  ratio = (ratio + pow(1.0 - reading / float(_max), POWER)) / 2.0;
  /* We're subtracting the ratio from 1 because we want brighter readings to result
   * in a dimmer display of colors, and smaller readings to result in brighter displays. */

  //Write the color from our spot in the spectrum at the relative brightness to the LED
  analogWrite(R_PIN, Rainbow(count + 170) * ratio);
  analogWrite(G_PIN, Rainbow(count + 85)  * ratio);
  analogWrite(B_PIN, Rainbow(count)       * ratio);
  /* Each color has the same pattern of increasing and decreasing brightness, just not synchronously.
   * We can reuse the same function and carefully offset each color to make sure we get to see all
   * the colors.*/


  if (!(millis() % TIME)) count++;
  /* There's a lot going on in this concise use of syntax. Essentially, whenever millis() (the
   * amount of milliseconds since the arduino has been on) is evenjly divisble by TIME (i.e.
   * TIME milliseconds have passed) then the modulo operator (%) will return 0, which evaluates
   * as FALSE. The ! in front of the expression means invert, so this means every TIME milliseconds,
   * the expression will return TRUE. If it's TRUE, we take a step through the color spectrum. Bytes
   * can only count to 255 before they reset back to 0. The overflow of "count" is a passive way to
   * take us back to the start of the color spectrum without having to explicitly set "count" to 0.*/
}

/* Returns an appropriate value in 0-255 for a given value in 0-255. With good timing, it can be used
 * to cycle through the entire color spectrum. */
byte Rainbow(byte i) {
  if (i > 213) return i * 6;
  if (i > 127) return 0;
  if (i > 85)  return 255 - i * 6;
  return 255;
}

Once the code is uploaded, you should have yourself an automatic mood night light! Here’s ours in action:

action GIF

Resources and Going Further

  • The TEMT6000 only detects the amalgamated presence of light with wavelengths in the range of 390–700 nm, but we’ve got a plethora of different light sensing options:
    • The TSL2561 Luminosity Sensor Breakout is an integrated sensor that can detect both visible light and infrared light.
    • The ISL29125 RGB Light Sensor can detect light that is specifically red, green, blue, or any combination thereof.
    • The ML8511 UV Sensor Breakout works similarly to the TEMT6000, but responds to ultraviolet light instead of visible light.
    • The Mini Photocell is a very small alternative to the TEMT6000, however it is a photo resistor (a resistor that changes resistance based on the presence of light) instead of a phototransistor.
  • If you plan on using the nightlight indefinitely, an energy-conscious suggestion would be to integrate a Wake on Shake. The Arduino will constantly be running and checking if its dark, which can use up a lot of energy over time. A Wake on Shake would make the current draw negligible until you bumped the circuit. This way you can easily activate the light in the dark if you need it, and would practically be off otherwise.
  • Want a night light for outdoors? The Sunny Buddy makes keeping a battery charged with solar energy easy. Your night light could store energy during the day, and light the way for you at night! Of course you may want to also invest in a transparent plastic case to keep the elements out.

Or, you can check out these other great light-based tutorials.

APDS-9960 RGB and Gesture Sensor Hookup Guide

Getting started guide for the Avago APDS-9960 color, proximity, and gesture sensor.

FLIR Lepton Hookup Guide

See the invisible world of infrared radiation using the FLIR Dev Kit and Raspberry Pi.

Boss Alarm

Build a Boss Alarm that alerts you of anyone walking into your office and automatically changes your computer screen.

Sensor Kit Resource Hub

An overview of each component in the SparkFun Sensor Kit, plus links to tutorials and other resources you'll need to hook them up.

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

ESP32 Thing Hookup Guide

$
0
0

ESP32 Thing Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The SparkFun ESP32 Thing is a comprehensive development platform for Espressif’s ESP32, their super-charged version of the popular ESP8266. Like the 8266, the ESP32 is a WiFi-compatible microcontroller, but to that it adds support for Bluetooth low-energy (i.e BLE, BT4.0, Bluetooth Smart), and nearly 30 I/O pins. The ESP32’s power and versatility will help make it the foundation of IoT and connected projects for many years to come.

SparkFun ESP32 Thing

DEV-13907
$19.95

The SparkFun ESP32 Thing equips the ESP32 with everything necessary to program, run, and develop on the wonderchip. In addition to the WiFi/BLE SoC, the Thing includes an FTDI FT231x, which converts USB to serial, and allows your computer to program and communicate with the microcontroller. It also features a lithium-polymer (LiPo) battery charger, so your ESP32 project can be truly wireless. Additionally, the board includes a handful of LEDs and buttons to aid in your development.

Covered In This Tutorial

This hookup guide serves as a primer on all things ESP32 Thing. It documents hardware features of the board, including a handful of assembly tips. Then it will delve into firmware development – including demonstrating how to add ESP32 support to the popular Arduino IDE.

The tutorial is broken up into a handful of sections, which you can navigate through using the menu on the right. Those sections include:

Bill of Materials

The ESP32 Thing includes almost everything you’ll need to begin using and programming the WiFi/BT SoC. In fact, the only required extra is a Micro-B USB Cable. The ESP32 Thing’s USB interface can be used to both power and program the chip. Once you’re done programming the chip, a 5V Micro-B USB Wall Adapter can be used to power the board.

USB microB Cable - 6 Foot

CAB-10215
$4.95
7
SparkFun Cerberus USB Cable - 6ft

CAB-12016
$6.97
9
Wall Adapter Power Supply - 5V DC 2A (USB Micro-B)

TOL-12890
$5.95
11
USB Micro-B Cable - 6"

CAB-13244
$1.95
3

As an alternative power source, the ESP32 Thing includes support for single-cell lithium-polymer (LiPo) batteries, which plug into the board’s white 2-pin JST connector. LiPo’s are perfect for projects on-the-go, or those that just need a little extra umph. The board includes a LiPo charger– the rechargeable batteries can be juiced back up by plugging the Thing into a 5V USB source.

Lithium Ion Battery - 400mAh

PRT-13851
$4.95
Lithium Ion Battery - 2000mAh

PRT-08483
$12.95
25
Lithium Ion Battery - 850mAh

PRT-00341
11
Lithium Ion Battery - 1Ah

PRT-13813
$9.95
3

Finally, to connect the ESP32’s 28 I/O pins to external components, you’ll need to do some soldering. Soldering tools, including an iron and solder, are a must for any electronics workbench. And either headers or wire are our recommended mate for soldering into the Thing’s pins.

Break Away Headers - Straight

PRT-00116
$1.5
20
Hook-Up Wire - Assortment (Stranded, 22 AWG)

PRT-11375
$16.95
11
Solder Lead Free - 100-gram Spool

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

TOL-09507
$9.95
5

Suggested Reading

It may look intimidating, but the ESP32 Thing – especially when you take advantage of its Arduino compatibility – is a perfect IoT foundation for electronics users of all experience levels. There are, however, a few concepts you should be familiar with before venturing further into this tutorial. If any of the concepts below sound foreign to you, consider reading through that tutorial first:

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.

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

How to Power a Project

A tutorial to help figure out the power requirements of your project.

What is an Arduino?

What is this 'Arduino' thing anyway?

Hardware Overview

Espressif’s ESP32 is one of the most unique microcontrollers on the market. Its laundry list of features include:

  • Dual-core Tensilica LX6 microprocessor
  • Up to 240MHz clock frequency
  • 520kB internal SRAM
  • Integrated 802.11 BGN WiFi transceiver
  • Integrated dual-mode Bluetooth (classic and BLE)
  • 2.2 to 3.6V operating range
  • 2.5 µA deep sleep current
  • 32 GPIO
  • 10-electrode capacitive touch support
  • Hardware accelerated encryption (AES, SHA2, ECC, RSA-4096)

The ESP32 Thing is designed to surround the ESP32 with everything necessary to run and program the microcontroller, plus a few extra goodies to take advantage of the chip’s unique features.

Annotated top diagram

Peripherals and I/O

The ESP32 features your standard fare of hardware peripherals, including:

And, thanks to the chip’s pin multiplexing feature, those peripherals can be connected to just about any of the 28 broken out I/O pins. That means you decide which pins are RX, TX, MISO, MOSI, SCLK, SDA, SCL, etc.

There are, however, a few hardware features – namely the ADC and DAC – which are assigned static pins. The graphical reference below helps demonstrate where you can find those peripherals (click to embiggen!).

Graphical datasheet

Click the image for a closer look.

One I2C, two of the UART interfaces, and one of the SPI interfaces can be assigned to any pin your project requires.

Input Only Pins: 34-39

Pins 34, 35, 36, 37, 38 and 39 cannot be configured as outputs, but they can be used as either digital inputs, analog inputs, or for other unique purposes. Also note that they do not have internal pull-up or pull-down resistors, like the other I/O pins.

GPIO pins 36-39 are an integral part of the ultra low noise pre-amplifier for the ADC – they are wired up to 270pF capacitors, which help to configure the sampling time and noise of the pre-amp.

Schematic close up of pins 34-39

From the ESP32 Thing Schematic: GPIO 36-39 are tied together with caps. Those and pins 34 and 35 are input only!

Powering the ESP32 Thing

The two main power inputs to the ESP32 Thing are USB and a single-cell lithium-polymer (LiPo) battery. If both USB and the LiPo are plugged into the board, the onboard charge controller will charge the LiPo battery at a rate of up to 500mA.

The ESP32's operating voltage range is 2.2 to 3.6V. Under normal operation the ESP32 Thing will power the chip at 3.3V. The I/O pins are not 5V-tolerant! If you interface the board with 5V (or higher) components, you'll need to do some level shifting.

The 3.3V regulator on the ESP32 Thing can reliably supply up to 600mA, which should be more than enough overhead for most projects. The ESP32 can pull as much as 250mA during RF transmissions, but we’ve generally measured it to consume around 150mA – even while actively transmitting over WiFi. The output of the regulator is also broken out to the sides of the board – the pins labeled “3V3.” These pins can be used to supply external components.

ESP32 power inputs/outputs

In addition to USB and battery connectors, the VBAT, and VUSB pins are all broken out to both sides of the board. These pins can be used as an alternative supply input to the Thing. The maximum, allowable voltage input to VUSB is 6V, and VBAT should not be connected to anything other than a LiPo battery. Alternatively, if you have a regulated voltage source between 2.2V and 3.6V, the “3V3” lines can be used to directly supply the ESP32 and its peripherals.

Assembly Tips

The ESP32 Thing ships without anything soldered into the header pins – ensuring that you can mold the board to best fit your project. To use the chip’s pins you’ll need to solder something to the I/O and power rail vias broken out to either side of the board.

New to soldering? Check out our Through-Hole Soldering Tutorial for a quick introduction!

What you solder to the ESP32 Thing’s I/O pins is completely up to you. The header rows are breadboard-compatible, so you may want to solder male headers in. (Mildly satisfying: the ESP32 Thing’s pair of 20-pin headers means you can get the most out of our 40-pin header strips.)

ESP32 Thing with male headers soldered

Then plug it into the breadboard, hanging the USB and LiPo connectors off the end, and start wiring!

ESP32 Thing breadboard action shot

All those wires and components, and there are still plenty of GPIO left to use!

Alternatively, female headers (you may need two separate strips to solder all 40 pins), right-angle headers, or stranded wire are all good options, depending on your project’s needs.

Installing the ESP32 Arduino Core

The pair of Tensilica cores in the ESP32 are Xtensa-based – not your standard ARM or AVR. Fortunately, there is still a GNU compiler available for the ESP32, which opens up a a world of possible development environment (IDE) set ups! The rest of this tutorial covers setting up the Arduino IDE with ESP32 support, and documents a few simple example sketches to help get your WiFi/BLE microcontroller off the ground.

In abstracting away a lot of the complicated overhead, the Arduino IDE for the ESP32 also eliminates access to some of the SoC's more advanced features. If you'd like to try your hand at setting up a more advanced toolchain for the ESP32, we recommend checking out Espressif's esp-idf GitHub repository. The esp-idf – short for IoT Development Framework – is Espressif's software development kit (SDK) for the ESP32.

Installing the ESP32 Core

Espressif’s official ESP32 Arduino core is hosted here on GitHub. They don’t have an Arduino board manager install yet (it should be coming soon), but they do have a simple set of installation directions to help.

Python Required

esptool– Espressif's bootloader utility program, used to upload code to the ESP32 – is a Python script. That's great because it's generally OS-agnostic, but it does require you to have Python installed on your computer. Python 2.7 to be more exact.

If you don't have Python installed (Mac and Linux machines should come stock with Python), visit python.org to download it – make sure you get 2.7.x, not 3.x! Then follow along with the installer's instructions to install it on your system.

One more note: you'll need to add Python's base directory to your PATH environment variable. For help with that, check out this link.

Clone or Download the Core

To install the ESP32 board definitions, you’ll need download the contents of the esp32-arduino repository, and place them in a “hardware/espressif/esp32” directory in your Arduino sketchbook directory. You can either download those files using the git command line tool, or by downloading them from GitHub.

Alternatively, these files can be installed in your Arduino’s base directory. On Windows, that may be C:/Program Files (x86)/Arduino/hardware and on Mac that may be /Applications/Arduino.app/Contents/Java/hardware.

If you have git, open a terminal, navigate to your Arduino sketchbook, and type:

mkdir hardware
cd hardware
mkdir espressif
cd espressif
git clone https://github.com/espressif/arduino-esp32.git esp32

Those commands will make a “hardware” and “espressif” directories, then download the arduino-esp32 GitHub repository into an “esp32” folder.

Example terminal commands

If you don’t have git, click here to download the core (or click “Download” >“Download ZIP” on the GitHub page), and unzip it to an espressif/esp32 directory in your Arduino sketchbook.

Windows folder installation

“boards.txt”, “platform.txt”, and the cores, doc, tools, etc. folders should all live in the esp32 directory.

Install the Xtensa and ESP32 Tools

To compile code for the ESP32, you need the Xtensa GNU compiler collection (GCC) installed on your machine. The tools/get.py file, included with the ESP32 core, should be used to download and install these tools.

Using a terminal or command prompt, navigate to the tools folder in the esp32 folder you just downloaded. Then type:

python get.py

Alternatively, you can double-click the script in your file explorer to run it.

The “get.py” python script will download the Xtensa GNU tools and the ESP32 software development kit (SDK), and unzip them to the proper location. You should see a few new folders in the “tools” directory, including “sdk” and “xtensa-esp32-elf” once it’s done.

With the ESP32 Arduino core installed, you’re ready to begin programming. If you haven’t already, plug the ESP32 Thing into your computer using a micro-B USB cable.

ESP32 Thing plugged into breadboard

FTDI Drivers

If you've never connected an FTDI device to your computer before, you may need to install drivers for the USB-to-serial converter. Check out our How to Install FTDI Drivers tutorial for help with the installation.

Once the board is plugged in (and drivers installed), it should be assigned a unique port identifier. On Windows machines, this will be something like “COM#”, and on Macs or Linux computers it will come in the form of “/dev/tty.usbserial-XXXXXX.”

Select the Board and Port

Once the ESP32 Arduino core is installed, you should see an “ESP32 Dev Module” option under your “Tools” >“Board” menu. Select that.

Arduino board select

Then select your ESP32 Thing’s serial port under the “Tools” >“Port” menu.

Arduino port select

You can also select the “Upload Speed”. 921600 baud – the fastest selectable rate – will get the code loaded onto your ESP32 the fastest, but may fail to upload once-in-a-while. (It’s still way worth it for the speed increase!)

Loading Blink

To make sure your toolchain and board are properly set up, we’ll upload the simplest of sketches – Blink! The LED attached to GPIO 5 is perfect for this test. Plus, with the ESP32 attached to your computer, it’s a good time to test out serial. Copy and paste the example sketch below, into a fresh Arduino sketch:

language:c
int ledPin = 5;

void setup()
{
    pinMode(ledPin, OUTPUT);
    Serial.begin(115200);
}

void loop()
{
    Serial.println("Hello, world!");
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
}

With everything setup correctly, upload the code! Once the code finishes transferring, open the serial monitor and set the baud rate to 115200. You should see “Hello, world”’s begin to fly by.

If the blue LED remains dimly lit, it's probably still sitting in the bootloader. After uploading a sketch, you may need to tap the RST button to get your ESP32 Thing to begin running the sketch.

Example serial port output

You may also notice that when the ESP32 boots up it prints out a long sequence of debug messages. These are emitted every time the chip resets – always at 115200 baud.

Arduino Example: WiFi

The ESP32 Arduino core includes a handful of WiFi examples, which demonstrate everything from scanning for nearby networks to sending data to data.sparkfun.com. You can find the examples under the File>Examples>WiFi menu.

Here’s another example using the WiFi library, which demonstrates how to connect to a nearby WiFi network and poll a remote domain (http://example.com/) as a client:

language:c
#include <WiFi.h>

// WiFi network name and password:
const char * networkName = "YOUR_NETWORK_HERE";
const char * networkPswd = "YOUR_PASSWORD_HERE";

// Internet domain to request from:
const char * hostDomain = "example.com";
const int hostPort = 80;

const int BUTTON_PIN = 0;
const int LED_PIN = 5;

void setup()
{
  // Initilize hardware:
  Serial.begin(115200);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);

  // Connect to the WiFi network (see function below loop)
  connectToWiFi(networkName, networkPswd);

  digitalWrite(LED_PIN, LOW); // LED off
  Serial.print("Press button 0 to connect to ");
  Serial.println(hostDomain);
}

void loop()
{
  if (digitalRead(BUTTON_PIN) == LOW)
  { // Check if button has been pressed
    while (digitalRead(BUTTON_PIN) == LOW)
      ; // Wait for button to be released

    digitalWrite(LED_PIN, HIGH); // Turn on LED
    requestURL(hostDomain, hostPort); // Connect to server
    digitalWrite(LED_PIN, LOW); // Turn off LED
  }
}

void connectToWiFi(const char * ssid, const char * pwd)
{
  int ledState = 0;

  printLine();
  Serial.println("Connecting to WiFi network: " + String(ssid));

  WiFi.begin(ssid, pwd);

  while (WiFi.status() != WL_CONNECTED)
  {
    // Blink LED while we're connecting:
    digitalWrite(LED_PIN, ledState);
    ledState = (ledState + 1) % 2; // Flip ledState
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi connected!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void requestURL(const char * host, uint8_t port)
{
  printLine();
  Serial.println("Connecting to domain: " + String(host));

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  if (!client.connect(host, port))
  {
    Serial.println("connection failed");
    return;
  }
  Serial.println("Connected!");
  printLine();

  // This will send the request to the server
  client.print((String)"GET / HTTP/1.1\r\n" +"Host: " + String(host) + "\r\n" +"Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0)
  {
    if (millis() - timeout > 5000)
    {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  // Read all the lines of the reply from server and print them to Serial
  while (client.available())
  {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }

  Serial.println();
  Serial.println("closing connection");
  client.stop();
}

void printLine()
{
  Serial.println();
  for (int i=0; i<30; i++)
    Serial.print("-");
  Serial.println();
}

Make sure you fill in the networkName and networkPswd variables with the name (SSID) and password of your WiFi network! Once you’ve done that and uploaded the code, open your serial monitor.

WiFi example serial terminal output

After your ESP32 connects to the WiFi network, it will wait for you to press the “0” button. Tapping that will cause the ESP32 to make an HTTP request to example.com. You should see a string of HTTP headers and HTML similar to the screenshot above.

Using the Arduino Addon

Before we leave you, here are a few tips, tricks, and gotchya’s to look out for while you’re using the ESP32 Arduino core.

Pin Mapping

The pin number you use for digitalWrite([pin], [value]) or digitalRead([pin]) should match those printed onto the board. You can also reference the graphical datasheet, if the tiny numbers are a strain on the eyes.

Both I2C interfaces are supported by the Wire library. The SDA and SCL pins are assigned, by default, to pins 21 and 22.

I2C SignalESP32 Pin
SDA21
SCL22

And the SPI library should support all three possible SPI interfaces. By default, here are the pin mappings for those interfaces:

SPI SignalESP32 Pin
MOSI23
MISO19
SCLK18
SS5

In addition to SPI and I2C, the Arduino core also supports interrupts on any pin with the attachInterrupt() function.

Not Yet Implemented

The Arduino board definitions for the ESP32 are still a work in progress. There are a handful of peripherals and features that have yet to be implemented, including:

  • Bluetooth
  • Analog Input (analogRead([pin]))
  • Analog Ouptut (analogWrite([pin], [value]))
  • WiFi Server and WiFI UDP
  • Real-Time Clock
  • Touch-controller interface

These peripherals are available (if, also, still in their infancy) in the IoT Development Framework for the ESP32. If your application requires Bluetooth, analog input, or any of the features above, consider giving the ESP-IDF a try!

Resources & Going Further

The ESP32 Thing’s design is open-source! You can download, view, and modify the Eagle files (PCB design), checkout the schematic, or suggest revisions on the ESP32 Thing GitHub repository.

The ESP32 is still in its infancy, but resources are popping up all over the place for the chip. Check out some of these links for more information, documentation, and examples.

Going Further

  • ESP-IDF – IoT Development Framework– If you want to take your development environment up a step from Arduino, this should be your first step into ESP32 software development. Some notes on the IDF:
    • The IDF is well-documented. Check out the set up guides (for Windows, Mac or Linux) for help getting your environment set up. For help with the API’s and data structures, check out esp32.info.
    • There are a handful of example applications, including a BLE Advertising example, which works as a proof-of-concept for the ESP32’s Bluetooth support.
    • Use the ESP-IDF project template, once you’re ready to start creating applications of your own.
  • Blynk– Blynk allows you to control IoT development boards with an easily configurable iOS/Android app. And it already supports the ESP32!

If you need some project inspiration, we’ve got plenty of tutorials to stir your mind. Check out some of these IoT-focused tutorials and get making!

LED Cloud-Connected Cloud

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

Photon Remote Temperature Sensor

Learn how to build your own Internet-connect, solar-powered temperature collection station using the Photon from Particle.

ESP8266 Powered Propane Poofer

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

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


PiRetrocade Assembly Guide

$
0
0

PiRetrocade Assembly Guide a learn.sparkfun.com tutorial

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

PiRetrocade

Pew-Pew. Got you. The Raspberry Pi 3 has been the latest and greatest in the line of Raspberry Pi Single Board Computers. Need some inspiration for your next Raspberry Pi project? How about a retro arcade gaming kit?

SparkFun PiRetrocade

KIT-14007
$39.95

Kit Includes:

  • 5x Arcade Buttons
  • 1x Joystick
  • 1x SD Card with Porta Pi
  • 20x Female quick disconnects
  • 20x 6-inch M-F Jumper Wires
  • 1x Utility Knife
  • 4x Screws and four nuts

Covered in This Tutorial

This guide aims to get you up and running with your PiRetrocade in no time. Thanks to the included SD Card with the emulation image installed, setup is quick and requires no programming! This guide in conjunction with the video below will guide you through the assembly of the PiRetrocade, so you can get gaming.

Materials Required

The following is additional supplies you’ll need that are not include in the PiRetrocade Kit.

Suggested Reading

Before building your PiRetrocade, you may want to read some of the tutorials below if you’re unfamiliar with the Raspberry Pi. You do not need to have any previous experience with Raspberry Pi to build and use this kit.

SD Cards and Writing Images

How to upload images to an SD card for Raspberry Pi, PCDuino, or your favorite SBC.

Raspberry gPIo

How to use either Python or C++ to drive the I/O lines on a Raspberry Pi.

Preassembled 40-pin Pi Wedge Hookup Guide

Using the Preassembled Pi Wedge to prototype with the Raspberry Pi B+.

Raspberry Pi 3 Starter Kit Hookup Guide

Guide for getting going with the Raspberry Pi 3 starter kit

Kit Assembly

For step-by-step instructions on how to assemble the PiRetrocade, watch the video below. Then read on for more detailed instructions.

Hardware

This project really boils down to five buttons and a joy stick connected to the GPIO pins on the Raspberry Pi 3 and an SD card fully loaded with arcade software. Let’s get started building this controller. Insert the SD Card into the Raspberry Pi . On top of the box, you will find blue prints for your controller layout. Use the provided hobby knife to cut holes labeled “Cut”.

Buttons

Remove the switches from the arcade buttons. Unscrew the nut, and feed a button through each hole and secure the button to the box with the nut. Once they are all in place, replace the switches.

alt text

alt text

The bottom pin labeled “COM” for common or ground on the switch is ground. The single wiring harness will attach to the bottom pin on the short right side of the switch. It is labeled “NO” for normally open.

Joystick

First, figure out which switch corresponds to Up, Down, Left and Right. To do this easily, you can unscrew the bottom metal plate like this:

alt text

The switches will be exposed and you can test each direction. With the orientation shown holding the joystick to the left produces this result:

alt text

I labeled that top right switch “Left” which corresponds to GPIO Pin 7. Continue the same process for each direction and replace the bottom cover with the four screws along the outer edge.

alt text

Once you have the orientation, unscrew the red ball from the top of the joystick handle, and remove the black washer as well. Unscrew the top metal plate, and feed the joystick from under the box lid. Secure the joystick by screwing the metal plate on top of the box. You’ll want to mark where those holes are and pre-cut a hole for each screw as well. Replace the black washer, and replace the red ball.

Wiring

You may have noticed some 6" strands of wire and 20 female quick disconnects. You will need a pair of crimpers or there may be a crimp tool on your wire strippers already. You will build two wiring harnesses for ground. One wiring harness will have five quick disconnects daisy chained together for the buttons, and the other will have four quick disconnects daisy chained together for each ground pin in the joystick. Then nine individual wiring harness for each button and direction on the joystick. The ground on the button switches are the lone tabs on the long side of the switch. The same goes for the joystick.

alt text

Single wiring harness with female end. You need nine of these.

alt text

Ground wiring harness for the joystick with female end. You need one.

alt text

_ Ground wiring harness for the buttons with female end. You need one._

In the video, each button and direction was labeled along with its corresponding GPIO on the box with marker. Below is a picture of the mapping. The individual wiring harnesses are attached on the tab that is labeled “NO” (Normally Open). It is also labeled pin 3 on the switch.

alt text

For the power, audio and monitor cables, cut three holes in the back of the box, and feed those cables through them. I’m using a set of powered speakers for audio. Close the box, and get ready to play.

alt text

Emulation Software

In the video above you saw how easy it was to get up and running on your gaming machine. Let’s take a look at what’s going on inside.

Besides powering the Pi and restarting the Pi after adding ROMs you will not have to do anything else to get started playing games. The Image on the SD card is called Porta Pi Aracde and is a collage of several programs compiled by Ryan Bates at Retro Built Games. The image contains RetroPie, Emulation Station, RetroArch and Retrogame.

Power the Pi, and connect a monitor through an HDMI cable. Once it boots up you should see the RetroPie home screen, then the Emulation Station home screen and then a menu which shows you the available system emulators and how many games you have in each emulator. Now is when you’ll want to get familiar with navigating through the menu and add your roms. You can fully navigate through the menus with your newly assembled gamepad, or you can use a keyboard.

A Little Background on the SD Card Image

RetroPie is backbone of your retro-gaming machine. It can be installed on top of an OS like Rasbian. We left off the OS so you can decide which one you’d like to add or if you need one at all.

If you decide to add an OS, you can exit the emulator, and enter the Linux GUI by pressing F4. This brings you to a terminal window, and typing the command sudo startx starts the GUI.

To get back to the emulator, log out of the Linux GUI, and type the command emulationstation in the terminal window.

Without Rasbian the only commands you need are the F4 key to enter terminal window and emulationstation to return to the emulator.

Emulation Station is the graphical front end that gets you easy access to your favorite retro games without a keyboard. Once you have built your controller, you will have all the buttons necessary to navigate through Emulation Station and play your legally obtained roms.

RetroArch exposes the functionality of a game or emulator. It is the front-end for libretro and can do things like raw video recording and netplay. It also allows for universal controls to be programmed – it currently is for this tutorial. This means that the controls set for ESC, Enter, Jump, Shoot, etc. are seen across all games in all emulators - you won’t have to set up your game pad every time you enter a new emulator.

Retrogame is a great tool which allows Raspberry PI GPIO-to-USB utility for emulators written by Phil Burgess for Adafruit. This is how the button mashing gets registered as keyboard presses. To change where the buttons are mapped to or to add more buttons head over to Retro Built Games .

Adding Roms

The easiest way to add roms is to use a USB Thumb Drive or SD Card with adapter. Format the USB drive to get a fresh drive. Add a folder called ‘retropie’, and insert it into your Raspberry Pi 3. Wait a few minutes, or look for the flashing light on your USB to stop.

Pull out the USB drive, and plug it back into your computer. The ‘retropie’ folder will now have three sub folders: ‘BIOS’, ‘Configs’ and ‘roms’. Save your roms into the appropriate folder within the ‘roms’ folder.

Put the USB drive back in the Pi, and wait once more for the file transfer to finish. The roms are automatically saved to the correct emulator folder. You now need to restart your Raspberry Pi.

Plug in a keyboard, and Hit F4 to exit emulation station. From the terminal window, type the command sudo reboot to restart your station. You should now see the menu expanded based on the roms you saved. Thus, if you added NES roms, there will now be an NES option in the menu. Instructions on obtaining roms is beyond th scope of this tutorial. You should only be adding legally sourced roms onto your Raspberry Pi gaming station.

Test

Once you have your buttons placed, the wiring finished and your roms installed, it is time to test your gamepad. Power your Raspberry Pi, and wait for the emulation station menu screen. Use the joystick to navigate through the different emulators. Button A will act as select or Enter in the menu, and B will act as a back button. The select button is escape for when you want to change games and get back to the main menu from within a game. From within a game A, B, & C will act as the normal fight and special buttons.

Audio Set Up

The simplest way to get audio for your arcade machine is to plug powered speakers into the audio jack. You can also change the settings in RetroPie. To use headphones, navigate to the RetroPie emulator and press A. Select Audio in the menu by pressing A again. Select option 2 to use headphones. select Option 3 to use HDMI. To get a portable solution-if you are making a cabinet, select option 4 and check out SparkFun’s Audio amplifier kit. Just be sure to tie ground from the amp kit to a ground pin.

Resources and Going Further

Go beyond the box, and customize your own arcade cabinet. Retro Built Games is a great resource for building arcade cabinets, navigating through RetroPie, EmulationStation, RetroArch and Retrogame, expanding roots to increase SD space, adding roms and much more. If you are having any trouble, the Forums on this site are excellent. There are also instructions for adding a player two, adding a coin acceptor, free plans for a MiniCade, and then random cool stuff like a Vending Machine and a folding dog ramp. Give this gaming maker some love.

alt text

Photo Courtesy of Ryan Bates at Retro Built Games

alt text

Photo Courtesy of Ryan Bates at Retro Built Games

A table top vending machine seems like a worthy investment.


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

LP55231 Breakout Board Hookup Guide

$
0
0

LP55231 Breakout Board Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The SparkFun LP55231 Breakout Board features Texas Instrument’s LP55231, a nine-channel, I2C LED controller. It drives LEDs using pulse-width-modulation, so it is well-suited for variable intensity and color mixing applications.

SparkFun LED Driver Breakout - LP55231

BOB-13884
$7.95

It’s intended for mobile device and automotive applications, offloading LED control operations from a host controller. It’s not meant to be blindingly bright, but it’s got a couple useful tricks up its sleeve.

  • First, there is an onboard charge-pump power supply, which allows it to drive LEDs with a forward voltage that’s higher than the power supply voltage. (Recall that the forward voltage of a White LED is right around 3.3V, blue is even higher).
  • Second, it has an LED offload engine. This is an LED-specific microcontroller, which allows it do LED operations without requiring assistance from the host microcontroller. It can independently perform LED operations like chases, blinks and fades.

The breakout board includes the chip, and adds three RGB LEDs, plus connection pads and configuration jumpers.

In this hookup guide, we’ll demonstrate the difference between the regular and offloaded modes. We’ll start with a simple application to illustrate using the LED driver under control of the host microcontroller, then move on to show the capabilities of the offload engines. The second example will be much more technical and will put your programming chops to the test.

Suggested Reading

Before embarking upon this guide, you may want to familiarize with any of the topics below.

Breakout Basics

The LP55231 Breakout is a self-contained solution for developing and deploying the LP55231. It includes the LP55231 LED controller IC, plus three RGB LEDs. It also sports pads and jumpers for replacing the onboard LEDs with external ones, and configuring the I2C bus, which allows you to daisy-chain up to four LP55231’s.

alt text

Lp55231 Breakout.

Major Functions

alt text

Major features.

Host Microcontroller Interface

Along the left edge if the board are the logic signals that interface with the host microcontroller. This is the power input (GND and VCC pads), the I2C bus (SDA and SCL), and logic signals to interact with the execution engines (TRIG and INT). Finally, the charge pump voltage is available on the VOUT pad.

LP55231 IC

Towards the center of the board is the LP55231 chip, with supporting components. The chip is mostly self contained, though it requires a few resistors and capacitors.

Onboard LEDs

The board has three WS2801 RGB LEDs on it.

Pads For External LEDs

Adjacent to the RGB LEDs are groups of four pads, for attaching external LEDs. The pads are in the same order as a common-cathode PTH LED, though, with some creativity, you can apply other LEDs.

Because the outputs are current sources, you don’t need a series resistor when attaching external LEDs. Instead of calculating a resistor value for bias current, the current is configured by writing registers in the LP55231.

Breakout Configuration

While the breakout is functional with no further configuration, it can be tailored to specific applications using solder jumpers on the back of the board.

alt text

Configuration jumpers.

Jumpers D1, D2 and D3

As mentioned above, the breakout includes RGB LEDs, with pads for adding external LEDs. If you’re adding external LEDs, you can defeat the onboard RGBs by cutting jumpers D1, D2 and D3.

Jumpers A0, A1 and I2C Pullup Defeat

If you want to daisy-chain more than one LP55231 breakout, you’ll want to assign each board a unique I2C address. You’ll also want to defeat the I2C pullup resistors on all but one board, usually the last one in the chain.

alt text

Daisy-chain of four LP55231s.

Chip Internals

For an apparently tiny chip that simply illuminates LEDs, the LP55231 has a lot inside. Before we get into the example projects, lets take a peek under the hood.

alt text

LP55231 Internals.

Host Microcontroller Interface

The chip has 118 registers on the I2C bus, divided into several sections.

  • The first group of registers is used for basic control of the chip. This includes power-up and reset functionality, as well as features such as charge-pump control and onboard diagnostics that can detect open or shorted LED outputs.
  • Increasing in sophistication over the basics, the chip offers direct control over the LEDs. They can be turned on and off, output drive current can be set, and groups of LEDs can be controlled together using master faders.
  • Finally, there are the execution engines. Their register interface includes random-access memory that holds the program, and registers that control when and how they run. We’ll cover these in much greater detail shortly.

Charge Pump

The charge pump is a power supply that boosts the input voltage to a higher level.

Green, blue and white LEDs all have forward voltages in the 3.4VDC range. On a system powered from a 3.3V supply, they won’t light up, so the LP55231 uses the charge pump to create a higher voltage to get those LEDs to turn on.

The charge pump is only used for the first six outputs – the other three all use the system voltage. Channels 7, 8 and 9 are intended to drive red LEDs, which have a forward voltage around 2 volts, so they have no problem operating from a 3.3V supply. This also means that when driving RGB LEDs, the red, green, and blue channels aren’t adjacent.

The IC enables the charge pump automatically when it detects that the system voltage is in the 3.3V range. With a 5V power supply, the charge pump is bypassed, and the 5V supply is used for all LEDs.

Output Drivers

The LED output drivers are Pulse Width Modulation outputs. They are highly configurable, with many options determining how they drive the outputs.

First, they are current-source outputs, configurable to match the attached LEDs, to a maximum of 25.5 mA per output. The output current is set per-channel by writing the corresponding current control registers.

Each output can also be configured to a logarithmic brightness response curve. Our eyes preceive light on a logarithmic scale, so the log mode allows the chip to fade in and fade out in a more visibly obvious manner. The tradeoff is that log mode doesn’t achieve the brightest overall response.

Outputs can be grouped together using master fader channels. By assigning outputs to a master fader, the host microcontroller can control many LEDs with a single write operation. Master faders are also useful for fading mixed colors. The intensity of a mixed color can be controlled, without causing the color to shift as it fades.

Execution Engines

The crowning features of the LP55231 are the three execution engines. These are simple computers that perform LED-specific operations. They can set outputs to specific values, perform timed operations like blink and fade sequences, and respond to logic signals.

The engines are programmed using a simple machine language, which is loaded into memory over I2C.

The execution engines are powerful, but also cryptic. We’ll demonstrate a program in the Execution Engine example, and there are demonstrations of more advanced features in the GitHub Repository.

One Thing Missing

The notable thing the LP55231 is lacking is non-volatile storage – it doesn’t have ROM or FLASH memory that would allow it to remember what it was doing across a power-cycle. As such, it works best as a peripheral to a microcontroller, rather than as a stand-alone device.

Demo Circuit

Before we get into some software examples that use the LP55231 breakout, we’ll need to connect it to a microcontroller. The examples were written using a 3.3V Pro Micro, but any Arduino-compatible microcontroller with an I2C interface will work with a little translation.

Materials

The Schematic

There’s not much to the circuit: the Pro Micro, the LP55231 breakout, and a few wires to connect them.

alt text

LP55231 with Pro-Micro.

Assembly Notes

The connections are relatively simple. For simple operations, you’ll need to connect 5 wires from the microcontroller to the LP55231. For some of the more sophisticated examples, you’ll also need to connect two GPIO pins for INT and TRIG.

Pro Micro PinLP55231 Pin
GNDGND
VCCVCC
GPIO 2SDA
GPIO 3SCL
GPIO 15EN
GPIO 16INT
GPIO 14TRIG

The Fritzing layout looks like this

alt text

Which was built on a breadboard as shown below.

alt text

Power

Since we’ll be using Arduino to load the example sketches, we can use the USB connection to power to breadboard. If you want to disconnect USB and use another source of power, you can connect a source of regulated 3.3VDC to the VCC connection, or a source of up to 16VDC to the RAW pin on the Pro Micro.

Arduino Library

We’ve written an Arduino library to control the LP55231. It consists of two classes, which allow different degrees of control over the IC.

  • The Lp55231 class provides simple LED control.
  • the Lp55231Engines class extends the Lp55231 class, adding more sophisticated LP55231 features, such as the execution engines, and internal diagnostics, though also consuming more flash memory to do it.

We’ll explore both classes in the following examples.

Simple Example

We’ll start with a simple example: initializing the IC, and turning the LED channels on and off.

language:c
/******************************************************************************
simple-demo.ino
simple demo of using LP55231 to control 9 LEDs.
Byron Jacquot @ SparkFun Electronics
October 12, 2016
https://github.com/sparkfun/SparkFun_LP55231_Arduino_Library

The simplest demo of LP55231 functionality.  Initializes the chip, then
sequentially turn on each of the 9 channels.

Resources:

Development environment specifics:
Written using Arduino 1.6.5

This code is released under the [MIT License](http://opensource.org/licenses/MIT).

Please review the LICENSE.md file included with this example. If you have any questions
or concerns with licensing, please contact techsupport@sparkfun.com.

Distributed as-is; no warranty is given.
******************************************************************************/

#include <Wire.h>
#include <lp55231.h>

Lp55231 ledChip;

void setup() {
// put your setup code here, to run once:

    Serial.begin(9600);
    delay(5000);
    Serial.println("-- Starting Setup() --");

    ledChip.Begin();
    ledChip.Enable();

    delay(500);

    Serial.println("-- Setup() Complete --");
}

void loop() {
// put your main code here, to run repeatedly:

// current will track the LED we're turning on
// previous will keep track of the last one we turned on to turn it off again

    static uint8_t current = 0, previous = 0;
    static uint32_t next = millis()+1000;

    if(millis() >= next)
    {
        next += 1000;

        Serial.print("Illuminating: ");
        Serial.println(current);

        ledChip.SetChannelPWM(previous, 0);
        ledChip.SetChannelPWM(current, 255);

        previous = current;
        current++;
        if(current >= ledChip.NumChannels)
        {
            current = 0;
        }
    }
}

The Lp55231 class is declared with no parameters, initializing it to the default I2C address of 0x32. Begin initializes the I2C bus, and Enable turns on the LED driver stages.

As loop runs, it cycles among the outputs, calling SetChannnelPWM on each channel in turn, to turn it on, wait for a moment, then turn it off and proceeed to the next channel.

alt text

The result of the program is that each LED lights successively: blue one, green one, blue two, green two, blue three, green there, then each of the red channels.

Other Examples

There are a couple other demos of the simple Lp55231 library in the repository.

  • simple-two-chips demonstrates two LP55231 breakouts on the I2C bus, each configured for a unique address. There is a note in the file describing how the breakout boardss need to be configured for the example.
  • simple-master-fader demonstrates the color mixing capabilities of the IC. The output channels are set to a color ratio using their SetChannelPWM methods, and also assigned to the same master fader using AssignChannelToMasterFader. As loop executes, it adjusts the group using SetMasterFader. The color ratios established in setup are maintained as the master fader value is adjusted.

Execution Engines

The most interesting features in the LP55231 are the three execution engines. These are three simple, independent, computers that can be programmed to perform LED-related tasks. Before we can look at code written to run on them, we need a little more complete concept of what’s inside and how it works.

alt text

Execution engine internal detail.

Each engine has the following structure:

  • Program memory– RAM locations, accessed via I2C, that store the program. The LP55231 has memory for 96 locations that store 16-bit instructions, shared between all three engines.
  • Program Counter or PC– a 7-bit value that indicates which RAM location stores the current instruction.
  • Variables– there are 4 variables that can be shared among the engines.
  • Control bits– a few bits that tell the engine how to execute the program. They instruct the engine to run, halt or step by one instruction.
  • Output value– each engine calculates a single output value.
  • Mapping bits– the engine output can control one or more LEDs, as assigned by the mapping bits.

Execution Model

Each engine is a simple Fetch-Execute Machine. A Fetch-Execute Machine is the basis for a computer. When we think of a computer, we usually think of a general-purpose machine that can be programmed to accomplish many different tasks, such as writing documents or performing mathematical work. In contrast, this one is tailored to LED-specific tasks.

alt text

The fetch-execute cycle.

It works like this:

  1. To initialize the machine, instructions are loaded into the program memory.
  2. The program counter is set to the first instruction in the program.
  3. The machine starts running.
  4. The engine uses the PC to fetch an instruction from the program memory.
  5. It decodes the instruction, and executes it by performing the actions it describes.

For example, when the program in the diagram above starts, the PC is pointing at location 0, so the engine fetches the instruction FADE UP TO FULL. The engine would increment the output value until it reaches maximum, then increment the PC and fetch the next instruction.

Instruction Set

The 96 words of program memory mentioned above store a program, which is a series of encoded commands, or Instructions. Within the 16-bit words, some bits describe the action to be taken, while others modify that action, specifying things like brightness levels, channel mapping and ramp times.

The LP55231 instruction set is broken into four categories.

Driver instructions

This group of instructions effects the LED output of the engine. The output can be set directly, instructed to ramp from one value to another, or simply pause for a specified time.

Mapping instructions

Each engine calculates a single output value. The engine output can be routed to a single LED with the MUX_SEL instruction.

The mapping instructions can also send that value to multiple outputs, using an indirection table. The table contains one or more bitmaps that describe the outputs controlled by the engine – the LSB maps to output 1, the next bit to output 2, and so on, using 9 bits. The program uses instructions to select the outputs by referencing the table entries.

A table can be composed of multiple entries, and output selections sequenced by selecting new rows in the table. We’ll show how to use this in the following example.

Branch instructions

Ordinarily, as the program executes, the PC increments to select the next instruction. The BRANCH instructions change this behavior.

Branches cause the program counter to be loaded with a new value, to create loops and conditional execution (like for or if statements).

The Interrupt instruction allows the LP55231 to notify the microcontroller that it has reached a specified line in the program. The Trigger instruction makes the engine wait until certain conditions (such as a logic level on the Trig input) are present.

There are also RST and END instructions. Reset causes the program to start over form the beginning, while End causes the engine to halt.

Arithmetic instructions

Finally, the LP55231 can perform addition and subtraction on values stored in the variables.

More Information

A detailed description of every instruction is in section 7.6 of the LP55231 datasheet.

Now that we have a conceptual model of the execution engines, let’s move on to an example that applies them.

Engine Example

To demonstrate the power of the execution engines, we’re going to use a classic LED-switching application: the LED scanner.

alt text

9 LED Scanner.

While chasing among the colors of the RGB LEDs is colorful, it doesn’t lend the sense of motion that we’d expect from an LED scanner. For a more traditional look, we cut the jumpers to disable the onboard LEDs, and added a group of 9 red 5mm LEDs.

language:c
/******************************************************************************
Engines-scaner.ino
9-channel LED scanner using LP55231.

Byron Jacquot @ SparkFun Electronics
October 21, 2016
https://github.com/sparkfun/SparkFun_LP55231_Arduino_Library

Using output maps for the execution engine, sequentially cycles through the 9
LED outputs, resulting in a scrolling pattern.  See the LP55231 breakout board
hookup guide for a  detailed examination of how this works.

Resources:
Written using SparkFun Pro Micro controller, with LP55231 breakout board.

Development environment specifics:
Written using Arduino 1.6.5

This code is released under the [MIT License](http://opensource.org/licenses/MIT).

Please review the LICENSE.md file included with this example. If you have any questions
or concerns with licensing, please contact techsupport@sparkfun.com.

Distributed as-is; no warranty is given.
******************************************************************************/


#include <Wire.h>

#include <lp55231.h>

static const int32_t enable_pin = 15; // Apparently active high?
static const int32_t trigger_pin = 14; // low if unused
static const int32_t interrupt_pin = 16;

static uint32_t next;

static Lp55231Engines ledChip(0x32);

static const uint16_t program[] =
{
    0x9c10, // 0 map start
    0x9c9f, // 1 map end
    0x06ff, // 2 ramp up
    0x0200, // 3 wait
    0x07ff, // 4 ramp down
    0x9d80, // 5 map next
    0xa002, // 6 loop to 2
    0x000a, // 7 - empty placeholder
    0x0005, // 8 - empty placeholder
    0x000a, // 9 - empty placeholder
    0x0005, // a - empty placeholder
    0x000a, // b - empty placeholder
    0x0005, // c - empty placeholder
    0x000a, // d - empty placeholder
    0x0005, // e - empty placeholder
    0x000a, // f - empty placeholder
    0x0001, // 10 map begin - start of 2nd page
    0x0002, // 11
    0x0040, // 12
    0x0004, // 13
    0x0008, // 14
    0x0080, // 15
    0x0010, // 16
    0x0020, // 17
    0x0100, // 18
    0x0020, // 19
    0x0010, // 1a
    0x0080, // 1b
    0x0008, // 1c
    0x0004, // 1d
    0x0040, // 1e
    0x0002, // 1f  map end
};


void setup()
{
    Serial.begin(9600);

    delay(5000);
    Serial.println("### Setup entry");

    pinMode(enable_pin, OUTPUT);
    digitalWrite(enable_pin, LOW);
    digitalWrite(enable_pin, HIGH);

    ledChip.Begin();
    ledChip.Enable();

    // Chip needs a moment to wake up.

    delay(1000);

    ledChip.ClearInterrupt();

    for(uint8_t i = 0; i < 9; i++)
    {
        ledChip.SetLogBrightness(i, true);
        ledChip.SetDriveCurrent(i, 0xff);
    }

    if(ledChip.LoadProgram(program, (sizeof(program)/2)))
    {
    Serial.println("Program loaded?");

        if(ledChip.VerifyProgram(program, (sizeof(program)/2)))
        {
            Serial.println("program verifies");
        }
    }
    else
    {
        Serial.println("Program dodn't load?");
    }

    next = millis() + 3000;

    ledChip.SetEngineEntryPoint(0, 0);
    ledChip.SetEnginePC(0, 0);

    ledChip.SetEngineModeFree(0);
    ledChip.SetEngineRunning(0);

    Serial.println("### Setup complete");

}

void loop()
{
int32_t result;
int8_t  val;
static uint32_t count = 0;

    if(millis() >= next)
    {
        next += 1000;
        count++;

        Serial.print("# ");
        Serial.println(count);

        Serial.print(ledChip.GetEnginePC(0));
        Serial.print("");
        Serial.println(ledChip.GetEngineMode(0));

    }
}

Load the sketch above, and observe that the LEDs chase from side to side.

Theory Of Operations

Let’s dissect the sketch a little, and examine a couple of the finer points. We’ll read it in reverse, starting at the bottom, and working out way to the top.

First, note what’s going on in loop()

language:c
 void loop()
{
    static uint32_t count = 0;

    if(millis() >= next)
    {
        next += 1000;
        count++;

        Serial.print("# ");
        Serial.println(count);

        Serial.print(ledChip.GetEnginePC(0));
        Serial.print("");
        Serial.println(ledChip.GetEngineMode(0));
    }
}

It’s not doing anything that specifically makes the LED scanner run! It checks the program counter, but doesn’t do anything that makes LEDs illuminate. After initialization, all of the LED scanning work is being done independently by the LP55231. This means that the microcontroller is completely available for other tasks.

The tradeoff of avoiding computational load in loop is that the initialization is much more detailed. setup contains the following lines.

language:c
...
ledChip.Begin();
ledChip.Enable();

// Chip needs a moment to wake up.

delay(1000);

ledChip.ClearInterrupt();

for(uint8_t i = 0; i < 9; i++)
{
    ledChip.SetLogBrightness(i, true);
    ledChip.SetDriveCurrent(i, 0xff);
}
if(ledChip.LoadProgram(program, (sizeof(program)/2)))
{
    Serial.println("Program loaded?");

    if(ledChip.VerifyProgram(program, (sizeof(program)/2)))
    {
        Serial.println("program verifies");
    }
}
else
{
    Serial.println("Program dodn't load?");
}

next = millis() + 3000;

ledChip.SetEngineEntryPoint(0, 0);
ledChip.SetEnginePC(0, 0);

ledChip.SetEngineModeFree(0);
ledChip.SetEngineRunning(0);
...

This Sequence of commands:

  1. Initializes the IC (Beginand Enable)
  2. Loads and verifies the execution engine program (LoadProgram and VerifyProgram). We’ll examine the program more closely in a moment.
  3. Instructs the LP55231 to execute the program (SetEngineEntryPoint, SetEnginePC,SetEngineModeFree and SetEngineRunning).

The actual scanner is written in LP55231 machine language, contained in the program array:

language:c
static const uint16_t program[] =
{
    0x9c10, // 0 map start
    0x9c9f, // 1 map end
    0x06ff, // 2 ramp up
    0x0200, // 3 wait
    0x07ff, // 4 ramp down
    0x9d80, // 5 map next
    0xa002, // 6 loop to 2
    0x000a, // 7 - empty placeholder
    0x0005, // 8 - empty placeholder
    0x000a, // 9 - empty placeholder
    0x0005, // a - empty placeholder
    0x000a, // b - empty placeholder
    0x0005, // c - empty placeholder
    0x000a, // d - empty placeholder
    0x0005, // e - empty placeholder
    0x000a, // f - empty placeholder
    0x0001, // 10 map begin - start of 2nd page
    0x0002, // 11
    0x0040, // 12
    0x0004, // 13
    0x0008, // 14
    0x0080, // 15
    0x0010, // 16
    0x0020, // 17
    0x0100, // 18
    0x0020, // 19
    0x0010, // 1a
    0x0080, // 1b
    0x0008, // 1c
    0x0004, // 1d
    0x0040, // 1e
    0x0002, // 1f  map end
};

The program breaks down into 4 sections, marked with line numbers in the comment column. Let’s review the sections, starting from the bottom

  1. Lines 10 through 1f are the output mapping table. Each line in the table specifies a single LED. The table is 16 lines long – 9 lines to scan form 1 to 9, then 7 more lines from 9 back down to 1.
  2. Lines 0 and 1 specify the start and end of the mapping table. As the program runs, it increments through the table. When it reaches the end, it starts over from the beginning.
  3. Lines 7 to f are unused. Developing the program, there’s less to keep track of if there’s a little room for the program to grow or shrink, without having to move the mapping table and remember to adjust the table mapping instructions.
  4. Lines 2 to 6 are the actual program. It fades in, pauses a moment, then fades out, selects the next output, and loops back to the beginning.

More Engine Information

If you’re working with the execution engines, you’ll probably find that the LP55231 datasheet seems a little short. The LP55231 has a cousin in the LP8501 which is very similar. It’s a tiny BGA part, but the datasheet is more detailed, particularly pages 19 through 25, that explain the instruction set more clearly, and give an example of setting the engine to run a program.

We’ve also got a number of examples showing off various features – check the github repo. As we explored the features of the LP55231, we kept sketches to demonstrate them. Each sketch starts with a comment that describes what it’s doing.

Texas Instruments also have a Windows assembler application to assist in writing LP55231 programs. You can find it in the tools & software section of the LP55231 webpage. We started out using it, but quickly learned to write LP55231 programs from scratch, in hexadecimal.

A Few Notes On using The Execution Engines

Things we’ve learned through trial and error.

  • Each engine calculates a single output value. To drive multiple LEDs from a single engine, you need to use mapping tables.
  • The Lp55231Engines library has routines to read the program counter and output mapping bits of each engine. These can be very useful when troubleshooting engine behavior. An engine that’s not running will never change it’s PC, and an engine without a mapped output, won’t do anything visible.
  • If multiple engines map the same output, the lower-numbered engine controls the LED.
  • All three engines have to be idle before program memory is accessible. The Lp55231Engines class will force the engines into this state as part of the LoadProgram call. In other words: loading and running are mutually exclusive.
  • There’s an error in the datasheet: It transposes the INT and END names in table 6. The instruction 0xd000 executes as an interrupt.

Resources and Going Further

alt text

Resources

  • LP55231 datasheet
  • The LP8501 is a similar part in a BGA package. It’s datasheet contains some information about the execution engines that’s not included in the LP55231 datasheet.

Going Further

The LP55231 is a deep part. Our recommended “going further” in this case is actually becoming more familiar with its inner workings.

To get deeper into the LP55231, look over the other example sketches in the repository. There are demonstrations of features that we haven’t touched on here. Each sketch has a detailed comment near the top that describes what is going on.

From there, you can start to write your own LP55231 programs by modifying the examples, or even take the bold step of writing them from scratch!

For more LED fun, check out these other great SparkFun tutorials.

WS2812 Breakout Hookup Guide

How to create a pixel string with the WS2812!

Dot/Bar Display Driver Hookup Guide

How to hook up the LM3914 or LM3916 to drive a 10-LED display with a lone analog signal.

Button Pad Hookup Guide

An introduction to matrix scanning, using the SparkFun 4x4 Button Pad.

LED Cloud-Connected Cloud

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

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

Reducing Arduino Power Consumption

$
0
0

Reducing Arduino Power Consumption a learn.sparkfun.com tutorial

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

Introduction

alt text

When it comes to portable electronics, one of the most important features is how to maximize the battery life. The ATmega328P, used on popular boards like the SparkFun RedBoard, Arduino Uno, and Pro Mini are actually quite power hungry. The RedBoard and Arduino Uno, draw around 15mA minimum, which doesn’t sound like much but as you’ll see in this guide, we can drastically bring that down with just a few tricks. In this guide we’ll see if we can reduce the supply current to less than 10uA with a couple hardware and software tricks.

Suggested Reading

If you have not worked with the Arduino development platform before, you may want to check out the tutorials below before diving into this tutorial.

If you have never worked with a multimeter before, take a look at our extensive guide on using a multimeter to measure the various components of your circuit.

How to Use a Multimeter

January 9, 2015

Learn the basics of using a multimeter to measure continuity, voltage, resistance and current.

Removing Extra Hardware

Every integrated circuit (IC) needs power to function. By reducing the number of ICs needed, you can save a bit of power. The Arduino Uno and RedBoard both have a USB bridge that converts the USB signals to signals that the Arduino’s Universal Asynchronous Receiver Transmitter (UART) can use. The FT231x, used on the RedBoard, alone draws around 10mA. Just by replacing the SparkFun RedBoard with a 5V Pro Mini, not only do you save quite a bit of physical space, you can reduce the supply current from 15mA, down to just 4mA.

Ditching the Linear Regulator

Linear regulators are great. They’re cheap and can regulate a higher voltage to a lower voltage with as few as 3 pins (Vin, ground Vout). The downside of a linear regulator however is they can get pretty hot when you have a large difference between the input and output voltage, or if you’re drawing a lot of current. You can calculate the power that gets wasted in the form of heat with a simple equation:

Pwasted = (Vin - Vout) * I

With a linear regulator, the input current is equal to the output current. Linear regulators are, at best, only around 70% efficient. The more current you draw, the lower the efficiency.

Without going into too much detail, switch mode power supplies are much more efficient because the input current doesn’t have to be the same as the output current. With a light load, you can find switching regulators that are over 90% efficient. With a switching regulator, you can not only reduce the input voltage (using a buck converter), but also increase the voltage (using a boost converter). Other ICs, like the TPS61200 used on the PowerCell, are perfect for battery powered applications, because it can efficiently reduce the battery’s voltage or boost it!

Lowering the Voltage

One of the easiest ways to reduce current is to lower the voltage you give to the Arduino. Just by reducing the voltage from 5V to 3.3V, the current drops from ~4mA, down to ~1mA!

Reducing the voltage, does have a catch though. Reducing the system voltage too much, without reducing clock speed, could make the microcontroller start to behave strangely. The RedBoard, Uno, and 5V Pro Mini all use a 16MHz crystal. Looking at the datasheet for the 328P, we can see that at 3.3V, the recommended maximum frequency is around 13MHz. The relationship between clock speed and system voltage is the reason our 3.3V Pro Mini uses a 8MHz clock instead of 16MHz.

Note: It is worth mentioning that I will sometimes run my ATmega328P at 16MHz while powering it with 3.3V and haven’t had any issues, but your results may vary. We do not recommend running your microcontroller outside the specs listed in its datasheet.

Max Freq v Vcc

Below I’ve created a graph that shows how just by reducing the voltage, you can significantly reduce the power consumption of your Arduino. For my test, I uploaded a blank sketch onto the 328P running at 1MHz.

voltage v current graph

Reducing the Clock Speed

In projects where the Arduino doesn’t need to execute a large number of instructions in a short amount of time or in projects where timing isn’t an issue, reducing the clock speed of the microcontroller can shave a few milliamps off the supply current. For example, running the Arduino at 5V and reducing the clock speed from 16MHz down to just 8MHz can drop the current needed from 12mA down to ~8.5mA.

To better understand the relationship clock speed has with the microcontroller, let’s look at the graph below.

current v clock speed graph

As you can see, reducing the clock speed can triple the battery life. The trade off of course is that you won’t be able to execute as many instructions per second, and for some applications, this solution isn’t an option.

Saving Power with Software

So far we’ve talked about how to reduce the power of the Arduino, but we haven’t talked about why it uses the power it does. Inside the ATmega328P, lies a series of circuits that work together to offload work from the processor, and each of these draws some amount of power. The Arduino’s analogWrite() function, for example, doesn’t have the processor create a PWM signal by counting the clock cycles itself. Instead, the Arduino uses one of the built in timers to count clock cycles and send an interrupt request to the processor. From there, the processor stops what it’s doing and handles the interrupt by switching the pin’s state. By offloading some of the work, the microcontroller is able to do multiple things at the same time. Some of the other circuitry built into the ATmega328P include:

  • 3 timers
  • Watchdog timer
  • Brown-out detect
  • Analog to digital conversion

Each of these independent components need power to work, and, unless you manually disable them, they will continue to draw power. The brown-out detection actively monitors the system voltage to ensure it doesn’t drop below its threshold. If it does, the controller powers down until the voltage is increased above that threshold. The analog to digital converter (ADC) does just as the name suggests, it take the analog voltage (which can be any value from 0V up to VCC) and converts it to a digital value that the microcontroller can use (0-1023 for 10-bit converters). If your project doesn’t need to use the ADC, disabling it will cut down on the power draw drastically.

But what if you still need the ADC? Thankfully there are registers where you can disable some of these circuits with software. Using software allows you to enable the circuits you need, when you need them, and, when you’re done, you can disable them again. All of the registers are well documented in the datasheet for the ATmega328p, but, if directly writing to registers makes you uncomfortable, there is a library available that you can download from the link below. For instructions on how to install an Arduino library, check out this tutorial.

Download the Low-Power Library

This library allows you to set how long to enter into sleep mode, from a few milliseconds, up to indefinitely. It also allows you to specify which parts of the micro to disable, making it a pretty powerful and versatile library for your low-power needs.

In this first example, let’s load the sketch below onto our Arduino, which is running off of 5V at 16MHz. To see how little current is needed in sleep mode, I’m using a bare bones Arduino by using the ATmega328P on a breadboard to minimize the current I’m using.

language:c
#include "LowPower.h"

void setup()
{
  pinMode(13,OUTPUT);
}

void loop()
{
  digitalWrite(13,HIGH);
  delay(2000);
  digitalWrite(13,LOW);
  LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
}

In this sketch the Arduino blinks an LED on for two seconds and is then powered down for two seconds, and during that time the ADC and brown-out detect (BOD) are disabled. When powered down, the Arduino’s current drops from 14mA, down to just 6uA! If we use some of the other power saving tricks from previous sections, we can see in the table below just how low we can get the sleep current.

sleep table

If you’re wondering why clock speed doesn’t affect the sleep current, during power down the clock is also disabled. Obviously you won’t want to keep the Arduino in low-power mode. But, in projects where you don’t need to take readings continuously, shutting the Arduino down 50% of the time, and using the techniques we covered, can allow the battery to last over seven times longer!

Resources and Going Further

More information on low-power modes and options can be found in the datasheet for the 328P.

For more power-related fun, check out the following SparkFun tutorials.

Uh-Oh Battery Level Indicator Hookup Guide

Learn how to assemble and use the Uh-Oh Battery Level Indicator Kit.

PicoBuck Hookup Guide V12

The PicoBuck board is a high-efficiency three-channel constant-current LED driver.

What is a Battery?

An overview of the inner workings of a battery and how it was invented.

Battery Babysitter Hookup Guide

An introduction and getting started guide for the Battery Babysitter - a flexible LiPo battery charger and monitor.

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

Serial Controlled Motor Driver Hookup Guide

$
0
0

Serial Controlled Motor Driver Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The Serial Controlled Motor Driver (abbreviated SCMD for the rest of this guide) is a DC motor driver that’s been designed to drive small DC motors with ease. It can be commanded by UART, I2C, or SPI communication, and it can drive a constant 1.2A load per motor (peak 1.5A) at 11V. Need more than two motors? Chain multiple SCMDs together and command them through the same serial interface. Need more current? Each board’s output can be bridged to allow double current.

SparkFun Serial Controlled Motor Driver

ROB-13911
$16.95

This driver board was designed to be affordable, compact and have more features than previous versions of serial-controlled motor drivers. Its main advantage is the variability of drive levels making fine control adjustments a possibility.

Features:

  • 1.5 A peak drive per channel, 1.2 A steady state
  • Operates from 3 to 11 volts with 12v absolute max
  • 3.3v default VCC and logic
  • Max VCC in of 5.5v
  • 127 levels of DC drive strength.
  • Controllable by I2C, SPI, or TTL UART signals
  • Direction inversion on a per motor basis
  • Global Drive enable
  • Expansion port utilizing I2C, allows 16 additional drivers
  • Exposed TO-220 heat sink shape
  • Several I2C addresses, default UART bauds available
  • Bridgeable outputs
  • Optional fail-safe and diagnostics available.
  • Configurable expansion bus bit rate to 50, 100, or 400 kHz.
  • Configurable expansion bus update rate from 1ms to 255ms, or by command only

Covered In This Tutorial

This tutorial covers basic usage of the motor driver. It shows how to connect it to I2C, SPI, or UART at 3.3V levels, and how to attach more drivers to the master and control them all independently. It also shows some common motors that can be used without heatsinks.

Required Materials

This tutorial explains how to use the Serial Controlled Motor Driver Breakout Board with an Arduino or direct serial. To follow along, you’ll need the following materials:

Hobby Motor - Gear

ROB-11696
$1.95
4
Hobby Gearmotor - 200 RPM (Pair)

ROB-13302
$3.95
Micro Gearmotor - 460 RPM (6-12V)

ROB-12429
$12.95
Standard Gearmotor - 303 RPM (3-12V)

ROB-12147
$24.95
1

Check out our entire offering of DC motors:

DC Gearmotor Catalog



The SCMD is a 3.3V logic device! If you need to interface to 5V you'll need to use a logic level converter, or modify the SCMDs from stock to operate at 5V, and supply your own regulated 5V.


SparkFun Logic Level Converter - Bi-Directional

BOB-12009
$2.95
59

Suggested Reading

If you aren’t familiar with the following concepts, we recommend you read over these tutorials before continuing.

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

Serial Peripheral Interface (SPI)

SPI is commonly used to connect microcontrollers to peripherals such as sensors, shift registers, and SD cards.

I2C

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

Motors and Selecting the Right One

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

Binary

Binary is the numeral system of electronics and programming...so it must be important to learn. But, what is binary? How does it translate to other numeral systems like decimal?

Logic Levels

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

Bi-Directional Logic Level Converter Hookup Guide

An overview of the Bi-Directional Logic Level Converter, and some example circuits to show how it works.

Hexadecimal

How to interpret hex numbers, and how to convert them to/from decimal and binary.

Terminology

This guide and related documentation uses a few terms with specific meanings. When User and Expansion are used, it is referring to the physical pins of the connection. When Master and Slave are used, it matches the I2C behavior on the expansion port, and refers to the connected chain of SCMDs.

  • User Port– Connects the user’s project to the master SCMD and is unused on slaves.
  • Expansion Port– Connects a single master and up to 16 slaves, and should never be connected to the user’s project.
  • Master– The SCMD that is connected to the user’s project. Also, it is the I2C master on the expansion port
  • Slave– A SCMD that is only connected to a master SCMD by way of the expansion port.

Note: The config in and out pins of the expansion port may sometimes be connected to the user’s project for error checking and mitigation purposes.

Motor Polarity– The driver and this document often omit motor polarity. This is because polarity to spin direction is not standardized, and it is assumed the user will attach them backwards 50% of the time. Each motor channel is independently configurable for what is thought of as ‘forward’ spin by command. It is assumed that the user will first attach the motors, then decide which channels need to be inverted and issue inversion settings at boot time.

Expansion Bus I2C Pull-Ups– All master SCMDs should have at least one set of pull-ups enabled for their expansion bus, even if no slaves are present! The board’s default state is disabled because pull-up resistors should be applied thoughtfully per design, but it means a single master without slaves will un-intuitively require the jumper to be closed.

Motor Numbering– The SCMD’s silkscreen shows connections for motor ‘A’ and motor ‘B’ to prevent confusion within a programming environment where numbers are used to denote motors or drivers.

alt text

Motor numbering scheme

When somethings refers to a ‘motor number’, the following scheme is used. The motor attached to the master at position ‘A’ will always be motor 0, and the ‘B’ position, motor 1. The first slave device attached will have motors 2, and 3, at positions ‘A’ and ‘B’ respectively. Slave 2 will have motors 4, and 5, and so on.

When a SCMD is designated as bridged mode, it loses whatever motor is attached to the ‘B’ position, and any information sent to control the ‘A’ position will control both outputs synchronously, such as inversion or drive strength.

This is not to be confused with ‘driver number’, which indicates which SCMD in the chain is being referenced.

Hardware Overview

This section describes the basic parts of the hardware.

alt text

All of the components are populated on the top side of the board.

Power is supplied through the VIN Connection and is regulated down to 3.3V for the PSoC and logic circuits. A VCC rail pin is provided for hackability.

The Status LED has a few things that it displays simultaneously:

  • Emits a blip when it receives data from the master.
  • Flashes once every ~2.5 seconds to indicate nominal condition
  • Flashes eight times per ~2.5 second period to indicate that the failsafe condition has occurred.

The User Port is designated for connection to the user’s project (which will tell the motors what to do), and can be configured as UART, SPI, or I2C by jumper setting.

The Expansion Port is configured as I2C master or slave based on jumper settings, and operates on a second I2C bus with only other motor drivers.

The microcontroller generates PWM signals that go straight to the DRV8835 motor driver, which consists of 2 mosfet H-bridge driver circuits with thermal and current protection built in.

alt text

The bottom of the board contains user configuration jumpers and a large area to wick the heat.

Powering the SCMD

Provide 3.3V to 11V to “MAX 11V” and “GND”. Each has two through-holes for general use. They can be used to reduce connection resistance or to piggyback other devices, or can accept the leads of a large capacitor. The terminal is directly connected to the DRV8835’s power input, and is also regulated down to 3.3V for the PSoC supply and logic levels. The driver can consume up to 3A of current so make sure these wires are short or heavier gauge, or both.

When slaves are attached to the expansion port, they also require power from another source. Wire the “MAX 11V” and “3.3V” pins in parallel with the master as shown in (Expansion Port Usage)[https://learn.sparkfun.com/tutorials/serial-controlled-motor-driver-hookup-guide#expansion-port-usage]

The VCC pin is an advanced feature that can be used to operate the SCMD at a different voltage, but isn’t used for basic applications. See the SCMD Datasheet for more information.

Jumper Usage Table

There are 4 sets of jumpers to configure on this board. There are pull-up enables for both user (User PU) and expansion bus (Exp. PU, default not-pulled up), A VCC disconnect jumper (VCC Src) to remove all logic from the on-board regulator, and 4 config bits that select operational mode.

NameDescriptionUsage
VCC SrcConnects VCC rail (pin) to on-board regulatorOpen to remove regulator from VCC rail. User must supply 1.8V to 5.5V to VCC pin
User PUI2C pull-up enable for User PortClose all three pads to connect 4.7k resistors to SDA and SCL of user port
Exp. PUI2C pull-up enable for Expansion PortClose all three pads to connect 4.7k resistors to SDA and SCL of expansion port. The expansion bus should have exactly one board with pull-ups enabled on it. A single master without slaves is technically a complete expansion bus, and thus the single master needs these jumper pads bridged.
ConfigSerial and function selectionThe config bits are 4 bits that form a configuration nybble. A closed jumper is a '1' and an open jumper is a '0'. See config table for more information.

Config Bits Table

The configuration is set by encoding a number into the 4 config bits on the bottom of the board. Close a jumper to indicate a 1, or leave it open to indicate a 0. Use this table to see what the user port, address, and expansion port will become in each configuration.

PatternModeUser PortUser AddressExpansion Port
0000UART at 9600UARTN/AMaster
0001SPISPIN/AMaster
0010SlaveN/AN/ASlave
0011I2CI2C0x58Master
0100I2CI2C0x59Master
0101I2CI2C0x5AMaster
0110I2CI2C0x5BMaster
0111I2CI2C0x5CMaster
1000I2CI2C0x5DMaster
1001I2CI2C0x5EMaster
1010I2CI2C0x5FMaster
1011I2CI2C0x60Master
1100I2CI2C0x61Master
1101UART at 57600UARTN/AMaster
1110UART at 115200UARTN/AMaster
1111N/AReservedN/AN/A

Pin Connections

The function of the 0.1" holes are explicitly indicated in this table, and are organized by physical location on the PCB.

Function / Connection
GroupNameDirectionDescriptionUARTI2CSPI
User PortRX,SCL,MOSIIMulti-function SerialData In (RX)SCLMOSI
TX,SDA,MISOIOMulti-function SerialData Out (TX)SDAMISO
GND-GroundGroundGroundGround
NC,SCLISPI clockNCNCSCL
NC,CSISPI chip selectNCNCCS
Expansion PortGND-GroundSlave bus Ground
SDAIOI2C Data lineSlave bus SCL
SCLII2C Clock lineSlave bus SDA
InIConfig In. Slave aquire-address/enableConnects to upstream slave*
OutOConfig Out. Enable next slaveConnects to downstream slave*
Motor PortA1OWinding of first addressable locationMotor A winding
A2OWinding of first addressable locationMotor A winding
B1OWinding of second addressable locationMotor B winding
B2OWinding of second addressable locationMotor B winding
PowerGNDIMain system ground (two pads)Supply ground
MAX 11VIMotor driver raw voltage, regulator in (two pads)Supply power
VCCIORegulator output or user supplied VCCNC

Typical Application Motors and Heat Sinking

The SCMD is designed to operate small robot drive motors without a heatsink, up to about 500mA continuous current. Here’s how some regular motors fair when used.

  • Hobby Gearmotor - 200 RPM (Pair)– RedBot style motors. These have low stall current and can be used without heatsinks.
  • Micro Gearmotor - 460RPM– These can be used without heatsinks.
  • Standard Gearmotor - 303RPM– Motors of this larger size can also be used without heatsinks.
  • CPU fans – can be varied. Include a forward diode to prevent reverse voltage application. Some can draw a large amount of current! If the driver is getting too warm, a heatsink (or forced air) is required.
  • Vacuum Pump - 12V– These pumps can draw amps. The driver will need to have heatsinking.

Determining if a heat sink is necessary

The temperature rise is related to the current load on the motor driver. To determine what your load is, attach the motor directly to a power supply and apply torque as will be done by the final application. Then use the chart below to determine if you need to heat sink. You can also stall the motor completely and measure the stall current (or use a multimeter to check the coil resistance, then do the math).

alt text

Temperature rise as a function of total driver load

This graph shows total current sourced by the SCMD from both channels. If using bridged mode, find your target current load on the X axis, then see what to expect from these configurations on the Y axis. If not using bridged mode, double the current of a single motor to find the worst case condition of both motors at max current, then use that instead.

The TO-220 Heat Sink and Theragrip Thermal Tape were used to make the above graph, and work well to give yourself an extra amp of capability in a typical application.

Example 1: Interactive UART control with slaves.

This example demonstrates the basic commands, plus some direct register access possible with only a UART available. This type of program could be easily run from a script from a more classic PC where I2C or SPI isn’t available.

User port as UART

Requirements

  • Computer serial terminal set to 9600 baud.
  • Terminal set to send CR and LF (Carriage return and line feed).
  • Config jumpers set to ‘0000’, or all open.
  • Exp. PU jumper fully closed
  • A 5V wall supply

Connect the FTDI to the SCMD using the diagram in “Hardware Connections”, and power the SCMD from the wall supply. Attach two motors to the driver, one between A1 and A2, and the other between B1 and B2.

alt text

A SCMD ready to drive motors from UART command.

alt text

The master is configured as UART (“0000”), and has pull up resistors enabled for the expansion bus.

Connections

Connect the FTDI basic to the motor drvier as follows. Notice that the both sides have RX that indicates data in, so the RX-TX serial lines must be crossed.

alt text

Typing should now echo back to your terminal, pressing return should generate a new line (or error message), and commands can be entered. Skip forward to the UART Commands, or, enter the following commands as a guided tour. You may notice some responses like “inv” and “ovf” if the data entered was no good.

Example Commands

When you’re ready, send the following commands:

“R01”

This will read the ID register and return 0xA9

“M01F50”

This will tell motor 0 to drive at half speed, forward – But nothing will happen yet!

“E”

This will enable all drivers. Motor 0 should begin spinning at half speed.

“M01R100”

This will tell motor 1 to drive at full speed backwards. Now both should be spinning opposite directions.

“M01S”

This will cause motor 1 to reverse “forward” direction. Both should be spinning in the same direction now.

“E”

E again will disable both motors, which will stop spinning.

See the section “UART Commands” for a full command listing.

UART Commands

General:

The command parser is built to accept short strings of ascii data, compacted to reduce data transfer size while being easy to handle by standard UART hardware. The general form is a letter indicating which operation to perform followed by a series of numbers and letters, and finally a carriage return and line feed. As a string, an example command would be “M0F50\r\n”.

Return codes:

Overflow (“ovf”): The input buffer is filled (no command should be that long). Send delimiter to clear buffer

Invalid Syntax (“inv”): The first character in the command is not one of the defined prefixes.

Formatting Error (“fmt”): There was something generally wrong with the command, like it had the wrong number of characters or an out of range value was detected.

No Motor (“nom”): The motor’s number is past the most downstream slave detected.

Commands:

Help:

"H" or "?"

Prints command reference to serial.

Example:
"H\r\n"– Drive master motor B forward at 34%.

Drive motor:

"Mndl"
n = motor number, single or double digits
d = direction, R or F
l = level, 0 to 100

Example:
"M1F34\r\n"– Drive master motor B forward at 34%.
"M2R80\r\n"– Drive slave motor A reverse at 80%.

Invert motor polarity:

"MnI"
n = motor number, single or double digits

Example:
"M1I\r\n"– Invert the polarity of motor 1.

Clear motor inversion:

"MnC"
n = motor number, single or double digits

Example:
"M1C\r\n"– Set polarity of motor 1 to default.

Enable and disable Drivers"E" and "D"

The drivers boot in the disabled state so that other settings can be configured before beginning to drive the motors. Use these commands to enable and disable them.

Example:
"E\r\n"– Enable all outputs
"D\r\n"– Disable all outputs

Bridge and un-bridge outputs

"Brr" and "Nrr"
rr = Motor driver number, 0 is master, 1-16 is slave

This causes a motor driver to start or stop synchronous PWM on both ‘A’ and ‘B’ ports. Notice that the input is by board number, not motor number.

Example:
"B0\r\n"– Bridge master’s outputs"B2\r\n"– Bridge the 2nd physical slave’s outputs (motors 4&5)"N0\r\n"– Un-bridge master’s outputs"N2\r\n"– Un-bridge the 2nd physical slave’s outputs (motors 4&5)

Change the Baud Rate

"Un"
n = baud rate selection

This command changes the bitrate of the UART. The serial terminal will need to be reconfigured after this command. The command reports new rate at old baud before changing to the new one.

Rates supported:
1 – 2400
2 – 4800
3 – 9600
4 – 14400
5 – 19200
6 – 38400
7 – 57600
8 – 115200

Examples:
"U3\r\n"– Set baud rate to 9600
"U8\r\n"– Set baud rate to 115200

Write Register

"Wrrhh"
rr = two digit hex address
hh = two digit hex data

Example:
"W20FF\r\n"– Write 0xFF to register 0x20 (MA_DRIVE).

Read Register

"Rrr"
rr = two digit hex address

Example:
"R01\r\n"– Read address 0x01 (ID), bus will display “A9”, ID word of 0xA9

Arbitrary register access Some of the more intricate features like bus settings and debug information can be accessed by reading from a user-facing memory space, called registers. Use the SCMD datasheet for mapping and function.

Arduino Library Reference

Example 2 and 3 use the Arduino IDE and a RedBoard to communicate with the SCMD. This section outlines how to get it and how the functions themselves operate.

Getting the Arduino Library

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

Use the library manager or install in the Arduino IDE

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_Serial_Controlled_Motor_Driver_Arduino_Library folder into a libraries folder within your Arduino sketchbook.

Operating the Library

The library is made such that new motor driver object is constructed without parameters, the user populates the public settings structure, then calls .begin() to start the wire library and apply the communication settings.

Example:

language:c
SCMD myMotorDriver; //This creates an instance of SCMD which will be bound to a single master.

void setup()
{
    myMotorDriver.settings.commInterface = I2C_MODE; //or SPI_MODE
    myMotorDriver.settings.I2CAddress = 0x5A;
    myMotorDriver.settings.chipSelectPin = 10;
    myMotorDriver.begin();
}

Settings

The main SCMD class has a public member which is named settings. To configure settings, use the format myMotorDriver.settings.I2CAddress = (...); then call .begin() to apply.

settings contains the following members:

  • uint8_t commInterface – Set equal to I2C_MODE or SPI_MODE
  • uint8_t I2CAddress – Set to address that master is configured to in case of I2C usage
  • uint8_t chipSelectPin – Set to chip select pin used on Arduino in case of SPI

Classes and Structures

There are a few classes used in the library. The main class is called SCMD, which is the object that talks to the motor drivers. There are also a couple structs in use – SCMDSettings and SCMDDiagnostics. A SCMDSettings object named settings is present within the SCMD class for configuration.

SCMD

SCMD is used to declare a single chain of motor drivers at specified port and modes in settings. The contained functions are described in a later section.

language:c
class SCMD
{
public:
    //settings
    SCMDSettings settings;
    SCMD( void );

    uint8_t begin( void );
    ... (Other functions...)

    uint16_t i2cFaults; //Location to hold i2c faults for alternate
    driver
};

SCMD Settings

SCMDSettings is an type for the settings member of SCMD. It is declared public to be configured by the user.

language:c
struct SCMDSettings
{
public:
    //Main Interface and mode settings
    uint8_t commInterface;
    uint8_t I2CAddress;
    uint8_t chipSelectPin;
};

SCMD Diagnostics

SCMDDiagnostics contains a bunch of 8 bit values of data for use with getDiagnostics and getRemoteDiagnostics. Declared objects are passed as a reference to the diagnostic function and written by the collected data.

language:c
struct SCMDDiagnostics
{
public:
    //Attainable metrics from SCMD
    uint8_t numberOfSlaves = 0;
    uint8_t U_I2C_RD_ERR = 0;
    uint8_t U_I2C_WR_ERR = 0;
    uint8_t U_BUF_DUMPED = 0;
    uint8_t E_I2C_RD_ERR = 0;
    uint8_t E_I2C_WR_ERR = 0;
    uint8_t LOOP_TIME = 0;
    uint8_t SLV_POLL_CNT = 0;
    uint8_t MST_E_ERR = 0;
    uint8_t MST_E_STATUS = 0;
    uint8_t FSAFE_FAULTS = 0;
    uint8_t REG_OOR_CNT = 0;
    uint8_t REG_RO_WRITE_CNT = 0;
};

Functions

uint8_t begin( void );

Call after providing settings to start the wire library, apply the settings, and get the ID word (return value should be 0xA9). Don’t progress unless this returns 0xA9!

bool ready( void );

This function checks to see if the SCMD is done booting and is ready to receive commands. Use this after .begin(), and don’t progress to your main program until this returns true.

bool busy( void );

This function checks to see if the SCMD busy with an operation. Wait for busy to be clear before sending each configuration commands (not needed for motor drive levels).

void enable( void );

Call after .begin(); to allow PWM signals into the H-bridges. If any outputs are connected as bridged, configure the driver to be bridged before calling .enable();. This prevents the bridges from shorting out each other before configuration.

void disable( void );

Call to remove drive from the H-bridges. All outputs will go low.

void reset( void );

This resets the I2C hardware for Teensy 3 devices using the alternate library, and nothing otherwise.

void setDrive( uint8_t channel, uint8_t direction, uint8_t level );

This sets an output to drive at a level and direction.

  • channel: Motor number, 0 through 33.
  • direction: 1 or 0 for forward or backwards.
  • level: 0 to 255 for drive strength.

void inversionMode( uint8_t motorNum, uint8_t polarity );

This switches the perceived direction of a particular motor.

  • motorNum: Motor number, 0 through 33.
  • polarity: 0 for normal and 1 for inverted direction.

void bridgingMode( uint8_t driverNum, uint8_t bridged );

This connects any board’s outputs together controlling both from what was the ‘A’ position.

  • driverNum: Number of connected SCMD, 0 (master) to 16.
  • bridged: 0 for normal and 1 for bridged.

void getDiagnostics( SCMDDiagnostics &diagObjectReference );

This returns a diagnostic report from the master.

  • &diagObjectReference: Pass a local SCMDDiagnostics object that will be written into.

void getRemoteDiagnostics( uint8_t address, SCMDDiagnostics &diagObjectReference );

This returns a diagnostic report from a slave.

  • address: address of intended slave. This starts at 0x50 for the first slave and goes up from there.
  • &diagObjectReference: Pass a local SCMDDiagnostics object that will be written into.

void resetDiagnosticCounts( void );

Clears the diagnostic counts of a master.

void resetRemoteDiagnosticCounts( uint8_t address );

Clears the diagnostic counts of a slave.

  • address: address of intended slave. This starts at 0x50 for the first slave and goes up from there.

uint8_t readRegister(uint8_t offset);

Returns the contents of a memory location of the master.

  • offset: Memory address to read.

void writeRegister(uint8_t offset, uint8_t dataToWrite);

Writes data to a memory location of the master.

  • offset: Memory address to write.
  • dataToWrite: Data to write to that address.

uint8_t readRemoteRegister(uint8_t address, uint8_t offset);

Returns the contents of a memory location of a slave.

  • address: address of intended slave. This starts at 0x50 for the first slave and goes up from there.
  • offset: Memory address to read.

void writeRemoteRegister(uint8_t address, uint8_t offset, uint8_t dataToWrite);

Writes data to a memory location of a slave.

  • address: address of intended slave. This starts at 0x50 for the first slave and goes up from there.
  • offset: Memory address to write.
  • dataToWrite: Data to write to that address.

Example 2: RedBot Retrofit (I2C control)

This example drives a robot in left and right arcs, driving in an overall wiggly course. It demonstrates the variable control abilities. When used with a RedBot chassis, each turn is about 90 degrees per drive.

Requirements

  • SparkFun RedBoard or Arduino compatible 328p device
  • The Arduino Library
  • Config jumpers set to address 0x5A, or ‘0101’, or positions 0 and 2 closed with 1 and 3 open. Other addresses can be selected by using the bit patters of 0x3 to 0xE, and appropriate address programmed into the 328p code.
  • User PU jumper fully closed
  • Exp. PU jumper fully closed

The 328p is now ready to communicate with the SCMD. Skip forward to the Arduino Library section for API usage, or use one of the example sketches.

alt text

This Shadow Chassis has been Red-trofitted with a RedBoard and SCMD

alt text

The connections made are shown here.

Connections

Connect the Arduino basic to the motor drvier as follows. The SDA and SCL pins are pulled up by the SCMD only, and should idle at 3.3V.

alt text

Example Code

The example, also available from the drop-down menu in Arduino (It’s called TwoMotorRobot), is as follows:

language:c
//This example drives a robot in left and right arcs, driving in an overall wiggly course.
//  It demonstrates the variable control abilities. When used with a RedBot chassis,
//  each turn is about 90 degrees per drive.
//
//  Pin 8 can be grounded to disable motor movement, for debugging.

#include <Arduino.h>
#include <stdint.h>
#include "SCMD.h"
#include "SCMD_config.h" //Contains #defines for common SCMD register names and values
#include "Wire.h"

SCMD myMotorDriver; //This creates the main object of one motor driver and connected slaves.

void setup()
{
  pinMode(8, INPUT_PULLUP); //Use to halt motor movement (ground)

  Serial.begin(9600);
  Serial.println("Starting sketch.");

  //***** Configure the Motor Driver's Settings *****//
  //  .commInter face can be I2C_MODE or SPI_MODE
  myMotorDriver.settings.commInterface = I2C_MODE;
  //myMotorDriver.settings.commInterface = SPI_MODE;

  //  set address if I2C configuration selected with the config jumpers
  myMotorDriver.settings.I2CAddress = 0x5A; //config pattern "0101" on board for address 0x5A

  //  set chip select if SPI selected with the config jumpers
  myMotorDriver.settings.chipSelectPin = 10;

  //*****initialize the driver get wait for idle*****//
  while ( myMotorDriver.begin() != 0xA9 ) //Wait until a valid ID word is returned
  {
    Serial.println( "ID mismatch, trying again" );
    delay(500);
  }
  Serial.println( "ID matches 0xA9" );

  //  Check to make sure the driver is done looking for slaves before beginning
  Serial.print("Waiting for enumeration...");
  while ( myMotorDriver.ready() == false );
  Serial.println("Done.");
  Serial.println();

  //*****Set application settings and enable driver*****//

  //Uncomment code for motor 0 inversion
  //while( myMotorDriver.busy() );
  //myMotorDriver.inversionMode(0, 1); //invert motor 0

  //Uncomment code for motor 1 inversion
  while ( myMotorDriver.busy() ); //Waits until the SCMD is available.
  myMotorDriver.inversionMode(1, 1); //invert motor 1

  while ( myMotorDriver.busy() );
  myMotorDriver.enable(); //Enables the output driver hardware

}

#define LEFT_MOTOR 0
#define RIGHT_MOTOR 1
void loop()
{
  //pass setDrive() a motor number, direction as 0(call 0 forward) or 1, and level from 0 to 255
  myMotorDriver.setDrive( LEFT_MOTOR, 0, 0); //Stop motor
  myMotorDriver.setDrive( RIGHT_MOTOR, 0, 0); //Stop motor
  while (digitalRead(8) == 0); //Hold if jumper is placed between pin 8 and ground

  //***** Operate the Motor Driver *****//
  //  This walks through all 34 motor positions driving them forward and back.
  //  It uses .setDrive( motorNum, direction, level ) to drive the motors.

  //Smoothly move one motor up to speed and back (drive level 0 to 255)
  for (int i = 0; i < 256; i++)
  {
    myMotorDriver.setDrive( LEFT_MOTOR, 0, i);
    myMotorDriver.setDrive( RIGHT_MOTOR, 0, 20 + (i / 2));
    delay(5);
  }
  for (int i = 255; i >= 0; i--)
  {
    myMotorDriver.setDrive( LEFT_MOTOR, 0, i);
    myMotorDriver.setDrive( RIGHT_MOTOR, 0, 20 + (i / 2));
    delay(5);
  }
  //Smoothly move the other motor up to speed and back
  for (int i = 0; i < 256; i++)
  {
    myMotorDriver.setDrive( LEFT_MOTOR, 0, 20 + (i / 2));
    myMotorDriver.setDrive( RIGHT_MOTOR, 0, i);
    delay(5);
  }
  for (int i = 255; i >= 0; i--)
  {
    myMotorDriver.setDrive( LEFT_MOTOR, 0, 20 + (i / 2));
    myMotorDriver.setDrive( RIGHT_MOTOR, 0, i);
    delay(5);
  }
}

The example works by configuring the motor driver, then using for loops to ramp up and down the motor drive levels.

Things to note:

  • begin is periodically ran until the returned ID word is valid.
  • Setup waits for isReady() to become true before going on to the drive section
  • One motor is inverted by command at setup. Do it here so you don’t have to mess with it later.
  • enable() is called to connect the drivers to the PWM generators.
  • LEFT_MOTOR and RIGHT_MOTOR are defined to ease use of the setDrive( … ) function.

Example 3: Two slaves, 5 motors, 1 bridged (SPI control)

This demonstrates more advanced usage of the serial driver. Here, we have a couple slaves attached, with one being configured as a bridged mode. This is a good example of how the motor numbering scheme works.

Requirements

  • SparkFun RedBoard or Arduino compatible 328p device
  • The Arduino Library
  • A Logic Level Converter
  • Master config jumpers set to ‘0001’, or only position ‘0’ closed.
  • Slave config jumpers set to ‘0010’, or only position ‘1’ closed.
  • Exp. PU jumper fully closed

alt text

The motor drivers are connected on a breadboard for test.

alt text

The master is configured as SPI (“0001”), and has pull up resistors enabled for the expansion bus.

alt text

Slaves boards should be set to “0010” with no pull up resistors enabled, as the master is doing it.

Connections

Connect the Arduino and Level Shifter to the motor drvier as follows. This connects to the standard SCL, MOSI, and MISO positions, and uses pin 10 as a chip select.

alt text

The user port connections for this example

While this example will operate with only a master, add slaves to the expansion port to get the full experience.

The expansion port allows multiple SCMDs to be run from the same I2C address, SPI select line, or UART instance. The port can support up to 16 SCMDs set as slave by a common I2C interface, and daisy-chained config-in to config-out wiring

alt text

A diagram showing the expansion bus usage

Notice that the expansion I2C lines are connected to a common bus while the config lines are connected from one board’s ‘Out’ to the next’s ‘In’. More slaves can be added onto the end of the chain.

alt text

The expansion bus connections

When power is applied, the master will assign addresses to the slaves. This may take a couple seconds. When complete, the slaves should all have a faintly lit, blinking status LED indicating communication.

Example Code

The example, also available from the drop-down menu in Arduino (It’s called DriverChainWithBridging), is as follows:

language:c
//This example demonstrates some of the more advanced usage of the motor driver.
//It uses 3 motor drivers, with the master attached as SPI.  One slave is bridged,
//and the sketch test drives each motor. (There will be a break when the overtaken motor
//channel is activated.)
//
//This also shows how to count the number of connected slaves and report, as well as
//arbitrary register access.

#include <Arduino.h>
#include <stdint.h>
#include "SCMD.h"
#include "SCMD_config.h" //Contains #defines for common SCMD register names and values
#include "Wire.h"

//#defines

//Variables
//***** Create the Motor Driver object*****//
SCMD myMotorDriver;

void setup()
{
  Serial.begin(9600);

  Serial.println("Starting sketch.");

  //***** Configure the Motor Driver's Settings *****//

  //  .commInter face can be I2C_MODE or SPI_MODE
  myMotorDriver.settings.commInterface = I2C_MODE;
  //myMotorDriver.settings.commInterface = SPI_MODE;

  //  set address if I2C configuration selected with the config jumpers
  myMotorDriver.settings.I2CAddress = 0x5A; //config pattern "0101" on board for address 0x5A
  //  set chip select if SPI selected with the config jumpers
  myMotorDriver.settings.chipSelectPin = 10;

  delay(2500); //Give the serial driver time to check for slaves

  //  initialize the driver and enable the motor outputs
  uint8_t tempReturnValue = myMotorDriver.begin();
  while ( tempReturnValue != 0xA9 )
  {
    Serial.print( "ID mismatch, read as 0x" );
    Serial.println( tempReturnValue, HEX );
    delay(500);
    tempReturnValue = myMotorDriver.begin();
  }
  Serial.println( "ID matches 0xA9" );

  Serial.print("Waiting for enumeration...");
  while ( myMotorDriver.ready() == false );
  Serial.println("Done.");

  //  Report number of slaves found
  uint8_t tempAddr = myMotorDriver.readRegister(SCMD_SLV_TOP_ADDR);
  if ( tempAddr >= START_SLAVE_ADDR )
  {
    Serial.print("Detected ");
    Serial.print(tempAddr - START_SLAVE_ADDR + 1); //Top address minus bottom address + 1 = number of slaves
    Serial.println(" slaves.");
  }
  else
  {
    Serial.println("No slaves detected");
  }

  //Configure bridging modes
  myMotorDriver.bridgingMode( 1, 1 ); //( DriverNum 1, bridged state = 1 )  This will bridge the first slave

  //Uncomment to set inversion

  //myMotorDriver.inversionMode(0, 1); //invert master, channel A
  //myMotorDriver.inversionMode(1, 1); //invert master, channel B
  //myMotorDriver.inversionMode(2, 1); //invert slave 1, channel A
  //    no need to configure motor 3, this position does nothing because the slave is bridged.
  //myMotorDriver.inversionMode(4, 1); //invert slave 2, channel A
  //myMotorDriver.inversionMode(5, 1); //invert slave 2, channel B

  //Enable the motors.
  myMotorDriver.enable();

  pinMode(8, INPUT_PULLUP);

}

void loop()
{
  //***** Operate the Motor Driver *****//
  //  This walks through all 34 motor positions driving them forward and back.
  //  It uses .setDrive( motorNum, direction, level ) to drive the motors.
  //
  //  Notice that when i == 3, no motor spins.  This position is made inactive by bridging the first slave.
  Serial.println("Now stepping through the motors.");
  for (int i = 0; i < 6; i++)
  {
    Serial.print("Driving motor ");
    Serial.println(i);

    myMotorDriver.setDrive( i, 1, 255); //Drive motor i forward at full speed
    delay(1000);
    myMotorDriver.setDrive( i, 0, 255); //Drive motor i backward at full speed
    delay(1000);
    myMotorDriver.setDrive( i, 1, 0);
  }
}

The example works by counting through the 6 motor positions and commanding them forward, then back.

Things to note:

  • Only a single SCMD object is used, all slaves are accessed through the master.
  • begin is periodically ran until the returned ID word is valid.
  • Setup waits for isReady() to become true before going on to the drive section
  • Slaves are counted by directly accessing the registers. ALL_CAPS_VALUES are #defined in SCMD_config.h.
  • bridgingMode( … ) is called to bridge, by number of motor driver (master is driver 0).
  • Motor 3 is excluded because the channel gets connected to motor 2 by brdiging. Though it can still be commanded, it will have no effect.
  • enable() is called to activate the motors. This happens after the bridging configuration is set to protect the drivers.

Resources and Going Further

Advanced Features

The advanced features such as configuring the fail safe, data rates, diagnostic features, and bridging can be found in the following document. Use a PDF viewer that supports bookmarks for easiest navigation.

Not covered in this guide:

  • VCC breakable to allow up to 5.5v levels.
  • PSoC programming port.
  • Bus diagnostic reporting
  • Configurable failsafe time and operation
  • Configurable expansion bus bitrate to 50, 100, or 400 kHz.
  • Configurable expansion bus update rate from 1ms to 255ms, or by command only.

Additional Examples

There are also some additional examples packaged with the library which are not described here. Have a look at them and the arduino library source files to better understand the advanced usage.

Arduino examples not covered in this guide:

  • RegisterRWTool – Use to convert ascii communication from a Arduino window into direct register access.
  • Run-timeDiagnostics – Demonstrates reading the diagnostic registers and using the built-in diagnostic structure for data storage.

Robot examples available by github repo XbeeTeensyXCVR:

  • HamburgerBot – Two wheeled robot using digital inputs that emulate analog drive behavior.
  • DualDriveBot – Double wheeled robot using analog sticks to provide smooth single stick driving.

These robots are built using the serial controlled motor driver, with an XBee link.

Check out more robot action in the SCMD demo video:


For more motor-driving action, check out these other great SparkFun tutorials:

Big Easy Driver Hookup Guide

How to get started with the SparkFun Big Easy Driver.

Hacker in Residence: The Harmonic Skew Zoetrope

Check out Hacker in Residence, Jesse's awesome Harmonic Skew Zoetrope in this project tutorial.

Experiment Guide for RedBot with Shadow Chassis

This Experiment Guide offers nine experiments to get you started with the SparkFun RedBot. This guide is designed for those familiar with our SparkFun Inventors Kit and want to take their robotics knowledge to the next level.

Continuous Rotation Servo Trigger Hookup Guide

How to use the SparkFun Continuous Rotation Servo Trigger with continuous rotation servos, without any programming!

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

nRF52832 Breakout Board Hookup Guide

$
0
0

nRF52832 Breakout Board Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

The nRF52832 is Nordic Semiconductor’s latest multiprotocol radio system-on-chip (SoC). It’s half microcontroller, with a list of features including 32 configurable I/O pins, SPI, I2C, UART, PWM, ADC’s, 512kB flash, and 64kB RAM. And, it’s half 2.4GHz multiprotocol radio, supporting Bluetooth low energy (BLE), ANT, and Nordic’s proprietary 2.4GHz ultra low-power wireless communication – it even features on-chip NFC tag support.

SparkFun nRF52832 Breakout

WRL-13990
$19.95

SparkFun’s nRF52832 Breakout provides easy access to all of the chip’s features. It breaks out all of the nRF52’s I/O pins, provides a 32.768kHz RTC crystal, a user-programmable button and LED, and a trace antenna to send and receive those 2.4GHz transmissions. Plus, to make the chip as easy-to-flash as possible, the breakout comes pre-programmed with a serial bootloader.

Covered In This Tutorial

This tutorial is a comprehensive getting started guide for the SparkFun nRF52832 Breakout. It documents hardware features of the board, and includes tips on getting a computer set up for nRF52832 software development. Programming the chip via the serial bootloader using the Arduino IDE is the primary focus of the latter half of the tutorial.

Bill of Materials

To follow along with this tutorial – and to get your nRF52832 Breakout up-and-running – you’ll need a few additional components.

To program the board, we recommend interfacing the breakout board with a SparkFun Beefy 3 - FTDI Basic Breakout. In addition to providing a USB-to-serial programming interface, this board will also be able to fully-power the nRF52832 breakout. The less-beefy 3.3V FTDI Basic can also be used to program the board, but we recommend finding an alternative power supply to power the nRF52832 board. Whichever USB-to-serial converter you go with, don’t forget the USB cable!

USB microB Cable - 6 Foot

CAB-10215
$4.95
7
SparkFun Beefy 3 - FTDI Basic Breakout

DEV-13746
$14.95

To interface the nRF52832 Breakout with the FTDI, you’ll need to solder a 6-pin strip of headers to the board’s serial interface. We recommend right-angle headers for this job, but the straight or long headers can also get it done. Grab some extra male headers – or even female headers– if you plan on connecting to any of the I/O pins.

Break Away Headers - Straight

PRT-00116
$1.5
20
Break Away Male Headers - Right Angle

PRT-00553
$1.95
4
Break Away Headers - 40-pin Male (Long Centered, PTH, 0.1")

PRT-12693
$0.75
1

Finally, to complete the Bluetooth connection, you’ll need a BLE-equipped smartphone. This tutorial documents how to use the nRF52832 with Nordic’s free, open-source nRF Toolbox and nRF Connect apps, which are available on both iOS and Android devices.

nRF Toolbox

nRF Toolbox

    nRF Connect

nRF Connect

Suggested Reading

The nRF52832 Breakout is an intermediate-to-advanced level board, but don’t let that scare you off! This tutorial should be able to walk you through getting started with the board regardless of your skill level. That said, we do recommend that you’re familiar with the topics covered in these tutorials:

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

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.

Bluetooth Basics

An overview of the Bluetooth wireless technology.

SparkFun USB to serial UART Boards Hookup Guide

How to use the SparkFun FTDI based boards to program an Arduino and access another serial device over the hardware serial port, without unplugging anything!

Hardware Overview

Nordic’s nRF52832 is a system-on-chip (SoC) that combines an ARM Cortex-M4F microprocessor with a 2.4GHz multiprotocol radio. In addition to providing access to all of the chip’s I/O pins, the breakout board also includes a handful of external components. The annotated image below summarizes the breakout board’s features:

Annotated top diagram of nRF52832 Breakout

Powering the nRF52832 Breakout Board

The nRF52832 can operate on a power supply between 1.7 and 3.6V. The board also includes a 3.3V regulator with a maximum input of 6V, in case you want to power the board with batteries or a regulated wall supply.

The power input pins are located toward the bottom side of the board. Each of the header rows includes a “GND”, “VIN” and “3.3V” supply input. The “VCC” and “GND” pins on the 6-pin serial header can also be used to power the board (assuming the jumper is closed, more on that later).

Power supply inputs

The VIN pin feeds into the on-board regulator, which brings the voltage down to 3.3V to supply the nRF52832. The regulator can supply up to 600mA – way more than the nRF52832 should ever need. If you’re powering via regulator, you can use the 3.3V pins as outputs to supply external components.

Note that the maximum input to the 3.3V regulator (into the VIN pin) is 6V!

Alternatively, you can skip the regulator and supply the nRF52832 directly by using the 3.3V pin. Voltage supplied here doesn’t necessarily have to be 3.3V – it can be anywhere between the SoC’s 1.7V and 3.6V operating range – so you can use a coin cell battery, or a pair of alkaline batteries to power the chip.

The red power LED is tied to that “3.3V” bus as well. If it’s lighting up, your nRF52832 should be getting power.

32 Multipurpose I/O Pins

The nrF52832’s microprocessor features an array of hardware peripherals, including three SPI– configurable as either master or slave, two I2C interfaces, and a UART (with optional flow control). On top of the serial interfaces, the chip also features 8 ADC pins and three hardware PWM outputs. Each of the 32 I/O pins can be assigned almost any function, so you can move those interfaces around the board as you see fit.

Serial Communication

Asynchronous serial communication concepts: packets, signal levels, baud rates, UARTs and more!

Serial Peripheral Interface (SPI)

SPI is commonly used to connect microcontrollers to peripherals such as sensors, shift registers, and SD cards.

Analog to Digital Conversion

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

I2C

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

There are just a few functions that are assigned static pins:

  • For your real-time counting (RTC) needs, a 32.768kHz crystal is connected to pins 0 and 1.
  • Pin 6 is connected to a momentary push-button, which serves an important function during bootloading.
  • Pin 7 is tied to an LED. It’s active-low, so pull the pin to ground to turn the LED on.
  • Pins 26 and 27 were chosen as the RX and TX UART pins. They can be re-assigned in a user-application but are stuck as the serial pins during the bootloader’s operation.
  • Pin 21 also doubles as an active-low reset input.
  • The nRF52832’s NFC capability can be supported by an antenna connected to pins 9 and 10.

Setting the Solder Jumpers

The back side of the nRF52832 Breakout is filled with jumpers to help you customize the operation of your board. They’re labeled with an abbreviation of their purpose.

Board bottom side with jumpers highlighted

The jumpers that default closed can be sliced open with a hobby knife, while those jumpers that default open can be closed with a small application of solder.

Jumper LabelDefaultNotes
FTDI VCC-ENClosedConnects 6-pin serial header VCC to 3.3V bus.
PWR-LEDClosedEnables or disables the red power indicator LED.
1/2 (NFC)OpenConnects GPIO 9 and 10 to NFC antenna tuning capacitors.
RTC-ENClosedConnects GPIO 0 and 1 to a 32.768kHz RTC crystal.

FTDI VCC-EN - Power via 6-Pin Serial Connector

This jumper controls whether or not an FTDI Breakout connected via the 6-pin serial connector can supply power to the nRF52832. By keeping this jumper to closed, you’ll be able to power the nRF52832 with the same device used to program it.

You may want to cut the jumper if you’re powering the board externally. Also consider opening the jumper if you’re using a 3.3V FTDI Basic (the non-“beefy” version), which may not be able to source enough sustained power to supply the chip.

PWR-LED - Turn Off the Power LED

One of the nRF52832’s most important features is its low-power capability. If your application needs to run for months on a single battery and you’re making full-use of the nRF52832’s ultra-low power sleep modes, the 1-2mA of current pulled by the LED may relatively dwarf the current draw of the microcontroller.

Cutting this jumper will effectively disable the power LED. You won’t always have a visible power indicator, but you’ll be able to save a lot of power!

1 & 2 - NFC Antenna Tuning Capacitors

One of the most unique features of the nRF52832 is its NFC tag support – it can transmit data to a nearby NFC-compatible device, or even be programmed to wake-from-sleep in the presence of an NFC field.

To use the NFC feature, a 13.56 MHz antenna must be connected to GPIO pins 9 and 10. Most NFC antennae also require a pair of tuning capacitors between the antenna pins and ground. The NFC jumpers can be closed to connect each of the NFC antenna pins to a 180pF capacitor.

NFC tuning caps from schematic

NFC tuning caps and enable jumpers, from the nRF52832 Breakout schematic.

This cap value may not be perfect for every antenna, but it should support a relatively wide range of antenna inductances. We tested it successfully with an Abracon ANFACA-4545-A01 and a Pulse Electronics W7001.

RTC-EN - Connect/Disconnect the 32.768kHz Crystal

The nRF52832 Breakout equips the chip with a 32.768kHz crystal – connected to GPIO pins 0 and 1. Unfortunately, those pins make up a quarter of the available ADC inputs. So, if your application doesn’t require an RTC – and you need those pins to for another purpose – grab a hobby knife and cut the two traces between their pads to disconnect the crystal.

Hardware Assembly

To program the chip, and to use any of the nRF52832’s 32 I/O, you’ll need to solder something to its headers. In the least, we recommend soldering right-angle male headers or straight male headers onto the six-pin serial header. Either of these will interface easily with the FTDI Basic and Beefy Breakouts.

six-pin right-angle header soldered into serial port

Solder a six-pin right-angle header into the serial port to interface it with an FTDI Beefy 3.

The remaining two rows of vias are breadboard-compatible, so you can solder male pins into both and have it straddle a breadboard.

male headers soldered into both header rows, making it breadboard-compatible

Solder straight male headers into the pair of header rows to make the breakout breadboard-compatible.

Or you can solder wire, female headers, or anything else your project requires into those remaining holes.

Adding Arduino Compatibility

Arduino isn’t the most powerful IDE out there, nor is it the most versatile, but it does make things easy if you’re just getting started with a new platform. Fortunately, there’s an nRF52 Arduino board addon available for just that purpose! This section details how to install the nRF52 Arduino libraries, cores, and tools.

Download and Install the Board Package

The nRF52 Arduino cores are based on the great work by sandeepmistry. We’ve added nRF52832 Breakout Board compatibility to his board files, and added an extra tool to enable serial bootloading.

To install support for the nRF52 board in Arduino, begin by opening your Arduino preferences (File > Preferences). Then copy and paste the URL below into the “Additional Board Manager URLs” text box.

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

Adding the additional board manager URL

Then hit OK, and navigate to the Tools>Board>Boards Manager… tool. A search for “nRF52” should turn up a SparkFun nRF52 Boards result. Select that and click install.

nRF52832 Board Manager installation

The install may take a few minutes – the package includes arm-gcc and a few other tools totaling around 100 MB. Once the installation is complete, go to Tools>Board and select “SparkFun nRF52832 Breakout” under the “Nordic Semiconductor nRF5 Boards” section.

SparkFun nRF52832 Breakout Arduino Board selection

Programming via Bootloader

The nRF52832 Breakout ships out with a pre-programmed serial bootloader, so you don’t need a specialized JTAG programmer to load code onto it. You do, however, need an FTDI Basic (or an FTDI Basic -like device) to set up a serial interface between your computer and the breakout.

Connecting the FTDI to the Breakout

The FTDI Basic mates up with the nRF52832’s 6-pin serial header. Match up the “BLK” and “GRN” labels, and slide the boards together.

FTDI Beefy 3 connected, providing power and a programming interface

You should see the red power LED illuminate. If it doesn’t power up, make sure you haven’t disabled the FTDI-VCC EN jumper on the back of the board.

Triggering the Bootloader

Unfortunately, the nRF52832 Breakout’s bootloader doesn’t feature an auto-reset function like many Arduino’s. To decide whether to enter the bootloader or run its application code, the nRF52832 samples the state of GPIO 6 when it boots up. If pin 6 is LOW, it enters the bootloader, otherwise it boots into its programmed application

So, to boot the nRF52832 into its bootloader you must reset the chip while holding down the pin 6 button. In step-by-step form, the trick to resetting into the bootloader is:

  1. Press down on both the RESET and 06 buttons.
  2. Release reset.
  3. Verify that the blue (pin 7) LED begins blinking.
  4. Release the 06-labeled user button.

example button pressing to get into bootloader mode

While in bootloader mode, the nRF52832’s blue LED on pin 7 should blink at increasing speed in what we call the “timebomb” sequence.

This is, admittedly, a little tricky and a lot annoying to perform before every program, but it’s the trade-off we get for not programming via expensive JTAG programmers. Once you’ve entered the bootloader, you can upload code to the chip via Arduino’s “Upload” button.

Upload Blink

Try loading up a basic blink example – setting the blinking pin to the on-board LED on pin 7 – and uploading. Here’s some code to copy paste:

language:c
const int ledPin = 7;

void setup()
{
    pinMode(ledPin, OUTPUT);
}

void loop()
{
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
}
LED Polarity– The blue LED, attached to pin 7, is active-low. Writing the pin LOW will turn the LED on, and writing it HIGH will turn it off.

Troubleshooting

If you get an upload error like this:

Failed to upgrade target. Error is: No data received on serial port. Not able to proceed.

Possible causes:

- bootloader, SoftDevice or application on target does not match the requirements in the DFU package.
- baud rate or flow control is not the same as in the target bootloader.
- target is not in DFU mode. If using the SDK examples, press Button 4 and RESET and release both to enter DFU mode.


Make sure your nRF52832 Breakout’s LED is blinking in a ticking-timebomb pattern – ensuring that it’s in bootloader mode. If the chip is in the bootloader and still not accepting code, try cycling power to the breakout by disconnecting and reconnecting the FTDI Basic.

BLEPeriphial Arduino Library

The nRF5 board definitions will allow you to program the nRF52832 and toggle its GPIO, but it doesn’t include any Bluetooth support. For that, we recommend grabbing the BLEPeripheral Arduino library.

The BLEPeripheral library can be installed from Arduino’s Library Manager. Simply go to Sketch>Include Library>Manage Libraries…. In the search box, type “BLEPeripheral”, select it, and click “Install.”

Installing the BLEPeripheral library

Alternatively, the library can be installed by downloading the latest version from the GitHub repository. Follow along with our Installing an Arduino Library tutorial for help installing the library via this method.

Here are a few examples that show as bare-bones as possible what it takes to turn your nRF52832 Breakout into a BLE peripheral. This first example allows you to control the board’s pin 7 LED from your smart phone – using the nRF Connect app. It’s the Blink sketch of the BLE world!

To test the Bluetooth connection, you’ll need to pair the breakout board with another Bluetooth-compatible device. Most modern smartphones can fit that bill.

You'll also need a BLE application installed on your phone – something that lets you connect to devices and fiddle with or read their characteristics. There are a handful of Bluetooth debugging applications out there that can help get you started communicating via Bluetooth. PunchThrough’s LightBlue Explorer is one of our favorite’s, but it’s only available for iOS. Nordic’s nRF Connect– available for both iOS and Android devices – is another good choice. That’s what we’ll document here.

The Code

Copy and paste the code below into your Arduino IDE.

language:c
// Import libraries (BLEPeripheral depends on SPI)
#include <SPI.h>
#include <BLEPeripheral.h>

//////////////
// Hardware //
//////////////
#define LED_PIN    7 // LED on pin 7
#define LED_ACTIVE LOW // Pin 7 LED is active low
#define LED_DEFAULT LOW

///////////////////////
// BLE Advertisments //
///////////////////////
const char * localName = "nRF52832 LED";
BLEPeripheral blePeriph;
BLEService bleServ("1207");
BLECharCharacteristic ledChar("1207", BLERead | BLEWrite);

void setup()
{
  Serial.begin(115200); // Set up serial at 115200 baud

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, !LED_ACTIVE);

  setupBLE();
}

void loop()
{
  blePeriph.poll();

  if (ledChar.written())
  {
    int ledState = ledChar.value();
    if (ledState)
      digitalWrite(LED_PIN, LED_ACTIVE);
    else
      digitalWrite(LED_PIN, !LED_ACTIVE);
  }
}

void setupBLE()
{
  // Advertise name and service:
  blePeriph.setDeviceName(localName);
  blePeriph.setLocalName(localName);
  blePeriph.setAdvertisedServiceUuid(bleServ.uuid());

  // Add service
  blePeriph.addAttribute(bleServ);

  // Add characteristic
  blePeriph.addAttribute(ledChar);

  // Now that device6, service, characteristic are set up,
  // initialize BLE:
  blePeriph.begin();

  // Set led characteristic to default value:
  ledChar.setValue(!LED_ACTIVE);
}

Then upload the code to your Breakout, using the instructions from the previous section.

Use the nRF Connect to Test

Upon opening nRF Connect, you’ll be presented with a list of nearby Bluetooth devices. If you’re in the SparkFun offices – or otherwise surrounded by coworker’s with way too many Bluetooth devices – your list may include page(s) of device names. Look for “nRF52832 LED”, and click the “Connect” button next to that. (Note: until you connect to the breakout, it may, instead, advertise the name “Arduino”.)

nRF Connect device list

You can set the device name -- replacing "nRF52832 LED" -- with the blePeripheral.setDeviceName([name]) function.

Click “Connect” on the nRF52832 LED device, and you’ll be sent over to the “Services” view. From there, click “Unknown Service” – the UUID string should match that of the bleServ object in your example code.

This next interface takes some experimenting to figure out. The down arrows represent reads, the up arrows allow you to write to a characteristic, and the triple-down-arrow turns notify on or off. To begin, tap the up arrow next to the top “unknown service”. This will allow you to control the state of the LED. In the box that opens up, try entering either 00 or 01, which should turn the LED either off or on, respectively.

Writing a 0x01 to the LED characteristic

After tapping “Send” you should see the LED change state.

BLE Button Example

This example demonstrates how to use the BLE read and notify features. It monitors the button on pin 6 of the nRF52832 Breakout. When the button state changes a BLE notification is sent.

The Code

Using the BLEPeripheral library, upload this code to your Breakout:

language:c
// Import libraries (BLEPeripheral depends on SPI)
#include <SPI.h>
#include <BLEPeripheral.h>

//////////////
// Hardware //
//////////////
#define BTN_PIN    6 // BTN pin on 6
#define BTN_ACTIVE LOW

///////////////////////
// BLE Advertisments //
///////////////////////
const char * localName = "nRF52832 Button";
BLEPeripheral blePeriph;
BLEService bleServ("1234");
BLECharCharacteristic btnChar("1234", BLERead | BLENotify);

void setup()
{
  Serial.begin(115200); // Set up serial at 115200 baud

  pinMode(BTN_PIN, INPUT_PULLUP);
  digitalWrite(7, HIGH);

  setupBLE();
}

void loop()
{
  blePeriph.poll();

  // read the current button pin state
  char buttonValue = digitalRead(BTN_PIN);

  // has the value changed since the last read
  bool buttonChanged = (btnChar.value() != buttonValue);

  if (buttonChanged)
  {
    // button state changed, update characteristics
    btnChar.setValue(buttonValue);
  }
}

void setupBLE()
{
  // Advertise name and service:
  blePeriph.setDeviceName(localName);
  blePeriph.setLocalName(localName);
  blePeriph.setAdvertisedServiceUuid(bleServ.uuid());

  // Add service
  blePeriph.addAttribute(bleServ);

  // Add characteristic
  blePeriph.addAttribute(btnChar);

  // Now that device, service, characteristic are set up,
  // initialize BLE:
  blePeriph.begin();
}

Use the nRF Connect to Test

Use nRF Connect to connect to your nRF52832 Breakout – just like last time. This time the name of the device should change to nRF52832 Button (if it’s still “LED”, try connecting anyway – sometimes the local ID doesn’t change until you’ve connected to it).

Tap into the “Unknown Service” again, but, this time, try tapping the single-down arrow to read the service’s characteristic. This will read the state of the nRF52832 Breakout’s pin 6 button. While the button is un-actuated, the value of the property should be 0x01. If you can hold the button down while also tapping the single-down arrow, the value should change to 0x00.

Reading the nRF52832's button in nRF Connect

Activate notify by tapping the triple-down-arrow. Then when you press the button, the value should automatically update.

You can also try setting the characteristic to notify, by tapping the triple-down arrow. In this mode, the value should automatically be notified when there’s a change in state. Press and release the button to see the value change from 0x00 to 0x01.

Resources & Going Further

There are loads of resources available to you as you continue on in your nRF52832 development.

Hardware Resources

The nRF52832 Breakout is open-source hardware. Feel free to browse our EAGLE design files, download schematics and follow the products lifecycle on our GitHub repository.

For more on the nRF52832, your first visit should be to the “Documentation” and “Downloads” tabs of Nordic’s nRF52832 Product Page. There you’ll find loads of datasheets, user manuals, and software tools.

If you feel hamstrung by the bootloader and want to begin JTAG'ing and debugging the nRF52832 with a more robust tool, consider grabbing the nRF52832 Hardware Development Kit. You can even use it to program the nRF52832 via the SWD protocol.

Using the nRF52832 Development Kit to program the Breakout board

For faster programming, an nRF52832 Development Kit can be used to program the nRF52832 Breakout Board.

(The nRF52832’s single-wire debug – SWD – pins are broken out to test points near the NFC antenna pads – labeled “C” and “D” for SWDCLK and SWDIO.)

Software Resources

The pair of Arduino examples in this tutorial barely scratch the surface of the nRF52832 and the BLEPeripheral library’s capabilities. For more on the BLEPeripheral library, we recommend checking out the included examples, under the File>Examples>BLEPeripheral menu in Arduino. When you begin creating BLEPeripheral sketches of your own, we recommend checking out the library’s API.

The nRF5 SDK– Nordic’s software development kit for the nRF51 and nRF52 series chips – is an amazing suite of software and example applications. All you need to set the toolchain up is ARMGCC (the SDK also supports Keil and IAR, if you’ve already shelled out for those options). The SDK is rife with examples which demonstrate all of the nRF52832’s BLE capabilities, plus ANT, NFC, and all of the chip’s hardware peripheral features.

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

ATmega128RFA1 Dev Board Hookup Guide

A hookup example guide for SparkFun's ATmega128RFA1 Development Board. Includes a schematic/board overview and explanation, and example code.

SparkFun RFID Starter Kit Hookup Guide

Learn the basics of Radio Frequency Identification (RFID) and how to get started with the SparkFun RFID Starter Kit.

Si4703 FM Radio Receiver Hookup Guide

Add some tunes to your project with the Si4703 FM Radio Receiver Breakout.

SparkFun Inventor's Kit for Edison Experiment Guide

Learn how to harness the power of the Intel® Edison using JavaScript to post data to the cloud, control electronics from smartphones, and host web pages that interact with circuits.

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>