One of the problems that I have with the CAN bus is that it uses DB-9 connectors, which are expensive. I'm not building a real industrial product here, so the DB-9 is a bit of over-kill. For this prototype, I'm going to substitute an RJ-45 connector, so that I can use CAT-5 cabling. I've got a bunch of that stuff, and tooling from an old job to make even more.
One of the features of the CAN bus is that it carries power along with signal. We can do the same with the CAT-5 cabling, modeling it after Power over Ethernet. I'm modeling my connections on the IEEE 802.3af mode B (10/100 with DC on spares.)
Since power is (potentially) coming in via the CAN bus, I'm also making the bus card the power entry point for the whole system. This means a 12v jack and power regulating components. Not being very skilled at analog circuit design, I borrowed liberally from Spark Fun's breadboard power supply.
The design of the CAN bus portion was pretty straight forward. I'm using the Microchip 2515 controller and 2515 transciever. There are a number of example circuits out there. The MCP controller uses SPI to talk to an MCU. For an MCU, I'm going with the ATmega328P. The ATtiny84 is just a bit too tiny to handle working as an SPI master (talking to the MCP2515) as well as a slave (talking to the module's controller board.) The ATmega328P is a bit big for our needs, but if we want to shave a few pennies off of the cost, it can be replaced with a 16K or 8K version. Unlike the front panel board, we'll be running this one at 16Mhz using a crystal oscillator.
Here's the schematic: Download Plc_comm_can_v10a
To test this out, I built two of them on the breadboard and wired them together. The test and debug phase was more than a little frustrating. Some of the problems:
- 16Mhz is too close to the logic analyzer's maximum sampling rate of 24Mhz. I'm not spending thousands of dollars on a more heavy duty analyzier. I got useful information out but some times it wasn't clear whether what I saw was a real problem or an artefact of the sampling issues;
- The logic analyzer's CAN protocol interpreter blew up several times. Because of problems in getting the bus frequency right (see below), it wasn't giving good information. Once I got the bus frequency right, it did work.
- I'm still not sure what the actual clock speed in the MCU is. Although I've got a 16Mhz crystal and turned off the divide-by-8 mode, it still seemed to be running at 4Mhz. Added to this, it was very difficult to get the right parameters for the MCP2515 to produce the bus speed that I wanted (about 125Khz.)
- I originally put in a couple of LEDs on the transmit and receive data lines between the MCP2515 and the MCP2551. The problem with that is that the bus is normally in the high state so they were on all the time. The bus frequency is fast enough that they didn't really flicker much when active, so I removed them.
- On the prototype, I connected one of my front panel boards to provide output for debugging. It shared the same SPI bus as the MCP2515, with a separate SS line. I found out that the front panel board wasn't putting MISO into the high impedance state as it should, so it was preventing the MCP2515 from working. I couldn't get the software right for that (it still has issues), so I just disconnected the MISO line from the front panel.
The software for this provided more than a few challenges. First, the ATmega328P has two interfaces capable of supporting SPI. There's an SPI interface as well as a USART. The former shares pins with the ICSP interface, so I kept that one as the slave side. (Note: That hasn't been tested yet.) The USART is master-only, so that's perfect for talking to the MCP2515. The USI-based SPI that I put together for the front panel wasn't suitable, so I had to write a new SPI package. I'll cover this in another post, but using C++ inheritance, I'm able to deal with multiple SPI implementations with a few simple interfaces.
The first beneficiary of this SPI package is the MCP2515 driver. The architecture of that one is a subject for a post on its own.
Once I got my two prototypes up and talking to each other, I laid out and ordered a set of boards. As of today, I have the boards and have populated two of them, but haven't done much in the way of debugging. Amongh the goofs here, I forgot to order one part (a resettable fuse for the power supply) and so I don't have a good way to test them. Another goof: While I realized that with SMD components I would need headers for testing, I left off a header for the RESET line and one for GND. I'll probably have to greenwire these or only test connected to another board that has these. A third goof: My components are a bit too close together. Trying to solder them is awkward and trying to do repairs once everything is in place is even more difficult. Ah well, this is a learning process. I can design software so that it's maintainable but I don't have the skills yet for hardware.