Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C

FMBomb - A Beginner's Approach to Hardware Programming

4.94/5 (63 votes)
26 Mar 2011CPOL15 min read 207.3K   882  
A beginner's hardware project using a PIC microcontroller.

Image 1

Latest Update

Just a simple but fun update. Added an electret microphone with preamp that feeds directly into the FM transmitter. You can now broadcast your voice over the airwaves. No firmware changes were required.

Introduction

In this article, I want to take you through the process of creating your own hardware project. I hope it can serve as an example that working in hardware can be an approachable and a fun hobby for people that are already smart enough to know how to code.

Disclaimer: This is a beginner’s article and as such, I do not use or explain some best practices in hardware construction that would be out of the scope for this article. I’m going for quick and simple.

Dispelling Hardware Fears

So right away, I want to attack some of the major reasons not to get into hardware as a hobby, and hopefully convince you otherwise. In talking with people, I found there are really five big reasons that software people don’t get into hardware.

  1. Lack of knowledge in all things electrical
  2. Cost
  3. The dreaded assembly and C programming
  4. Afraid to zap yourself or fry something
  5. Lack of interest

Let me briefly share my opinion on each of these, and then we’ll get to the good stuff. Feel free to skip ahead to the good stuff if you don't want to hear me ramble about each of these. It won't hurt my feelings.

Lack of knowledge in all things electrical

I have a B.S. in Electrical Engineering so I know a little bit about this stuff, but I spent most of my degree solving Fourier transforms, creating PID controllers, and building opamps from scratch. Sure that knowledge helps, but I never touched a microcontroller in college. All my microcontroller knowledge has been self taught while working in my basement. It just takes some effort and a little patience. You’re smart enough to figure this stuff out. Trust me.

Cost

OK, so we all know that writing software is essentially free once you have the computer (how much did that cost you by the way?). Software tools are free for hobby use, and you can accomplish a lot without spending any money. There’s not much we can do here. Hardware parts cost money, but most of the tools to develop firmware are free, and parts are cheaper than you think. And remember, in many cases, you can rip stuff out of those old electronics collecting dust in your attic and give them new life.

The dreaded assembly and C programming

You can skip the assembly, but you’ll have to get to know C a little if you want to write any firmware. You learned Java, didn’t you? Or C# or Ruby? If you’re half a decent programmer, you can learn how to write code in C for microcontrollers. It doesn’t hurt that bad, and you might actually learn some valuable skills that you can apply to your other favorite languages. There are some platforms out there that support the .NET Framework, but the majority still use C. Personally, if I make a mistake while tinkering, I'd rather fry a $2 PIC than a much more expensive .NET development board.

Afraid to zap yourself or fry something

OK, I’m going to give my disclaimer here that you should proceed at your own risk. Playing with electricity and soldering irons can hurt, and break you and your stuff, and things can catch fire and all of that legal wording you’ve already heard before, and I don’t want to be held responsible if you blow something up. But I’m going to be crazy here and ignore the legal bit for a second and suggest that in most small electronics projects, we’re dealing with harmlessly low voltage and current. The worst you’ll usually get if you're not careful is a little zap, if that. As far as frying something, we're dealing with a $2 chip. If it fries, grab another one. It happens to us all at least once. I’ve been doing this for years, and can tell you that if you exercise some common sense and caution, and do some Googling if you’re not sure, you’ll keep all of your fingers, toes, and eyebrows. Having said that, please be careful, but try to have some fun.

Lack of interest

Can’t help you here. Maybe you opened the wrong article link.

The Point

So what’s my main point? Learning how to create hardware projects is like learning to program; it requires patience and a lot of effort and time, and there is a learning curve. However, like most things in life that have these prerequisites, it is incredibly rewarding to crank out something even half functional that you can then show off to all of your friends. They probably won't care, but that's just because they are jealous of your mad hardware skills.

What's the Project?

Everybody does the LED flashing thing, but that’s boring and a little too beginner for me. I’d guess that not too many people are flocking to the hardware side of things to make LEDs flash. Sure, it’s exhilarating the first time you get that blinkety blink to work just right, but we want to do some cool stuff too. Hopefully this article will show you that you can do cool things without being an electrical engineer.

