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

WAV Trigger Hookup Guide

0
0

WAV Trigger Hookup Guide a learn.sparkfun.com tutorial

Introduction

The WAV Trigger is a development platform that allows you to easily add music and sound effects to your project. The WAV Trigger plays uncompressed WAV files up to 16-bit stereo 44.1kHz, the same quality as audio CD’s. One significant feature is that the board has the ability to play multiple tracks at the same time, mixing up to 8 stereo tracks together on the fly. The board has a audio jack and a 2-pin output that can be connected to either headphones or speakers for audio output.

Tracks are played when some type of condition is met. For example, the most basic use is to connect a button between ground and a trigger. By default, when the button is pressed, the track (.WAV file) on the micro SD card to that corresponds to that trigger will be played. There are more advanced options that can be created with a configuration file that allows triggers to play random tracks, pause tracks, and change volume, amongst other operations.

The WAV Trigger

In addition to using buttons and switches, sounds can be triggered by the digital outputs of microcontrollers or sensors. This can allow for many interesting uses of this product that depend on environmental stimuli. There are various ways to configure your board, which we’ll detail later in the tutorial.

We will also explain how to use the WAV Trigger’s applications for configuration, flashing new firmware, or controlling the board remotely with a serial connection. Download these applications with the links below for either Windows or Mac.

Required Materials

The beauty of the WAV Trigger is that you can make it as simple or as complex as you want. However, to follow along with this tutorial you will need a few things besides just a WAV trigger board. At the very least you will need some wire to connect your triggers to ground and test them out. You may also want to grab some male and/or female headers, some buttons and switches, and a Micro SD card to store the files you want to trigger. For software debugging, configuration settings, and testing you’ll need a USB mini-B cable and an FTDI Basic.

In addition to the hardware mentioned above, you’ll need to download the WAV Trigger Applications to follow along.

Suggested Reading/Viewing

Before you begin, you should watch the WAV Trigger Demo Video. It goes over both the basic and advanced features of the WAV Trigger.

This tutorial builds upon some other concepts. Check out any that you may be unfamiliar with before continuing.

Hardware

Let’s take a look at the WAV Trigger’s hardware so we can get an idea of where things are and how to use the board.

The bits and pieces of the WAV Trigger used for operation

  1. The barrel jack is where you supply power. Alternatively, you can use the nearby VIN and GND via’s for supplying power. Either way, any input voltage between 6V and 15V will work.

  2. There is a run/load switch that should always be set to run when you are using the board normally. The board is set to load only when updating the firmware on the ARM processor, which is done before hand at SparkFun. It will only be necessary to put the switch into the load setting if there is a newer version of firmware that you would like to use.

  3. The micro SD card is where your .WAV files and optional configuration file are stored. This micro SD card works well with the board and also includes a micro SD USB Card Reader for transferring the files to/from your computer.

  4. The audio jack is the standard 3.5mm variety and can be used with headphones or speakers of your choice. There is also a 2 pin header for directly wiring and soldering a speaker such as this to the board itself.

  5. The FTDI port is used to program the firmware or can be used with the WAV Trigger’s Remote Control App to test triggers using your computer instead of hardware. This way, you can test triggering tracks before soldering hardware to the actual trigger ports. The FTDI port can also be used in conjunction with WAV Trigger’s Initialization Editor so when you set a trigger to a non default function such as playing a random track, you can experiment with the trigger’s functionality without first having to put the configuration file on the SD card. We will explain more about configuration and testing triggers with the computer later on. To use this port, consider an FTDI Basic.

  6. This button, by default, triggers the first track on the memory card. A future release of the firmware may allow you to modify its functionality.

  7. The row of 16 triggers are the core of this board’s utility. These are what we are going to use to start the playing of music or sound effect tracks on the SD card. We’ll also learn how to use them for more advanced options like playing a random track or changing volume with the help of a configuration file. Keep in mind, ground connections are closest to the edge of the board and are there for convenience to be used along with a trigger. The actual triggers are the second row from the edge.

Now that we have an understanding of the board’s hardware, let’s dive a bit deeper into what you can do with it.

Operation

The Basics

By default, each trigger will cause its corresponding track to play when it is connected with ground. For example, first place a track on the micro SD card called 001-example-name.WAV. The name doesn’t matter as long as it starts with 001 and is a WAV audio file. Plug the microSD card into the WAV Trigger. Power the board with a source that can provide between 6V and 15V, and connect headphones or speakers.

Using a stripped piece of wire, connect the via for T1 with the via for GND (no soldering necessary). This shorts trigger 1 to ground, causing track 001 to play. You could also solder a switch or button between the T1 and GND connections so that they trigger the sound. Trigger 1’s sound file will continually play while it’s held to ground.

The other triggers will work the same way by default. For example, if you have a file named 012-music.WAV on your SD card, connecting Trigger 12 (T12) to ground (GND) will cause this file to play. If you play this track while trigger 1 or another track is still playing, the two will mix together, since polyphony is enabled by default, and you will hear both at the same time. This allows you to mix music with sound effects or whatever else you desire.

Here are some sample tracks with which to experiment.

Note: If you are using a microcontroller or sensor to trigger the tracks, make sure you are matching up your logic levels. You may need to use oneofourlogic level converters.

Extra Features

There are many other ways of using these triggers including playing random tracks, pausing tracks, or even changing volume as it plays. These features will be discussed in detail since they require configuration with the InitMaker application. This app allows you to change how each trigger works, test them, and then save your setup to put on the SD card along with your tracks. If you have not downloaded the app, now would be a good time. Here are the links again:

Here is a picture of the InitMaker, which we’ll use to test different methods of setting up a trigger and make our configuration file to put on the SD card so the board’s triggers behave the way we want.

A screenshot of the WAV Trigger's InitMaker application

Let’s go over each setting, piece by piece.

Trigger - This selects which trigger’s functionality we are changing.

Hardware Interface - In short, use “Contact Closure” for when you’re connecting triggers to buttons or switches. The trigger will start if physically connected to ground, and otherwise will be high due to an internal pull-up resistor. Use “Active – 3.3V/5V” with active devices like microcontrollers or sensors. If this is selected, the trigger will be activated if connected to a high signal (3.3V or 5V) and will otherwise remain low due to an internal pull-down resistor.

Type - By default, “Edge Triggered” starts the track when the trigger first goes active, and the track continues to play until stopped by some other event. “Level Triggered” starts the track when the trigger goes active, but the track plays only as long as the trigger remains active.

Function - This option selects the function that the trigger will perform. Some of the functions require that a range of tracks be specified, and the values in the range can be from 1 to 999.

“Normal”, the default function, directs the WAV Trigger to play the corresponding track number.

“Next” plays the next track in the specified range, starting with the low track and wrapping back to that track after playing the high track in the range.

“Previous” plays the previous track in the specified range, starting with the highest track and wrapping back to that track after playing the lowest track in the range.

“Random” plays a random track from the specified range. It will not play the same track twice in a row.

“Pause” will pause all the tracks in the specified range. These tracks will remain paused until they are resumed or restarted. Combining with the “Level Triggered” type option creates a momentary Pause feature; The specified tracks will resume when the trigger is released.

“Resume” will resume all the tracks in the specified range, provided that they are still “paused”.

“Stop” will stop all the tracks in the specified range. Combining with the “Level Triggered” type option will create a “Stop and Inhibit” function, preventing all the tracks in the range from restarting as long as the trigger remains active.

“Volume Up” or Volume Dn” will re-purpose the trigger to be a volume control. Each activation of the trigger will increase or decrease the output stage volume of the WAV Trigger by 1dB.

Invert - This check box will invert the logic of the trigger. The default is active low. Checking this option makes the trigger active high. This is automatically checked when selecting an “Active 3.3V/5V” hardware interface.

Re-Triggers - This option enables certain trigger functions to work again immediately while the track(s) that they may have previously started is(are) still playing. For example, with the “Normal” trigger function, enabling this option allows the trigger to restart the corresponding track, even if it has not finished playing, while disabling this option prevents the trigger from working until the track has finished playing (or is stopped by some other event.) Similarly, for the “Next”, “Previous” and “Random” functions, disabling this option prevents the trigger from working until whatever track was previously started from this trigger is finished. This is enabled by default.

Polyphonic - This option specifies that the track played by the trigger function can be mixed with any track(s) currently playing. When this option is disabled, activating the trigger will stop any and all tracks that are currently playing before the new track is started.


Now that you have a sense of the possibilities, let’s walk through an example of testing a custom trigger and initialization file.

Example

For this example, make sure you have the sample WAV files already on your micro SD card and have the card in your WAV Trigger board.

Without any configuration at all, you should be able to play each track by connecting the trigger pin with the ground pin. Each track just says the name of the number of the trigger.

Now to test a custom trigger, we need to use the InitMaker application.

Let’s set up a few triggers as an example. Leave trigger 1 with its default settings. Set trigger 2 to play a random track between 5 and 10. First, select random under the “Function” category, then input 5 and 10 under “Track Range”. Click the Add button below the settings to add it to the configuration file.

Follow the same procedure to setup a few more triggers. Set trigger 3 to pause and trigger 4 to resume. Also set trigger 5 to the hardware interface of “Active 3.3V/5V” used for when we connect microcontrollers or sensors. Remember to click Add after setting up each trigger to add it to the configuration. If you don’t, the settings you input won’t be remembered.

Before creating our initialization file, we can test out a custom trigger, if desired, with a USB mini-B cable and an FTDI Basic. Select trigger 2. It should still be set up to play a random track between 5 and 10. Make sure the correct COM port is selected, the one corresponding to your FTDI, then hit the red Test button. Afterwards, activate trigger 2 by connecting its pin to ground. It should randomly play a track between 5 and 10. If this test doesn’t work, try reconnecting the FTDI Basic, restarting the InitMaker application, or restarting the WAV Trigger itself.

Now that we have set up triggers 1 through 5, let’s save them to a configuration file. Your InitMaker screen should like this if you have it set up the way we described above:

Example Configuration, if you set it up the same, your screen should look just like this

Now, save this configuration using the Save As button in the lower left. The file will need to be called wavtrigr.ini. Put this file on your micro SD card along with the sound files. In case you had trouble making this file, you can download it here.

Also, to demonstrate the pause and resume functions, you may want a longer wav file to play. Here is a longer WAV file you can download if you don’t have any of your own currently. Replace the current file that begins with ‘001’ on your SD card with this track. As a side note, you can convert any of your MP3’s to WAV’s easily with programs like Audacity.

Now that you have your micro SD card loaded with sound files (including new, longer track one) as well as the initialization file we just created, let’s test it out to see if it works.

Connect Trigger 1’s pin to ground, the first track should play. Connect Trigger pin 3 to ground, and track 1 should pause. Connect Trigger pin 4 to ground, and track 1 should resume. Connect Trigger pin 2 to ground, and a random track between 5 and 10 will play. It should mix with track one if it’s still playing, so you’ll hear both at once.

To simulate a microcontroller, connect Trigger pin 5 to the 3.3V pin on the side of the board and track 5 should play. Just be very careful not to accidentally connect 3.3V to the GND pins. Remember, the ground pins are closest to the edge of the board, while the trigger pins are the second row from the edge.

You should now have a good idea of how to make a configuration file and customize your triggers. Keep playing with the various options until they suit your project.

Remote App

Another application you can use to do some basic testing with your WAV Trigger is the Serial Control Utility. This allows you to connect your powered WAV Trigger to a computer with an USB mini-B cable and an FTDI Basic.

When you load the application, it will look like this:

Serial Control Utility for the WAV Trigger

First, select the correct COM port for your FTDI device. Check that you are properly connected by clicking the Get Info button in the top left, and seeing if the Firmware version field is populated. If not, reconnect your FTDI, restart the Control Utility, and/or repower your board before trying again.

Once connected, you can use the Track Control to play tracks on the SD card. As an example, click loop by Track 1 and hit Play Poly. This will continuously play track 1 on your device. Now if you hit Play Poly by Track 2, track 2 will play mixed with the looping track 1. If you hit Play Solo instead, track 1 will stop, and you’ll only hear track 2 play. You can also pause, resume, and stop tracks as well as change the overall volume.

Feel free to mess around with this utility, it’s essentially for getting a quick feel for your tracks and how well they work together without having to mess with wires and physical connections.

Firmware Updates

The final utility you may need to use at some point is the WAV Trigger’s Firmware Flasher Utility. This app allows you to update the firmware on the WAV Trigger should new firmware be released.

This application is very simple. It takes a hex file, the compiled new firmware from the creator at RobertSonics, and updates the firmware on your device. Once again, all you’ll need for this is a USB mini-B cable and a FTDI Basic.

The application looks like this:

WAV Trigger's Firmware Flasher Utility

Simply select the COM port for your FTDI, click Browse, and select the hex file you have downloaded. Then click program. Wait for it to tell you the process is complete, and you can test out the new firmware.

Resources and Going Further

By now, you have a good idea of how to get rocking with the WAV Trigger board and its associated applications. You may even already have plenty ideas of how your going to use this in your future projects.

Enjoy playing and mixing those tracks, and always feel free to share your experiences and creations with us here at SparkFun.

Additional Resources:

Check out these other great audio related SparkFun tutorials:


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


RedBot Assembly Guide

0
0

RedBot Assembly Guide a learn.sparkfun.com tutorial

Introduction

The assembled RedBot kit

The RedBot is robotic development platform capable of teaching basic robotics and sensor integration! Based on the SparkFun RedBoard and programmable in the Arduino environment, the RedBot has all the I/O you need to make a small robot in no time at all.

Required Materials

This assembly guide will cover how to assemble all the following parts:

Suggested Reading

Before you go any further, you should probably make certain that you're familiar with the RedBot:

Preparing the Wheel Encoder

We will be placing screws that will later hold the RedBot Sensor - Wheel Encoder to the bottom chassis. If you do not have a RedBot Sensor - Wheel Encoder, you will want to skip this section and move on to the Motors section on this Assembly Guide.

Locate the following:

  • 1x Bottom chassis piece
  • 2x 4-40 screws
  • 2x Nuts

There are different types of screws in this kit. Make sure you use the 4-40 screws for the RedBot Wheel Encoder.

Picking the right screw

Locate the two positions on the bottom chassis piece where the 4-40 screws will go.

bottom chassis

Place one of the 4-40 screw through the chassis piece in the correct location. This side of the chassis piece will be your bottom side.

Screw going into Bottom Chassis

Tightly screw down the nut on the top side of the chassis piece to hold the screw down.

Screw on the bottom chassis

Add the second 4-40 screw and nut in the correct position on the chassis piece.

Second Screw

Motors

In this section, you will be placing the two motors on the bottom side of the bottom chassis piece. If you are using the RedBot Sensor - Wheel Encoder, please play close attention to what chassis side you are placing the motors on.

Locate the following:

  • 1x Bottom chassis piece
  • 4x Motor holders
  • 2x Motors
  • 2x M3*30 screws
  • 2x Nuts

Locate the correct location on the chassis piece.

Bottom chassis motor graphic

Place one of the motor holders through the right opening in the chassis. If you are using the RedBot Sensor - Wheel Encoder, make sure you are on the top side of the chassis piece. The top side will have the M3*6 nuts showing.

Motor Holder

Push the motor holder all the way down.

Motor Holder all the way down

Place the first motor on the bottom side of the chassis piece. Make sure that the red wire is on top and away from the chassis piece.

Place Motor

Add the speed board to the motor. Make sure the speed board fits in the chassis opening.

Speed Board holder

Now you can add the second motor holder on the opposite side.

Add the second motor holder

Place M3*30 screw through the motor holder and the motor.

Place screw through the motor holder and the motor

Add a M3 nut to the M3*30 screw.

Add nut

Add the second M3*30 screw and nut.

Add the second screw and nut

Using the same steps as above, you can now you can add the second motor on the opposite end on the same side of the chassis piece.

Add second motor

Ball Caster

In this section, you will be adding the ball caster to the bottom side of your bottom chassis piece.

Locate the following:

  • 4x M3*6 screws
  • 2x L25 Metal standoffs
  • 1x Ball caster

There are different types of screws in this kit. Make sure you use the M3*6 screws for this section.

Pick the right screw

Place a M3*6 screw through one of the ball caster's holes. Then screw in one of the L25 standoffs to the ball caster. Please note: the L25 metal standoffs will be longer then the L10 standoffs.

Screw in ball caster

Screw on the second L25 standoff on the other side of the ball caster.

Second stand off on

Locate the two positions on the chassis piece where you will be screwing down the ball caster.

Bottom chassis graphic for ball caster

Now you can use two M3*6 screws to tighten down the ball baster to the bottom side of the chassis piece.

Screw to the chassis

RedBot Wheel Encoder

If you are not using the RedBot Sensor - Wheel Encoder, you may skip to the next section. If you are using the RedBot Sensor - Wheel Encoder, in this section you will be tightening down the RedBot Sensor - Wheel Encoder to the bottom chassis piece.

Locate the following:

With the six pin male header side on the RedBot Sensor - Wheel Encoder facing upwards, place down the encoder on the top side of the bottom chassis piece. Pay close attention that the six pin male header side is also closest to the front side of the chassis. Tighten down the RedBot Sensor - Wheel Encoder on the top side of the bottom chassis piece in the same location in the earlier “Preparing the Wheel Encoder” section in this assembly guide.

Encoder on the board

RedBot Line Followers

In this section, you will be putting standoffs on the RedBot Sensor - Line Followers. Then you will add the sensors on your chassis.

Locate the following:

  • 3x Line followers
  • 2x Nuts
  • 3x 4-40 1" Phillips screw
  • 3x 4-40 ¼" Phillips screw
  • 6x Standoff

Screw a 4-40 1" Phillips screw to the plastic standoff through one of the RedBot Sensor - Line Followers. Make sure to hand tighten the standoff on the line follower’s header side. The top of the screw should be on the same side as the RedBot Sensor - Line Follower’s sensor.

Screw the plastic stand off

You should see part of the 4-40 1" Phillips screw sticking out.

alt text

You will screw on another standoff on top of the one already on the screw. The screw's end should now be covered as pictured below.

Place the second stand off on top

Do this for all three line followers.

Do for all three line followers

Locate three spots on the chassis where you will be adding the RedBot Sensor - Line Followers.

Line Follower location

Using a 4-40 ¼" Phillips screw, tighten down the standoff with a RedBot Sensor - Line Follower into bottom chassis.

Screw into bottom chassis

Using you other two 4-40 ¼" Phillips screws, hand tighten the other two RedBot Sensor - Line Followers.

Do for all three line followers

Wheels

In this section, you will be putting two wheels on the RedBot motors.

Locate the following:

  • 2x Wheels

Place the two tires on the ends of the motors.

Place the two tires on the motors

Make sure the tires are on all the way.

Make sure the tires are on all the way

Standoffs

In order to connect the top chassis piece to the bottom piece, you will need to put stand offs between the two chassis pieces. Follow along to see the best locations to place the metal stand offs.

Locate the following:

  • 4x L25 Metal standoffs
  • 4x M3*6 Screws

Locate the four L25 metal standoff locations.

Stand off locations

Using M3*6 screws, tighten down all four metal standoffs on the top of the bottom chassis piece.

Make sure the stands offs are screwed all the way down

Battery Holder

Before connecting the top chassis piece to the bottom piece, you will want to add the battery holder.

Locate the following:

  • 1x Battery holder
  • 2x M3 - 10 Flathead screw
  • 2x Nuts
  • 1x Top chassis piece

Locate the M3 - 10 flathead screw.

M3 - 10 flathead screw

Locate two positions on the top chassis piece for the screws.

Screw down

Screw down the battery holder.

Screw down the battery holder

Make sure they are screwed down nice and tight on the top chassis.

Back side of top chassis

RedBot MainBoard Standoffs

Since the battery holder is screwed down, it is now easier to add the metal L10 standoffs in the locations where the RedBot Mainboard will go.

Locate the following:

  • 4x M3*6 Flathead screw
  • 4x L10 Metal standoffs

Locate the following locations on the top chassis piece where you will add four L10 Metal standoffs.

Stand offs for RedBot Mainboard

Add all four standoffs on the top chassis piece with the standoffs located on the same side as the battery holder.

All 4 stands on the top chassis piece

Jumper Wires

It will make it easier to connect the sensors to the RedBot mainboard later if you add the jumper wires to the RedBot Sensor - Line Followers and RedBot Sensor - Wheel Encoder now, before screwing down the top chassis piece.

Locate the following:

  • 1x Top chassis piece
  • 2x Standoffs
  • 13x Jumper wires

The motors already have wires, so you won't have to add more jumper wires. You will need to place the motor jumper wires through the top chassis.

Motor Jumper wires through the chassis

Connect one end of the Jumper wires to the Line Followers' headers. Keep in mind you are able to use any jumper wire colors. However, following along with the jumper wire colors this assembly guide may be helpful if this is your first time assembling the RebBot.

Jumper wires to the Line followers

Stick the Line Followers' jumper wires through the top chassis piece.

Stick the Line Followers' jumper wires through the chassis

Add jumper wires to the encoder.

Add jumper wires to the encoder

RedBot Mechanical Bumpers

Read on if you are using the RedBot Sensor - Mechanical Bumpers. If not, skip to the Top Chassis section.

You will need to prepare the music wire by bending the wire itself. Then, you will add standoffs and screws to your bumpers.

Locate the following:

  • 2x 4-40 Nylon standoffs
  • 4x 4-40 Screws
  • 2x Nuts
  • 2x Wire

It is easy to bend the wire with needle nose pliers. However, there is a trick to bend the wire using the Mechanical Bumper PCB itself. First, stick one of the wires through one of the small side holes. It only needs to stick out a little bit.

wire through hole

Bend the wire 90 degrees.

Benting the wire

Bend the wire 90 degrees again.

Benting the wire even more

Now that the wire is bent, take the wire out of the PCB hole. Place a 4-40 screw through the bottom side of one of the bigger holes on the Mechanical Bumper. Then add a 4-40 screw from the bottom and loop the bent wire around the screw. It is very important that you do not let wire touch the other side's nut and 4-40 screw, since that is what triggers the sensor. Leave a little space between the wire and other side's nut.

Wire looped around screw

Twist on a nylon standoff on top of the screw to secure the wire.

Adding standoff

Double check that the wire does not touch the other side's nut and 4-40 screw.

Do not let wire touch

Take note of which side your nylon standoff is on for the first Mechanical Bumper. Do the opposite for the other bumper. Double check that there is one Mechanical Bumper that has a nylon standoff on the right side of the “RedBot Bumper” silkscreen and one that has a nylon standoffs on the left side.

Do the opposite for the other music bumper

Adding the Bumpers

In this section, you will need to screw the Mechanical Bumpers into place on the front end of your RedBot chassis.

Locate the following:

  • 2x 4-40 Screws

Locate the two positions on the top chassis piece.

Top chassis locations for Mechanical Bumpers

Using two 4-40 screws, tighten down the Mechanical Bumpers, with the two wires pointing in opposite directions, on the bottom side of the top chassis piece.

Screw on top of chassis

Add jumper wires to the GND and OUT pins on both of the Mechanical Bumpers. Again, which color jumper wires you choose does not matter, but it might be helpful to follow along with this assembly guide.

Adding jumper wires

Put the other ends of the jumper wires through the top chassis piece.

Putting the jumper wires through the chassis

Make sure the jumper wires are all the way through.

Make sure the jumper wires are all the way through

Top Chassis

Now it is time to connect the top chassis piece to the bottom chassis piece.

Locate the following:

  • 4x M3*6 Screws

First, push all the jumper wires through top chassis piece.

Jumper wires through top chassis

After all the jumper wires are through the top, you can screw down the top chassis piece to the four L25 metal standoffs already on the bottom chassis piece.

Tighten top of chassis

RedBot Mainboard

You are now ready to add the RedBot Mainboard to the four L10 metal standoffs on the top chassis piece.

Locate the following:

  • 4x M3*6 Screws

Place the RedBot Mainboard on the top of the L10 metal standoffs. When looking down on your RedBot, the battery pack will be on the top end, the RedBot Mainboard’s power jack will be on the right side, and the USB will be on the left. Using four M3*6 screws, screw down the RedBot Mainboard to the L10 metal standoffs.

Adding RedBot mainboard

RedBot Accelerometer

Time to add the Accelerometer! If you do not have headers on your Accelerometer already. We recommend soldering on female headers to your Accelerometer to fit on top of the RedBot Mainboard’s female headers.

Locate the following:

Locate the position on the RedBot Mainboard to add the Accelerometer. Line up the “A4” pin on the Accelerometer to the “A4” male header pin in the “SENSOR” section on the RedBot Mainboard.

Accelerometer

RedBot Buzzer

Adding the RedBot Buzzer is nice and easy!

Locate the following:

Locate the position on the RedBot Mainboard to add the RedBot Buzzer. With the buzzer side and female header PCB side of the RedBot Buzzer facing to the right, place the RedBot Buzzer on top of the “9”, “POW”, and “GND” male header pin row in the “SERVO” section on the RedBot Mainboard.

Buzzer

RedBot Mainboard Hook-up

It is time to hookup all the jumper wires to the RedBot Mainboard!

Play close attention when connecting the jumper wires to the RedBot Mainboard. It is very important that the motors and add-ons are connected to the right pins.

Fritzing Diagram

Made with Fritzing.org

The only wires left should be for the motors. Connect the left motor’s red wire to the RedBot Mainboard’s “RED” female header pin in the “LEFT MOTOR” section. Connect the left motor’s black wire to the RedBot Mainboard’s “BLACK” female header pin in the “LEFT MOTOR” section. Connect the right motor’s red wire to the RedBot Mainboard’s “RED” female header pin in the “RIGHT MOTOR” section. Connect the left motor’s black wire to the RedBot Mainboard’s “BLACK” female header pin in the “RIGHT MOTOR” section.

jumper wire for motors

Batteries

Just add batteries, and you are done putting together your RedBot!

Locate the following:

  • 4x AA batteries

Use the graphics on the Battery Pack Holder to place the batteries in the right orientation. Plug in the Battery Pack Holder’s barrel power plug into the barrel power jack on the RedBot Mainboard.

Add batteries to RedBot

Resources and Going Further

Ready to start driving your RedBot? Check out the Getting Started with the RedBot!


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

WiFly Shield Hookup Guide

0
0

WiFly Shield Hookup Guide a learn.sparkfun.com tutorial

Introduction

The WiFly Shield allows you to easily connect your Arduino to a wireless network, serve up data, act as a client, create an ad-hoc network for your Internet of things devices, and get data such as data and time from your network. This hookup guide will show you how get started, how to configure the WiFly module, and how to set up some simple sketches using the WiFly Shield.

WiFly Shield

Covered in This Tutorial

This guide will show you:

  • How to connect the WiFly Shield to the Arduino
  • How to communicate with the WiFly Shield through the terminal
  • How to connect the WiFly to a WiFi network
  • Simple communication over a network
  • How to create a simple server
  • How to update the firmware on the WiFly module

All of the functions and commands used in this tutorial can be found in the RN131 documentation:

Suggested Reading

If you’re new to electronics or wireless communication, you may also want to check out these other concepts first:

You should also have a basic understanding of simple networking terms such as:

Hardware Overview

WiFly Shield

The WiFly Shield consists of two major components:

The WiFly module communicates via its UART to the SC16IS750 bridge chip, which in turn communicates with the Arduino via SPI.

Communication diagram

This allows the WiFly module to communicate with the Arduino at high speed without using the Arduino’s UART so that the Arduino can still communicate with a serial terminal. Any communication from the WiFly to the Arduino (or vice versa) must be sent through the SC16IS50.

The WiFly module is connected to four indicator LEDs through its I/O pins. These indicator LEDs will blink at different rates depending on the state of the module. They can provide a lot of information to the user about the state of the module without the user having to connect the device to a serial terminal. For more information on the behavior of the LEDs, see the RN-131 Reference Guide.

LED Status Table

The WiFly module is also connected to four jumpers. The jumper PIO9 is a special jumper and is used to put the module into adhoc mode. If you would like to communicate directly with the WiFly from a computer in an adhoc fashion, short the PIO9 jumper with solder.

Last, the WiFly has a small prototyping area to connect any other components you’d like. You could add additional LEDs, sensors, motors, or other bits to make your project come alive.

WiFly Breakout Board

You can also use the information in this tutorial to use the WiFly GSX Breakout. However, since the breakout board does not include an SPI-to-UART IC, you will have to either use a separate conversion chip or communicate directly to the WiFly module over the UART. Keep in mind that if you do use the Arduino’s UART to communicate to the module, you will not be able to send back repsonses to the termial window unless you use a seperate UART (The Arduino mega has several UARTs or you can you the SoftwareSerial library on an Uno).

Connecting the WiFly Shield to the Arduino

What You Will Need

To get the WiFly Shield up and networking, you’ll need the following things:

Assembly

Connecting the WiFly Shield to the Arduino is easy. Solder on the headers, and attach the shield to the Arduino board. You can use male headers or stackable headers, depending on how you intend to use your WiFly. For detailed instructions on how to connect headers to the WiFly shield, please see the Arduino Shields tutorial.

wifly shield with headers

WiFly Shield with standard strait male headers.

Next, connect the Arduino to the computer through the USB cable. Some of the LEDs on the WiFly shield should now be blinking. You should see the yellow LED blinking quickly and the green LED blinking slowly. This indicates that the WiFly is open for new connections.

WiFly Library and the Termianl Sketch

WiFly Shield Library

To aid in the use of the WiFly shield, several authors have contributed to making a WiFly library. It has gone through several iterations, and, although it is not perfect, it allows the end user to easily get the WiFly up and running.

Interaction with the WiFly Shield will be done via the Arduino Serial monitor or a terminal program of your choice. In order to do this, we’ll need an example sketch called SpiUartTerminal from the WiFly Shield github page. Use the following steps to install the library and sketch in the Arduino environment.

  1. Download the library code as a zip file from the WiFly Shield github page.
  2. Unzip the downloaded file into your …/arduino/libraries/ folder
  3. Rename the unzipped folder “WiFly”. This must be done because the Arduino environment does not accept library folder names with dashes in them.
  4. Start the Arduino IDE (or restart if it is open).

The Terminal Sketch

Once you’ve installed the library, navigate to the example sketch

File->Examples->WiFlyShield->SpiUartTerminal

Load the sketch in tot he Arduino IDE. This sketch allows the user to communicate with the WiFly Shield directly through the Arduino serial monitor or any other terminal emulator.

Upload the sketch to the Arduino board, and open the Arduino serial monitor (or terminal emulator of your choice). Make sure the baud rate is set to 9600, 8-N-1-NONE.

alt text

The Arduino should now print out an info menu with instructions on how to use the sketch. We’re now ready to configure the WiFly to connect to a network.

Please note that you will need to use this sketch a lot when working with your WiFly Shield. Anytime this tutorial references talking to the WiFly module, assume that it is referring to using this sketch to do so.

Troubleshooting

  • If you are experiencing problems with you WiFly Shield, make sure you are using the most up to date version of the library from GitHub. The Arduino IDE is constantly evolving, and, occasionally, the newest version might not work with existing libraries. If you can’t get the WiFly shield to work with the latest version of the Arduino IDE, you may have to revert to an older version of the IDE. If you are using Arduino 0023 or older, you will want to use the pre-Arduino 1.0 version of the library.

  • If you are seeing data that looks mostly right but is jumbled in places when you use the terminal sketch, the problem is most likely related to not having the correct library matched up with the correct version of the IDE.

Connecting to a Network

The WiFly module is configured by sending it commands through its UART. To do this, the user must first place the module in command mode. For a complete list of configuration commands, please see the RN-131 Reference Guide.

To begin, put the module in command mode by typing the command

$$$

into the Arduino Serial Monitor and pressing enter. (Make sure the serial monitor is set to “No line ending” when you type in the $$$). The module will respond with the letters “CMD”, indicating that it is in command mode. From this point on, commands that we send must be ended with a carriage return, so in the dropdown menu next to the baud rate menu, select “Carriage return”. This will ensure that the serial monitor sends a carriage return after every command you type in the send box.

alt text

Next, we need to scan for wifi networks. To do this type the command

scan

You can skip this step if you already know the credentials of your wireless network. The WiFly module will scan for any networks and print the results to the terminal. We are concerned with the columns labeled “SSID” and “Sec”. These are the name of the access point and the security protocol of the access point, respectively. We will need them to configure the WiFly to connect to the access point.

At this point, we’ll need to tell the WiFly what security protocol to use. The security protocols have set values listed in the RN131 reference guide on page 65.

alt text

Find the value that corresponds to the security protocol on your access point. Then, in the serial monitor, send the command

set wlan auth <value>

where <value> is the number that corresponds to the access point’s security protocol. This tells the WiFly to use that security protocol when connecting.

If your access point is using a security protocol, you will need to tell the WiFly your passphrase. To do this, send the command

set wlan phrase <passphrase>

where <passphrase> is the password to connect to the access point.

Now our module should be configured and ready to connect to the access point. Tell it to join by sending the command

join <ssid>

Where <ssid> is the name of the access point you found during the scan. The WiFly module should now connect and print out information about your connection, such as the IP address.

alt text

Congrats, you are now networking from the Arduino!

Autoconnect to a Network

If you would like the WiFly module to automatically connect to a network upon power up, follow the above directions. Instead of using the join command, you can store the SSID and tell the module to connect to that SSID by default.

Do so by using this command

set wlan ssid <ssid>

where <ssid> is the name of the access point you’d like to connect to automatically. Then use the command

set wlan join 1

This tells the module to try and connect to the SSID stored in memory automatically.

The last thing is to store these settings in the WiFly’s config file. We’ll talk about this more in depth in the Configuration Files and Firmware Upgrade section, but, for now, just know that is where the WiFly stores all its settings. To do this, simply type

save

Now, whenever you power up your WiFly, it should connect to that network without having to issue it any commands. To join to the network you just stored in memory without reseting the Arduino, issue just the join command without an parameters.

Static IP

If you want your WiFly Shiled to have a static IP address instead of having one assigned via DHCP, you must first turn of DHCP and then set the IP address you want if it hasn’t been set already. Using the Terminal sketch, enter command mode. Issue this command to turn of DHCP:

set ip dhcp 0

Next you can assign the IP address you want using this command:

set ip address <address>

Troubleshooting

  • If you already used the WiFly shield with DHCP on, there may already be an IP address stored in the WiFly’s memory. You can keep this IP address as you static IP address, and you know that it will be available.

  • If you upload any of the default example sketches that come with the WiFly library, you may overwrite the settings you just configured. If you are using an example sketch with a static IP, comment out the following lines in the Setup() function.

    if (!WiFly.join(ssid, passphrase)) {
      while (1) {
        // Hang on failure.
      }
    }

This will prevent the sketch from overwriting your settings.

Also, check out the Configuration Files section of this tutorial to see how you can save and load different settings profiles in case you do accidentally overwrite your settings.

  • You may also need to change this line in any example sketch, if you plan on using a port other than 80.

    WiFlyServer server(80);

Communicating with the Network

Now that the WiFly is connected, we’d like to communicate with the network. But how? What do we send? Where do we send it? The WiFly will transmit anything it’s sent, the trick to successful networking is knowing where the data is going and how to package it.

