Friday, June 1, 2012

RDM6300 RFID with PIC18 Dev Board

After getting a simple LED-blink program working, I moved on to the RFID portion of my project.  It seemed to be the simplest of the three major parts (RFID, SD card, and MP3) because it's basically just configuring the UART to receive and check the card IDs.  I'm using the RDM6300 UART RFID Module from ITeadStudio, which cost $11 for the reader and $0.50 per card.  The datasheet is posted and it describes both the pinout of the module and the data format.  I started out by wiring up the power, ground, and TX line to an FTDI breakout board to verify that the RFID reader worked correctly by reading the data into Docklight.  The data format is 9600bps 8N1 serial.  The datasheet listed 13 bytes (0x02, 10 data bytes, checksum, 0x03), yet I consistently received 14 bytes.  I'm not totally sure what's going on, but I always get the same 14 bytes, so I just recorded those for each of the 10 cards I purchased.  The table below shows the hex values I receive for each of the cards.


The datasheet for the RFID module lists the operating current as <50 mA, which is high enough that I want to be able to turn the module on and off from the PIC instead of just leaving it on all the time.  To do this, I used a 2N3906 PNP transistor in between the board 5V supply and the RFID 5V supply, with the base connected to a GPIO with a 1k resistor.  Turning the GPIO high turns the RFID module on;  setting it low turns the RFID module off.  Using the transistor dropped the supply from 5V to 4.87V, but this is still within the +/-5% of 5V listed on the datasheet spec, and it appears to be working just fine.  I also added a resistor divider to the UART TX line of the RFID module to bring the 5V output down below 3.3V.  The following two pictures show a circuit diagram of this, and then what it looks like soldered onto my development board (some parts/wires were soldered underneath the RFID module).



The PIC C18 compiler comes with a set of peripheral libraries, including one for the USART, which made it very easy to configure the USART and had a good example of using it to send and receive data.  Once I verified that I could receive a single card's data, I set up a demo with three RFID tags programmed into the PIC so that it would toggle an LED based on which card was swiped.  I initially tried to use the "gets1USART" function to read a 14 characters off of the USART, but every once and a while the RFID unit spits out a random bad character (sometimes at power up) that was causing me issues.  Instead, the USART reception is handled using an interrupt service routine, and I pulled the basic setup for it from an Example #6 in an older copy of the C18 Getting Started Guide.  The code is below, followed by a video of the demo.  Note that the code assumes a 16 Mhz clock speed, like my previous post.  You'll need to adjust the USART initialization line and delay line if you're using a different clock speed.

#include <p18lf26j11.h>
#include <delays.h>
#include <usart.h>
#include <string.h>

#pragma config OSC = HS //High speed crystal
#pragma config WDTEN = OFF //Disable watchdog timer
#pragma config XINST = OFF //Disable Extended CPU mode

//LED Pin Configuration
#define LED1Pin LATAbits.LATA0
#define LED1Tris TRISAbits.TRISA0
#define LED2Pin LATAbits.LATA1
#define LED2Tris TRISAbits.TRISA1
#define LED3Pin LATAbits.LATA2
#define LED3Tris TRISAbits.TRISA2

#define RFIDVCCPin LATBbits.LATB4 //Define RFIDVCCPin as PORT B Pin 4
#define RFIDVCCTris TRISBbits.TRISB4 //Define RFIDVCCTris as TRISB Pin 4

//Flags & Data Reception Variables
volatile char tagRecdFlag;
volatile char tagComingFlag;
volatile char tagCounter;
volatile char tagRX[14] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//RFID Tag IDs
char rfidTag1[14] = {0x02, 0x30, 0x35, 0x30, 0x30, 0x41, 0x44, 0x44, 0x38, 0x46, 0x46, 0x43, 0x3f, 0x03};
char rfidTag2[14] = {0x02, 0x30, 0x35, 0x30, 0x30, 0x41, 0x44, 0x42, 0x46, 0x35, 0x37, 0x36, 0x30, 0x03};
char rfidTag3[14] = {0x02, 0x30, 0x35, 0x30, 0x30, 0x41, 0x45, 0x33, 0x46, 0x36, 0x35, 0x44, 0x33, 0x03};

//Function Prototypes
void rx_handler(void);
//Function Prototypes

#pragma code rx_interrupt = 0x8
void rx_int(void)
{
    _asm goto rx_handler _endasm
}
#pragma code