So what is the FMBomb? Basically, this is just like your iPod car jack that lets you listen to your music on your car speakers by broadcasting the sound on an FM station that your radio picks up, except you’re building the hardware. Why the name FMBomb? Not sure, that was the first thing that came to my head. Remember, the methods and principles used in this project can be applied to a much larger pool of ideas. Ideas that are swimming around in your head, so try to see the big picture. I’ll try to help along the way.

Tell Me What I Need

So the bill of materials for this project is pretty simple and pretty affordable.

PartNotes
PIC16F688Available for sample from Microchip
NS73M Breakout BoardAvailable from Sparkfun
Hookup wireUsed for connecting everything together
4.7KΩ resistor
1.0KΩ resistor
LEDAny color will do

Now, as far as tools go, we'll be using the following:

  • MPLAB IDE (free)
  • HI-TECH C Compiler (free)
  • Pickit3 programmer (~$45 USD). Once you own one of these, you can program any PIC.
  • Breadboard
  • Basic hardware goodies like wire strippers (or teeth), pliers, hookup wire, etc.

Note: This article is not a plug for Microchip products. I use the Microchip microcontrollers and tools because that’s what I know. You can use any brand of microcontroller and accompanying tools you like. The basic concepts will be the same.

The Brains of the Project

I decided to use a PIC 16F688 microcontroller for this project because, well, I have a whole drawer of them lying around. Most of you probably don’t, but they are very cheap. In fact, the 16F688 is available as a sample from Microchip if you are interested in picking up a couple. I touched on microcontrollers a bit in my other article, so head over there for some background so I don’t have to repeat it here. Basically, the microcontroller will be the brains of our project. It’s where the firmware goes and what everything else connects to.

Important Hardware Concept #1: Datasheets are your friend. Anything and everything you need to know about any component will be spelled out in its datasheet. The datasheet for the 16F688 (hereafter to be referred to as the PIC) is 204 pages. Don’t freak out, we don’t need to read it all, just the parts we care about. The main thing you’ll always need to know for just about any microcontroller is how to setup the config registers. These are akin to the BIOS settings for a computer. They tell the microcontroller how to work on startup. Things like where the clock signal comes from, how certain pins should behave by default, etc. If you don’t get these right, you’ll spend a lot of time wondering why things don’t work. I heavily documented setting these up in the code. The next thing to remember is that each pin has different capabilities, and you can choose what functionality you want each pin to have, e.g., input pin, output pin, external clock signal, comparator input, etc. All of it is in the datasheet and very easy to configure. Well, this isn’t a microcontroller lecture, so let’s move on.

Step 1: Hardware Setup

In software, when we want to create a new project, we have to do File->New or something like that to get things started. In hardware, we have to do some basic hardware assembly before we write any firmware. A microcontroller needs two things to function:

  1. Power, and
  2. A clock source.

From the PIC datasheet, we know that there is an internal oscillator (clock source) that we can use as the clock, and for power, we know from the datasheet (pg. 144) that the PIC can be powered with anything between 2V and 5.5V. 2 AA batteries in series (3.0V) would work, or a DC wall adapter from an old electronic device. I’m using a wall adapter that outputs 3.3V. So let’s set up what we have so far. (I’ve also included the connections for our Pickit3 programmer. These are only used for getting our firmware image onto the device. This includes the 4.7K resistor attached between pins 1 and 4.)

Image 2

Pretty simple, huh? Now, how will we know if our firmware loaded properly? We need an indicator that we can control from the firmware to let us know if everything is working. How about an LED? Now here is where some electrical knowledge comes in. We can power the LED with one of the pins on the microcontroller (configured to be an output), but we need to put a resistor inline so we don’t burn out the LED. The resistor “resists” the flow of current so too much won’t flow through the LED and burn it out. Important Hardware Concept #2: Don’t Know Something, Google It. I did a search for “connecting an LED”, and the top result tells you everything you need to know about hooking up an LED to a power source. In our case, the power source will be the output pin of the PIC. So now our schematic looks like this:

