Jump to content
43oh

CAN BoosterPack


Recommended Posts

43oh Store: Buy the CAN BoosterPack for $14.99.

 

This is a universal BoosterPack for enabling CAN I/O for all the LaunchPad-capable products.  It sports an NXP TJA1051T/3 CAN transceiver which includes a "V_IO" rail for doing native 3.3V CMOS I/O with the CAN controller.

 

Included is the footprint for the Microchip MCP2515, SPI CAN Controller.  This is used to enable CAN connectivity for devices that do not have it natively supported.

This is optional though.  If you do not need the MCP2515, the CAN_RX and CAN_TX pads can be soldered to breakout pads inside the boosterpack arrangement that correspond to the requisite pins on the LaunchPad which have CAN capability.  Stellaris/Tiva and Hercules LaunchPads should be able to take advantage of this.

In that arrangement, the boosterpack simply supplies the CAN transceiver (physical-layer interface) as well as connectivity ports and the ability to supply or tap into a 5V rail going along the RJ45/CAT5 bus.

 

I decided to choose RJ45 (non-magjack) for the physical connection, primarily due to its versatility as a way to chain multiple LaunchPads together into a long-distance CAN bus arrangement and due to its general-purpose nature.  Most people use CAN to connect to their automobile; for this I will be producing a daughterboard that converts DE9 (DB9) OBD-II standard pinout into the Industrial CAN RJ45 standard, including the adaption of 12V automotive power down to 5V for powering the LaunchPad.  An OBD-II to DE9 cable will need to be supplied separately to connect this arrangement but they are easy to come by; see here for an example: https://www.sparkfun.com/products/10087

 

Support for terminating the CAN bus is included, and this board supports the Split-Bus configuration with two 60R resistors and a single 4.7nF capacitor to provide a noise sink.  This should be done at either end of the CAN bus, but nodes in the middle shouldn't need it.  If any nodes are connected to the bus with a stub (not in-line but branched off using some sort of 3-port concentrator), it is recommended they use termination with two 1.3K-ohm resistors.  This is not likely necessary thanks to the two RJ45 ports provided on the board which facilitate connecting nodes "in-line" to the bus.

 

The 5V rail (CAN_V+) in the RJ45 connection can be attached directly to the LaunchPad's 5V rail in order to let the LaunchPad supply power to the whole bus, or it can be connected through a Current-Limiting IC to supply the LaunchPad's 5V rail along with bulk capacitance (SMD 1206 and/or PTH aluminum electrolytic capacitors; supply bulk capacitance to the board to survive long-distance cabling).

To support using the 5V supply from the MSP430 LaunchPad, a "5VTAP" pad in the upper left is supplied which you can connect to TP1 (right behind the USB connector).  If you are powering the MSP430 LaunchPad from the CAN bus itself this is not needed (the MCP1725 voltage regulator will supply the 3.3V Vcc rail).

 

OSHpark mockup pics:

post-15991-0-16190300-1375476722_thumb.png

 

post-15991-0-53332800-1375476727_thumb.png

 

 

!!! NOTE : this design has major bugs, update forthcoming !!!

Schematic (PDF): DipTrace Schematic - SPI_CAN_BPak_draft1.pdf

OSHpark gerbers: OSH_SPICAN_v10.zip

Elecrow/Seeed/ITead gerbers: Elecrow_SPICANv10_5x10.zip

!!! NOTE : this design has major bugs, update forthcoming !!!

This board is intended to use the 5x10cm PCB service from the Chinese fabs.

Edited by bluehash
[ADMIN] - Add store link.
Link to post
Share on other sites
  • Replies 41
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

43oh Store: Buy the CAN BoosterPack for $14.99.   This is a universal BoosterPack for enabling CAN I/O for all the LaunchPad-capable products.  It sports an NXP TJA1051T/3 CAN transceiver which incl

http://www.asciiflow.com/#Draw .. useful for doing character based graphics

It's gettin' there... need to get a mouser order going soon for some 0805 components, including the 60R resistors and 4.7nF capacitors.  But it's awfully close to finished & ready to roll, plus my

Posted Images

  • 4 weeks later...