#pragma interrupt rx_handler
void rx_handler(void)
{
    unsigned char rxByte;
    rxByte = RCREG1; //Read character received from USART

    if (tagComingFlag == 0 && rxByte == 0x02)
    {
        tagRX[tagCounter] = rxByte;
        tagComingFlag = 1;
        tagCounter++;
    }   else if (tagComingFlag == 1)
        {
            tagRX[tagCounter] = rxByte;
            tagCounter++;
            if (tagCounter == 14)
            {
                tagCounter = 0;
                tagComingFlag = 0;
                tagRecdFlag = 1;
            }
        }   else
            {
                tagComingFlag = 0;
                tagCounter = 0;
            }
    PIR1bits.RCIF = 0; //Clear interrupt flag
}

void main()
{
        //Set LED Pins data direction to OUTPUT
        LED1Tris = 0;
        LED2Tris = 0;
        LED3Tris = 0;
        //Set LED Pins to OFF
        LED1Pin = 0;
        LED2Pin = 0;
        LED3Pin = 0;

        tagRecdFlag = 0; //Set in ISR if new RFID tag has been read
        tagComingFlag = 0; //Indicates if a tag is partially received
        tagCounter = 0; //Counts byte index
        
        //USART1 Initialization
        Open1USART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 25);

        //Interrupts
        RCONbits.IPEN = 1;  //Enable interrupt priority
        IPR1bits.RC1IP = 1;  //Make receive interrupt high priority
        INTCONbits.GIEH = 1; //Enable all high priority interrupts
        
        //Turn on RFID Module
        RFIDVCCTris = 0; //Set to output
        RFIDVCCPin = 1; //Turn on RFID Module

        while(1)
        {
            if (tagRecdFlag)
            {                 
                //Toggle LED corresponding to which card was read
                if (memcmp(tagRX, rfidTag1, 14) == 0)
                {
                    LED1Pin = ~LED1Pin;
                }
                if (memcmp(tagRX, rfidTag2, 14) == 0)
                {
                    LED2Pin = ~LED2Pin;
                }
                if (memcmp(tagRX, rfidTag3, 14) == 0)
                {
                    LED3Pin = ~LED3Pin;
                }

                //Delay 1/2 sec & clear flags to prevent repeated card read
                Delay10KTCYx(200);
                tagRecdFlag = 0; 
                tagComingFlag = 0; 
                tagCounter = 0; 
                }
        }
}

Wednesday, May 30, 2012

PIC18 Getting Started

Now that I have my development boards in hand, I'm getting set up to work with Microchip PIC18 microcontrollers.  My first step (detailed here) is to just get an LED to blink and confirm that I can compile and run code on the microcontroller.  Going forward, I'll do a post each on testing of the other functional parts of my project as I get them working:  the UART interface to an RFID module, working with an SD card and working with the VS1003 MP3 chip.  I don't get much time to play with this stuff, so it'll probably be a few months before I'm done.

I'm going to be using the new MPLAB X IDE, which you can download for free at the MPLAB X IDE download page.  There's video on that page that describes everything you need to do to download and install the IDE.  There are several options to download different compilers.  I selected the "MPLAB IDE X v1.10", "MPLAB X IDE Release Notes/User' Guide", and "MPLAB C18 Lite Compiler for PIC18 MCUs".  The other compiler option for the PIC18 series is the HITECH C compiler, and you can also download a Lite version of this from the same page.  From the research I've done, it looks like the C18 compiler is a better option for compatibility with the application libraries provided by Microchip.  It also looks like both of these compilers will be combined and migrated to the new XC8 compiler from Microchip very soon (or maybe will already be by the time I actually post this), but I'm going to stick with the C18 compiler for now.

For a programmer/debugger, I'm using the PICkit 2, which runs about $35.  Microchip offers several packages that come with the PICkit 2 plus a development board (or the newer PICkit 3 with a development board), but since I have my own board, I bought only the programmer.  There are several other options for programmers from Microchip, and many more from third party sources.  Microchip offers a Development Tool Selector where you can put in the microcontroller you want to use and it will show you which of their development tools are compatible with it.  There's also a device support list for the PICkit 2 specifically, which shows the microcontroller I'm using, PIC18LF26J11, is supported.


