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

Python and GPS Tracking

$
0
0

Introduction

In my quest to design a radio tracking system for my next HAB, I found it very easy to create applications on my computer and interact with embedded hardware over a serial port using the Python programming language. My goal was to have my HAB transmit GPS data (as well as other sensor data) over RF, to a base station, and graphically display position and altitude on a map. My base station is a radio receiver connected to my laptop over a serial to USB connection. However, in this tutorial, instead of using radios, we will use a GPS tethered to your computer over USB, as a proof of concept.

Of course, with an internet connection, I could easily load my waypoints into many different online tools to view my position on a map, but I didn't want to rely on internet coverage. I wanted the position of the balloon plotted on my own map, so that I could actively track, without the need for internet or paper maps. The program can also be used as a general purpose NMEA parser, that will plot positions on a map of your choice. Just enter your NMEA data into a text file and the program will do the rest.

Showing a trip from SparkFun to Boulder, CO. 

This tutorial will start with a general introduction to Python and Python programming. Once you can run a simple Python script, we move to an example that shows you how to perform a serial loop back test, by creating a stripped down serial terminal program. The loopback test demonstrates how to send and receive serial data through Python, which is the first step to interacting with all kinds of embedded hardware over the serial port. We will finish with a real-world example that takes GPS data over the serial port and plots position overlaid on a scaled map of your choice. If you want to follow along with everything in this tutorial, there are a few pieces of hardware you will need.

For the loopback test, all you need is the FTDI Basic. For the GPS tracking example, you will need a GPS unit, as well as the FTDI. 

What is Python?

If you are already familiar with installing and running Python, feel free to skip ahead. Python is an interpreted programming language, which is slightly different than something like Arduino or programming in C. The program you write isn't compiled as a whole, into machine code, rather each line of the program is sequentially fed into something called a Python interpreter. Once you get the Python interpreter installed, you can write scripts using any text editor. Your program is run by simply calling your Python script and, line by line, your code is fed into the interpreter. If your code has a mistake, the interpreter will stop at that line and give you an error code, along with the line number of the error.

The holy grail for Python 2.7 reference can be found here:

Installing Python

At the time of this tutorial, Python 2.7 is the most widely used version of Python and has the most compatible libraries (aka modules). Python 3 is available, but I suggest sticking with 2.7, if you want the greatest compatibility. 

After you install Python, you should be able to open a command prompt within any directory and type 'python'. You should see the interpreter fire up.

If you don't see this, it is time to start some detective work. Copy your error code, enter it into your search engine along with the name 'python' and your OS name, and then you should see a wealth of solutions to issues similar, if not exact, to yours. Very likely, if the command 'python' is not found, you will need to edit your PATH variables. More information on this can be found here. FYI, be VERY careful editing PATH variables. If you don't do it correctly, you can really mess up your computer, so follow the instructions exactly. You have been warned. 

If you don't want to edit PATH variables, you can always run Python.exe directly out of your Python installation folder.

Running a Python Script 

Once you can invoke the Python interpreter, you can now run a simple test script. Now is a good time to choose a text editor, preferably one that knows you are writing Python code. In Windows, I suggest Programmers Notepad, and in Mac/Linux I use gedit. One of the main rules you need to follow when writing Python code is that code chunks are not enclosed by brackets {}, like they are in C programming. Instead, Python uses tabs to separate code blocks, specifically 4 space tabs. If you don't use 4 space tabs or don't use an editor that tabs correctly, you could get errant formatting, the interpreter will throw errors, and you will no doubt have a bad time. 

For example, here is a simple script that will print 'test' continuously. 

# simple script
def test():
    print "test"
while 1:
    test()

Now save this code in a text editor with the extention your_script_name.py.

