After working on the CAN bus reader on Arduino, I thought it would be interesting to work it up into a full Arduino shield for use in any CAN network. In particular, it could be a nice alternative to XBee and other wireless communication devices for sensor networks or other mid-range communication applications. I have been interested in doing an eagle project for a while, and this seemed like a good opportunity.

Before getting very far on the board, I went to check my parts to make sure they were still the best choices. It turns out that I missed an 8-pin DIP CAN transceiver chip in my initial search. I imagine that I mis-selected something on a Digikey search so that this chip was filtered out, or they happened to be out of stock when I was first looking and I selected “In-Stock”. I was excited to find the MCP2551, which is nearly pin-compatible with the MAX3058 I was using. I also found the MCP2515, which is a pin-compatible upgrade from the MCP2510. Neither of these chips were new; I just missed them in my initial search. I’m quickly learning that part selection is a skill to be learned along with everything else.

I spent quite a bit of time drawing the schematic and laying out the board. As this was my first time using Eagle other than following along with tutorials, a lot of the time was just getting a feel for how to use the software. After much tweaking and tuning, I had a board that I was feeling pretty good about.

I am interested in trying to etch my own circuit boards with toner transfer sometime, but I have already put a lot of effort into this project, and don’t really want to add that element to it. I’d also like to start with a much simpler board when trying that, as I think I’ll be more successful and less frustrated. I decided to just go all out and have my board fabbed!

After looking through different fab sites, I narrowed my choices down to either BatchPCB or Gold Phoenix. The others were either just too expensive for small runs, or I couldn’t find out enough about them to be confident working with them. The advantage of BatchPCB is that it is possible to do a very small number of boards and they personally look over your schematics and notify you of any glaring errors. I want at least 4-5 boards out of this run. From BatchPCB my boards are about $15 apiece, plus a $10 setup fee. From Gold Phoenix’s special prototype pricing, I could get about 15 boards for $90, or 25 boards for $100. This winds up being almost the same price for a lot more boards. There shouldn’t be a quality difference, because BatchPCB uses Gold Phoenix as their fab house. I had been very careful with my board design, and wanted more boards in a shorter time, so I went with Gold Pheonix.

I checked my Gerber files carefully using a couple viewers. Sparkfun recommends ViewPlot, which is an old Windows tool, but it ran under Wine with no trouble at all. I also found gerbv, which is a native Linux tool that I found much easier to use. When I thought everything looked good, I packed up my files and sent them to Gold Phoenix.

My experience with Gold Pheonix was better than I hoped for. I expected mediocre treatment since I was doing a very small run. They were incredibly quick to respond to both my quote request and payment. Payment was through PayPal, so there’s no worry about sending my credit card number overseas. I’ll wait for my boards to arrive to make my final judgment, but so far, I’m impressed!

I intend to make this into a kit once I get the boards and have everything tested. It will be pretty simple to assemble and fills a hole in the Arduino shield world. Once the shields come in, it shouldn’t be too long before I get it all put together!

It is pretty easy to get started with AVR development under Linux.Â Here are the steps I use to set up a C development environment under Ubuntu.Â Install these packages:

sudo apt-get install avr-libc gcc-avr binutils-avr avrdude

To build, you will probably need a makefile.Â The AVR Libc project provides one, but it’s a little hard to find on their site.Â Here is a direct link.

The default target in the makefile is atmega8.Â If you’re using a different target processor, comment out the atmega8 line by putting a ‘#’ in front of it, and uncomment the name of your processor by removing the ‘#’.Â If your processor isn’t listed, you can add it.Â To find out the names of the supported processor, you can run:

avr-gcc --target-help | grep "Known MCU names" -A 26

For instance, the Arduino uses an ATMega328p.Â There is no line in the makefile for this processor, so I add “MCU_TARGETÂ Â Â Â = atmega328p”.

You will also want to change the “OBJ” variable at the top to the name of the objects you will generate.Â For each C file you want to compile, add the name of the file, but with a “.o” extention instead of a “.c” extension.Â You can have multiple C files.Â For instance:

This is saying that you haven’t set the speed of the CPU you’re compiling for, so the delay functions may not be timed correctly.Â We can fix this by adding a macro definition to the makefile.Â For Arduino, the CPU is clocked by a 16 MHz crystal.Â Find the definition of “DEFS” and set it to read:

DEFSÂ Â Â Â Â Â Â Â Â Â = -DF_CPU=16000000UL

If you are using an internally clocked AVR, the default factory setting is 1 MHz.Â To change the clock speed or source you have to set the fuse bits.Â If you do this, update the Makefile accordingly.