After installing the IDE and PICkit 2 driver, I populated enough of my circuit board to start testing with the PIC.  I added the LDO regulators for 5V, 3.3V, and 2.5V, a power LED, the reset circuit, crystal, LEDs, and DIP socket.  My first mistake was soldering on a 48 MHz crystal when I saw 48 MHz as the max clock speed.  I started up the LED blink program, and the timing wasn't even close.  After some digging, I figure out that 48 MHz was the max clock speed, but to get that you either need an external clock or a 12 MHz crystal with the 4x PLL activated.  I'm not finding it in the datasheet right now, but I seem to recall 25 MHz was about the max crystal frequency the PIC could drive.  I'm using 16 MHz for now.


When you download the Microchip C18 compiler, be sure to check out the included documentation.  It's located in the install directory in a "doc" folder (for me it is at C:\Program Files (x86)\Microchip\mplabc18\v3.40\doc).  The "Getting Started" document and "User Guide" are obviously helpful, but the "hlpPIC18ConfigSet.chm" and "PIC18F Peripheral Library Help Document.chm" are also extremely useful.  The first one lets you select your microcontroller and then list all of the configuration settings and possible values.  The configuration settings do similar things as fuses in AVRs, but it seems to be a little smoother with PICs to use them.  The issue I had at first is that the configuration settings names between chips vary, so if you're trying to get sample code for a different PIC to work with yours and are seeing compiler issues it'd be a good idea to reference this document.  For example, the sample LED blink program I found in the user guide used "WDT" to set the watchdog timer to off, but for the  PIC18LF26J11 , I needed to use "WDTEN" instead.  The library help document shows all of the functions available in the C18 library, and again they're broken down by what's available for your specific microcontroller.

The following code is what I wrote as a sample program to make sure I had everything working correctly and could program the PIC.  I wired an LED each to pins 2, 3, & 4 on the PIC (PORTA0-2), and set them blinking at a 1, 2, & 4 Hz rate.  This is where I figured out about the crystal frequency being off, because the blink rate was much slower than in should have been.  I'm using two of the libraries that come with the C18 compiler, and had to add them to the project to get it to work (though I just referenced them from their default location).

#include <p18lf26j11.h>
#include <delays.h>

#pragma config OSC = HS //High speed crystal
#pragma config WDTEN = OFF //Disable watchdog timer
#pragma config XINST = OFF //Disable Extended CPU mode

#define LED1hzPin LATAbits.LATA0
#define LED1hzTris TRISAbits.TRISA0
#define LED2hzPin LATAbits.LATA1
#define LED2hzTris TRISAbits.TRISA1
#define LED4hzPin LATAbits.LATA2
#define LED4hzTris TRISAbits.TRISA2

char i;

void main()
{
        //Set LED Pins data direction to OUTPUT
        LED1hzTris = 0;
        LED2hzTris = 0;
        LED4hzTris = 0;
        //Set LED Pins to OFF
        LED1hzPin = 0;
        LED2hzPin = 0;
        LED4hzPin = 0;

        i = 0;
        while(1)
        {
            Delay10KTCYx(50);//Delay 1/8 sec
            LED4hzPin = ~LED4hzPin;//Toggle LED Pin
            if (i%2==0)
                LED2hzPin = ~LED2hzPin;//Toggle LED Pin
            if (i%4==0)
                LED1hzPin = ~LED1hzPin;//Toggle LED Pin
            i++;
        }
}

This step was pretty simple, but it's one that can take some time tracking down silly errors when you're starting with something new, and now I'm ready to move on to my actual project.  Next up will be getting the RFID module working.

Thursday, April 26, 2012

28 Pin PIC18F Development Board



The next project I'm working on incorporates several things I've never worked with before, and instead of buying breakout boards for some parts and breadboarding the rest, I decided to design my own development board that was tailored specifically to my project.  While this board is designed with a particular project in mind, I still tried to add generic features and as much flexibility as I could.  I'm trying to learn how to use a variety of different microcontrollers (I've mostly used AVRs and MSP430s up til now), and this project seemed like a good fit to try out PICs.  The MSP430F/G chips I have are 14 pin with 2KB flash, and I needed more than that for my project.  The AVRs I have are in the ATmegaXX8 line, which certainly could have worked, but looking through the Microchip 28pin options, I saw a lot more flexibility with peripherals.  Having multiple SPI and USART ports would be useful for this project, and USB could work well for other projects to avoid using an FTDI or MCP2200.  In the end, it was mostly the chance to learn something new that made me decide to go with a PIC18 for this project.