When the WiFly connects to an access point, it communicates through a port. Ports are like sub-addresses, they indicate what type of information is being sent or received so that devices know how to use the sent data. For example, when trying to reach a website, a browser communicates on port 80, which is the HTTP port (hence the “http://” at the beginning of most URLs). The server “listens” on port 80, and when a browser request comes in, it sends the requested information back on port 80. There are thousands of port numbers, each with a different standardized protocol.

By default, the WiFly transmits and listens on port 2000. We can change the port by sending the command

set ip local <port>

Where <port> is the port on which the WiFly will listen. To listen for HTTP requests from a browser, we send the command

set ip local 80

Now, any computer that is also connected to the same access point as the WiFly can query the WiFly through a browser. Simply open a browser and attempt to navigate to

http://<IP of WiFly>

The IP address of the WiFly is always printed when it joins a network, and you can always find it by sending the command

get ip

when the device is in command mode.

When the WiFly receives a request from a browser, it will print the incoming data to the terminal. For example:

alt text

The browser is now waiting for data, the WiFly can send sensor values, serve web pages, or any other data straight back to the browser! In this case, the browser is waiting for a web page. If the WiFly responds with an HTML-formatted page, the browser will display it. The next section will show you exactly how to do that.

Setting Up a Simple Server

In this example, you will create a simple server with your WiFly module. The functionallity will be simple, but you can take what you learn with this example to create more complex projects.

Materials Needed

If you’ve been following along, you should already have a WiFly shield attached to an Arduino. For this example, the only other items you will need are an RGB LED and three 330&ohm; resistors. You will also need some wire or other means to connect the LED to the WiFly Shield.

Assembly

In this example, the LED and resistors will be soldered directly to the shield. If you need a refresher on soldering, check out our tutorial. For those who don’t want to solder to their shield, you can use a breadboard to build the circuit.

Connect the LED and resistors to the shield like the image below. When working with a prototyping surface, don’t forget that none of the through-holes are connected to one another. You must make solder connections on the underside of the shield to complete the circuit.

alt text

Don’t forget that the RGB LED has polarity and must be placed in the correct orientation.

Firmware

Once the hardware is wired up, it’s time to upload the code. Copy the code below, and upload it to your Arduino, or you can download the sketch here. Note: Keep in mind that you must have gone through the previous steps to configure your WiFly module to connect to your network automatically.

language:c
/*********************************************************
WiFi LED Controller
Joel Bartlett
SparkFun Electronics
August 1, 2013

This code uses an Arduino Uno with a SparkFun WiFly shield attached
to act as a webserver cabable of controlling an RGB LED

To use this code with Arduino 1.0+, it is recommended that you use
the latest version of the WiFLy Library found here:
https://github.com/sparkfun/WiFly-Shield
Many thanks to Philip Lindsay (aka Follower) for creating this library
and many thanks to jmr13031 for updating the library for Arduino 1.0+

This code borrows heavily from the code found from Upverter.com
https://gist.github.com/1201213
Many thanks to Emmanuel DeVries for doing a lot of the heavy lifting.

This also borrows from the Sparkfun Speakjet Wifly Example by Chris Taylor
https://www.sparkfun.com/tutorials/158
***********************************************************/
//I took out the credentials.h file as well as the code that
//tells the wifly server the ssid and the parephrase since
//this info was setup manually on the WiFly shield.
//The IP address is also set maually instead of being assigned.

#include <SPI.h>
#include "WiFly.h" //include the WiFly experimental library

char msg[128];//variables for reading in the html responses
int letterCount = 0;

int redPin = 3;
int greenPin = 5;
int bluePin = 6;

WiFlyServer server(80);// This is set manually but this line is needed to initialize server()
                  //Port 80 is the default HTTP port

///////////////////////////////////////////////////////////////////
void setup()
{
  pinMode(redPin, OUTPUT);  //set RGB pins as outputs
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  digitalWrite(redPin, LOW); //set all LEDS to LOW/OFF
  digitalWrite(greenPin, LOW);
  digitalWrite(bluePin, LOW);

   WiFly.begin();//begin WiFly communictaiosn

  Serial.begin(9600);  //Serial communication at 9600 buad for debugging
  Serial.print("IP: ");
  Serial.println(WiFly.ip());  //Prints IP address once associated with the network
                              //If DHCP is on, this IP can change. If static IP is set, it should not.

  server.begin(); //initialize the server
}
///////////////////////////////////////////////////////////////////
void loop()
{
  WiFlyClient client = server.available();
  //the flag dataFlag give a notification of where the actual post
  //is once we flag it we can begin recording the message
  //so we can do stuff with it later on

  int dataFlag = 0;
  int msgIsolator = 0;

  //int inChar; //variable for reading in data from the phone/browser
  //boolean isParsing = false;// flag for reading in and parsing data

  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    boolean endOfCode = true;
    char c;

    while (client.connected())
    {
      if (client.available())
      {
        c = client.read();
        delay(10);
        //Uncomment this line to see the HTTP respone
        Serial.print(c);

        // if we've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so we can send a reply
        if (!client.available()) {
          endOfCode = true;
        } else if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } else if (c != '\r') {
          // we've gotten a character on the current line
          current_line_is_blank = false;
          endOfCode = false;
        }

        //this is where the message that the user entered is going so this is where
        //we record it into a char array
        if (msgIsolator == 1)
        {
          recordMessage(c);
          delay(100);
        }

        if ((c == '\n' && current_line_is_blank && !client.available()) || endOfCode)
        {

          //As soon as the page has been refreshed the letter count is set to zero
          letterCount = 0;

          //Once the page has been refreshed we are no longer on the first run through
          //off the program so we set this to false
          endOfCode = false;

          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          //client.println("Connection: close");

          client.println();

          //This basically creates what the user will see on the site.
          client.println("<html>");
          client.println("<title>RGB LED Server</title>");

          //the form code creates the buttons to click and change the temp/blanketstate
          client.println("<center>");
          client.println("<form name=\"input\" action=\"\" method=\"post\">");
          client.println("<input type=\"submit\" name=\"%\" value=\"Red\" style=\"height:50px; width:150px\">");// I made the buttons larger for smart phone screens
          client.println("</form>");

          client.println("<form name=\"input\" action=\"\" method=\"post\">");
          client.println("<input type=\"submit\" name=\"%\" value=\"Green\" style=\"height:50px; width:150px\">");
          client.println("</form>");

          client.println("<form name=\"input\" action=\"\" method=\"post\">");
          client.println("<input type=\"submit\" name=\"%\" value=\"Blue\" style=\"height:50px; width:150px\">");
          client.println("</form>");

          client.println("</center>");
          client.println("</html>");
          //***NOTE: I originally added the Reload button, and it broke everything. I combined the temperature state and number into one line and
          //took out some other html code. It then worked. This leads me to beleive that there is only so much that the WiFly can serve up at a time??***
          delay(500);//delay is very important. It gives the browser time to process requests
          letterCount = 0;
          checkAction();//go to check action function is a HTML button is pressed.
          break;
        }

        //if you want to see all data comming in and going out uncomment the line below
        //Serial.print(c);

        //We detect where the actual post data is in other words what the user entered
        //once we isolate it we can parse it and use it
        if (c =='%')
        {
          dataFlag = 1;
        }
          if (dataFlag == 1)
          {
            //in here goes the user entered data it follows the string "25="
            if (c == '=')
            {
              //trim the fat of the soon to be recorded char so we only get the user entered message
              msgIsolator = 1;
            }
          }
      }
    }

  // give the web browser time to receive the data
  delay(100);//delay is very important
  client.flush();
  client.stop();
  }
}
///////////////////////////////////////////////////////////////////////

char recordMessage (char incomingMsg)
{
  //letterCount = 0;
  msg[letterCount] = incomingMsg;
  letterCount++;
  delay(100);
}
///////////////////////////////////////////////////////////////////////
void checkAction()
// the first two or three letters of each message are read to determine which button was clicked on the webage
{
  if (msg[0] == 'R' && msg[1] == 'e' && msg[2] == 'd')// Turn on RED LED
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    digitalWrite(bluePin, LOW);
  }
  //-------------------------------------------------------
  else if (msg[0] == 'G' && msg[1] == 'r' && msg[2] == 'e')//Turn on GREEN LED
  {
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, HIGH);
    digitalWrite(bluePin, LOW);
  }
  //-------------------------------------------------------
  else if (msg[0] == 'B' && msg[1] == 'l' && msg[2] == 'u')//Turn on BLUE LED
  {
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, LOW);
    digitalWrite(bluePin, HIGH);
  }

}//end checkAction()

Once the code is uploaded, open the Serial Terminal set to 9600. After a few seconds, the WiFly should print out its IP address. This will vary depending on if you are using DHCP or if you assigned a static IP.

alt text

In your browser, type the IP address that was printed out in the Terminal into the address bar. After a few seconds, you should see a web page with these three buttons load.

alt text

As long as everything is connected correctly, each button on the website should light up the corresponding LED when clicked. The change will not be instantaneous as the commands need to propagate from the browser, through the network, and to your WiFly shield.

alt text

You can even control it from your smart phone as long as it’s connected to the same wireless network as the WiFly shield.

iphone screenshot

Troubleshooting

  • Please note that data transmission of the wireless network is NOT instantaneous. It may take up to several seconds for your request to be sent to and processed by the Wifly shield depending on the size and configuration of your wireless network. If you are experiencing problems, there are many links in the chain to investigate.

It is also worth noting that the sketch prints data to the terminal by default. This will add some time to this delay. You can change this by commenting/uncommenting line 88.

if (client.available())
      {
        c = client.read();
        delay(10);
        //Uncomment this line to see the HTTP respone
        //Serial.print(c);
  • When you click any of the HTML buttons, you should see the green LED on the WiFly shield go solid while it processes the request. If you see that the LED is just hanging and never returns to blinking, then the WiFly shield is getting hung up on the HTML request. This could be the result of a firmware issue or a network/browser issue.

  • If the red or yellow LED on the WiFly shield are blinking continuously, it is having a problem connecting to your wireless network. See the datasheet for more info on LED statuses.

  • If you have a steady blinking green LED and your Arduino is printing out a valid IP address but you are not seeing a webpage load, then the problem is most likely in the code or in your wireless network settings. Makes sure you selected the correct security settings and make sure you save your settings to the WiFly config file after you have set all the necessary settings.

Going Further

Try changing up the code to add different colors and more buttons. You can also take a look at the server example that comes with the WiFly library. This example reads the analog inputs on the Arduino and posts them to a webpage. See if you can add digital inputs and analog outputs to the same webpage. You could also replace the single RGB LED with a strip of RGB LEDS controlled via some MOSFETs. Then you could create an Internet controlled LED Light Cube

Configuration Files and Upgrading the Firmware

The firmware for the WiFly module is updated occasionally. Luckily for you, there is a simple way to update your module to the latest version.

The WiFly module sold by SparkFun Electronics currently ships with firmware version 2.38. To check which version of the firmware your WiFly shield is running, upload the Terminal sketch, enter command mode, and enter this command:

ver

Note: The version is usually displayed after each command issued in command mode as well.

Before we update the firmware, let’s go over the configuration files stored within the WiFly and how to add other config files.

Storing Separate Configuration Files

Using the terminal sketch mentioned on the WiFly Library page, create a connection to the module, and enter command mode.

Now issue the command

ls

to list all the files on the module. Depending on what firmware version you have, you should see something like this:

ls config files

You’ll notice the WiFly_GSX-2.21 file is the current firmware version and the config file is where all of the settings are stored.

One great feature of the WiFly is its ability to store multiple configuration files. For instance, if you wanted to use the WiFly at both your home and your work, you could create two separate config files, each with the correct settings for both locations. To do so, set all the settings for one location such as SSID, pasphrase, security. etc. Then use the save command followed by the name you want to call that configuration.

alt text

Notice that there is now two config files named home and work.

Now, to use one of those config files, simply issue the load command followed by the name of the file. It’s impotant to note that even though there are separate config files, the WiFly always uses what is stored in the default config file, so after you load a config file, it’s best to save it to the default config file using just the save command.

alt text

Now, even after a firmware update, you should be able to load all of the settings you had before. (Note: Firmware updates will often include new features/settings, so there is no guarantee that your previous settings will work on a new version of the firmware.) You can delete a config file using the del command.

Updating the Firmware

Directions on how to update the firmware can be found on Microchip site, but we will also go over the process here.

Again, use the terminal sketch to enter command mode. You must be connected to the Internet in order to get the firmware update from Roving Networks, so follow the directions on the Connecting to a Network page to connect to your wireless network.

While you are connected, you should still be able to issue commands. We now need to set the FTP settings on the module and point it to the correct website from which to retrieve the new firmware. Depending on 1) how old your module is and 2) how many settings you have changed, you may need to change several settings.

The first thing to check/change is the FTP settings. Issue the command

get f

to see your current FTP settings.

ftp settings

To get the update, you must make sure the FTP address is the correct one. The Roving Networks page say the the firmware must be pulled from rn.microchip.com. Pinging this URL gives the correct IP address.

ping

Now, set the FTP address to the one returned during the ping, if it does not match the one stored in memory. Also make sure the user name and password match the ones in the image below. These should be the default values unless you changed them in your configuration.

set ftp

With all the correct settings, issue this command

ftp update

You should see something like this:

ftp update

Notice how the Ver is now 4.00

Once the update has finished, you need to reboot the module, give it a factory RESET, and then reboot it again.

alt text

Failing to issue the factory RESET will result in config files not being saved correctly.

Now, using the ls command, we can see the new firmware. The old firmware is still stored in the module in case you need to revert back to an older version.

ls 2

To boot from an older firmware version, use the boot image command. In the image above, you can see that the older firmware (2.21) is stored in FL# 11. So we issue the boot image 11 command to get back to that version.

alt text

Again, it’s best to reboot, RESET, and reboot after changing the firmware.

As of this writing, the most up to date version of the firmware that will be downloaded with this process is Ver 4.41.

Troubleshooting

If you can’t get the firmware to update, check the following:

  • Make sure you are actually connected to the Internet.
  • Make sure the FTP address is correct (198.175.253.161).
  • Make sure the FTP port is correct (21).
  • Make sure the FTP User=roving and the Pass=Pass123
  • If all else fails, issue a factory RESET and then try updating the firmware.

Resources and Going Further

This is just the basc hookup of the WiFly Shield. The shield works very well as a host or client. To use it as a host, many projects also include an SD Shield to hold large amounts of data to be served, rather than save them on the Arduino chip.

Check out the other examples you downloaded with the WiFly Shield library. There are some great web client and server examples as well as a lot of other great info on using the shield

To get the most out of your shield, be sure to read the reference guides and datasheets. Here are links to all the most important ones.

For more examples of what the WiFly is capable of, check out these projects:


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

MaKey MaKey Quickstart Guide

0
0

MaKey MaKey Quickstart Guide a learn.sparkfun.com tutorial

Introduction

Welcome to the world of MaKey MaKey! A world where every day objects are much more than what they appear. Bananas are more than just a curvy fruit - they’re keys to a virtual piano. Play-dough isn’t just a tasty child’s toy - it’s the controlling force behind Pacman’s up/down/left/right. And your simple pencil drawings are a portal to Portal.

Be prepared to look at every day objects in a whole new light. Be stoked! The world is your construction kit.

Covered in This Tutorial

This tutorial’s purpose is to help get you up and running with the MaKey MaKey – everything from what the board is, to installing it, to using it. Sections are split into pages, covering the following topics:

Materials Required

Suggested Reading

  • What is a Circuit?– To create a MaKey MaKey “key”, a circuit must be created so current can flow.
  • Voltage, Current, Resistance and Ohm’s Law– Learn about the three fundamental concepts behind electricity, and how they’re related by Ohm’s law. The MaKey MaKey works by bending our idea of resistive material.
  • Voltage Dividers– Voltage dividers are the secret behind every MaKey MaKey input. This tutorial digs a bit deeper into circuit theory.

What is the MaKey MaKey?

The MaKey MaKey is a collaborative project between Jay Silver and Eric Rosenbaum of the MIT Media Lab, and us here at SparkFun Electronics. It’s an invention kit that encourages people to find creative ways to interact with their computers, by using every day objects as a replacement for keyboards and mice. With the MaKey MaKey, you could replace your space key with a banana, use play-doh to move and click your mouse, or high-five your best friend to advance PowerPoint slides.

It’s a Mouse/Keyboard

The MaKey MaKey is a two-sided circuit board. On the more simple, top side, the MaKey MaKey has 6-inputs: the up/down/left/right arrow keys, as well as the space bar and mouse left click:

Top of board, explained

Each of those inputs as well as the very important “Earth bar” are available in the form of what I like to call “alligator-bait” connectors. You’ll use the included alligator clip cables to clip right into the hole pairs. This will all be made much more clear in the next section. For now, let’s keep summarizing your MaKey MaKey.

When you flip the board over, you’ve got access to 12 more keys: W, A, S, D, F, and G on the keyboard side, and up/down/left/right mouse movement and left/right clicks on the mouse side. The bottom header has six ground (aka Earth) outputs, while the top header is an expansion/output header. There are also a few LEDs on the back to indicate whether you’re pressing a mouse or keyboard key.

Bottom of Board Explained

The pins on the back side are all available in the form of “jumper-wire” connectors. If you bought the deluxe kit, you’ll already have the jumper wires needed, otherwise you can buy them separately here.

It’s an Arduino

As I mentioned before, what makes the MaKey MaKey extra-awesome is the fact that it’s completely Arduino-compatible.

Ardu-what-now?

Arduino is a super-popular electronics development platform. In essence, it’s a tiny, little programmable computer, with seemingly infinite uses, that’s been adopted as the go-to electronics platform for artists and electronics veterans alike.

What’s made Arduino so popular, though, is the fact that it’s a lot more than just a board full of electronics. It’s a well-documented programming environment. It’s a huge electronics and programming resource manual. And, most importantly, it’s a community full of both budding electronics-addicts, and helpful EE know-it-alls.

But, I digress. Basically, the MaKey MaKey’s Arduino-ness, means that you can easily reprogram it to work just exactly how you want. Do you need to replace W, A, S, D, F and G with Q, W, E, R, T, and Y? You’re about six lines of easy code edits, and one button click away from that quick fix!

Installing the Board

Enough talk, let’s start making! On this page we’ll detail the installation process for both Windows and Mac OS X (which should match Linux pretty closely).

Windows Installation

If you’re a Windows person, there are drivers. Sort of. The keyboard/mouse part of the MaKey MaKey should not require drivers. If you have no interest in reprogramming the board, then skip this part. But, it’s really worth it to install the drivers. You want to get the most out of your MaKey MaKey, right?

First, you’ll need a copy of the driver. Click here to grab the driver. You’ll need to unzip that folder. Remember where it saves to on your computer!

  1. The first time you plug your MaKey MaKey in, Windows will try to find drivers for it. It’ll fail pretty miserably. You might get an error like this:

  2. So, we’ll tell Windows what’s what with these drivers. You’ll need to open your Device Manager. Either by navigating to your Control Panel, then System, and then Device Manager. Or (my preferred method) by running (press either Windows Key + R, or Start > Run) devmgmt.msc.
  3. In the Device Manager, scroll down to Other Devices. There you should find the cause of all this unpleasantness. Mr. “USB IO Board”. Right click that and select Update Driver Software….

  4. Next Windows will ask you how you want to search for the driver. Well, it’s already failed at searching “automatically” for the driver, so let’s pick Browse my computer for driver software. On the next screen, click Browse… and navigate to the folder where you stored the driver (Downloads perhaps?). Then you can click Next.

  5. Uh, oh. Red alert. Windows security is being a little nosy. You can safely click Install this driver software anyway.

  6. Finally, after a few moments you should be greeted with something like this:

  7. Do a happy dance!

If you’re having any trouble installing drivers, please don’t hesitate to contact our technical support team. We’re more than happy to help out!

Mac Installation

If you’re a Mac or Linux person, there are no drivers! When you plug your MaKey MaKey in, you’ll be greeted with a screen like this:

Mac Keyboard Setup Assistant Screenshot

To which you can reply with a “Continue”. That’ll be followed by:

Second Keyboard Setup Assistant screenshot

The MaKey MaKey doesn’t exactly have a shift key, much less a key next to it. I’m not exactly sure of what Mac OS is trying to do here, but you’re safe to ignore this window by just closing it. You’ll only be asked to “Identify Your Keyboard” the first time you plug the MaKey MaKey in.

Making Your First Key

The most simple MaKey MaKey key you can make is one that only uses your fingers. Try touching the Earth bar while simultaneously touching the space circle pad. The LED above the SPACE key should light up, and a space command should be sent to your computer.

Pressing a key with fingers

Now try leaving one finger on the Earth bar while quickly tapping the space button. Getting a feel for it? It should work just like your standard space key!

MaKey Key-Making Materials

To make your “standard” key with the MaKey MaKey you need the following:

  • A connection to a MaKey MaKey input. This can be done using alligator clips on the top side, or jumper wires on the bottom.
  • Connection to a MaKey MaKey ground (Earth). Again, you’ll connect to earth using either alligator clips or jumper wires.
  • Some sort of key material. This is the fun/creative part! There’s a world of MaKey MaKey keys out there. Anything that’s even slightly conductive is just waiting to become a computer input. The classics, of course, are your fingers, bananas, and pencil scratchings.
  • Something to activate the key, by connecting between the key material and the ground input. Your fingers work pretty well for this. Anything even slightly conductive will do though.

Making a Key

Activating a key means creating a closed circuit. For the circuit to work, electrons have to be able to flow from the MaKey MaKey input key to MaKey MaKey’s ground. Usually your fingers will be the missing link between those two:

MaKey MaKey key sketch

Let’s try making a bona fide MaKey MaKey key. First, you’ll need to find some sort of key object. Dig around your house, check your fruit basket, your coin purse, or grab a pencil and make a drawing.

Pick out your favorite-colored alligator clip cable, open one of the jaws, and snap it down onto your key. And clip the other end of the clip into one of the MaKey MaKey top-side inputs. SPACE is great for testing purposes:

First alligator clip connected to banana

Now, grab a second cable for the ground connection. Black is the classic “ground color”, but set your own trend and pick whatever you want. Clip one end of one cable into the Earth bar, and let the other end dangle for now.

Ground clip attached to banana

Open up some sort of text editor (Notepad, Word, TextEdit, etc.) on your computer. Remember that, just as with your boring ol' keyboard, your computer will interpret keypresses differently depending on what program is active.

Finally! Grab the dangling end of the ground cable with one hand. Make sure you’re touching the metal part of the clip. Then use your other hand to touch the banana, or whatever your key might be. BAM! Space!

Pressing the banana key

Adding More Keys, Using the Back

To add more keys, simply connect another alligator clip to another MaKey MaKey input (e.g. arrow keys or mouse click), and connect the other end to a key material. No further ground connections are necessary.

Want to make use of the back side of the board? You can follow a similar set of steps, replacing alligator cables with jumper wires. Jumper wires are a bit tougher to connect to keys. An easy solution is to connect an alligator cable to the free end of the jumper.

Play-doh, or other materials which enable you to jab the jumper wire in also work great! How about a Play-doh Mouse:

Play-Doh MousePad

(Hint: Get creative with the ground connection. In the example above, we connected ground to a penciled bar where we rested our hand.)

What Makes a Key? Conductivity.

A material is a conductor if it allows electricity (even just a tiny bit of it) to flow. This is the magic behind the MaKey MaKey: most of the world is conductive! Anything metal will almost certainly conduct electricity. The “standard” conductors are copper, silver, gold, etc. But with the Makey MaKey our conductor scope grows. Most organic materials - things like human skin, liquids, foods, and frog legs - are at least a little conductive. And that’s really all the MaKey MaKey needs.

If an object isn’t conductive, it’s an insulator. Common insulators include plastic, glass, ceramic and wood. You can usually tell just by looking at something whether it’s an insulator or conductor. You’ll have to watch out for objects like this, as they just won’t work with the MaKey MaKey. To get around that, though, you can line them with a conductive material (like copper tape, or just regular old wire), to create the illusion that they’re conducting electricity.

Resistance is a measure of exactly how conductive a device is. Resistance can be measured with just about any standard multimeter. Any object with a resistance of about 4.5MΩ (that’s a really high resistance) or less should work as a MaKey MaKey input. If you’re not sure if something will work with the MaKey MaKey, whip out a multimeter (buy one if you have to, they’re an essential tool for electronics hobbyists) and test that resistance! Or, better yet, just connect it to your MaKey MaKey and experiment.

Resources and Going Further

If you’re left with any questions after reading this tutorial, here are all the MaKey MaKey-related resources we can find:

Example Projects

Sometimes following by example is the best way to learn. If you’re not sure where to start with the MaKey MaKey, give these examples a look-over. I hope they inspire you! If you want your project added to this list, post it in the comments below, or send us an email!

Advanced MaKey MaKey-ing

Have you outgrown the MaKey MaKey’s default arrow, space, and home keys? Want to remap the MaKey MaKey inputs, program the MaKey MaKey in Arduino, and use that mysterious output connector? Then join us over on part 2 of this quickstart guide!


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

MaKey MaKey Advanced Guide

0
0

MaKey MaKey Advanced Guide a learn.sparkfun.com tutorial

Introduction

Previously on Getting Started with the MaKey MaKey we discussed how to make your standard banana space bar. But what if you want to make a full-on banana piano, and the default MaKey MaKey key presses don’t fit your needs? Among its many magical characteristics, the MaKey MaKey is easily reprogrammable, so you can customize the key-mapping to fit your project.

alt text

In this tutorial we’ll show you how to use Arduino – the most popular embedded development environment out there – to reprogram the MaKey MaKey and modify which inputs press which keyboard or mouse control. We’ll also talk a bit about that mysterious output header, which you can use to turn the MaKey MaKey into more than just an input device.

Suggested Reading

Before following along with this tutorial, we highly recommend you read through our Getting Started with the MaKey MaKey tutorial. That guide will help get you fully up-and-running with the MaKey MaKey, leading you from driver installation to making your first key.

Beyond that tutorial, here are some related tutorials we’d recommend reading as well:

  • What is an Arduino?– An overview of Arduino, from the IDE to the boards to the language.
  • How to Install the Arduino IDE– You won’t get too far in this tutorial without having Arduino installed, this tutorial will help you through the process.
  • Logic Levels– Learn about the difference between HIGH, LOW, 0V, 5V, on, off, etc.
  • Using GitHub– The MaKey MaKey Arduino files are hosted on GitHub, where we keep the most up-to-date files.

Installing the Arduino Addon

Before you can program the MaKey MaKey using Arduino, you need to download and install the Arduino IDE (integrated development environment). Check out our Installing Arduino IDE tutorial for help with that. From there you can access the Arduino application by double-clicking (using the MaKey MaKey!?) the Arduino application.

Adding the Addon

The MaKey MaKey addon for Arduino adds an entry to the Arduino “Boards” list tailored to the MaKey MaKey. Click the link below to download the addon.

Download the Addon

The download is a zip file, which includes a directory named “hardware”. Unzip the hardware folder into your Arduino sketchbook. Where’s your Arduino sketchbook? Well, by default, it should be an “Arduino” folder in your home directory, but to double-check you can go to File > Preferences within Arduino and see the Sketchbook location text box. Just make sure you close all Arduino windows once you’re done.

Sketchbook location

After you’ve unzipped the addon, your directory structure should look a little something like this:

Addon directory structure

Make sure any existing Arduino windows are closed (if you’ve opened any), and open up a new Arduino window. Let’s do some programming!

Programming the MaKey MaKey

You’re just about ready to modify the firmware driving the MaKey MaKey. But first there are a few settings we need to adjust.

Board and Port Selection

The addon you installed will add a “MaKey MaKey” option to the Tools > Board menu within the Arduino IDE. Go ahead and select that.

Board selection

You’ll also need to set the Serial Port. When you plug in the MaKey MaKey it enumerates as a communication device and gets assigned a COM port (Windows users, you’ll need drivers installed, see here). Select the MaKey MaKey’s COM port under the Tools > Serial Port menu in Arduino. For most users, there’ll be only one port to choose from. If there are two, unplug and replug the MaKey MaKey in, observing which COM port disappears and reappears.

Port selection on Windows

On a Mac, the Serial Port will come in the form of “/dev/tty.usbmodem”:

Port selection on Mac

Modifying the Code

Onto the code. You can find the most up-to-date MaKey MaKey source code at its Github home (check out our Using GitHub tutorial for help downloading). Or click here to download it directly. It’s another zip file, so don’t forget to unzip!

There are two pieces to the MaKey MaKey code: the main file (currently makey_makey_1_4_1.ino) and the settings.h file. Open the .ino file with your Arduino IDE, settings.h will open up in a tab up top.

Generally you’ll only need to futz with settings.h. This is where all of the keys are defined, and there are a few more advanced options to play with the filters, and mouse movement speed. Here’s what it’ll look like by default:

language:c
#include "Arduino.h"

/*
/////////////////////////////////////////////////////////////////////////
// KEY MAPPINGS: WHICH KEY MAPS TO WHICH PIN ON THE MAKEY MAKEY BOARD? //
/////////////////////////////////////////////////////////////////////////

  - edit the keyCodes array below to change the keys sent by the MaKey MaKey for each input
  - the comments tell you which input sends that key (for example, by default 'w' is sent by pin D5)
  - change the keys by replacing them. for example, you can replace 'w' with any other individual letter,
    number, or symbol on your keyboard
  - you can also use codes for other keys such as modifier and function keys (see the
    the list of additional key codes at the bottom of this file)

*/

int keyCodes[NUM_INPUTS] = {
  // top side of the makey makey board

  KEY_UP_ARROW,      // up arrow pad
  KEY_DOWN_ARROW,    // down arrow pad
  KEY_LEFT_ARROW,    // left arrow pad
  KEY_RIGHT_ARROW,   // right arrow pad
  ' ',               // space button pad
  MOUSE_LEFT,        // click button pad

  // female header on the back left side

  'w',                // pin D5
  'a',                // pin D4
  's',                // pin D3
  'd',                // pin D2
  'f',                // pin D1
  'g',                // pin D0

  // female header on the back right side

  MOUSE_MOVE_UP,      // pin A5
  MOUSE_MOVE_DOWN,    // pin A4
  MOUSE_MOVE_LEFT,    // pin A3
  MOUSE_MOVE_RIGHT,   // pin A2
  MOUSE_LEFT,         // pin A1
  MOUSE_RIGHT         // pin A0
};

///////////////////////////
// NOISE CANCELLATION /////
///////////////////////////
#define SWITCH_THRESHOLD_OFFSET_PERC  5    // number between 1 and 49
                                           // larger value protects better against noise oscillations, but makes it harder to press and release
                                           // recommended values are between 2 and 20
                                           // default value is 5

#define SWITCH_THRESHOLD_CENTER_BIAS 55   // number between 1 and 99
                                          // larger value makes it easier to "release" keys, but harder to "press"
                                          // smaller value makes it easier to "press" keys, but harder to "release"
                                          // recommended values are between 30 and 70
                                          // 50 is "middle" 2.5 volt center
                                          // default value is 55
                                          // 100 = 5V (never use this high)
                                          // 0 = 0 V (never use this low


/////////////////////////
// MOUSE MOTION /////////
/////////////////////////
#define MOUSE_MOTION_UPDATE_INTERVAL  35   // how many loops to wait between
                                           // sending mouse motion updates

#define PIXELS_PER_MOUSE_STEP         4     // a larger number will make the mouse
                                           // move faster

#define MOUSE_RAMP_SCALE              150  // Scaling factor for mouse movement ramping
                                           // Lower = more sensitive mouse movement
                                           // Higher = slower ramping of speed
                                           // 0 = Ramping off

#define MOUSE_MAX_PIXELS              10   // Max pixels per step for mouse movement

/*

///////////////////////////
// ADDITIONAL KEY CODES ///
///////////////////////////

- you can use these codes in the keyCodes array above
- to get modifier keys, function keys, etc

KEY_LEFT_CTRL
KEY_LEFT_SHIFT
KEY_LEFT_ALT
KEY_LEFT_GUI
KEY_RIGHT_CTRL
KEY_RIGHT_SHIFT
KEY_RIGHT_ALT
KEY_RIGHT_GUI

KEY_BACKSPACE
KEY_TAB
KEY_RETURN
KEY_ESC
KEY_INSERT
KEY_DELETE
KEY_PAGE_UP
KEY_PAGE_DOWN
KEY_HOME
KEY_END
KEY_CAPS_LOCK

KEY_F1
KEY_F2
KEY_F3
KEY_F4
KEY_F5
KEY_F6
KEY_F7
KEY_F8
KEY_F9
KEY_F10
KEY_F11
KEY_F12

*/

The first variable definition, keyCodes[NUM_INPUTS], is an array of 18 values. Each value in this array represents a single key or mouse input. Each variable in that array has a defined position, called an index, numbered from 0 to 17. KEY_UP_ARROW is at position 0, while, down at the bottom, MOUSE_RIGHT is at position 17. The positions in the array map to the MaKey MaKey inputs as such:

Key-array mapping

If you want to define an input as a-z, A-Z, 0-9, or other printable characters, you can fill the keyCodes array with single characters surrounded by apostrophes (e.g. ‘a’,’s',’d',…). If there’s no printable character for the key you need, like the arrow keys, modifier keys, etc. you’ll need to use one of the defined special key values. The special keys available are all printed (in comments) at the bottom of settings.h (KEY_LEFT_CTRL, KEY_LEFT_SHIFT, etc.). Their function should be pretty self-explanatory.

Just remember, there can only be 18 total values, comma-seperated, in that array!

As an example, say you want the ‘CLICK’ key on the top side to instead be the ENTER key. Easy! Just go to the sixth entry (position 5, darn that 0!) in the keyCodes array and replace MOUSE_LEFT with KEY_RETURN (just like that, all caps, don’t remove the comma that was there already).

To load your new code onto the MaKey MaKey, all you need to do is hit the Upload button (the right-facing arrow icon up top). If all of the settings in the Tools menu are correct, you should see some blinky lights on the MaKey MaKey, followed by something like this:

Upload Successful

Now you should have some ENTER action on your MaKey MaKey, in place of the top-side click!

Using the Output Header

If an elephant remains in this room, it’s probably that output/expansion header at the top of the board. This header is what really makes the MaKey MaKey versatile. Not only can the MaKey MaKey receive inputs from all sorts of crazy objects, but output signals back into the world.

Output header

D14 and D16 are what we’re going to focus on here. The default MaKey MaKey firmware configures each of those pins as outputs. They’ll produce either 5V or 0V, on depending what MaKey MaKey keys are pressed.

D14 is tied to the keyboard inputs, so whenever a keyboard button is pressed, it’ll generate a HIGH (5V) voltage, otherwise it stays LOW (0V). Same goes for D16, which is tied to mouse buttons/movements.

What use is that? Well it’s a great way to trigger external objects. You could hook up an LED to those pins, and get even more blinkies! Or, you could connect a DC motor, to automate something. Or you hook it up to a 5V relay, and really get your MaKey MaKey interacting with the world.

alt text

Anything that can operate on a 5V DC signal could be triggered by one of these inputs.

Going Further

If this is your first foray into programming in general, or even just Arduino programming, we’d encourage you to check out these resources and tutorials:

  • Arduino Learning Database– A series of code examples which will help you figure out exactly what’s going on with all this Arduino code. Don’t be afraid to try loading the MaKey MaKey with Arduino sketches that have little to do with MaKey MaKey-ing. A great way to learn how to code is by following code examples, of which Arduino has many. Either peer into the File > Examples menu within Arduino, or check out all of the links on this database.
  • Arduino Language Reference– Here you’ll find links explaining the purpose and operation of Arduino’s standard structures, variables, and functions. This is a great place to look up what exactly digitalWrite(), int, loop(), and the rest are all for.
  • Arduino Community Forum– Anything left unanswered after browsing the previous two links? Head over to the community forum! Try searching out for previously asked questions, or pose one of your own.
  • Turn Your Arduino Into A Keyboard/Mouse– How to take advantage of the Keyboard and Mouse functions of the ATmega32U4. The MaKey MaKey makes use of many of the functions discussed here. If you’re curious about writing your own version of the MaKey MaKey code, this might be a handy place to start. Arduino’s also got an entry for the Mouse and Keyboard library on their website.
  • Arduino Comparison Guide– Learn about other Arduino-compatible boards like the Uno and Leonardo.

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

USB Type A Female Breakout Hookup Guide

0
0

USB Type A Female Breakout Hookup Guide a learn.sparkfun.com tutorial

Introduction

If you have a microcontroller that can act as a USB host, then you will need a way to plug in USB cables and devices. The USB Type A Female Breakout accepts a Type A USB plug on one end and breaks out the 4 USB lines to a standard 0.100 inch header.

USB Type A Female Breakout Board

USB Type A Female Breakout

NOTE: This tutorial uses the mbedLPC1768, as it has a built-in USB host. However, the breakout board can be used for any platform that has a USB host.

Covered In This Tutorial

In this tutorial, we will use the mbed LPB1768 and the USB Type A Female Breakout to create a simple circuit that accepts a USB keyboard and prints pressed keys to a serial console.

Required Materials

Suggested Reading

Board Overview

The board is a simple breakout for USB lines.

USB Type A Female Breakout Board

USB Type A Female Breakout front

GND should be connected to the ground of the host circuit.

D+ and D- are the differential pair lines for USB. They should be connected to D+ and D-, respectively, of the host circuit. Additionally, a 15kΩ pull-down resistor is needed on each D+ and D-.

VCC needs to be connected to a 5V supply (which could come from the host circuit, if available).

Hookup Example

Assembly

To connect the USB breakout board, solder the break away headers to the 4 header holes on the board.

Header pins soldered onto USB Type A Female Breakout

PTH headers on the USB breakout board

Connecting the USB Breakout Board

alt text

Basic hookup using an mbed LPC1768 and a breadboard

For the LPC1768, make the following connections with jumper wires:

(USB Breakout → LPC1768)

  • VCC → VU
  • D- → D-
  • D+ → D+
  • GND → GND

Additionally, add 2 15kΩ pull-down resistors on the D+ and D- lines. Attach one resistor from D+ to GND, and attach another from D- to GND.

Completed mbed LPC1768 and USB breakout circuit

USB Type A Female Breakout added to the mbed LPC1768

Example Code