It's gettin' there... need to get a mouser order going soon for some 0805 components, including the 60R resistors and 4.7nF capacitors.  But it's awfully close to finished & ready to roll, plus my CAN-RJ45-DE9 adapter board from OSHpark should be here tomorrow.  After that I'll have a solution for hooking the LaunchPads to my car.  Oh, need to snag an OBD-II-to-DE9 cable too.

post-15991-0-65585000-1377833422_thumb.jpg

Link to post
Share on other sites

It's gettin' there... need to get a mouser order going soon for some 0805 components, including the 60R resistors and 4.7nF capacitors.  But it's awfully close to finished & ready to roll, plus my CAN-RJ45-DE9 adapter board from OSHpark should be here tomorrow.  After that I'll have a solution for hooking the LaunchPads to my car.  Oh, need to snag an OBD-II-to-DE9 cable too.

I bought my cable from here - http://www.obd2cables.com/products/obd-cables/obd-ii-cables/

Link to post
Share on other sites
  • 2 weeks later...

Got a decent library written, IMO, just not tested at ALL... LOL

 

I decided to take the opportunity to write proper documentation for it before I go crunching at the code: https://github.com/spirilis/mcp2515/blob/master/API.md

 

Now, time to play... with my logic analyzer hooked up to see what's going on.

Link to post
Share on other sites
  • 3 months later...

New boards have been in for a little while, I got one built out with the MCP2515 - this time SOIC-18 instead of TSSOP.  Loopback mode at least works, successfully transmits & receives that way, but to do a proper test of the transceiver hardware I need to get a 2nd one built with MCP2515 since I wrote the library & know how to use it (not so much with Tiva and Hercules just yet, although Hercules should be E-A-S-Y with HALCoGen...).  Currently have one mostly built with pins on CAN_RX/CAN_TX for Tiva or Hercules, but none built out with the MCP2515.  Also running out of RJ45 jacks... oops.

 

Gonna spend my last 2 RJ45 jacks on an MCP2515-based board so I can test my library live over the wire.  Then early next month, mouser order time.

Link to post
Share on other sites

@@spirilis Don't you need two Hercules'? I can loan you mine for testing.

Naw I should be able to have heterogeneous CPUs talking... MSP430+MCP2515 talking to Tiva, Hercules, etc (even BBB if I make a cape for this RJ45 pinout)

 

For now I'll build out another MCP2515-populated bpak and have 2 MSP430's talking.

 

Sent from my Galaxy Note II with Tapatalk 4

 

 

Link to post
Share on other sites

Soldered up my 3rd bpak and used the last 2 RJ45 jacks I got-

post-15991-0-27117700-1387908283_thumb.jpg

 

Will have to test it out later.  I wrote a "call.c" and "response.c" based around my library that should properly vet the workability of this boosterpack with a pair of MSP430's.

 

Next month's mouser order... wishlist:

Bunch of RJ45 jacks

Bunch of NXP TJA1051T/3's

Maybe 10 MCP2515's

Shitton of TI TPS27081A (the inrush-current limiter chip for nodes feeding off the 5V VBUS in the RJ45 pinout)

 

Then if the BPak does indeed work properly, I'll look into options for selling (probably through the 43oh store, as I know @@bluehash has mentioned interest in CAN work!)

 