Several sites offer a 10 copies of 10x10 cm pcb for ~$25 deal, so I initially planned on that size, but I'm using the freeware version of Cadsoft Eagle for the PCB layout, so board size was limited to 10x8 cm.  I upgraded to Eagle 6 for this layout, but I didn't notice too many changes from version 5 on the user interface side.  My goal was to essentially make a simple breakout board for the VS1003 MP3 chip, SD card, and PIC18 on a single board, add a power supply, and then leave the rest as a prototyping area.  The prototyping area is just big enough for an RFID module from ITeadStudio with two extra rows, but also makes the space more useful in projects that don't use RFID.

Most of the eagle parts I used came from the default libraries, but I also made use of the Sparkfun library and Adafruit library.  In theory, the Sparkfun library is nice because it contains part numbers so you can order straight from them and know that your parts will match the footprint, but it's not foolproof. While Sparkfun only gives you Sparkfun part numbers, Adafruit goes further and gives part numbers for multiple major distributors (Digikey, Mouser, etc.), so I used Adafruit's library whenever a part was in both.

For the power supply, I used separate MCP1702 low dropout regulators.  This regulator is available in a variety of voltages (1.20V, 1.5V, 1.8V, 2.5V, 2.8V, 3.0V, 3.3V, 4.0V, 5.0V)  and has a typical active current of 2uA, making it a good fit for battery operated projects.  They have a typical voltage drop of 625 mA, compared to 2V for an LM7805, so the power supply input doesn't need to be as high.  I used separate regulators for each of the 3 supplies for the VS1003 chip (IOVDD, CVDD, AVDD), a regulator for the PIC CVDD, and then 3.3V and 5V generic supplies for the PIC and other parts.  There is a PTC fuse for protection, and the power input is pretty flexible and can come from USB, a barrel plug wall adapter, or two wires from a battery pack.  I used solder jumpers throughout the board so that I can configure the board as needed for each project.  In addition to the jumpers selecting the power input, there's one that allows selection of 3.3V or 5V power to the PIC.


I looked at the pinouts for the two PIC18F series chips I had on hand as samples from Microchip (PIC18LF26J11 and PIC18LF26J50) and added the basic support circuit.  This included the ICSP connector for programming/debugging, reset circuitry, a crystal, and decoupling capacitors.  One of the chips has USB built in, so I routed those pins to a mini-B connector, but solder jumpers are used so that is a select-able feature.  I will not be using USB for the project I'm working towards right now, but I'd like the option to use it in the future.


The circuit for the VS1003 mp3 chip is straight out of page 15 of the datasheet, and is definitely the part of this board in which I am the least confident.  I left out the microphone input portion of the circuit because I didn't need it, but everything else is included.  I didn't route any of the pins to the PIC, but I broke out the pins required for interfacing, so it's basically a breakout board for the VS1003 on the same PCB.   I used a Sparkfun part for a headphone jack that had a part number, but it was a mistake in their library and it wasn't until I got the board and was starting to order parts that I realized the problem.  I'll probably end up getting a separate breakout board for just the headphone jack of the part of my project.