We will use the mbed online editor and compiler for this example. First, navigate to mbed.org, and login or create a profile.

mbed login

Once logged in, go to the Handbook Homepage, which contains all of the official mbed libraries.

mbed Handbook

Scroll down to find the USB Host Keyboard library under “Communication Interfaces.”

mbed USB Host Keyboard library

Click the “Import Program” button to load the library and example program into the online compiler.

mbed import program

Make sure you have “Program” selected from “Import As:”, as we want to use the example program (select “Library” if you plan to write your own program using the library).

importing example mbed program

In the “Program Workspace,” select the “USBHostKeyboard_HelloWorld” folder and click “Compile” at the top. This will automatically compile the program and download a binary (.bin file) to your computer.

mbed compile USB keyboard example

Plug in the mbed microcontroller to your computer using a USB cable. The mbed should enumerate as a USB mass storage device. If you are using Windows, it will appear as if you plugged in a thumb drive.

Find where you downloaded the compiled .bin file and copy it to the root directory of your mbed device.

mbed copying compiled program

Press the reset button on the mbed system. This will reboot the mbed and load the .bin file to be immediately executed.

In addition to enumerating as a mass storage device, the mbed also has a built-in COM port. If you are on Windows, open up the Device Manager and locate the mbed Serial Port’s COM number.

mbed COM port

Start the serial program of your choice (I will use PuTTY for this example) and select the COM port correseponding to the mbed device. Use 9600 baud, and click “Open.”

Configure PuTTY for the mbed

Once you establish a Serial connection to the mbed, you will be presented with a blank console.

blank Serial console

Plug in a USB keyboard to the USB Type A Female Breakout Board.

mbed LPC 1768 and USB keyboard

The Serial console should show the keyboard being enumerated. You can type, and keystrokes will appear in the console. If you unplug the keyboard, you should see a “disconnected” message.

IMPORTANT: Only letters and numbers are supported in this example program. Additionally, the program cannot discern multiple keystrokes (for example, if you hold ‘1’, press ‘2’, let go of ‘2’, and let go of ‘1’, you’ll see “111” printed).

Testing the mbed USB keyboard program

Resources and Going Further

The USB Type A Female Breakout is a great way to add USB devices to your microcontroller, assuming your microcontroller can support a USB host. For some ideas, see mbed’s Handbook section on USB host libraries:

Resources


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

Simon Splosion Wireless

0
0

Simon Splosion Wireless a learn.sparkfun.com tutorial

Introduction

Simon is an all-time classic game made by Milton Bradley. Kids have been playing this game for years - dating back to 1978. That’s pretty impressive! I can’t even imagine what kinds of electronics were available in 1978!

alt text

SparkFun created our own version of this game that now runs on the ATmega328 chip (the same microcontroller as the one on the Arduino Uno). This was originally designed as a simple soldering kit, but we quickly realized it had much more potential and could be used to teach programming as well. With a few header pins and an FTDI breakout, you can start reprogramming your Simon in Arduino.

Our basic game runs in a single-player mode. There have been many adaptations to the Simon Code - including a battle-mode that allows two players to challenge each other.

Easter Eggs?

If you haven’t discovered these yet - we have embedded two easter eggs into our code. The first is the Bee Gees Disco Mode. Hold down the Lower-Right button when you turn on the Simon to see this one.

There is also a “Battle-Mode” version that we programmed in as well. Hold the upper right button when you turn on the device. To start the game, the first player should hit a single button. Pass the Simon to your opponent. Your opponent repeats the button press, adds a second button, and then passes it back. Continue by mimicking the pattern and adding a new button for each round. This pattern repeats until someone loses.

Got it?

Wait! I bought my Simon Says kit a long time ago and it doesn’t have this feature? No worries. We’re going to show you how to update and modify your code.

Things you’ll need to get started:

You’ll need a few more things to add wireless, but let’s start with just making some easy modifications first.

Suggested Reading

Modifications

Step 1 – Soldering Programming Headers

To program the Simon, we need access to the FTDI pins. Flip your Simon board upside down. On the left side, you will see a label that says FTDI Basic.

alt text

There are six pins here. I like to solder these right-angle headers to the pins.

alt text

Alternatively, if you don’t have a soldering iron or you don’t want to solder, you can use straight pin headers. Just hold the connector in the holes while programming the device. The holes are what we call plated-through holes. This means that each hole has a cylinder of metal that connects to the pad. If you hold a straight pin header in at an angle, it should make a good electrical connection to the pins.

Step 2 – Downloading the base code

If your Simon is an older version or if it doesn’t have the two easter eggs, click here for the latest code from github. If you need a refresher on how to use GitHUb, visit our tutorial.

Open / Unzip this file to your computer. Note: you must unzip the files in order to use them. Windows will often allow you to view the files within a compressed file, but you won’t be able to access all of the files.

Under the folder \Simon-Says-master\Firmware\Simon_Says\ you should find the Arduino code – Simon_Says.ino

alt text

Open this file in Arduino.

alt text

Step 3 – Upload to Simon

Using the FTDI Basic and your USB cable, connect the Simon to your computer.

alt text

Be careful to line up the BLK and GRN markings on the FTDI Basic with the labels on the Simon.

Setting the Board Type

The Simon Says uses the LilyPad Arduino w/ ATMega328 bootloader. This is because we are using the internal oscillator on the ATMega328 instead of a separate crystal as on the Arduino Uno or on our RedBoard.

Under the Tools menu in Arduino, change the board type to Lilypad Arduino w/ ATMega328.

Select the proper Serial Port (generally the largest COM# for PCs and \dev\tty\usb-serialxxxx for Mac & Linux).

Make sure the Simon has batteries and is turned ON and click upload.

Now - remember there are two easter-eggs in this code. One is triggered by holding down the Lower-Right button when it turns on, the other is triggered by holding down the Upper-Right button.

Hacking the Simon

Now you’re ready to start reprogramming your Simon. We’ve created a few activities to play around with here.

A while back, we created a tutorial around tweaking the Simon - https://www.sparkfun.com/tutorials/203. The images are of an older version but the experiments and documentation are all applicable to the current version of the Simon. You will also find example experiments to play around with here.

To help you out with hacking into the Simon, here are a few notes about the LEDs, buttons, and the buzzer on the Plated-through Hole (PTH) Simon:

alt text

Pins 4 and 7 are tied to the buzzer. To use the tone() command, set both pin 4 and pin 7 as OUTPUTs, start with a digitalWrite(7, LOW), and use tone(4, freq); to drive the buzzer.

If you happened to get the SMD version of the Simon, the pin assignments are a little different. Here are the pin-outs for the LEDs and buttons on the Surface Mount Device (SMD) Simon:

alt text

Buzzer is between pins 3 and 4.

If you’re curious, check out Pete’s tutorial and tinker around with the Simon. It has 4 buttons, 4 LEDs, a buzzer, and access to 6 additional I/O pins. What cool games or applications can you come up with for it? Be sure to share it back with us!

For now, we’re going to show you how to add wireless XBee communication to your Simon.

Simon Says - Go Wireless (Part I)

Now that you have the latest firmware code on your Simon and you’ve challenged your friends at Battle-Mode Simon, what’s next? Well, we thought it would be awesome to have a Wireless Battle-Mode version of the Simon game. So, we stepped things up and added an XBee wireless module to our device.

If you haven’t played around with XBee, take a look at the materials from our Xciting Xbees class. For this we won’t dig deep into the XBee side. In fact, we’re going to just use two XBees with their standard factory settings. As a note - this will only work with two XBees in a single room. If you wish to have multiple Wireless Battle Simons you will need to configure and pair the XBees individually.

For now let’s get started with hacking our Simon to go Wireless!

What you need:

alt text

Want to add this all to your shopping cart? Click here for the complete wishlist

Circuit Modifications / Soldering

Add male header pins to FTDI

If you skipped ahead to this step make sure that you have male header pins soldered to the FTDI pins on the back of your Simon. Here’s an image of one of the boards we did here:

alt text

Generally, the FTDI header is tied to the main power of the board. For reasons I won’t go into here, this was not done in our original board design. So, we need to add a small modification here. We need to solder a short length wire (~3 - 4 inches) from the Vcc (Power) pin on the FTDI header to the Vcc on the Simon.

Flip the Simon so that the side that you can see the side that says BOTTOM. Take a short length of solid core wire and solder this to the third pin from the top of the FTDI header (labeled BLK). If you look closely, you can see that I used needle-nose pliers to make a small hook on the end of the wire. I found this to be easier to hold the wire in place while I was soldering it. Be careful not to melt the buzzer housing while you’re doing this. The buzzer is really close to these pins!

alt text

Now, take the other end of the wire and solder this to the outside pin on the POWER swtich (this is also the right side - when the board is upside down). It should look like this when you’re done. I’d suggest using a slightly longer length of wire than I show here:

alt text

Repeat these steps for your other Simon.

New Firmware

If you haven’t downloaded the firmware code yet, download it here from github.

Under the firmware subfolder there is a folder called Simon_Wireless. Open the file Simon_Wireless.ino and upload this to both of your Simons. Remember that the ATMega328 should be programmed using the LilyPad Arduino w/ ATMega328 board setting.

Simon Says - Go Wireless (Part II)

Now you have the headers soldered, the modifications made, and the new firmware on both of your Simons. Just a few more steps and you can start wirelessly battling Simon Says!

Configuring the XBees

The factory settings of the XBees will work for this tutorial as is. However, if you want to configure your XBees you will need to get an XBee USB Exporer. You can change the settings of the XBee with either AT Commands from a terminal window or using a program like XCTU.

If you change the settings just make sure that you have two XBees that are directly paired with each other.

Soldering headers to the XBee Explorer

The XBee Explorer comes unpopulated with header pins. So, we’ll need to solder right angle female headers to this board.

alt text + alt text

Solder the 6 pin right angle headers to the holes on the edge of the XBee Explorer. There should be exactly six pins there.

Let’s Play!

Plug the XBees into the FTDI header pins you soldered in earlier. Your two Simons should look like this:

alt text

How to play

Turn on both Simons. Each unit will power on and play an “attract” sequence of blinking LEDs. This will continue until one player presses a button. That player’s unit will then go dark and wait for a first button in the sequence to be pressed. So, here’s how to play:

  • Player 1 – Hit any button to start.
  • Player 1 – Hit first button to begin a pattern.
  • Player 2 – Wait and watch the pattern to light up. Press the button that lights up, and add another button to the sequence.
  • Player 1 - Repeat

This sequence will repeat over and over until one player makes a mistake. This unit will play the “You lost!” tune while the other unit will play the “Winner!” tune.

Want to modify or change the code? Well - you’ve got it. If you want the original program back, upload the Simon_Says.ino file.

Resources and Going Further

What’s next? With an XBee and the Simon, you now have a remote controller. Use it to add remote control to a robot or to an LED Arduino project. Modify the code and use it to send messages to another Simon across a room! Maybe signal a partner when you’re ready to leave a party?

For some project ideas, check out these other SparkFun tutorials:


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

VKey Voltage Keypad Hookup Guide

0
0

VKey Voltage Keypad Hookup Guide a learn.sparkfun.com tutorial

Introduction

If you need to add a keypad to your microcontroller project, but don’t want to use up a lot of I/O pins to interface with it, the VKey is the solution for you. It outputs an analog voltage to encode which key has been pressed, which can in turn be read by an analog to digital converter on a microcontroller.

alt text

VKey Voltage Keypad

Traditional digital keypad interfacing techniques can require a large number of digital I/O lines. One common arrangement uses N digital outputs and M digital inputs to interface with an N*M array of keys, as described here. On a small controller, there may not be many I/O pins left for other tasks.

The VKey board has 12 pushbutton switches and some supporting circuitry. It outputs an analog voltage that represents which of the keys is being pressed. This output can be sampled using a single channel of ADC, allowing 12 keys to be scanned using a single analog input pin.

Covered In This Tutorial

This tutorial will guide you through connecting the VKey to an Arduino, and it introduces a library that tells the application which key is currently pressed.

Required Materials

Suggested Reading

Board Overview

Looking at the front of the board, we see an 3 by 4 array of tactile switches and three connection pads near the bottom edge of the board.

Front of VKey

Front of VKey

The connection pads are as follows.

GND should be connected to the ground of the host circuit.

Vout is the analog output of the keypad, and should be connected to an analog-to-digital channel (such as A0, A1, etc on an Arduino).

V+ is the power supply, and should be connected to a voltage between 3.3V - 5.5V.

How It Works

Take a look at the back of the VKey.

Back of VKey

Back of VKey

The IC is a dual opamp, used as a current source and buffer amplifier. The current source drives a string of resistors that form a voltage divider, and the tact switches select voltages at the different taps of the divider.

See the resources section for links to a much more detailed guide to the internals of the VKey.

Each of the buttons on the VKey produces a unique analog voltage, as listed below/

Key NumberVout (5V supply)Vout (3.3V supply)
None.057.053
12.198.194
11.396.388
10.596.583
9.794.776
8.992.970
71.1901.164
61.3881.358
51.5851.551
41.7811.744
31.9791.938
22.1762.131
12.3722.323

As you can see, with a 5V supply, each successive button adds about 200 mV to the output voltage – at 3.3V the voltage per step is slightly less.

One situation to consider is when more than one key is pressed at the same time. The VKey implements high-key number (or low voltage) priority – when more than one of the switches is closed at a time, the output will indicate the higher key number. For instance, if you hold down 5 and 9 together, the output will indicate key 9 is pressed.

Assembly

The VKey comes with the surface mount components assembled, but the PTH tactile switches are loose, and need to be soldered to the board.

Contents of the VKey package

Contents of the VKey package

The first step in hooking up the VKey is to solder in the key switches.

alt text

Attaching the tact switches

Depending on how the board is to be mounted, different headers can be soldered to the board.

If the overall depth of the assembly is a concern, you can use a right angle header on the same side of the board as the tact switches.

alt text

Right angle header on top of board

If clearance past the edge of the board is a concern, you can use a straight header soldered to the side opposite the switches.

alt text

Straight header on back of board

And of course, you could always solder wires directly to the board in place of the header.

Connecting The VKey To An Arduino

alt text

Basic hookup to an Arduino

It takes three wires to connect the VKey to an Arduino.

(VKey → Arduino)

  • V+ → 5V
  • Vout → A1 (or any other analog pin)
  • GND → GND

Arduino Library

To make interfacing the VKey as simple as possible, we’ve written anArduino library and example sketch. If you need a refresher on how to install an Arduino library, please see our library tutorial.

The VKey library provides an object that interfaces with a VKey keypad. In a typical application, this class is instantiated as a global object before the setup() function. In the VKey object declaration, you need to select the appropriate analog input pin, and set the power indication to the proper voltage, either THREE (actually shorthand for the more common 3.3V) or FIVE.

It is possible to attach several VKeys, each on it’s own analog input pin, by declaring multiple VKey objects to watch the corresponding analog pin numbers.

The VKey status is queried using the function

bool CheckKeys(eKeynum & k);

The function will always return an indication of the current button in reference parameter k, or NONE in the case that no buttons are pressed. The function also returns a boolean indication of whether the key has changed since the last time it was queried – a form of edge detection. Many applications will only care about handling the key number when it updates, and don’t need to process the input when it is unchanging.

The next page will show us a quick sample sketch that uses the VKey library.

Example Code

Once you have installed the library, open the Arduino IDE, and paste the following into the sketch:

language:c
/******************************************************************************
 VKey_demo_main.ino
 VKey Voltage Keypad decoding demo
 By Byron Jacquot @ @ SparkFun Electronics
 February 4, 2014
 https://github.com/sparkfun/VKey_Voltage_Keypad

 This demonstrates interfacing the SparkFun VKey voltage keypad using
 the VKey Arduino library.

 The VKey has an array of 12 pushbuttons, each producing a unique analog
 voltage when  pushed.  A microcontroller can read the voltage, and determine
 which key has been pressed.  The VKey library keeps track of the analog pin
 connection, key status, and voltage calibration details.

 The VKey was connected to the Arduino as follows:
 VKey GND  -> Arduino GND
 VKey Vout -> Arduino analog input A1
 VKey V+   -> Arduino VCC

 To use the library, instantiate a VKey object and periodically check for input
 using the checkKeys() function.

 Resources:
 no additional library requirements

 Development environment specifics:
 Developed on Arduino IDE 1.0.5
 Tested on a 5V Redboard and 3.3V Pro Mini

 This code is beerware; if you see me (or any other SparkFun employee) at the
 local, and you've found our code helpful, please buy us a round!

 Distributed as-is; no warranty is given.
******************************************************************************/

#include <VKey.h>

// Global declaration of the VKey class
// Initialized with analog pin number and supply voltage
VKey keypad(A1, VKey::FIVE );

void setup()
{
  // Initialize serial port for text output
  Serial.begin(9600);
  Serial.println("Welcome to VKey example");

  // No VKey specific initialization required.
}

void loop()
{
  VKey::eKeynum k;  // Variable to receive the key indication

    /* CheckKeys will always return the current key in parameter k.
       The boolean return value indicates whether that value is different than
       the previous value.
     */
  if(keypad.checkKeys(k))
  {
    // Only print when value has changed
    Serial.print("Got key: ");
    Serial.println(k);
  }

  // The responsiveness of the keypad depends on how frequently it is checked.
  // 50 milliseconds seems to be a reasonable poll interval.
  delay(50);
}

Build and upload the sketch. Then open a serial terminal, and observe the output while pressing buttons.

alt text

The Arduino recognizes keys based on the voltage produced by the VKey

The Arduino will print notifications as buttons are pressed and released. A key number of 0 indicates that no keys are currently pressed.

If the Arduino isn’t properly tracking the key numbers, double-check that the VKey object was declared with the proper analog pin and supply voltage parameters. Also doublecheck that you’ve got the latest code from the Github repository.

Resources And Going Further

The VKey is a great way to add up to 12 buttons to a project, while still leaving many I/O pins for other tasks.

The schematics, PCB artwork and source code for the VKey are all found on it’s Github page. For a deeper look at the internals of the VKey, check the documents directory found there. You’ll find a more detailed theory of operations document, with supporting SPICE simulations and spreadsheets.

Modifications

There are a number of possible alterations that can be made to the VKey, to tailor it to a specific application.

Different Switches

The VKey comes with 12 PTH pushbutton switches, but can support nearly any normally-open SPST switch, such as arcade buttons or microswitches.

alt text

Connect alternate switches across the left pair of pads

To connect other switches, connect them to the pair of pads on the left of the tact switch footprint, as seen from the front of the board.

Voltage Source

While the VKey is primarily intended to interface with a microcontroller, that doesn’t mean it can’t be used for other applications. The circuit is similar to those used in analog synthesizers to extract a control voltage from the piano keyboard. You could use the VKey to drive any device with a control voltage input.


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


Vernier Shield Hookup Guide

0
0

Vernier Shield Hookup Guide a learn.sparkfun.com tutorial

Introduction

As a former high school physics teacher, I taught nearly every unit using Vernier sensors in my classroom. Vernier has an extensive suite of sensors, easy-to-use software, and amazing support for all of their products.

I had great success using Vernier in my physics class, but I was looking for a solution that would enable me to use these same sensors in other classrooms where I did not have direct access to computers with LoggerPro software or the Vernier LabPro hardware.

Part of this journey led me to developing this low-cost photogate timer project. I had conceived this idea before starting here at SparkFun, and, once here, I was able to start this project to develop an Arduino shield that would allow us to quickly connect any Vernier probe to an Arduino.

Vernier LabPro

alt text

Vernier LabPro Startup Beep

This green box is a classic in many science classrooms. It makes a very pleasant, instantly recognizable tone when it’s plugged into a computer.

In addition to the LabPro, Vernier also has a variety of other interfaces including the:

These interfaces are great solutions for data collection and automation in the classroom. They are simple to use and integrate directly with Vernier’s LoggerPro software platform. With the increased access to of low-cost micro-controllers in classrooms, we wanted to help provide an alternative for teachers to leverage their existing sensors, activities, and materials from Vernier with Arduino.

We have developed this Arduino Shield to connect your favorite Vernier sensors to any Arduino Uno or Arduino Uno compatible device.

alt text

What you’ll need:

Suggested Reading

About Vernier

alt text

Vernier Software and Technology has been a leader in data collection and analysis for educators world-wide. Started in 1981 by David and Christine Vernier, they were amongst the first companies to design and promote the use of computers, sensors, and data collection in K-12 classroom laboratory experiments.

They currently have over 70 fully calibrated sensors and 5 different data collection interfaces that are part of their catalog. We have been very fortunate to partner and collaborate with Vernier in the development of this Arduino shield. It allows teachers to combine the power and versatility of the Arduino platform with the wealth of calibrated, classroom tested, and rugged sensors produced and supported by Vernier.

Vernier Shield Pin-out and Configuration

Vernier standardized all of their sensors using a “standard” British Telecom connector. These connectors each have 6 wires that connect the sensor to the Vernier data collection interface. We designed the shield to maximize flexibility and ease-of-use for integrating up to two analog (BTA) and two digital (BTD) Vernier sensors to an Arduino. The full sensor pin-outs can be found on Vernier’s site here.

British Telecom Analog (BTA) – Right Hand

alt text

A large number of sensors used in the classroom fall under the category of “analog” sensors. Learn more about the differences between analog and digital here.

The pins of the BTA connector are defined as such:

PIN #Pin NameDescription
1Analog Sensor Output
(-10V to +10V)
Used with a number of Vernier voltage probes. This is wired through a scale and shifting op-amp circuit so that the Arduino can read it on a scale of 0 - 5V.
2GNDGround.
3VresResistance reference. 15K pull-up resistor ties this pin to 5V to use as a voltage divider between Pin 6 and GND.
4*AutoIDENTMost sensors have a unique resistor that is tied between this pin and GND. Vernier uses this to identify the sensor. (not supported on all sensors)
5Power5 VDC
6Analog Sensor Output
(0V to -5V)
Primary sensor output for most analog sensors including light, temperature, force, pressure, pH, etc...

http://www.vernier.com/support/sensor-pinouts/

To extend the use of Vernier equipment, they also offer a few voltage probes that allow for direct voltage measurements between +/- 6V, +/- 10V, and +/- 30V. On each of these probes, the signals are each tied to Pin 1 and and GND of the BTA connector.

British Telecom Digital (BTD) – Left Hand

alt text

Digital sensors are any of the devices that return a signal that is either on (5V) or off (0V). Common digital sensors include: motion detector, photogate, radiation monitor, and the rotary motion sensors.

These sensors each have a somewhat unique pin-out definition. The following table outlines the pin assignments used for the Vernier digital connector.

Note that the connector is slightly different compared to the analog sensors. This is called a left-handed British Telecom connector and has the tab on the opposite side. The BTA and BTD connectors will not plug into the same socket.

PIN #DEFAULTMOTION
DETECTOR
PHOTOGATERADIATION
MONITOR
ROTARY
MOTION
1IO1EchoInputCountCCWcount
2IO2InitCWcount
3IO3AutoIDENTAutoIDENTAutoIDENTAutoIDENT
4PWRPWRPWRPWRPWR
5GNDGNDGNDGNDGND
6IO4X4res

Arduino Shield Pin Assignments

To maximize the flexibility of using all of the Vernier sensors, we have made the following pin assignments on our shield. Many of the Vernier sensors use I2C for identification and calibration data. We use a multiplexer to “share” (multiplex) pins A4 and A5 between all four connectors. The multiplexer is controlled with Pins 10 (LSB) and Pin 11 (MSB). See the section on multiplexing for more information.

Pin assignments for analog ports

Analog 1Analog 2Description
MUX Control Address0001Pins 10 (LSB) and 11 (MSB) control a multiplexer for A4 and A5.
Analog Signal
(O - 5V)
A0A2Most analog sensors will interface to this pin. Use A0 for Analog 1 and A2 for Analog 2.
Analog Signal
(-10V - +10V)
A1A3The shield has a built-in circuit to scale and shift input voltages from -10V to +10V to a range of 0V to 5V for pins A1 and A3.
V_resA4*A4*Resistance reference. 15K pull-up resistor ties this pin to 5V to use as a voltage divider between Pin 6 and GND.
AutoIDENA5*A5*A 10K pull-up resistor ties these pins to 5V. The measured voltage drop across this pin uniquely identifies the sensor.

Pin assignments for digital ports

Digital 1Digital 2Description
MUX Control Address1011Pins 10 (LSB) and 11 (MSB) control a multiplexer for A4 and A5.
IO1
(BTD Pin 1)
26Signal pin used for the photogate, motion detector echo, radiation count, and CCW rotary motion count.
IO2
(BTD Pin 2)
3 / A4*7 / A4*Trigger pin for the motion detector and I2C data (SDA) for sensor ID
IO3
(BTD Pin 3)
4 / A5*8 / A5*I2C clock (SCL) for sensor ID
IO4
(BTD Pin 6)
59Used for rotary motion sensor to increase sensitivity.

*Pins A4 and A5 are shared across all four connectors. In order to properly access the BTA and BTD connector pins, you will need to interface the analog multiplexer circuit.

Auxillary Pins and Connections

In addition to the internal wiring and routing for the Vernier BTA and BTD connectors, we placed an indicator LED tied to pin 13, a general purpose button on pin 12, and a reset button on the shield.

alt text

We also exposed vias for power and ground and pins 0 (RX) and 1 (TX) for adding serial communication peripherals like a Serial-enabled LCD or Serial 7-segment Display.

Multiplexer

Vernier uses a variety of methods for identifying which sensors are connected to the interface. A majority of sensors use a resistor placed on one of the pins, but some of their sensors use I2C for both sensor identification and storing calibration data. The Vernier shield uses an analog multiplexer to share / route pins A4 (SDA) and A5 (SCL) to each of the four connectors.

Pins 10 (LSB) and 11 (MSB) are used to control the multiplexer. The following snippet of code illustrates one way to switch which connector A4 and A5 are connected to.

language:c
const int muxLSB = 10;
const int muxMSB = 11;

void setup()
{
  pinMode(muxLSB, OUTPUT);
  pinMode(muxMSB, OUTPUT);
}
void setMux(int connectorNum)
{
// void setMux(int connectorNum)
// connectorNum is a number from 0 to 3 which
// identifies which connector to switch the MUX to.
// Where if connector num is equal to:
//    0 --> Analog 1
//    1 --> Analog 2
//    2 --> Digital 1
//    3 --> Digital 2

  switch (connectorNum)
  {
  case 1: // ANALOG 2 - MUX ADDR 01
    digitalWrite(muxMSB, LOW);
    digitalWrite(muxLSB, HIGH);
    break;
  case 2: // DIGITAL 1 - MUX ADDR 10
    digitalWrite(muxMSB, HIGH);
    digitalWrite(muxLSB, LOW);
    break;
  case 3: // DIGITAL 2 - MUX ADDR 11
    digitalWrite(muxMSB, HIGH);
    digitalWrite(muxLSB, HIGH);
    break;
  default: // ANALOG 1 - MUX ADDR 00
    digitalWrite(muxMSB, LOW);
    digitalWrite(muxLSB, LOW);
  }
}

In general, you won’t need to access these lines unless you are interfacing to the Vernier sensors through I2C.

Vernier Sensor Identification

Vernier developed a very clever method to identify sensors connected to their interface using a simple, passive resistor. Many Vernier sensors can be uniquely identified by a specific resistor placed between the AutoIDENT pin and GND.

We have integrated a 10k Ohm pull-up resistor on the shield so that we can directly measure the AutoIDENT resistor using a simple voltage divider calculation.

alt text

Voltage divider circuit

Nominal Resistor and voltage values for Vernier sensors

We’ve collected a list of popular sensors used by Vernier and their corresponding unique IDENT resistor values. These are nominal values and may vary within +/- 5%.

Analog Sensors

alt text

Digital Sensors

alt text

You will notice that there are not 70 sensors listed here. For all new sensors, Vernier has standardized on an I2C interface to query and communicate SensorID and calibration data. An example of this code is explained in the next section.

Example 1 - AutoID Arduino

The team at Vernier have helped us with creating a couple simple Arduino sketches that automatically query either the Analog or the Digital ports of the Arduino and report back the sensor identification and standard calibration data.

Vernier has created a wealth of examples hosted on github. Upload these sketches to your arduino device, and open up a Serial Monitor to view the data coming back to your computer.

AutoID Analog Sensors

This sketch is designed to automatically query the sensors connected to the two analog ports on the Vernier shield. After the AutoID, it prints the sensor information to the Serial Monitor and starts logging (calibrated) data to the screen. Written into this script are the default calibration constants used with Vernier’s sensors.

This will, most likely, be the only Arduino sketch you need for most of your sensors.

As it is written, the data is collected once per second. Change the value of the variable TimeBetweenReadings to change the rate of the data collection.

AutoID Digital Sensors

This sketch queries the digital sensors connected to the Vernier Shield and prints out the information to the Serial Monitor. Because each digital sensor is unique, this sketch does not start logging data or printing out results. It will, however, suggest the name of the Vernier Arduino sketch to use. You can find these on the Vernier github repository.

Example 2 - Photogate Timer

alt text

In many classrooms, a standard stopwatch or timer is used to measure the time elapsed for moving objects such as mousetrap car races, rolling dynamics carts, or falling tennis balls.

These little stopwatches are great for most simple activities, but for many investigations and experiments, human reaction time and classroom distractions often introduce too much error and uncertainty to collect repeatable results for students to draw clear conclusions from their data.

Integrating a photogate timer is one of the simplest and low-cost tools a teacher can use. A photogate is simply an infra-red LED and receiver pair. The photogate normally produces a HIGH signal on DIO0 when the gate is unblocked. When an object passes through the gate, the signal is LOW until the gate is unblocked again.

Integrating this with a very fast timer, we can achieve very reliable and precise timing results.

alt text

The Arduino UNO has a 16 MHz clock. Accounting for overhead events and extra needed clock cycles and such, the Arduino is capable of timing results with a precision better than +/- 1 uS.

This code example is interrupt driven and uses the micros() arduino command to return the number of microseconds since the start of the program. This number is stored in an unsigned long variable. This gives the program a maximum time limit of about 1 hour and 11 minutes before the counter wraps. Generally speaking, we’re looking to capture the amount of time for a marble, toy car, or playing card to move through the gate.

This sketch simpily outputs an event entry to the Serial Monitor with the Event #, the photogate state (Blocked or Unblocked), and the time since the start of the program.

Data Output Format

The data is tab delimitted, and you can simply copy-paste this into your favorite data analysis program such as LoggerPro, Matlab, Google Sheets, or Excel.

Vernier Format 2

Event    Blocked    Time
#   (n/a)   (s)
--------------------------
1   1   1.885308
2   0   1.903900
3   1   1.908432
4   0   1.927056
5   1   1.945756
6   0   1.964332
7   1   1.980148
8   0   1.996724

Sensor Calibration and Verification - Falling Picket Fence

The Falling Picket Fence is a classic activity used in many physics classes. It extends and combines the concepts of average velocity to instantaneous velocity and explore uniform acceleration and the nature of the acceleration due to gravity.

A picket fence is nothing more than a clear piece of plastic with opaque bars spaced 5 centimeters apart (center-to-center).

alt text

Dropping a picket fence near the surface of the Earth should accelerate uniformly at a rate of 9.8 m/s/s. I used this to verify and check the accuracy of the timing. I used the sample code from above and dropped a picket fence through the photogate, and here is the data it returned:

Vernier Format 2

Event   Blocked    Time
#   (n/a)   (s)
--------------------------
1   1   5.520980
2   0   5.542184
3   1   5.570784
4   0   5.584924
5   1   5.605876
6   0   5.617208
7   1   5.635028
8   0   5.644568
9   1   5.659904
10  0   5.668612
11  1   5.682448
12  0   5.690280
13  1   5.702860
14  0   5.710160
15  1   5.721872
16  0   5.728644

Clearly that’s accelerating at 9.8 m/s/s, right?

Okay, you’re right. It’s about as clear as mud. It’s just a bunch of numbers, but if you look closely, you can see that the time between events appears to be getting smaller and smaller. Ah, ha! It’s speeding up! That’s a good sign.

The raw data is difficult to understand without processing, so I created a sample worksheet that can be used in any class. The worksheet calculates the average velocity between blocking events.

Using the worksheet, I graphed velocity vs. time and found the slope.

Data Statistics
slope: 9.78799 m/s/s
intercept: 0.758978 m/s

Is it right? Well - I try to avoid making right vs. wrong judgements in science. It is simply data, and all I can say is that it appears to agree with our existing assumptions and observations of the universe.

Other things you can do with photogates?

Check out the Vernier Photogate Timer Project tutorial.

Example 3 - Motion Detector

Vernier’s motion detector sensor is one of the most popular sensors used in classrooms. It uses a ultrasonic transducer similar ones used in older auto-focusing Polaroid cameras.

Combined with a graphing utility, it allows students to immediately see how position varies with time and how the slope of this graph is related to quantities such as velocity and acceleration.

alt text

The motion detector uses echo-location or sonar to determine the distance of objects in front of the sensor. It works by emitting an ultrasonic pulse and then listening for the echo of the pulse from the reflection off objects. The Vernier motion detector uses two pins for this:

Init (Pin 2 on the BTD connector)
Echo (Pin 1 on the BTD connector)

On the Vernier shield, we have these pins tied to:

Digital 1Digital 2
INIT48Trigger pin to send the ultrasonic pulse.
ECHO37Listen to this pin for the echo return / reflection.

Using the Arduino function micros, we can catch the time of the echo to an accuracy of 1 us. If we assume that sound travels at a speed of about 340 m/s, this translates to a round-trip accuracy of better than 1 mm.

Because we know that sound travels at a constant speed in a uniform medium, we can use simple kinematics to determine the distance the reflected sound travelled. In our code, we assume that the speed of sound is nominally 340 m/s. If you care to account for differences in temperature, hyperphysics has a great tool to calculate and adjust for differences in temperature.

alt text

Code example

The following code example has been adapted from the Vernier github repository. This sketch will record at a dataRate of 20 samples per second for a duration of 5 seconds. There are two variables declared in the beginning of the code that control these two parameters.

After uploading this file to your Arduino, open up a Serial Monitor and press the push button (D12) to start the data collection. Data will be displayed to the Serial Monitor. You can copy-paste this into Excel, Matlab, or LoggerPro for analysis. Or, you use a Serial graphing program like SerialChart, MakerPlot, or write your own in Processing.

Example 4 - Temperature Probe

alt text

Measuring temperature is a quantity that crosses into nearly every area of science and engineering (except maybe computer science). Vernier sells a great stainless steel temperature probe that is accurate from -40 degrees C to +135 degrees C. According to their site, the sensor can handle up to 150 degrees C before it is damaged. For us in the U.S., this is about 300 degrees F. It’s not quite safe to use as a meat thermometer in the oven, but it covers a pretty wide range for most scientific exporations.

The probe has a device called a thermistor that exhibits a change in resistance with respect to temperature. The Vernier probe uses a 20 kΩ NTC (negative thermal coefficient) Thermistor. As the temperature increases, the resistance drops.

The resistance vs. temperature relationship is non-linear and pretty complex, but it can be approximated using the Steinhart-Hart equation:

alt text

Where, RT is the resistance of the thermistor, and k0, k1, k2 are unique constants for the device. For the Vernier sensor:

k0 = 1.02119E-3
k1 = 2.22468E-4
k2 = 1.33342E-7

You can write your own function to convert the analog read value from the Arduino to a resistance.

Schematic:

alt text

The Vernier Interface Shield has a 15k Pull-up Resistor on Vres. We can determine the resistance of the thermistor because this is a simple voltage divider circuit:

alt text

So - here’s the derivation of the work and the algebra:

alt text

Example Code

The example below will collect data and display it to the Serial Monitor. After uploading this example sketch to your Arduino, open up a Serial Monitor to view the data.

This example code will take measurements at a rate of 2 samples per second. Modify the variable dataRate to adjust the sampling speed.

This code has a function called resistance() that converts the raw AnalogRead value to the resistance of the thermistor, and a function called steinharthart() that applies the Steinhart-Hart equation and returns a temperature in degrees Celsius.

For more information on thermistors, take a look at Vernier’s resource on making temperature measurements

Connecting an External Display

Adding an external display greatly enhances the ability to interface to the Vernier sensors independent of having a computer. The Arduino can be powered off a few AA batteries, and adding an LCD display will allow you to provide immediate feedback to the user.

What you’ll need

Recommended Reading / Useful Resources

Getting Started

You’ll need to solder on the male break-away headers to access pins D0 and D1. These will be used to transmit / send data to your Serial display device. You will also need to add headers to the power pins (5V and GND). We suggest using the female headers for this, though. Having power and GND exposed creates a risk of a short-circuit. Thankfully, the Arduino has a PTC resettable fuse that will protect your computer and the Arduino from this, but it should still be avoided.

The example code will vary depending on the Serial device you are using. You will need to connect Power (5V), GND, and the Transmit (Pin 1) on the Vernier Shield to your serial display device. Remember: the TX line should go to the RX line on the serial device.

Serial LCD Quickstart

Storing Data to an SD Card

alt text

What you’ll need

Recommended Reading / Useful Resources

Adding an SD Card Interface to your Vernier shield is pretty simple. The SD Card shield will have to go below the Vernier Shield using a set of stack-able headers).