It'll be a little different since there will be 2 options for these bpak's... Populate MCP2515, or not.  Depends on whether the user will want to use it with an MSP430/C2000 LP (which also doesn't have CAN builtin) or one of the CAN-native MCUs like Tiva and Hercules.

 

Link to post
Share on other sites

Welp, got my two MCP2515 BoosterPacks built out, fixed some bad solder joints, can't get the two to talk... slapped my Saleae Logic16 on there and I'm giving it the fine analysis.

 

I'm basically in bitrate/time quanta hell right now, trying to figure out where my can_speed() function and params are going wrong here since I'm getting errors every time I TX - the MCP2515 detects them too and kicks back a message error, Saleae shows it as well.  Finally got a CAN frame going out that looks halfway complete except it errors at the very end (ACK)... not to mention the Extended CAN Identifier that my Saleae reports isn't anywhere close to what I was sending.

 

More debugging to go...

Link to post
Share on other sites

Well how 'bout that, the GND pad on the NXP CAN transceiver on my target/receiver boosterpack wasn't connected properly.  Many of those chips were reclaimed from my first attempt using a heat gun, so the pads aren't necessarily 100% straight & true.  Bolstered them up with a lot more solder+flux and now I have a successful transmission!  ... according to the Saleae anyhow.  Plus my values I was writing to the speed control registers were off by 1 (many needed a -1 before writing, since value 0 implies whatever the lowest possible value can be).

 

The ID is way off, so my bit shifting math must be wrong somewhere.  Gotta sit down with pen & paper and map those out properly.

 

Alas, making good progress!

Link to post
Share on other sites

Huh ok, revelation- Extended CAN IDs have the Standard ID at the high 11 bits, ext ID at the lower 18 bits, not the other way around as I had assumed!

So my call.c test is transmitting correctly over the CAN bus now.  Receiver isn't sending a reply which is puzzling, so I'll have to try troubleshooting that differently (going to try sending debug info back over the CAN bus now...)

 

Woot!  Got my example working properly now.  Yay!

Lots of small bugs in the handling of the SIDH, SIDL registers... What a mess!  At least it's working now.

 

For a sneak peek before I document the library & post it, here's my call & response programs:

 

 

call.c

/* call.c
 * Very basic I/O test of the MCP2515 on MSP430
 * Sends a message every second, responds if it finds the right response
 * Intended for MSP430 Value Line (G2xxx) chips
 */
#include <msp430.h>
#include "mcp2515.h"

uint32_t rid;
uint8_t mext;
uint8_t irq, buf[8], buf2[16];
volatile int i;
volatile uint16_t sleep_counter;
#define SLEEP_COUNTER 20

int main()
{
        WDTCTL = WDTPW | WDTHOLD;
        DCOCTL = CALDCO_16MHZ;
        BCSCTL1 = CALBC1_16MHZ;
        BCSCTL2 = DIVS_1;
        BCSCTL3 = LFXT1S_2;
        while (BCSCTL3 & LFXT1OF)
                ;
        
        P1DIR |= BIT0;
        P1OUT &= ~BIT0;
        sleep_counter = SLEEP_COUNTER;

        can_init();
        if (can_speed(500000, 1, 3) < 0) {
                P1OUT |= BIT0;
                LPM4;
        }

        can_rx_setmask(0, 0x000000FF, 1);
        can_rx_setfilter(0, 0, 0x000000F0);
        can_rx_mode(0, MCP2515_RXB0CTRL_MODE_RECV_STD_OR_EXT);

        can_ioctl(MCP2515_OPTION_LOOPBACK, 0);
        can_ioctl(MCP2515_OPTION_ONESHOT, 0);
        can_ioctl(MCP2515_OPTION_MULTISAMPLE, 0);

        // dump registers over SPI for debugging (logic analyzer can view this)
        for (i=0; i < 16; i++)
                can_r_reg(i * 16, buf2, 16);
        WDTCTL = WDT_ADLY_16;
        IFG1 &= ~WDTIFG;
        IE1 |= WDTIE;

        while(1) {
                if (mcp2515_irq & MCP2515_IRQ_FLAGGED) {
                        irq = can_irq_handler();
                        if (irq & MCP2515_IRQ_RX && !(irq & MCP2515_IRQ_ERROR)) {
                                i = can_recv(&rid, &mext, buf);
                                if (i > 0) {
                                        if (buf[0] == '1' && mext && rid == 0x00000040) {
                                                P1OUT |= BIT0;
                                                __delay_cycles(800000);
                                                P1OUT &= ~BIT0;
                                                __delay_cycles(800000);
                                                P1OUT |= BIT0;
                                                __delay_cycles(800000);
                                                P1OUT &= ~BIT0;
                                                __delay_cycles(800000);
                                        }
                                }
                        } else if (irq & MCP2515_IRQ_ERROR) {
                                if (irq & MCP2515_IRQ_TX && !(irq & MCP2515_IRQ_HANDLED))
                                        can_tx_cancel();
                                can_r_reg(MCP2515_CANINTF, &mext, 1);
                                can_r_reg(MCP2515_EFLG, &mext, 1);
                                while(1) {
                                        P1OUT |= BIT0;
                                        __delay_cycles(400000);
                                        P1OUT &= ~BIT0;
                                        __delay_cycles(400000);
                                }
                        }
                }

                if (!sleep_counter) {
                        buf[0] = '1';
                        buf[1]++;
                        can_send(0x00000080, 1, buf, 2, 3);
                        sleep_counter = SLEEP_COUNTER;
                }

                if ( !(mcp2515_irq & MCP2515_IRQ_FLAGGED) ) {
                        //P1OUT ^= BIT0;
                        LPM3;
                }
        }
        return 0;
}

// WDT overflow/timer
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
        IFG1 &= ~WDTIFG;
        if (sleep_counter)
                sleep_counter--;
        else
                __bic_SR_register_on_exit(LPM3_bits);
}