To program your target, use avrdude.Â When plugged in, the Arduino shows up as a USB to Serial device, probably something like /dev/ttyUSB0.Â You can use this command to flash your program to the Arduino, after replacing “<program_name>” with your program name, and “/dev/ttyUSB0” with the device that the Arduino shows up as:

If you get a permission error, use sudo.Â I also program breadboarded AVRs with the USBtinyISP.Â The tinyisp does not need a “-P” or “-b” option, so the command will look something like this:

avrdude -c usbtiny -p t24 -U flash:w:<program_name>.hex

Make sure to select the correct processor type.Â To see a list of processors, run just “avrdude -c usbtiny”.

Finally, I like to build ctags for the AVR header files.Â This is completely optional, and if you don’t know what ctags is, just ignore it.Â I’ve written a script to do this for me so that only the values for the target processor are indexed, and not the values for all AVR processors.Â If you want to use it, download it to your project directory.Â It takes the processor name as the first argument, so you can incorporate it in your makefile like this:

The software for the CAN reader was pretty straightforward.Â The Arduino continuously polls the MCP2510 over SPI to see if a transmission has been received.Â When one is found, it reads the data out of the receive buffer and transmits an ASCII version of it over the USART.Â While these two tasks could probably both be performed by polling, I implemented the USART transmission with an interrupt to make sure that no bytes were lost in either reception or transmission.

There is not a lot that needs to be done to set up the MCP2510, but it takes a bit of reading.Â The main task is to configure the timing of the bit sampling logic.Â This defines when the CAN lines are sampled to read a dominant or recessive bit and how the timing is adjusted bit to bit so that the chip doesn’t get out of sync with other devices on the bus.Â The datasheet gives good examples of how to do this, so it’s not too bad.Â My only other concern was setting up the message filtering.Â On reset the message filters are configured to accept all messages, which is what we want for this project.Â Easy!

The 2510 has a handy loopback method for testing the settings.Â I did a quick test with this to make sure that my settings were correct.Â I hard-coded some messages into the program and transmitted them to test my receiver code.Â When I saw the same messages printed over the USART on the PC, I knew it was working.Â I then set the mode to listen-only to ensure that the chip wouldn’t interfere with the CAN bus.Â It was time to try it on the car!

I hooked it up and turned the key to the accessory position, but nothing happened.Â Apparently none of the computers are turned on in the accessory position.Â Once I turned the key to “on” though, I got a whole pile of CAN messages!Â The screen scrolled with them for a few seconds, then froze.Â This was due to a problem with the way my code ran on the AVR chip that took me a while to solve, and I still don’t fully understand.Â I’ll probably write more about that one in a future post.Â It was a silly error with strange consequences.Â Once I got it fixed, I collected all sorts of CAN data!

After reading the previously mentioned blog post from the other Mazda owner, Madox, I thought that it would be possible to do a sort of visual inspection of the packets as they arrived and to correlate them with what I was doing.Â I expected to see a few messages here and there, and then have a noticeable change when I turned something on, pushed buttons, controlled the radio, etc.Â Not so!Â There are constantly messages flying across the CAN bus, and I couldn’t notice any difference between when I was messing with the controls and when I wasn’t.

I was also disappointed to see that there is virtually no overlap between Madox’s messages and mine.Â The message identifiers I receive fit neatly in the gaps between the ones he lists.Â My best guess about this is that there are different CAN messages for different geographical regions.Â Car manufacturers might do this so that if they had to change message formats for one region, they wouldn’t have to test or recertify for other markets.Â I have no particular reason for thinking this; it’s just the only thing that I’ve thought of that makes any sense.Â Madox owns an Australian model, and I have the North American version.Â I am hoping that the formats are similar, but the message identifiers are offset somehow.

Another thing that’s kind of weird is that I see some extended CAN identifiers as well as standard length ones.Â Madox makes no mention of this.Â Maybe his commercial CAN reader isn’t reporting them?Â Or maybe his parsing software is ignoring them?Â I started to write some parsing software to help me filter the messages and see what’s going on as I do things in the car.Â While working on this I got distracted with other projects and haven’t come back to it yet.Â I’m posting one of my captures in case anyone’s interested in taking a look.

But the great thing is: it works!Â While it will be really cool when I can decode all of this, the really interesting part for me was creating the device to do the reading.Â I still have some neat ideas for in-car projects based on this work, so I hope I can get it decoded sometime so I can do more cool stuff in the Mazda!