Upload this code to your shield. It logs raw voltage values of the sensors to a microSD Card, if you are using the SparkFun microSD Card Shield. If you are using your own SD Card shield implementation, double check the pin assignments for chipselect. On the SparkFun microSD Card Shield, chipselect is on pin 8.

This code example will read raw voltage levels from any analog Vernier Sensor that provides a voltage from 0 to 5V (this accounts for a majority of their sensors). Pressing the button (D12) will start the data collection for a time period defined by the variable duration. Data is logged to a file called “datalog.txt” and displayed to the Serial Monitor.

Resources and Going Further

We hope that these examples will get you going on digging into the details of data collection and calibration. Vernier has been incredibly helpful with this collaboration. They have a wealth of resources on their site, as well:

Please send an e-mail to education@sparkfun.com if you’d like to share what you are doing with Vernier Sensors and Arduino or if you have any questions or problems with your board.


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

Getting Started with the BrickPi

0
0

Getting Started with the BrickPi a learn.sparkfun.com tutorial

Introduction

If you’re familiar with Lego Mindstorms, then you are probably aware of all the cool projects that you can make and the educational value of such an easy-to-use robotics platform. Enter the BrickPi.

BrickPi board

Bare BrickPi board

The BrickPi is a RasbperryPi add-on that lets you control Lego Mindstorm parts. The BrickPi stacks on top of the Raspberry Pi and accepts Lego Mindstorms motors and sensors.

BrickPi on a Raspberry Pi

BrickPi on top of a Raspberry Pi

The BrickPi allows you to control Mindstorms parts using any number of languages including C, Python, and Scratch.

Covered in This Tutorial

In this tutorial, we will cover how to get started with the BrickPi. We will show you how to connect the BrickPi to a Raspberry Pi, attach Legos, connect motors/sensors, and write a simple Python script to control the motors/sensors.

Required Materials

NOTE: The servo motor and touch sensor can also be found within the Lego Mindstorms NXT set.

Suggested Reading

Configure SD Card

IMPORTANT: You need to use Dexter Industries' custom Raspbian build to get the BrickPi to work.

Required Downloads

Flash the SD Card

  1. Insert the SD Card into your computer
  2. Install Win32DiskImager
  3. Unzip Dexter Industries' Raspbian build (use 7-Zip if the image is in .rar form)
  4. Run Win32DiskImager with administrative privileges
  5. Select the unzipped Dexter Industries' Raspbian build as the Image File
  6. Select the location of the SD Card
  7. Click “Write”

Win32DiskImager flashing Dexter Industries' Raspbian build

Don’t forget to Run as Administrator!

BrickPi Assembly

You will need to build the hardware around the BrickPi in order to connect it to the Raspberry Pi and Legos.

Build the Case

1) Unpack the BrickPi hardware and remove the protective paper from the case.

BrickPi parts

2) Screw the two small standoffs into the holes in the bottom piece of acrylic.

BrickPi assembly

3) Screw a Raspberry Pi onto the two bottom standoffs.

Raspberry Pi in BrickPi case

4) Screw the four long standoffs into corner slots of the bottom piece of acrylic.

BrickPi assembly process

5) Attach the BrickPi to the Raspberry Pi by mating the BrickPi’s header to the Raspberry Pi’s GPIO header.

BrickPi mounted on Raspberry Pi

6) (Optional) Now is a good time to label the motor and sensor ports on the BrickPi. I recommend S1, S2, and so on for the sensor ports and MA, MB, and so on for the motor ports.

BrickPi with labels

7) Attach the top piece of acrylic to the four posts using the remaining screws.

Fully assembled BrickPi with Raspberry Pi

8) Insert the SD card.

SD Card in Raspberry Pi inside BrickPi case

Attach Legos

Lego beams can be attached to the top and bottom pieces of acrylic in order to secure the BrickPi and Raspberry Pi to your Lego creation.

Lego pegs in BrickPi case

Attach Lego pegs to the holes in the acrylic

Lego beam on BrickPi case

Attach Lego beams to the pegs

Any of the Lego Mindstorms sensors can be attached to the ports labeled with an “S” followed by a number. You will need to remember the port number that you plugged your sensor into.

BrickPi Lego motor port locations

Sensor port locations (Image courtesy of dexterindustries.com)

Motors can be attached to the ports labeled with an “M” followed by a letter.

BrickPi Lego sensor port locations

Motor port locations (Image courtesy of dexterindustries.com)

For this example, connect a single touch sensor to S1 and a single servo motor to MA.

Sensor and motor connected to the BrickPi

Connect Peripherals

Similar to the setting up the Raspberry Pi tutorial, we need to connect a keyboard, mouse, and monitor. Plug a keyboard and mouse into the USB ports, and connect a monitor using an HDMI cable.

BrickPi and Raspberry Pi with connected peripherals

Powering the BrickPi

Dexter Industries recommends a few different ways to provide power to your Lego robot.

Powering the BrickPi

Dexter Industries' guide to powering the BrickPi (Image courtesy of dexterindustries.com)

However, we will do things differently. In order to get unlimited run time and the ability to power a couple of motors, we will hack a wall power supply to attach to the BrickPi.

1) Cut the 9V battery connector off of the 9V Snap Connector and strip the ends.

Hacked BrickPi 9V connector

2) Attach the red wire to the positive (+) and the black wire to the negative (-) screw terminals of the DC Barrel Jack Adapter.

Attach 9V connector ends to DC Barrel Jack Adapter

3) Plug the connector into the BrickPi.

Hacked 9V adapter on BrickPi

4) Plug the 9V wall adapter into the other end of the DC Barrel Jack Adapter.

5) IMPORTANT: Make sure your monitor is connected to the Raspberry Pi and turned on!

6) Plug the wall adapter power supply into a wall outlet.

WARNING: The large power regulator (TO-220 Package) gets hot! Be careful when plugging or unplugging the power adapter.

Highlighted regulator on BrickPi

7) Your Raspberry Pi should come to life!

Dexter Industries' custom Raspbian build

Configure the Raspberry Pi

Once the Raspberry Pi has booted, you should be presented with the Dexter Industries desktop. If you are ever asked for a username or password, the defaults are:

Username: pi
Password: raspberry

BrickPi Desktop

If you would like to configure the Raspberry Pi, open up a terminal:

Raspberry Pi Terminal

and enter the following command:

sudo raspi-config

You will be presented with the Raspberry Pi configuration screen. It is recommended that you expand the filesystem. Have a look at the other options (descriptions for the various options can be found here).

Raspberry Pi configuration

Programming

Open a terminal (if you do not already have one open) and create a new file for our motor and sensor test. Open that file with Leadpad (Raspbian’s default text editor).

leafpad motor_sensor.py

Enter the following code into the text editor:

from BrickPi import *

BrickPiSetup()

BrickPi.SensorType[PORT_1] = TYPE_SENSOR_TOUCH
BrickPi.MotorEnable[PORT_A] = 1

BrickPiSetupSensors()

while True:
        result = BrickPiUpdateValues()
        if not result:
                if BrickPi.Sensor[PORT_1]:
                        BrickPi.MotorSpeed[PORT_A] = 200
                else:
                        BrickPi.MotorSpeed[PORT_A] = 0
        time.sleep(0.01)

Raspberry Pi Leafpad with BrickPi Python code

Save and exit out of Leafpad. In the console, enter the following:

python motor_sensor.py

Now, whenever you press the Lego Touch Sensor, the Servo Motor should move!

BrickPi Python example working

Press ctrl+c to end the program.

Resources and Going Further

The BrickPi opens up many opportunities to expand on the Lego Mindstorms kit. To learn more about Dexter Industries and the BrickPi, check out their website: http://www.dexterindustries.com/BrickPi/.

If you are looking for some ideas, Dexter Industries updates their BrickPi site with interesting projects: http://www.dexterindustries.com/BrickPi/projects/

Resources


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

Tomatoless Boots - Reprogram Your Arduino from the Internet Using Electric Imp

0
0

Tomatoless Boots - Reprogram Your Arduino from the Internet Using Electric Imp a learn.sparkfun.com tutorial

Getting Started

Imp Arduino Bootloader Screen

Loading a new sketch via wireless

This tutorial will show you how to use an Electric Imp to repogram an Arduino from a webpage. Yep, you read that right. Now you can reprogram an Arduino (and an Imp) from anywhere in the world!

Picture of imp stack without yellow wire

The Electric Imp before modification for bootloading

The Electric Imp is a powerful device that allows you to connect to the internet relatively easily. For a lot of my Imp projects, I use an Arduino to handle the interface between the various bits of hardware. While reprogramming the Imp is extremely easy via their web-based IDE, reprogramming an Arduino is much more tedious and requires plugging in a computer and downloading new code. Why not use the Imp’s wireless connection to push new Arduino sketches as well?

If you’ve ever installed an Arduino into a place that required a scissor lift, in a water tight enclosure, on the top of a building, or into a paper-mache piñata, you understand how problematic it can be to fix that bug you never imagined. With a few bits of hardware you can have an Arduino attached firmly to the Internet of things as well as making the Imp+Arduino a heck of a lot easier to reprogram.

What in the world is Tomatoless Boots? Sorry. It’s a joke first told by Rob Faludi:

Wireless is a pointless way to describe wireless. It only describes what wireless is not, not what it is.
For example, it also has no tomatoes, so we might as well call it 'tomatoless'.

And since it’s a bootloader of sorts, we decided (against good judgement) to call it Tomatoless Boots. Zomg thank you Aron Steg for writing the original Imp code. We took his code and made a few improvements to dramatically improve the bootload time and to get it to work with general Arduinos.

Required Materials

Parts you’ll need:

This reprogramming-over-wifi trick only works with ATmega328 based Arduinos with a serial bootloader such as the Arduino Uno, Fio, LilyPad, Pro, Pro Mini, and RedBoard. This tutorial will not work with the Due, Leonardo, Micro, Galileo, or Teensy. There are probably some really good ways of getting these other boards to bootload over wifi but their bootloaders are different enough that this tutorial doesn’t attempt to cover them.

Suggested Reading

Other tutorials you may want to brush up on before diving into this one:

Bootloading 101

Now for a bit of history and bootloader basics:

Optiboot logo

The Optiboot Logo

There have been lots of serial bootloaders written throughout the years for lots of different microcontrollers. I wrote one for the PIC ages ago and one to wirelessly bootload Arduinos over XBee as well. The Arduino originally used the STK500 bootloader written by Atmel(see app note AVR061) that was then updated by Peter Knight and Bill Westfield to become the shrunk down Optiboot. Optiboot and a handful of similar bootloaders are what are installed on every ATmega328 based Arduino today.

The serial bootloader is activated each time the ATmega328/Arduino is powered up or reset. For a brief period of time (about 500ms), the microcontroller will listen for a special set of characters. If it hears nothing from the computer, then the ATmega will exit the bootloader and begin to run the user’s code that resides in flash memory. However, if the microcontroller hears those special characters, then it will know that a new program needs to be downloaded and begins to wait for a HEX file to be sent. Normally this communication is done while connected to a computer (via a USB to serial connection), but anything capable of attaching to the serial port on the Arduino has the option to reprogram it. The Imp can talk serial with ease, and the fact that it connects to the world wide web so easily makes it a good choice for wirelessly bootloading your board.

Hardware Connections

Bare Imp Shield

Imp Shield with no headers

The very first step is to solder the Arduino headers to the Imp shield. For more information about how to do this, checkout this tutorial.

Electric Imp Shield Schematic

Schematic for the Imp Shield

Next, we need to re-route the Imp’s UART to the Arduino’s serial pins (0 and 1). By default the Imp Shield connects the Imp’s serial port (pins 5 and 7) to Arduino’s pins 8 and 9.

Solder pads on Imp Shield

The TX and RX pads with default trace

Luckily, the genius behind the Imp shield design had the foresight to make it easy to switch pins (Jim is awesome). On the back of the shield, you’ll find two jumpers labeled RX and TX. In the image above, you should see a small trace connecting the TX and RX pins of the Imp to the right pads labeled 8 and 9.

Cut solder pads

Default trace has been cut

Carefully use an exacto knife to cut the default trace. If you’ve never cut a trace before don’t worry - it’s easy! Just take your time. Cutting a trace is less like cutting through metal and more like scoring tile or scraping ice off your windshield; it takes a few passes. Once you’ve cut the traces, use a multimeter to do a continuity test to verify that you have indeed severed the connection between the center pad and the pad to the right.

Pads soldered together

New connections jumpered

Next, add some solder and jumper the center pads to their matching left pad. The Imp should now be wired directly to the Arduino’s serial port.

Jumper wire from P1 to RST

Jumper wire added

The final hardware modification is a jumper from P1 of the Imp to RST on the shield. This will allow the Imp to reset the Arduino whenever it pulls the P1 pin low.

Full stack with jumper in place

Full stack with jumper in place

Once you’ve soldered the jumpers and single wire, add the Imp shield to your Arduino and connect a USB cable. Assuming you have commissioned your Imp to your local wifi, the Imp should power up, blink red, then blink green as it attaches to the Internet.


Now why did I tell you to take your time cutting the default traces? Because I made a big mistake when cutting the default TX trace. Have a second look:

Cut trace

Don’t see the problem? How about now:

A bad cut trace

Uh oh…

I was going too fast, the cut I made was too long, and I ended up cutting the TX trace to the Imp. When I attached everything to my Imp bootloading failed to work; everything was timing out because the Imp never heard a response from the Arduino (because the TX trace was cut). Luckily, I had a second functioning setup, so I tested my code on that. Everything worked, so I knew it must be a hardware problem with the board I was using for this tutorial. After a few minutes of scratching my head I used a multimeter to start probing for continuity. Once I discovered TX was not connected I tracked down this bad cut.

Green wire fix

Green wire fix

With some 30AWG wire wrap wire and some hemostats, the trace was quickly repaired, and the board started working as expected.

Take extra time when cutting traces so as to not cut beyond or knick nearby traces.

Software Connections

We are going to assume that you have already commissioned your Imp and gotten it onto your local wifi. Log in to your Electric Imp account and open the Imp IDE. Here is the code you’ll need to load code into the Agent:

Above is the code for the Imp Agent

And here is the code you’ll need to load into the Imp Device:

Above is the code for the Imp Device

Once you’ve successfully loaded both bits of code, find the agent link at the top of the page. Open another browser tab, and navigate to the agent link. You should be presented with a simple HTML page:

Imp Bootloading Page

Get ready… Go!

From here you can select the hex file you would like to send to your Arduino. The HEX file is found after compiling your sketch in the Arduino IDE. We’ll tell you how to get these HEX files in the next section. For now, use these two:

Download these HEX files to your local computer. Select the Blink-1Hz.hex from the ‘Choose File’ button, then ‘Send’ the file to the Arduino. After a few seconds, your Arduino should be bootloaded with the new program! The LED should be blinking once per second. Now select the Blink-Fast hex file, and upload it. The LED should now be blinking four times per second.

Output log in Imp IDE

Watch the output in the IDE

The Imp will provide various bits debug information as well during booloading. If you run into issues, be sure to check the output from the Imp IDE.

Getting HEX

By default, Arduino outputs the HEX file of your sketch to a rather hard to find, hidden, temporary folder such as C:\Users\Cylon\AppData\Local\Temp\build7734646579940080062.tmp\Blink.cpp.hex. Here’s a trick to make change the output folder of Arduino to an easier to find C:\HEXFiles\Blink.cpp.hex.

Arduino Preferences Menu

Open Arduino, and click on File->Preferences. This will show you where the preferences.txt file is stored. If you move your cursor to this area of the window, the directory will turn blue, and if you click on it, you will open the directory that contains the preferences.txt file. You must close Arduino before editing this file. Every time Arduino closes, it will overwrite the preferences file with the current settings. If you edit the preferences file while Arduino is open all your changes will be lost.

Arduino properties file

With Arduino closed, open the preferences.txt. Add a line:

build.path=C:\Arduino-Output\

Or the equivalent path for your OS. Any path without spaces is valid. I enjoy pointing both my Arduino sketch folder and output folder to a dropbox folder so that I can share libraries and HEX files between computers. You will need to avoid spaces in your build.path otherwise you may see this error:

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-ar: unable to rename 'core.a'; reason: File exists

For example: build.path=C:\Adruino HEX Files\ does not work because of the spaces.

Once you have a path in place, save the changes, and close the file. Reopen Arduino, and open a sketch of your choice (use the Examples->Digital->Blink if you have no other sketches). Hit the Verify button to compile the sketch.

HEX File in list

There’s the HEX file!

Now, navigate to the build.path folder. You should see a bunch of files including one with a .hex extension. This is the file that needs to be selected and sent via the Electric Imp bootloader.

Resources and Going Further

The Tomatoless Boots project is a work in progress. If you found this tutorial helpful, or if you know Squirrel and would like to help, we would love it! Please let us know. There is also a place over on Github to file issues and help make improvements. A few features that would make Tomatoless Boots even better:

  • Create a send again button: As you develop a project it’s common to send the same sketch over and over again with small tweaks so it would be really handy to avoid having to navigate to the same HEX file location. If the previous HEX file location can be remembered it should be relatively easy to create a button that allows a user to send the file that resides in the same spot. For example the contents of Blink.cpp.hex may change, but I’ll want to send it multiple times as I work out bugs and features. It would be nice to just hit a ‘Send Again’ button.

  • Pull from and poll a dropbox folder: If we can direct the Imp to monitor a page or folder location out on the Internet it would remove the need to even select the HEX file. I love dropbox, and it’s possible to have Arduino export directly to a given folder (see previous section). Why not have Arduino compile to a shared dropbox folder, and when the Imp detects a status change (aka /delta), automatically bootload that HEX file to the target Arduino?

For more wirless goodness, check out these other SparkFun tutorials:


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

How to Use an Oscilloscope

0
0

How to Use an Oscilloscope a learn.sparkfun.com tutorial

Introduction

Have you ever found yourself troubleshooting a circuit, needing more information than a simple multimeter can provide? If you need to uncover information like frequency, noise, amplitude, or any other characteristic that might change over time, you need an oscilloscope!

Oscilloscope in action

O-scopes are an important tool in any electrical engineer’s lab. They allow you to see electric signals as they vary over time, which can be critical in diagnosing why your 555 timer circuit isn’t blinking correctly, or why your noise maker isn’t reaching maximum annoyance levels.

Covered in This Tutorial

This tutorial aims to introduce the concepts, terminology, and control systems of oscilloscopes. It’s broken down into the following sections:

  • Basics of O-Scopes– An introduction to what, exactly, oscilloscopes are, what they measure, and why we use them.
  • Oscilloscope Lexicon– A glossary covering some of the more common oscilloscope characteristics.
  • Anatomy of an O-Scope– An overview of the most critical systems on an oscilloscope – the screen, horizontal and vertical controls, triggers, and probes.
  • Using an Oscilloscope– Tips and tricks for someone using an oscilloscope for the first time.

We’ll be using the Gratten GA1102CAL– a handy, mid-level, digital oscilloscope – as the basis for our scope discussion. Other o-scopes may look different, but they should all share a similar set of control and interface mechanisms.

Suggested Reading

Before continuing with this tutorial, you should be familiar with the concepts below. Check out the tutorial if you want to learn more!

Basics of O-Scopes

The main purpose of an oscilloscope is to graph an electrical signal as it varies over time. Most scopes produce a two-dimensional graph with time on the x-axis and voltage on the y-axis.

example o-scope graph

An example of an oscilloscope display. A signal (the yellow sine wave in this case) is graphed on a horizontal time axis and a vertical voltage axis.

Controls surrounding the scope’s screen allow you to adjust the scale of the graph, both vertically and horizontally – allowing you to zoom in and out on a signal. There are also controls to set the trigger on the scope, which helps focus and stabilize the display.

What Can Scopes Measure

In addition to those fundamental features, many scopes have measurement tools, which help to quickly quantify frequency, amplitude, and other waveform characteristics. In general a scope can measure both time-based and voltage-based characteristics:

  • Timing characteristics:
    • Frequency and period– Frequency is defined as the number of times per second a waveform repeats. And the period is the reciprocal of that (number of seconds each repeating waveform takes). The maximum frequency a scope can measure varies, but it’s often in the 100’s of MHz (1E6 Hz) range.
    • Duty cycle– The percentage of a period that a wave is either positive or negative (there are both positive and negative duty cycles). The duty cycle is a ratio that tells you how long a signal is “on” versus how long it’s “off” each period.
    • Rise and fall time– Signals can’t instantaneously go from 0V to 5V, they have to smoothly rise. The duration of a wave going from a low point to a high point is called the rise time, and fall time measures the opposite. These characteristics are important when considering how fast a circuit can respond to signals.
  • Voltage characteristics:
    • Amplitude– Amplitude is a measure of the magnitude of a signal. There are a variety of amplitude measurements including peak-to-peak amplitude, which measures the absoluted difference between a high and low voltage point of a signal. Peak amplitude, on the other hand, only measures how high or low a signal is past 0V.
    • Maximum and minimum voltages– The scope can tell you exactly how high and low the voltage of your signal gets.
    • Mean and average voltages– Oscilloscopes can calculate the average or mean of your signal, and it can also tell you the average of your signal’s minimum and maximum voltage.

When to Use an O-Scope

The o-scope is useful in a variety of troubleshooting and research situations, including:

  • Determining the frequency and amplitude of a signal, which can be critical in debugging a circuit’s input, output, or internal systems. From this, you can tell if a component in your circuit has malfunctioned.
  • Identifying how much noise is in your circuit.
  • Identifying the shape of a wave – sine, square, triangle, sawtooth, complex, etc.
  • Quantifying phase differences between two different signals.

Oscilloscope Lexicon

Learning how to use an oscilloscope means being introduced to an entire lexicon of terms. On this page we’ll introduce some of the important o-scope buzzwords you should be familiar with before turning one on.

Key Oscilloscope Specifications

Some scopes are better than others. These characteristics help define how well you might expect a scope to perform:

  • Bandwidth– Oscilloscopes are most commonly used to measure waveforms which have a defined frequency. No scope is perfect though, they all have limits as to how fast they can see a signal change. The bandwidth of a scope specifies the range of frequencies it can reliably measure.
  • Digital vs. Analog– As with most everything electronic, o-scopes can either be analog or digital. Analog scopes use an electron beam to directly map the input voltage to a display. Digital scopes incorporate microcontrollers, which sample the input signal with an analog-to-digital converter and map that reading to the display. Generally analog scopes are older, have a lower bandwidth, and less features, but they may have a faster response (and look much cooler).
  • Channel Amount– Many scopes can read more than one signal at a time, displaying them all on the screen simultaneously. Each signal read by a scope is fed into a separate channel. Two to four channel scopes are very common.
  • Sampling Rate– This characteristic is unique to digital scopes, it defines how many times per second a signal is read. If a scope has more than one channel, this value may decrease if multiple channels are in use.
  • Rise Time– The specified rise time of a scope defines the fastest rising pulse it can measure. The rise time of a scope is very closely related to the bandwidth. It can be calculated as Rise Time = 0.35 / Bandwidth.
  • Maximum Input Voltage– Every piece of electronics has its limits when it comes to high voltage. Scopes all have a
  • Resolution– The resolution of a scope represents how precisely it can measure the input voltage. This value can change as the vertical scale is adjusted.
  • Vertical Sensitivity– This value represents the minimum and maximum values of your vertical, voltage scale. This value is listed in volts per div.
  • Time Base– Time base usually indicates the range of sensitivities on the horizontal, time axis. This value is listed in seconds per div.
  • Input Impedance– When signal frequencies get very high, even a small impedance (resistance, capacitance, or inductance) added to a circuit can affect the signal. Every oscilloscope will add a certain impedance to a circuit it’s reading, called the input impedance. Input impedances are generally represented as a large resistive impedance (>1 MΩ) in parallel (||) with small capacitance (in the pF range). The impact of input impedance is more apparent when measuring very high frequency signals, and the probe you use may have to help compensate for it.

Using the GA1102CAL as an example, here are specifications you might expect from a mid-range scope:

CharacteristicValue
Bandwidth100 MHz
Sampling Rate1 GSa/s (1E9 samples per second)
Rise Time
Channel Count2
Maximum Input Voltage400V
Resolution8-bit
Vertical sensitivity2mV/div - 5V/div
Time base2ns/div - 50s/div
Input Impedance1 MΩ ±3% || 16pF ±3pF

Understanding these characteristics, you should be able to pick out an oscilloscope that’ll best fit your needs. But you still have to know how to use it…onto the next page!

Anatomy of An O-Scope

While no scopes are created exactly equal, they should all share a few similarities that make them function similarly. On this page we’ll discuss a few of the more common systems of an oscilloscope: the display, horizontal, vertical, trigger, and inputs.

The Display

An oscilloscope isn’t any good unless it can display the information you’re trying to test, which makes the display one of the more important sections on the scope.

scope screen example

Every oscilloscope display should be criss-crossed with horizontal and vertical lines called divisions. The scale of those divisions are modified with the horizontal and vertical systems. The vertical system is measured in “volts per division” and the horizontal is “seconds per division”. Generally, scopes will feature around 8-10 vertical (voltage) divisions, and 10-14 horizontal (seconds) divisions.

Older scopes (especially those of the analog variety) usually feature a simple, monochrome display, though the intensity of the wave may vary. More modern scopes feature multicolor LCD screens, which are a great help in showing more than one waveform at a time.

Many scope displays are situated next to a set of about five buttons – either to the side or below the display. These buttons can be used to navigate menus and control settings of the scope.

Vertical System

The vertical section of the scope controls the voltage scale on the display. There are traditionally two knobs in this section, which allow you to individually control the vertical position and volts/div.

The vertical system

The more critical volts per division knob allows you to set the vertical scale on the screen. Rotating the knob clockwise will decrease the scale, and counter-clockwise will increase. A smaller scale – fewer volts per division on the screen – means you’re more “zoomed in” to the waveform.

The display on the GA1102, for example, has 8 vertical divisions, and the volts/div knob can select a scale between 2mV/div and 5V/div. So, zoomed all the way in to 2mV/div, the display can show waveform that is 16mV from top to bottom. Fully “zoomed out”, the scope can show a waveform ranging over 40V. (The probe, as we’ll discuss below, can further increase this range.)

The position knob controls the vertical offset of the waveform on the screen. Rotate the knob clockwise, and the wave will move down, counter-clockwise will move it up the display. You can use the position knob to offset part of a waveform off the screen.

alt text

Using both the position and volts/div knobs in conjunction, you can zoom in on just a tiny part of the waveform that you care about the most. If you had a 5V square wave, but only cared about how much it was ringing on the edges, you could zoom in on the rising edge using both knobs.

Horizontal System

The horizontal section of the scope controls the time scale on the screen. Like the vertical system, the horizontal control gives you two knobs: position and seconds/div.

The horizontal system

The seconds per division (s/div) knob rotates to increase or decrease the horizontal scale. If you rotate the s/div knob clockwise, the number of seconds each division represents will decrease – you’ll be “zooming in” on the time scale. Rotate counter-clockwise to increase the time scale, and show a longer amount of time on the screen.

Using the GA1102 as an example again, the display has 14 horizontal divisions, and can show anywhere between 2nS and 50s per division. So zoomed all the way in on the horizontal scale, the scope can show 28nS of a waveform, and zoomed way out it can show a signal as it changes over 70 seconds.

The position knob can move your waveform to the right or left of the display, adjusting the horizontal offset.

Using the horizontal system, you can adjust how many periods of a waveform you want to see. You can zoom out, and show multiple peaks and troughs of a signal:

Zoomed out, showing multiple periods

Or you can zoom way in, and use the position knob to show just a tiny part of a wave:

Zoom in to show half a period

Trigger System

The trigger section is devoted to stabilizing and focusing the oscilloscope. The trigger tells the scope what parts of the signal to “trigger” on and start measuring. If your waveform is periodic, the trigger can be manipulated to keep the display static and unflinching. A poorly triggered wave will produce seizure-inducing sweeping waves like this:

untriggered wave

The trigger section of a scope is usually comprised of a level knob and a set of buttons to select the source and type of the trigger. The level knob can be twisted to set a trigger to a specific voltage point.

trigger system

A series of buttons and screen menus make up the rest of the trigger system. Their main purpose is to select the trigger source and mode. There are a variety of trigger types, which manipulate how the trigger is activated:

  • An edge trigger is the most basic form of the trigger. It will key the oscilloscope to start measuring when the signal voltage passes a certain level. An edge trigger can be set to catch on a rising or falling edge (or both).
  • A pulse trigger tells the scope to key in on a specified “pulse” of voltage. You can specify the duration and direction of the pulse. For example, it can be a tiny blip of 0V -> 5V -> 0V, or it can be a seconds-long dip from 5V to 0V, back to 5V.
  • A slope trigger can be set to trigger the scope on a positive or negative slope over a specified amount of time.
  • More complicated triggers exist to focus on standardized waveforms that carry video data, like NTSC or PAL. These waves use a unique synchronizing pattern at the begging of every frame.

You can also usually select a triggering mode, which, in effect, tells the scope how strongly you feel about your trigger. In automatic trigger mode, the scope can attempt to draw your waveform even if it doesn’t trigger. Normal mode will only draw your wave if it sees the specified trigger. And single mode looks for your specified trigger, when it sees it it will draw your wave then stop.

The Probes

An oscilloscope is only good if you can actually connect it to a signal, and for that you need probes. Probes are single-input devices that route a signal from your circuit to the scope. They have a sharp tip which probes into a point on your circuit. The tip can also be equipped with hooks, tweezers or clips to make latching onto a circuit easier. Every probe also includes a ground clip, which should be secured safely to a common ground point on the circuit under test.

probe image

While probes may seem like simple devices that just latch onto your circuit and carry a signal to the scope, there’s actually a lot that goes into probe design and selection.

Optimally, what a probe needs to be is invisible – it shouldn’t have any effect on your signal under test. Unfortunately, long wires all have intrinsic inductance, capacitance, and resistance, so, no matter what, they’ll affect scope readings (especially at high frequencies).

There are a variety of probe types out there, the most common of which is the passive probe, included with most scopes. Most of the “stock” passive probes are attenuated. Attenuating probes have a large resistance intentionally built-in and shunted by a small capacitor, which helps to minimize the effect that a long cable might have on loading your circuit. In series with the input impedance of a scope, this attenuated probe will create a voltage divider between your signal and the scope input.

simplified schematic of probe, transmission wire, scope input

Most probes have a 9MΩ resistor for attenuating, which, when combined with a standard 1MΩ input impedance on a scope, creates a 1/10 voltage divider. These probes are commonly called 10X attenuated probes. Many probes include a switch to select between 10X and 1X (no attenuation).

Probe attenuation settings

Attenuated probes are great for improving accuracy at high frequencies, but they will also reduce the amplitude of your signal. If you’re trying to measure a very low-voltage signal, you may have to go with a 1X probe. You may also need to select a setting on your scope to tell it you’re using an attenuated probe, although many scopes can automatically detect this.

Beyond the passive attenuated probe, there are a variety of other probes out there. Active probes are powered probes (they require a separate power source), which can amplify your signal or even pre-process it before it get to your scope. While most probes are designed to measure voltage, there are probes designed to measure AC or DC current. Current probes are unique because they often clamp around a wire, never actually making contact with the circuit.

Using an Oscilloscope

The infinite variety of signals out there means you’ll never operate an oscilloscope the same way twice. But there are some steps you can count on performing just about every time you test a circuit. On this page we’ll show an example signal, and the steps required to measure it.

Probe Selection and Setup

First off, you’ll need to select a probe. For most signals, the simple passive probe included with your scope will work perfectly fine.

Next, before connecting it to your scope, set the attenuation on your probe. 10X – the most common attenuation factor – is usually the most well-rounded choice. If you’re trying to measure a very low-voltage signal though, you may need to use 1X.

Connect the Probe and Turn the Scope On

Connect your probe to the first channel on your scope, and turn it on. Have some patience here, some scopes take as long to boot up as an old PC.

When the scope boots up you should see the divisions, scale, and a noisy, flat line of a waveform.

scope flat lined

The screen should also show previously set values for time and volts per div. Ignoring those scales for now, make these adjustments to put your scope into a standard setup:

  • Turn channel 1 on and channel 2 off.
  • Set channel 1 to DC coupling.
  • Set the trigger source to channel 1 – no external source or alternate channel triggering.
  • Set the trigger type to rising edge, and the trigger mode to auto (as opposed to single).
  • Make sure the scope probe attenuation on your scope matches the setting on your probe (e.g. 1X, 10X).

For help making these adjustments, consult your scope’s user’s manual (as an example, here’s the GA1102CAL manual).

Testing the Probe

Let’s connect that channel up to a meaningful signal. Most scopes will have a built-in frequency generator that emits a reliable, set-frequency wave – on the GA1102CAL there is a 1kHz square wave output at the bottom-right of the front panel. The frequency generator output has two separate conductors – one for the signal and one for ground. Connect your probe’s ground clip to the ground, and the probe tip to the signal output.

alt text

As soon as you connect both parts of the probe, you should see a signal begin to dance around your screen. Try fiddling with the horizontal and vertical system knobs to maneuver the waveform around the screen. Rotating the scale knobs clockwise will “zoom into” your waveform, and counter-clockwise zooms out. You can also use the position knob to further locate your waveform.

If your wave is still unstable, try rotating the trigger position knob. Make sure the trigger isn’t higher than the tallest peak of your waveform. By default, the trigger type should be set to edge, which is usually a good choice for square waves like this.

Try fiddling with those knobs enough to display a single period of your wave on the screen.

single period of square wave

Or try zooming way out on the time scale to show dozens of squares.

Compensating an Attenuated Probe

If your probe is set to 10X, and you don’t have a perfectly square waveform as shown above, you may need to compensate your probe. Most probes have a recessed screw head, which you can rotate to adjust the shunt capacitance of the probe.

Probe compensating screw

Try using a small screwdriver to rotate this trimmer, and look at what happens to the waveform.

Effect of compensation

Adjust the trimming cap on the probe handle until you have a straight-edged square wave. Compensation is only necessary if your probe is attenuated (e.g. 10X), in which case it’s critical (especially if you don’t know who used your scope last!).

Probing, Triggering, and Scaling Tips

Once you’ve compensated your probe, it’s time to measure a real signal! Go find a signal source (frequency generator?, Terror-Min?) and come back.

The first key to probing a signal is finding a solid, reliable grounding point. Clasp your ground clip to a known ground, sometimes you may have to use a small wire to intermediate between the ground clip and your circuit’s ground point. Then connect your probe tip to the signal under test. Probe tips exist in a variety of form factors – the spring-loaded clip, fine point, hooks, etc. – try to find one that doesn’t require you to hold it in place all the time.

alt text

Once your signal is on the screen, you may want to begin by adjusting the horizontal and vertical scales into at least the “ballpark” of your signal. If you’re probing a 5V 1kHz square wave, you’ll probably want the volts/div somewhere around 0.5-1V, and set the seconds/div to around 100µs (14 divisions would show about one and a half periods).

If part of your wave is rising or falling of the screen, you can adjust the vertical position to move it up or down. If your signal is purely DC, you may want to adjust the 0V level near the bottom of your display.

Once you have the scales ballparked, your waveform may need some triggering. Edge triggering– where the scope tries to begin its scan when it sees voltage rise (or fall) past a set point – is the easiest type to use. Using an edge trigger, try to set the trigger level to a point on your waveform that only sees a rising edge once per period.

Now just scale, position, trigger and repeat until you’re looking at exactly what you need.

Measure Twice, Cut Once

With a signal scoped, triggered, and scaled, it comes time to measure transients, periods, and other waveform properties. Some scopes have more measurement tools than others, but they’ll all at least have divisions, from which you should be able to at least estimate the amplitude and frequency.

Many scopes support a variety of automatic measurement tools, they may even constantly display the most relevant information, like frequency. To get the most out of your scope, you’ll want to explore all of the measure functions it supports. Most scopes will calculate frequency, amplitude, duty cycle, mean voltage, and a variety of other wave characteristics for you automatically.

Measuring with the scope

Using the scope’s measure tools to find VPP, VMax, frequency, period, and duty cycle.

A third measuring tool many scopes provide is cursors. Cursors are on-screen, movable markers which can be placed on either the time or voltage axis. Cursors usually come in pairs, so you can measure the difference between one and the other.