// ISR for PORT1
#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR(void)
{
        if (P1IFG & CAN_IRQ_PORTBIT) {
                P1IFG &= ~CAN_IRQ_PORTBIT;
                mcp2515_irq |= MCP2515_IRQ_FLAGGED;
                __bic_SR_register_on_exit(LPM4_bits);
        }
}

response.c

/* response.c
 * Very basic I/O test of the MCP2515 on MSP430
 * Waits to receive a message at 0x80, sends a reply to 0x40
 * Intended for MSP430 Value Line (G2xxx) chips
 */
#include <msp430.h>
#include "mcp2515.h"

uint32_t rid;
uint8_t mext;
uint8_t irq, buf[8], buf2[16];
volatile int i;
#define SLEEP_COUNTER 20

int main()
{
        WDTCTL = WDTPW | WDTHOLD;
        DCOCTL = CALDCO_16MHZ;
        BCSCTL1 = CALBC1_16MHZ;
        BCSCTL2 = DIVS_1;
        BCSCTL3 = LFXT1S_2;
        while (BCSCTL3 & LFXT1OF)
                ;
        
        P1DIR |= BIT0;
        P1OUT &= ~BIT0;

        can_init();
        if (can_speed(500000, 1, 1) < 0) {
                P1OUT |= BIT0;
                LPM4;
        }

        can_rx_setmask(0, 0x000000FF, 1);
        can_rx_setfilter(0, 0, 0x000000F0);
        can_rx_mode(0, MCP2515_RXB0CTRL_MODE_RECV_STD_OR_EXT);

        can_ioctl(MCP2515_OPTION_LOOPBACK, 0);
        can_ioctl(MCP2515_OPTION_ONESHOT, 1);

        for (i=0; i < 16; i++)
                can_r_reg(i * 16, buf2, 16);

        while(1) {
                if (mcp2515_irq & MCP2515_IRQ_FLAGGED) {
                        irq = can_irq_handler();
                        if (irq & MCP2515_IRQ_RX && !(irq & MCP2515_IRQ_ERROR)) {
                                i = can_recv(&rid, &mext, buf);
                                if (i > 0) {
                                        if (mext && rid == 0x00000080) {
                                                can_send(0x00000040, 1, buf, 2, 3);
                                        }
                                }
                        } else if (irq & MCP2515_IRQ_ERROR) {
                                can_r_reg(MCP2515_CANINTF, &mext, 1);
                                can_r_reg(MCP2515_EFLG, &mext, 1);
                                while(1) {
                                        P1OUT |= BIT0;
                                        __delay_cycles(1600000);
                                        P1OUT &= ~BIT0;
                                        __delay_cycles(1600000);
                                }
                        }
                }

                if ( !(mcp2515_irq & MCP2515_IRQ_FLAGGED) ) {
                        //P1OUT ^= BIT0;
                        LPM3;
                }
        }
        return 0;
}

// ISR for PORT1
#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR(void)
{
        if (P1IFG & CAN_IRQ_PORTBIT) {
                P1IFG &= ~CAN_IRQ_PORTBIT;
                mcp2515_irq |= MCP2515_IRQ_FLAGGED;
                __bic_SR_register_on_exit(LPM3_bits);
        }
}

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...