The SD card portion of the PCB is also essentially just a breakout board.  There's a jumper that allows it to use the PIC's Vcc (which should only be selected if it's 3.3V).  I used the Adafruit SD card socket footprint, which was only available at 4UCON or Newark, but I found one that looked similar on Digikey and decided to get it, and it ended up being a match.


I put footprints for 5 LEDs on the board, mostly for status and testing as I'm developing.


I used the Open PCB service from iTeadStudio when I had my boards made, which for just $0.10 you get two random PCBs that someone else designed, and two copies of your boards are sent to random people.  The chances I'd get something useful were slim, but for ten cents it was worth it.  One of the boards I got looks like one of iTead Studio's Arduino Mega Sensor Shield.  I don't have an Arduino mega, and don't plan on getting one, so this one isn't really useful to me.  The other board was a breakout board for a TQFP-32 ATmega8.  Someone used the 5cm x 5cm service and put three copies of a simple breakout board onto a single PCB.  It looks like there's enough room that I could use my dremel to cut out 3 separate breakout boards.  This one looks more useful, and I actually have some TQFP ATmega88's on hand that I can use with it.  If anyone out there ended up with a copy of my board and happens to read this, I'd love to hear from you and see if it can be of any use to you.  Here's a picture of the two boards I received.


This is first PCB I've made where I've used silkscreen, and it was a lot easier than I thought...but it didn't turn out too well.  The first PCB I designed I used a company that didn't offer free silkscreen, so I left it off, and didn't bother with the next couple either.  Because I'm intending this to be more of a development board and will be doing quite a bit of wiring after all the components are soldered on, I realized that having labels on the rows of broken out pins would be very helpful.  The eagle "smash" command, in particular, was very helpful in laying out the board so that the text was not overlapping from different parts.  I resized a lot of the text, but didn't really have a good idea of what it would look like on the actual PCB.  A lot of it ended up being really tiny...way too small to read, and some of it didn't show up at all.  I always have the eagle files up on my computer while I'm working anyway, but it would've been nice to have better labeling on the board than I ended up with.  I'll have to pay more attention to text size in the future.  Here's a picture of the how the boards turned out.



I got all of the parts I needed from Digikey except for the VS1003 chip and the headphone jack, which I'll from Sparkfun, and the RFID module from ITeadStudio.  My end goal is to make a book reader for my daughter.  The basic idea is that I'll have extended family record themselves reading books to my daughter.  I'll put the files on an SD card, and have each one tied to an RFID tag taped inside the books so that she can swipe the book over the device and it will start reading the book to her.  My Sourceforge page for this project (https://sourceforge.net/projects/pic18devboard/) has the board design files and an Excel workbook with a (mostly complete) bill of materials with part numbers.  I'll add additional files to it as I get some of the firmware tested out and working.  My next few posts will go through getting started with PICs and implementing the different pieces needed to complete my project, assuming all goes as planned.  

Saturday, February 18, 2012

Baby Star Lights

My daughter just turned 3 months old, and she is completely fascinated by lights and things that move.  I got the idea to make a star projector from seeing one of these stuffed animals that puts a star pattern on the ceiling, although mine is a little different.  My project uses an MSP430 to control an LED inside of a ping pong ball that's mounted on the end of a servo to rotate it.


I started out by taking a ping pong ball and drilling holes all over it with a 1/16" bit, the smallest in my set.  I used a 3/16" bit to make hole for an LED and I spray painted the ball black to avoid having the ball glow.  To test it out, I wired up a quick LED circuit and when I went into a dark closet it was clear that 1/16" was too big of holes--the light was not near focused enough on the ceiling, and  it'd look even worse in the baby's room.  I started over with a new ping pong ball and used a hot sewing needle to poke tiny holes and got closer to the look I wanted.




 Switching over to the electronics, I used an MSP430G2211, which is one of the chips that comes with the MSP430 Launchpad.  Any of the small MSP430's would work just as well...the firmware's really simple.  Basically when you switch it on, the LED turns on, and then the servo rotates slowly one way to the max and then goes back the other way, and repeats.  It runs for a set amount of time (15 minutes right now...it can be varied based on how long it takes for my daughter to calm down and go to sleep), and then shuts everything down and goes to sleep (LPM3).  The servo control is on P1.1, and the LED is on P1.2.  I got a servo for $2.50 that works great.  I tried to use a red-yellow two color LED, but the one I had was too dim, so I used a bright bluish-white LED instead.  I might use an RGB LED in the future if I come back to this and clean it up.  It's powered by a 4xAA holder from Radio Shack with a power switch built in, and an L78L33 provides 3.3V for the MSP430.  The PCB I used is a spare from a stalled project (a Wii Nunchuk controlled RC car...the same board is used as the controller/transmitter and receiver/motor driver and also serves as a simple breakout board for 14 pin MSP430F/Gs) that I had made at Seeed Studio.


The most frustrating part of this project was when I tried to package it up.  I used a small Sparkfun box as a case, and once I put everything inside the box I realized that the wires I was using from the PCB to the LED at the end of the servo arm were way too thick and there wasn't enough give.  The servo was straining really hard and not moving much, so I reduced the swing range to only a few degrees, but that still didn't fix it.  I had to cut out that wire and use the thinnest I could find, which was some wire I snipped off of a spare battery holder.  It works...but I may decide to start over with the whole enclosure (maybe use this as a chance to try out a laser cutting service) and use thinner wire yet so that it works more like I'd initially planned.


The picture here is a longer exposure, so its fuzzy because of the movement, but you get the idea of how it looks on the ceiling.  The source code is very simple, but it's available at https://sourceforge.net/projects/babystarlights/.  The project didn't turn out quite like I'd planned, but it's tons of fun to see my daughter staring at the lights and following them as they move around the room, and my wife even asked to help me solder it.  My camera wouldn't pick up the light on the ceiling, but here's a quick clip of the light in action.