Image 3

Step 2: Write Some Firmware

The first thing to do with any PIC project is to create a new project in MPLAB, just like you would in <insert your favorite IDE here>. I don’t want to water down this article with IDE instructions, so read the quick-start guide for that. Basically, we are creating a new project and telling the IDE that our device is the PIC16F688.

Just like in a C program you would write for a computer, the firmware will start execution in a main() function. Before we do that, however, we need to setup our config registers as I mentioned above. Page 111 in the datasheet tells us what each bit in the 2 bytes of configuration data stands for. We use that as a guide to set things up. See the commented code for more details, but this is what the _CONFIG() macro looks like:

C++
__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & MCLREN & PWRTDIS & WDTDIS & INTIO);

Now we’re ready to write our main function. Let’s start with something simple to test our setup with the LED.

C++
void main(void)
{
    // Wait for the power supply to settle. This is always a good idea to do
    // at startup.
    __delay_ms(10);

    // From the datasheet we know that if we want certain pins to be
    // digital inputs instead of analog inputs that we need to set the
    // ANSEL and CMCON0 registers. The following settings make all 
    // pins digital.

    ANSEL = 0;
    CMCON0 = 0x07;

    // The internal oscillator we're using defaults to 4MHz on startup
    // You can confirm this on page 22 of the datasheet. If we wanted
    // we could change the frequency here to something else. For our
    // purposes we'll just leave it.

    // Setup pin 7 (RC3) to be an output so we can drive the LED with it. 
    // Remember, setting the TRIS bit to a 1 makes a pin an input and a 0 sets
    // it as an output. Think 1 is like I so Input. 0 is like an O so Output.

    TRISC3 = 0; // This tells the pin to be an output
    RC3 = 0;    // This sets the initial state to 0V.

    while(1)
    {
        RC3 = 1;          // Turn the LED on
        _delay_ms(1000);  // Delay for a second
        RC3 = 0;          // Turn the LED off
        _delay_ms(1000);  // Delay for a second
    }
}

This is pretty simple stuff. There are no other files in the project other than the standard htc.h supplied by the HI-TECH compiler install. I’m not hiding anything behind the scenes. This is really it. We set up one of the pins to be a digital output and then turn it on and off in an infinite while(1) loop to blink the LED. We use MPLAB to program our device with the .hex file created by the compiler, and we get a blinking LED. So we know our microcontroller is connected correctly and receiving the firmware we are sending it. Now we are ready to add our main functionality.

Step 3: Get Your FM Groove On

So for this project, we’ll be using the NS73M FM transmitter. Sparkfun Electronics sells the component and a breakout board version so it’s easy to prototype on a breadboard. I used the breakout board because it comes with the two external components needed to make the transmitter work already soldered on. Important Hardware Concept #3: Prepackaged components rock. Sure, we could build an FM transmitter from scratch, but why do that when you can drop in a module that somebody else has built and tested? It’s just like writing software. Sure you could write your own logging framework for .NET, but unless you really need specific functionality, a prepackaged library like NLog or log4net will work just fine in most cases. In computer terms, think of these modules as peripherals for which you have to write the driver. Sounds hard, but you’ll see that it is really not too bad. Connect it, add power, and start talking to it. The concepts we’ll use to connect our FM transmitter apply to connecting just about any external module, Wi-Fi, LCDs, sensors. All of these can be added to your project as external modules connected to your microcontroller.

Hook It Up

Our breakout board with the transmitter mounted has a bunch of connections we need to make. It’s all spelled out in the datasheet. From the NS73M datasheet (pg. 4), we see that the max supply voltage the module can handle is 3.7V. That’s within our PIC power range (2-5.5V), so we can share the 3.3V wall adapter power between our PIC and the transmitter module. Once everything is hooked up, it’s just a matter of writing the firmware to talk to the module and get it transmitting. Our hardware assembly is complete, and here is what we end up with:

Image 4

Communicating With the Transmitter Module