Scoping with a cursor

Measuring the ringing of a square wave with cursors.

Once you’ve measured the quantity you were looking for, you can begin to make adjustments to your circuit and measure some more! Some scopes also support saving, printing, or storing a waveform, so you can recall it and remember those good ol' times when you scoped that signal.

To find out more about what your scope can do, consult its user’s manual!

Resources and Going Further

With the tools discussed in this tutorial, you should be prepared to start scoping signals of your own. If you’re still unsure of what certain parts of your scope are for, first consult your user’s manual. Here are some additional resources we recommend checking out as well:

Going Further

Now that you’re a practiced oscilloscop-er, what circuit are you going to be debugging? Need some inspiration? Here are some related tutorials we’d recommend checking out next!

  • PCB Design with EAGLE– If you’re at a point where you need to troubleshoot circuits at the signal level, maybe you’re ready to step into designing PCBs. Our EAGLE series of tutorials how to use the freely available software to design your own circuit boards.
  • Recreating Classic Electronics Kits– If you’re in search of a circuit to troubleshoot with a scope, why not make your own version of 50-in-1 electronics kit?
  • Pulse-Width Modulation– PWM signals are the foundation behind dimming LEDs and driving servo motors. Learn about these signal types and then scope them with your new skills!

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

Wireless Arduino Programming with Electric Imp

0
0

Wireless Arduino Programming with Electric Imp a learn.sparkfun.com tutorial

Getting Started

Imp Arduino Bootloader Screen

Loading a new sketch via wireless

This tutorial will show you how to use an Electric Imp to repogram an Arduino from a webpage. Yep, you read that right. Now you can reprogram an Arduino (and an Imp) from anywhere in the world!

Picture of imp stack without yellow wire

The Electric Imp before modification for bootloading

The Electric Imp is a powerful device that allows you to connect to the internet relatively easily. For a lot of my Imp projects, I use an Arduino to handle the interface between the various bits of hardware. While reprogramming the Imp is extremely easy via their web-based IDE, reprogramming an Arduino is much more tedious and requires plugging in a computer and downloading new code. Why not use the Imp’s wireless connection to push new Arduino sketches as well?

If you’ve ever installed an Arduino into a place that required a scissor lift, in a water tight enclosure, on the top of a building, or into a paper-mache piñata, you understand how problematic it can be to fix that bug you never imagined. With a few bits of hardware you can have an Arduino attached firmly to the Internet of things as well as making the Imp+Arduino a heck of a lot easier to reprogram.

What in the world is Tomatoless Boots? Sorry. It’s a joke first told by Rob Faludi:

Wireless is a pointless way to describe wireless. It only describes what wireless is not, not what it is.
For example, it also has no tomatoes, so we might as well call it 'tomatoless'.

And since it’s a bootloader of sorts, we decided (against good judgement) to call it Tomatoless Boots. Zomg thank you Aron Steg for writing the original Imp code. We took his code and made a few improvements to dramatically improve the bootload time and to get it to work with general Arduinos.

Required Materials

Parts you’ll need:

Here’s a wishlist of the core parts without any tools:

This reprogramming-over-wifi trick only works with ATmega328 based Arduinos with a serial bootloader such as the Arduino Uno, Fio, LilyPad, Pro, Pro Mini, and RedBoard. This tutorial will not work with the Due, Leonardo, Micro, Galileo, or Teensy. There are probably some really good ways of getting these other boards to bootload over wifi but their bootloaders are different enough that this tutorial doesn’t attempt to cover them.

Suggested Reading

Other tutorials you may want to brush up on before diving into this one:

Bootloading 101

Now for a bit of history and bootloader basics:

Optiboot logo

The Optiboot Logo

There have been lots of serial bootloaders written throughout the years for lots of different microcontrollers. I wrote one for the PIC ages ago and one to wirelessly bootload Arduinos over XBee as well. The Arduino originally used the STK500 bootloader written by Atmel(see app note AVR061) that was then updated by Peter Knight and Bill Westfield to become the shrunk down Optiboot. Optiboot and a handful of similar bootloaders are what are installed on every ATmega328 based Arduino today.

The serial bootloader is activated each time the ATmega328/Arduino is powered up or reset. For a brief period of time (about 500ms), the microcontroller will listen for a special set of characters. If it hears nothing from the computer, then the ATmega will exit the bootloader and begin to run the user’s code that resides in flash memory. However, if the microcontroller hears those special characters, then it will know that a new program needs to be downloaded and begins to wait for a HEX file to be sent. Normally this communication is done while connected to a computer (via a USB to serial connection), but anything capable of attaching to the serial port on the Arduino has the option to reprogram it. The Imp can talk serial with ease, and the fact that it connects to the world wide web so easily makes it a good choice for wirelessly bootloading your board.

Hardware Connections

Bare Imp Shield

Imp Shield with no headers

The very first step is to solder the Arduino headers to the Imp shield. For more information about how to do this, checkout this tutorial.

Electric Imp Shield Schematic

Schematic for the Imp Shield

Next, we need to re-route the Imp’s UART to the Arduino’s serial pins (0 and 1). By default the Imp Shield connects the Imp’s serial port (pins 5 and 7) to Arduino’s pins 8 and 9.

Solder pads on Imp Shield

The TX and RX pads with default trace

Luckily, the genius behind the Imp shield design had the foresight to make it easy to switch pins (Jim is awesome). On the back of the shield, you’ll find two jumpers labeled RX and TX. In the image above, you should see a small trace connecting the TX and RX pins of the Imp to the right pads labeled 8 and 9.

Cut solder pads

Default trace has been cut

Carefully use an exacto knife to cut the default trace. If you’ve never cut a trace before don’t worry - it’s easy! Just take your time. Cutting a trace is less like cutting through metal and more like scoring tile or scraping ice off your windshield; it takes a few passes. Once you’ve cut the traces, use a multimeter to do a continuity test to verify that you have indeed severed the connection between the center pad and the pad to the right.

Pads soldered together

New connections jumpered

Next, add some solder and jumper the center pads to their matching left pad. The Imp should now be wired directly to the Arduino’s serial port.

Jumper wire from P1 to RST

Jumper wire added

The final hardware modification is a jumper from P1 of the Imp to RST on the shield. This will allow the Imp to reset the Arduino whenever it pulls the P1 pin low.

Full stack with jumper in place

Full stack with jumper in place

Once you’ve soldered the jumpers and single wire, add the Imp shield to your Arduino and connect a USB cable. Assuming you have commissioned your Imp to your local wifi, the Imp should power up, blink red, then blink green as it attaches to the Internet.


Now why did I tell you to take your time cutting the default traces? Because I made a big mistake when cutting the default TX trace. Have a second look:

Cut trace

Don’t see the problem? How about now:

A bad cut trace

Uh oh…

I was going too fast, the cut I made was too long, and I ended up cutting the TX trace to the Imp. When I attached everything to my Imp bootloading failed to work; everything was timing out because the Imp never heard a response from the Arduino (because the TX trace was cut). Luckily, I had a second functioning setup, so I tested my code on that. Everything worked, so I knew it must be a hardware problem with the board I was using for this tutorial. After a few minutes of scratching my head I used a multimeter to start probing for continuity. Once I discovered TX was not connected I tracked down this bad cut.

Green wire fix

Green wire fix

With some 30AWG wire wrap wire and some hemostats, the trace was quickly repaired, and the board started working as expected.

Take extra time when cutting traces so as to not cut beyond or knick nearby traces.

Software Connections

We are going to assume that you have already commissioned your Imp and gotten it onto your local wifi. Log in to your Electric Imp account and open the Imp IDE. Here is the code you’ll need to load code into the Agent:

Above is the code for the Imp Agent

And here is the code you’ll need to load into the Imp Device:

Above is the code for the Imp Device

Once you’ve successfully loaded both bits of code, find the agent link at the top of the page. Open another browser tab, and navigate to the agent link. You should be presented with a simple HTML page:

Imp Bootloading Page

Get ready… Go!

From here you can select the hex file you would like to send to your Arduino. The HEX file is found after compiling your sketch in the Arduino IDE. We’ll tell you how to get these HEX files in the next section. For now, use these two:

Download these HEX files to your local computer. Select the Blink-1Hz.hex from the ‘Choose File’ button, then ‘Send’ the file to the Arduino. After a few seconds, your Arduino should be bootloaded with the new program! The LED should be blinking once per second. Now select the Blink-Fast hex file, and upload it. The LED should now be blinking four times per second.

Output log in Imp IDE

Watch the output in the IDE

The Imp will provide various bits debug information as well during booloading. If you run into issues, be sure to check the output from the Imp IDE.

Getting HEX

By default, Arduino outputs the HEX file of your sketch to a rather hard to find, hidden, temporary folder such as C:\Users\Cylon\AppData\Local\Temp\build7734646579940080062.tmp\Blink.cpp.hex. Here’s a trick to make change the output folder of Arduino to an easier to find C:\HEXFiles\Blink.cpp.hex.

Arduino Preferences Menu

Open Arduino, and click on File->Preferences. This will show you where the preferences.txt file is stored. If you move your cursor to this area of the window, the directory will turn blue, and if you click on it, you will open the directory that contains the preferences.txt file. You must close Arduino before editing this file. Every time Arduino closes, it will overwrite the preferences file with the current settings. If you edit the preferences file while Arduino is open all your changes will be lost.

Arduino properties file

With Arduino closed, open the preferences.txt. Add a line:

build.path=C:\Arduino-Output\

Or the equivalent path for your OS. Any path without spaces is valid. I enjoy pointing both my Arduino sketch folder and output folder to a dropbox folder so that I can share libraries and HEX files between computers. You will need to avoid spaces in your build.path otherwise you may see this error:

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-ar: unable to rename 'core.a'; reason: File exists

For example: build.path=C:\Adruino HEX Files\ does not work because of the spaces.

Once you have a path in place, save the changes, and close the file. Reopen Arduino, and open a sketch of your choice (use the Examples->Digital->Blink if you have no other sketches). Hit the Verify button to compile the sketch.

HEX File in list

There’s the HEX file!

Now, navigate to the build.path folder. You should see a bunch of files including one with a .hex extension. This is the file that needs to be selected and sent via the Electric Imp bootloader.

Resources and Going Further

The Tomatoless Boots project is a work in progress. If you found this tutorial helpful, or if you know Squirrel and would like to help, we would love it! Please let us know. There is also a place over on Github to file issues and help make improvements. A few features that would make Tomatoless Boots even better:

  • Create a send again button: As you develop a project it’s common to send the same sketch over and over again with small tweaks so it would be really handy to avoid having to navigate to the same HEX file location. If the previous HEX file location can be remembered it should be relatively easy to create a button that allows a user to send the file that resides in the same spot. For example the contents of Blink.cpp.hex may change, but I’ll want to send it multiple times as I work out bugs and features. It would be nice to just hit a ‘Send Again’ button.

  • Pull from and poll a dropbox folder: If we can direct the Imp to monitor a page or folder location out on the Internet it would remove the need to even select the HEX file. I love dropbox, and it’s possible to have Arduino export directly to a given folder (see previous section). Why not have Arduino compile to a shared dropbox folder, and when the Imp detects a status change (aka /delta), automatically bootload that HEX file to the target Arduino?

For more wirless goodness, check out these other SparkFun tutorials:


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

Hackers in Residence - Hacking MindWave Mobile

0
0

Hackers in Residence - Hacking MindWave Mobile a learn.sparkfun.com tutorial

Introduction

Brought to you by Hacker in Residence, Sophi Kravitz.

Have you ever wanted to control something just by thinking about it? Well, you’re in luck. The MindWave allows you to turn electronic signals that flow in your body into digital signals that can be understood by a microcontroller. There is also the MindWave Mobile, which is designed ot interface with your mobile devices. This tutorial will serve as half teardown/review and half project. After we explore the inner-workings of the MindWave Mobile, we’ll switch gears and focus on hacking it.

mindwave mobile

Covered in This Tutorial

This tutorial will go over:

  • What is MindWave Mobile?
  • Configuring the RN42 Bluetooth module
  • Pairing MindWave Mobile with the RN42
  • What is the data you will see coming out of the MindWave? What does it mean?
  • Programming the Arduino with provided source code to see MindWave data
  • Using Processing to graph specific values from the digital data
  • Next steps, after the MindWave

Suggested Reading

This tutorial builds on some previously covered topics. Please visit any of the links below if you are unfamiliar with the concepts mentioned.

What is the MindWave Mobile?

alt text

The MindWave Mobile from NeuroSky

To understand the MindWave and MindWave Mobile, we must first understand what an EEG sensor is. The first recording of the human brain’s electric field was made by Hans Berger, a German psychiatrist, in 1924. Berger gave the recording the name electroencephalogram (EEG). Put simply, the EEG is performed by placing electrodes all over the subject’s scalp, and then reading in the electrical signals for analysis. Fast forward to today, and you have all of this technology packed into a compact form factor that is the MindWave and the MindWave Mobile.

Project Scope

The amplitude of the EEG is ~ 100 µV when measured on the scalp, and about 1-2 mV when measured on the surface of the brain. The bandwidth of this signal is from under 1 Hz to about 50 Hz.

Because of the amplitude and low frequency of the brainwave signal, I was curious about how well a relatively cheap (~$100) sensor would measure brain signals.

In this project, the analog brainwaves enter a processing ASIC chip and have digital values that are communicated over Bluetooth. I accessed only the digital data. It is certainly possible to look at the analog brain waves before they enter the processing ASIC, but it would be much more difficult, requiring a schematic and specialized oscilloscope probes.

The Mindwave Mobile was chosen because because it uses Bluetooth, making it easier to interface it with a microcontroller or other hardware. Please note that Neurosky has multiple models of the MindWave.

alt text

SFE Creative Technologist, Nick Poole, sporting the MindWave. The electrode rests on the forehead, above the eyebrow, and the reference clips onto the ear.

Taking it Apart

Pictured here is the MindWave headset. Nick Poole took one of these apart, so the insides of the headset are pictured here as well.

alt text

Here is a closeup of the internal circuitry. You may recognize the MSP430 hanging out at the top.

alt text

And, the backside….

alt text

In between the two boards is an ASIC. The ASIC on the Neurosky calculates a value for Attention and Meditation. It also processes five types of brainwaves (more on this shortly) and sends out unitless values for each one. This unit measures eyeblinks too.

alt text

Gathering Materials

In order to interface with the MindWave, you’ll need a few bits of hardware and software.

Hardware

To interface with the MindWave, the RN-42 Bluetooth module was chosen. For this project, I created a custom PCB, however, you could also use a BlueSMiRF or a Bluetooth Mate. The Bluetooth module will be connected to an Arduino Uno to read in the data being transmitted wirelessly.

alt text

The BlueSMiRF Silver module from SparkFun.

Once you’ve decided on which hardware you’ll be using, connect everything. Again, the Bluetooth Basics and BlueSMiRF tutorials should cover how to do this extensively.

Software

You’ll want to get some programs to be able to read data from and configure the RN42 Bluetooth module.

If you are unfamiliar with serial terminal emulators, please check out our tutorial.

Firmware

Here is the firmware for the Arduino side of this project. If you are following along, you’ll want to upload this to whichever Arduino board you are using.

language:c
///////////////////////////////////////////////////////////////
// Arduino Bluetooth Interface with Mindwave
// Sophi Kravitz edit 11-4
// Shane Clements edit 11-5
////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>     // library for software serial
SoftwareSerial mySerial(5, 6);  // RX, TX
int LED = 8;                    // yellow one
int LED1 = 7;                   //white one
int BAUDRATE = 57600;

// checksum variables
byte payloadChecksum = 0;
byte CalculatedChecksum;
byte checksum = 0;              //data type byte stores an 8-bit unsigned number, from 0 to 255
int payloadLength = 0;
byte payloadData[64] = {0};
byte poorQuality = 0;
byte attention = 0;
byte meditation = 0;

// system variables
long lastReceivedPacket = 0;
boolean bigPacket = false;
boolean brainwave = false;
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(LED1, OUTPUT);
  digitalWrite(LED, HIGH);   // hello sequence
  delay(100);
  digitalWrite(LED, LOW);
  delay(100);
  Serial.begin(57600);       // Bluetooth
  delay(500);
  mySerial.begin(4800);      // software serial
  delay(500);
  mySerial.print("Communicating... ");
  mySerial.println();
}
byte ReadOneByte() {
   int ByteRead;
  // Wait until there is data
  while(!Serial.available());
  //Get the number of bytes (characters) available for reading from the serial port.
  //This is data that's already arrived and stored in the serial receive buffer (which holds 64 bytes)
  ByteRead = Serial.read();
  return ByteRead; // read incoming serial data
  }

unsigned int delta_wave = 0;
unsigned int theta_wave = 0;
unsigned int low_alpha_wave = 0;
unsigned int high_alpha_wave = 0;
unsigned int low_beta_wave = 0;
unsigned int high_beta_wave = 0;
unsigned int low_gamma_wave = 0;
unsigned int mid_gamma_wave = 0;

void read_waves(int i) {
  delta_wave = read_3byte_int(i);
  i+=3;
  theta_wave = read_3byte_int(i);
  i+=3;
  low_alpha_wave = read_3byte_int(i);
  i+=3;
  high_alpha_wave = read_3byte_int(i);
  i+=3;
  low_beta_wave = read_3byte_int(i);
  i+=3;
  high_beta_wave = read_3byte_int(i);
  i+=3;
  low_gamma_wave = read_3byte_int(i);
  i+=3;
  mid_gamma_wave = read_3byte_int(i);
}

int read_3byte_int(int i) {
  return ((payloadData[i] << 16) + (payloadData[i+1] << 8) + payloadData[i+2]);
}

void loop() {
  // Look for sync bytes
  // Byte order: 0xAA, 0xAA, payloadLength, payloadData,
  // Checksum (sum all the bytes of payload, take lowest 8 bits, then bit inverse on lowest
if(ReadOneByte() == 0xAA) {
if(ReadOneByte() == 0xAA) {
payloadLength = ReadOneByte();
if(payloadLength > 169) //Payload length can not be greater than 169
return;
payloadChecksum = 0;
      for(int i = 0; i < payloadLength; i++) {      //loop until payload length is complete
        payloadData[i] = ReadOneByte();             //Read payload
        payloadChecksum += payloadData[i];
      }
      checksum = ReadOneByte();                     //Read checksum byte from stream
      payloadChecksum = 255 - payloadChecksum;      //Take one’s compliment of generated checksum
      if(checksum == payloadChecksum) {
        poorQuality = 200;
        attention = 0;
        meditation = 0;
 }
     brainwave = false;
     for(int i = 0; i < payloadLength; i++) { // Parse the payload
          switch (payloadData[i]) {
          case 02:
            i++;
            poorQuality = payloadData[i];
            bigPacket = true;
            break;
          case 04:
            i++;
            attention = payloadData[i];
            break;
          case 05:
            i++;
            meditation = payloadData[i];
            break;
          case 0x80:
            i = i + 3;
            break;
          case 0x83:                         // ASIC EEG POWER INT
            i++;
            brainwave = true;
            byte vlen = payloadData[i];
            //mySerial.print(vlen, DEC);
            //mySerial.println();
            read_waves(i+1);
            i += vlen; // i = i + vlen
            break;
          }                                 // switch
        }                                   // for loop

        if(bigPacket) {
          if(poorQuality == 0){
          }
          else{                             // do nothing
           }
         }


            if(brainwave && attention > 0 && attention < 100) {
            mySerial.print("Attention value is: ");
            mySerial.print(attention, DEC);
            mySerial.println();
            mySerial.print("Delta value is: ");
            mySerial.print(delta_wave, DEC);
            mySerial.println();
            mySerial.print("Theta value is: ");
            mySerial.print(theta_wave, DEC);
      mySerial.println();
            mySerial.print("Low Alpha value is: ");
            mySerial.print(low_alpha_wave, DEC);
            mySerial.println();
            mySerial.print("High Alpha value is: ");
            mySerial.print(high_alpha_wave, DEC);
            mySerial.println();
            mySerial.print("Alertness value1 is: ");
            mySerial.print(low_beta_wave, DEC);
            mySerial.println();
            mySerial.print("Alertness value2 is: ");
            mySerial.print(high_beta_wave, DEC);
            mySerial.println();
            mySerial.print(low_gamma_wave, DEC);
            mySerial.println();
            mySerial.print(mid_gamma_wave, DEC);
            mySerial.println();
         }

          if(attention > 40){
            digitalWrite(LED1, HIGH);
          }
          else
            digitalWrite(LED1, LOW);
        }
        }
      }

Here is the Processing code, which interprets the data coming from the MindWave to the Arduino, and then gives you a visual representation of that data.

language:java
//Processing code to graph Attention values
//Comment out all of the lines after “if(brainwave && attention > 0 && attention < 100) {“
//Except for
//mySerial.print(attention, DEC);
// mySerial.println();
//This will print out ONLY an Attention value and a new line afterwards

// Graphing sketch by Tom Igoe
// Sophi Kravitz edit 11/8

 import processing.serial.*;
 Serial myPort;        // The serial port
 int xPos = 1;         // horizontal position of the graph
 void setup () {
 // set the window size:
 size(400, 300);
String portName = Serial.list()[1];         //[1]  println(Serial.list()) to find the ports
 myPort = new Serial(this, "COM16", 4800);  // make sure the Baud rate matches the Arduino code
 myPort.bufferUntil('\n');                  // Wait for newline character:
 background(0);                             // set inital background color: 0 = black, 255 = white
 }

void draw () {                              // everything happens in the serialEvent()
 }

 void serialEvent (Serial myPort) {
 String inString = myPort.readStringUntil('\n');

   if (inString != null) {                  // trim whitespace:
   inString = trim(inString);               // convert to an int and map to the screen height:
   float inByte = float(inString);
   inByte = map(inByte, 0, 100, 0, height); // take number from 0 to 100, and map it to 0 to height
   stroke(5,34,255);                        // draw the line:
   line(xPos, height, xPos, height - inByte);

   if (xPos >= width) {                     // at the edge of the screen, go back to the beginning:
   xPos = 0;
   background(0);
   }
   else {
   xPos++;                                  // increment the horizontal position:
   }
 }
 }

Configuring the Bluetooth Module

The RN42 module can be configured to behave in a variety of different ways. If you have never configured one of the RN Bluetooth modules, please read our BlueSMiRF Hookup Guide.

You can use any serial terminal you wish to configure the bluetooth module. For this project, I used my Android phone with an app called S2 Terminal for Bluetooth to configure the RN42. The configuration process went as so:

Note: If you are using the S2 Terminal program, you will need to type in ASCII and put a return after each command. Also, you only have 60 seconds after power up to enter the first command.

  1. To put the RN42 into COMMAND mode, type $$$ (NO carriage return). If successful, you will see “CMD”.
  2. Type: D + carriage return. You will see the current configuration of the RN42.

    alt text

  3. Type: SP,0000 + carriage return. This will change the pincode from ‘1234’ to ‘0000’. You will see “AOK” if this is done properly.

  4. Type: SM, 3 + carriage return. This will configure the RN42 to Auto-Connect Mode. Once the module is powered up, it will immediately look to connect (pair).You will see “AOK” if this is done properly.
  5. Type: SR,MAC ADDRESS + carriage return. Insert the 12 digit address you copied from the MindWave Mobile. Look for AOK. If you don’t see AOK, you’ll have to retype the MAC address command.
  6. Now type: SU,57.6 + carriage return. This will change the baud rate from 115200 to 57600.

    alt text

  7. Type D + carriage return. Double check that the stored address is the Mac address you entered in step 5 and that it’s configured to Auto, not Slave.

  8. Type: --- (three minus signs) + carriage return You should then see END.

    alt text

Turn the Mindwave on. The blue light flashes for a few moments, then it will pair with your hardware. You’ll know that the Mindwave Mobile is paired because the blue light on the Mindwave Mobile is solid. If it is solid red, it is out of battery (AAA, lasts for about 8 hours).

Deciphering the MindWave Data

Using an FTDI basic, I was able to view the data coming in from the Arudino through my USB port. I used X-CTU to read the data. The Arduino code mentioned in the Gathering Materials section is mostly a combination of the Mindwave Mobile example code and Shane Clements’ massaging. The code is set up to print all of the digital data available out of the Mindwave Mobile. The data runs through the software serial port and is read easily on the X-CTU screen.

You can see unitless values for Delta, Theta, Alpha, Low Beta, High Beta and Gamma waves. The Mindwave’s ASIC also presents a calculated value for both Attention and Meditation. A number between 20 and 100 for Attention is normal, and a value above 40 means you are concentrating.

I was able to get repeatable values with the Attention value by counting backwards from 100 to1. We had a Bring A Hack dinner in Boulder, CO, and a few other people were able to make the Attention value rise by counting backwards from 100 to 1 also.

What is interesting is that the 5 types of brainwaves measured and reported originate from different parts of the brain. They also have extremely low amplitudes and frequencies.

Brain-anatomy

  • Gamma waves are oscillating waves with frequencies around 40 Hz, although they can be as high as 100 Hz and as low as 24 Hz. These originate from the thalamus (buried deep in the center of the brain) and are responsible for states of high attention and concentration.
  • Beta waves are between 12 and 30 Hz and are the states associated with normal waking consciousness. These are emitted from the motor cortex, a region of the cerebral cortex, which is the outermost layer of tissue on the brain. Beta waves are split into three sections: Low Beta Waves (12.5-16 Hz, “Beta 1 power”); Beta Waves (16.5–20 Hz, “Beta 2 power”); and High Beta Waves (20.5-28 Hz, “Beta 3 power”).
  • Alpha waves originate at the Occipital lobe and have a frequency of 8-12Hz. These are most present when you are awake but are very drowsy or relaxed.
  • Theta waves are oscillating waves that are located in the Hippocampus and are associated with dreaming. They are in the 4-7Hz range.
  • Delta waves are associated with very deep, dreamless sleep cycles and are high amplitude waves, which have a 0 to 3Hz frequency. These waves emit from both the thalamus and the cortex.

The difference between these waves can be more easily understood when seen side-by-side.

alt text

If you used an Arduino with the code from the Gathering Materials section uploaded, you should be able to see these values printed out in X-CTU or the Serial terminal program of your choice.

alt text

The Processing code found in the same section as the Arduino code can be used and modified to graph different values from the Arduino.

alt text

The attention value being graphed on Processing.

Resources and Going Further

The best results using the MindWave Mobile came when I looked at the processed Attention value. It was easy to see that when I (or anyone else) counted backwards from 100 to 1, the Attention values went up.

The deep brainwave values that I really wanted to see, such as Gamma, Beta, etc., were all over the place, and it was difficult to see any consistency in those values at all. In fact, the brainwave values varied the same when the unit was on the head as when off the head!

The Android app that comes with the Mindwave Mobile didn’t work at all, I tried it on a few phones without success. Neurosky support thought that it was possible that my Android operating system was not compatible.

Overall, I don’t think using the Neurosky Mindwave product yields any data that is very useable. I look forward to trying Neurosky’s next revision, and I am really looking forward to trying OpenBCI!

For more teardowns, check out these other offerings from SparkFun:

To learn more about wireless technologies, visit some of these:


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

LSM9DS0 Hookup Guide

0
0

LSM9DS0 Hookup Guide a learn.sparkfun.com tutorial

Introduction

The LSM9DS0 is a versatile, motion-sensing system-in-a-chip. It houses a 3-axis accelerometer, 3-axis gyroscope, and 3-axis magnetometer – nine degrees of freedom (9DOF) in a single IC! Each sensor in the LSM9DS0 supports a wide range of…ranges: the accelerometer’s scale can be set to ± 2, 4, 6, 8, or 16 g, the gyroscope supports ± 245, 500, and 2000 °/s, and the magnetometer has full-scale ranges of ± 2, 4, 8, or 12 gauss. The IMU-in-a-chip is so cool we put it on a breakout board.

ISO shot of LSM9DS0 Breakout

The LSM9DS0 is equipped with a digital interface, but even that is flexible: it supports both I2C and SPI, so you’ll be hard-pressed to find a microcontroller it doesn’t work with.

Covered In This Tutorial

This tutorial is devoted to all things LSM9DS0. We’ll introduce you to the chip itself, then the breakout board. Then we’ll switch over to example code, and show you how to interface with the board using an Arduino and our SFE_LSM9DS0 Arduino library.

The tutorial is split into the following pages:

  • About the LSM9DS0– An overview of the LSM9DS0, examining its features and capabilities.
  • Breakout Overview– This page covers the LSM9DS0 Breakout Board – topics like the pinout, jumpers, and schematic.
  • Hardware Assembly– Assembly tips and tricks, plus some information about the breakout’s dimensions.
  • Basic Arduino Example– How to install the Arduino library, and use a simple example sketch.
  • Advanced Arduino Example– A more advanced Arduino sketch – using the library – showing off features like switch the sensors' scales and data rates.
  • Using the Arduino Library– An overview of the SFE_LSM9DS0 Arduino library.

Required Materials

This tutorial explains how to use the LSM9DS0 Breakout Board with an Arduino. To follow along, you’ll need the following materials:

alt text

A logic level shifter is required for any 5V-operating Arduino (UNO, RedBoard, Leonardo, etc). If you use a 3.3V-based ‘duino – like the Arduino Pro 3.3V or 3.3V Pro Mini– there is no need for level shifting.

Suggested Reading

If you’re not familiar with some of the concepts below, we recommend checking out that tutorial before continuing on.

About the LSM9DS0

The LSM9DS0 is one of only a handful of IC’s that can measure three key properties of movement – angular velocity, acceleration, and heading – in a single IC.

The gyroscope can measure angular velocity– that is “how fast, and along which axis, am I rotating?” Angular velocities are measured in degrees per second– usually abbreviated to DPS or °/s. The LSM9DS0 can measure up to ± 2000 DPS, though that scale can also be set to either 245 or 500 DPS to get a finer resolution.

An accelerometer measures acceleration, which indicates how fast velocity is changing – “how fast am I speeding up or slowing down?” Acceleration is usually either measured in m/s2 (meters per second per second) or g’s (gravities [about 9.8 m/s2]). If an object is sitting motionless it feels about 1 g of acceleration towards the ground (assuming that ground is on earth, and the object is near sea-level). The LSM9DS0 measures its acceleration in g’s, and its scale can be set to either ± 2, 4, 6, 8, or 16_g_.

Finally, there’s the magnetometer, which measures the power and direction of magnetic fields. Though they’re not easily visible, magnetic fields exist all around us – whether you’re holding a tiny ferromagnet or feeling an attraction to Earth’s magnetic field. The LSM9DS0 measures magnetic fields in units of gauss (Gs), and can set its measurement scale to either ± 2, 4, 8, or 12 Gs.

By measuring these three properties, you can gain a great deal of knowledge about an object’s movement. 9DOF’s have tons and tons of applications. Measuring the force and direction of Earth’s magnetic field with a magnetometer, you can approximate your heading. An accelerometer in your phone can measure the direction of the force of gravity, and estimate orientation (portrait, landscape, flat, etc.). Quadcopters with built-in gyroscopes can look out for sudden rolls or pitches, and correct their momentum before things get out of hand.

9 degrees of freedom

The LSM9DS0 measures each of these movement properties in three dimensions. That means it produces nine pieces of data: acceleration in x/y/z, angular rotation in x/y/z, and magnetic force in x/y/z. On the breakout board, the z-axis runs normal to the PCB, the y-axis runs parallel to the short edge, and the x-axis is parallel to the long edge. Each axis has a positive and negative direction as well, noted by the direction of the arrow on the label.

The LSM9DS0 is, in a sense, two IC’s smashed into one package – like if you combined an L3G4200D gyro with an LSM303DLMTR accel/mag. One half of the device takes care of all-things gyroscope, and the other half manages both the accelerometer and magnetometer. In fact, a few of the control pins are dedicated to a single sensor – there are two chip select pins (CSG for the gyro and CSXM for the accel/mag) and two serial data out pins (SDOG and SDOXM).

Choose Your Own Adventure: SPI or I2C

In addition to being able to measure a wide variety of movement vectors, the LSM9DS0 is also multi-featured on the hardware end. It supports both SPI and I2C, so you should have no difficulty finding a microcontroller that can talk to it.

SPI is generally the easier of the two to implement, but it also requires more wires – four versus I2C’s two.

Because the LSM9DS0 supports both methods of communication, some pins have to pull double-duty. The Serial Data Out pin for example, does just that for SPI mode, but if you’re using the device over I2C it becomes an address selector. Chip select activates SPI mode when it’s low, but if it’s pulled high the device assumes I2C communication. In the section below we discuss each of the LSM9DS0’s pins, pay close attention to those pins that support both interfaces.


For much more detailed information about the IC, we encourage you to check out the datasheet!

Breakout Overview

Now that you know everything you need to about the LSM9DS0 IC, let’s talk a bit about the breakout board it’s resting on. On this page we’ll discuss the pins that are broken out, and some of the other features on the board.

The Pinout

In total, the LSM9DS0 Breakout breaks out 13 pins.

alt text

Here’s an overview of each of the pin functions:

Pin LabelPin FunctionNotes
CSGChip Select GyroThis pin selects between I2C and SPI on the gyro. Keep it HIGH for I2C, or use it as an (active-low) chip select for SPI.
HIGH (1): SPI idle mode / I2C enabled
LOW (0): SPI enabled / I2C disabled.
CSXMChip Select Accel/Mag (XM)This pin selects between I2C and SPI on the XM. Keep it HIGH for I2C, or use it as an (active-low) chip select for SPI.
HIGH (1): SPI idle mode / I2C enabled
LOW (0): SPI enabled / I2C disabled.
SDOGSPI: Gyroscope MISO
I2C: Gyro address select
In SPI mode, this is the gyroscope data output (SDO_G).
In I2C mode, this selects the LSb of the I2C address (SA0_G)
SDOXMSPI: Accel/Mag MISO
I2C: XM address select
In SPI mode, this is the XM data output (SDO_XM).
In I2C mode, this selects the LSb of the I2C address (SA0_XM)
SCLSerial ClockI2C and SPI serial clock.
SDASPI: MOSI
I2C:Serial Data
SPI: Device data in (MOSI)
I2C: Serial data (bi-directional)
VDDPower SupplySupply voltage to the chip. Should be regulated between 2.4V and 3.6V.
GNDGround0V voltage supply
DENGyroscope Data EnableMostly unknown. The LSM9DS0 datasheet doesn't have much to say about this pin.
INTGGyro Programmable InterruptAn interrupt that can be programmed as active high/low, push-pull, or open drain. It can trigger on over/under rotation speeds.
DRDYGGyroscope data readyAn interrupt that can indicate new gyro data is ready or buffer overrun.
INT1XMAccel/Mag Interrupt 1A programmable interrupt that can trigger on data ready, over-acceleration or "taps".
INT2XMAccel/Mag Interrupt 2A programmable interrupt that can trigger on data ready, over-acceleration or "taps".

These pins can all be classified into one of three categories: communication, interrupts, or power.

Power Supply

The VDD and GND pins are where you’ll supply a voltage and 0V reference to the IC. The breakout board does not regulate this voltage, so make sure it falls within the allowed supply voltage range of the LSM9DS0: 2.4V to 3.6V. Below is the electrical characteristics table from the datasheet.

alt text

The communication pins are not 5V tolerant, so they’ll need to be regulated to within a few mV of VDD.

Another very cool thing about this sensor is how low-power it is. In normal operation – with every sensor turned on – it’ll pull around 6.5mA.

Communication

CSG, CSXM, SDOG, SDOXM, SCL, and SDA are all used for the I2C and SPI interfaces. The function of these pins depends upon which of the two interfaces you’re using.

If you’re using using I2C here’s how you might configure these pins:

  • Pull CSG and CSXM HIGH. This will set both the gyro and accel/mag to I2C mode.
  • Set SDOG and SDOXM either HIGH or LOW. These pins set the I2C address of the gyro and accel/mag sensors.
  • Connect SCL to your microcontroller’s SCL pin.
  • Connect SDA to your microcontroller’s SDA pin.
  • The board has a built-in 10kΩ pull-up resistor on both SDA and SCL lines. If that value is too high, you can add a second 10kΩ resistor in parallel to divide the pull-up resistance to about 5kΩ.

Or, if you’re using SPI:

  • Connect CSG and CSXM to two individually controllable pins on your microcontroller. These chip-selects are active-low – when the pin goes LOW, SPI communication with either the gyro (CSG) or accel/mag (CSXM) is enabled.
  • SDOG and SDOXM are the serial data out pins. In many cases you’ll want to connect them together, and wire them to your microcontroller’s MISO (master-in, slave-out) pin.
  • Connect SCL to your microcontroller’s SCLK (serial clock) pin.
  • Connect SDA to your microcontroller’s MOSI (master-out, slave-in) pin.