The first line is a comment (text that isn't executed) and can be created by using a # .

The second line is a function definition named test().

The third line is spaced 4 times and is the function body, which just prints "test"to the command window.

The third line is where the code starts in a while loop, running the test() function.

To run this script, copy and paste the code into a file and save it with the extention .py. Now open a command line in the directory of your script and type:

python your_script_name.py

The window should see the word 'test' screaming by.

To stop the program, hit Ctrl+c or close the window. 

Installing a Python Module

At some point in your development, you will want to use a library or module that someone else has written. There is a simple process of installing Python modules. The first one we want to install is pyserial.

Download the tar.gz file and un-compress it to an accessible location. Open a command prompt in the location of the pyserial directory and send the command (use sudo if using linux):

python setup.py install

You should see a bunch of action in the command window and hopefully no errors. All this process is doing is moving some files into your main Python installation location, so that when you call the module in your script, Python knows where to find it. You can actually delete the module folder and tar.gz file when you are done, since the relevant source code was just copied to a location in your main Python directory. More information on how this works can be found here:

FYI, many Python modules can be found in Windows .exe installation packages that allow you to forgo the above steps for a 'one-click' installation. A good resource for Windows binary files for 32-bit and 64-bit OS can be found here:

Python Serial Loopback Test

This example requires using an FTDI Basic or any other serial COM port device.

Simply, connect the TX pin to the RX pin with a wire to form a loopback. Anything that gets sent out of the serial port transmit pin gets bounced back to the receive pin. This test proves your serial device works and that you can send and receive data.  

Now, plug your FTDI Basic into your computer and find your COM port number. We can see a list of available ports by typing this:

python -m serial.tools.list_ports

If you are using linux:

dmesg | grep tty

Note your COM port number. 

Now download the piece of code below and open it in a text editor (make sure everything is tabbed in 4 space intervals!!):

import serial

#####Global Variables######################################
#be sure to declare the variable as 'global var' in the fxn
ser = 0

#####FUNCTIONS#############################################
#initialize serial connection 
def init_serial():
    COMNUM = 9 #set you COM port # here
    global ser #must be declared in each fxn used
    ser = serial.Serial()
    ser.baudrate = 9600
    ser.port = COMNUM - 1 #starts at 0, so subtract 1
    #ser.port = '/dev/ttyUSB0' #uncomment for linux

    #you must specify a timeout (in seconds) so that the
    # serial port doesn't hang
    ser.timeout = 1
    ser.open() #open the serial port

    # print port open or closed
    if ser.isOpen():
        print 'Open: ' + ser.portstr
#####SETUP################################################
#this is a good spot to run your initializations 
init_serial()

#####MAIN LOOP############################################
while 1:
    #prints what is sent in on the serial port
    temp = raw_input('Type what you want to send, hit enter:\n\r')
    ser.write(temp) #write to the serial port
    bytes = ser.readline() #reads in bytes followed by a newline 
    print 'You sent: ' + bytes #print to the console
    break #jump out of loop 
#hit ctr-c to close python window

First thing you need to do before running this code is to change the COM port number to the one that is attached to your FTDI. The COMNUM variable in the first few lines is where you enter your COM port number. If you are running linux, read the comments above for ser.port.

Now, if you want to send data over the serial port, use: 

ser.write(your_data)

your_data can be one byte or multiple bytes.

If you want to receive data over the serial port, use:

your_data = ser.readline() 

The readline() function will read in a series of bytes terminated with a new line character (i.e. typing something then hitting enter on your keyboard). This works great with GPS, because each GPS NMEA sentence is terminated with a newline. For more information on how to use pyserial, look here.

You might realize that there are three communication channels being used:

  1. ser.write - writes or transmitts data out of the serial port
  2. ser.read - reads or receives data from the serial port
  3. print - prints to the console window

Just be aware that 'print' does not mean print out to the serial port, it prints to the console window. 

Notice, we don't define the type of variables (i.e. int i = 0). This is because Python treats all variables like strings, which makes parsing text/data very easy. If you need to make calculations, you will need to type cast your variables as floats. An example of this is in the GPS tracking section below.

Now try to run the script by typing (remember you need to be working out of the directory of the pythonGPS.py file):

python pythonGPS.py

This script will open a port and display the port number, then wait for you to enter a string followed by the enter key. If the loopback was successful, you should see what you sent and the program should end with a Python prompt >>>. 

To close the window after successfully running, hit Ctrl + c.

Congratulations! You have just made yourself a very simple serial terminal program that can transmit and receive data!

Read a GPS and plot position with Python

Now that we know how to run a python script and open a serial port, there are many things you can do to create computer applications that communicate with embedded hardware. In this example, I am going to show you a program that reads GPS data over a serial port, saves the data to a txt file; then the data is read from the txt file, parsed, and plotted on a map. 

There are a few steps that need to be followed in order for this program to work.Install the modules in the order below.

Install modules

Use the same module installation process as above or find an executable package. 

The above process worked for me on my W7 machine, but I had to do some extra steps to get it to work on Ubuntu. Same might be said about Macs. With Ubuntu, you will need to completely clean your system of numpy, then build the source for numpy and matplotlib separately, so that you don't mess up all of the dependencies. Here is the process I used for Ubuntu.

Once you have all of these modules installed without errors, you can download my project from github and run the program with a pre-loaded map and GPS NMEA data to see how it works:

Or you can proceed and create your own map and GPS NMEA data.

Select a map

Any map image will work, all you need to know are the bottom left and top right coordinates of the image. The map I used was a screen shot from Google Earth. I set placemarks at each corner and noted the latitude and longitude of each corner. Be sure to use decimal degrees coordinates.

Then I cropped the image around the two points using gimp. The more accurate you crop the image the more accurate your tracking will be. Save the image as 'map.png' and keep it to the side for now.

Hardware Setup

The hardware for this example includes a FTDI Basic and any NMEA capable GPS unit.

EM-406 GPS connected to a FTDI Basic

For the connections, all you need to do is power the GPS with the FTDI basic (3.3V or 5V and GND), then connect the TX pin of the GPS to the RX pin on the FTDI Basic.

It is probably best to allow the GPS to get a lock by leaving it powered for a few minutes before running the program. If the GPS doesn't have a lock when you run the program, the maps will not be generated and you will see the raw NMEA data streaming in the console window. If you don't have a GPS connected and you try to run the program, you will get out-of-bound errors from the parsing. You can verify your GPS is working correctly by opening a serial terminal program.  

Run the program

Here is the main GPS tracking program file:

Save the python script into a folder and drop your map.png file along side maps.py. Here is what your program directory should look like if you have a GPS connected:

The nmea.txt file will automatically be created if you have your GPS connected. If you don't have a GPS connected and you already have NMEA sentences to be displayed, create a file called 'nmea.txt' and drop the data into the file.

Now open maps.py, we will need to edit some variables, so that your map image will scale correctly. 

Edit these variables specific to the top right and bottom left corners of your map. Don't forget to use decimal degree units!

#adjust these values based on your location and map, lat and long are in decimal degrees
TRX = -105.1621     #top right longitude
TRY = 40.0868       #top right latitude
BLX = -105.2898     #bottom left longitude
BLY = 40.0010       #bottom left latitude

Run the program by typing:

python gpsmap.py

The program starts by getting some information from the user.

You will select to either run the program with a GPS device connected or you can load your own GPS NMEA sentences into a file called nmea.txt. Since you have your GPS connected, you will select your COM port and be presented with two mapping options: a position map...

...or an altitude map.

Once you open the serial port to your GPS, the nmea.txt file will automatically be created and raw GPS NMEA data, specifically GPGGA sentences, will be logged in a private thread. When you make a map selection, the nmea.txt file is copied into a file called temp.txt, which is parsed for latitude and longitude (or altitude). The temp.txt file is created to parse the data so that we don't corrupt or happen to change the main nmea.txt log file. 

The maps are generated in their own windows with options to save, zoom, and hover your mouse over points to get fine grain x,y coordinates. 

Also, the maps don't refresh automatically, so as your GPS logs data, you will need to close the map window and run the map generation commands to get new data. If you close the entire Python program, the logging to nmea.txt halts. 

This program isn't finished by any means. I found myself constantly wanting to add features and fix bugs. I binged on Python for a weekend, simply because there are so many modules to work with: GUI tools, interfacing to the web, etc. It is seriously addicting. If you have any modifications or suggestions, please feel free to leave them in the comments below. Thanks for reading!


EL Wire Quickstart Guide

$
0
0

Let it Glow

When it comes to creating projects that glow, nothing beats EL wire. LEDs are fun and all, but EL wire is what all the hip kids are using. Whether you just want to light up your bicycle for an evening cruise or you're creating an entire light up costume for Burning Man, EL wire is a great solution. In this tutorial, we will show you how to experiment with EL wire without having to worry about how to connect it, how to control it, and how to power it. With the right parts, EL wire can be very easy to implement into any project.

Requirements

If you have purchased the SparkFun EL Wire Starter Kit, you should have everything you need to follow along. If you have purchased just a spool of EL wire, the following is a list of suggested parts to help get you started. With these parts, using EL wire can be simple for those who have no electronics experience at all and for those who are extremely knowledgeable but are looking for a quick and easy solution to using EL wire. Before we go into further detail, let's take a look at what parts we should have:

That might not seem like much, but that's all you need to get started with any EL project.

How it Works

EL wire (short for electroluminescent wire) is particularly useful for many reasons. First, it is flexible, allowing you to sew it into clothing, attach it to moving parts, and bend it into any shape you desire. Second, it comes in many different colors, shapes, and sizes. You can get it in wire form (the most typical shape), tape form, or in panels. (For the sake of this tutorial, I will refer to all of these forms simply as EL wire.) All of these can be cut to any shape or size to achieve the desired effect. Just be sure to reseal the ends that have been cut. Last, EL wire is great because it is cool to the touch, even after being on for hours. Hence why it is often seen in clothing applications. The EL product does not heat up because, rather than heating an element to achieve an optical phenomenon, the glowing in EL comes from sending an electrical current through the material, which is comprised of semiconducting mixtures. The electrons flowing through the material create photons, which create the glowing that we see as a result.

Many people ask, "Can't I just hook up EL wire to a battery?"The answer is, no! In order to operate EL wire properly, you must use AC (alternating current) power. This is similar to the power that comes out of your outlets at home, though outlets provide much more current than needed for EL wire. That's where the inverter comes in. The battery pack included in the EL Starter Kit is not just a battery holder. It houses an inverter as well. This inverter takes the DC (direct current) power produced by the batteries and turns it into AC. If you listen very closely to the inverter battery pack while it's on, you will hear a slight hum, similar to what you would hear if you stand under power lines or close to transformer boxes. (Note: SparkFun does not condone hanging out around high voltage areas). With that, it's important to mention that, although the AC power coming from the inverter is not enough to hurt or kill you, it is enough to give you a good shock, so be careful when handling EL products that are powered. As, I mentioned above, you can cut EL wire to any length or shape, but you must reseal the ends you cut. I recommend using hot glue or epoxy to seal cut wire. If you don't reseal, you could end up getting a good jolt.

How to Use It

Using the EL Wire Starter Kit is about as simple as it gets. Simply plug in the male JST connector from your EL wire into one of the two female JST connectors on the inverter battery pack. Make sure there is a solid connection between the two. Take the battery cover off by sliding in the direction indicated on the pack. Place your batteries in the battery pack inverter, and put the cover back on. Click the button on the case, and your EL wire should illuminate. Press it again for a slow blinking effect, and press it once more for a fast blink. This inverter pack allows you to connect two EL products of your choice at a time. You can mix and match colors as well as shapes. You coul have a red panel with blue wire, green tape with a pink wire, or two yellow and purple wires. The possibilities are endless!

If you need a little more explanation, you can check out our demonstaration video. In it, the two different inverters that SparkFun carries are breifly described, and you can see how each color looks when it’s illuminated.

It’s as simple as that. However, if you are looking for more of a challenge, fear not. EL projects can become very complex, very quickly. You may have noticed that the effects are somewhat limited on the inverter, and both products hooked up behave the same when plugged into it. Let’s say you want one color to blink while the other stays solid. You could purchase another inverter battery pack, or you could get one of the many boards out there that are specifically designed to work with EL products. SparkFun carries two such boards, the EL Sequencer and the EL Escudo Dos. Both of these boards are designed to handle many EL products hooked up to them at once, and there are many different effects you can create with both. If you’re looking for something a little more, check out the Wrapping it Up section.

Wrapping it Up

You should now know everything you need to know to get started with EL wire and the EL Wire Starter Kit. If you have any questions or comments please drop them in the box below. For more information on EL products, how to control them, and project ideas, please check out the following links:

Thanks for checking out our tutorial!

Stepper Motor Quickstart Guide

$
0
0

Stepping Up to the Challenge

There are a handful of motors to choose from, and sometimes it’s unclear as to which one will be best suited for your particular application. In this tutorial, we will discuss one of these motors, the stepper motor, and when it best to choose a stepper motor over the alternatives. We will also discuss how to use this motor with the EasyDriver Stepper Motor Driver board, one of the simplest driver boards around.

Stepper

Requirements

Here is a list of recommended items needed to follow along:

How it Works

Stepper motors vary from regular DC motors in that, rather than just spinning in one direction or another, they can spin in very precise increments. Imagine a motor on an RC airplane. The motor spins very fast in on direction or another. You can vary the speed with the amount of power given to the motor, but you cannot tell the propeller to stop at a specific position. Now imagine a printer. There are lots of moving parts inside a printer, including motors. One such motor acts as the paper feed, spinning rollers that move the piece of paper as ink is being printed on it. This motor needs to be able to move the paper an exact distance to be able to print the next line of text or next line of an image. There is another motor attached to a threaded rod that moves the print head back on forth. Again, that threaded rod needs to be moved an exact amount to print one letter after another. This is where stepper motors come in handy.

Stepper motors can move an exact amount of degrees (or steps) when told to do so. This gives you total control over the motor, allowing you to move it to an exact location and hold that position. It does so by powering coils inside the motor for very short periods of time. The trade off is that you have to power the motor all the time to keep it in the position that you desire. We won’t go into too much detail here, but you can check out this Wikipedia article on stepper motors for all the nitty-gritty information. All you need to know for now is that, to move a stepper motor, you tell it to move a certain number of steps in one direction or the other, and tell it the speed at which to step in that direction.

There are numerous varieties of stepper motors as well as driver boards with which to control them. The methods described here can be used to infer how to use other motors and drivers not mentioned in this tutorial. However, it is always recommended that you consult the datasheets and guides of the motors and drivers specific to the models you have.

How to Use it

Here we will discuss how to assemble, hook up and control your motor with firmware uploaded to the Arduino.

Assembly

The simplest way to use the EasyDriver is to attach headers to it for easy insertion onto a breadboard. Alternatively, you could solder the wires straight to the board. These instructions will assume you are using the breadboard method.

The first step is to solder straight male headers to the EasyDriver. Very few of the actual pins on the EasyDriver will be used in this example. However, soldering headers on all the broken out pins is recommended to give the board more stability when attached to a breadboard. A simple method for this is to break off the desired amount of headers, place them in the breadboard in the appropriate locations, place the EasyDriver on top, and then solder all the connections.

alt text

alt text

alt text

Hook-up

Once you have all the headers soldered on, it’s time to hook up the EasyDriver to your Arduino. Using the picture below, make all the necessary connections.

alt text

Note: The small stepper motor looks different than the one pictured. It should have a 4-pin connector on the end. This will be attached to the 4-pin male header facing upward (see picture #3 in Assembly). Because of the nature of this particular stepper, you can hook up the connector in either orientation, i.e. either the black wire on the left or the yellow wire on the left. It will work either way. If you are using a different motor, consult its documentation to find out which wires should go where.

IMPORTANT: Stepper motors require more power than can be supplied by the Arduino. In this example we will be powering the Uno with a 12V external supply. Notice that the power input (M+) on the EasyDriver is attached to the Vin pin on the Arduino. This will allow you to power both the Arduino and the motor with the same power supply.

Firmware

Once you have everything hooked up correctly, you can upload firmware to the Arduino. The following is some very simple example code to get you up and running. There are numerous examples online, as well as a Stepper library included with the Arduino IDE. Feel free to play around with this code, changing values to see what happens, and feel free to explore other code.

/*************************
Joel Bartlett
SparkFun Electronics
December 27, 2012

This code controls a stepper motor with the 
EasyDriver board. It spins forwards and backwards
***************************/
int dirpin = 2;
int steppin = 3;

void setup() 
{
pinMode(dirpin, OUTPUT);
pinMode(steppin, OUTPUT);
}
void loop()
{

  int i;

  digitalWrite(dirpin, LOW);     // Set the direction.
  delay(100);


  for (i = 0; i<4000; i++)       // Iterate for 4000 microsteps.
  {
    digitalWrite(steppin, LOW);  // This LOW to HIGH change is what creates the
    digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step.
    delayMicroseconds(500);      // This delay time is close to top speed for this
  }                              // particular motor. Any faster the motor stalls.

  digitalWrite(dirpin, HIGH);    // Change direction.
  delay(100);


  for (i = 0; i<4000; i++)       // Iterate for 4000 microsteps
  {
    digitalWrite(steppin, LOW);  // This LOW to HIGH change is what creates the
    digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step.
    delayMicroseconds(500);      // This delay time is close to top speed for this
  }                              // particular motor. Any faster the motor stalls.

}

Going further

Now that you’ve figured out how to operate your stepper motor at the simplest level, it’s time to take it to the next level. There is a vast amount of information on the web regarding the Easy Driver and stepper motors in general. The best place to look next would be the EasyDriver website. There is also an great tutoral on the bildr website. Another great resource is the EasyDriver Schematic. If you’re curious as to what the other pins on the EasyDriver do, the schematic will give you some insight. Lastly, you can check out one of my projects involving stepper motors, the Arduija. In it, I use stepper motors controlled by EasyDrivers to create an X-Y gantry that moves a Ouija board automatically.

You should be well on your way to adding stepper motors to your next project. If you have any questions, comments or just want to show off your project, drop us a line in the comments below. Happy hacking!

Mono Audio Amplifier Quickstart Guide

$
0
0

This tiny audio amplifier is based on the Texas Instruments TPA2005D1. It can drive an 8-Ohm speaker at up to 1.4 Watts; it won't shake a stadium, but it will provide plenty of volume for your audio projects.

Quickstart

  • Connect your line-level audio input to the IN + and - header.
  • Connect your speaker to the OUT + and - header.
  • Connect 2.5V to 5.5V to the PWR + and - header. (Don't connect anything to the S (shutdown) pin yet.)

Send some audio to the input, and you should hear it on the speaker! If the sound is not loud enough, if you hear buzzing, or if you'd like to add a volume control, read on.

How it works

Traditional audio amplifiers use power transistors to multiply an analog input by a certain gain to produce an analog output. This produces great sound, but the transistors must operate in the intermediate region between on and off. Transistors operate most efficiently when they're fully on or off, and waste a lot of energy as heat when they're run in between.

The class-D amplifier is radically different. At any moment its output transistors are either fully on or fully off, which is very efficient. But this means that the output isn't true audio, it's a digital PWM-like waveform which is mostly on (VCC) for high output values, and mostly off (GND) for low output values.

This PWM signal is clocked at 250kHz, which is much higher than the audio frequencies being encoded (< 20kHz). Because speakers are mechanical devices that can only respond to audio frequencies, the PWM signal is effectively filtered back into the original audio frequencies by the speaker coil itself. All you hear is the music!

Check out the TPA2005D1 datasheet if you'd like to know more about this amplifier.

To use the amplifier

Connect your input source to the IN + and - header. Because the inputs are differential, it technically doesn't matter which direction you connect them, but if one of your inputs is ground or shield, connect that line to the - terminal. (See the Tips below if you're having problems with hum).

Connect your speaker to the OUT + and - header. If you're using one speaker the polarity doesn't matter, but if you'll be using multiple speakers, ensure that you wire them all the same way to avoid phase problems. The speaker can be 4 or 8 Ohms. The maximum output of the amplifier is 1.4 Watts into 8 Ohms. You can drive smaller-wattage speakers with this amplifier, but you should be careful not to turn up the volume too high to avoid damaging the speaker. You can also drive speakers larger than 1.4W at reduced volume. In general, larger speakers will sound much better than smaller speakers; we've had great luck with old automotive speakers.

Connect a power source to the + and - pins. The power source can be from 2.5V to 5.5V, and should be able to source at least 280 milliamps if you want maximum volume. The red LED will illuminate when the board is powered up.

Apply an audio signal to the input, and you should be able to hear it on the speaker. To change the volume, either change the volume of the signal at its source, or add a volume-control potentiometer to the board (instructions below).

Adding a volume control knob

If you wish, you can easily add a 10K volume control potentiometer to this board. The volume control will let you control the volume by reducing the input signal from 100% to 0%. Note that this will not make the amplifier any louder - if you'd like to do that, see changing the gain resistors below. Here's how to add a volume control potentiometer:

Remove the solder from jumper SJ1. This is the small blob of solder within the white brackets on the bottom right of the board. The easiest way to do this is to apply solder wick to the jumper, and heat it with your soldering iron. When you're done, ensure that the two sides are electrically separated from each other.

Now, connect your 10K potentiometer to the three pads on the lower right of the board. The bottom of the board has silkscreen showing the proper connections. You can solder a trimpot with 0.1"-spacing on the pins (such as COM-09806) directly to the board, or you can use wires to connect the board to a larger potentiometer in a chassis, etc.

Note: Potentiometers come in two styles: "linear taper"and "audio (or logarithmic) taper". Audio taper potentiometers have a logarithmic bias that give a more natural feel in audio volume control applications like this one, but linear taper will also work just fine.

How to use the shutdown pin

The SDN* input can be used to turn off the amplifier to save power when it's not being used. When SDN* is disconnected, or connected to a high logic signal (> 2V), the amplifier will function normally. When the SDN* pin is connected to ground or a low logic signal (< 0.8V), the amplifier and LED will turn off. You can use this feature to save power in battery-operated projects.

Changing the gain resistors

The amplifier chip uses two fixed resistors to set the gain, which is how much the input signal will be amplified. On this board, we're using 150K resistors as recommended by the datasheet, for a gain of 2. If you would like the output to be louder, you can install smaller resistors.

The gain equation for this amplifier is 2 * (150K / R). So if you use 100K resistors the gain would be 3, for 50K resistors the gain would be 6, etc. The datasheet states that the smallest value you should use is 15K for a gain of 20, but we've gone down to 3K (gain = 100) with fair results.

The amplifier board has two positions to add your own through-hole resistors. These are within the white rectangles on the top of the board. You do not need to remove the existing surface-mount resistors, just put your through-hole resistors over the top of them. (Leaving the SMD resistors in parallel with the new resistors will slightly reduce the total resistor value, but this is generally not a problem).

For best results, the two gain resistors should be as closely matched as possible. If you have a bag of identical resistors, you might measure them all with a multimeter and pick the two that have the closest resistance.

Tips

The amplifier's output is only designed to be connected to something with a coil (a speaker or magnetic transducer). Since the output is not a true analog signal, you shouldn't expect to use this board as a preamplifier, etc.

The differential inputs of this board are safe to connect directly to floating-ground audio signals such as from the MP3 Shield and MP3 Trigger.

If your audio source and amplifier have different AC power supplies (such as audio coming from a desktop computer), you may hear a loud hum in the output. To fix this, connect a jumper wire between the - side of the audio input and the power supply ground (PWR - header).

Because the amplifier outputs a 250Khz PWM-like signal, it could potentially radiate interference to nearby sensitive circuitry. For this reason, keep the wires between the amplifier and speaker as short as possible.

Questions?

If you have any questions or problems, let us know at techsupport@sparkfun.com and we'll do our best to help you out. We'd also like to hear about the cool projects you're building with our parts!

Have fun!
- Your friends at SparkFun.

Flexiforce Pressure Sensor (25lbs) Quick Start Guide

$
0
0

Introduction

This is a quick how-to explaining everything you need to get started using your Flexiforce Pressure Sensor.  This example uses the 25lb version, but the concepts learned apply to all the Flex sensors.

Flexiforce

Requirements

Necessary hardware to follow this guide:

You'll also need the Arduino IDE for programming.

Hardware

The Flexiforce Pressure Sensor is essentially a variable resistor. When no pressure is applied, the resistance between the two outer leads is incredibly large, probably greater than 10 Mega Ohms (more than my meter can measure). When pressure is applied, the resistance measured between the outer leads lowers until you've reached the max pressure it's intended to measure. In this case that's about 25 lbs of pressure, and the current Flexiforce Pressure sensor I'm using measures about 50K Ohms when given that max amount of pressure.

You can test the range of your sensor using a multimeter. Just attach the two outer leads to the multimeter and set the meter to measure resistance. Then squeeze the sensor and watch the resistance value change.

Now, let's read values with an Arduino. To do this, we create a voltage divider circuit with the Flexiforce sensor and an extra resistor. I picked 1M Ohm in this example because it's about in the middle of the Flexiforce sensor's dynamic range. Many other similar values could work as well.

Connect 5V to one side of the voltage divider, and GND to the other. In the middle, where the Flexiforce sensor and the resistor connect, connect one of the analog-in pins of the Arduino with a jumper wire. In this case I used pin A0. Here is a Fritzing diagram of the setup:

alt text

Fritzing Wiring Diagram

*Note*: The sensor in the image doesn't look exactly the same as the Flexiforce sensor, but very close. The actual Flexiforce sensor has a larger surface area.

Software

Now that you have your circuit wired and ready, it's time to write some very basic Arduino code.  This code is almost exactly the same as Arduino's standard AnalogReadSerial example. Let's take a look to see what it's doing:

 
// Flexiforce quick start example// Reads A0 every 100ms and sends voltage value over serialvoidsetup() 
{
  // Start serial at 9600 baud  Serial.begin(9600); 
}

voidloop() 
{
  // Read the input on analog pin 0:  int sensorValue = analogRead(A0);
  
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):  float voltage = sensorValue * (5.0 / 1023.0);
  
  // Print out the value you read:  Serial.println(voltage);
  
  // Wait 100 milliseconds  delay(100);
}

The code is simply running in a small infinite loop every 100ms, or 10 times a second. In each pass through the loop, it measures the voltage on pin A0 and returns a corresponding value between 0 and 1023. 0 represents ground in this case and 1023 indicates A0 is sitting at 5 Volts. For other numbers in between, we can figure out the voltage by multiplying the measured number by the fraction, 5.0 / 1023.0. We then spit this value back over the Serial port, we can watch the values change in real time.

Go ahead and try. Make sure you have the hardware connected correctly. Program the Arduino, open up the Arduino Serial Monitor (make sure it's using 9600 baud), and watch the voltage values change as you press and release the Flexiforce Pressure Sensor.

Conclusion

Now you know how to use the Flexiforce Pressure Sensor. Believe it or not, there are many different analog sensors where you can use what you learned here and collect data the exact same way. Now it's all up to you to use these types of products however you imagine. If you have any other questions or comments, please drop them in the box below. Enjoy!

LDK Experiment 1: Lighting Up a Basic Circuit

$
0
0

LDK Experiment 1: Lighting Up a Basic Circuit a learn.sparkfun.com tutorial

Introduction

Welcome to your first e-textiles circuit! If you’ve never sewn before or never worked with electronics, you’re in the right place. This is a very simple project, with only two traces and two components to lay down.

Here are a few related tutorials that you might like to browse:

Getting Started

These are all of the parts you’ll need to complete this circuit. If you’re using the LilyPad Design Kit, you’ve already got them all.

You’ll also want to have scissors, fabric, an embroidery hoop, and possibly a needle threader.

Threading your needle

Select a needle to use for this project. The larger the needle, the easier it will be to thread, but the harder it will be to pull through a thick fabric. Balance the needs of your eyesight and hand steadiness with the heaviness of the fabric you’ll be using for this project. If threading a needle is difficult or frustrating for you, you may want to use a needle threader. These are inexpensive and available at any craft store that sells sewing supplies. Cut off a length of conductive thread roughly 2 feet long, and thread it through the needle. Pull it until your needle is in the middle of the length of thread, then pull the two ends together and tie them together into an overhand knot. You should now have a double length of thread about a foot long. In general, I recommend threading your needle with relatively short lengths of thread; try to avoid anything longer than two feet doubled over (four feet before doubling.) Conductive thread is more prone to knots and tangles than traditional thread, and a shorter length will help with that.

alt text

Preparing your fabric

For greatest ease, use an embroidery hoop. These are inexpensive and available at any craft store. The hoop will hold your fabric taut, which helps you to spot and repair potential problems early, as well as preventing the fabric from bunching or gathering while you sew.

alt text

Positive Trace

The positive trace will take power from the power supply to the positive side of the LED.

Start with your battery pack; this will supply power to your circuit. Don’t put the battery in yet; we won’t do that until the end. While you’re sewing, you’re liable to create small short circuits, just by touching across the circuit with your needle or the length of your thread. If the battery is on, these ‘incidental shorts’ will drain it.

Place the battery pack near where you would like to put your LED, making sure that you’ve got one hole with a plus sign and one hole with a negative sign pointed towards the intended LED location. These holes are called ‘pins,’ and you’re looking at the positive and negative pins of your battery pack. When you’ve got your battery pack placed where you’d like it, you can start sewing. Push the needle up through the fabric, bringing it through the positive hole furthest from where you’d like to put your LED. Pull the thread all the way through until the knot you made is firmly against the back of your fabric. Pass the needle back through the top of the fabric to the bottom, just outside of the hole, so that you form a small loop that the edge of the board is trapped in. Pull the thread tight again- your board should now be attached to the fabric by one stitch. This is your first stitch. You’ll repeat this process three times on this pin and on every pin you sew down in this circuit. Go ahead and tack this pin down with two more stitches, and it should look like this:

alt text

Next you need to sew to the second positive pin of the battery pack. You don’t want one big stitch between these two pins. Large stitches are loose, will move around, touching parts of the circuit they’re not meant to touch, and will cause shorts. Instead, put several small stitches between pins, making sure you’ve pulled them tight before you begin to stitch down the next pin. The easiest way to do this is with what’s called a running stitch.

Once you’re at your second positive pin, sew it down with three tight stitches, repeating the process from the first pin.

alt text

From here, it’s time to sew to the positive side of your LED. Continue with the same thread you’ve been using and sew a straight line from the second positive pin to where you would like the positive pin of your LED to be.

Double check that you’ve got the positive LED pin- LEDs are polarized, so if you sew it in backwards, it won’t light up. The good news is that this won’t damage your LED at all; you’ll just have to cut it back out and put it back in the other way.

alt text

Once you’re sure you’ve got the orientation right, you can sew down the positive pin with three stitches, just like you did with both positive battery pack pins.

alt text

This is the end of the positive trace! We’re half done, and you can tie off your thread and cut it. Do not continue around the LED and sew down the next pin!

Negative Trace

The negative trace will return current from the LED to the negative side of the battery pack. This way the current travels in a circle (hence ‘circuit’!), which passes through the LED, lighting it up.

Re-knot your thread and start at the negative pin of the LED, sewing it down with three stitches. As you did on the battery pack, make sure that the knot in your thread is flush against the back of the fabric, and draw all of the stitches tight.

alt text

Sew a line of small stitches from the negative pin of the LED to the closest negative pin of your battery pack, and sew it down with three stitches.

alt text

Almost done! Sew a few small stitches to the second negative pin (this should be the last open pin on your battery pack), and sew it down with three stitches. Tie off again, and cut your thread.

alt text

Take one last look at your circuit. You’re checking for loose or dangling threads or places where the positive and negative traces touch at all. If you find any, you’ll need to correct them. Cutting thread ends short and close to the knot will help.

alt text

This is the moment of truth! Your battery has a smooth side with a + on it and a textured side. Slide it into the battery holder, + side up, textured side down. Your LED should immediately light up! There’s no switch or button on this circuit, so you’ll have to put the battery in to turn it on and take it out to turn it off. Congratulations on your first e-textiles circuit!

alt text

Going Further

Ready to do more? Here are some circuits you can apply this knowledge to:


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

Light

$
0
0

Light a learn.sparkfun.com tutorial

Introduction

Manipulation of light is a very useful skill for any electronics tinkerer. From illumination to infrared data transmission, light bridges the electronic and the physical in myriad useful ways.

Wavelength

The key defining feature of a beam of light is its wavelength. Light travels through space as a wave, and the distance between two wave peaks is the wavelength of that beam of light. In human terms, the wavelength is what determines the color of a light beam.

alt text

Wavelength is usually denoted by the greek character λ (pronounced “lamb-da”) (Image by Wikipedia user dicklyon).

Because nothing in physics can be simple, a light beam also behaves as a stream of particles, or photons (masochists can refer to this article on the wave/particle duality of light). Shorter wavelength light has more energy per photon.

Intensity

The other characteristic of a beam of light is its intensity. Radiant intensity is measured by the rate at which energy intersects the surface of the sphere bounded by that circle at the top of the ice cream cone, in watts per steradian. To understand this, imagine a sphere with a teeny, tiny star in the center. Light is spreading out from the star in all directions equally. Now, add an ice cream cone with its point in the center of the star, extending to the surface of the sphere. The angle at the bottom of the cone is one radian (there are 2π radians in a circle; one radian is approximately 57.3°). The area defined by this imaginary ice cream cone is called a steradian.

alt text

Graphical depiction of a steradian. A beam of light’s radiant intensity is described by the wattage of the light beam divided by this surface area (Image courtesy of wikimedia commons.)

Visible light versus invisible light

When we talk about light, we generally mean visible light—the wonderful stuff of rainbows and sunshine. Light, however, spans a very, very wide range of wavelengths. This is referred to as the electromagnetic spectrum.

The electromagnetic spectrum

The full spectrum of electromagnetic radiation. Visible light is a very small part! Image created by Philip Ronan).

At one end, there are gamma rays and X-rays, which are nasty, high energy ionizing electromagnetic radiation that are fundamentally incompatible with life. At the other end, very low-frequency, long-wavelength radio waves carry information across vast distances, yielding glimpses into the very origins of the universe itself.

In this article, we’ll be sticking to visible light and the areas closest to it: infrared and ultraviolet. From ultraviolet through far infrared, light behaves pretty similarly to what we’re used to seeing with visible light: shadows are cast, lenses can focus it, it can be diffused by, say, a white sheet of paper, etc. Once you move out into the longer and shorter wavelengths, things start to get weird, and we’ll reserve discussion of that for another lesson.

We’re going to discuss light in three different groups: ultraviolet, visible, and infrared. Ultraviolet light is light which has a wavelength just slightly shorter than visible light; infrared, just slightly longer. Of the three groups, visible and infrared are somewhat more useful and common in electronics, and we’ll give them correspondingly more time.

Tutorial thumbnail courtesy D-Kuru/Wikimedia Commons.

Ultraviolet Light

Ultraviolet light is light between 10nm and 400nm, which places it between X-rays and visible light. Ultraviolet can be very harmful to life forms—you’re probably most familiar with its effects in the form of sunburn.

Ultraviolet spectrum

Ultraviolet-A

UVA (315nm to 400nm wavelength) is the lowest energy band of ultraviolet light. It is nearly visible to humans, and many insects, and even some birds, can see into this light band. White fluorescent bulbs and white LEDs work by exposing a material to UVA light, which absorbs the UVA photons and emits photons in the visible spectrum, appearing white to us.

UVA is also often used to detect counterfeit documents; as a hedge against counterfeiting, many documents (passports, driver’s licenses, and bank notes, to name a few) will include a watermark that glows under UVA radiation. Blacklight posters are another example of things which react to UVA light, and bleach, soap, and many biological materials will also glow when exposed to UVA.

alt text

Anti-counterfeiting features in a US $20 bill revealed by a 400nm UVA LED.

Most of the UVA light in a sunbeam reaches the earth’s surface.

Ultraviolet-B

UVB (280nm to 315nm) is a higher energy level light than UVA. It is found in sunlight, and is responsible not only for the skin damage that causes sunburn and skin cancer but also the synthesis of Vitamin D in the human body. It is also produced by welding torches; even brief exposure to the flare from a welding torch, and even at a reasonable distance, can cause serious eye damage if the viewer is not protected.

Welding torch flare

Welding torches create a lot of UVB and UVC light. Welders must minimize exposure to avoid sunburn and eye damage (Image courtesy wikipedia).

UVB light is fairly well blocked by normal window glass; this is why hanging an arm out of an open car window can result in a sunburn affecting that arm only. Richard Feynman (Nobel laureate and noted bongo musician) observed the Trinity nuclear test explosion using the windscreen of a pickup truck to protect himself from the ultraviolet radiation emitted by the blast.

Only about 10% of the UVB light emitted by the sun reaches earth’s surface; the other 90% is absorbed by the atmosphere (primarily the ozone layer).

Ultraviolet-C

UVC ( 100nm to 280nm) tends to be the limit of the interesting UV light for us. Almost none of the sun’s UVC reaches the earth’s surface; the atmosphere does a very effective job of screening it away.

In the bad old days, before EEPROM memory and flash memory (which can be erased and rewritten electronically), the only non-volatile, non-magnetic means of electronic data storage was the EPROM. Once an EPROM was written, it could only be erased by being exposed to a strong source of UVC light for 20-30 minutes. For a hobbyist, that’s a long time to wait to find out if the changes you made to your code fixed a bug!

UV-erasable microchip

An old UV-erasable PIC16C765 microcontroller. The window over the die is made of quartz, because normal glass is not transparent to ultraviolet light.

Visible Light

Visible light is light in the range of (approximately) 380nm to 740nm. This can vary; some people’s eyes will be able to detect light of lower or higher wavelengths than this, but in general, most humans' eyes are sensitive to this region.

Visible spectrum of light

The Human Eye

There are two peculiarities in the way the human eye perceives light: our eyes are sensitive to different wavelengths in different amounts, and our eyes perceive light intensity logarithmically rather than linearly.

Perception of Color

As you can see on this chart, our eyes pick up different wavelengths of light with different efficiency, mixing the perceived intensities to yield what we refer to as a “color”. Furthermore, you can also see that at low light levels, our perception of color becomes skewed.

Luminosity curves for the human eye

Scotopic and photopic luminosity curves for the human eye. These curves show the perceived intensity of a light source by wavelength, assuming the radiant intensity of the light sources are all equal.

Because of this, a special unit of light intensity, the candela, was developed. The candela weights the intensity of a light source according to its color; a human eye will perceive a one-candela light source to be of similar brightness to another one-candela light source, regardless of wavelength. LED brightness is typically given in terms of millicandelas (mcd), and a great demonstration of the perceived intensity difference across colors can be seen when considering the intensity of an RGB LED such as this one: 800mcd for the blue, 4000mcd for the green, and 900mcd for the red. I’ve marked the wavelengths of those three colors (467.5nm, 520nm, and 625nm) on the chart below.

RGB LED marked on photopic curve

The relative intensities of the blue, green, and red LEDs in a tricolor LED have been marked on this photopic curve. Compare the relative intensities (.15 for the red, .7 for the green, and .3 for the blue) to the millicandela ratings for the three colors given by the LEDs datasheet (800mcd, 4000mcd, and 900mcd). The ratios aren’t exact, the colors with higher millicandela ratings are also higher on the curve.

The eye can be fooled into detecting wavelengths of light that are not present by mixing different wavelengths; it is by this principle which most color displays work. Only three colors (some form of red, green, and blue) are actually available; by mixing those three light colors at different intensities, the vast majority of natural colors can be simulated (at least, as far as our eyes are concerned).

Color mixing diagram

Color mixing of red, green and blue light sources. By tweaking the light levels, a vast number of other light colors can be simulated.

Perception of Intensity

We naturally tend to think of light as a linear phenomenon. Given two light sources, we may reasonably perceive one to be twice as bright as the other. We’ve already seen how this can be affected by color; now let’s consider the intensity of a light of a single color relative to our perception of it. The intensity of an LED varies linearly with the current being used to drive it.

LED current versus intensity

Actual data gathered by pointing an LED at a photodiode and linearly increasing the LED drive current linearly from 0-25mA.

Let’s do a little experiment. If you have an Arduino, breadboard, resistor, LED, and a pushbutton, whip up this circuit, download the code, and throw the code onto the Arduino.

alt text

This circuit is pretty simple: push the button once, and the LED will turn on. Push it and hold it, and the LED will start to get brighter. Release it, and the LED will stop getting brighter and the Arduino will print out over the serial port how much brighter the LED was when you stopped it getting brighter than it was when it started. Try to stop the LED when it is twice as bright as it was when it started.

Why is it so hard? The light output of an LED is linear, so doubling the current through the LED doubles the amount of light energy it is emitting. However, your eye does not respond in a linear fashion, it responds logarithmically. The reason for this is simple: our eyes need to provide us with useful information across a full range of lighting conditions, from starlight to daylight. On a cloudless night under a full moon, the light intensity is only 1/440,000th that of a sunny day, yet our eyes must function well at both of those extremes and everywhere in between! That makes judging a linear light source’s relative brightness very difficult.

Color blindness

Color blindness is not, as the name would suggest, a simple inability to perceive color. There are in fact many varieties of color blindness; the most common, red-green color blindness, affects almost 10% of the male population to some degree.

Color blindness can be diagnosed by a simple test, where the subject is asked to identify patterns or symbols created from dots of a different color against a background of similarly-sized dots.

Ishihara test plate

Test plate from the Ishihara color blindness test. A person with normal color vision will see the number 74; color blind persons may see the number 21 or no number at all, depending on the type of deficiency present.

As a kindness to those of us with color blindness, please try not to use color to convey information. Good examples of bad design include LEDs which change color to signify a condition (green means “okay”, red means “failure”), maps using a range of colors to connect a numerical value to a region, and text colors other than white-on-black or black-on-white.

Infrared Light

Infrared light is light with a longer wavelength than visible light, but a shorter wavelength than microwave. It has arbitrarily been chosen to start at 700nm and stop at 1mm (1,000,000nm), making it a far larger segment of the spectrum than ultraviolet or visible light. Something like 55% of the light energy reaching the earth’s surface from the sun is infrared.

Infrared light spectrum

Near-Infrared

Near-infrared is a region of great interest in electronics: this is the region within which infrared remote controls, object sensors, and distance detectors operate. It is just barely above the visible range, and is extremely easy to both create and detect with solid-state technologies.

IR Emitter/Detector Pair

SparkFun’s matched infrared emitter/detector pair. Inexpensive, but extremely susceptible to interference from both visible and infrared light in the environment.

The near-infrared band extends up to 1400nm. Common emitter wavelengths are 850nm and 950nm. There is a tremendous amount of near-infrared light surrounding us at all times; the potential for interference with infrared signaling and sensing is great. Most infrared signaling systems (such as infrared remote controls solve this by modulating the beam at a fixed frequency, rather than attempting to filter out light which is not of the desired wavelength.

alt text

Modulated IR receiver module. This small IC looks for infrared light being pulsed at 38kHz and attempts to interpret it as a data signal.

Near-infrared is well detected by digital cameras, too. So well detected, in fact, that most digital cameras have a physical filter to block out infrared wavelengths. This filter can be removed, allowing greater sensitivity in the infrared range. A simple filter which allows infrared light to pass but blocks visible light can be created out of 35mm film negatives; the tag end of the film roll which has no pictures on it is perfect for this.

IR image vs. Visible image

Two pictures of the same scene. The image on the left was taken in a darkened room with a cheap webcam that has had its infrared filter removed and replaced by film negatives, and the image on the right was taken with a standard point-and-shoot camera.

Long-wavelength Infrared

Long-wavelength infrared is light in the 8000nm-15000nm range. This is the thermal imaging zone, where all of those amazing false-color images detailing the relative temperature of things come from.

False-color infrared image

The same scene in the visible spectrum and the long-wavelength infrared. Notice that the plastic bag is opaque to visible light but nearly transparent to infrared (courtesy NASA Spitzer Infrared Telescope team).

It’s a common mistake for people to misunderstand the difference between near-infrared imaging and long-wave infrared imaging. Near-infrared imaging is pretty easy to achieve—standard CMOS and CCD imaging chips can easily detect light in the near-infrared region. Long-wave IR requires special sensors, since the light beam has a wavelength 1000 times longer than near-IR. This requires a correspondingly larger geometry in the sensor elements.

Long-wave IR temp sensor

A long-wave IR temperature sensor. The longer wavelength requires a larger sensing region than visible or near-IR applications.

Another increasingly familiar use of this region is laser etching and cutting. Most laser cutters rely on a CO2 laser tubes to generate the laser beam at a wavelength of 10640nm.

Going Further

Light is a fascinating and complex thing, and we only scratched the surface in this tutorial. If you find yourself wanting to learn more, here are some excellent resources to check out:


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

Binary

$
0
0

Binary a learn.sparkfun.com tutorial

ABC's of 1's and 0's

Prepare to have your perception of reality shattered. Everything you ever thought you knew about something so simple as numbers is going to change. All your life you thought having 100 somethings meant having this many:

100 Somethings

When, really, it only meant having this many:

4 Somethings

No, Rod Serling’s not about to cross into the frame, and you haven’t swallowed any red pills. You’ve entered the binary zone and have just encountered base numbering systems.

Number systems and bases

Number systems are the methods we use to represent numbers. Since grade school, we’ve all been mostly operating within the comfy confines of a base-10 number system, but there are many others. Base-2, base-8, base-16, base-20, base…you get the point. There are an infinite variety of base-number systems out there, but only a few are especially important to electrical engineering.

The really popular number systems even have their own name. Base-10, for example, is commonly referred to as the decimal number system. Base-2, which we’re here to talk about today, also goes by the moniker of binary. Another popular numeral system, base-16, is called hexadecimal.

The base of a number is often represented by a subscripted integer trailing a value. So in the introduction above, the first image would actually be 10010 somethings while the second image would be 1002 somethings. This is a handy way to specify a number’s base when there’s ever any possibility of ambiguity.

Why binary?

Why binary you ask? Well, why decimal? We’ve been using decimal forever and have mostly taken for granted the reason we settled on the base-10 number system for our everyday number needs. Maybe it’s because we have 10 fingers, or maybe it’s just because the Romans forced it upon their ancient subjugates. Regardless of what lead to it, tricks we’ve learned along the way have solidified base-10’s place in our heart; everyone can count by 10’s. We even round large numbers to the nearest multiple of 10. We’re obsessed with 10!

Computers and electronics are rather limited in the finger-and-toe department. At the lowest level, they really only have two ways to represent the state of anything: ON or OFF, high or low, 1 or 0. And so, almost all electronics rely on a base-2 number system to store, manipulate, and math numbers.

The heavy reliance electronics place on binary numbers means it’s important to know how the base-2 number system works. You’ll commonly encounter binary, or its cousins, like hexadecimal, all over computer programs. Analysis of Digital logic circuits and other very low-level electronics also requires heavy use of binary.

In this tutorial, you’ll find that anything you can do to a decimal number can also be done to a binary number. Some operations may be even easier to do on a binary number (though others can be more painful). We’ll cover all of that and more in this tutorial.

Concepts in this tutorial

We’re reaching pretty deep into the concepts bin. A lot of this tutorial builds on mathematical concepts like addition, multiplication, division (including remainders) and exponents.

No previous knowledge of electronics is required, but we do observe how binary is used in Arduino programming, and knowing something about data types could come in handy. In addition, knowledge of digital logic will help to supplement all of this binary business.

Counting and Converting

The base of each number system is also called the radix. The radix of a decimal number is ten, and the radix of binary is two. The radix determines how many different symbols are required in order to flesh out a number system. In our decimal number system we’ve got 10 numeral representations for values between nothing and ten somethings: 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. Each of those symbols represents a very specific, standardized value.

In binary we’re only allowed two symbols: 0 and 1. But using those two symbols we can create any number that a decimal system can.

Counting in binary

You can count in decimal endlessly, even in your sleep, but how would you count in binary? Zero and one in base-two should look pretty familiar: 0 and 1. From there things get decidedly binary.

Remember that we’ve only got those two digits, so as we do in decimal, when we run out of symbols we’ve got to shift one column to the left, add a 1, and turn all of the digits to right to 0. So after 1 we get 10, then 11, then 100. Let’s start counting…

DecimalBinary...DecimalBinary
001610000
111710001
2101810010
3111910011
41002010100
51012110101
61102210110
71112310111
810002411000
910012511001
1010102611010
1110112711011
1211002811100
1311012911101
1411103011110
1511113111111

Does that start to paint the picture? Let’s examine how we might convert from those binary numbers to decimal.

Converting binary to decimal

There’s no one way to convert binary-to-decimal. We’ll outline two methods below, the more “mathy” method, and another that’s more visual. We’ll cover both, but if the first uses too much ugly terminology skip down to the second.

Method 1

There’s a handy function we can use to convert any binary number to decimal:

Binary to decimal conversion equation

There are four important elements to that equation:

  • an, an-1, a1, etc., are the digits of a number. These are the 0’s and 1’s you’re familiar with, but in binary they can only be 0 or 1.
  • The position of a digit is also important to observe. The position starts at 0, on the right-most digit; this 1 or 0 is the least-significant. Every digit you move to the left increases in significance, and also increases the position by 1.
  • The length of a binary number is given by the value of n, actually it’s n+1. For example, a binary number like 101 has a length of 3, something larger, like 10011110 has a length of 8.
  • Each digit is multiplied by a weight: the 2n, 2n-1, 21, etc. The right-most weight – 20 equates to 1, move one digit to the right and the weight becomes 2, then 4, 8, 16, 32, 64, 128, 256,… and on and on. Powers of two are of great importance to binary, they quickly become very familiar.

Let’s get rid of those n’s and exponents, and carry out our binary positional notation equation out eight positions:

Binary conversion with exponents multiplied out

Taking that further, let’s plug in some values for the digits. What if you had a binary number like: 10011011? That would mean an values of:

Mapping digits to values

For the sake of this tutorial, assume that the right-most value is always the least-significant. The least-significant digit in a number is the digit that has the smallest influence on a number’s ultimate value. The significance of the digits is arbitrary – part of a convention called endianness. A binary number can be either big-endian, where the most-significant digit is the left-most, or little-endian which we’ll use in this tutorial (and you’ll usually see binary numbers written this way).

Now, plug those digits into our binary to decimal equation. Because our number is little-endian the least-significant value should be multiplied by the smallest weight.

  1 * 27 + 0 * 26 + 0 * 25 + 1 * 24 + 1 * 23 + 0 * 22 + 1 * 21 + 1 * 20

And we can simplify it down to find our decimal number:

= 1 * 128 + 0 * 64 + 0 * 32 + 1 * 16 + 1 * 8 + 0 * 4 + 1 * 2 + 1 * 1
= 128 + 16 + 8  + 2 + 1
= 155

You’ll quickly notice that it takes many more digits to represent a number in binary than it does in decimal, but it’s all done with just two digits!

Method 2

Another, more visual way to convert binary numbers to decimal is to begin by sorting each 1 and 0 into a bin. Each bin has a successive power of two weight to it, the 1, 2, 4, 8, 16,… we’re used to. Carrying it out eight places would look something like this:

1286432168421

So, if we sorted our 10011011 binary number into those bins, it’d look like this:

1286432168421
10011011

For every bin that has a binary 0 value in it, just cross out and remove it.

1286432168421
10011011

And then add up any remaining weights to get your number!

Visual method for converting binary to decimal

Converting from decimal to binary

Just like going from binary to decimal, there’s more than one way to convert decimal to binary. The first uses division and remainders, and the second uses subtraction. Try both, or stick to one you’re comfortable with!

Method 1

It isn’t quite as simple to convert a decimal number to binary. This conversion requires repeatedly dividing the decimal number by 2, until you’ve reduced it to zero. Every time you divide the remainder of the division becomes a digit in the binary number you’re creating.

Don’t remember how to do remainders? If it’s been a while, remember that, since we’re dividing by two, if the dividend is even, the remainder will be 0; an odd dividend means a remainder of 1.

For example, to convert 155 to binary you’d go through this process:

155 ÷ 2 = 77 R 1 (That’s the right-most digit, 1st position)
 77 ÷ 2 = 38 R 1 (2nd position)
 38 ÷ 2 = 19 R 0 (3rd position)
 19 ÷ 2 =  9 R 1
  9 ÷ 2 =  4 R 1
  4 ÷ 2 =  2 R 0
  2 ÷ 2 =  1 R 0
  1 ÷ 2 =  0 R 1 (8th position)

The first remainder is the least-significant (right-most) digit, so read from top-to-bottom to flesh out our binary number right-to-left: 10011011. Match it up to the example above…that’s a bingo!

Method 2

If dividing and finding remainders isn’t your thing, there may be an easier method for converting decimal to binary. Start by finding the largest power of two that’s still smaller than your decimal number, and subtract it from the decimal. Then, continue to subtract by the largest possible power of two until you get to zero. Every weight-position that was subtracted, gets a binary 1 digit; digits that weren’t subtracted get a 0.

Continuing with our example, 155 can be subtracted by 128, producing 27:

155 - 128 = 27
1286432168421
1

Our new number, 27, can’t be subtracted by either 64 or 32. Both of those positions get a 0. We can subtract by 16, producing 11.

27 - 16 = 11
1286432168421
1001

And 8 subtracts from 11, producing 3. After that, no such luck with 4.

11 - 8 = 3
1286432168421
100110

Our 3 can be subtracted by 2, producing 1. And finally, the 1 subtracts by 1 to make 0.

3 - 2 = 1
1 - 1 = 0
1286432168421
10011011

We’ve got a binary number!

Visually converting decimal to binary

Conversion calculators

Fortunately, there are tons of binary-to-decimal and vice-versa calculators out there. You shouldn’t often need to resort to long-hand conversion.

Here! Plug some numbers into these boxes, and the other should magically change.

Binary:
Decimal:

Make sure you only put 1’s or 0’s in the binary box, and 0-9 in the decimal one. Have fun!

Bits, Nibbles, and Bytes

In discussing the make of a binary number, we briefly covered the length of the number. The length of a binary number is the amount of 1’s and 0’s it has.

Common binary number lengths

Binary values are often grouped into a common length of 1’s and 0’s, this number of digits is called the length of a number. Common bit-lengths of binary numbers include bits, nibbles, and bytes (hungry yet?). Each 1 or 0 in a binary number is called a bit. From there, a group of 4 bits is called a nibble, and 8-bits makes a byte.

Bytes are a pretty common buzzword when working in binary. Processors are all built to work with a set length of bits, which is usually this length is a multiple of a byte: 8, 16, 32, 64, etc.

To sum it up:

LengthNameExample
1Bit0
4Nibble1011
8Byte10110101

Word is another length buzzword that gets thrown out from time-to-time. Word is much less yummy sounding and much more ambiguous. The length of a word is usually dependent on the architecture of a processor. It could be 16-bits, 32, 64, or even more.

Padding with leading zeros

You might see binary values represented in bytes (or more), even if making a number 8-bits-long requires adding leading zeros. Leading zeros are one or more 0’s added to the left of the most-significant 1-bit in a number. You usually don’t see leading zeros in a decimal number: 007 doesn’t tell you any more about the value of a number 7 (it might say something else).

Leading zeros aren’t required on binary values, but they do help present information about the bit-length of a number. For example, you may see the number 1 printed as 00000001, just to tell you we’re working within the realm of a byte. Both numbers represent the same value, however, the number with seven 0’s in front adds information about the bit-length of a value.

Bitwise Operators

There are a number of ways to manipulate binary values. Just as you can with decimal numbers, you can perform standard mathematical operations – addition, subtraction, multiplication, division – on binary values (which we’ll cover on the next page). You can also manipulate individual bits of a binary value using bitwise operators.

Bitwise operators perform functions bit-by-bit on either one or two full binary numbers. They make use of boolean logic operating on a group of binary symbols. These bitwise operators are widely used throughout both electronics and programming.

Complement (NOT)

The complement of a binary value is like finding the exact opposite of everything about it. The complement function looks at a number and turns every 1 into a 0 and every 0 becomes a 1. The complement operator is also called NOT.

For example to find the complement of 10110101:

NOT 10110101 (decimal 181)
    -------- =
    01001010 (decimal 74)

NOT is the only bitwise operator which only operates on a single binary value.

OR

OR takes two numbers and produces the union of them. Here’s the process to OR two binary numbers together: line up each number so the bits match up, then compare each of their bits that share a position. For each bit comparison, if either or both bits are 1, the value of the result at that bit-position is 1. If both values have a 0 at that position, the result also gets a 0 at that position.

The four possible OR combinations, and their outcome are:

  • 0 OR 0 = 0
  • 0 OR 1 = 1
  • 1 OR 0 = 1
  • 1 OR 1 = 1

For example to find the 10011010 OR 01000110, line up each of the numbers bit-by-bit. If either or both numbers has a 1 in a column, the result value has a 1 there too:

   10011010
OR 01000110
   -------- =
   11011110

Think of the OR operation as binary addition, without a carry-over. 0 plus 0 is 0, but 1 plus anything will be 1.

AND

AND takes two numbers and produces the conjunction of them. AND will only produce a 1 if both of the values it’s operating on are also 1.

The process of AND'ing two binary values together is similar to that of OR. Line up each number so the bits match up, then compare each of their bits that share a position. For each bit comparison, if either or both bits are 0, the value of the result at that bit-position is 0. If both values have a 1 at that position, the result also gets a 1 at that position.

The four possible AND combinations, and their outcome are:

  • 0 OR 0 = 0
  • 0 OR 1 = 0
  • 1 OR 0 = 0
  • 1 OR 1 = 1

For example, to find the value of 10011010 AND 01000110, start by lining up each value. The result of each bit-position will only be 1 if both bits in that column are also 1.

    10011010
AND 01000110
    -------- =
    00000010

Think of AND as kind of like multiplication. Whenever you multiply by 0 the result will also be 0.

XOR

XOR is the exclusive OR. XOR behaves like regular OR, except it’ll only produce a 1 if either one or the other numbers has a 1 in that bit-position.

The four possible XOR combinations, and their outcome are:

  • 0 OR 0 = 0
  • 0 OR 1 = 1
  • 1 OR 0 = 1
  • 1 OR 1 = 0

For example, to find the result of 10011010 XOR 01000110:

    10011010
XOR 01000110
    -------- =
    11011100

Notice the 2nd bit, a 0 resulting from two 1’s XOR’ed together.

Bit shifts

Bit shifts aren’t necessarily a bitwise operator like those listed above, but they are a handy tool in manipulating a single binary value.

There are two components to a bit shift – the direction and the amount of bits to shift. You can shift a number either to the left or right, and you can shift by one bit or many bits.

When shifting to the right, one or more of the least-significant bits (on the right-side of the number) just get cut off, shifted into the infinite nothing. Leading zeros can be added to keep the bit-length the same.

For example, shifting 10011010 to the right two bits:

RIGHT-SHIFT-2 10011010 (decimal 154)
              -------- =
              00100110 (decimal 38)

Shifting to the left adds pushes all of the bits toward the most-significant side (the left-side) of the number. For each shift, a zero is added in the least-significant-bit position.

For example, shifting 10011010 to the left one bit:

LEFT-SHIFT-1 10011010 (decimal 154)
             -------- =
            100110100 (decimal 308)

That simple bit shift actually performs a relatively complicated mathematical function. Shifts to the left n bits multiplies a number by 2n (see how the last example multiplied the input by two?), while a shift n bits to the right will do an integer divide by 2n. Shifting to the right to divide can get weird – any fractions produced by the shift division will be chopped off, which is why 154 shifted right twice equals 38 instead of 154/4=38.5. Bit shifts can be a powerfully fast way to divide or multiply by 2, 4, 8, etc.


These bitwise operators provide us most of the tools necessary to do standard mathematical operations on binary numbers.

Binary in Programming

At their very lowest-level, binary is what drives all electronics. As such, encountering binary in computer programming is inevitable.

Representing binary values in a program

In Arduino, and most other programming languages, a binary number can be represented by a 0b preceding the binary number. Without that 0b the number will just be a decimal number.

For example, these two numbers in code would produce two very different values:

a = 0b01101010; // Decimal 106
c = 01101010;  // Decimal 1,101,010 - no 0b prefix means decimal

Bitwise operators in programming

Each of the bitwise operators discussed a few pages ago can be performed in a programming language.

AND bitwise operator

To AND two different binary values, use the ampersand, &, operator. For example:

x = 0b10011010 & 0b01000110;
// x would equal 0b00000010

AND’ing a binary value is useful if you need to apply a bit-mask to a value, or check if a specific bit in a binary number is 1.

The AND bitwise operator shouldn’t be confused with the AND conditional operation, which uses the double-ampersand (&&) and produces a true or false based on the input of multiple logic statements.

OR bitwise operator

The OR bitwise operator is the pipe| (shift+\, the key below backspace). For example:

y = 0b10011010 | 0b01000110;
// y would equal 0b11011110

OR’ing a binary value is useful if you want to set one or more bits in a number to be 1.

As with AND, make sure you don’t switch up the OR bitwise operator with the OR conditional operator – the double-pipe (||).

NOT bitwise operator

The bitwise NOT operator is the tilde~ (shift+`, the key above tab). As an example:

z = ~(0b10100110);
// z would equal 0b01011001

XOR bitwise operator

To XOR two values use the carrot (^) between them:

r = 0b10011010 ^ 0b01000110;
// r would equal 0b11011100

XOR is useful for checking if bits are different, because it’ll only result in a 1 if it operates on both a 0 or 1.

Shifting left and right

To shift a binary number left or right n bits, use the <<n or >>n operators. A couple examples:

i = 0b10100101 << 4;    // Shift i left 4 bits
// i would equal 0b101001010000
j = 0b10010010 >> 2;    // Shift j right 2 bits
// j would equal 0b00100100

Shift’s are an especially efficient way to multiply or divide by powers of two. In the example above, shifting four units to the left multiplies that value by 24 (16). The second example, shifting two bits to the right, would divide that number by 22 (4).

Further Reading

Binary is the building block of all computations, calculations, and operations in electronics. So there are many places to go from here.

Are you interested in learning more about binary, and other important numeral systems?

Now that you can convert between decimal and binary, you can apply that knowledge to understanding how characters are encoded universally:

Or you can apply your shiny new knowledge to low-level circuits and IC’s:


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


Voltage Dividers

$
0
0

Voltage Dividers a learn.sparkfun.com tutorial

Introduction

A voltage divider is a simple circuit which turns a large voltage into a smaller one. Using just two series resistors and an input voltage, we can create an output voltage that is a fraction of the input. Voltage dividers are one of the most fundamental circuits in electronics. If learning Ohm’s law was like being introduced to the ABC’s, learning about voltage dividers would be like learning how to spell cat.

In this tutorial we’ll examine

  • What a voltage divider circuit looks like.
  • How the output voltage depends on the input voltage and divider resistors.
  • How voltage dividers behave in the real-world.
  • Real-life voltage divider applications.

You should know

This tutorial builds on basic electronics knowledge. If you haven’t already, consider reading these tutorials:

Ideal Voltage Divider

There are two important parts to the voltage divider: the circuit and the equation.

The circuit

A voltage divider involves applying a voltage source across a series of two resistors. You may see it drawn a few different ways, but they should always essentially be the same circuit.

Examples of voltage divider schematics

Examples of voltage divider schematics. Shorthand, longhand, resistors at same/different angles, etc.

We’ll call the resistor closest to the input voltage (Vin) R1, and the resistor closest to ground R2. The voltage drop across R2 is called Vout, that’s the divided voltage our circuit exists to make.

That’s all there is to the circuit! Vout is our divided voltage. That’s what’ll end up being a fraction of the input voltage.

The equation

The voltage divider equation assumes that you know three values of the above circuit: the input voltage (Vin), and both resistor values (R1 and R2). Given those values, we can use this equation to find the output voltage (Vout):

Vout = Vin * (R1 / (R1 + R2))

Memorize that equation!

This equation states that the output voltage is directly proportional to the input voltage and the ratio of R1 and R2. If you’d like to find out where this comes from, check out this section where the equaion is derived. But for now, just write it down and remember it!

Calculator

Have some fun experimenting with inputs and outputs to the voltage divider equation! Below, you can plug in numbers for Vin and both resistors and see what kind of output voltage they produce.

Vin =  V
R1 =  &ohm;
R2 =  &ohm;
Vout =  V

Or, if you adjust Vout, you’ll see what resistance value at R2 is required (given a Vin and R1).

Simplifications

There are a few generalizations that are good to keep in mind when using voltage dividers. These are simplifications that make evaluating a voltage dividing circuit just a little easier.

Vout = Vin/2 if R1=R2

First, if R2 and R1 are equal then the output voltage is half that of the input. This is true regardless of the resistors' values.

Vout=Vin if R2>>R1

If R2 is much larger (at least an order of magnitude) than R1, then the output voltage will be very close to the input. There will be very little voltage across R1.

Vout=0 if R2<<R1

Conversely, if R2 is much larger than R1, the output voltage will be tiny compared to the input. Most of the input voltage will be across R1

Applications

Voltage dividers have tons of applications, they are among the most common of circuits electrical engineers use. Here are just a few of the many places you’ll find voltage dividers.

Potentiometers

A potentiometer is a variable resistor which can be used to create an adjustable voltage divider.

A variety of pots

A smattering of potentiometers. From top-left, clockwise: a standard 10k trimpot, 2-axis joystick, softpot, slide pot, classic right-angle, and a breadboard friendly 10k trimpot.

Internal to the pot is a single resistor and a wiper, which cuts the resistor in two and moves to adjust the ratio between both halves. Externally there are usually three pins: two pins connect to each end of the resistor, while the third connects to the pot’s wiper.

Schematic symbol for a potentiometer

A potentiometer schematic symbol. Pins 1 and 3 are the resistor ends. Pin 2 connects to the wiper.

If the outside pins connect to a voltage source (one to ground, the other to Vin), the output (Vout at the middle pin will mimic a voltage divider. Turn the pot all the way in one direction, and the voltage may be zero; turned to the other side the output voltage approaches the input; a wiper in the middle position means the output voltage will be half of the input.

Potentiometers come in a variety of packages, and have many applications of their own. They may be used to create a reference voltage, adjust radio stations, measure position on a joystick, or in tons of other applications which require a variable input voltage.

Reading resistive sensors

Many sensors in the real world are simple resistive devices. A photocell is a variable resistor, which produces a resistance proportional to the amount of light it senses. Other devices like flex sensors, force-sensitive resistors, and thermistors, are also variable resistors.

It turns out voltage is really easy for microcontrollers (those with analog-to-digital converters– ADC’s – at least) to measure. Resistance? Not so much. But, by adding another resistor to the resistive sensors, we can create a voltage divider. Once the output of the voltage divider is known, we can go back and calculate the resistance of the sensor.

For example, the photocell’s resistance varies between 1kΩ in the light and about 10kΩ in the dark. If we combine that with a static resistance somewhere in the middle – say 5.6kΩ, we can get a wide range out of the voltage divider they create.

Photocell interface schematic

Photocell makes up half of this voltage divider. The voltage is measured to find the resistance of the light sensor.

Light LevelR2 (Sensor)R1 (Fixed)Ratio R2/(R1+R2)Vout
Light1kΩ5.6kΩ0.150.76 V
Dim7kΩ5.6kΩ0.562.78 V
Dark10kΩ5.6kΩ0.673.21 V

A swing of about 2.45V from light to dark. Plenty of resolution for most ADCs!

Level shifting

More complicated sensors may transmit their readings using heavier serial interfaces, like a UART, SPI, or I2C. Many of those sensors operate at a relatively low voltage, in order to conserve power. Unfortunately, it’s not uncommon that those low-voltage sensors are ultimately interfacing with a microcontroller operating at a higher system voltage. This leads to a problem of level shifting, which has a number of solutions including voltage dividing.

For example, an ADXL345 accelerometer allows for a maximum input voltage of 3.3V, so if you try to interface it with an Arduino (assumably operating at 5V), something will need to be done to step down that 5V signal to 3.3V. Voltage divider! All that’s needed is a couple resistors whose ratio will divide a 5V signal to about 3.3V. Resistors in the 1kΩ-10kΩ range are usually best for such an application; let’s

Breadboard example of level-shifting voltage dividers

3.3kΩ resistors (orange, orange, red) are the R2’s, 1.8kΩ resistors are the R1’s. An example of voltage dividers in a breadboard, level shifting 5V signals to 3.24V. (Click to see a larger view).

Keep in mind, this solution only works in one direction. A voltage divider alone will never be able to step a lower voltage up to a higher one.

Application Dont’s

As tempting as it may be to use a voltage divider to step down, say, a 12V power supply to 5V, voltage dividers should not be used to supply power to a load.

Any current that the load requires is also going to have to run through R1. The current and voltage across R1 produce power, which is dissipated in the form of heat. If that power exceeds the rating of the resistor (usually between &frac18;W and 1W), the heat begins to become a major problem, potentially melting the poor resistor.

That doesn’t even mention how inefficient a voltage-divider-power-supply would be. Basically, don’t use a voltage divider as a voltage supply for anything that requires even a modest amount of power. If you need to drop down a voltage to use it as a power supply, look into voltage regulators or switching supplies.

Going Further

Now that you’ve got the gist of one of the most common circuits in electronics, there’s a world of new stuff to learn!

Would you like to learn how a microcontroller, like an Arduino, could read the analog voltage produced by a voltage divider?

Now that you know how to use a voltage divider, there are all sorts of components you can stick into your circuits. Analog sensors and potentiometers especially make heavy use of voltage dividers:

Extra Credit: Proof

If you haven’t yet gotten your fill of voltage dividers, in this section we’ll evaluate how Ohm’s law is applied to produce the voltage divider equation. This is a fun exercise, but not super-important to understanding what voltage dividers do. If you’re interested, prepare for some fun times with Ohm’s law and algebra.

Evaluating the circuit

So, what if you wanted to measure the voltage at Vout? How could Ohm’s law be applied to create a formula to calculate the voltage there? Let’s assume that we know the values of Vout, R1, and R2, so let’s get our Vout equation in terms of those values.

Let’s start by drawing out the currents in the circuit – I1 and I2– which we’ll call the currents across the respective resistors.

Standard voltage divider circuit with currents drawn in

Our goal is to calculate Vout, what if we applied Ohm’s law to that voltage? Easy enough, there’s just one resistor and one current involved:

Vout = R2 * I2

Sweet! We know R2’s value, but what about I2? That’s an unknown value, but we do know a little something about it. We can assume (and this turns out to be a big assumption) that I1 is equivalent to I2. Alright, but does that help us? Hold that thought. Our circuit now looks like this, where I equals both I1 and I2.

Voltage divider with just a single current loop

What do we know about Vin? Well, Vin is the voltage across both resistors R1 and R2. Those resistors are in series. Series resistors add up to one value, so we could say:

R = R1 + R2

And, for a moment, we can simplify the circuit to:

Further simpling the voltage divider circuit - combining R1 and R2

Ohm’s law at its most basic! Vin = I * R. Which, if we turn that R back into R1 + R2, can also be written as:

I = Vin/(R1 + R2)

And since I is equivalent to I2, plug that into our Vout equation to get:

Voltage divider equation! Vout = R2 * (Vin/(R1+R2))

And that, my friends, is the voltage divider equation! The output voltage is a fraction of the input voltage, and that fraction is R2 divided by the sum of R1 and R2.


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

Working with Wire

$
0
0

Working with Wire a learn.sparkfun.com tutorial

Introduction

When someone mentions the word wire, they are more than likely referring to a flexible, cylindrical piece of metal that can vary in size from just a few millimeters in diameter to several centimeters. Wire can refer to either a mechanical or electrical application. An example of a mechanical wire could be a Guy-wire, but this this guide will focus on electrical wiring.

wire

Inside a stranded wire

Electrical wire is a backbone of our society. There is wire in houses to turn on lights, heat the stove, and even talk on the phone. Wire is used to allow current to flow from one place to another. Most wires have insulation surrounding the metallic core. An electrical insulator is a material whose internal electric charges do not flow freely and, therefore, does not conduct an electric current. A perfect insulator does not exist, but some materials such as glass, paper and Teflon, which have high resistivity, are very good electrical insulators. Insulation exists because touching a bare wire could allow current to flow through a persons body (bad) or into another wire unintentionally.

Recommended Reading:

Here are some topics you might want to explore before reading about wire:

Stranded vs Solid

Wire can come in one of two forms, stranded or solid core.

Solid Wire

Various colors of solid core wire

Solid wire is composed of a single piece of metal wire, also known as a strand. One very common type of solid wire is known as wire wrap. Stranded wire is composed of many pieces of solid wire all bundled into one group.

Stranded Wire

Various colors and sizes of stranded wire

Stranded wire is much more flexible than solid wire of equal size. For this reason, stranded wire is used when the wire needs to move around frequently, in a robot arm for example. Conversely, solid wire is used when little or no movement is needed, such as prototyping circuits on a breadboard. Using solid core wire makes it easy to push the wire into a breadboard. Trying to use stranded wire on a breadboard can be very difficult, as the strands want to separate as they are pressed in.

Wire Thickness

The term ‘gauge’ is used to define the diameter of the wire. The gauge of a wire is used to determine the amount of current a wire can safely handle. Wire gauge can refer to both electrical and mechanical. This tutorial will only cover electrical. There are two main systems for measuring gauge, American Wire Gauge (AWG) and Standard Wire Gauge (SWG). The differences between the two are not critical to this guide.

Wire Gauges

An approximate scale of several different gauges of wire

The amount of current that a wire can carry depends on a few different factors, for example the composition of the wire, wire length, and condition of the wire. In general, thicker wire can carry more current.

Amps to Gauge

An approximate wire thickness to current capability chart

Here at SparkFun we typically use 22 AWG wire for prototyping and breadboarding. When using a breadboard, the solid core is perfect because it fits nicely into the breadboard holes. For other prototyping/building involving soldering, the stranded core is #1, just be sure not to let too much current run through a single wire, it will get hot and could melt!

SparkFun carries a variety of both solid and stranded 22 AWG wire. Check it out!

How to Strip a Wire

Safe, durable electrical connections begin with clean, accurate wire stripping. Removing the outer layer of plastic without nicking the wires underneath is critical. If a wire does get nicked, the connection may break or an electrical short may occur.

Nice Wires

No nicks or gouges. These wires have been properly stripped

The Tool

Wire Stripper

A simple manual wire stripper is a pair of opposing blades much like scissors. There are several notches of varying size. This allows the user to match the notch size to the wire size, which is very important for not damaging the wires.

Warning: Many wire strippers found at the hardware store do not strip small gauge wire (22 to 30). When getting into prototyping, be sure to get a tool that is capable of stripping 22 AWG and smaller. Being able to strip very small 30 AWG wire (also known as wire wrap wire) is a plus.

Although a knife would also strip the wires, it may also damage the wire by nicking the metal or cutting into it. Using a knife to strip wire is also really dangerous! The knife can easily slip and cause wicked injuries.

Stripping the Wire

Wire in Stripper

By simply squeezing the handles about ¼" from the end of the wire or the desired length, using the correct notch on the tool, and then twisting it slightly, the insulation will be cut free.

Wire After Strip

Then by pulling the wire strippers towards the end of the wire, the insulation should slide right off of the wire.

Tips, Tricks, and Hints

It is important to match the size of wire to the correct notch in the stripper. If the notch is too large, the wire will not get stripped. If the notch is too small, there is a risk of damaging the wire. Using an undersized notch means the strippers will close too far, digging into the wire underneath. With stranded wire, the tool will cut off the outer ring of wires, decreasing the total diameter of wire and reduce the strength of the wire. A nick in solid core wire will severely reduce the strength and flexibility of the wire. The likelihood of the wire breaking upon being bent increases significantly.

Damaged Wire

This wire was not stripped properly, there are gouges and missing strands

If a wire does accidentally get a nick in it, the best plan of action is to cut the damaged part of the wire off and try again.

How to Crimp an Electrical Connector

An electrical connector is a device for joining electrical circuits together using a mechanical assembly. The connection may be temporary or serve as a permanent electrical joint between two wires.

There are hundreds of types of electrical connectors. Connectors may join two lengths of wire together or connect a wire to an electrical terminal.

Connector Types

The Tool

The word crimping in this context means to join two pieces of metal together by deforming one or both of them to hold the other. The deformity is called the crimp.

crimped

The metal has been deformed to pinch the wire and hold it in place

In order to crimp connectors onto a wire, a special tool is required. Note: Pliers are not crimpers! Neither are hammers, vises, needle nose pliers or flat rocks. A good crimper when used correctly will make a cold weld between the wire and the barrel of the connector. If you were to cut a well executed crimp in half you would see a solid form of wire and connector. Using the wrong tool will not achieve a good crimp!

Why is this level of perfection required? A poor crimp leaves air pockets between the wire and connector. Air pockets allow moisture to collect, moisture causes corrosion, corrosion causes resistance, resistance causes heat, and may ultimately lead to breakage.

Crimper Tools

The top crimper will give better results, however the bottom one works just fine too

There are several different styles of crimpers available. The best crimper, shown on the top, has a built in ratchet. As the handles are squeezed together, it will ratchet and prevent the jaws from opening back up. When enough pressure has been applied, the ratchet will disengage and release the crimped part. This ensures enough pressure has been applied. This style of crimper also has a wide jaw to cover more surface area on the connector.

The crimping tool on the bottom can achieve nearly the same results, although it requires the user be be much more vigilant. This style of crimper is generally less sturdy. Attention must be given while crimping to ensure the jaws are lined up properly on the connector. Misalignment will cause a less than desirable crimp connection. Over time, wear and tear from normal usage can also cause the jaws to become separated and not close fully. Generally, squeezing it as hard as possible will be sufficient.

Crimp the Connector

There are several arguments for and against using solid core wire with crimp connections. Many believe crimping to solid core wire creates a weak point in the wire, which can lead to breakage. There is also a greater chance for a crimp connection to come loose with solid core wire because the wire will not conform to the terminal as well. If you must use solid core wire, it is a good idea to solder the wire in place after you crimp it.

First, the correct size wire must be chosen for the terminal size, or vice versa. Next, strip the wire. The amount of exposed wire should be equal to the length of the metal barrel on the connector, usually around ¼” or so. If the stripped wire fits up into the metal portion of the barrel with little or no free space, the connector is the right size.

Good Length

A good length of wire to barrel ratio

Remember: If the wire does not fit in the barrel, or is excessively loose, the wrong size of either wire or connector was chosen.

The wire should then be inserted until the insulation on the wire touches the end of the barrel.

Good Crimp Example

Good: The wire is sticking past the barrel just a little

The wire and terminal are then inserted into the crimper. The color of the terminal’s insulation needs to be matched with the same color on the crimping tool. So if the terminal’s insulation is red, use the spot marked by the red dot on the crimpers. Alternatively, if the crimper does not have color markings, use the gauge markings on the side.

The terminal should be sitting horizontal with the barrel side up. The tool is then held perpendicular to the terminal and placed over the barrel, nearest to the ring (or other connection type). To finish the crimp, the tool is squeezed with a considerable force. In general, it is almost impossible to ‘over crimp’ a connection.

crimped

After the crimp is completed, the wire and connector should still hold together after trying to pull them apart with great force. If the connection can be pulled apart, the crimp was not done correctly. It is better to have the crimp fail now, versus after it has been installed in its application. Below is a military spec chart for crimped connections.

Mil Spec Chart

Common Mishaps

Wrong size connector for the wire or wrong size wire for the connector.

bad crimp 1

Bad crimp. Connector was too small for the gauge of wire chosen.

Be cautious not to strip too much insulation off.

bad crimp 2

Too much insulation has been stripped off, too much bare wire exposed

It is also worth mentioning that, while not necessarily harmful, The wire should not be protruding too far past the barrel. If this happens, trimming the wire is recommended.

bad crimp 3

The excess bare wire should be trimmed off

Going Further

You should now be familiar with electrical wire and how useful it is in the world of electronics. Whether you’re prototyping, reworking, or building a final product, electrical wire can be your best friend.

Here are some other tutorials you can explore that involve electrical wire.

  • Wire is the most basic element when creating your own circuits.
  • Unsure which connectors to use? Have a look at Connector Basics to get what you need!
  • Want to start prototyping? Check out Breadboards to get going!

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

Soft Circuits: LED Feelings Pizza

$
0
0

Soft Circuits: LED Feelings Pizza a learn.sparkfun.com tutorial

You are here

alt text

Love is sort of an unavoidable human condition, be it love for a person or a delicious snack. So here — whether you give it to someone you love more than pizza, or keep it for yourself as a symbol of your own undying love for pizza — are my detailed instructions on how to make your own slice of LED-riddled, felt Feelings Pizza. Is it silly? Yes. Does it serve a purpose? Other than amusement, not especially. So why are we doing this? We are doing this because it’s better than watching Rock of Love re-runs, and why not.

When I started at SparkFun I was coming from a career in print, so in my interview when they asked if I had any experience working with electronics, I think my response was, “I have a few.” Luckily, SparkFun sees electronics inexperience as an opportunity instead of a drawback, and now here I am, carrying the banner. And while the learning curve has been steep (I’m still not sure what this microcontroller I soldered together is for), I can say that I’ve been able to experience firsthand the addictive “a-ha!” moment our education department was founded to foster in other beginners like me.

In my experience thus far, e-textiles gets a bit of a bad rap for its ease of use and lack of any kind of coding or soldering requirements. Well I’m here to tell you that e-textiles are people too, and getting the hang of a sewn circuit is no less exciting than coding a GPS tracker. The first time I got it right, I accidentally flipped over a table of eggnog glasses in my excitement, which a) had almost nothing to do with the eggnog I was consuming at the time and b) did not make me popular among the partygoers, but diminished my insufferable sense of self-accomplishment no less. So, dear beginners, I’m here to share that moment with you, sans eggnog (company policy).

As a side bonus, this is also a good project to introduce kids to electronics, as the supplies are inexpensive, the electronic components are simple and the danger level is low.

If you’d like to start from square one, here are a couple tutorials that cover some of the basic concepts we’ll be using to build our dream pizza:

The Recipe

alt text

Here is a list of the materials needed to follow along with this tutorial.

  • Felt pizza bits (I used wool felt from a craft supply store – I cut the pieces with a laser cutter but you can cut the pizza and toppings out by hand; felt is very easy to work with):
    • two triangles for the front and back of the pizza (so we can hide the circuitry between them); one yellow for cheese, and one brown for the crust
    • one crust-colored piece to go across the top of the front
    • toppings of choice: I made mushrooms, green and black olives, and red, heart-shaped pepperonis (these are the only ones that really matter for this project, since the hearts will be the part that lights up)
  • LilyTwinkle board
  • battery holder with switch
  • 20mm coin cell battery
  • LilyPad LED micro – red (we will use three of the five pieces provided)
  • conductive thread and a needle
  • fabric glue or hot glue to attach toppings

The Setup

You’ll want to start by figuring out a layout for your toppings on the top triangle – you can put the toppings wherever you like, but be sure to space out the pepperonis enough that you’ll be able to sew an LED underneath each one with enough room. You can attach the toppings to the top piece now if you like, as all our circuitry will be sewn onto the crust piece, or you can just mark a small dot where you know your pepperonis will be.

alt text

Once you’ve decided where you want your pepperonis, use small scissors to cut a tiny hole in the top triangle underneath where each pepperoni will be so the LED can shine through more easily.

alt text

Stack the top piece on the crust and mark through the holes with a pencil so you know where to sew down each LED on the crust piece. Then attach all your toppings to the top piece of the pizza and set it aside.

alt text

alt text

Electronics. Part I.

Now: ELECTRONICS. I want my LilyTwinkle board and the three LEDs to be hidden inside the pizza, but I want to be able to access the on/off switch and the battery, so I’m going to sew the battery holder onto the back of the pizza first.

Thread your needle with a 6” piece of thread (doubled as in the photo, with a double knot at the end to prevent it from pulling through the felt).

alt text

Place the battery holder in the upper left corner of what will be the very back of your pizza, with the switch right side up and the positive sides on the left. Sew the upper positive terminal down (I loop each stitch through the terminals three times to ensure strong contact with the conductive thread), run stitches down to the lower positive terminal, and sew that down also. Don’t cut the thread yet! We’ll continue this circuit on the inside.

alt text

alt text

Electronics. Part II.

Now, without cutting our first piece of thread, we will flip the felt over and begin sewing our circuit on the other side, which will be the inside of our pizza. On the blank side of the felt — somewhere below where the battery holder lies on the other side, but not obstructing any of the spots you’ll need to sew down the LEDs to match up with your pepperonis — continue your stitch from the second positive terminal of the battery holder to the positive terminal on the LilyTwinkle, and sew it down.

alt text

Now you can cut and tie off your thread (make sure to tie it tight and cut the ends of all threads short to avoid crossing stray threads and shorting your circuit), and re-thread the needle with a new piece of conductive thread for the next part.

alt text

Electronics. Part III.

Using a new piece of thread for each LED, sew a numbered terminal (whichever ones are easiest to reach with a stitch) on the LilyTwinkle to the positive terminal on an LED, and cut and tie off the thread. Make sure the LEDs are placed on the spots you marked earlier to match up with the locations of the pepperonis.

alt text

Once all your LEDs are sewn to the LilyTwinkle board, use one long piece of conductive thread to connect the negative terminals of the LEDs to each other and then to the negative terminal on the LilyTwinkle. Tie off the thread, and cut it.

alt text

Electronics. Part IV.

alt text

Finally, sew both negative terminals on the battery holder down and to each other, and then to the negative terminal on the LilyTwinkle (it’ll be tight with the thread from the negative LED terminals, but now it’s all connected!). This is what my full circuit looks like (yours will look different depending on the placement of your LEDs.

alt text

The Moment of Truth

Jam that coin cell battery into the battery holder (writing side up), and flip the switch to “on.”

alt text

Your LEDs should light up randomly, at which point you can plop the top of your pizza over the bottom and, if you lined everything up correctly, your heart-shaped pepperonis should begin twinkling festively. Hurray! Now you can glue or sew your pizza halves together (stick to the edges and don’t get glue all over your circuits) and be on your way, to wave your success from the rooftops and bask in the accolades of potential love interests everywhere.

alt text

Congratulations!

Hooked? Here are some other tutorials you can check out to use your new skillz:


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

Electronics Assembly

$
0
0

Electronics Assembly a learn.sparkfun.com tutorial

The Steps

SparkFun has some very unorthodox methods for assembling electronics. We’ve compiled some of the steps and the lessons we’ve learned over the past decade of DIY PCBA (printed circuit board assembly). We’ve grown to a point where some of this doesn’t make sense to do in the basement of your house, but if you’re wondering how we do what we do (build over 80,000 widgets a month), read on.

We are going to start at the front of production. This means the design has already been vetted, prototyped, reviewed, and ‘gone to red boards’ (once a green colored prototype is ready for production we have the PCB made in red). Now we just have to build the thing!

If you’re completely new to electronics, you might want to checkout PCB Basics.

An electronic assembly at SparkFun typically goes through seven steps:

  • Paste Stenciling
  • Placement
  • Reflow
  • Manual Assembly
  • Inspection and Testing
  • Washing
  • Packaging

Here’s a quick video to show you all the steps in one, awesomely silly, video:

Now let’s go through each step…

Stenciling

Panel of PCBs

16 copies of the EL Escudo Dos

Solder paste stenciling is a lot like silk screen stenciling a t-shirt. You have a mask that you lay over the thing you want to apply ink to. In our case we use a metal stencil to apply paste to very specific parts of a PCB (printed circuit board).

At SparkFun, we start with a PCB panel. Panels are a larger board with the design repeated several times over, to make handling easier. In this case we have 16 copies of the EL Escudo Dos. We make these larger panels so that we can stencil multiple boards at the same time. However, you can just as easily stencil one board at a time.

Solder stencil foil

Solder paste stencil, also called a ‘foil’.

A small dab of solder paste is placed on each pad where a component will sit. To make this process faster, a stencil is laid over the board, and the paste is smeared over the stencil with a metal squeegee.

Lead free solder paste

This is what solder paste looks like in the wild. It’s a mixture of metal alloys: 96.5% tin (Sn), 3% silver (Ag), and 0.5% copper (Cu). Most paste has an expiration date and should be stored in a cool place. This has to do with the flux that is added to the metals thus creating the paste consistency. Flux changes the surface tension of the metal when it is in liquid form helping it to flow into the joints.

We use lead-free solder paste but if you’re not planning on selling your widget in Europe then leaded paste is a little more forgiving and easier to use.

We design all our boards in Eagle PCB. The software outputs various layer files that the PCB manufacture uses to create the actual PCB. There are also two layers (top paste and bottom paste) that we send to our stencil fabricator. They use a high power CO2 laser to cut the stencil out of thin stainless steel sheets.

Stenciling can be done by hand. In the video above, Abe does a quick demonstration of how to line up a stencil and apply solder paste. Checkout this awesome presentation for some additional photos and information about stenciling.

Solder paste on a foil

There is no magic when globbing paste onto a stencil. We like to use off the shelf putty knives from the local hardware store.

Here’s the stenciling machine at SparkFun. It’s a lot of work to setup the machine, but for very large runs (greater than 500 pcs), it makes stenciling a bit easier.

Pick and Place

Populating electronic components

Once the board has paste applied, the components are placed on top. This can be done by hand or by a machine. Using tweezers is a great way to place components. There is a common fallacy that you need large, expensive machines to make electronics. Not true! A human is quite fast at placing components and the surface tension of liquid metal is such that most components will shift into their correct location during reflow. But humans have a limit to their stamina. After a few hours it becomes harder to place components quickly. The small size of the components also tend to strain eyes.

You don’t need a pick and place machine to make electronics; you need a pick and place machine to build a lot of electronics.

SparkFun started by placing all the components by hand and we still do! But if we have more than about a hundred units to build we use a pick and place machine to allow us to build lots of boards.

A pick and place (PNP) machine is a robotic assembly device that uses a vacuum to lift a component off of a piece of tape, rotate it to the right orientation, then place it on a circuit board. It takes a few hours to setup a machine to build the assembly, but once everything is running, it is very fast.

In a large factory, a conveyor belt often carries the board directly from an automated paste deposition machine into the pick-and-place machines; at SparkFun, we move our boards manually around the production floor.

Bob shows us SparkFun’s new MYDATA PNP machine. It’s pretty awesome.

Reflow

After pick-and-place, the paste must be reflowed to create a solid solder joint. The boards are put on a conveyor belt that moves slowly through a large oven, exposing the boards to enough heat to melt the solder (about 250°C!). As the board moves through the oven, it encounters different temperature zones, allowing it to warm up and cool down at a controlled rate.

Board with paste and electronic components

Here we have the control board for the infamous Portable Rotary Phone with components placed on the solder paste. The paste is tacky like butter sticking to a dish. The components stay in place while the board slowly moves through the reflow oven.

Board entering the reflow oven

A populated board as it slowly enters the reflow oven

The reflow oven is kind of like a pizza oven. The board is raised in temperature to about 250°C (~480°F) at which point the paste turns to liquid metal. As the board exits the reflow oven, it quickly cools soldering all the components in place.

The video shows a DIY toaster oven showing the various stages of reflow. At the beginning, you can see the little gray blobs of solder paste on the various pads. This paste was probably hand applied rather than stenciled on; you’ll see why that sloppiness factor doesn’t matter so much later in the video. At about 1:05, the first milestone is passed: the flux within the paste gets runnier and begins to form puddles. The metal solder has not yet melted. At about 3:10, the solder starts to melt, and the surface tension of the molten solder causes the puddles of melted solder to form the smallest possible object: a blob centered on a pad.

You can also see the degree to which the solder can move the parts around as it reflows. Some of the parts end up misplaced and will need to be reworked later. However, this tendency to contract and move parts means that small misalignments and stray solder tend to be largely self-correcting problems. With really tiny parts, however, if one end of the part is pulled harder than the other, the result can be a part standing on end; that’s called tombstoning, and it causes a functional defect in the board.

A reflowed PCB

Cool to the touch, this board now has all the SMD components fully soldered to the PCB. The board is now ready for the next step!

How do you do two sided boards?

A few of our assemblies (the Arduino Fio for example) have parts on both sides of the board. In those cases, the side with the fewest and smallest components is stenciled and reflowed first. Once the board is out of the reflow oven it is stenciled on the second side, placed, and reflowed. The surface tension of metal is very high and holds everything in place. In factories with larger, more complex assemblies various bits of the board may be glue in place during the pick and place step to insure the component doesn’t move during reflow.

Manual Soldering

Hand soldering components

After reflow, a technician takes the board and manually solders any PTH (plated through-hole) components. In a larger production facility, the soldering of through-hole components may be done using a technique known as wave soldering, where the board is passed over a standing wave of molten solder, which adheres to component leads and any exposed metal on the board.

Soldering through hole components

Because of the high mix of different designs and quantities at SparkFun, we’ve found it’s easier to push as much as possible to SMD (surface mount devices) and hand solder any PTH components. We use the Hakko FX-888D soldering iron on the production floor. They work fabulously, but the lower cost Atten 937b is great for entry level soldering.

Here’s Dave showing us how to do basic soldering.

Inspection and Testing

Automated optical inspection machine

The next step is optical inspection. Optical inspection catches any problems with parts (wrong resistor, missing cap, etc.). The AOI (automated optical inspection) machine is fast. You watched the video, right? That’s very close to real time. The AOI uses a series of high-power cameras at different angles to see different parts of the solder connections (sometimes called fillets). Good and bad solder fillets reflect light differently so the AOI using different color LEDs to illuminate and inspect every connection, with great accuracy, at high speed. It’s pretty sweet.

Do you need optical inspection for your board? Probably not. We didn’t get one until we were doing 30,000+ boards a month when it was becoming harder and harder to catch all the errors.

Solder jumper on IC

Can you see the problem?

We run the majority of boards through our automated optical inspection (AOI) machine. Optical inspection checks to make sure all of the correct components are on the board, in the right places, with correct solder fillets and no solder jumpers between adjacent pins.

Pogo pin test jig

Once the board has been inspected it is tested to make sure it does what it is supposed to do.

Imagine if it takes 15 seconds to test a board. What if you have to test 10 boards? That’s about 3 minutes. What about 1500? That’s over 6 hours of mind numbing testing. We spend a tremendous amount of time making our test procedures and programming as quick as possible.

To speed up this process, our technicians use a test fixture, sometimes called a pogo bed to allow for quick testing. Pogo pins use a spring loaded head to create a temporary electrical connection to the various points on the board for power and data. Once the board or panel is loaded onto the pogo bed we run various tests to make sure the board is fully electrically functional. This may include testing the voltage output of regulators, expected voltages on certain pins and sending various commands to the board under test to make sure it responds correctly. On boards that require programming or calibration, additional steps are taken to load code and verify the output.

Larger facilities may use flying probe or bed of nails fixtures to test every connection on a board for continuity before powering the board. These larger fixtures are good for more complex, expensive products but can frequently run into the tens of thousands of dollars to create.

Washing

PCB with flux residue

Various steps of the manufacturing process leave residue on the board. If you’ve ever put one of our kits together, you know that soldering leaves a small amount of flux on the board. Over a period of months this flux residue becomes sticky, looks horrible, and can become slightly acidic leading to a weakening of solder joints. To prevent this (and to give our customers the best looking boards) we wash every board we produce.

Boards loaded in the dish washer

To get the boards clean again we load batches into what we call the ‘dishwasher’. This high temperature, high pressure, all stainless steel dishwasher uses deionized water to remove any residue from the manufacturing process.

The parts washer uses a closed loop system. After the completion of a wash, the waste water is collected in a basin below the washer and automatically tested for conductivity. If the electrical conductivity is very low (if the resistance is very high) then the wash phase is complete and the waste water is recycled through very high quality filters.

That’s right! We completely dunk your expensive electronics into water. The secret is in the type of water. Deionized water is very pure water that lacks any ions. Water doesn’t kill your cell phone when you drop it in the toilet, it’s the ions that allow electricity to short various parts of the device. Because DI water has no ions, it’s actually fairly toxic to humans. While handling DI water is safe, drinking DI water can cause serious damage to your body as it forces your body to give up ions as you ingest it. Because DI water has such a thirst (hah!) for ions, the inside of the dishwasher is made completely of stainless steel. Any other metal would quickly disintegrate.

Electronics in a crockpot

Don’t have access to an expensive washer? A cheap crockpot with deionized water and a toothbrush work swimmingly! If you’re cleaning just a few boards, a Q-tip with some isopropyl alcohol works very well.

Air drying a board

A fan or compressed air work well to remove any water that remains.

Packaging

Touch Shield

The board is reaching the end of its journey!

Sealing in ESD plastic

Once the batch of boards is clean and dry, they go to packaging where each board is individually heat sealed into ESD plastic.

Chain of 10 boards

Because picking and packaging orders needs to be as fast as possible, we make sure every product is ‘pick ready’ for the shipping department. For most products, we will create a chain of 10 pieces with a bar-coded label on each end. The barcode label contains the product name, SKU, and a batch identifier that helps us track any problems.

Once the product is completely packaged, it is sent over to the shipping floor. We record the departing inventory, deduct all the work in progress parts, and add the new quantities to our storefront stock. The product then begins an entirely new journey to your door. We’ll leave that tutorial for another day.

More Reading

Thanks for checking out how we build electronics at SparkFun. Now that you’ve read a little, we recommend you checkout a few more tutorials:


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

The Uncertain 7-Cube

$
0
0

The Uncertain 7-Cube a learn.sparkfun.com tutorial

Magic Isn't Real

It’s sad but true. We can’t levitate, we can’t teleport and we definitely can’t see the future. That last bit makes the so-called “Magic 8-Ball” especially sinister. There’s nothing magical about randomly answering a yes or no question. Knowing that, the only responsible thing to do is to build a better, more honest, fortune telling device for the enlightened age. I present to you: The Uncertain 7-Cube.

7Cube

The Uncertain 7-Cube is a non-committal, less-than-helpful, but also entirely honest fortune teller. Simply ask it a yes or no question, give it a nudge, and the 7-Cube will dutifully inform you that it doesn’t have all the facts and doesn’t feel comfortable making a guess. That’s right, in a variety of voices and a multitude of responses, the Uncertain 7-Cube will preserve your sense of responsibility for the future by refusing to make your decisions for you!

To make this happen we’ll need a few things:

Behind the Uncertainty

Since magic isn’t making this thing tick, what is? Well, it’s a bit of a jumble:

fritzingschem

The ability of the Uncertain 7-Cube to remain in ‘stasis’ while waiting to be picked up or bumped is a function of the Wake-on-Shake board. The Wake-on-Shake uses an ultra low power accelerometer to detect motion. When motion is detected, the on-board microcontroller wakes up and turns on power to the rest of the cube.

The ability to speak (magical as it may seem) is actually provided by the emic2 Text-to-Speech module from Parallax. This module simply takes character strings over a serial connection, parses them into pronounceable words, and uses a built-in voice synthesizer to speak them out loud. Our Mono Amp breakout turns the volume to 11 so you can clearly hear the cube’s non-advice.

All of the different non-committal answers are stored on an Arduino Pro Mini, which is programmed to randomly choose an answer from the list and transmit it over the serial port. When it gets a signal back from the emic2 module that it’s done talking, the Pro Mini shuts everything down and the cube goes back into stasis.

The emic2 module has an input voltage of 5V, so the supply voltage for the cube needed to be able to provide that. A lithium polymer battery and a Powercell board provide 5V to the system. The Powercell also provides an easy way to charge the battery without having to remove it.

The Build

The Uncertain 7-Cube was supposed to be about the size of a Magic 8-Ball except, you know, cube shaped. The way this was accomplished is that almost all of the component boards were mounted vertically on a 2” square ProtoBoard using right-angle headers. This kept everything mounted firmly to the cube and left room in the center for a battery.

buildpic

As you can see, there’s a ribbon cable attached to the FTDI header on the Arduino Pro Mini. That’s just there to allow the Arduino to be programmed after the whole thing is enclosed. The headphone jack on the Text-to-Speech module, the charging jack on the Powercell and the FTDI ribbon are all accessible from one side of the assembly; That way, I could avoid taking the whole enclosure apart if I needed to get to something.

The only part that isn’t mounted vertically is the Wake-on-Shake board. Since it uses an accelerometer to detect when it changes position, it needs to be firmly connected to the board so it can’t wiggle around and decrease the reliability of the sensor. You’ll also notice the speaker is just hanging off of the board. When everything is mounted in the enclosure, the standoffs keep the speaker from moving.

The Enclosure

Cubes are a nice shape. They’re made up of regular planes and are therefore really easy to fabricate out of almost anything. I decided that laser cut acrylic was the fastest way to make a really good looking enclosure. To make the basic box shape, I used an awesome online tool called BoxMaker which takes the dimensions of your box and the thickness of your material and generates a vector file with the pattern. I imported the pattern into InkScape (a free vector drawing tool) and added a little flair of my own.

svgpng

After I had the file drawn out, I sent it to the laser cutter. The thin lines were cut and the thick features and shapes were raster etched. When the pieces came out of the laser cutter I cleaned them with a plastic polish and painted inside of the etched features using a white paint pen.

When everything was clean and dry, it was puzzle time. I started by screwing the electronics to the bottom plate of the cube. There were three holes cut in the piece that would match the position of the standoffs. I used a handheld drill to add a chamfer to the holes which would hide the head of the machine screws.

Once the core was in place, I started assembling the cube one panel at a time using hot glue. I left one panel loose so that I could still access the board to change/charge the battery or connect to the emic2 module’s headphone jack.

The Code

Since the Wake-on-Shake board handles all of the hibernation and motion detecting functions, all that the Arduino has to do is pick a phrase, send it to the voice synth, and then tell the Wake-on-Shake to turn everything off again. The code is based heavily on the Emic2 example code provided by Parallax.

    #include <SoftwareSerial.h>
    #include <TrueRandom.h>

    #define rxPin 2    // Serial input (connects to Emic 2 SOUT)
    #define txPin 3    // Serial output (connects to Emic 2 SIN)
    #define ledPin 13  // Most Arduino boards have an on-board LED on this pin
    #define wakePin 9 // Wake on Shake "Keep Awake" Pin

    // set up a new serial port
    SoftwareSerial emicSerial =  SoftwareSerial(rxPin, txPin);

    void setup()  // Set up code called once on start-up
    {
     // define pin modes
     pinMode(ledPin, OUTPUT);
     pinMode(rxPin, INPUT);
     pinMode(txPin, OUTPUT);
     pinMode(wakePin, OUTPUT);

     // set the data rate for the SoftwareSerial port
     emicSerial.begin(9600);

     /*
        When the Emic 2 powers on, it takes about 3 seconds for it to successfully
        intialize. It then sends a ":" character to indicate it's ready to accept
        commands. If the Emic 2 is already initialized, a CR will also cause it
        to send a ":"
     */

     emicSerial.print('\n');             // Send a CR in case the system is already up

     while (emicSerial.read() != ':');   // When the Emic 2 has initialized and is ready, it will
     //send a single ':' character, so wait here until we receive it
     delay(10);                          // Short delay
     emicSerial.flush();                 // Flush the receive buffer
     digitalWrite(wakePin, HIGH); // Tell the Wake-on-Shake that we're still awake
    }

    void loop()
    {
    int freeWill = TrueRandom.random(16); // Choose a response. This is the magic part.
    // int summonVoice = TrueRandom.random(9); // Summon a voice from Beyond
    // summonVoice = char(summonVoice); // Convert the will of the universe
    //to a character so the emic module will accept it
    // emicSerial.print('N'); // Select voice
    // emicSerial.print(summonVoice); // Our voice from Beyond
    // emicSerial.print('\n'); // Terminate the voice command
    emicSerial.print('S'); // Speak some text command
    switch (freeWill) {

     case 0:
      emicSerial.print("I mean, anything is possible. Right?");
      break;
     case 1:
      emicSerial.print("I don't feel comfortable saying either way.");
      break;
     case 2:
      emicSerial.print("Yes. . Oor No. . I won't speculate.");
      break;
     case 3:
      emicSerial.print("I say: go with what you know.");
      break;
     case 4:
      emicSerial.print("How important is it to know that right now?");
      break;
     case 5:
      emicSerial.print("If it happens, it happens.");
      break;
     case 6:
      emicSerial.print("Hoo could possibly know that?");
      break;
     case 7:
      emicSerial.print("I won't pretend to be an expert on the subject.");
      break;
     case 8:
      emicSerial.print("It's not obviously a yes. It's not a particularly strong no either.");
      break;
     case 9:
      emicSerial.print("Bro... You need to live in the now. The future will be here soon enough.");
      break;
     case 10:
      emicSerial.print("Ummmm. . . Sure? I mean, I don't know. but maybe?");
      break;
     case 11:
      emicSerial.print("You're not giving me a lot to work with here.");
      break;
     case 12:
      emicSerial.print("I'll need to form a subcommittee and get back to you.");
      break;
     case 13:
      emicSerial.print("Market research in that segment shows a trend torward attitudes that strongly favor neither answer in particular.");
      break;
     case 14:
      emicSerial.print("I suggest you shop the idea with a focus group.");
      break;
     case 15:
      emicSerial.print("You should leverage web 2 point oh social leadership to crowdsource the answer.");
      break;

    default:
      emicSerial.print("The default case occurred. This shouldn't have happened.");
      }

     emicSerial.print('\n'); // Terminate the speech command
     while (emicSerial.read() != ':');   // Wait here until the Emic 2 responds with a ":" indicating it's done talking
     digitalWrite(wakePin, LOW); // Let the Wake-On-Shake module know it's okay to turn off
     while(1){}; // Hang out here until the WOS module shuts us down
    }

So there it is, I simply used a random number generator library called “TrueRandom” to pick a number. Then I used that number to select a phrase from a list. That phrase was sent to the serial port, and then the sleep pin was allowed to fall to 0V, signalling the Wake-on-Shake to shut down. Pick up the cube and the whole process starts over again!

All Together Now

Uncertain 7 Cube from SparkFun on Vimeo.

There you have it. A fortune telling device that doesn’t make any supernatural claims. Does it take all the fun out it? Maybe. Was it an entertaining build? Totally. Will I win the lottery? I don’t feel comfortable saying either way, but anything could happen… right?

If you wanna take a crack at this yourself, here are some resources you might find useful:

New Page


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

Getting Started with pcDuino

$
0
0

Getting Started with pcDuino a learn.sparkfun.com tutorial

Introduction

This article should give you a leg up on developing a project around the pcDuino. Getting started is easy: just plug in the cables, and away you go!

Okay, so that bit was easy. But what’s next? Now that you’ve got the machine up and running, what do you actually do with it?

We’re here to help. In the following pages, you’ll find some handy mini-tutorials to add features, change settings, write code, and just generally get more out of your pcDuino. All of these things assume that you’re running the standard Linux distribution that came with the pcDuino; as time goes by we’ll add some content covering Android as well.

Hardware Tour

Here’s a brief visual rundown of the hardware on the pcDuino.

Top side

Top side connections and hardware

  • Debugging serial port – a root-level session is initiated to this serial port at power up. It can be accessed as a 3.3V serial port, 8-N-1, no handshaking. For more information, see this page.
  • Android buttons – these duplicate the functions of the hardware buttons on many Android-based tablets and phones. In Android programming, these buttons have a special function.
  • GPIO – four 3.3V GPIO pins.
  • SPI – two dedicated SPI peripheral headers. J6 is the SPI2 peripheral; J7 is the SPI0 peripheral, which is also broken out to the appropriate pins on the Arduino-ish headers. SPI0 pins also provide access to two more UARTs and external interrupts, as well.
  • Arduino-ish headers – these pins closely follow the functionality of the pins on standard Arduino-compatible boards: I2C, SPI, UART, PWM, and ADC. The mapping is the same as it would be on a standard Arduino-compatible, as well, making it easy to convert Arduino shields to work with pcDuino.

Bottom side

Bottom side connections and hardware

  • MicroUSB power port – this port is for power only- the data pins don’t connect to anything. The board uses about 500mA under normal circumstances, meaning it can be powered from most USB ports; most modern cellular phone chargers use microUSB as well, making finding a power supply easy.
  • USB-OTG port – this port can be used either as a standard USB port (with the appropriate converter) or to connect the pcDuino to another PC for debugging and upgrading the onboard software. The board can be powered through this port for debugging.

DVI Video Fix

The first-generation pcDuino has an issue with its display setup, which causes it to fail to properly display images on some DVI monitors. In future hardware revisions, this fix will ship with the device; for now, you may need to apply it manually.

Download these files to the root directory of a USB flash drive or microSD card:

If your display is working, but the color is “off”, follow these instructions:

  1. Insert the USB drive or microSD card into the pcDuino.
  2. Launch LXTerminal from the link on the pcDuino desktop.
  3. Enter the following commands at the prompt:

    cd /media/*
    sudo bash ./update_for_dvi

The patch will be applied automatically; it takes a few seconds. You should get a message stating that the pcDuino will restart in 10 seconds; after the restart, the problem should be solved.

If you cannot see the image on your display, the process is slightly more complicated. You’ll need to connect to the onboard serial debugging port. For instructions on how to do this, visit this page.

Now go ahead and connect the power to the pcDuino. You should see the light next to the reset button (between the HDMI and Ethernet ports) come on, and text should start scrolling by in the console. If that doesn’t happen, you may need to check the connection between your pcDuino and the serial bridge to make sure the wires are in right.

This is what you’ll see when the boot process is completed.

pcDuino boot completed on a terminal

Now, follow these steps:

  1. Insert the USB drive or microSD card into the pcDuino.
  2. Enter the following commands in the terminal window:

    cd /media/*
    bash ./update_for_dvi

The patch will be applied automatically; it takes a few seconds. You should get a message stating that the pcDuino will restart in 10 seconds; after the restart, the problem should be solved.

If you have any questions or problems, pleasecontact SparkFun technical support!

Serial Debugging

A very useful feature of the pcDuino is a 3.3V logic-level serial port, which allows access to a root-level terminal session after boot. It also delivers information about the boot process, which can be useful for troubleshooting issues occurring during boot.

Debug serial pins

Connecting to this is simple, and there are many options for doing so. Here, I’ll give you instructions on using an FTDI Basic board, an FTDI cable, or an Arduino-compatible board. You’ll need either some female-male jumper wires or (second best option) some male header pins and female-female jumper wires.

FTDI Basic

FTDI Basic connection

The FTDI Basic connection is easy, since the pins on the FTDI Basic board are labeled.

FTDI Cable

FTDI cable connection

The FTDI cable has no label on the connector, but the pinout is (for this use, anyway) the same as that for the FTDI Basic.

Arduino-Compatible board

Using an Arduino-compatible board as a serial bridge

This is the most difficult method for connecting to the debugging port, although probably the most readily available. The first thing you’ll want to do is load a sketch (like this one) which makes the RX and TX pins inputs. That will ensure that there’s no conflict between the ATmega on the Arduino-compatible and the pcDuino. Then, connect the pins from the pcDuino to the headers on the Arduino-compatible board. Unlike the other two options, in this case, you’ll connect the pcDuino transmit pin to the TX pin on the Arduino-compatible and the pcDuino receive pin to the RX pin. This is because the label on the Arduino-compatible headers refers to the direction of the data relative to the ATmega, not the serial bridge device.

Terminal settings

Use your favorite terminal program (I like PuTTY); I’d strongly suggest avoiding the Arduino serial terminal function, however. You’ll want to be sure local echo is off. The connection settings you’ll need are:

  • 115200 baud
  • 8 data bits
  • no parity
  • 1 stop bit
  • no handshaking

Wireless Networking

The minimalist Linux installation that comes with the pcDuino supports wireless networking, but you’ll have to get your hands a little dirty to get it to work. Here’s a walkthrough for getting the USB wifi dongle we sell working with your pcDuino:

  1. Boot the pcDuino.
  2. Plug in the dongle.

    Finding the "Network Connections" utility
  3. Open the “Network Connections” utility, under the “Preferences” submenu in the system menu.

    Adding a wireless connection
  4. Under the “Wireless” tab, click the “Add” button.

    Configuring wireless connection
  5. You can put whatever you like in the “Connection name” field, but you’ll need to have the SSID of the network you want to connect to in the SSID field. Mode should default to “Infrastructure”, which is correct for most networks, and the bottom four fields can be ignored.

    Configuring wireless security
  6. In the “Wireless Security” tab, you can set the network security options for your network. We won’t attempt to cover this, because it’s too big a topic; the fields should be pretty similar to those on other devices, so copy the settings from something else if necessary.

  7. The last two tabs, “IPV4 Settings” and “IPV6 Settings”, you can probably ignore. If you do need to use them, you likely know that you do, and you probably quit reading this page a while ago.

    Network connection creation completed
  8. Hit the “Save” button to return to the “Network Connections” utility. You’ll see your new connection in the list; the “Last Used” column will say “never” next to this connection. That’s okay. Go ahead and close the window and your connection should be ready to go!

Tips and Tricks

Now that you’re up and running, there are a few things you may find useful to do immediately.

Change/disable screensaver timeout

The default screensaver settings will cause the monitor to blank almost immediately after boot. If that’s not to your liking, here’s how to change it.

  1. Open Leafpad. There’s an icon on the desktop.
  2. From the “File” menu, choose the “Open…” option.
  3. The file you want is hidden, so you’ll have to type the filename to open it. In the “Places” frame, click “ubuntu” to show the contents of the ubuntu user home directory. Then, click the pencil in the upper left to enable the filename entry field. Type “.xscreensaver” in the “Location:” field, and click open.

    Leafpad open file dialog
  4. The file that opens has one line:

    mode: blank

Change “blank” to “off”. That will disable the screensaver entirely. Save the file, and you’re done! There are more settings that can be made here; see this link for details.

Running a program at boot

Say you want to always have an LXTerminal window open when the GUI loads. How do you go about doing this?

All you need to do is add the command to the end of the autostart file located here:

/etc/xdg/lxsession/Lubuntu/autostart

For instance, to launch LXTerminal at boot, add the line “lxterm” to the end of the file.

Stopping the GUI from automatically loading on boot

If you’re using a pcDuino in an embedded application, it may be helpful to prevent the GUI from loading, to conserve processor resources. To log in only as root, with access only via the debugging serial port, open this file:

/etc/lightdm/lightdm.conf

Delete all of the content after [SeatDefaults]. This will stop it from launching the window manager and logging you in.

If you only want to stop the automatic login, just remove the last line (“autologin-user=ubuntu”) from the file, and you’ll be presented with a login screen at reboot.

Changing the OS

The last thing you might be interested in doing is reloading or changing the operating system on the device. There are two methods for doing this: LiveSuit (sometimes found on the internet as “LiveSuite”) and PhoenixCard. LiveSuit can be used to load either Lubuntu or Android; PhoenixCard can only be used to load Linux. We’ll only be covering LiveSuit, as it is the easier and preferred means for doing this.

LiveSuit is available in a Windows (32-bit) version, a Windows 7 (64-bit) version, or in a Linux (64-bit-only) version. We’ll skip over installation of the tool; the linked website explains how to install the Linux version, and the Windows versions don’t need to be installed, merely extracted.

You’ll also need the appropriate image file. Here’s the Lubuntu image that ships with the pcDuino, and this Android image can be loaded as well.

Installing drivers (Windows only)

Before going any farther, you should install the drivers for the pcDuino debugging port. Make sure that you have the right version of LiveSuit—the drivers in the 32-bit version won’t work on a 64-bit system!

  1. Plug a microUSB cable into your computer. While holding the button marked SW2 on your pcDuino, plug the other end of the cable into the USB-OTG port on your pcDuino.

    Labeled hardware for updating flash

  2. In Windows XP, you’ll see a driver installation query pop up. In Windows 7, you’ll probably have to open the device manager. The device will appear as “USB Device(VID_1f3a_PIDefe8)” under the “Universal Serial Bus controllers” section. The drivers are in the LiveSuit directory, in the “UsbDriver” directory.

    Device manager for Windows 7

  3. Once driver installation has completed, unplug the pcDuino.

Installing Android

  1. Launch the LiveSuit application.
  2. Select the Android image file you downloaded above.
  3. Plug a microUSB cable into your computer. While holding the button marked SW2 on your pcDuino, plug the other end of the cable into the USB-OTG port on your pcDuino.

    LiveSuit first format message

  4. After a few seconds, LiveSuit will popup with a window asking if you want to format the device. Since we’re reflashing, choose “Yes”. Note that even if mandatory doesn’t format, you’ll lose anything installed on the device, so back it up!

    LiveSuit second format message

  5. LiveSuit will double check that you want to format the device. Click “Yes” again.

    Update success message

  6. Click “Finish” in the next window. Don’t worry about the directions in the window; they’re not important. Or comprehensible.

    LiveSuit updating

  7. The progress bar will fill in, and if you’ve got a connection on the serial port terminal, you can watch the progress there as well. Don’t be alarmed if there are some long pauses during the update, although the whole process should not take more than five minutes.

  8. LiveSuit will give you an “Update success” window, and the pcDuino will automatically reboot into Android. Note that when watching the serial debugger port output, Android doesn’t give you any kind of a prompt—just a blank line, into which you can enter commands.

Installing Ubuntu

  1. Launch the LiveSuit application.
  2. Extract the Ubuntu archive you downloaded above. In it are two image files: “a10_kernel_20130203.img” and “ubuntu_20130203.img”. Select the “a10_kernel_20130203.img” file.
  3. Copy the files “env_nandd.fex”, “ubuntu_20130203.img”, and “update.sh” from the Ubuntu directory you just extracted to either a microSD card or a flash drive. Make sure the files are in the root directory of the drive!
  4. Insert the flash drive or microSD card into the pcDuino.
  5. Plug a microUSB cable into your computer. While holding the button marked SW2 on your pcDuino, plug the other end of the cable into the USB-OTG port on your pcDuino.

    LiveSuit first format message

  6. After a few seconds, LiveSuit will popup with a window asking if you want to format the device. Since we’re reflashing, choose “Yes”. Note that even if mandatory doesn’t format, you’ll lose anything installed on the device, so back it up!

    LiveSuit second format message

  7. LiveSuit will double check that you want to format the device. Click “Yes” again.

    LiveSuit update complete

  8. Click “Finish” in the next window. Don’t worry about the directions in the window; they’re not important. Or comprehensible.

    LiveSuit updating

  9. The progress bar will fill in, and if you’ve got a connection on the serial port terminal, you can watch the progress there, as well. Don’t be alarmed if there are some long pauses during the update, but it won’t take more than five minutes to complete.

  10. LiveSuit will open an “Update success” message. Do not disconnect the power from the pcDuino at this time.

Serial monitor after Ubuntu image load complete
  1. If you’re connected to the serial monitor, you can watch the device update from the external memory. It takes some time—several minutes at least—and at the end, an “update complete” message will appear on the serial monitor.

  2. If you’re not connected to the serial monitor, you’ll know the update process is completed when the RXLED and TXLED will blink slowly, in unison. While the upgrade is underway, RX will be solid on and TX will be blinking.

  3. Once the upgrade is complete, you may restart the pcDuino.

Going Further

Here are a few links that may be useful:


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

Sparkfun Humidor

$
0
0

Sparkfun Humidor a learn.sparkfun.com tutorial

Overview

In this tutorial, I am going to go through the process of how the SparkFun humidor was designed and built. In case you don’t know, A humidor is any kind of box or room with constant humidity, used to store cigars, cigarettes, pipe tobacco, or in this case sensors. I’ll be covering designing a 3D software model and fabricating it using a CNC router.

Requirements

I realize the following list includes some items that are very expensive and probably not too common in everyone’s home/shop. I still wanted to show their use for someone who may not be familiar with these tools. Here is what I will be using:

  • Creo Parametric 2.0 (formerly Pro Engineer, FREE for educational purposes – Software)
  • Visual Mill 5 (Software)
  • Mach 2 CNC (Software)
  • K2 CNC Machine (Hardware)

Introduction

If you don’t already know, a CNC router is a computer controlled router capable of cutting out very complex shapes. CNC stands for Computer Numerical Control. The CNC machine is connected to a computer and is given very precise three dimensional coordinates to which the machine should move. Using a combination of motors and encoders, the machine is able to cut out nearly anything you can draw. There is lots to cover, so lets get started.

3D Design

Our Production department came to me needing a humidor built. They needed a better system to re-humidify a select few of our boards that need it after coming out of the reflow oven.

I am a very visual person. I like to see exactly what I have designed and how it fits together before I start making it. By doing this, it is easy to see where my mistakes are and correct them.

For this project, I designed both the humidor and the control box for it. The control box allows our Production team to select which board they are placing in the humidor, iit will keep track of the time it has been in there. It also makes sure the humidity stays at the required percentage. I’m not going to cover much of the humidor in this tutorial, however. I laser cut acrylic and epoxied it together in the shape of a box. When it was dry, I added some weather strip to the front door to seal it and put caulk in all the joints to ensure it was air tight. Not too much going on there!

alt text

The control box was really fun to make. I decided to cut ‘teeth’ in all of the edges so it would fit together like a 3D puzzle. Here at Sparkfun, we use Creo Parametric 2.0 for our 3D modeling. Our Arduino and breadboard holder was designed with this along with all of our retail clamshell packaging. I learned this program in High School, and of all the modeling software I have used along the way, it is my favorite. Before I begin, I want to tell you that this tutorial only scratches the surface of the feature in Creo. I’m only going to cover a few main points and features, there is certainly more than one way to do all of this. Let’s start designing!

In the picture below, we are going to start drawing the top panel for the control box. The area with the labels ‘FRONT’, ‘TOP’, and ‘RIGHT’ is our workspace. We want to choose one that accurately describes the surface that we want to draw. Since this panel will go on the top side of the box, I am going to select the ‘TOP’ plane. Probably the most used feature is the Extrude command. This allows us to create material (or remove it) in the shape we want. So to recap, we choose the ‘TOP’ plane and click Extrude.

alt text

This brings us to the Sketcher. The Sketcher is where we draw the features that we want. Using the Rectangle command, I will draw a rectangle. I decided that I wanted the panel to be 8 inches wide and 6 inches tall. The dimensions are added automatically when I draw the rectangle. All I have to do it change them to what I want. Once they are correct, I click OK.

alt text

If the computer accepts the shape, it will add depth to it. This is where we move from a 2D drawing to a 3D model. Since I am cutting this out of plywood that is 0.35” thick, I will enter that in the box shown and click OK.

alt text

Next, I want to cut a hole for the LCD and a few buttons. I’ll select the surface that I want to create the 2D drawing on. In this case, I’ll choose the top of the panel. Once again, I’ll click the Extrude command for this. Remember: Extrude can add or remove material.

alt text

After measuring the size of the LCD screen, I’ll use the Rectangle command to draw the hole where I want it. Now I want to add holes for the buttons. I want the buttons on the right side of the screen, and I want them to be lined up perfectly. I’m going to use what’s called a Centerline for this. You can think of a Centerline as a reference or helper line. In this picture, they are the purple dashed lines. When it comes time to create the 3D model, the computer will ignore these lines, so it doesn’t matter how many you have or where they are placed. Creo will create the center line where I click and it will ‘snap’ to a vertical position, ensuring the buttons are lined up perfectly with the panel.

alt text

By default, the Extrude command adds material. Since we want to do a cut out, we use the ‘Change Direction’ button on the left to tell the computer to cut away from where we drew the hole and also the ‘Remove Material’ button on the right to tell it to remove material. The result is what we want, a hole for the LCD and holes for buttons. I’ll repeat this process for the other buttons.

alt text

alt text

Now it is time to create the ‘teeth’ for the edges. Like before, I select the top surface of the panel and click Extrude. In the Sketcher, I’ll draw a small rectangle that represents one of the teeth I want to cut out. The red color of the dimension indicates that I have locked the dimension. This prevents me or the computer from altering that particular dimension. For now, I am only going to draw one. I’ll show you why in the next step.

alt text

Now drawing 7 cutouts would not have taken too much time, but what if we needed to create 1000 teeth around a circular gear? That would take forever. To save time I will use the ‘Pattern’ command. This allows me to duplicate a feature that I had previously drawn. If you look at the red arrows in the picture below, from left to right: Direction – tells the computer that you want to pattern in a straight line, as opposed to circular. 1 Plane – if you look very carefully, the right side of the panel has an orange line, that is the direction I choose to move. 7 – the number of copies I want to make. 1.0625 – the spacing between each copy. The black dots represent where the computer will add the feature.

alt text

Voilà! We have created the top 8 teeth for our box!

alt text

Since the top and bottom of the panel both use the same pattern, we can use the ‘Mirror’ command to do this easily. I’ll turn on the planes again and select the ‘FRONT’ plane because it runs through the center of the panel. Now the computer will take that single tooth that we drew and patterned and copy it to the bottom of the panel.

alt text

I’ll repeat these last few steps for the teeth on the left and right side of the panel. In the end, we have one part of the box done!

alt text

3D Assembly

Using the same techniques, I went ahead and made the side walls and bottom piece for the box using the same steps. Now that we have 6 individual parts of the box, let’s put them together! In a new file, I’ll import the control panel using the ‘Assemble’ command.

alt text

Next, I will tell the computer that I do not want this piece to move. Since I will be building all of the other parts around it, it is nice to have it stay still. By right clicking on the part in the Model Tree, I can choose Fix Location. Mine is already fixed so the option to UnFix is displayed.

alt text

Next, I will add another piece of the box. Using the Assemble command from before, I’ll bring in the part I want. If you look at the picture, the word ‘Coincidence’ appears several times. This is more or less the way to tell the computer to ‘make these two surfaces touch or line up.’ Simply put, I choose what surfaces should be lined up, and the computer will ‘glue’ them together.

alt text

Repeating the process four more times gives us a completed box! Now we can inspect all the sides to see if we made any mistakes in the length or position of any features.

alt text

Let’s go ahead and add the LCD screen and buttons just for fun.

alt text

We can now use the ‘Exploded View’ command to see the box as if it were taken apart.

alt text

Now that I box is designed, assembled, and inspected, we can get the files ready to cut out on the CNC router. In Creo, we want to create a new Drawing.

alt text

Since we only care about the 2D feature of each part at this point, the parts can lay flat on the screen.

alt text

After adding all views we have the entire box laid out in front of us.

alt text

Lastly, we want to export this drawing as a .dxf file. This type of file is supported in many, many different types of programs so it is a good choice to use.

alt text

Creating Tool Paths

I’m using a program called Visual Mill to create the tool paths for the box. A Tool Path is the area that the CNC machine will follow to cut out our box.

First, I will open the .dxf file that we saved. Then we need to choose the size of the endmill we are going to use.

alt text

I am going to use a 1/8” endmill. We can enter in the specific feature of our tool if we need to. Everything looks good so I’ll choose OK.

alt text

Next, I’m going to select everything that we want to cut out. Selected lines turn yellow so the user can tell they are selected. We want to do a ‘Profile’ type cut. A profile cut will cut around the inside or outside of the part and leave the center intact.

alt text

Next, we have to define a few options. We set the ‘Tolerance’ to .001 inches for good accuracy. ‘Cut Direction’ tells the computer to cut either clockwise or counter clockwise. For wood, a ‘Conventional’ cut works well. This will make the cutting edge on the tool spin into the material (think of a car tire spinning on pavement as the car slowly creeps forward) and keep the wood from peeling off instead of being cut. And lastly, ‘Cut Start Side’ tells the computer to either cut on the inside or outside of the selected lines. We want to cut on the outside.

alt text

On the next tab, we define how deep to cut. This is why earlier in the tutorial I said we only care about the 2D features of the parts. ‘Total Cut Depth’ tells the computer; yep you guessed it, how deep we want to cut. Since the wood is 0.35” thick, lets go 0.36” to be sure. The ‘Rough Depth’ and ‘Finish Depth’ are ways to allow the user to very precisely control how much the CNC cuts off at a given time. Since we are cutting wood and not metal, we don’t need to worry too much about this. I have told the machine to cut in depths of 0.09”. That means it will make 4 passes to cut through. And lastly, ‘Cut Level Ordering’ tells the computer whether it should cut all of the pieces at 0.09” and then all of the pieces at 0.18” and so on or if it should cut one single part at 0.09” and then 0.18” and so on until the set depth. Since it is faster to cut each part one at a time (otherwise the machine has to move around to each part every 0.09”), we will do that.

alt text

Lastly, for this options box are the approaches and engage motions. Because the bit I have is a center cutting bit, I can do what is called plunge cutting. Some bits can drill straight down (plunge) through the material, while others cannot. This is because the teeth of some cutters do not go all the way to the center of the end face. However, these cutters can cut downwards at an angle of 45 degrees or so (called ramp cutting). We can set all of these values to zero. This will make the mill move into position and come straight down (plunge). Think of it like a bulldozer cutting into the ground (ramp cutting) versus an excavator digging in one spot (plunge cutting). For cutting metal, plunge cutting will certainly shorten the life of the endmill. Since we are cutting wood I’m not going to worry about it. The ‘Cut Transfer’ tells the CNC how high to lift up when moving from one spot to another. Since the plywood I’m using is somewhat warped, I’ll use 0.25” to be sure the machine does not accidently cut into a high spot in the wood when it is moving.

alt text

Here we can see the tool path that has been created. If you look at the light blue colored lines you can see exactly where the endmill will be cutting. Hmm…wait a minute something doesn’t look right. The tool paths are on the inside of the part. If we run this, the panel will be too small!

alt text

Easy fix! I’ll just edit the tool path and change the ‘Cut Start Side’ from Left to Right. This will generate the tool path on the correct side.

alt text

That fixed the tool path for the panels. The cut marks are on the outside of the parts, which is what we want, but look at the LCD hole and button holes. Now they are on the outside. If we run the CNC now, they will be too big. So I guess we can’t select everything at the same time. I’ll do one tool path for the outlines and one for the LCD + buttons.

alt text

There! Now everything looks as it should. The tool paths are on the outside of the exterior and inside the interior of the parts we want to cut out. Those green lines show where the machine will raise the bit and move to a new area.

alt text

Now we can export the tool paths as G code. G code is a format in which the computer tells the CNC where to move, one point at a time. The CNC moves in a straight line from one point to the next. As you can imagine for a circle, there are lots and lots of coordinates. The CNC controller program we use is called Mach2 so I’ll tell it to export for that.

alt text

We’re almost there now! This is Mach2, the program that reads the G code and sends the pulse commands to the CNC machine. I’ll explain the areas that I highlighted.

G CODE – This is the G code that is loaded into the program. N10 stands for Line Number 1. The G command tells the computer that we want to move the cutting bit to a certain location without cutting anything. A person could write an entire tool path in word pad if they wanted. It might take a while though. Check out the wiki page for G code for a full list of all the codes!

POSITION – This is the current position of the center of the cutting bit as reported by the encoders on the CNC motors. X, Y, and Z are used here (we have a 3 axis CNC) but the 4th is not used.

USER SETTINGS – The Jog setting sets the speed limit for movement. If I want to manually move the CNC head to a certain spot, I can use the keyboard. If I tap an arrow key once, the CNC head will move a distance set in the Step box, in this case 0.001”. If I hold shift and press an arrow key, the CNC will move rapidly for as long as I hold the key. The ‘Slow Jog Rate’ limits the speed that the CNC can travel during the rapid movement.

Units/Min – This shows how fast the mill is traveling. When I cut wood, it will usually be around 15-30 inches per minute.

SPEED CONTROL – I didn’t show you this in Visual Mill, mostly because I hardly ever adjust it, but there are several speed setting for various things. We can set the speed at which material is cut, the speed at which the cutting bit goes up and down, the speed at which the CNC makes non-cutting movements, and other. The Speed Control lets us manually speed up or slow down all of these settings at the same time.

VISUALIZATION – This area shows 3 things. The lines in blue are what the mill is going to cut out, the green lines show where the mill has already cut (we haven’t cut anything yet), and the yellow crosshairs show where the center of the endmill is at.

The other setting I have only looked at and don’t need adjusting. Some other features here are not even available on our CNC. For example the Mist and Flood buttons control whether or not coolant is being sprayed on our part. We don’t have coolant on our CNC, so we don’t use this feature.

alt text

Once the machine is set up, it is time to get the wood into place. I’ll be using some run-of-the-mill 3/8" plywood. Because there will be large amounts of force pushing into the wood from the endmill, it is very important to secure the wood to the table. Our CNC has a grid pattern of threaded holes that allow pieces of any size and shape (okay, almost any size and shape) to be securely mounted to the bed.

alt text

Next, we need to tell the machine where the wood is located. Since we could have placed the wood at any random location on the bed, we need to make sure the machine knows where to start cutting. We do this by placing the center of the bit over the bottom left corner of the plywood and clicking the ‘Zero X’ and ‘Zero Y’ buttons shown in the POSITION box I labeled above. Because our plywood is larger than it needs to be, our positioning does not need to be exact. Anywhere near the bottom corner will be just fine.

alt text

Once that is all set, we can clicking the ‘Cycle Start’ button and watch in wonder as the parts are cut out. You will have to talk my word for it since you only get to see a picture, but trust me, it’s totally rad, bro.

alt text

Once the box was cut out, I stained it and fit the pieces together. I added all of the electronic components and glued them in.

alt text

Going Further

Wow, what a crazy ride! We went from a computer generated model all the way to a finished product. Sure, I could have bought a humidor, but what fun is that? What’s that? You don’t want to use drafting software to draw parts? Check out this box generator!

Check out another Creo example.


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


Creating a Humidor Control Box

$
0
0

Creating a Humidor Control Box a learn.sparkfun.com tutorial

Overview

In this tutorial, I am going to go through the process of how the SparkFun humidor was designed and built. A humidor is any kind of box or room with constant humidity, used to store cigars, cigarettes, pipe tobacco, or in this case sensors. I’ll be covering designing a 3D software model and fabricating it using a CNC router.

alt text

The finished project

Requirements

I realize the following list includes some items that are very expensive and probably not too common in everyone’s home/shop. I still wanted to show their use for someone who may not be familiar with these tools. Here is what I will be using:

  • Creo Parametric 2.0 (formerly Pro Engineer, FREE for educational purposes – Software)
  • Visual Mill 5 (Software)
  • Mach 2 CNC (Software)
  • K2 CNC Machine (Hardware)

Introduction

If you don’t already know, a CNC router is a computer controlled router capable of cutting out very complex shapes. CNC stands for Computer Numerical Control. The CNC machine is connected to a computer and is given very precise three dimensional coordinates to which the machine should move. Using a combination of motors and encoders, the machine is able to cut out nearly anything you can draw. There is lots to cover, so lets get started.

3D Design

Our Production department came to me needing a humidor built. They needed a better system to re-humidify a select few of our boards that need it after coming out of the reflow oven.

I am a very visual person. I like to see exactly what I have designed and how it fits together before I start making it. By doing this, it is easy to see where my mistakes are and correct them.

For this project, I designed both the humidor and the control box for it. The control box allows our Production team to select which board they are placing in the humidor, iit will keep track of the time it has been in there. It also makes sure the humidity stays at the required percentage. I’m not going to cover much of the humidor in this tutorial, however. I laser cut acrylic and epoxied it together in the shape of a box. When it was dry, I added some weather strip to the front door to seal it and put caulk in all the joints to ensure it was air tight. Not too much going on there!

The control box was really fun to make. I decided to cut ‘teeth’ in all of the edges so it would fit together like a 3D puzzle. Here at Sparkfun, we use Creo Parametric 2.0 for our 3D modeling. Our Arduino and breadboard holder was designed with this along with all of our retail clamshell packaging. I learned this program in High School, and of all the modeling software I have used along the way, it is my favorite. Before I begin, I want to tell you that this tutorial only scratches the surface of the feature in Creo. I’m only going to cover a few main points and features, there is certainly more than one way to do all of this. Let’s start designing!

(1) In the picture below, we are going to start drawing the top panel for the control box. The area with the labels ‘FRONT’, ‘TOP’, and ‘RIGHT’ is our workspace. We want to choose one that accurately describes the surface that we want to draw. Since this panel will go on the top side of the box, I am going to select the ‘TOP’ plane. Probably the most used feature is the Extrude command. This allows us to create material (or remove it) in the shape we want. So to recap, we choose the ‘TOP’ plane and click Extrude.

Choose Plane

(1) Choose Plane

(2) This brings us to the Sketcher. The Sketcher is where we draw the features that we want. Using the Rectangle command, I will draw a rectangle. I decided that I wanted the panel to be 8 inches wide and 6 inches tall. The dimensions are added automatically when I draw the rectangle. All I have to do it change them to what I want. Once they are correct, I click OK.

Draw!

(2) Draw Rectangle

(3) If the computer accepts the shape, it will add depth to it. This is where we move from a 2D drawing to a 3D model. Since I am cutting this out of plywood that is 0.35” thick, I will enter that in the box shown and click OK.

Time for 3D

(3) Time to go 3D!

(4) Next, I want to cut a hole for the LCD and a few buttons. I’ll select the surface that I want to create the 2D drawing on. In this case, I’ll choose the top of the panel. Once again, I’ll click the Extrude command for this. Remember: Extrude can add or remove material.

Cut LCD hole

(4) Select the surface to cut through

(5) After measuring the size of the LCD screen, I’ll use the Rectangle command to draw the hole where I want it. Now I want to add holes for the buttons. I want the buttons on the right side of the screen, and I want them to be lined up perfectly. I’m going to use what’s called a Centerline for this. You can think of a Centerline as a reference or helper line. In this picture, they are the purple dashed lines. When it comes time to create the 3D model, the computer will ignore these lines, so it doesn’t matter how many you have or where they are placed. Creo will create the center line where I click and it will ‘snap’ to a vertical position, ensuring the buttons are lined up perfectly with the panel.

Sketch cutouts

(5) Drawing the cut-outs

(6) By default, the Extrude command adds material. Since we want to do a cut out, we use the ‘Change Direction’ button on the left to tell the computer to cut away from where we drew the hole and also the ‘Remove Material’ button on the right to tell it to remove material. The result is what we want, a hole for the LCD and holes for buttons. I’ll repeat this process for the other buttons.

Extrude a cut

(6) Not what we want

Now it is cut

(6) After a few changes to the settings, it is correct

(7) Now it is time to create the ‘teeth’ for the edges. Like before, I select the top surface of the panel and click Extrude. In the Sketcher, I’ll draw a small rectangle that represents one of the teeth I want to cut out. The red color of the dimension indicates that I have locked the dimension. This prevents me or the computer from altering that particular dimension. For now, I am only going to draw one. I’ll show you why in the next step.

Create one tooth

(7) We only need to draw one tooth

(8) Now drawing 7 cutouts would not have taken too much time, but what if we needed to create 1000 teeth around a circular gear? That would take forever. To save time I will use the ‘Pattern’ command. This allows me to duplicate a feature that I had previously drawn. If you look at the red arrows in the picture below, from left to right:

  • Direction – tells the computer that you want to pattern in a straight line, as opposed to circular.
  • 1 Plane – if you look very carefully, the right side of the panel has an orange line, that is the direction I choose to move.
  • 7 – the number of copies I want to make.
  • 1.0625 – the spacing between each copy. The black dots represent where the computer will add the feature.

Pattern

(8) Setting up the pattern

Voilà! We have created the top 8 teeth for our box!

Confirming the pattern

(8) The pattern looks correct

(9) Since the top and bottom of the panel both use the same pattern, we can use the ‘Mirror’ command to do this easily. I’ll turn on the planes again and select the ‘FRONT’ plane because it runs through the center of the panel. Now the computer will take that single tooth that we drew and patterned and copy it to the bottom of the panel.

Mirror the pattern

(9) The Mirror command can save a great amount of time

(10) I’ll repeat these last few steps for the teeth on the left and right side of the panel. In the end, we have one part of the box done!

Repeat process

(10) The finished face plate of the controller

3D Assembly

(1) Using the same techniques as above, I went ahead and made the side walls and bottom piece for the box. Now that we have 6 individual parts of the box, let’s put them together! In a new file, I’ll import the control panel using the ‘Assemble’ command.

–>Time to assemble<–

(1)Assembling the box

(2) Next, I will tell the computer that I do not want this piece to move. I will be building all of the other parts around it, so it is nice to have it stay still. By right clicking on the part in the Model Tree, I can choose Fix Location. Mine is already fixed so the option to UnFix is displayed.

Fix location

(2) Fixing the location prevents it from moving

(3) Next, I will add another piece of the box. Using the Assemble command from before, I’ll bring in the part I want. If you look at the picture, the word ‘Coincidence’ appears several times. This is more or less the way to tell the computer to ‘make these two surfaces touch or line up.’ Simply put, I choose what surfaces should be lined up, and the computer will ‘glue’ them together.

Add more parts

(3)Adding more parts to the assembly

(4) Repeating the process four more times gives us a completed box! Now we can inspect all the sides to see if we made any mistakes in the length or position of any features.

Complete assembly

(4) The assembled box

(5) Let’s go ahead and add the LCD screen and buttons just for fun.

Add electronics

(5) Added the LCD and buttons

(6) We can now use the ‘Exploded View’ command to see the box as if it were taken apart.

Exploded viewt

(6)The exploded view with temporarily split apart the assembly

(7) Now that I box is designed, assembled, and inspected, we can get the files ready to cut out on the CNC router. In Creo, we want to create a new Drawing.

Create drawing

(7) Creating a new drawing

(8) Since we only care about the 2D feature of each part at this point, the parts can lay flat on the screen.

2D now

(8) The 3D model is no longer needed

(9) After adding all views we have the entire box laid out in front of us.

All parts

(9) Each part in a 2D view

(10) Lastly, we want to export this drawing as a .dxf file. This type of file is supported in many, many different types of programs so it is a good choice to use.

Export

(10) Exporting the drawing for later use

Creating Tool Paths

I’m using a program called Visual Mill to create the tool paths for the box. A Tool Path is the area that the CNC machine will follow to cut out our box.

(1) First I will open the .dxf file that we saved. Then we need to choose the size of the endmill we are going to use.

Open file, choose bit

(1) Open the file, choose the bit

(2) I am going to use a 1/8” endmill. We can enter in the specific feature of our tool if we need to. Everything looks good so I’ll choose OK.

Choose bit

(2) Select the ⅛” bit

(3) Next, I’m going to select everything that we want to cut out. Selected lines turn yellow so the user can tell they are selected. We want to do a ‘Profile’ type cut. A profile cut will cut around the inside or outside of the part and leave the center intact.

–>Select lines<–

(3) Select lines, choose cut type

(4) Next we have to define a few options. We set the ‘Tolerance’ to .001 inches for good accuracy. ‘Cut Direction’ tells the computer to cut either clockwise or counter clockwise. For wood, a ‘Conventional’ cut works well. This will make the cutting edge on the tool spin into the material (think of a car tire spinning on pavement as the car slowly creeps forward) and keep the wood from peeling off instead of being cut. And lastly ‘Cut Start Side’ tells the computer to either cut on the inside or outside of the selected lines. We want to cut on the outside.

–>alt text<–

(4) Setting cut parameters

(5) On the next tab, we define how deep to cut. This is why earlier in the tutorial I said we only care about the 2D features of the parts. ‘Total Cut Depth’ tells the computer; yep you guessed it, how deep we want to cut. Since the wood is 0.35” thick, let’s go 0.36” to be sure. The ‘Rough Depth’ and ‘Finish Depth’ are ways to allow the user to very precisely control how much the CNC cuts off at a given time. Since we are cutting wood and not metal, we don’t need to worry too much about this. I have told the machine to cut in depths of 0.09”. That means it will take 4 passes to cut through.

–>Parameters<–

(5) Setting the cut depth and step distance

(6) Lastly for this options box are the approaches and engage motions. Because the bit I have is a center cutting bit, I can do what is called plunge cutting. Some bits can drill straight down (plunge) through the material, while others cannot. This is because the teeth of some cutters do not extend all the way to the center of the bit. However, these cutters can cut downwards at an angle of 45 degrees or so (called ramp cutting). We can set all of these values to zero. This will make the mill move into position and come straight down (plunge). Think of it like a bulldozer cutting into the ground (ramp cutting) versus an excavator digging in one spot (plunge cutting). The ‘Cut Transfer’ tells the CNC how high to lift up when moving from one spot to another. Since the plywood I’m using is somewhat warped, I’ll use 0.25” to be sure the machine does not accidently cut into a high spot in the wood when it is moving.

Motions

(6) Telling the CNC how we want it to move

(7) Here we can see the tool path that has been created. If you look at the light blue colored lines you can see exactly where the endmill will be cutting. Hmm…wait a minute something doesn’t look right. The tool paths are on the inside of the part. If we run this, the panel will be too small!

Incorrect tool path

(7) Incorrect tool path

(8) Easy fix! I’ll just edit the tool path and change the ‘Cut Start Side’ from Left to Right. This will generate the tool path on the correct side.

Change the starting side

(8) Change the start side to correct the problem

(9) Well that fixed the tool path for the panels. The cut marks are on the outside of the parts, which is what we want, but look at the LCD hole and button holes. Now they are on the outside. If we run the CNC now, they will be too big. So I guess we can’t select everything at the same time. I’ll do one tool path for the outlines and one for the LCD + buttons.

Must create 2 different tool paths

(9) We’ll need 2 separate paths for this

(10) There! Now everything looks as it should. The tool paths are on the outside of the exterior and inside the interior of the parts we want to cut out. Those green lines show where the machine will raise the bit and move to a new area.

–>The correct tool path<–

(10) Everything looks correct now

(11) Now we can export the tool paths as G code. G code is a format in which the computer tells the CNC where to move, one point at a time. The CNC moves in a straight line from one point to the next. As you can imagine for a circle, there are lots and lots of coordinates. The CNC controller program we use is called Mach2 so I’ll tell it to export for that.

–>Export tool paths<–

(11) Exporting the tool paths

(12) We’re almost there now! This is Mach2 (see below), the program that reads the G code and sends the pulse commands to the CNC machine. I’ll explain the areas that I highlighted.

G CODE – This is the G code that is loaded into the program. N10 stands for Line Number 1. The G command tells the computer that we want to move the cutting bit to a certain location without cutting anything. A person could write an entire tool path in a text document if they wanted. It might take awhile though. Check out the wiki page for G code for a full list of all the codes!

POSITION – This is the current position of the center of the cutting bit as reported by the encoders on the CNC motors. X, Y, and Z are used here (we have a 3 axis CNC) but the 4th is not used.

USER SETTINGS – The Jog setting sets the speed limit for movement. If I want to manually move the CNC head to a certain spot, I can use the keyboard. If I tap an arrow key once, the CNC head will move a distance set in the Step box, in this case 0.001”. If I hold shift and press an arrow key, the CNC will move rapidly for as long as I hold the key. The ‘Slow Jog Rate’ limits the speed that the CNC can travel during the rapid movement.

Units/Min – This shows how fast the mill is traveling. When I cut wood, it will usually be around 15-30 inches per minute.

SPEED CONTROL – I didn’t show you this in Visual Mill, mostly because I hardly ever adjust it, but there are several speed setting for various things. We can set the speed at which material is cut, the speed at which the cutting bit goes up and down, the speed at which the CNC makes non-cutting movements, and other. The Speed Control lets us manually speed up or slow down all of these settings at the same time.

VISUALIZATION – This area shows 3 things. The lines in blue are what the mill is going to cut out, the green lines show where the mill has already cut (we haven’t cut anything yet), and the yellow crosshairs show where the center of the endmill is at.

Some other features here are not available on our CNC. For example the Mist and Flood buttons control whether or not coolant is being sprayed on our part. We don’t have coolant on our CNC, so we don’t use this feature.

Mach2

(12) The CNC control layout

Time to Cut

(1) Once the machine is set up, it is time to get the wood into place. I’ll be using some run-of-the-mill 3/8" plywood. Because there will be large amounts of force pushing into the wood from the endmill, it is very important to secure the wood to the table. Our CNC has a grid pattern of threaded holes that allow pieces of any size and shape (okay, almost any size and shape) to be securely mounted to the bed.

Secure the wood

(1) It is very important that the piece does not move

(2) Next we need to tell the machine where the wood is located. Since we could have placed the wood at any random location on the bed, we need to make sure the machine knows where to start cutting. We do this by placing the center of the bit over the bottom left corner of the plywood and clicking the ‘Zero X’ and ‘Zero Y’ buttons shown in the POSITION box I labeled in the previous section. Because our plywood is larger than it needs to be, our positioning does not need to be exact. Anywhere near the bottom corner will be just fine.

Setting the home

(2) Setting the (0,0) position

(3) Once that is all set, we can click the ‘Cycle Start’ button and watch in wonder as the parts are cut out. You will have to talk my word for it since you only get to see a picture. But trust me, it is really fun to watch!

–>Running the CNC<–

(3) One piece of the box

(4) Once the box was cut out, I stained it and fit the pieces together. I added all of the electronic components and glued them in.

Finished

(4) The finished box

Going Further

Wow, what a crazy ride! We went from a computer generated model all the way to a finished product. Sure, I could have bought a humidor, but what fun is that? What’s that? You don’t want to use drafting software to draw parts? Check out this box generator!

Check out another Creo example.


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

Using OpenSegment

$
0
0

Using OpenSegment a learn.sparkfun.com tutorial

Basics

OpenSegment 7-segment serial display

OpenSegment is a simple to use 7-segment display. It has the ability to communicate over serial, I2C, SPI, as well as analog and counter modes. It’s super easy to use if you just need to display a number but has a lot of features such as brightness levels and individual segment control built in.

OpegSegment as boxing counter

OpenSegment displaying the number of speed bag hits.

The OpenSegment is the big brother to Serial7Segment by Jim Lindblom. Both products use the same firmware but have different hardware layouts. Therefor, you can rely heavily on Jim’s datasheet for Serial7Segment and all the example code located here.

Things you may need to know before wiring up an OpenSegment:

Hardware Info

Mounted 7 segment display

SparkFun boxes make great enclosures!

OpenSegment can be powered from 4V (less bright) to 12V, but we recommend 5 to 6V. The default communication is 9600bps over serial.

Note: At any time the device can be reset to factory defaults (9600bps) by tying the RX pin to GND and powering up the device. See the Factory Reset section for more information.

Hardware Backpack

The onboard regulator will regulate down to 5V. The regulator will protect against shorts, reverse power, over current, and overheating. Powering the board with more than 7V is ok, but the regulator will begin to dissipate the extra power by heating up and—depending on the brightness setting and input voltage—may cause the board to flicker.

The OpenSegment has an ATmega328 running a modified Optiboot bootloader. It’s basically a little Arduino running at 8MHz. You can reprogram the board using a standard serial connection. We always have an FTDI basic handy to make code changes, but you shouldn’t ever have to reprogram the display unless you really want to tweak the code.

Serial Communication

Serial pins

The serial connection pins

The easiest way to control OpenSegment is over serial. You need only 3 pins: PWR, GND and RX. The RX pin on OpenSegment should be connected to the TX pin of your microcontroller.

JST Pins

The basic 3 pins, ready for a JST connector

The easiest way to physically connect to OpenSegment is through a 3-pin JST connector.

JST connector soldered

3-pin JST connector soldered in and ready to go!

Solder the JST onto the backpack, plug the JST cable in, and then plug the red wire to 5V to 7V, black wire to GND, and yellow wire to the TX pin of your development board.

Arduino Serial Example

Basic serial hookup

Connect 3 wires to your Arduino

Using an OpenSegment display with Arduino is very straightforward. Power the display from the 5V pin, GND, and connect the RX pin of the display to pin 8 on the Arduino.

Load the above example code onto your Arduino, and watch the display count up!

You can find many more examples here on GitHub. There are sketches to show you:

  • Basic counting
  • Controlling the colon and dots on a display
  • Changing the mode
  • Fun Predator mode
  • Changing the baud rate
  • Doing a software serial reset

I2C/SPI Communication

If you need to control lots of displays at the same time, OpenSegment has the ability to communicate over I2C and SPI.

I2C Communication

I2C pins

I2C communication requires 4 pins: SDA, SCL, PWR, and GND.

I2C side pins

The I2C pins are labeled on the edge of the backpack and on the sides to make it easier to chain many displays together.

The default I2C address is 113 in base10 or 0x71 in HEX or 01110001 in binary. Checkout the I2C examples on GitHub for good code to start from.

SPI Communication

SPI pins

Bank of SPI pins

SPI communication requires 6 pins: SDO, SDI, SCK, CS, PWR, and GND. We may add a feature in the future, but for now OpenSegment does not pass data out of the SDO (serial data out) pin and can be left disconnected. If you’re hooking multiple OpenSegments together on the same SPI bus, the CS pin on each display must be connected to a different GPIO on your microcontroller.

Checkout the SPI examples on GitHub for good code to start from.

Counter/Analog Modes

OpenSegment has three modes:

  • Data mode (where you send commands and data over Serial/SPI/I2C)
  • Counter mode (count up/down based on SDI/SDO)
  • Analog meter mode (display analog voltages on A6/A7)

We’ve covered the basic data mode; let’s cover the other two modes.

To control the mode of the display, send the command 0x82 over serial followed by:

  • 0 for data mode
  • 1 for analog meter mode
  • 2 for counter mode

An example of how to do this over serial is available here.

You do not need to solder the jumper to control the mode. Please read the solder jumper section below for more information.

Counter Mode

alt text

The counter jumper and the two pins that control the count.

When the display is in Counter mode, the display will increase by one every time the SDI pin (i is for increase!) is pulled low and will decrease by one every time the SDO pin is pulled low. This mode was created to monitor and count the number of times a button is pressed or a reed switch is closed. The display must be power cycled to reset the count.

Analog Meter Mode

Analog pins on OpenSegment

When the display is in Analog mode the instantaneous analog voltage on pins A7 and A6 will be shown on the display with 1/10th volt resolution (0.0V to 5.0V).

The voltage on A6 is displayed on the left and A7 is displayed on the right. This mode was created to monitor basic voltages (0 to 5V) without the need of a multimeter.

Solder Jumpers

Solder jumpers

You can use OpenSegment as a counter and as an analog meter without any software configuration. By closing a solder jumper on the back of the display OpenSegment will enter one of two modes: Counter or Analog Meter mode.

Closing a solder jumper will override any software settings and will force the display into that mode after power up. If both jumpers are closed the display will startup in Counter mode.

Factory Reset

Have you forgotten what baud rate the device has been configured to? Don’t worry! The device can be reset to factory defaults by tying the RX pin to GND and then powering up the device.

Dashes during resetDashes during reset

Once powered up you will see alternating – (dashes) and _ (underscores) for 1 second.

Reset stateReset state

Once you see a rotating display of 0-00 you will know the device has been reset to 9600bps. You can now release the RX pin from ground, and the display will continue to function normally.

There is also an example sketch to show you how to do a reset over serial. This can be handy if the display is installed in an application and you can’t pull the RX line low during power up.

Further Reading

You should now be able to control the OpenSegment with serial and a few other methods. Be sure to checkout the example code and datasheet for more information.

Now that you’ve got your OpenSegment figured out, you should consider reading about:


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

What is an Arduino?

$
0
0

What is an Arduino? a learn.sparkfun.com tutorial

Introduction

Arduino is an open-source platform used for building electronics projects. Arduino consists of both a physical programmable circuit board (often reffered to as a microcontroller) and a piece of software, or IDE (Integrated Development Environment) that runs on your computer, used to write and upload computer code to the physical board.

The Arduino platform has become quite popular with people just starting out with electronics, and for good reason. Unlike most previous programmable circuit boards, the Arduino does not need a separate piece of hardware (called a programmer) in order to load new code onto the board—you can simply use a USB cable. Additionally, the Arduino IDE uses a simplified version of C++, making it easier to learn to program. Finally, Arduino provides a standard form factor that breaks out the functions of the micro-controller into a more accessible package. For more info about the Arduino, check here and here.

alt text

This is an Arduino Uno

The Uno is one of the more popular boards in the Arduino family and a great choice for beginners. We’ll talk about what’s on it and what it can do later in the tutorial.

This is a screenshot of the Arduino IDE:

Arduino Uno

Believe it or not, those 10 lines of code are all you need to blink the on-board LED on your Arduino. The code might not make perfect sense right now, but our tutorials on getting started with Arduino will get you up to speed in no time!

In this tutorial, we’ll go over some of the things you can do with an Arduino, what’s on the typical Arduino board, and some of the different kinds of Arduino boards.

We will learn:

  • What you might use an Arduino for
  • What is on the typical Arduino board and why
  • The different varieties of Arduino boards
  • Some useful widgets to use with your Arduino

You may want to know about these concepts to help you with this tutorial:

What does it do?

The Arduino hardware and software was designed for artists, designers, hobbyists, hackers, newbies, and anyone interested in creating interactive objects or environments. Arduino can interact with buttons, LEDs, motors, speakers, GPS units, cameras, the internet, and even your smart-phone or your TV! This flexibility combined with the fact that the Arduino software is free, the hardware boards are pretty cheap, and both the software and hardware are easy to learn has led to a large community of users who have contributed code and released instructions for a huge variety of Arduino-based projects.

For everything from RC robot and car controls and a heating pad hand warming blanket to honest fortune-telling machines, and even a Dungeons and Dragons dice-throwing gauntlet, the Arduino can be used as the brains behind almost any electronics project.

alt text

Yes, Dia really did build a D&D Dice throwing gauntlet. She is that cool.

And that’s really just the tip of the iceberg — if you’re curious about where to find more examples of Arduino projects in action, here are some good resources for Arduino-based projects to get your creative juices flowing:

What's on the board?

There are many varieties of Arduino boards (explained on the next page) that can be used for different purposes. Some boards look a bit different from the one below, but most Arduinos have the majority of these components in common:

alt text

Power (USB / Barrel Jack)

Every Arduino board needs a way to be connected to a power source. The Arduino UNO can be powered from a USB cable coming from your computer or a wall power supply (like this) that is terminated in a barrel jack. In the picture above the USB connection is labeled (1) and the barrel jack is labeled (2).

The USB connection is also how you will load code onto your Arduino board. More on how to program with Arduino can be found in our Installing and Programming Arduino tutorial.

NOTE: Do NOT use a power supply greater than 20 Volts as you will overpower (and thereby destroy) your Arduino. The recommended voltage for most Arduino models is between 6 and 12 Volts.

Pins (5V, 3.3V, GND, Analog, Digital, PWM, AREF)

The pins on your Arduino are the places where you connect wires to construct a circuit (probably in conjuction with a breadboard and some wire. They usually have black plastic ‘headers’ that allow you to just plug a wire right into the board. The Arduino has several different kinds of pins, each of which is labeled on the board and used for different functions.

  • GND (3): Short for ‘Ground’. There are several GND pins on the Arduino, any of which can be used to ground your circuit.
  • 5V (4) & 3.3V (5): As you might guess, the 5V pin supplies 5 volts of power, and the 3.3V pin supplies 3.3 volts of power. Most of the simple components used with the Arduino run happily off of 5 or 3.3 volts. If you’re not sure, take a look at our datasheet tutorial then look up the datasheet for your part.
  • Analog (6): The area of pins under the ‘Analog In’ label (A0 through A5 on the UNO) are Analog In pins. These pins can read the signal from an analog sensor (like a temperature sensor) and convert it into a digital value that we can read.
  • Digital (7): Across from the analog pins are the digital pins (0 through 13 on the UNO). These pins can be used for both digital input (like telling if a button is pushed) and digital output (like powering an LED).
  • PWM (8): You may have noticed the tilde (~) next to some of the digital pins (3, 5, 6, 9, 10, and 11 on the UNO). These pins act as normal digital pins, but can also be used for something called Pulse-Width Modulation (PWM). We have a tutorial on PWM, but for now, think of these pins as being able to simulate analog output (like fading an LED in and out).
  • AREF (9): Stands for Analog Reference. Most of the time you can leave this pin alone. It is sometimes used to set an external reference voltage (between 0 and 5 Volts) as the upper limit for the analog input pins.

Reset Button

Just like the original Nintendo, the Arduino has a reset button (10). Pushing it will temporarily connect the reset pin to ground and restart any code that is loaded on the Arduino. This can be very useful if your code doesn’t repeat, but you want to test it multiple times. Unlike the original Nintendo however, blowing on the Arduino doesn’t usually fix any problems.

Power LED Indicator

Just beneath and to the right of the word “UNO” on your circuit board, there’s a tiny LED next to the word ‘ON’ (11). This LED should light up whenever you plug your Arduino into a power source. If this light doesn’t turn on, there’s a good chance something is wrong. Time to re-check your circuit!

TX RX LEDs

TX is short for transmit, RX is short for receive. These markings appear quite a bit in electronics to indicate the pins responsible for serial communication. In our case, there are two places on the Arduino UNO where TX and RX appear — once by digital pins 0 and 1, and a second time next to the TX and RX indicator LEDs (12). These LEDs will give us some nice visual indications whenever our Arduino is receiving or transmitting data (like when we’re loading a new program onto the board).

Main IC

The black thing with all the metal legs is an IC, or Integrated Circuit (13). Think of it as the brains of our Arduino. The main IC on the Arduino is slightly different from board type to board type, but is usually from the ATmega line of IC’s from the ATMEL company. This can be important, as you may need to know the IC type (along with your board type) before loading up a new program from the Arduino software. This information can usually be found in writing on the top side of the IC. If you want to know more about the difference between various IC’s, reading the datasheets is often a good idea.

Voltage Regulator

The voltage regulator (14) is not actually something you can (or should) interact with on the Arduino. But it is potentially useful to know that it is there and what it’s for. The voltage regulator does exactly what it says — it controls the amount of voltage that is let into the Arduino board. Think of it as a kind of gatekeeper; it will turn away an extra voltage that might harm the circuit. Of course, it has its limits, so don’t hook up your Arduino to anything greater than 20 volts.

The Arduino Family

Arduino makes several different boards, each with different capabilities. In addition, part of being open source hardware means that others can modify and produce derivatives of Arduino boards that provide even more form factors and functionality. If you’re not sure which one is right for your project, check this guide for some helpful hints. Here are a few options that are well-suited to someone new to the world of Arduino:

Arduino Uno (R3)

The Uno is a great choice for your first Arduino. It’s got everything you need to get started, and nothing you don’t. It has 14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analog inputs, a USB connection, a power jack, a reset button and more. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started.

alt text

LilyPad Arduino

This is LilyPad Arduino main board! LilyPad is a wearable e-textile technology developed by Leah Buechley and cooperatively designed by Leah and SparkFun. Each LilyPad was creatively designed with large connecting pads and a flat back to allow them to be sewn into clothing with conductive thread. The LilyPad also has its own family of input, output, power, and sensor boards that are also built specifically for e-textiles. They’re even washable!

alt text

RedBoard

At SparkFun we use many Arduinos and we’re always looking for the simplest, most stable one. Each board is a bit different and no one board has everything we want — so we decided to make our own version that combines all our favorite features.

The RedBoard can be programmed over a USB Mini-B cable using the Arduino IDE. It’ll work on Windows 8 without having to change your security settings (we used signed drivers, unlike the UNO). It’s more stable due to the USB/FTDI chip we used, plus it’s completely flat on the back, making it easier to embed in your projects. Just plug in the board, select “Arduino UNO” from the board menu and you’re ready to upload code. You can power the RedBoard over USB or through the barrel jack. The on-board power regulator can handle anything from 7 to 15VDC.

alt text

Arduino Mega (R3)

The Arduino Mega is like the UNO’s big brother. It has lots (54!) of digital input/output pins (14 can be used as PWM outputs), 16 analog inputs, a USB connection, a power jack, and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started. The large number of pins make this board very handy for projects that require a bunch of digital inputs or outputs (like lots of LEDs or buttons).

alt text

Arduino Leonardo

The Leonardo is Arduino’s first development board to use one microcontroller with built-in USB. This means that it can be cheaper and simpler. Also, because the board is handling USB directly, code libraries are available which allow the board to emulate a computer keyboard, mouse, and more!

alt text

The Extended Family

While your Arduino board sure is pretty, it can’t do a whole lot on its own — you’ve got to hook it up to something. There are lots of tutorials here on learn as well as the links back in the ‘What does it do’ section, but rarely do we talk about the general kinds of things you can easily hook into. In this section we’ll introduce basic sensors as well as Arduino shields, two of the most handy tools to use in bringing your projects to life.

Sensors

With some simple code, the Arduino can control and interact with a wide variety of sensors– things that can measure light, temperature, degree of flex, pressure, proximity, acceleration, carbon monoxide, radioactivity, humidity, barometric pressure, you name it, you can sense it!

alt text

Just a few of the sensors that are easily compatible with Arduino

Shields

Additionally, there are these things called shields— basically they are pre-built circuit boards that fit on top of your Arduino and provide additional capabilities — controlling motors, connecting to the internet, providing cellular or other wireless communication, controlling an LCD screen, and much more.

alt text

A partial selection of available shields to extend the power of your Arduino

For more on shields, check out:

Further Reading

Now that you know all about the Arduino family, which board you might want to use for your project, and that there are tons of sensors and shields to help take your projects to the next level. Here’s some further reading that may help you along in learning more about the world of electronics:


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

Pulse Width Modulation

$
0
0

Pulse Width Modulation a learn.sparkfun.com tutorial

Pulse Width Modulation

Pulse width modulation is a fancy term for describing a type of digital signal. Pulse width modulation is used in a variety of applications including sophisticated control circuitry. A common way we use them here at SparkFun is to control dimming of RGB LEDs or to control the direction of a servo motor. We can accomplish a range of results in both applications because pulse width modulation allows us to vary how much time the signal is high in an analog fashion. While the signal can only be high (usually 5V) or low (ground) at any time, we can change the proportion of time the signal is high compared to when it is low over a consistent time interval.

Two servo motors used to control the pan/tilt of a robotic claw with PWM

Robotic claw controlled by a servo motor using Pulse Width Modulation

Some background tutorials you might consider first:

Duty Cycle

When the signal is high, we call this “on time”. To describe the amount of “on time” , we use the concept of duty cycle. Duty cycle is measured in percentage. The percentage duty cycle specifically describes the percentage of time a digital signal is on over an interval or period of time. This period is the inverse of the frequency of the waveform.

If a digital signal spends half of the time on and the other half off, we would say the digital signal has a duty cycle of 50% and resembles an ideal square wave. If the percentage is higher than 50%, the digital signal spends more time in the high state than the low state and vice versa if the duty cycle is less than 50%. Here is a graph that illustrates these three scenarios:

Duty Cycle Percentage reflects percentage of 'on' time per interval

50%, 75%, and 25% Duty Cycle Examples

100% duty cycle would be the same as setting the voltage to 5 Volts (high). 0% duty cycle would be the same as grounding the signal.

Examples

You can control the brightness of an LED by adjusting the duty cycle.

Three dim LEDs

PWM used to control LED brightness

With an RGB (red green blue) LED, you can control how much of each of the three colors you want in the mix of color by dimming them with various amounts.

Red + Blue = Purple... etc

Basics of color mixing

If all three are on in equal amounts, the result will be white light of varying brightness. Blue equally mixed with green will get teal. As slightly more complex example, try turning red fully on, and green 50% duty cycle and blue fully off to get an orange color.

pick a color in the spectrum, then use PWM to achieve it

PWM can be used to mix RGB color

The frequency of the square wave does need to be sufficiently high enough when controlling LEDs to get the proper dimming effect. A 20% duty cycle wave at 1 Hz will be obvious that it’s turning on and off to your eyes meanwhile, 20% duty cycle at 100 Hz or above will just look dimmer than fully on. Essentially, the period can not be too large if you’re aiming for a dimming effect with the LEDs.

You can also use pulse width modulation to control the angle of a servo motor attached to something mechanical like a robot arm. Servos have a shaft that turns to specific position based on its control line. Our servo motors have a range of about 180 degrees.

Frequency/period are specific to controlling a specific servo. A typical servo motor expects to be updated every 20 ms with a pulse between 1 ms and 2 ms, or in other words, between a 5 and 10% duty cycle on a 50 Hz waveform. With a 1.5 ms pulse, the servo motor will be at the natural 90 degree position. With a 1 ms pulse, the servo will be at the 0 degree position, and with a 2 ms pulse, the servo will be at 180 degrees. You can obtain the full range of motion by updating the servo with an value in between.

Servo Motor at a controlled specific angle

PWM used to hold a servo motor at 90 degrees relative to its bracket

Going Further

Pulse width modulation is used in a variety of applications particularly for control. You already know it can be used for the dimming of LEDs and controlling the angle of servo motors and now you can begin to explore other possible uses. If you feel lost, feel free to check out the SparkFun Inventor’s Kit which has examples using pulse width modulation. If you’re ready to jump into coding immediately and have an Arduino, look at the PWM coding example here.

Feel free to keep exploring:


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

Programming the pcDuino

$
0
0

Programming the pcDuino a learn.sparkfun.com tutorial

Introduction

The pcDuino board

The beauty of the pcDuino lies in its extraordinarily well exposed hardware peripherals. However, using these peripherals is more complex than using them on, say, an Arduino-compatible board.

This tutorial will help you sort out the various peripherals, what they can do, and how to use them.

Before we get started, there are a few things you should be certain you’re familiar with, to get the most out of this tutorial:

  • pcDuino– some familiarity with the basics of the pcDuino is needed before you jump into this. Please review our Getting Started with pcDuino tutorial before going any further.
  • Linux – the biggest thing you should be familiar with it the Linux OS. Remember, pcDuino is not an Arduino—it is a modern microcomputer running a fully-functional, if compact, operating system.
  • SPI– a synchronous (clocked) serial peripheral interface used for communications between chips at a board level. Requires a minimum of four wires (clock, master-out-slave-in data, master-in-slave-out data, and slave chip select), and each additional chip added to the bus requires one extra chip select line.
  • I2C– also known as IIC (inter-integrated circuit), SMBus, or TWI (two-wire interface), I2C uses only two wires (bidirectional data and clock lines) to communicate with multiple devices.
  • Serial Communication– an asynchronous (no transmitted clock) data interface with at least two wires (data transmit and data receive; sometimes, additional signals are added to indicate when a device is ready to send or receive).
  • Pulse Width Modulation– a digital-to-analog conversion technique using a fixed frequency square wave of varying duty cycle, which can be easily converted to an analog signal between 0V and the full amplitude of the digital IC driving the signal.
  • Analog-to-Digital Conversion– measurement of an analog voltage and conversion of that voltage into a digital value.

All of the code in this tutorial can be found online, in our pcDuino Github repository. It’s not a bad idea to check there for any updates to the code since this tutorial was written.

Your First Program

Even if you’ve programmed Linux computers before, it may be a good idea to give this section a brief run-through, just to make sure you know what to do for this particular device. If you’ve never written any code for anything more advanced than an Arduino, that’s okay, too! We’ll get you started.

This tutorial is going to cover two different languages: Python 2.7 and C++. It is not meant to be a “learn to program” tutorial; rather, it’s meant to introduce and provide examples for accessing the various resources on the pcDuino, as well as getting code to compile and run.

C++ Programming

Compiling and running a C++ program is pretty easy. All you need to do is invoke the g++ compiler pointed at a source file and it will build an executable of that file.

Let’s give it a try. Open a new LeafPad document and type in this code:

language:cpp
#include <stdio.h> // Include the standard IO library.

int main(void) // For C++, main *must* return type int!
{
  printf("Hello, world!\n"); // Print "Hello, world!" string to the command line.
}

Save the file with the name “hello_world.cpp” to any convenient directory (say, “~/Documents”), then open an LXTerm window and navigate to that directory. At the command prompt, type these commands:

language:text
g++ hello_world.cpp -o hello_world
./hello_world

Here’s what your command line output should look like (note that, for most examples in this tutorial, I’m running the commands in a PuTTY terminal on Windows, to make my life a little easier—that’s why the menu bar looks different to LXTerm):

Hello world C++ output

So, there you have it: your first C++ program written and run on the pcDuino!

Python Programming

Python programming is even easier than C++. Python is an interpreted language, which means that there’s no compilation step which produces an executable. The code you write gets executed line-by-line by the interpreter. There’s a price to pay in terms of performance, in most cases, but the ease of coding in Python, coupled with incredibly powerful libraries, makes it very attractive.

Open another Leafpad document and put this code in:

language:python
print "Hello, world!"

That’s it. Simple, innit? Now, save that file to a convenient location as “hello_world.py”, and get an LXTerm prompt in that directory. Type in the following command:

language:text
python hello_world.py

Your output should look a lot like this:

Hello world Python output

And that’s Python. If you haven’t used Python before, I strongly suggest you give it a try—it’s insanely powerful. All of the examples in this tutorial will be done in both C++ and Python; it will quickly become obvious why Python is a favorite for getting good results, fast.

Accessing GPIO Pins

The pcDuino comes with 18 pins that can be accessed as, among other things, general purpose I/O.

Hardware

Accessing GPIO pins is not hard; simply open the file associated with the pin you wish to access and read or write that file. The files are located in the following locations:

language:text
/sys/devices/virtual/misc/gpio/mode/
/sys/devices/virtual/misc/gpio/pin/

Each pin has its own file. Note that there are 20 files; only 18 of them are actually mapped to available pins. The files map to the pins as seen in the image below:

GPIO pin mapping on the pcDuino

Some pins can do double (or triple) duty. Writing certain strings to the “mode” file will activate the various different modes (serial, SPI, input, output, etc) for the particular pin you’re accessing; we’ll cover those different values in later exercises. For now, you really only need to worry about three of them:

  • ‘0’ – make the pin an INPUT
  • ‘1’ – make the pin an OUTPUT
  • ‘8’ – make the pin an INPUT, with a pull-up resistor

The logic on these pins is 3.3V; attempting to use 5V devices can cause damage to your pcDuino. The output current capacity is not as high as it is on Arduino-type boards, but should be sufficient to drive a small LED fairly easily.

GPIO in C++

Here is an example program for using C++ to read and write GPIO pins. It’s pretty simple: it waits for a button attached to GPIO2 to be pressed (thereby pulling the pin low), then turns LEDs attached to the various GPIO pins on one at a time, then back off again.

language:cpp
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "gpio_test.h"

// These arrays will become file descriptors for the 18 IO pin and mode files.
int pinMode[18];
int pinData[18];

int main(void)
{
  int i = 0;       // Loop iterator

  char inputBuffer = HIGH; // create and clear a buffer for data from pins

  char path[256]; // nice, long buffer to hold the path name for pin access

  // This first loop does four things:
  //   - initialize the file descriptors for the pin mode files
  //   - initialize the file descriptors for the pin data files
  //   - make the pins outputs
  //   - set all the pins low
  for (i = 2; i <= 17; i++)
  {
    // Clear the path variable...
    memset(path,0,sizeof(path));
    // ...then assemble the path variable for the current pin mode file...
    sprintf(path, "%s%s%d", GPIO_MODE_PATH, GPIO_FILENAME, i);
    // ...and create a file descriptor...
    pinMode[i] = open(path, O_RDWR);
    // ...then rinse, repeat, for the pin data files.
    memset(path,0,sizeof(path));
    sprintf(path, "%s%s%d", GPIO_PIN_PATH, GPIO_FILENAME, i);
    pinData[i] = open(path, O_RDWR);
    // Now that we have descriptors, make the pin an output, then set it low.
    setPinMode(pinMode[i], OUTPUT);
    setPin(pinData[i], LOW);
    printf("Pin %d low\n", i);  // Print info to the command line.
  }

  // Now, we're going to wait for a button connected to pin 2 to be pressed
  //  before moving on with our demo.
  setPinMode(pinMode[2], INPUT_PU);

  do
  {
    printf("Waiting for button press...\n");
    // This lseek() is very important- must read from the top of the file!
    lseek(pinData[2], 0, SEEK_SET);
    // Read one byte from the pinData register. The first byte will be '1' if
    //   the pin is high and '0' if it is low.
    read(pinData[2], &inputBuffer, 1);
    usleep(100000);       // Sleep for 1/10 second.
  } while (inputBuffer == HIGH);

  // After the button press, let's scan through and turn the lights on one
  //   at a time, the back off again. After that, we're done.
  for (i = 3; i <= 17; i++)
  {
    setPin(pinData[i], HIGH);
    printf("Pin %d HIGH\n", i);
    usleep(250000);
  }

  for (i = 17; i >=3; i--)
  {
    setPin(pinData[i], LOW);
    printf("Pin %d LOW\n", i);
    usleep(250000);
  }
}

// These two 'set' functions are just wrappers to the writeFile() function to
//   make the code prettier.
void setPinMode(int pinID, int mode)
{
  writeFile(pinID, mode);
}

void setPin(int pinID, int state)
{
  writeFile(pinID, state);
}

// While it seems okay to only *read* the first value from the file, you
//   seemingly must write four bytes to the file to get the I/O setting to
//   work properly. This function does that.
void writeFile(int fileID, int value)
{
  char buffer[4];  // A place to build our four-byte string.
  memset((void *)buffer, 0, sizeof(buffer)); // clear the buffer out.
  sprintf(buffer, "%c", value);
  lseek(fileID, 0, SEEK_SET);   // Make sure we're at the top of the file!
  write(fileID, buffer, sizeof(buffer));
}

GPIO Access in Python

Here’s the same program realized in Python. Again, it simply waits for a button on GPIO2 to be pressed, then scans through the other GPIO pins, making them first high, then low.

language:python
#!/usr/bin/env python

import time, os

## For simplicity's sake, we'll create a string for our paths.
GPIO_MODE_PATH= os.path.normpath('/sys/devices/virtual/misc/gpio/mode/')
GPIO_PIN_PATH=os.path.normpath('/sys/devices/virtual/misc/gpio/pin/')
GPIO_FILENAME="gpio"

## create a couple of empty arrays to store the pointers for our files
pinMode = []
pinData = []

## Create a few strings for file I/O equivalence
HIGH = "1"
LOW =  "0"
INPUT = "0"
OUTPUT = "1"
INPUT_PU = "8"

## First, populate the arrays with file objects that we can use later.
for i in range(0,18):
  pinMode.append(os.path.join(GPIO_MODE_PATH, 'gpio'+str(i)))
  pinData.append(os.path.join(GPIO_PIN_PATH, 'gpio'+str(i)))

## Now, let's make all the pins outputs...
for pin in pinMode:
  file = open(pin, 'r+')  ## open the file in r/w mode
  file.write(OUTPUT)      ## set the mode of the pin
  file.close()            ## IMPORTANT- must close file to make changes!

## ...and make them low.
for pin in pinData:
  file = open(pin, 'r+')
  file.write(LOW)
  file.close()

## Next, let's wait for a button press on pin 2.
file = open(pinMode[2], 'r+') ## accessing pin 2 mode file
file.write(INPUT_PU)          ## make the pin input with pull up
file.close()                  ## write the changes

temp = ['']   ## a string to store the value
file = open(pinData[2], 'r') ## open the file
temp[0] = file.read()       ## fetch the pin state

## Now, wait until the button gets pressed.
while '0' not in temp[0]:
  file.seek(0)      ## *MUST* be sure that we're at the start of the file!
  temp[0] = file.read()   ## fetch the pin state
  print "Waiting for button press..."
  time.sleep(.1)  ## sleep for 1/10 of a second.

file.close()  ## Make sure to close the file when you're done!

## Now, for the final trick, we're going to turn on all the pins, one at a
##   time, then turn them off again.
for i in range(3,17):
  file = open(pinData[i], 'r+')
  file.write(HIGH)
  file.close()
  time.sleep(.25)

for i in range(17,2, -1):
  file = open(pinData[i], 'r+')
  file.write(LOW)
  file.close()
  time.sleep(.25)

Analog Input and Output

Unlike the Raspberry Pi, the pcDuino does have some analog input and output functionality. Here are examples of using the analog circuitry in your projects.

Hardware

Analog pin mapping on the pcDuino

Analog output on the pcDuino is accomplished via PWM. There are six PWM enabled pins in the Arduino-ish headers: 3, 5, 6, 9, 10, and 11. These, of course, correspond to the PWM pins on Arduino boards. Pins 5 and 6 are true 520Hz 8-bit PWM; the others are limited to a range of 0-20 at 5Hz. The high-level output for all the pins is 3.3V.

Analog input on the pcDuino is done through six dedicated pins labeled A0-A5 on the Arduino-ish headers. A0 and A1 are six-bit inputs, returning a value from 0-63 over a range from 0-2V; A2-A5 are 12-bit inputs operating across the full 3.3V range. Setting an analog reference on the AREF pin is not supported as of the time of this writing.

Analog in C++

Analog input is handled through standard file stream input: simply open the appropriate file and read the value. Values are read as a string, so an atoi() conversion is necessary to get an integer value to work with.

Analog output is handled through a command line interface. Piping a value into a particular file via the system() call allows you to set the PWM level on the appropriate pins; file streams do not work for this. Again, the file expects a string, not an integer, so you must format the output appropriately.

This example program fades the PWM pins from off to on, slowly, then prints the output of each analog input.

language:cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "analog.h"

int adc[6];     // Array for file descriptors for the adc pins
int PWMMaxVal[6]; // Store the max values for the PWM outputs
char path[64];  // Nice big buffer for constructing file paths

int main(void)
{
  // For starters, let's create file descriptors for all the ADC pins. PWM is
  //   handled differently; see the analogWrite() function for details.
  for(int i = 0; i<= 5; i++)
  {
    memset(path, 0, sizeof(path));
    sprintf(path, "%s%s%d", ADC_IF_PATH, ADC_IF_FILE , i);
    adc[i] = open(path, O_RDONLY);
    memset(path, 0, sizeof(path));
    sprintf(path, "%s%s%d/%s", PWM_IF_PATH, PWM_IF_FILE , i, PWM_MAX);
    int PWMMaxFD = open(path, O_RDONLY);
    char PWMMaxStr[4];
    read(PWMMaxFD, PWMMaxStr, sizeof(PWMMaxStr));
    PWMMaxVal[i] = atoi(PWMMaxStr);
  }

  // Now, we'll blast all the PWM pins to zero.
  for(int j = 0; j<=5; j++)
  {
    analogWrite(j, 0);
  }

  // Now we can go about the business of dimming some LEDs.
  for(int j = 0; j<=5; j++)
  {
    for(int i = 0; i<=255; i++)
    {
      analogWrite(j, i);
      usleep(10000);
    }
    analogWrite(j, 0);
  }

  // Analog input is handled by file streams.
  for (int i = 0; i <= 5; i++)
  {
    char ADCBuffer[16];
    lseek(adc[i], 0, SEEK_SET);
    int res = read(adc[i], ADCBuffer, sizeof(ADCBuffer));
    int ADCResult = atoi(ADCBuffer);
    printf("ADC Channel: %d Value: %s", i, ADCBuffer);
  }
}

  // PWM pin access is handled by
  //   using the system() command to invoke the command process to execute a
  //   command. We assemble the command using sprintf()- the command takes
  //   the form
  //   echo <value> > /sys/class/leds/pwmX/brightness
  //   where <value> should be replaced by an integer from 0-255 and X should
  //   be replaced by an index value from 0-5
void analogWrite(int pin, int value)
{
  memset(path, 0, sizeof(path));
  value = (PWMMaxVal[pin] * value)/255;
  sprintf(path, "echo %d > %s%s%d/%s", value, PWM_IF_PATH, PWM_IF_FILE, \
    pin, PWM_IF);
  system(path);
}

Analog in Python

As usual, the Python code mirrors C++ functionally, but is somewhat simpler. The code performs a very similar operation to the C++ program—fade the PWM pins, then spit out the analog inputs.

language:python
#!/usr/bin/env python

import time, os

## For simplicity's sake, we'll create a strings and filenames for our paths
ADC_PATH= os.path.normpath('/proc/')
ADC_FILENAME = "adc"
PWM_PATH= os.path.normpath('/sys/class/leds/')
PWM_DIR = "pwm"
PWM_FILENAME = "brightness"
PWM_MAX = "max_brightness"

## create empty arrays to store the pointers for our files
adcFiles = []
pwmFiles = []
pwmMaxFiles = []

## create an empty array to store the maximum value for each channel of PWM
pwmMaxVal = []

## Populate the arrays with paths that we can use later.
for i in range(0,6):
  adcFiles.append(os.path.join(ADC_PATH, ADC_FILENAME+str(i)))
  pwmFiles.append(os.path.join(PWM_PATH, PWM_DIR+str(i), PWM_FILENAME))
  pwmMaxFiles.append(os.path.join(PWM_PATH, PWM_DIR+str(i), PWM_MAX))

## Now, let's scan the PWM directories and pull out the values we should use
##   for the maximum PWM level.
for file in pwmMaxFiles:
  fd = open(file, 'r')
  pwmMaxVal.append(int(fd.read(16)))
  fd.close()

## Let's dim some LEDs! The method for controlling a PWM pin on the pcDuino is
##   to send to the command interpreter (via os.system() this command:
##   echo <value> > /sys/class/leds/pwmX/brightness
##   where <value> varies from 0 to the maximum value found in the
##   max_brightness file, and X can be from 0-5.
for file in pwmFiles:
  j = pwmFiles.index(file)  ## extract the PWM limit for this LED
  for i in range (0,pwmMaxVal[j]):
    os.system("echo " + str(i) + ">" + file)
    time.sleep(.01)
  os.system("echo 0 >" + file)

## Reading ADC values is a little more straightforward than PWM- it's just
##   classic OS file reads. Note that the value that comes out of the file is
##   a string, so you'll need to format it with int() if you want to do math
##   with that value later on!
for file in adcFiles:
  fd = open(file, 'r')
  fd.seek(0)
  print "ADC Channel: " + str(adcFiles.index(file)) + " Result: " + fd.read(16)
  fd.close()

Serial Communications

The pcDuino comes with several built-in serial ports. Here’s how to use those ports to send and receive data from within a program.

Hardware

Serial port pin mapping on the pcDuino

The A10 processor on the pcDuino has eight serial ports on board. Only two of these ports actually map to a Linux device: /dev/ttyS0 is the debugging port, and /dev/ttyS1 is the UART which is pinned out on the Arduino-ish header.

Pin mode settings

As mentioned on the GPIO page, the “mode” registers for each pin control the functionality of that pin. For serial I/O, you may need to write ‘3’ to the mode files for pins 0 and 1. The C++ code includes that; the serial library for Python does it by default.

Serial Communications in C++

Using C++ to access the serial port is not too hard. There are lots of good sites out there about serial port access in Linux; here’s a simple example program to get your started. All it does is configure the port, send “Hello, world!” across it, wait for an input keystroke to come back, then exit.

language:cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include "serial_test.h"

// Life is easier if we make a constant for our port name.
static const char* portName = "/dev/ttyS1";

int main(void)
{

  // The very first thing we need to do is make sure that the pins are set
  //   to SERIAL mode, rather than, say, GPIO mode.
  char path[256];

  for (int i = 0; i<=1; i++)
  {
    // Clear the path variable...
    memset(path,0,sizeof(path));
    // ...then assemble the path variable for the current pin mode file...
    sprintf(path, "%s%s%d", GPIO_MODE_PATH, GPIO_FILENAME, i);
    // ...and create a file descriptor...
    int pinMode = open(path, O_RDWR);
    // ...which we then use to set the pin mode to SERIAL...
    setPinMode(pinMode, SERIAL);
    // ...and then, close the pinMode file.
    close(pinMode);
  }

  int serialPort; // File descriptor for serial port
  struct termios portOptions; // struct to hold the port settings
  // Open the serial port as read/write, not as controlling terminal, and
  //   don't block the CPU if it takes too long to open the port.
  serialPort = open(portName, O_RDWR | O_NOCTTY | O_NDELAY );

  // Fetch the current port settings
  tcgetattr(serialPort, &portOptions);

  // Flush the port's buffers (in and out) before we start using it
  tcflush(serialPort, TCIOFLUSH);

  // Set the input and output baud rates
  cfsetispeed(&portOptions, B115200);
  cfsetospeed(&portOptions, B115200);

  // c_cflag contains a few important things- CLOCAL and CREAD, to prevent
  //   this program from "owning" the port and to enable receipt of data.
  //   Also, it holds the settings for number of data bits, parity, stop bits,
  //   and hardware flow control.
  portOptions.c_cflag |= CLOCAL;
  portOptions.c_cflag |= CREAD;
  // Set up the frame information.
  portOptions.c_cflag &= ~CSIZE; // clear frame size info
  portOptions.c_cflag |= CS8;    // 8 bit frames
  portOptions.c_cflag &= ~PARENB;// no parity
  portOptions.c_cflag &= ~CSTOPB;// one stop bit

  // Now that we've populated our options structure, let's push it back to the
  //   system.
  tcsetattr(serialPort, TCSANOW, &portOptions);

  // Flush the buffer one more time.
  tcflush(serialPort, TCIOFLUSH);

  // Let's write the canonical test string to the serial port.
  write(serialPort, "Hello, World!", 13);

  // Now, let's wait for an input from the serial port.
  fcntl(serialPort, F_SETFL, 0); // block until data comes in

  char dataIn = 0;
  do
  {
    read(serialPort,&dataIn,1);
  } while(dataIn == 0);

  printf("You entered: %c\n", dataIn);

  // Don't forget to close the port! Failing to do so can cause problems when
  //   attempting to execute code in another program.
  close(serialPort);
}

void setPinMode(int pinID, int mode)
{
  writeFile(pinID, mode);
}

// While it seems okay to only *read* the first value from the file, you
//   seemingly must write four bytes to the file to get the I/O setting to
//   work properly. This function does that.
void writeFile(int fileID, int value)
{
  char buffer[4];  // A place to build our four-byte string.
  memset((void *)buffer, 0, sizeof(buffer)); // clear the buffer out.
  sprintf(buffer, "%d", value);
  lseek(fileID, 0, SEEK_SET);   // Make sure we're at the top of the file!
  int res = write(fileID, buffer, sizeof(buffer));
}

Serial Communications in Python

Python requires an external library to use serial ports; however, it’s very easy to install. Just open up an LXTerm window and type

language:text
sudo apt-get install python-serial

Pyserial, the Python serial library, will be automatically installed.

Now, let’s run our first Python serial communications program. We’ll do the same thing we did in C++: open the port, wait for the user to input a keystroke, echo back the keystroke, then exit. Here’s the code:

language:python
#!/usr/bin/env python

import serial ## Load the serial library

## Select and configure the port
myPort = serial.Serial('/dev/ttyS1', 115200, timeout = 10)

## Dump some data out of the port
myPort.write("Hello, world!")

## Wait for data to come in- one byte, only
x = myPort.read()

## Echo the data to the command prompt
print "You entered " + x

## Close the port so other applications can use it.
myPort.close()

I2C Communications

I2C communication on the pcDuino is pretty easy.

Hardware

I2C hardware resources on the pcDuino

As with serial communications, there are several I2C bus devices, but only one (/dev/i2c-2) is readily available to the user. A very, very important feature to take note of is that the I2C bus speed is fixed at 200kHz, which means that some devices may not work on the pcDuino I2C bus. The bus speed is fixed at driver compile time and cannot be changed from user space.

The pcDuino has on-board 2.2k pull-up resistors. These are pinned out to the Arduino-ish header, to the location typical for Arduino Uno R3 and later boards. On older boards, the pins were shared with analog inputs 4 and 5; there are solder jumpers on the pcDuino which allow you to redirect the SDA and SCL lines to those pins if you so desire. They’re labeled on the image above, and they’re designated R75 and R76.

There’s also a lovely set of tools that allow you to twiddle around with the I2C bus a bit without writing any code. To install this toolset, open a command line and type

language:text
sudo apt-get install i2c-tools

These tools can be a valuable sanity check for your hardware, so you can verify that problems you’re seeing are, in fact, in your code.

I2C Communications in C++

This simple program will connect to a couple of devices on the I2C port, read their device ID registers, and print them to the command line. The board used for the example is a SparkFun 6DOF Digital, but the principle is the same for any devices.

language:cpp
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

int main(void)
{
  // Set up some variables that we'll use along the way
  char rxBuffer[32];  // receive buffer
  char txBuffer[32];  // transmit buffer
  int gyroAddress = 0x68; // gyro device address
  int xlAddress = 0x53;   // accelerometer device address
  int tenBitAddress = 0;  // is the device's address 10-bit? Usually not.
  int opResult = 0;   // for error checking of operations

  // Create a file descriptor for the I2C bus
  int i2cHandle = open("/dev/i2c-2", O_RDWR);

  // Tell the I2C peripheral that the device address is (or isn't) a 10-bit
  //   value. Most probably won't be.
  opResult = ioctl(i2cHandle, I2C_TENBIT, tenBitAddress);

  // Tell the I2C peripheral what the address of the device is. We're going to
  //   start out by talking to the gyro.
  opResult = ioctl(i2cHandle, I2C_SLAVE, gyroAddress);

  // Clear our buffers
  memset(rxBuffer, 0, sizeof(rxBuffer));
  memset(txBuffer, 0, sizeof(txBuffer));

  // The easiest way to access I2C devices is through the read/write
  //   commands. We're going to ask the gyro to read back its "WHO_AM_I"
  //   register, which contains the I2C address. The process is easy- write the
  //   desired address, the execute a read command.
  txBuffer[0] = 0x00; // This is the address we want to read from.
  opResult = write(i2cHandle, txBuffer, 1);
  if (opResult != 1) printf("No ACK bit!\n");
  opResult = read(i2cHandle, rxBuffer, 1);
  printf("Part ID: %d\n", (int)rxBuffer[0]); // should print 105

  // Next, we'll query the accelerometer using the same process- but first,
  //   we need to change the slave address!
  opResult = ioctl(i2cHandle, I2C_SLAVE, xlAddress);
  txBuffer[0] = 0x00;  // This is the address to read from.
  opResult = write(i2cHandle, txBuffer, 1);
  if (opResult != 1) printf("No ACK bit!\n");
  opResult = read(i2cHandle, rxBuffer, 1);
  printf("Part ID: %d\n", (int)rxBuffer[0]); // should print 229
}

I2C in Python

Python has a support package much like pySerial to make interfacing with I2C devices easier. To install it, open a command line and type

language:text
sudo apt-get install python-smbus

SMBus is the name given to the I2C derivative used on PC motherboards. The main differences are hardware-level and not reflected in the user coding level, so we’ll ignore them and just point out that the SMBus Python package can be used here.

This code does the same thing the C++ code does: queries the two devices on a 6DOF digital and prints the result to the command line.

language:python
#!/usr/bin/env python

import smbus

## As before, we'll create an alias for our addresses, just to make things
##   a bit easier and more readable later on.
gyroAddress = 0x68
xlAddress   = 0x53

## Initialize an smbus object. The parameter passed is the number of the I2C
##   bus; for the Arduino-ish headers on the pcDuino, it will be "2".
i2c = smbus.SMBus(2)

## With both of these devices, the first byte written specifies the address of
##   the register we want to read or write; for both devices, the device ID is
##   stored in location 0. Writing that address, than issuing a read, will
##   give us our answer.
i2c.write_byte(gyroAddress, 0)
print "Device ID: " + str(i2c.read_byte(gyroAddress)) ## should be 105

i2c.write_byte(xlAddress, 0)
print "Device ID: " + str(i2c.read_byte(xlAddress)) ## should be 229

SPI Communications

The pcDuino has headers exposing two different SPI buses. At this time, however, only one bus, and only one device on that bus, is supported. It’s possible to use other GPIO pins to add slave select lines, of course, with a hit to performance.

Hardware

SPI pinout mapping on the pcDuino

The currently available SPI peripheral, SPI0, can be accessed through four of the pins on the Arduino-compatible headers along the bottom edge of the board. These pins break out the MOSI, MISO, SCK, and CS lines from the processor, allowing full hardware peripheral support of SPI communications.

SPI programming in C++

If you’ve been following along with the tutorial, a lot of this stuff should look familiar. Open a file descriptor for the spidev0.0 device, then use ioctl() to pass settings (defined in /linux/spi/spidev.h) to the peripheral. Actual message passing is a bit messy, though: you need to create a structure, then pass that structure to the file descriptor via ioctl().

We’ll be using the ADXL362 accelerometer breakout board as a test device in this code.

Don’t forget to use the pin mode files that we talked about back in the GPIO section to set the pins to SPI mode!

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include "spi_test.h"

static const char *spi_name = "/dev/spidev0.0";

int main(void)
{
  int res = 0;  // We can use this to monitor the results of any operation.

  // The very first thing we need to do is make sure that the pins are set
  //   to SPI mode, rather than, say, GPIO mode.
  char path[256];

  for (int i = 10; i<=13; i++)
  {
    // Clear the path variable...
    memset(path,0,sizeof(path));
    // ...then assemble the path variable for the current pin mode file...
    sprintf(path, "%s%s%d", GPIO_MODE_PATH, GPIO_FILENAME, i);
    // ...and create a file descriptor...
    int pinMode = open(path, O_RDWR);
    // ...which we then use to set the pin mode to SPI...
    setPinMode(pinMode, SPI);
    // ...and then, close the pinMode file.
    close(pinMode);
  }

  // As usual, we begin the relationship by establishing a file object which
  //   points to the SPI device.
  int spiDev = open(spi_name, O_RDWR);

  // We'll want to configure our SPI hardware before we do anything else. To do
  //   this, we use the ioctl() function. Calls to this function take the form
  //   of a file descriptor, a "command", and a value. The returned value is
  //   always the result of the operation; pass it a pointer to receive a value
  //   requested from the SPI peripheral.

  // Start by setting the mode. If we wanted to *get* the mode, we could
  //   use SPI_IOC_RD_MODE instead. In general, the "WR" can be replaced by
  //   "RD" to fetch rather than write. Also note the somewhat awkward
  //   setting a variable rather than passing the constant. *All* data sent
  //   via ioctl() must be passed by reference!
  int mode = SPI_MODE0;
  ioctl(spiDev, SPI_IOC_WR_MODE, &mode);

  // The maximum speed of the SPI bus can be fetched. You'll find that, on the
  //  pcDuino, it's 12MHz.
  int maxSpeed = 0;
  ioctl(spiDev, SPI_IOC_RD_MAX_SPEED_HZ, &maxSpeed);
  printf("Max speed: %dHz\n", maxSpeed);

  // In rare cases, you may find that a device expects data least significant
  //   bit first; in that case, you'll need to set that up. Writing a 0
  //   indicates MSb first; anything else indicates LSb first.
  int lsb_setting = 0;
  ioctl(spiDev, SPI_IOC_WR_LSB_FIRST, &lsb_setting);

  // Some devices may require more than 8 bits of data per transfer word. The
  //   SPI_IOC_WR_BITS_PER_WORD command allows you to change this; the default,
  //   0, corresponds to 8 bits per word.
  int bits_per_word = 0;
  ioctl(spiDev, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word);

  // Okay, now that we're all set up, we can start thinking about transferring
  //   data. This, too, is done through ioctl(); in this case, there's a special
  //   struct (spi_ioc_transfer) defined in spidev.h which holds the needful
  //   info for completing a transfer. Its members are:
  //    * tx_buf - a pointer to the data to be transferred
  //    * rx_buf - a pointer to storage for received data
  //    * len - length in bytes of tx and rx buffers
  //    * speed_hz - the clock speed, in Hz
  //    * delay_usecs - delay between last bit and deassertion of CS
  //    * bits_per_word - override global word length for this transfer
  //    * cs_change - strobe chip select between transfers?
  //    * pad - ??? leave it alone.

  // For this example, we'll be reading the address location of an ADXL362
  //   accelerometer, then writing a value to a register and reading it back.
  //   We'll do two transfers, for ease of data handling: the first will
  //   transfer the "read register" command (0x0B) and the address (0x02), the
  //   second will dump the response back into the same buffer.

  struct spi_ioc_transfer xfer;
  memset(&xfer, 0, sizeof(xfer));
  char dataBuffer[3];
  char rxBuffer[3];
  dataBuffer[0] = 0x0B;
  dataBuffer[1] = 0x02;
  dataBuffer[2] = 0x00;
  xfer.tx_buf = (unsigned long)dataBuffer;
  xfer.rx_buf = (unsigned long)rxBuffer;
  xfer.len = 3;
  xfer.speed_hz = 500000;
  xfer.cs_change = 1;
  xfer.bits_per_word = 8;
  res = ioctl(spiDev, SPI_IOC_MESSAGE(1), &xfer);
  printf("SPI result: %d\n", res);
  printf("Device ID: %d - %d - %d\n", rxBuffer[2], rxBuffer[1], rxBuffer[0]);
}

void setPinMode(int pinID, int mode)
{
  writeFile(pinID, mode);
}

// While it seems okay to only *read* the first value from the file, you
//   seemingly must write four bytes to the file to get the I/O setting to
//   work properly. This function does that.
void writeFile(int fileID, int value)
{
  char buffer[4];  // A place to build our four-byte string.
  memset((void *)buffer, 0, sizeof(buffer)); // clear the buffer out.
  sprintf(buffer, "%d", value);
  lseek(fileID, 0, SEEK_SET);   // Make sure we're at the top of the file!
  int res = write(fileID, buffer, sizeof(buffer));
}

SPI Programming in Python

Fortunately, a nice package exists for making SPI more accessible in Python. Unfortunately, installing it is difficult—much more so than the packages for I2C or serial. Here are the instructions to follow:

  1. Update your package list for apt-get. In a terminal, type

     sudo apt-get update

    This will update the list of packages available to the apt-get program, ensuring that you get the right versions of the things we’ll be installing next.

  2. Install git. Git is a source control tool used for version tracking, and it’s extremely useful. The SPI package in question resides on GitHub, which is a web portal for sharing git projects. To install git, pull up a terminal window and type

     sudo apt-get install git

    This installs the git toolchain; you don’t really need to know how to use it for what we’re doing here, but if you’re interested, we have a git tutorial that will teach you a lot of what you need to know.

  3. Install python-dev. This is adds to python the ability to develop C-based extensions. To install, open a terminal window (or use the one that was open from installing git) and type

     sudo apt-get install python-dev
  4. Clone the SPI-Py git repository. This is the source code for the SPI python library we’ll be using. The command to type is

     git clone https://github.com/lthiery/SPI-Py.git
  5. Install the SPI-Py module. Type

     cd SPI-Py
     sudo python setup.py install

Now you’re set up and ready to write some code! Here’s a very simple Python app that will do essentially the same thing as the C++ code above does—connect to an ADXL362 and check the device ID register.

#!/usr/bin/env python

import spi

## The openSPI() function is where the SPI interface is configured. There are
##   three possible configuration options, and they all expect integer values:
##   speed - the clock speed in Hz
##   mode - the SPI mode (0, 1, 2, 3)
##   bits - the length of each word, in bits (defaults to 8, which is standard)
## It is also possible to pass a device name, but the default, spidev0.0, is
##   the only device currently supported by the pcDuino.

spi.openSPI(speed=1000000, mode=0)

## Data is sent as a tuple, so you can construct a tuple as long as you want
##   and the result will come back as a tuple of the same length.
print spi.transfer((0x0B, 0x02, 0x00))

## Finally, close the SPI connection. This is probably not necessary but it's
##   good practice.
spi.closeSPI()

For More Information...


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

Viewing all 1123 articles
Browse latest View live


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