In the NS73M datasheet, we learn two important things. First, all communication with the module is in the form of command packets, and second, those packets can be sent in one of two ways: 3-wire SPI, or the I2C protocol. Many microcontrollers have an I2C peripheral built in, but our PIC doesn’t, so we’ll use the SPI method. Lucky for us, the NS73M datasheet also tells us exactly how that protocol should be implemented. Each packet to the module consists of 4 bits, specifying a register address, followed by a byte of data to be stored at that address. The module’s operation is determined by the values in all of the registers. Page 8 of the datasheet shows us what the SPI communication protocol looks like.

Image 5

I heavily commented the firmware source code attached to this article so you can get more detail there, but basically, when the line for a signal is high, we set its pin to 1 in the firmware. When it is low, we set it to 0. So let’s add a routine in our firmware that will handle sending a packet to the module. (I’ve removed some of the comments for space reasons. You can find the full version in the code.)

C++
void SendCommand(char address, char data)
{
    char x;

    // The clocking diagram shows that the LA pin needs to be
    // low until the data has all been sent so lets set it to
    // zero here.
    LA = 0;

    // The first thing we need to send is the 4 address bits
    for(x = 0 ; x < 4 ; x++)
    {
        CK = 0;
        DA = address & 0x01;
        // This is a trick for getting the value of the LSB

        // Rotate 1 bit to the right. This rolls the LSB to the right
        // and makes the second bit the LSB
        address >>= 1; 
        CK = 1;
    }
    
    // Now that the address bits have been sent let's send the data
    for(x = 0 ; x < 8 ; x++)
    {
        // We'll follow the exact same pattern as seen with the 
        // address bits
        CK = 0;
        DA = data & 0x01;    
        data >>= 1;
        CK = 1;
    }
    
    // From the diagram we see that once all bits have been
    // sent we need to latch the transfer by setting LA
    // high. From the table on page 9 we see that we need
    // to hold that line high for a minimum of 250 ns so
    // we'll use a 1 ms delay for good measure before setting
    // LA back to zero.
    LA = 1;
    __delay_ms(1);
    LA = 0;
}

With this in place, we can set the values in the registers to make the transmitter bend to our will. How do I know what to write to the registers? That’s right, look in the NS73M datasheet. You can find my sample setup in the code. Once you've done that, you’re done. Power it up, tune your radio to the FM channel you setup in the firmware, and marvel at your abilities.

Adding Voice

It's fun to transmit your iPod music on the radio but it's even better to broadcast your voice. The voice addition to the circuit is a great example of how easy it can be to bolt on functionality to an embedded project. No firmware changes were needed and the whole upgrade, including soldering a breakaway header to the microphone breakout board, took me about 20 minutes. I immediately tuned all of the radios in the house to my preset transmission frequency and began speaking to the family from my basement lair. The transmission range is pretty good with just a simple 30 inch hookup wire antenna. Just to reinforce the datasheet principle, I found on page 3 of the datasheet that the OpAmp can be powered with 2.7V to 5.5V which is right in our power range. What should we add next?

Conclusion

That’s it. I know this article has been pretty long, so thanks for making it this far. If something isn't clear or if you have general questions, please submit them in the comments below. I’ve tried to demonstrate that, with some simple hardware and pretty simple firmware, we can achieve something pretty neat. I’ve heavily commented the code, so I encourage you to check it out. From here, you can modify the firmware to suit your needs. Maybe you could add a button that will tune to the next FM station when you press it, or add an LCD to display information about what frequency you are transmitting on. Add a real time clock and calendar module, and program your device to start broadcasting at a certain time each day and stop broadcasting at a later time. Anything you can think of.

If you found this article interesting and would like to see some enhancements made or a follow-up article, please let me know. I maintain the Embedded Fun blog where I post things from time to time. It contains a link to the source code for this project on github. You are welcome to leave comments there or at the bottom of this article. I'll try to be as responsive as I can.

That brings us to Important Hardware Concept #4: You CAN figure this stuff out. Give it a try and have some fun. You’ll be building the Iron Man suit in no time.

History

  • 1/11/2011 - Original article.
  • 3/24/2011 - Added mic with preamp to circuit.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)