Interrupts

There are a variety of interrupts on the LSM9DS0. While connecting up to these is not as critical as the communication or power supply pins, using them will help you get the most out of the chip.

The accelerometer- and magnetometer-specific interrupts are INT1XM and INT2XM. These can both be programmed to interrupt as either active-high or active-low, triggering on events like data ready, tap-detection, or when an acceleration or magnetic field passes a set threshold.

DRDY and INTG are devoted gyroscope interrupts. DRDY can be programmed to go high or low when new gyroscope readings are ready to read. INTG is a little more customizable, it can be used to trigger whenever angular rotation exceeds a threshold on any axis.

The Jumpers

Flipping the LSM9DS0 breakout over reveals three two-way, surface mount jumpers. Each of these jumpers comes closed. Their purpose is to automatically put the LSM9DS0 into I2C mode.

Jumpers on breakout

The three two-way jumpers on the back of the board. Follow the labels to see which pin they pull up.

Each of these jumpers pulls a pair of pins up to VDD, through a 10kΩ resistor. The middle pad of the jumper connects to the resistor, and the edge pads connect to a pin (follow the labels to find out which one). You can see how those jumpers match up on the schematic:

Jumpers on schematic

The far-right jumper connects CSG and CSXM to a pull-up – this’ll set the LSM9DS0 to I2C mode. The middle jumper pulls up SDOG and SDOXM, which sets the I2C address of the chip. Finally, the far-left jumper adds pull-up resistors to the I2C communication pins – SDA and SCL.

The intention of these jumpers is to make it as easy-as-possible to use the board; using as few wires as possible. If you’re using the breakout with I2C, you can ignore the four SDO and CS pins.

To disable any of these jumpers, whip out your handy hobby knife, and carefully cut the small traces between middle pad and edge pads. Even if you’re using SPI, though, the jumpers shouldn’t hinder your ability to communicate with the chip.


For more information about the breakout board, we encourage you to check out the schematic. Or, if you really want to delve into the anatomy of the PCB, you can download the EAGLE files.

Hardware Assembly

On this page we’ll discuss assembly hints. There’s really not much to assembling the breakout board – the real key is solderingsomething into the breakout holes.

Solder Something

To get a solid electrical and physical connection to the LSM9DS0 Breakout, you’ll need to solder either connectors or wires to the break-out pins. What, exactly, you solder into the board depends on how you’re going to use it.

If you’re going to use the breakout board in a breadboard or similar 0.1"-spaced perfboard, we recommend soldering straight male headers into the pins (there are also long headers if you need ‘em).

Headers soldered into board

If you’re going to mount the breakout into a tight place, you may want to opt for soldering wires (stranded or solid-core) into the pins.

Mounting the Breakout

Because the LSM9DS0 senses motion, it’s important (for most applications, at least) to keep in pinned in place. So the boards have a pair of mounting holes on the corners opposite the pins. The drill holes are 0.13" in diameter, so they should accommodate any 4/40 screw.

If you have any further dimension-related questions, hopefully the dimensional drawing below can answer them:

alt text

Consult the EAGLE PCB design files to find out more about the Breakout’s dimensions.

Basic Arduino Example

This example will show you how to download and install the SFE_LSM9DS0 library, and use it in it’s most basic form. We’ll use I2C and ignore the interrupts, which means we’ll be using as few wires and Arduino pins as possible.

Download and Install the Library

We’ve written a full-featured Arduino library to help make interfacing with the LSM9DS0’s gyro and accelerometer/magnetometer as easy-as-possible. Visit the GitHub repository to download the most recent version of the library, or click the link below:

Download the SFE_LSM9DS0 Arduino Library

For help installing the library, check out our How To Install An Arduino Library tutorial. You’ll need to move the SFE_LSM9DS0 folder into a libraries folder within your Arduino sketchbook.

Simple Hardware Hookup (I2C)

The library will work with either I2C or SPI. Since we’re trying to be as frugal with our Arduino pins as possible, I2C it is! Here’s a fritzing diagram for this example:

Redboard connected to LSM9DS0 via LLC

Connecting the LSM9DS0 to a RedBoard via a Bi-Directional Logic Level Converter.

This hookup relies on all of the jumpers on the back of the board being set (as they should be, unless they’ve been sliced). If the jumpers have been disconnected, connect all four CS and SDO pins to 3.3V.

Since we’re using I2C all we have to do is connect SDA to SDA and SCL to SCL. Unfortunately, since the LSM9DS0’s maximum operating voltage is 3.6V, we need to use a level shifting board to switch between 3.3V and 5V.

Alternatively, if you have a 3.3V-operating Arduino – like the 3.3V/8MHz Pro– you can connect SDA and SCL directly from microcontroller to sensor.

LSM9DS0 connected directly to Arduino Pro 3.3V

Heck, you can even mount the breakout board on top of the Arduino Pro. If you do this, you’ll need to set A3 HIGH and A2 LOW. The sensor pulls little enough current that the Arduino’s I/O pins can power it!

alt text

The wireless hookup: mounting an LSM9DS0 on top of an Arduino Pro. Pull A2 LOW and A3 HIGH to power the breakout.

Open the LSM9DS0_Simple Example

Once you’ve installed the library, open Arduino (or restart it if it was already open). You’ll find this first example under the File>Examples>SFE_LSM9DS0>LSM9DS0_Simple:

language:c
/*****************************************************************
LSM9DS0_Simple.ino
SFE_LSM9DS0 Library Simple Example Code
Jim Lindblom @ SparkFun Electronics
Original Creation Date: February 18, 2014
https://github.com/sparkfun/LSM9DS0_Breakout

The LSM9DS0 is a versatile 9DOF sensor. It has a built-in
accelerometer, gyroscope, and magnetometer. Very cool! Plus it
functions over either SPI or I2C.

This Arduino sketch is a demo of the simple side of the
SFE_LSM9DS0 library. It'll demo the following:
* How to create a LSM9DS0 object, using a constructor (global
  variables section).
* How to use the begin() function of the LSM9DS0 class.
* How to read the gyroscope, accelerometer, and magnetometer
  using the readGryo(), readAccel(), readMag() functions and the
  gx, gy, gz, ax, ay, az, mx, my, and mz variables.
* How to calculate actual acceleration, rotation speed, magnetic
  field strength using the calcAccel(), calcGyro() and calcMag()
  functions.
* How to use the data from the LSM9DS0 to calculate orientation
  and heading.

Hardware setup: This library supports communicating with the
LSM9DS0 over either I2C or SPI. If you're using I2C, these are
the only connections that need to be made:
    LSM9DS0 --------- Arduino
     SCL ---------- SCL (A5 on older 'Duinos')
     SDA ---------- SDA (A4 on older 'Duinos')
     VDD ------------- 3.3V
     GND ------------- GND
(CSG, CSXM, SDOG, and SDOXM should all be pulled high jumpers on
  the breakout board will do this for you.)

If you're using SPI, here is an example hardware setup:
    LSM9DS0 --------- Arduino
          CSG -------------- 9
          CSXM ------------- 10
          SDOG ------------- 12
          SDOXM ------------ 12 (tied to SDOG)
          SCL -------------- 13
          SDA -------------- 11
          VDD -------------- 3.3V
          GND -------------- GND

The LSM9DS0 has a maximum voltage of 3.6V. Make sure you power it
off the 3.3V rail! And either use level shifters between SCL
and SDA or just use a 3.3V Arduino Pro.

Development environment specifics:
    IDE: Arduino 1.0.5
    Hardware Platform: Arduino Pro 3.3V/8MHz
    LSM9DS0 Breakout Version: 1.0

This code is beerware. If you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!

Distributed as-is; no warranty is given.
*****************************************************************/

// The SFE_LSM9DS0 requires both the SPI and Wire libraries.
// Unfortunately, you'll need to include both in the Arduino
// sketch, before including the SFE_LSM9DS0 library.
#include <SPI.h> // Included for SFE_LSM9DS0 library
#include <Wire.h>
#include <SFE_LSM9DS0.h>

///////////////////////
// Example I2C Setup //
///////////////////////
// Comment out this section if you're using SPI
// SDO_XM and SDO_G are both grounded, so our addresses are:
#define LSM9DS0_XM  0x1D // Would be 0x1E if SDO_XM is LOW
#define LSM9DS0_G   0x6B // Would be 0x6A if SDO_G is LOW
// Create an instance of the LSM9DS0 library called `dof` the
// parameters for this constructor are:
// [SPI or I2C Mode declaration],[gyro I2C address],[xm I2C add.]
LSM9DS0 dof(MODE_I2C, LSM9DS0_G, LSM9DS0_XM);

///////////////////////
// Example SPI Setup //
///////////////////////
/* // Uncomment this section if you're using SPI
#define LSM9DS0_CSG  9  // CSG connected to Arduino pin 9
#define LSM9DS0_CSXM 10 // CSXM connected to Arduino pin 10
LSM9DS0 dof(MODE_SPI, LSM9DS0_CSG, LSM9DS0_CSXM);
*/

// Do you want to print calculated values or raw ADC ticks read
// from the sensor? Comment out ONE of the two #defines below
// to pick:
#define PRINT_CALCULATED
//#define PRINT_RAW

#define PRINT_SPEED 500 // 500 ms between prints

void setup()
{
  Serial.begin(115200); // Start serial at 115200 bps
  // Use the begin() function to initialize the LSM9DS0 library.
  // You can either call it with no parameters (the easy way):
  uint16_t status = dof.begin();
  // Or call it with declarations for sensor scales and data rates:
  //uint16_t status = dof.begin(dof.G_SCALE_2000DPS,
  //                            dof.A_SCALE_6G, dof.M_SCALE_2GS);

  // begin() returns a 16-bit value which includes both the gyro
  // and accelerometers WHO_AM_I response. You can check this to
  // make sure communication was successful.
  Serial.print("LSM9DS0 WHO_AM_I's returned: 0x");
  Serial.println(status, HEX);
  Serial.println("Should be 0x49D4");
  Serial.println();
}

void loop()
{
  printGyro();  // Print "G: gx, gy, gz"
  printAccel(); // Print "A: ax, ay, az"
  printMag();   // Print "M: mx, my, mz"

  // Print the heading and orientation for fun!
  printHeading((float) dof.mx, (float) dof.my);
  printOrientation(dof.calcAccel(dof.ax), dof.calcAccel(dof.ay),
                   dof.calcAccel(dof.az));
  Serial.println();

  delay(PRINT_SPEED);
}

void printGyro()
{
  // To read from the gyroscope, you must first call the
  // readGyro() function. When this exits, it'll update the
  // gx, gy, and gz variables with the most current data.
  dof.readGyro();

  // Now we can use the gx, gy, and gz variables as we please.
  // Either print them as raw ADC values, or calculated in DPS.
  Serial.print("G: ");
#ifdef PRINT_CALCULATED
  // If you want to print calculated values, you can use the
  // calcGyro helper function to convert a raw ADC value to
  // DPS. Give the function the value that you want to convert.
  Serial.print(dof.calcGyro(dof.gx), 2);
  Serial.print(", ");
  Serial.print(dof.calcGyro(dof.gy), 2);
  Serial.print(", ");
  Serial.println(dof.calcGyro(dof.gz), 2);
#elif defined PRINT_RAW
  Serial.print(dof.gx);
  Serial.print(", ");
  Serial.print(dof.gy);
  Serial.print(", ");
  Serial.println(dof.gz);
#endif
}

void printAccel()
{
  // To read from the accelerometer, you must first call the
  // readAccel() function. When this exits, it'll update the
  // ax, ay, and az variables with the most current data.
  dof.readAccel();

  // Now we can use the ax, ay, and az variables as we please.
  // Either print them as raw ADC values, or calculated in g's.
  Serial.print("A: ");
#ifdef PRINT_CALCULATED
  // If you want to print calculated values, you can use the
  // calcAccel helper function to convert a raw ADC value to
  // g's. Give the function the value that you want to convert.
  Serial.print(dof.calcAccel(dof.ax), 2);
  Serial.print(", ");
  Serial.print(dof.calcAccel(dof.ay), 2);
  Serial.print(", ");
  Serial.println(dof.calcAccel(dof.az), 2);
#elif defined PRINT_RAW
  Serial.print(dof.ax);
  Serial.print(", ");
  Serial.print(dof.ay);
  Serial.print(", ");
  Serial.println(dof.az);
#endif

}

void printMag()
{
  // To read from the magnetometer, you must first call the
  // readMag() function. When this exits, it'll update the
  // mx, my, and mz variables with the most current data.
  dof.readMag();

  // Now we can use the mx, my, and mz variables as we please.
  // Either print them as raw ADC values, or calculated in Gauss.
  Serial.print("M: ");
#ifdef PRINT_CALCULATED
  // If you want to print calculated values, you can use the
  // calcMag helper function to convert a raw ADC value to
  // Gauss. Give the function the value that you want to convert.
  Serial.print(dof.calcMag(dof.mx), 2);
  Serial.print(", ");
  Serial.print(dof.calcMag(dof.my), 2);
  Serial.print(", ");
  Serial.println(dof.calcMag(dof.mz), 2);
#elif defined PRINT_RAW
  Serial.print(dof.mx);
  Serial.print(", ");
  Serial.print(dof.my);
  Serial.print(", ");
  Serial.println(dof.mz);
#endif
}

// Here's a fun function to calculate your heading, using Earth's
// magnetic field.
// It only works if the sensor is flat (z-axis normal to Earth).
// Additionally, you may need to add or subtract a declination
// angle to get the heading normalized to your location.
// See: http://www.ngdc.noaa.gov/geomag/declination.shtml
void printHeading(float hx, float hy)
{
  float heading;

  if (hy > 0)
  {
    heading = 90 - (atan(hx / hy) * (180 / PI));
  }
  else if (hy < 0)
  {
    heading = - (atan(hx / hy) * (180 / PI));
  }
  else // hy = 0
  {
    if (hx < 0) heading = 180;
    else heading = 0;
  }

  Serial.print("Heading: ");
  Serial.println(heading, 2);
}

// Another fun function that does calculations based on the
// acclerometer data. This function will print your LSM9DS0's
// orientation -- it's roll and pitch angles.
void printOrientation(float x, float y, float z)
{
  float pitch, roll;

  pitch = atan2(x, sqrt(y * y) + (z * z));
  roll = atan2(y, sqrt(x * x) + (z * z));
  pitch *= 180.0 / PI;
  roll *= 180.0 / PI;

  Serial.print("Pitch, Roll: ");
  Serial.print(pitch, 2);
  Serial.print(", ");
  Serial.println(roll, 2);
}

After uploading the code, open up your serial monitor and set the baud rate to 115200 bps. You should see something like this begin to stream by:

alt text

Each serial output blurb spits out the readings from all nine dimensions of movement. First the gyroscope readings (“G: x, y, z”) in degrees per second (DPS). Then come three degrees of acceleration in g’s (“A: x, y, z”), followed by the magnetic field readings (“M: x, y, z”) in gauss (Gs).

Try moving your breadboard around (carefully, don’t disconnect any wires!). Are the numbers changing? Check out the acceleration values – the axis normal to gravity should feel about 1 g of acceleration on it.

Does the heading output what you’d expect? If north seems a few degrees off, you may need to adjust for your declination. That means adding or subtracting a constant number that correlates to your location on this map.


That’s all there is to it! If you want to get more out of the LSM9DS0 by using the interrupt outputs, check out the next page! Or check out the Using the Arduino Library Page for help using the library.

Advanced Arduino Example

The basic example is perfect if all you want to do is poll the LSM9DS0 a few times per second to get movement data, but what if you want to make use of the IMU’s interrupt outputs? Using interrupts you can get read data in from the LSM9DS0 as soon as it’s available. This example will show you how to get more out of your LSM9DS0 Breakout.

Circuit Diagram

In addition to the SDA and SCL pins, this example will make use of the DRDYG, INT1XM, and INT2XM pins. Here’s the hookup diagram:

alt text

Again, you’ll need to use a logic level converter between SDAs and SCLs. There is no need for level shifting on the three interrupt lines – the 3.3V output from the LSM9DS0 will be enough to trigger a logic high on the Arduino (see Logic Levels).

Example Code: LSM9DS0_SerialMenus

Open up the LSM9DS0_SerialMenus example by going to File>Examples>SFE_LSM9DS0>LSM9DS0_SerialMenus. Here’s the code:

language:c
/*****************************************************************
LSM9DS0_SerialMenus.ino
SFE_LSM9DS0 Library Example Code: Interact With Serial Menus
Jim Lindblom @ SparkFun Electronics
Original Creation Date: February 14, 2014 (Happy Valentines Day!)
https://github.com/sparkfun/LSM9DS0_Breakout

This Arduino sketch is a demo of all things SEF_LSM9DS0 library.
Once you attach all hardware, and upload the sketch, open your
Serial monitor at 115200 BPS. Follow the menu prompts to either:
    1) Stream readings from the accelerometer.
    2) Stream readings from the gyroscope.
    3) Stream readings from the magnetometer.
    4) Set the scales of each sensor (e.g. +/-4g, 500DPS, 8Gs)
    5) Switch to/from calculated or raw data (e.g. ADC ticks or
        g's, DPS, and Gs)
    6) Set the output data rate of each sensor.

Hardware setup: This library supports communicating with the
LSM9DS0 over either I2C or SPI. In addition to those wires, this
sketch demos how to use the interrupts. Here's what the I2C setup
looks like:
    LSM9DS0 --------- Arduino
     CSG ------------- NONE (Pulled HIGH [indicates I2C mode])
     CSXM ------------ NONE (Pulled HIGH [indicates I2C mode])
     SDOG ------------ NONE (Pulled HIGH [sets I2C address])
     SDOXM ----------- NONE (Pulled HIGH [sets I2C address])
     SCL ---------- SCL (A5 on older 'Duinos')
     SDA ---------- SDA (A4 on older 'Duinos')
     VDD ------------- 3.3V
     GND ------------- GND
     DEN ------------- NONE (Not used in this example)
     INTG ------------ NONE (Not used in this example)
     DRDYG ------------ 4 (Could be any digital pin)
     INT1XM ----------- 3 (Could be any digital pin)
     INT2XM ----------- 2 (Could be any digital pin)

The LSM9DS0 has a maximum voltage of 3.6V. Make sure you power it
off the 3.3V rail! And either use level shifters between SCL
and SDA or just use a 3.3V Arduino Pro.

Development environment specifics:
    IDE: Arduino 1.0.5
    Hardware Platform: Arduino Pro 3.3V/8MHz
    LSM9DS0 Breakout Version: 1.0

This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!

Distributed as-is; no warranty is given.
*****************************************************************/

// The SFE_LSM9DS0 requires both the SPI and Wire libraries.
// Unfortunately, you'll need to include both in the Arduino
// sketch, before including the SFE_LSM9DS0 library.
#include <SPI.h> // Included for SFE_LSM9DS0 library
#include <Wire.h>
#include <SFE_LSM9DS0.h>

///////////////////////
// Example I2C Setup //
///////////////////////
// SDO_XM and SDO_G are both grounded, therefore our addresses are:
#define LSM9DS0_XM  0x1D // Would be 0x1E if SDO_XM is LOW
#define LSM9DS0_G   0x6B // Would be 0x6A if SDO_G is LOW
// Create an instance of the LSM9DS0 library called `dof` the
// parameters for this constructor are:
// [SPI or I2C Mode declaration], [gyro I2C address], [xm I2C address]
LSM9DS0 dof(MODE_I2C, LSM9DS0_G, LSM9DS0_XM);

///////////////////////
// Example SPI Setup //
///////////////////////
//#define LSM9DS0_CSG  9  // CSG connected to Arduino pin 9
//#define LSM9DS0_CSXM 10 // CSXM connected to Arduino pin 10
//LSM9DS0 dof(MODE_SPI, LSM9DS0_CSG, LSM9DS0_CSXM);

///////////////////////////////
// Interrupt Pin Definitions //
///////////////////////////////
const byte INT1XM = 2; // INT1XM tells us when accel data is ready
const byte INT2XM = 3; // INT2XM tells us when mag data is ready
const byte DRDYG = 4;  // DRDYG tells us when gyro data is ready

// A boolean to keep track of whether we're printing raw (ADC)
// or calculated (g's, DPS, Gs) sensor data:
boolean printRaw = true;

void setup()
{
  // Set up interrupt pins as inputs:
  pinMode(INT1XM, INPUT);
  pinMode(INT2XM, INPUT);
  pinMode(DRDYG, INPUT);

  Serial.begin(115200); // Start serial at 115200 bps
  // Use the begin() function to initialize the LSM9DS0 library.
  // You can either call it with no parameters (the easy way):
  uint16_t status = dof.begin();
  // Or call it with declarations for sensor scales and data rates:
  //uint16_t status = dof.begin(dof.G_SCALE_2000DPS, dof.A_SCALE_6G, dof.M_SCALE_2GS);

  // begin() returns a 16-bit value which includes both the gyro and
  // accelerometers WHO_AM_I response. You can check this to make sure
  // communication was successful.
  Serial.println(status, HEX);
}

void loop()
{
  // Print the control menu:
  printMenu();
  // Then wait for any serial data to come in:
  while (!Serial.available())
    ;
  // Once serial data is received, call parseMenu to act on it:
  parseMenu(Serial.read());

}

void printAccel()
{
  // Only read from the accelerometer if the accel interrupts,
  // which means that new data is ready.
  if (digitalRead(INT1XM))
  {
    // Use the readAccel() function to get new data from the accel.
    // After calling this function, new values will be stored in
    // the ax, ay, and az variables.
    dof.readAccel();

    Serial.print("A: ");
    if (printRaw)
    {
      Serial.print(dof.ax);
      Serial.print(", ");
      Serial.print(dof.ay);
      Serial.print(", ");
      Serial.println(dof.az);
    }
    else
    {
      Serial.print(dof.calcAccel(dof.ax));
      Serial.print(", ");
      Serial.print(dof.calcAccel(dof.ay));
      Serial.print(", ");
      Serial.println(dof.calcAccel(dof.az));
    }
  }
}

void printGyro()
{
  // Only read from the gyro if the DRDY interrupts,
  // which means that new data is ready.
  if (digitalRead(DRDYG))
  {
    // Use the readGyro() function to get new data from the gyro.
    // After calling this function, new values will be stored in
    // the gx, gy, and gz variables.
    dof.readGyro();

    Serial.print("G: ");
    if (printRaw)
    {
      Serial.print(dof.gx);
      Serial.print(", ");
      Serial.print(dof.gy);
      Serial.print(", ");
      Serial.println(dof.gz);
    }
    else
    {
      Serial.print(dof.calcGyro(dof.gx));
      Serial.print(", ");
      Serial.print(dof.calcGyro(dof.gy));
      Serial.print(", ");
      Serial.println(dof.calcGyro(dof.gz));
    }
  }
}

void printMag()
{
  // Only read from the magnetometer if the INT2XM interrupts,
  // which means that new data is ready.
  if (digitalRead(INT2XM))
  {
    // Use the readMag() function to get new data from the mag.
    // After calling this function, new values will be stored in
    // the mx, my, and mz variables.
    dof.readMag();

    Serial.print("M: ");
    if (printRaw)
    {
      Serial.print(dof.mx);
      Serial.print(", ");
      Serial.print(dof.my);
      Serial.print(", ");
      Serial.print(dof.mz);
      Serial.print(", ");
      Serial.println(calcHeading(dof.mx, dof.my, dof.mz));
    }
    else
    {
      Serial.print(dof.calcMag(dof.mx), 4);
      Serial.print(", ");
      Serial.print(dof.calcMag(dof.my), 4);
      Serial.print(", ");
      Serial.print(dof.calcMag(dof.mz), 4);
      Serial.print(", ");
      Serial.println(calcHeading(dof.mx, dof.my, dof.mz));
    }
  }
}

// Here's a simple example function to calculate heading based on
// magnetometer readings. This only works when the 9DOF is flat
// (x-axis normal to gravity).
float calcHeading(float hx, float hy, float hz)
{
  if (hy > 0)
  {
    return 90 - atan(hx / hy) * 180 / PI;
  }
  else if (hy < 0)
  {
    return 270 - atan(hx / hy) * 180 / PI;
  }
  else // hy = 0
  {
    if (hx < 0) return 180;
    else return 0;
  }
}

// This function will print all data from all sensors at once.
// It'll wait until every sensor interrupt triggers before
// printing.
void streamAll()
{
  if ((digitalRead(INT2XM)) && (digitalRead(INT1XM)) &&
      (digitalRead(DRDYG)))
  {
    printAccel();
    printGyro();
    printMag();
  }
}

void setScale()
{
  char c;

  Serial.println(F("Set accelerometer scale:"));
  Serial.println(F("\t1) +/- 2G"));
  Serial.println(F("\t2) +/- 4G"));
  Serial.println(F("\t3) +/- 6G"));
  Serial.println(F("\t4) +/- 8G"));
  Serial.println(F("\t5) +/- 16G"));
  while (Serial.available() < 1)
    ;
  c = Serial.read();
  switch (c)
  {
    case '1':
      dof.setAccelScale(dof.A_SCALE_2G);
      break;
    case '2':
      dof.setAccelScale(dof.A_SCALE_4G);
      break;
    case '3':
      dof.setAccelScale(dof.A_SCALE_6G);
      break;
    case '4':
      dof.setAccelScale(dof.A_SCALE_8G);
      break;
    case '5':
      dof.setAccelScale(dof.A_SCALE_16G);
      break;
  }

  Serial.println(F("Set gyroscope scale:"));
  Serial.println(F("\t1) +/- 245 DPS"));
  Serial.println(F("\t2) +/- 500 DPS"));
  Serial.println(F("\t3) +/- 2000 DPS"));
  while (Serial.available() < 1)
    ;
  c = Serial.read();
  switch (c)
  {
    case '1':
      dof.setGyroScale(dof.G_SCALE_245DPS);
      break;
    case '2':
      dof.setGyroScale(dof.G_SCALE_500DPS);
      break;
    case '3':
      dof.setGyroScale(dof.G_SCALE_2000DPS);
      break;
  }

  Serial.println(F("Set magnetometer scale:"));
  Serial.println(F("\t1) +/- 2GS"));
  Serial.println(F("\t2) +/- 4GS"));
  Serial.println(F("\t3) +/- 8GS"));
  Serial.println(F("\t4) +/- 12GS"));
  while (Serial.available() < 1)
    ;
  c = Serial.read();
  switch (c)
  {
    case '1':
      dof.setMagScale(dof.M_SCALE_2GS);
      break;
    case '2':
      dof.setMagScale(dof.M_SCALE_4GS);
      break;
    case '3':
      dof.setMagScale(dof.M_SCALE_8GS);
      break;
    case '4':
      dof.setMagScale(dof.M_SCALE_12GS);
      break;
  }
}

void setRaw()
{
  if (printRaw)
  {
    printRaw = false;
    Serial.println(F("Printing calculated readings"));
  }
  else
  {
    printRaw = true;
    Serial.println(F("Printing raw readings"));
  }
}

void setODR()
{
  char c;

  Serial.println(F("Set Accelerometer ODR (Hz):"));
  Serial.println(F("\t1) 3.125 \t 6) 100"));
  Serial.println(F("\t2) 6.25  \t 7) 200"));
  Serial.println(F("\t3) 12.5  \t 8) 400"));
  Serial.println(F("\t4) 25    \t 9) 800"));
  Serial.println(F("\t5) 50    \t A) 1600"));
  while (Serial.available() < 1)
    ;
  c = Serial.read();
  switch (c)
  {
    case '1':
      dof.setAccelODR(dof.A_ODR_3125);
      break;
    case '2':
      dof.setAccelODR(dof.A_ODR_625);
      break;
    case '3':
      dof.setAccelODR(dof.A_ODR_125);
      break;
    case '4':
      dof.setAccelODR(dof.A_ODR_25);
      break;
    case '5':
      dof.setAccelODR(dof.A_ODR_50);
      break;
    case '6':
      dof.setAccelODR(dof.A_ODR_100);
      break;
    case '7':
      dof.setAccelODR(dof.A_ODR_200);
      break;
    case '8':
      dof.setAccelODR(dof.A_ODR_400);
      break;
    case '9':
      dof.setAccelODR(dof.A_ODR_800);
      break;
    case 'A':
    case 'a':
      dof.setAccelODR(dof.A_ODR_1600);
      break;
  }

  Serial.println(F("Set Gyro ODR/Cutoff (Hz):"));
  Serial.println(F("\t1) 95/12.5 \t 8) 380/25"));
  Serial.println(F("\t2) 95/25   \t 9) 380/50"));
  Serial.println(F("\t3) 190/125 \t A) 380/100"));
  Serial.println(F("\t4) 190/25  \t B) 760/30"));
  Serial.println(F("\t5) 190/50  \t C) 760/35"));
  Serial.println(F("\t6) 190/70  \t D) 760/50"));
  Serial.println(F("\t7) 380/20  \t E) 760/100"));
  while (Serial.available() < 1)
    ;
  c = Serial.read();
  switch (c)
  {
    case '1':
      dof.setGyroODR(dof.G_ODR_95_BW_125);
      break;
    case '2':
      dof.setGyroODR(dof.G_ODR_95_BW_25);
      break;
    case '3':
      dof.setGyroODR(dof.G_ODR_190_BW_125);
      break;
    case '4':
      dof.setGyroODR(dof.G_ODR_190_BW_25);
      break;
    case '5':
      dof.setGyroODR(dof.G_ODR_190_BW_50);
      break;
    case '6':
      dof.setGyroODR(dof.G_ODR_190_BW_70);
      break;
    case '7':
      dof.setGyroODR(dof.G_ODR_380_BW_20);
      break;
    case '8':
      dof.setGyroODR(dof.G_ODR_380_BW_25);
      break;
    case '9':
      dof.setGyroODR(dof.G_ODR_380_BW_50);
      break;
    case 'A':
    case 'a':
      dof.setGyroODR(dof.G_ODR_380_BW_100);
      break;
    case 'B':
    case 'b':
      dof.setGyroODR(dof.G_ODR_760_BW_30);
      break;
    case 'C':
    case 'c':
      dof.setGyroODR(dof.G_ODR_760_BW_35);
      break;
    case 'D':
    case 'd':
      dof.setGyroODR(dof.G_ODR_760_BW_50);
      break;
    case 'E':
    case 'e':
      dof.setGyroODR(dof.G_ODR_760_BW_100);
      break;
  }

  Serial.println(F("Set Magnetometer ODR (Hz):"));
  Serial.println(F("\t1) 3.125 \t 4) 25"));
  Serial.println(F("\t2) 6.25  \t 5) 50"));
  Serial.println(F("\t3) 12.5  \t 6) 100"));
  while (Serial.available() < 1)
    ;
  c = Serial.read();
  switch (c)
  {
    case '1':
      dof.setMagODR(dof.M_ODR_3125);
      break;
    case '2':
      dof.setMagODR(dof.M_ODR_625);
      break;
    case '3':
      dof.setMagODR(dof.M_ODR_125);
      break;
    case '4':
      dof.setMagODR(dof.M_ODR_25);
      break;
    case '5':
      dof.setMagODR(dof.M_ODR_50);
      break;
    case '6':
      dof.setMagODR(dof.M_ODR_100);
      break;
  }
}

void printMenu()
{
  Serial.println();
  Serial.println(F("////////////////////////////////////////////"));
  Serial.println(F("// LSM9DS0 Super Awesome Amazing Fun Time //"));
  Serial.println(F("////////////////////////////////////////////"));
  Serial.println();
  Serial.println(F("1) Stream Accelerometer"));
  Serial.println(F("2) Stream Gyroscope"));
  Serial.println(F("3) Stream Magnetometer"));
  Serial.println(F("4) Stream output from all sensors"));
  Serial.println(F("5) Set Sensor Scales"));
  Serial.println(F("6) Switch To/From Raw/Calculated Readings"));
  Serial.println(F("7) Set Output Data Rates"));
  Serial.println();
}

void parseMenu(char c)
{
  switch (c)
  {
    case '1':
      while(!Serial.available())
        printAccel();
      break;
    case '2':
      while(!Serial.available())
        printGyro();
      break;
    case '3':
      while(!Serial.available())
        printMag();
      break;
    case '4':
      while(!Serial.available())
      {
        streamAll();
      }
      break;
    case '5':
      setScale();
      break;
    case '6':
      setRaw();
      break;
    case '7':
      setODR();
      break;
  }
}

Upload the code, then open up your serial monitor with the baud rate set to 115200 bps. Then just follow the menu prompts to interact with the sensor. You can stream the accelerometer, gyroscope, and magnetometer individually or together.

Serial menu interaction

Send any key to stop the streaming and bring the menu back.

There are also menu items that allow you to set the range and data rates of the sensors. Make sure you give those a spin, and see how they affect the output of the sensor.

Using the Arduino Library

Those two basic and advanced tutorials show off everything that the SFE_LSM9DS0 library can do. If you’re stumped on how to use the library, though, here are some of its key concepts and functions:

Setup Stuff

To enable the library, you’ll need to include it, and you also need to include the SPI and Wire libraries:

language:c
#include <SPI.h> // Included for SFE_LSM9DS0 library
#include <Wire.h>
#include <SFE_LSM9DS0.h>

Make sure the SPI and Wire includes are above the SFE_LSM9DS0.

Constructor

The constructor creates an instance of the LSM9DS0 class. Once you’ve created the instance, that’s what you’ll use to control the breakout from there on. This single line of code is usually placed in the global area of your sketch.

The constructor tells the library three things: whether you’re using I2C or SPI, and the addresses of the gyroscope and accelerometer/magnetomter sensors. If you’re using I2C, those address are the 7-bit address defined in the datasheet

language:c
// SDO_XM and SDO_G are both grounded, so our addresses are:
#define LSM9DS0_XM  0x1D // Would be 0x1E if SDO_XM is LOW
#define LSM9DS0_G   0x6B // Would be 0x6A if SDO_G is LOW
// Create an instance of the LSM9DS0 library called `dof` the
// parameters for this constructor are:
// [SPI or I2C Mode declaration],[gyro I2C address],[xm I2C add.]
LSM9DS0 dof(MODE_I2C, LSM9DS0_G, LSM9DS0_XM);

Declaring an LSM9DS0 object using I2C for communication.

If you’re using SPI, the gyro and accel/mag addresses should be the Arduino pin connected to each chip-select pin (CSG and CSXM).

language:c
#define LSM9DS0_CSG  9  // CSG connected to Arduino pin 9
#define LSM9DS0_CSXM 10 // CSXM connected to Arduino pin 10
LSM9DS0 dof(MODE_SPI, LSM9DS0_CSG, LSM9DS0_CSXM);

Declaring an LSM9DS0 object using SPI for communication.

Your LSM9DS0 class object can be named like any other variable. In our examples we called it dof– short and sweet.

begin()

Once you’ve created an LSM9DS0 object, you can start using it! The first step is initializing the sensor, by using the begin() function. You can either call this function with no parameters, to get a good, default init:

language:c
// Initialize LSM9DS0, setting gyro scale to 245 DPS, accel to 2g, and mag to 2Gs.
// Also set data rates to 95 Hz (gyro), 50 Hz (accel), and 50 Hz (mag).
dof.begin();

Or, give it a whole set of parameters that set each sensors scale and data rate.

language:c
// Initialize LSM9DS0, setting gyro scale to 500 DPS, accel to +/-16g, and mag to 12Gs.
// Also set data rates to 760 Hz (gyro), 1600 Hz (accel), and 100 Hz (mag) (lots of data!)
dof.begin(G_SCALE_500DPS, A_SCALE_16G, M_SCALE_12GS, G_ODR_760_BW_100, A_ODR_1600, M_ODR_100);

There are a variety of options for the scale and data rate selections. Consult SFE_LSM9DS0.h to find out more.

Reading and Interpreting the Sensors

What good is the sensor if you can’t get any data from it!? Here are the functions you’ll need to get acceleration, rotation speed, and magnetic field strength dat from the library.

readAccel(), readGyro(), and readMag()

These three functions – readAccel(), readGyro(), and readMag()– poll the LSM9DS0 to get the most up-to-date readings from each of the three sensors.

The read functions don’t take any parameters, and they don’t return anything, so how do you get that data? After the function runs its course, it’ll update a set of three class variables, which will have the sensor data you so desire. readAccel() will update ax, ay, and az, readGyro() will update gx, gy, and gz, and readMag() will update mx, my, and mz. Here’s an example:

language:c
dof.readAccel(); // Update the accelerometer data
Serial.print(dof.ax); // Print x-axis data
Serial.print(", ");
Serial.print(dof.ay); // print y-axis data
Serial.print(", ");
Serial.println(dof.az); // print z-axis data

An example of reading and printing all three axes of accelerometer data.