After looking around at CAN controllers, I settled on the MCP2510 by Microchip.Â It takes care of all the low-level CAN stuff for you, allowing you to just read the CAN messages over SPI.Â It also has hardware message filtering features, which I would probably never need, but are nice to have just in case.Â I would have liked to use an Atmel micro with built-in CAN, but I wasn’t able to find one in a DIP package, which I consider essential for prototype projects like this one.

This turned out to be just as well, because after messing around for a bit, I decided to order an Arduino to use as a development platform.Â I’d wanted to play with one anyway, and this seemed to be a good opportunity.Â The Arduino is easy to program over USB and handles USART over USB for you as well.Â The MCP2510 is a good choice for integration with the Arduino, so everything turned out well.

The MCP2510 requires an additional CAN transciever chip to do the actual interfacing with the CAN bus.Â Unfortunately, I couldn’t find one of these in a DIP package either.Â I did find a Maxim chip in a SOIC package, which is about the friendliest SMD package.Â Maxim is excellent about sending samples, and happily sent me several of these devices.Â I ordered my Arduino from Adafruit in a kit that also came with a protoshield board and tiny breadboard.Â This was perfect for the project, as the breadboard made for easy prototyping with the MCP2510 and the protoshield has SOIC pads broken out to solder points.

I didn’t do enough reading before placing my parts order, and so didn’t realize that the 2510 needs a clock source.Â Not wanting to order and wait for a crystal oscillator, I found that the ATMega328 on the Arduino can output its clock on a pin.Â This can be enabled by setting the eFuses a certain way.Â It was an easy fix to update the fuses and use the microprocessor clock to drive the 2510.Â I’ve since ordered a 16MHz crystal for it so that the Arduino fuses don’t have to be altered, but it works both ways.

The final build turned out to look like this:

The wiring’s a little messy, but it works!Â My only gripe about the protoboard is that if you populate the 5v and GND headers at the bottom, your breadboard will cover up some of the SOIC breakout points.Â This might be a design oversight, but I think it comes from a conscious layout choice to keep through-hole connections from being grounded by the casing on the USB jack.Â I luckily noticed this before placing the breadboard and was able to run the SOIC breakout wires from the bottom of the board, so it worked out.Â If you’re planning on using the breadboard and the SOIC spot on the protoboard, make sure to leave off the GND and 5V headers and place the breadboard low enough to allow access to the SOIC breakout points.

Several years ago, I read somewhere about the on-board diagnostic (OBD) systems in cars and got excited.Â There’s a whole heap of stuff your car is just dying to tell you, and all you have to do is know how to listen in!Â I had dreams of a dash-mounted display, showing all sorts of engine parameters and other car information while I drove.Â At the time, I didn’t know much about developing for microcontrollers, and couldn’t find a lot of information about the protocol, so the project fell aside.

A couple years later I got a new car, a Mazda 3.Â Like most newer cars, this one had a more standard OBD interface based on the Controller Area Network (CAN) bus.Â The CAN bus is a communication protocol designed for efficiency, reliability, and robustness.Â We had studied the CAN bus in school, writing programs for CAN-controlling microprocessors.Â I again got excited, because this time I knew what was needed to access the car electronics.

After a bit more looking, I was again disappointed.Â Even though the CAN communication protocol is a freely-published standard, the information sent across it is not.Â There are standards for automotive CAN, but they are not freely available.Â Unfortunately, standards companies charge several hundred dollars for access to their standards.Â This fee is nothing for a company selling millions of dollars in products based on these standards, but is a high barrier for any hobbyist just trying to figure out how something works.Â The expense, combined with not knowing exactly which standard (or standards) I needed to access to be able to decipher the CAN bus derailed my efforts a second time.

A few months ago, I found a blog entry of a similar hobbyist who also had a Mazda3.Â This time, I wasn’t taking no for an answer.Â I had previously assumed that there were layers to the CAN protocol, much like the TCP/IP stack.Â Even if you could read the data-link layer, you had no idea what was going on in the layers above, and especially not in the (probably proprietary) application layer.Â However, this guy had figured it out.Â An individual CAN message wasn’t just a fragment of a larger communication, but stood on its own, independent of the messages around it.Â I intended to repeat his experiment with my own hardware.

I’ve had some success with this project, and am planning to write up the details in several future posts.Â However, for the time being, if anyone knows of any source of freely-available information about automotive CAN standards, please post it up!Â I’d love to see it.

Eagle by CadSoft is a popular CAD tool for designing custom PCBs.Â A free version is available for educational and evaluation purposes.Â Getting started with any powerful tool can be challenging, but RPC Electronics has a good series of videos that explain the basics of using Eagle.