Those values are all signed 16-bit integers, meaning they’ll range from -32,768 to 32,767. That value doesn’t mean much unless you know the scale of your sensor, which is where the next functions come into play.

calcAccel(), calcGyro(), and calcMag()

The library keeps track of each sensor’s scale, and it implements these helper functions to make translating between the raw ADC readings of the sensor to actual units easy.

calcAccel(), calcGyro(), and calcMag() all take a single parameter – a signed 16-bit integer – and convert to their respective units. They all return a float value, which you can do with as you please.

Here’s an example of printing calculated gyroscope values:

language:c
dof.readGyro(); // Update gyroscope data
Serial.print(dof.calcGyro(dof.gx)); // Print x-axis rotation in DPS
Serial.print(", ");
Serial.print(dof.calcGyro(dof.gy)); // Print y-axis rotation in DPS
Serial.print(", ");
Serial.println(dof.calcGyro(dof.gz)); // Print z-axis rotation in DPS

The library also implements functions to individually set a sensor’s scale or data rate. For more help using the library, check out comments in the example code, or delve into the library code itself.

Resources & Going Further

Hopefully that info dump was enough to get you rolling with the LSM9DS0. If you need any more information, here are some more resources:

Going Further

Now that you’ve got the LSM9DS0 up-and-running, what project are you going to incorporate motion-sensing into? Need a little inspiration? Check out some of these tutorials!

  • Getting Started With the RedBot– The RedBot is a great entry-level robotics platform. It’d be really neat to see what could be done with an LSM9DS0 connected to it.
  • Dungeons and Dragons Dice Gauntlet– This project uses an accelerometer to sense a “rolling the dice” motion. You could swap in the LSM9DS0 to add more functionality – like compass-based damage multipliers!
  • Leap Motion Teardown– An IMU sensor is cool, but image-based motion sensing is the future. Check out this teardown of the miniature-Kinect-like Leap Motion!

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


Sound Detector Hookup Guide

0
0

Sound Detector Hookup Guide a learn.sparkfun.com tutorial

Introducing The Sound Detector

The Sound Detector

The Sound Detector

The Sound Detector is a small board that combines a microphone and some processing circuitry. It provides not only an audio output, but also a binary indication of the presence of sound, and an analog representation of it’s amplitude.

Covered in This Tutorial

This tutorial will guide you through hooking up and using the Sound Detector. It will examine how the circuit works, explain some details about getting the best performance from the Sound Detector, then present two different projects that demonstrate how to use it.

Suggested Reading

Quick Start

To get started with the Sound Detector, simply connect it to a power supply.

(Sound Detector → Power Supply )

  • GND → Supply Ground.
  • VCC → Power supply voltage between 3.5 and 5.5 Volts. 5 Volts is ideal.

In a quiet room, power the board up, and then speak into the microphone. You should see the red LED on the board blink in response to your voice.

alt text

With it’s 3 outputs, the board itself is a lot more flexible. To explore that flexibility, read on.

Looking Closer

Three Outputs?

The Sound Detector has 3 separate outputs. It’s easiest to see what each is doing with a graph. The following illustrates how the sound detector responds to a series of sound pulses.

Output Waveforms

Sample Sound Detector Output

This shows the output voltages over time.

  • The dark green trace is the audio output of the sound detector. The audio voltage directly from the microphone is found at this output.
  • The light green trace is the envelope output. This analog voltage traces the amplitude of the sound. Of particular interest, notice that the third pulse gets noticeably louder as it goes.
  • Finally, the red line is the gate output. This output is low when conditions are quiet, and goes high when sound is detected.

How It Works

Having examined the outputs, lets also take a quick walk through the schematic, to gain an understanding of how each stage works.

First Stage

The first section of the circuit is an electret microphone capsule. This portion of the circuit borrows from the Electret Microphone breakout board.

Microphone and Preamp

Microphone and Preamplifier

The capsule is biased by the supply voltage through R1, and it outputs an AC voltage that is riding a DC offset of approximately ½ the supply voltage.

The output from the capsule is an extremely small voltage, so the signal from the capsule is amplified by IC1G1, an operational amplifier stage. By default, the preamplifier has an arithmetic gain of 100 (20 dB), and the gain can be adjusted by populating R17 (which we’ll examine in detail on the next page).

The audio output is DC coupled, riding riding one half the supply voltage, so it can be directly connected to the ADC of a microcontroller. In perfectly quiet conditions, it will ideall read ½ full scale, or 512 on a 10-bit converter.

Second Stage

The second stage of the circuit is an envelope follower.

Envelope Follower

Envelope Follower

IC1G3 forms an opamp-based precision rectifier. This stage implements the equation

if(Vin > 0)
    Vout = 0;
else
    Vout = Vin * -2.2

The opamp inverts and amplifies the signal. When it’s output swings high, D2 turns on, and charges C1. When the opamp output is high or not swinging, D2 is turned off, and C1 discharges through R9. Thus, C1 tracks the peaks of the input signal.

IC1G4 is a buffer amplifier, so external loads on the envelope pin won’t change the C1’s charge/discharge behavior.

This results in a signal that tracks the peak amplitude of the input signal. A louder sound will result in a higher voltage on the Envelope pin. As with the audio pin, the envelope can be connected to the ADC of a microcontroller.

Third Stage

The final stage implements a thresholded switch on the envelope signal.

Schmitt Trigger

Schmitt Trigger

The Schmitt trigger watches the envelope signal, and toggles the output when the threshold is exceeded. A Schmitt trigger is a comparator that adjusts it’s threshold voltage when the output switches, requiring a higher voltage to switch on than to switch off. This allows it to ignore some ripple in the input signal, like the ripple present in the output of the envelope follower stage.

The output of the Schmitt trigger is found on the Gate pin. You can connect it to a digital input. We’ll use it to trigger interrupts in the software example.

Outputs

Each of the three output signals is present on the .1" header at the edge of the board. They are active simultaneously. If you aren’t using one in your particular application, simply leave that pin disconnected.

Configuration

Care and Feeding Of The Capsule

The heart of the Sound Detector is the electret microphone capsule - without it, we couldn’t convert acoustic energy into electrical energy. These capsules have a couple of quirks that we need to understand in order to apply them successfully.

Inside the capsule is the diaphragm, which is actually one plate of a small capacitor. That capacitor forms a voltage divider with the external bias resistor - the diaphragm moves in response to sound, and the capacitance changes as the plates get closer or farther apart, causing the divider to change. Since capacitors are sensitive to loading, it’s internally buffered with a JFET (junction field effect transistor).

Due to the mechanical and electronic tolerances involved, some capsules are more sensitive than others. Also, the JFET is rather sensitive to noise on the power supply. Both of these factors need to be accounted for when deploying the Sound Detector.

Power Supply

The Sound Detector is an analog circuit, and as such, it’s more sensitive to noise on the power supply than most digital circuits. Since the capsule is effectively a voltage divider sitting across the power rails, it will transcribe any noise on the supply lines onto the capsule output. The next circuit in the chain is a high-gain amplifier, so any noise on the supply will then be amplified. Therefore, the Sound Detector may require more careful power supply configuration than many circuits.

In testing with various supplies, a significant degree of variability was discovered - some supplies are less noisy than others. One exhibited as much as 30 mV ripple on the supply output, an as a result, the the Sound Detector was rather sensitive and unstable. You can check how clean a power supply is by checking it with an oscilloscope or volt meter, set to the AC Volts (or, if provided, the AC millivolts) range. A truly clean supply will show 0.000 VAC. Based on the supplies used in testing, ripple of more than about 10 mV is problematic.

Powering my Arduino with a 9V external supply, which allows the onboard regulators to function, the Arduino’s 5V output was sufficiently clean. However, powering it from the 5V available on the USB port on a PC, the regulators are bypassed, and the results were somewhat less usable, and vary greatly between different ports on different PCs. A powered USB hub will probably provide cleaner power than the ports on the PC itself.

If all else fails, three 1.5V batteries in series make a nice, clean source of 4.5V.

Amplitude Calibration

The Sound Detector comes set for moderate sensitivity - speaking directly into the microphone, or clapping your hands nearby should cause the gate output to fire. If you find that it doesn’t work well in a specific application, you can change the circuit to be more or less sensitive.

The gain is set by changing the feedback resistors in the preamp stage. The resistors are marked in the silkscreen on the PCB.

->Resistor Closeup<-

Resistor Closeup

R3 is a surface mount part, with 100K Ohm populated by default. R17 is an unpopulated position for a through hole resistor.

Lowering The gain

It’s most likely that you’ll find the detector to be too sensitive. In testing the board for this writeup, noisy air conditioning and music in the next office were enough to set it off. To make the board less sensitive, you can lower the preamplifier gain by populating R17 in parallel with R3.

R3 ValueR17 ValueArithmetic GainGain (dB)
100K-10040
100K100K5033
100K47K3230
100K22K1825
100K10K919
100K4.7K413
100K2.2K26
Raising The Gain

If you want to make the sound detector more sensitive, so that it will be activated by quieter sounds, you can remove R3, and populate R17.

R17 ValueArithmetic GainGain (dB)
100K10040
220K22046
470K47053
1Meg100060

Lights Out

In some applications, the onboard LED may be distracting or undesirable. To disable it, simply use a solder sucker or wick to remove the solder blob from the jumper near the LED.

alt text

Physical Considerations

The electret capsule on the Sound Detector is also sensitive to mechanical vibration and wind noise.

The Sound Detector will pick up handling noise. Mounting it with a resilient material can help absorb vibration - placing it on a piece of open-cell foam helped reject vibration conducted through the testing workbench. Other resilient mounting strategies would include suspending it using rubber bands, or building shock absorbers using #4 machine screws and heat-shrink tubing.

Wind noise is caused when blasts of air enter the capsule. Examples would be a windy day, or the sharp exhalation that often accompanies syllables such “p,” “b” and “t.” The capsule come with a thin fabric covering, but it may not be enough to prevent stronger blasts. You can craft a more robust windscreen with open-cell foam or synthetic fur (like the covering that sneaks into the frame when a boom mic accidentally enters a film scene).

Software Example

Now that we understand how to configure the board, lets hook it to an Arduino, and see what it can do.

Materials

In addition to the Sound Detector, we need the following parts.

Connections

We snapped a 5-pin section off the header, and soldered it to the Sound Detector. Then we took the jumper wires and made the following connections.

(Sound Detector → Arduino )

  • GND → Supply Ground
  • VCC → Power supply voltage between 3.5 and 5.5 Volts
  • Gate → Pin 2
  • Envelope → A0

Additionally, as described on the calibration page, a 33K Ohm resistor was soldered into position R17. R3 was left in place, so the gain was lowered from 40 dB to about 28 dB.

/******************************************************************************
 * sound_detector_demo.ino
 * Sound detector sample sketch
 * Byron Jacquot @ SparkFun Electronics
 * February 19, 2014
 * https://github.com/sparkfun/Sound_Detector
 *
 * This sketch demonstrates the use of the Sparkfun Sound Detector board.
 *
 * The Sound Detector is a small board that combines a microphone and some
 * processing circuitry.  It provides not only an audio output, but also a
 * binary indication of the presence of sound and an analog representation
 * of it's amplitude.
 *
 * This sketch demonstrates two different modes of usage for the Sound
 * Detector.  The gate output (a binary indication that is high when sound
 * is present, and low when conditions are quiet) is used to fire a pin-change
 * ISR, which lights an LED when the sound is present.  The envelope output
 * (an analog voltage to rises to indicate the amplitude of the sound) is
 * sampled in the loop(), and it prints an indication of the level to the
 * serial terminal.
 *
 * For more details about the Sound Detector, please check the hookup guide.
 *
 * Connections:
 * The Sound Detector is connected to the Adrduino as follows:
 * (Sound Detector -> Arduino pin)
 * GND → GND
 * VCC → 5V
 * Gate → Pin 2
 * Envelope → A0
 *
 * Resources:
 * Additional library requirements: none
 *
 * Development environment specifics:
 * Using Arduino IDe 1.0.5
 * Tested on Redboard, 3.3v/8MHz and 5v/16MHz ProMini hardware.
 *
 * This code is beerware; if you see me (or any other SparkFun employee) at the
 * local, and you've found our code helpful, please buy us a round!
 *
 * Distributed as-is; no warranty is given.
 ******************************************************************************/

 // Define hardware connections
#define PIN_GATE_IN 2
#define IRQ_GATE_IN  0
#define PIN_LED_OUT 13
#define PIN_ANALOG_IN A0

// soundISR()
// This function is installed as an interrupt service routine for the pin
// change interrupt.  When digital input 2 changes state, this routine
// is called.
// It queries the state of that pin, and sets the onboard LED to reflect that
// pin's state.
void soundISR()
{
  int pin_val;

  pin_val = digitalRead(PIN_GATE_IN);
  digitalWrite(PIN_LED_OUT, pin_val);
}

void setup()
{
  Serial.begin(9600);

  //  Configure LED pin as output
  pinMode(PIN_LED_OUT, OUTPUT);

  // configure input to interrupt
  pinMode(PIN_GATE_IN, INPUT);
  attachInterrupt(IRQ_GATE_IN, soundISR, CHANGE);

  // Display status
  Serial.println("Initialized");
}

void loop()
{
  int value;

  // Check the envelope input
  value = analogRead(PIN_ANALOG_IN);

  // Convert envelope value into a message
  Serial.print("Status: ");
  if(value <= 10)
  {
    Serial.println("Quiet.");
  }
  else if( (value > 10) && ( value <= 30) )
  {
    Serial.println("Moderate.");
  }
  else if(value > 30)
  {
    Serial.println("Loud.");
  }

  // pause for 1 second
  delay(1000);
}

This code simultaneously demonstrates two different operating modes of the Sound Detector.

  • First, using the external interrupt facility, the Arduino observes the gate output, and sets the onboard (pin 13) LED to follow the gate status.
  • Second, in the loop() routine, it uses an analog input to periodically sample the envelope signal. That value is interpreted into a message indicating the current loudness via a series of thresholds.

Analog Example

As a purely analog circuit, the Sound Detector isn’t limited to strictly being a peripheral for a microcontroller. To illustrate an alternate application, we’ve wired up a completely analog example. We’ve tied the envelope output to an LM3916 VU bar-graph LED driver, to make a visual sound level meter. For this application, the Sound Detector is configured with no resistor for R17, and the default 100K in position R3.

Materials

Again, we start with the Sound Detector, then add the following parts.

Schematic

We connect those parts as follows.

Fritzing Schematic

Which translates thusly onto a solderless breadboard.

Fritzing Breadboard

The assembled, operational version looks like this.

Physical Breadboard

Listening to The Lonely Bull by the Ventures

Sound picked up by the microphone is now translated onto the bar graph. The louder the sound is, the more LEDs light up!

A few of notes about the circuit.

  • It uses two power supply rails. An external supply was used as a source of 13 VDC. The 13V is further regulated down to 5V using an LM317 adjustable regulator. This provides the recommended minimum of 12V for the bar-graph driver, and a stable source of 5V for the Sound Detector.
    • The 5V is connected to the + rail at the top of the breadboard. It is used to power the Sound Detector, and as the anode supply for the LEDs.
    • The 13V is on the lower + rail, and is the power supply for the LM3916.
  • The 100K Ohm resistor between pins 6 and 7 of the LM3916 sets the reference for the scaling of the bar graph. If the meter seems to be too sensitive, it can be reduced to 10K or lower.
  • Pin 6 of the LED bar graph is at one of the covered-over positions on the power rail. The leg was folded over to make contact with pin 5.
  • Pin 9 of the LM3916 sets the chip for dot or bar modes. As shown above, tied to the 13V rail, the chip is in bar mode. If pin 9 is left unconnected, the chip will be in dot mode.

Resources and Going Further

A few parting thoughts.

Troubleshooting:

If the Sound Detector is misbehaving, try the following steps.

  • Double check that the power supply is clean, preferably with an oscilloscope. Irregularities on the supply will likely be present on the output.
  • The gain configuration is easier to tame with the higher headroom offered by higher supply voltages. Providing the Sound Detector with a stable 5V supply, and translating output down to 3.3V will yield better results than powering the detector directly from 3.3V.
  • Finally, listen to the audio output. AC-couple the audio output using a 10 uF electrolytic capacitor, with its + leg to the sound detector, and connect a small speaker or headphone. Simply listening to the output often yields clues as to what’s wrong.
    • You’ll be able to hear whether unexpected noises, such as wind and vibration, are being picked up.
    • If the audio output is distorted, the gain may need to be reduced.
    • If the audio output is really quiet, the gain may need to be increased.
    • If there is a constant tone on the audio output, double-check that the power supply is suitably stable. Switch-mode power supplies often introduce oscillations on the power rails.

Documentation

Design files for the Sound Detector are in the corresponding GitHub repository. This includes the Eagle files, and the Arduino example and Fritzing example we explored above.

Additionally, there are SPICE simulations of the circuit for LT Spice. One of those simulations, sound_detector-wav.asc actually analyzes the contents of a wav file (which was used to generate the diagram on page 2 of this tutorial), though you’ll have to modify the file path to analyze a wav file if your own.

Finally, the Sound Detector has been added to the sensors category in the Sparkfun Fritzing Library.

See Also


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

Large Solderable Breadboard Hookup Guide

0
0

Large Solderable Breadboard Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

Solderless breadboards are great for prototyping. But they’re not exactly mechanically robust. It seems like something, somewhere is always coming loose. Having a solderable board with a matching trace pattern allows you to make a prototype more solid without having to lay out a custom PCB.

Solderable Breadboard

At first glance, the large solderable breadboard mirrors the hole pattern of a regular large solderless breadboard. However, on closer inspection, you’ll find that it has some extra features that should ease the transition from solderless to solderable board.

In this tutorial, we’ll go over the features of the soderable breadboard, show you how to use it as the most basic level, and then show you more advanced examples.

Suggested Reading:

Quick Overview

I’ve used a number of similar soderable breadboards through the years, but many of them left something to be desired. The common ones are made from brittle phenolic PCB material. The copper traces are thin, poorly adhered, and tend to peel off when you rework the board. And most problematically, the trace pattern doesn’t always mimic a solderless breadboard – the power rails don’t match, or the center has four holes instead of five. Moving a circuit from to the soldered board involved extra translation work.

The large solderless breadboard is intended to solve those issues. It is a real FR4 fiberglass board, with soldermask, plated through-holes, and the layout duplicates the connectivity of a solderless breadboard.

alt text

Closeup of the pattern at the center of the board.

The center area of the breadboard mimics the hookup pattern of the solderless board - twin rows of 5 holes each, spaced 0.3" apart, to accommodate DIP ICs. Like the equivalent solderless board, the solderable board has 63 columns. The row and column coordinates are labeled to match the solderless boards.

Compared to the solderless boards, this solderable board also offers more flexiblity in how the power supplies can be wired.

Power Supply Background

A typical power supply provides a number of voltages to the attached circuitry. Each voltage is often referred to as a rail. * The number of supply rails needed, and the voltages provided on each, depend on the sort of circuitry being deployed.

  • To begin, every power supply has a “ground” rail. Ground is used as a 0V reference point, the voltage against which the others will be measured; it may not actually be connected to Earth.
  • For many years, digital circuits used a single 5V rail. More recently, lower supply voltages have become common, primarily 3.3V, but sometimes even lower, such as 1.8V.
  • Analog designs frequently use higher voltage bipolar power supplies, which provide mirror-image positive and negative rails. +/-12V and +/-15V are both common.
  • A mixed signal design involves both analog and digital sections, and brings along the supply voltage requirements form each. A good example would be a PC power supply, that provides 3.3V and 5V for the digital logic, and +/-12V for things like disk drive motors and cooling fans.

On a solderless breadboard, there are usually a pair of supply rails at each edge, that run the length of the board (though sometimes they aren’t totally continuous, split at the halfway point). They’re frequently marked with “+” and “-” symbols, possibly also color coded red and blue. The breadboard doesn’t make any assumptions about how the rails get used – it’s up to the user to feed voltages to the rails.

So with that, lets explore how to configure the supply rails on this breadboard.


* I’m having trouble finding a definitive etymology, but I believe the “rail” term stems from the use of the “third rail” to supply voltage on an electric railway, a usage that dates back to the 1880’s.

Optional Jumpers

With no further configuration, this board has 5 traces that run the length of the board. Four of them are the + and - traces at the top and bottom edges of the board, duplicating the equivalent points on a solderless board. The fifth of these traces runs down the “gutter” at the center of the board, intended for use as a ground.

These 5 traces meet with 5-pin 5mm screw terminals at each end of the board. The order of the terminals matches the order of the traces across the board. As seen below, the top screw terminal pin connects to the top “-” rail, the next screw terminal down meets the top “+” rail, and so on.

alt text

The board can be adapted with wire jumpers to accommodate a number of different voltage rail combinations.

The jumpers are as follows

  • JG1, JG2, JG3, JG4 can be populated to tie the mounting holes to the ground trace. If you are mounting the board in a metal enclosure, it’s good practice to ground the enclosure, and join the circuit ground to the enclosure.
  • JG5 and JG6 can be used to join the - rails at the edges of the board to the ground track down the center of the board.
  • TIE+ and TIE- connect the + and - rails on each side of the board, respectively. Just like a solderless board, these aren’t connected by default, but this board provides an easier option to tie them together.

The board also accepts screw 5mm terminals for the power connections, which can be populated to match the rail configuration. If you’d prefer a more solid connection than screw terminals provide, you can also solder wire directly to the pads.

The power connections and jumpers are duplicated at each end of the board. In most applications, you’ll only need to use the connections at one end.

Some Examples

Digital Circuit With One Supply Rail

alt text

Jumper details for single voltage, plus ground.

If you’re building a digital circuit with a single supply rail (typically 3.3V or 5V), make the following connections

  • Bridge jumpers TIE+ and TIE-.
  • Bridge jumpers JG5 or JG6.
  • Install a 2 position 5MM screw terminal. As seen above
    • The red wire is the supply voltage.
    • The black wire is ground.

When you install components, they can pick up the supply voltage on either + rail, and ground on the - rails or at the center ground trace.

Analog Circuit With Bipolar Rails

alt text

Jumper details for bipolar supply voltages, plus ground.

For an analog circuit with a bipolar power supply, configure the jumpers as follows

  • Bridge jumpers TIE+ and TIE-.
  • Install a 3 position 5MM screw terminal. As seen above
    • The red wire is the + supply voltage.
    • The blue wire is the - supply voltage.
    • The black wire is ground.

Components can pick up the positive supply voltage on either + rail, the negative supply voltage on either - rail, and ground on the center trace.

Multiple Boards

If you’re building a larger circuit using more than one of these boards, they can share a power supply. The most common configuration is known as “star power distribution.” The power supply forms the center of the system, and each board is connected directly to it.

Star Power

Or, redrawn for simplicity.

alt text

This configuration makes a direct connection between the supply and each board.

Resources and Going Further

Just having these boards around makes me want to solder something. Maybe a nice Moog Filter?

For smaller prototypes, the Medium Solderable Breadboard is a smaller version of this board that pairs with the 30-row solderless breadboard.

For more information on the large soderable breadboard, visit its GitHub repository.

For more prototyping goodness, check out these other SparkFun tutorials.


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

OBD II Uart Hookup Guide

0
0

OBD II Uart Hookup Guide a learn.sparkfun.com tutorial

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

Introduction

Have you ever had an infamous ‘check engine light’? Did you wish you could just check the error code yourself and not deal with going to a mechanic? With the OBD-II UART, your wishing can become a reality. The OBD-II UART allows you to connect your car to a computer, embedded microcontrollers, or single board computers such as the Raspberry Pi or Beaglebone Black.

alt text

This guide will show you:

  • What hardwrae is included on the OBD-II UART
  • The basics of OBD-II commands
  • How to hook this up over FTDI directly with your computer
  • How to hook this up to an Arduino and display information to an LCD

Required Materials

To follow along with the tutorial, you will need the following parts.


Required Tools

Suggested Reading

This tutorial does expect the user to have experience with basic electronics and serial communication. If you are unfamiliar with these concepts or need a refresher, check out these other tutorials.

Board Overview

On-Board Diagnostics, Second Generation (OBD-II) is a set of standards for implementing a computer based system to control emissions from vehicles. It was first introduced in the United States in 1994, and became a requirement on all 1996 and newer US vehicles. Other countries, including Canada, parts of the European Union, Japan, Australia, and Brazil adopted similar legislation. A large portion of the modern vehicle fleet supports OBD-II or one of its regional flavors.

Among other things, OBD-II requires that each compliant vehicle be equipped with a standard diagnostic connector (DLC) and describes a standard way of communicating with the vehicle’s computer, also known as the ECU (Electronic Control Unit). A wealth of information can be obtained by tapping into the OBD bus, including the status of the malfunction indicator light (MIL), diagnostic trouble codes (DTCs), inspection and maintenance (I/M) information, freeze frames, VIN, hundreds of real-time parameters, and more. You can read more about the OBD-II protocol here.

STN1110 is an OBD to UART interpreter that can be used to convert messages between any of the OBD-II protocols currently in use, and UART. It is fully compatible with the de facto industry standard ELM327 command set. Based on a 16-bit processor core, the STN1110 offers more features and better performance than any other ELM327 compatible IC. ScanTool has some great resources for the STN1110 available on their website, including:

Board Schematic

The OBD-II UART board has both the STN1110 and the MCP2551 chips populated on it, allowing the user to access both CAN and OBD-II protocols. The schematic can be viewed/downloaded here.

The STN1110 is the main controller chip on the board. This communicates with the CAN, ISO and J1850 transceivers. Voltage on the board is regulated to both 5V and 3.3V for all of the components to function properly. The board is powered from the DB9 connector.

Board Pin Out

There are two different connection points on the board. The first, on the outside edge of the board, is a 6-pin connector that is compatible with an FTDI board. However, only the TX, RX and GND pins are connected on this header, to allow for UART communication.

There is a second 8-pin header close to the DB9 connector. This allows the user to tap into the VBAT line, the CAN bus, the LINE bus and the J1858 bus, along with the common ground pin.

Now that we now about the board itself, let’s move on to hooking it up!

First Communcation

Soldering Headers

To create a solid electrical connection with any other components (such as an Arduino or an FTDI Basic), you need to solder headers to the board. For use with the FTDI Basic, it is easiest to solder male headers into the 6-pin header row at the edge of the board. Once you have this done, your board should look similar to this.

OBD-II With Headers

OBD-II Board with Right-Angle Male Headers soldered onto it.

Connecting to a Vehicle OBD Port

You will need to connect the OBD-II board to the OBD port on your vehicle. Depending on the make and model of your car, the port location may vary. Consult your owner’s maunal if you cannot locate the port.

Once you have located your OBD port, you will need to hook up the OBD-to-DB9 cable to the vehicle’s port.

OBD-II to DB9 cable

OBD-II to DB9 Cable

The mating end of the cable tends to be a very tight fit and require a bit of force to get it sitting securely, so it’s usually easier to start hooking everything together between the car and the cable. Once you get the car and the cable connected, then connect the DB9 end of the cable to the OBD-II board.

Connecting over a Serial Port

Once you have your headers attached to your board, and you’ve connected to your vehicle using the OBD-DB9 cable, you can start communicating withe OBD-II board over through a serial port using an FTDI Basic breakout board. The FTDI pinout matches with the 6 pin header on the OBD-II board, but only connects TX, RX and GND. Connect the FTDI board to the computer via a mini-USB cable, and open up a serial terminal on your computer. Configure the serial connection to 9600 bps, 8 data bits, 1 stop bit and no parity.

OBD-II UART connected to the car and the computer

Once you have your serial terminal set up, you will communicate with the OBD-II board by using AT commands. These commands always start with “AT”. The OBD-II board is case-insensitive, so don’t stress about only using capital letters. After sending “AT”, the next letters sent to the board will be the commands that should be executed by the board. You can find a list of all of the available AT commands here.

To start communicating with the board, type “ATZ” into your terminal window and hit “enter”. This will send the command to reset the board. You should see some LEDs flash on your board and then see the start-up prompt in the terminal window.

Start-up Prompt

If you receive back any garbled characters, double check that you have the correct serial port settings in your terminal.

Once you have proper communcation with your board set up, try reading the OBD-II UART system voltage. Type “ATRV” into the terminal window and hit enter. The board should then return the system voltage to you.

System voltage

This voltage reading should match your vehicle’s battery voltage.

To read additional OBD parapters for the vehicle, the OBD-II board must first be configured to the correct OBD protocol. There are several different OBD protocols, so it can be confusing attempting to find the correct one. However, like all things awesome, this OBD-II board automatically detects the protocol. To use this auto-detect feature, the vehicle’s ignition must be in the ‘On’ position. The vehicle doesn’t necessarily need to be running however. Once the ignition is on, send the command “ATSP0” (that’s a trailing zero). The board will then reply with “OK” once the proper protocol has been detected.

Auto-protocol detection

Once you have the proper protocol detected on your board, you can start sending OBD commands to the board.

OBD Commands

OBD Commands

The OBD commands are made up of hexadecimal codes written in ASCII characters. Generally, these commands contain 2 or more pairs of hexadecimal numbers, however there are a few commands that only require one hex pair.

The first hex pair in the OBD command represents the OBD mode which should be used. Any following hex pairs after that represent the Parameter ID (PID) to be read from the specified mode. There are 10 OBD modes, but keep in mind that not all vehicles will use all 10 modes. You will want to check your particular vehicle’s protocols to see what OBD modes and parameter IDs are supported.

Mode Number Mode Description
01 Current Data
02 Freeze Frame Data
03 Diagnostic Trouble Codes
04 Clear Trouble Code
05 Test Results/Oxygen Sensors
06 Test Results/Non-Continuous Testing
07 Show Pending Trouble Codes
08 Special Control Mode
09 Request Vehicle Information
0A Request Permanent Trouble Codes

You can read up more on the OBD PIDs functionality on Wikipedia. Some vehicle manufacturers also use their own proprietary parameters, so keep in mind that these may not be a comprehensive list for your car. Again, the ELM327 AT Commands datasheet is another good resource to check out.

Possibly the most important PID is 00. This works on any vehicle that supports OBD and gives a list of other PIDs which the car supports. In your terminal window (you do still have that open, right?!), type “0100” and hit “enter”. This command translates to “In mode 01, what PIDs are supported?”

PID Support Command

There is a general structure that all OBD responses have in common. The first response byte (in this case 0x41) lists the mode that was requested in the command. Thus the board sends 0x40 + 0x01. The second byte is the parameter that was requested, so in our case, 0x00. Any following bytes are the responses to the command. In this case, the bytes 0xBF, 0x9F, 0xA8 and 0x93 are the PIDs that are supported by the vehicle.

One other commonly supported parameter is the ‘Read Engine RPM’. Issue command “010C' and press enter. Keep in mind that the board will respond with a value listed in hex.

Read Engine RPM

The response structure is the same as before. 0x41 to state the board is in mode 01, followed by 0x0C to show that the board is looking at the RPM parameter. The returned value of 0x0E 0x96 can then be converted into a decimal value of 3734. This is actually 4 times the actual RPM, as this value is listed in quarters of RPM. Once the value is divided by 4, we have an idiling RPM of 933.

Check out the datasheet for the ELM327 for more PIDs to try out. Now let’s look at hooking the OBD-II board up to an Arduino.

Connecting to an Arduino

Connecting to an Arduino

Besides connecting directly to your computer with the OBD-II board, you can also run the data through an Arduino board and display the information on an LCD for embedding a project. For this section, you will need an Arduino Uno (or another 5V Arduino board), jumper wires, and a serial LCD.

You will only need to make 6 connections between all 3 devices to get this set up. Use the diagram and the chart below to properly wire everything.

alt text

Arduino Pin Serial LCD Pin OBD-II-UART Pin
GND GND GND
5V 5V None
D3 Rx None
D0(Rx) None Tx-O
D1(Tx) None Rx-I

You will want to download the sketch file here, or you can find the most up to date version of the code on GitHub. Keep in mind when you upload this to your board, you will want to disconnect the OBD-II board RX line from the Arduino TX-0, to prevent issues during code upload, such as bricking the OBD-II board.

Another thing to note about this set up is that the Arduino is not powered off of the OBD-II board. Therefore, you will need to either use USB power from your laptop to power the Arduino, or use a battery supply suck as a 9V battery and 9V barrel jack adapter.

Understanding the Sketch

This example sketch is very simple. The Arduino simply communicates with the OBD-II board and then sends the information received to the LCD screen. You will need to include the SoftwareSerial library in order to communicate with the LCD screen. Set the LCD TX/RX lines to pins 2 and 3 on the Arduino, and initialize the rest of your variables.

language:c
#include <SoftwareSerial.h>

//Create an instance of the new soft serial library to control the serial LCD
//Note, digital pin 3 of the Arduino should be connected to Rx of the serial LCD.

SoftwareSerial lcd(2,3);

//This is a character buffer that will store the data from the serial port
char rxData[20];
char rxIndex=0;

//Variables to hold the speed and RPM data.
int vehicleSpeed=0;
int vehicleRPM=0;

In the set up loop, the serial port for the LCD as well as the serial port for talking to the OBD-II board are both initialized at 9600 bps. The screen is then cleared, and the variable names of Speed and RPM are printed on the first and second rows respectively. As we did before, the OBD-II board is then reset.

language:c
void setup(){
  //Both the Serial LCD and the OBD-II-UART use 9600 bps.
  lcd.begin(9600);
  Serial.begin(9600);

  //Clear the old data from the LCD.
  lcd.write(254);
  lcd.write(1);

  //Put the speed header on the first row.
  lcd.print("Speed: ");
  lcd.write(254);
  //Put the RPM header on the second row.
  lcd.write(128+64);
  lcd.print("RPM: ");

  //Wait for a little while before sending the reset command to the OBD-II-UART
  delay(1500);
  //Reset the OBD-II-UART
  Serial.println("ATZ");
  //Wait for a bit before starting to send commands after the reset.
  delay(2000);

  //Delete any data that may be in the serial port before we begin.
  Serial.flush();
}

The main loop of the code simply sets the cursor locations, clears out any old data on the LCD screen, receives the data from the OBD-II board, tranlates it to an integer and prints the vehicle speed and RPM to the screen.

language:c
void loop(){
  //Delete any data that may be in the serial port before we begin.
  Serial.flush();
  //Set the cursor in the position where we want the speed data.
  lcd.write(254);
  lcd.write(128+8);
  //Clear out the old speed data, and reset the cursor position.
  lcd.print("");
  lcd.write(254);
  lcd.write(128+8);
  //Query the OBD-II-UART for the Vehicle Speed
  Serial.println("010D");
  //Get the response from the OBD-II-UART board. We get two responses
  //because the OBD-II-UART echoes the command that is sent.
  //We want the data in the second response.
  getResponse();
  getResponse();
  //Convert the string data to an integer
  vehicleSpeed = strtol(&rxData[6],0,16);
  //Print the speed data to the lcd
  lcd.print(vehicleSpeed);
  lcd.print(" km/h");
  delay(100);

  //Delete any data that may be left over in the serial port.
  Serial.flush();
  //Move the serial cursor to the position where we want the RPM data.
  lcd.write(254);
  lcd.write(128 + 69);
  //Clear the old RPM data, and then move the cursor position back.
  lcd.print("");
  lcd.write(254);
  lcd.write(128+69);

  //Query the OBD-II-UART for the Vehicle rpm
  Serial.println("010C");
  //Get the response from the OBD-II-UART board
  getResponse();
  getResponse();
  //Convert the string data to an integer
  //NOTE: RPM data is two bytes long, and delivered in 1/4 RPM from the OBD-II-UART
  vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
  //Print the rpm data to the lcd
  lcd.print(vehicleRPM);

  //Give the OBD bus a rest
  delay(100);

}

The final section of code simply defines the functions to communicate with the OBD-II board. This saves any incoming characters to the serial buffer until a carriage return is received.The buffer index is set to 0 and the board then waits for the next string to come in.

language:c
/The getResponse function collects incoming data from the UART into the rxData buffer
// and only exits when a carriage return character is seen. Once the carriage return
// string is detected, the rxData buffer is null terminated (so we can treat it as a string)
// and the rxData index is reset to 0 so that the next string can be copied.
void getResponse(void){
  char inChar=0;
  //Keep reading characters until we get a carriage return
  while(inChar != '\r'){
    //If a character comes in on the serial port, we need to act on it.
    if(Serial.available() > 0){
      //Start by checking if we've received the end of message character ('\r').
      if(Serial.peek() == '\r'){
        //Clear the Serial buffer
        inChar=Serial.read();
        //Put the end of string character on our data string
        rxData[rxIndex]='\0';
        //Reset the buffer index so that the next character goes back at the beginning of the string.
        rxIndex=0;
      }
      //If we didn't get the end of message character, just add the new character to the string.
      else{
        //Get the new character from the Serial port.
        inChar = Serial.read();
        //Add the new character to the string, and increment the index variable.
        rxData[rxIndex++]=inChar;
      }
    }
  }
}

Resources and Going Further

Now that you’ve gotten the basics down for communicating with the OBD-II UART board, try modifying the example sketch to work with parameter IDs that are supported on your particular vehicle.

You can also work with some free software available online, that prints the data out into cool graphs and meters for you without any programming required, other than using a serial port. Check out a current list of freeware for OBD boards here.


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

T5403 Barometric Pressure Sensor Hookup

0
0

T5403 Barometric Pressure Sensor Hookup a learn.sparkfun.com tutorial

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

Introduction

T5403 Breakout Board

The T5403 is a barometric pressure sensor with an I2C (“Wire”) interface.

Barometric pressure sensors measure the absolute pressure of the air around them. This pressure varies with both the weather and altitude. Depending on how you interpret the data, you can monitor changes in the weather, measure altitude, or any other tasks that require an accurate pressure reading.

Covered in This Tutorial

We will show you how to connect this sensor to an Arduino microcontroller and use the included software library to get measurements out of the sensor. We’ll also show you how to interpret the readings for both monitoring the weather and showing changes in altitude.

Suggested Reading

This part is easy to use. But before you start, we recommend the following background knowledge:

Connecting the Hardware

In this example, we will communicate with the T5403 using the I2C interface. While there are connections for SPI, they are currently unsupported.

Connection Names

The T5403 Breakout Board breaks out eight connections from the IC. We traditionally call these connections “pins” because they come from the pins on the IC, but they are actually holes that you can solder wires or header pins to.

T5403 breakout board

We’ll connect four of the eight pins on the board to your Arduino. The four pins you need are labeled GND, VCC, SCL, and SDA.

Connecting Wires to the Board

You can use any method you like to make your connections to the board. For this example, we’ll solder on a eight-pin length of male-male header strip, and use male-female jumper wires to connect the T5403 to your Arduino.

Solder a 8-pin length of male-male header to the board. You can solder it to either side. The bottom is more useful for breadboards, and the top is more useful for jumper wires.

T5403 Sensor with Headers

Note that the T5403 is sensitive to moisture. When you’re done soldering, do not clean off the flux by rinsing the board in water or other fluids.

Connecting the Board to your Arduino

When you’re done soldering, connect the +, -, CL, and DA pins to your Arduino. Different Arduino models use different pins for the I2C interface; use the following chart to determine where to plug everything in.

IMPORTANT: Connect the power pins (+ and -) ONLY to a 3.3V supply. Larger voltages will permanently damage the part. Note that because I2C uses open drain drivers, it is safe to connect the I2C pins (DA and CL) to an I2C port on a 5V microprocessor.

T5403 labelPin functionArduino connection
"-" (GND)groundGND
"+" (VDD)3.3V power supply3.3V
SDAI2C data Any pin labeled SDA, or:
Uno, Redboard, Pro / Pro MiniA4
Mega, Due20
Leonardo, Pro Micro2
SCLI2C clock Any pin labeled SCL, or:
Uno, Redboard, Pro / Pro MiniA5
Mega, Due21
Leonardo, Pro Micro3
MISOUnsupportedUnsupported
Reset/&SSDevice ResetAny I/O - Logic "LOW" to reset
SELI2C/SPI mode selectAny I/O - Logic "LOW" for SPI mode (Unsupported)
EOCEnd Of Conversion InterruptAny I/O or interrupt enabled pin - Outputs "HIGH" when measurement is complete

T5403 Frtizing Diagram

Once you have the T5403 connected to your Arduino, we’re ready to play with the software.

Installing the Arduino Library

Libraries are collections of software functions geared towards a single purpose, such as communicating with a specific device. Arduino comes with a number of built-in libraries that help you do advanced tasks. We’ve written an Arduino library called SFE_T5403 that allows you to easily talk to the T5403 sensor. This library is not included with the stock Arduino software, but don’t worry, installing new libraries is easy.

If you’d like to interface the T5403 to a microcontroller other than an Arduino, the C++ source code in the library and the information in the datasheet may be helpful when writing your own code.

1. Install the Arduino IDE

If you don’t already have the Arduino IDE (Integrated Development Environment) installed, download the version for your system (Windows, Mac, Linux) from http://arduino.cc/en/Main/Software and install it following the instructions on that site.

If you need help installing the IDE, check out our tutorial.

2. Install the SFE_T5403 Library

User-installed libraries live in a “libraries” folder within your personal Arduino sketch folder. On Windows systems your personal sketch folder is located in “My Documents/Arduino”. On Mac computers, it’s “~/Documents/Arduino”. On Linux it is usually “~/Arduino/sketchbook”. Locate your personal Arduino sketch folder and open it so you can drag new files into it.

Now download the latest T5403 software archive from this link: https://github.com/sparkfun/T5403_Barometric_Breakout/archive/master.zip. You can either save the file to your system and open it later, or open it directly.

(Note that you can find the .zip file for any Github repository by looking for the “Download ZIP” button on the main page:)

alt text

Open the .zip file you just downloaded. (On most systems you should be able to double-click it to show the included files.) Open the folder called “T5403_Barometric_Breakout-master”, then “software”, then “Arduino”. You should now see a folder called “libraries”. Drag the “libraries” folder from the .zip folder into your personal Arduino sketch folder. If you get a warning that there is already a libraries folder there, that’s fine. It just means you’ve already installed some libraries, which is great! Just tell your system to go ahead and overwrite them, which sounds alarming but will only add the new library to the existing folder.

alt text

That’s it! Now restart the Arduino IDE and you should be ready to go.

If any of these instructions are unclear, you can find more detailed instructions in our installing an arduino library tutorial.

Running the Example Sketches

Running the Example Sketch

The library you just installed includes an example sketch that show basic operation of the T5403. This are designed to be a starting point for writing your own code.

After you install the library, run the Arduino IDE, and open the following menu item: File / Examples / SFE_T5403 / SFE_T5403_example.

(If you don’t see this menu item, you may not have installed the library correctly, or didn’t restart the Arduino IDE. Take another look at the library installation page to see if you missed any steps.)

alt text

When the example opens, upload it to your Arduino (remember to select the correct board type and serial port), and open the Serial Monitor to 9600 baud. You should see some diagnostic information (if it can’t find the device, double check your hardware connections) followed by measurement readings. For more about interpreting these readings, see the next page, Measuring Weather and Altitude.

Writing Your Own Sketches

The comments and code in the example sketch should get you started when writing your own sketches. In many cases you should be able to copy and paste the example code into your own sketch.

Measuring Weather and Altitude

The T5403 was designed to accurately measure atmospheric pressure. Atmospheric pressure varies with both weather and altitude; you can measure both of these using this sensor. Here’s how:

What is Atmospheric Pressure?

The definition of pressure is a force “pressing” on an area. A common unit of pressure is pounds per square inch (psi). One pound, pressing on one square inch, equals one psi. The SI unit is newtons per square meter, which are called pascals (Pa).

There are lots of situations in which pressure can be measured (gravity, pull, etc.), but right now we’re interested in atmospheric pressure, which is the force that the air around you is exerting on everything. The weight of the gases in the atmosphere creates atmospheric pressure. One doesn’t normally notice that air weighs anything, but if you took a one inch wide column of air from sea level to the top of the atmosphere, it would weigh about 14.7 pounds. (A 1 cm wide column of air would weigh about 1 kg.) This weight, pressing down on the footprint of that column, creates the atmospheric pressure that we can measure with sensors like the T5403.

Because that inch-wide column of air weighs about 14.7 pounds, and is pressing on one square inch, it follows that the average sea level pressure is about 14.7 pounds per square inch (psi), or 101325 pascals. This will drop about 4% for each 1000 feet (or 300 meters) you ascend. The higher you get, the less pressure you’ll see, because the column to the top of the atmosphere is that much shorter and therefore weighs less. This is useful to know, because by measuring the pressure and doing some math, you can determine your altitude.

Fun fact: The air pressure at 12,500 feet (3810 meters) is only half of that at sea level. In other words, half of the mass of the atmosphere is below 12,500 feet, and the air at 12,500 feet is half as dense as that at sea level. No wonder you have a harder time breathing up there.

The T5403 outputs absolute pressure in hectopascal (hPa). This is equivalent to 100 pascals (Pa). One pascal is a very small amount of pressure, approximately the amount that a sheet of paper will exert resting on a table. You will more often see measurements in hectopascals (1 hPa = 100 Pa) or kilopascals (1 kPa = 1000 Pa). The Arduino library we’ve provided outputs values in hPa, which also happens to equal one millibar (mbar).

Here are some conversions to other pressure units:

1 hPa = 100 Pa = 1 mbar = 0.001 bar

1 hPa = 0.75006168 Torr

1 hPa = 0.01450377 psi (pounds per square inch)

1 hPa = 0.02953337 inHg (inches of mercury)

1 hpa = 0.00098692 atm (standard atmospheres)

Temperature Effects

Because temperature affects the density of a gas, and density affects the mass of a gas, and mass affects the pressure (whew), atmospheric pressure will change dramatically with temperature. Pilots know this as “density altitude”, which makes it easier to take off on a cold day than a hot one because the air is more dense and has a greater aerodynamic effect.

To compensate for temperature, the T5403 includes a rather good temperature sensor as well as a pressure sensor. To perform a pressure reading, you first take a temperature reading, then combine that with a raw pressure reading to come up with a final temperature-compensated pressure measurement. (Don’t worry, the Arduino library makes all of this very easy.)

Measuring Absolute Pressure

As we just mentioned, if your application requires measuring absolute pressure, all you have to do is get a temperature reading, then perform a pressure reading (see the example sketch for details). The final pressure reading will be in hPa = mbar. If you wish, you can convert this to a different unit using the above conversion factors.

Note that the absolute pressure of the atmosphere will vary with both your altitude and the current weather patterns, both of which are useful things to measure.

Weather Observations

The atmospheric pressure at any given location on earth (or anywhere with an atmosphere) isn’t constant. The complex interaction between the earth’s spin, axis tilt, and many other factors result in moving areas of higher and lower pressure, which in turn cause the variations in weather we see every day. By watching for changes in pressure, you can predict short-term changes in the weather. For example, dropping pressure usually means wet weather or a storm is approaching (a low-pressure system is moving in). Rising pressure usually means that clear weather is approaching (a high-pressure system is moving through).

But remember that atmospheric pressure also varies with altitude. The absolute pressure in Denver (altitude 5280') will always be lower than the absolute pressure in San Francisco (altitude 52'). If weather stations just reported their absolute pressure, it would be difficult to directly compare pressure measurements from one location to another (and large-scale weather predictions depend on measurements from as many stations as possible).

To solve this problem, weather stations always remove the effects of altitude from their reported pressure readings by mathematically adding the equivalent fixed pressure to make it appear as if the reading was taken at sea level. When you do this, a higher reading in San Francisco than Denver will always be because of weather patterns, and not because of altitude.

To do this, there is a function in the sketch called seaLevel(P,A). This takes absolute pressure (P) in hPa, and the station’s current altitude (A) in meters, and removes the effects of the altitude from the pressure. You can use the output of this function to directly compare your weather readings to other stations around the world.

For more information, here is a good Wikipedia article on mean sea level pressure.

Determining Altitude

Since pressure varies with altitude, you can use a pressure sensor to measure altitude (with a few caveats).

The average pressure of the atmosphere at sea level is 1013.25 hPa (or mbar). This drops off to zero as you climb towards the vacuum of space. Because the curve of this drop-off is well understood, you can compute the altitude difference between two pressure measurements (p and p0) by using this equation:

alt text

There are two ways you can take advantage of this.

  1. If you use sea level pressure (1013.25 hPa) as the baseline pressure (p0), the output of the equation will be your current altitude above sea level.

  2. Or, if you take a single pressure reading at your current location, and use that as your baseline (p0), all subsequent pressure readings will result in relative altitude changes from the baseline. Climb the stairs and you should see the altitude go from zero to 3 or 4 meters. Go down to the basement, and you’ll see -3 or -4 meters. There’s an example function in the example sketch called altitude(P,P0) that calculates the relative altitude change. If you give it the sea level pressure (1013.25 hPa) for p0, and your local pressure for p, it will give you your altitude above sea level. If you use a local pressure measurement for p0, subsequent p pressure readings will give you your change in altitude from the baseline.

Now for the caveats:

Accuracy: How accurate is this? The theoretical noise level at the T5403s highest resolution is 0.25m (about 10 inches), though in practice we see noise on the order of 1m (40 inches). You can improve the accuracy by taking a large number of readings and averaging them, although this will slow down your sample rate and response time.

Weather: You should also remember that pressure changes due to weather will affect your altitude readings. The best accuracy will be obtained if you take a “fresh” p0 when you need it and don’t rely on it to be accurate for extended periods due to changes in the weather.

Maximum altitude: The T5403 can’t measure all the way down to vacuum (or up to space). It’s advertised lower limit is about 300 hPa (or mbar), which corresponds to an altitude of about 3000m or 30,000 feet. People have flown these to higher altitudes and gotten useful results, but this isn’t guaranteed or likely to be accurate. (You might consider using GPS for high-altitude measurements).

Minimum altitude: Similarly, this sensor isn’t suited for large pressures either. The advertised upper limit is 1100 hPa=mbar (or 16 psi), which is about 500 feet below sea level (that’s in air - the T5403 isn’t submersible in water). This sensor isn’t a good choice for submersible or compressed-gas measurements.

Tips and Tricks

Things to Watch Out For

Give it the right voltage: The T5403 will operate on voltages from 1.7v to 3.6v. We recommend operating it at 3.3V. Never connect the “+” header to voltages higher than 3.6V!. Note that it is safe to connect the SCA and SDL pins to an I2C port on a 5V Arduino, as the pullup resistors on the T5403 board will keep the voltage below 3.6V.

Give it air: Remember that the T5403 needs access to ambient air to measure its pressure, so don’t put it in a sealed case. Providing a small vent hole should be adequate.

But not too much air: On the other hand, exposure to fast-moving air or wind can cause momentary pressure variations that will affect your readings. Shield the device from strong air currents.

Keep it cool: Because an accurate temperature reading is needed to measure the pressure, try not to expose the device to rapid temperature changes, and keep it away from nearby hot parts and other heat sources.

Keep it dry: The T5403 is sensitive to moisture. Don’t submerge it or allow it to contact liquid water.

Changing the Solder Jumper

Solder jumpers are closely-spaced pads on a printed circuit board that are covered by blobs of solder to create an electrical connection. The T5403 breakout board has one such jumper; you can remove the solder from these pads to break the connection and alter the function of the board.

To remove the solder from a solder jumper, cover it with solder wick, and carefully heat it with a soldering iron. When the solder melts, it will be absorbed by the wick. Remove the wick before the solder cools so it doesn’t stick to the pads. If you didn’t get all of the solder on the first pass, give it another try with a clean section of solder wick. When you’re done you should be able to see a broken connection between the pads. While doing this be careful not to overheat the board (let it cool off if you’re having problems), or the copper pads may lift from the board.

T5403 Breakout Board

Disabling the I2C pullup resistors (SJ1)

The T5403 communicates with a host microcontroller via a communications standard called “I2C” (for Inter Integrated Circut). I2C uses two wires, usually labeled SCL (Serial Clock) and SDA (Serial Data). To function properly, I2C requires a pullup resistor on each of those lines. The T5403 board includes these resistors. They’re enabled by default, but you can disable them by clearing solder jumper.

I2C allows you to have multiple devices connected to the same two lines (collectively called a bus). The pullup resistors allow the bus to function, but you should only have one set of pullup resistors per bus.

If you have just one I2C device (such as the T5403 breakout board) connected to your microcontroller, the board is already set up properly. You don’t need to change anything.

However, if you wish to connect more than one device to the bus, you should ensure that there is only one set of pullup resistors enabled on the bus. You do this by disabling every set of pullup resistors except one. (It doesn’t matter where the enabled resistors live; they can be anywhere on the bus.)

To disable the I2C pullup resistors, remove all of the solder from the jumper. This jumper has three pads; be sure to separate all of the pads from each other. Remember that you’ll need to ensure that another set of pullup resistors are enabled somewhere on the I2C bus.

Note that you should not operate an I2C bus without pullup resistors, as the internal weak pull-up resistors in the Arduino will pull the bus to 5V, which may damage the T5403.

Using the EOC pin

The End of Conversion (EOC) pin is used to signal when the T5403 is finished taking a measurement. There is a waiting period to read a measurement from the device. This time varies with the measurement type and accuracy desired. The example code uses preset delays as stated in the data sheet.

Resources and Going Further

The example sketch included with the library should help you write your own code for the T5403. The code is commented to help you understand what it’s doing. In many cases, you should be able to copy and paste the example code into your own sketches. You may also want to refer to the datasheet and app note for more information about the internal workings of the sensor.

If you have any problems or questions, our technical support department can help. Please don’t hesitate to contact us. We also love to hear about your projects!

Further reading and projects:


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

Build an Auduino Step Sequencer

0
0

Build an Auduino Step Sequencer a learn.sparkfun.com tutorial

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

"You Spelled Arduino Wrong"

Synthy Goodness

Kids these days, with their techno musics… am I right? Back in my day a synthesizer took up a whole room. Nowadays you can download one on your computerphone and be dubstepping by lunchtime.

Okay, I kind of am one of those kids. I can’t get enough ‘bleeps’ and ‘bloops’. So, when I came across the Auduino project, a grain synthesizer for Arduino, I was excited to put one together. And I did! And it was great! But that’s not what this tutorial is about, because there are plenty of well documented builds on the Auduino site already. No, today we’re going to take Auduino to the next level with the help of an Arduino Mega and a little code modification.

The original Auduino is a simple grain synthesizer: You twiddle the knobs and it makes a sound. Don’t get me wrong, you can spend hours doing that… there’s just not much composition in it. We’ll be turning this basic synthesizer into a step sequencer, allowing us to program 8 different sounds and play them in a repeated loop.

Before we start changing things up, let’s make sure we understand what Auduino looks like when you download it.

Suggested Reading

This project builds upon a few other concepts and skills. Feel free to read up on any with which you are unfamiliar.

Parts I Used

Understanding the Framework

The beauty of Auduino is that it’s elegantly written. There are no libraries to install, just a single sketch to download and unzip into its own folder. Heck, the whole thing compiles to only about 2KB! Instead of dumping that code out here and sifting through it, I’ll try to abbreviate and give you sort of a wireframe view of how it works:

The top of the sketch is mainly used as a space for declaring global variables where the oscillator parameters will be stored. There’s also a section that defines hardware dependent functions like PWM_INTERRUPT based on what hardware is detected by the compiler. After that, there are a few frequency mapping tables for the grain repetition frequency, the sketch uses a pentatonic mapping by default, which is nice because it makes it impossible to play a really sour note.

Next, we happen upon a procedure called AudioOn() which sets up the PWM timer. This is another hardware dependent setting.

Finally, we get to the familiar setup() routine, which is refreshingly straight-forward. All that happens here is that we put the PWM output (the audio out pin) in OUTPUT mode. Then the audioOn() procedure gets the PWM timer rolling, and we finish up by setting up our status LED.

The main loop of the sketch reads the analog inputs that are used to control the synth parameters. The controller will basically read and re-read the analog inputs until a preset timer overflows, and then the SIGNAL(PWM_INTERRUPT) procedure will launch. That’s where all of the action happens.

SIGNAL is a procedure that runs every time that the timer defined by PWM_INTERRUPT overflows. This ensures that the synthesizer runs at a set frequency, regardless of what’s happening in the main loop. We’ll use this to our advantage, when we make our modifications later. If you want to understand exactly how this routine creates the wild and wacky sounds you’re hearing, then you’ll need to poke around the Auduino Wiki; algorithmic synthesis can be a challenging concept.

In short, the sound is comprised of two triangle waves which are calculated based on the analog inputs. There are two analog inputs for each wave: one controls the frequency of the wave, and the other controls the decay.

figure 1

These waves have the same static duration, and the combined waves over the length of that duration comprise what’s called a grain.

figure 2

Finally there’s an analog input that controls the frequency at which this “grain” is repeated. The result is a mashup of the repetition frequency and the original grain.

figure 3

The Auduino Wiki claims that it sounds a lot like a single oscillator with a pair of resonating bandpass filters, and it does indeed. In fact, you could be forgiven for thinking of the frequency and decay knobs as frequency and resonance (‘Q’) knobs. However, because the effect is achieved through granular synthesis, some really interesting stuff happens when frequencies approach the extreme limits of the timer.

To accomplish this musical magic, the SIGNAL() procedure performs a handful of fancy bitwise operations, which make the code difficult to understand at first glance but make it very fast. So fast, in fact, that there’s plenty of room in between timer overflows for us to add a few features…

Modifying the Framework

Now that we have a basic understanding of how the standard Auduino sketch works, we can start adding some of our own procedures to the main loop. First let’s lay out what it is that we’re trying to accomplish.

This tutorial is all about building a “step sequencer,” a synthesizer that will hold a number of different parameters and play them back in sequence. This means that, along with more analog inputs, we’ll also need:

  • Global Variables to hold all of the parameters for each step
  • Controls for selecting and changing steps in the sequence (step editor)
  • A Mechanism for advancing through all steps in the sequence at a set rate (playback)
  • A Control for changing the step rate (tempo)

I threw in another cool feature: the ability to shift the parameters on all steps in the sequence at once. That way I can setup a sequence and run it while I sweep the filters around. Also, I can pitch-shift the entire sequence.

You can download the complete altered sketch here, if you’re not into copy/paste.

Let’s go through the new code and figure out where all of these changes are gonna live:

First, we’ll need to establish a heaping handful of global variables…

language:c
int tempo = 100000;
int pattern = 0;
int counter = 0;

int a1 = 0; int a2 = 0; int a3 = 0; int a4 = 0; int a5 = 0;
int b1 = 0; int b2 = 0; int b3 = 0; int b4 = 0; int b5 = 0;
int c1 = 0; int c2 = 0; int c3 = 0; int c4 = 0; int c5 = 0;
int d1 = 0; int d2 = 0; int d3 = 0; int d4 = 0; int d5 = 0;
int e1 = 0; int e2 = 0; int e3 = 0; int e4 = 0; int e5 = 0;
int f1 = 0; int f2 = 0; int f3 = 0; int f4 = 0; int f5 = 0;
int g1 = 0; int g2 = 0; int g3 = 0; int g4 = 0; int g5 = 0;
int h1 = 0; int h2 = 0; int h3 = 0; int h4 = 0; int h5 = 0;

int live_sync_phase = 0;
int live_grain_phase = 0;
int live_grain_decay = 0;
int live_grain2_phase = 0;
int live_grain2_decay = 0;

The “tempo” variable will dictate how many loop cycles can elapse before we move to the next step in the sequence. The user will access this variable directly using an analog input. Next, we setup a variable called “pattern,” which would be better thought of as “step.” It controls which step in the 8-step sequence we’re currently playing. We also need to create a counter, which will keep track of how many loop cycles we’ve executed. This will be compared to “tempo” during each iteration, so we know when to advance one step in the sequence.

The big block of alphanumerically labeled integer variables will be used to store the five grain synthesizer parameters (1-5) for each of the eight steps (a-h). This could be accomplished using a table as well. This way, it’s obvious to the beginner what’s going on later, because we won’t be calling stuff from tables.

Finally, there is a set of five variables that contain what I call the “live” parameters – the adjustments that are made to the entire 8-step sequence during play.

Now that we’ve created all of our global variables, we can start configuring our hardware. I added these chunks to the setup procedure:

language:c
  pinMode(39, OUTPUT); digitalWrite(39, LOW);
  pinMode(41, OUTPUT); digitalWrite(41, LOW);
  pinMode(43, OUTPUT); digitalWrite(43, LOW);
  pinMode(45, OUTPUT); digitalWrite(45, LOW);
  pinMode(47, OUTPUT); digitalWrite(47, LOW);
  pinMode(49, OUTPUT); digitalWrite(49, LOW);
  pinMode(51, OUTPUT); digitalWrite(51, LOW);
  pinMode(53, OUTPUT); digitalWrite(53, LOW);

  pinMode(24, INPUT); digitalWrite(24, HIGH);
  pinMode(26, INPUT); digitalWrite(26, HIGH);
  pinMode(28, INPUT); digitalWrite(28, HIGH);
  pinMode(30, INPUT); digitalWrite(30, HIGH);
  pinMode(32, INPUT); digitalWrite(32, HIGH);
  pinMode(34, INPUT); digitalWrite(34, HIGH);
  pinMode(36, INPUT); digitalWrite(36, HIGH);
  pinMode(38, INPUT); digitalWrite(38, HIGH);

The first eight lines correspond to the eight status LEDs that indicate the user’s position in the sequence. The second set of eight are the eight buttons used to select a step in the sequence for editing. All of the LEDs are declared as outputs and default to the LOW position. Whereas, all of the buttons are declared as inputs, and the internal pull-up resistors are set for each.

And now, the main loop. I’ll explain as much as I can in the comments:

language:c
void loop() {


  counter++;

/* Most of the time, the main loop will just advance the counter while we continue generating noise. Each iteration, we check the counter against our "tempo" parameter to find out if it's time yet to jump to the next step. */

  if(counter>tempo){ //If it's time to advance to the next step:



//Housecleaning: Just a few things to get out of the way since the counter is "full"

  counter=0; //Reset the counter variable
  if(pattern==8){pattern=0;} //Make sure we're not about to go to imaginary step 9.
  pattern++; //Let all of the following code know that we're setting up for the next step
  //Turn off all of the step indicator lights in preparation for lighting the correct one.
  digitalWrite(39, LOW);digitalWrite(41, LOW);digitalWrite(43, LOW);digitalWrite(45, LOW);
  digitalWrite(47, LOW);digitalWrite(49, LOW);digitalWrite(51, LOW);digitalWrite(53, LOW);



 //Live Tweaks: Read the analog inputs associated with each "live" parameter.

  live_sync_phase = map(analogRead(14),0,1023,-500,500);
  live_grain_phase = map(analogRead(10),0,1023,-200,200);
  live_grain_decay = map(analogRead(9),0,1023,-20,20);
  live_grain2_phase = map(analogRead(8),0,1023,-200,200);
  live_grain2_decay = map(analogRead(11),0,1023,-50,50);



//Tempo Control: Read the analog inputs associated with the "tempo" parameter.
  tempo = map(analogRead(15),0,1023,1000,32000);



//Grab the parameters for the step that we're now in. We'll use a series of case
//statements switched on the "pattern" variable that we incremented earlier.

/* In each of the case routines below you'll notice that we're addressing
each of the existing Auduino parameters and making them equal to the stored
parameter plus the associated "live" parameter. */

  switch(pattern){

    case 1:
    syncPhaseInc = a1 + live_sync_phase; grainPhaseInc = a2 + live_grain_phase; grainDecay = a3 + live_grain_decay; grain2PhaseInc = a4 + live_grain2_phase; grain2Decay = a5 + live_grain2_decay; digitalWrite(53, HIGH); break;
    case 2:
    syncPhaseInc = b1 + live_sync_phase; grainPhaseInc = b2 + live_grain_phase; grainDecay = b3 + live_grain_decay; grain2PhaseInc = b4 + live_grain2_phase; grain2Decay = b5 + live_grain2_decay; digitalWrite(51, HIGH); break;
    case 3:
    syncPhaseInc = c1 + live_sync_phase; grainPhaseInc = c2 + live_grain_phase; grainDecay = c3 + live_grain_decay; grain2PhaseInc = c4 + live_grain2_phase; grain2Decay = c5 + live_grain2_decay; digitalWrite(49, HIGH); break;
    case 4:
    syncPhaseInc = d1 + live_sync_phase; grainPhaseInc = d2 + live_grain_phase; grainDecay = d3 + live_grain_decay; grain2PhaseInc = d4 + live_grain2_phase; grain2Decay = d5 + live_grain2_decay; digitalWrite(47, HIGH); break;
    case 5:
    syncPhaseInc = e1 + live_sync_phase; grainPhaseInc = e2 + live_grain_phase; grainDecay = e3 + live_grain_decay; grain2PhaseInc = e4 + live_grain2_phase; grain2Decay = e5 + live_grain2_decay; digitalWrite(45, HIGH); break;
    case 6:
    syncPhaseInc = f1 + live_sync_phase; grainPhaseInc = f2 + live_grain_phase; grainDecay = f3 + live_grain_decay; grain2PhaseInc = f4 + live_grain2_phase; grain2Decay = f5 + live_grain2_decay; digitalWrite(43, HIGH); break;
    case 7:
    syncPhaseInc = g1 + live_sync_phase; grainPhaseInc = g2 + live_grain_phase; grainDecay = g3 + live_grain_decay; grain2PhaseInc = g4 + live_grain2_phase; grain2Decay = g5 + live_grain2_decay; digitalWrite(41, HIGH); break;
    case 8:
    syncPhaseInc = h1 + live_sync_phase; grainPhaseInc = h2 + live_grain_phase; grainDecay = h3 + live_grain_decay; grain2PhaseInc = h4 + live_grain2_phase; grain2Decay = h5 + live_grain2_decay; digitalWrite(39, HIGH); break;
  }

//Check to see if the user is trying to change the step parameters.
//This series of statements simply check for a button press from each of
//the step buttons and call a function to change the indicated step.

    if(digitalRead(24)==LOW){changeStep(1);}
    if(digitalRead(26)==LOW){changeStep(2);}
    if(digitalRead(28)==LOW){changeStep(3);}
    if(digitalRead(30)==LOW){changeStep(4);}
    if(digitalRead(32)==LOW){changeStep(5);}
    if(digitalRead(34)==LOW){changeStep(6);}
    if(digitalRead(38)==LOW){changeStep(7);}
    if(digitalRead(36)==LOW){changeStep(8);}
}}

Hopefully that wasn’t too confusing. Basically the main loop just counts up until the counter hits the “tempo” value, then it pops over to the next step in the sequence, loading up the parameters for that step and being sure to reset to step 1 when it passes step 8. Finally, it checks for user input from the step change buttons. If there’s a button press (meaning that the user wants to change the step for that button) we call a function to alter the appropriate parameters and pass it the number of the step that we want to change:

language:c
void changeStep(int step_num){

/* The first thing we do is to turn off all indicator lights so that we can properly indicate which step we're currently editing. */

  digitalWrite(39, LOW);digitalWrite(41, LOW);digitalWrite(43, LOW);digitalWrite(45, LOW);
  digitalWrite(47, LOW);digitalWrite(49, LOW);digitalWrite(51, LOW);digitalWrite(53, LOW);

// Then indicate the appropriate step.

    switch(step_num){

    case 1:
    digitalWrite(53, HIGH); break;
    case 2:
    digitalWrite(51, HIGH); break;
    case 3:
    digitalWrite(49, HIGH); break;
    case 4:
    digitalWrite(47, HIGH); break;
    case 5:
    digitalWrite(45, HIGH); break;
    case 6:
    digitalWrite(43, HIGH); break;
    case 7:
    digitalWrite(41, HIGH); break;
    case 8:
    digitalWrite(39, HIGH); break;
  }


/* This next chunk of code is fairly similar to the unaltered Auduino sketch. This allows
us to continue updating the synth parameters to the user input. That way, you can dial in
the sound of a particular step. The while-loop traps the program flow here until the user
pushes button 1. As the code currently stands, "live" parameters aren't applied while in
the step editor but you could easily add the live parameters below. */


while(1){

  counter++;
  if(counter>tempo){

  counter=0;
  syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));

  grainPhaseInc  = mapPhaseInc(analogRead(GRAIN_FREQ_CONTROL)) / 2;
  grainDecay     = analogRead(GRAIN_DECAY_CONTROL) / 8;
  grain2PhaseInc = mapPhaseInc(analogRead(GRAIN2_FREQ_CONTROL)) / 2;
  grain2Decay    = analogRead(GRAIN2_DECAY_CONTROL) / 4;

//Here we read the button 1 input and commit the step changes to the appropriate parameters.

  if(digitalRead(24)==LOW && step_num==1){
    a1 = syncPhaseInc; a2 = grainPhaseInc; a3 = grainDecay; a4 = grain2PhaseInc; a5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==2){
    b1 = syncPhaseInc; b2 = grainPhaseInc; b3 = grainDecay; b4 = grain2PhaseInc; b5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==3){
    c1 = syncPhaseInc; c2 = grainPhaseInc; c3 = grainDecay; c4 = grain2PhaseInc; c5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==4){
    d1 = syncPhaseInc; d2 = grainPhaseInc; d3 = grainDecay; d4 = grain2PhaseInc; d5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==5){
    e1 = syncPhaseInc; e2 = grainPhaseInc; e3 = grainDecay; e4 = grain2PhaseInc; e5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==6){
    f1 = syncPhaseInc; f2 = grainPhaseInc; f3 = grainDecay; f4 = grain2PhaseInc; f5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==7){
    g1 = syncPhaseInc; g2 = grainPhaseInc; g3 = grainDecay; g4 = grain2PhaseInc; g5 = grain2Decay;
    return;}

  else if(digitalRead(24)==LOW && step_num==8){
    h1 = syncPhaseInc; h2 = grainPhaseInc; h3 = grainDecay; h4 = grain2PhaseInc; h5 = grain2Decay;
    return;}

    }
  }
}

With these pieces of code added, the Auduino sketch should now act as an 8-step sequencer.

Now that we have the firmware nailed down, let’s get our hardware sorted. After all, a solid 32% of the fun is purely in turning the knobs and pushing the buttons.

Buttons and Knobs

Alright, now it’s time to put together the front panel! This will be the interface that we use to adjust synth parameters and edit steps. Looking back at the code, you’ll note that we have a number of analog inputs, digital inputs, and digital outputs. We can handle the analog inputs with 10k linear potentiometers. By forming a voltage divider across the potentiometer, we make it possible to dial in any voltage to the analog pin and read its position using the Arduino. The digital inputs will just be buttons to ground, since the Arduino has internal pull-up resistors. Finally, LEDs will act as our outputs.

I built the front panel of my synthesizer out of chipboard, which I coated in clear enamel for rigidity. You can make it from anything you want: acrylic, wood, sheet metal, so long as it’s rigid enough to hold all of the components in place. I started by just mounting all of my controls and making sure that they were all oriented correctly before wiring them up.

front_panel_1

You’ll notice there’s a rectangular hole in my front panel above the step indicator lights. That’s for a VU Meter that I dug up at a local surplus shop. It isn’t even a VU Meter. It was apparently for indicating the operating voltage of some huge piece of equipment… anyway, I just drove it off the audio output with a diode to prevent EMF related problems and drop the line voltage into the operating range of the gauge. I won’t go into any more detail about that since I’ll never be able to track down a part number for you on that, and, if you go find your own, it will undoubtedly have its own special operating range.

The next order of business is to wire everything. It helps to consult the code to figure out to which pin on the Arduino everything is supposed to connect. Each potentiometer gets a 5V and a GND connection. Then the center pin (the wiper) is connected to the appropriate analog input. Each LED is connected to its respective digital output as well as GND. Each button is connected to a digital input and a GND. Finally, connect the audio output to pin 13 and GND. If you’re using a stereo output jack, you can tie both channels together. In this configuration, the audio jack will output 5V audio instead of standard 1V line level. Most amplifiers and headphones don’t care, but just keep it in mind. I’ve put together the drawing below to help you wrap your head around things:

Fritz_Sequencer

I have a bunch more potentiometers than I really need on mine because I kind of designed the panel before I knew how the synth was going to work. You could always add some filters, though, and connect them to the leftover pots.

Along with the front panel, you’ll need some kind of power connection. Our Wall Adapter Power Supplies work well for that and plug directly into the Arduino. Once I stuffed everything into the enclosure, it looked like this:

synth_front_done

And then it was time to jam…

Beautiful Music

Time to Jam. Check it out!



As you can hear, this thing makes an impressive array of sounds for what it is. It’s hard to tell from the video but the panel is laid out as follows (Left to Right):

Top Row: Grain 1 Phase, Grain 1 Decay, Grain 2 Phase, Grain 2 Decay

Second Row: N/A, N/A, N/A, Sync Phase (Freq)

Third Row: Global 1 Phase, Global 1 Decay, Global 2 Phase, Global 2 Decay

Bottom Row: Step Tempo, Global Phase (Freq), N/A, N/A

Resources and Going Further

Hope you enjoyed this project and I hope you get around to building your own! If you do, link us some pictures in the discussion section of this tutorial, we’d love to see them!

If you’re building your own version of this, you can find more information on Auduino here. You can also download my altered version of the sketch here.

Check out some of our other audio related tutorials:


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

Viewing all 1114 articles
Browse latest View live




Latest Images