Interfacing with the CAN bus

I’m looking at creating a project which interfaces with a NMEA2000 (CAN) bus. Initially, I’ll mainly be reading from the network to start working out the messages, but the long-term goal is to participate both receiving and transmitting messages.

  1. Is there a specific driver/examples/etc for the CAN controller?
  2. Any tips on what parts I need to add to the project for CAN, I believe a CAN transceiver, but anything else?

I just got a Cobra and already placed an order for 5 Panda’s, they’re quite cool… seems the only thing thats holding me back from taking over the world is the segmentation in availability of example code, drivers and documentation :slight_smile:

Thanks in advance, and thanks to GHI for creating some fantastic products.

You probably only need a transceiver and the ebbok. From that point, come here and we can help further

Thank you. Any recommendations on a PDIP transceiver?

I’m sorry, when I saw the eBook I thought it meant it was a beginners guide to just the .NET Micro Framework, not something written by you guys which explains so much! That should be plenty to get me on my way, thanks!

Hi Patrick,

Did you succeed in the NMEA 2000 communication?

Any example code?

Thanks,

Erik

erik,

I did have full functionality with the FEZ and decoding of NMEA2k messages, as well as sending the device identifier PGN(s) so it would show up on the device list.

I will dig up the source code as soon as I have access, will be sometime early next week. I am not positive but I believe GHI has changed the CAN API since I wrote this.

-Patrick

Thanks Patrick,

What type op CAN transceiver did you use?

Erik

I used a Microchip MCP2551… REALLY easy to use. Simple two external resistors for a voltage divider for Vref, no other external parts… and it’s in DIP form for easy breadboarding.

I’m working on a NMEA 200 project as well… The MCP2551 arrived today, I’m waiting on FedEx to drop of my Panda II. I even managed to source proper NMEA 2000 connectors, so the whole things should bolt to my network pretty easily…
Did I mention that this is my fist project. Can’t wait to get all the parts.
Any hints on the NMEA 2000 code would be awesome.

I’m having a great time… My Panda II arrived and put together a proto shield. I added an MCP2551 and a resistors, and presto… Instant CAN bus communications…
I spent the past two weeks decoding NMEA 2000 packets… I’ve figured out a bunch of PGNs, and reading and decoding them is not that hard… I figured out how to send an ISO Address Claim message (PGN 60928)… I picked 130 as the default address for my device. I know 100% that there is no other device with that address. The device does show up on my Lowrance HDS…
However, things get tricky after I claim an address… I get bombarded with PGN 59904 (ISO Request) packets, asking me to send PGN 126996 (Product Information). I wrote a routine to build the 126996 PGN, but it is actually 19 CAN messages long… When I build an array of 19 messages, and call PostMessages, it only ever posts 1 message… I even tried to put things into a loop, but something is still wrong… I have a gut feeling that CAN mesage buffers get corrupted somewhere… I better example about sending packets would be nice… If anybody has any code they could share I’d appreciate it…

Her is what I have so far for sending:


        static void SendProductInformation(CAN can)
        {
            N2K126996 prod = new N2K126996();
            prod.PGN = 60928; //ISO Address prod
            prod.SA = 130; //Source Address
            prod.PRI = 6; //priority
            prod.PS = 255; //DST;
            prod.NMEA2000Version = 1300;
            prod.ProductCode = 12345;
            prod.ModelID = "NMEA 2000 Compass";
            prod.SoftwareVersion = "1.00";
            prod.ModelVersion = "COMP-1 v0.01";
            prod.ModelSerial = "123456";
            prod.CertificationLevel = 1;
            prod.LoadEquivalency = 1;

            int datacount = 0;
            int numberOfMessagesPosted = 0; 
            for (int l = 0; l < 134/7; l++)
            {
                msglistout[0].ArbID = prod.ID;
                if (l == 0)
                    msglistout[0].Data[0] = 134; //set the message lengh in first packet..
                else
                    msglistout[0].Data[0] = (byte)(10 + l); //set the seq number in subsequent packages

                for (int x = 1; x < 8; x++)
                    msglistout[0].Data[x] = prod.Data[datacount++];
                msglistout[0].DLC = 8;
                msglistout[0].IsEID = true;
                msglistout[0].IsRTR = false;
                numberOfMessagesPosted = 0;
                do
                {
                    numberOfMessagesPosted = can.PostMessages(msglistout, 0, 1);
                    Debug.Print("Working on packet ("+ l + "). Posted Msg Count:" + numberOfMessagesPosted);
                } while (numberOfMessagesPosted <= 0);


            }
            // Send all messages
        }

2 Likes

Never mind… I figured it out… That code had multiple bugs and typos… I guess I shouldn’t code when I have the flu ::slight_smile:
I can now get an address, send product information, and even send compass updates… Tomorrow I’ll start playing with engine and/or electrical parameters :slight_smile:

1 Like

This is cool. We want to see a video

As soon as I clean things up a little and make look messy I’ll post the code :slight_smile: Hopefully before the weekend.

Have you tried ?:


...
can.PostMessages(msglistout, 0, datacount);
...

Welcome to the community @ Toper

Hello All,

this is awsome ! thanks Andreas ! I was looking for exemple for NMEA2000 on bus CAN that’s great thanks !
I’m beguinner, I’m just starting with Netmf with GHI product that’s look very cool !

I just have on question about that you say … (forgiven my ignorance …)

but why we need MCP2551 ??
CAN bus is not directly conectable to RD and TD CAN pin out ?

Thanks

Yes using a transceiver is required. Take a look at the CAN tutorial please.

Welcome to the community.

Using a pull-up resistor and a diode on each device, you can get away with not using a tranceiver and using TTL/logic levels instead, provided all devices are setup this way and the leads are short, etc. Beware that you don’t get any overvoltage protection this way (in other words, you can ruin your relative expensive device). See for example Is a CAN enabled microcontroller sufficient to drive a CAN bus? - Electrical Engineering Stack Exchange , “Is a CAN enabled microcontroller sufficient to drive a CAN bus?”. That answer is really just a rehash of http://www.mikrocontroller.net/attachment/28831/siemens_AP2921.pdf, “On-Board Communication via CAN without Transceiver”. Using this method, I managed to start a standard CAN device (sending a bus start command). I could see it starting to send using an oscilloscope, but I could not receive anything as the voltage swing was too small.

But in general you do need a tranceiver as the voltage levels and voltage swing (is too small, typically 1.2 volt) are not suitable for normal logic gates.

If you have difficulty getting a tranceiver, a 1 Mbit/s capable one can be built out of discrete components (three transistors, a comparator, four diodes, resistors and capacitors ) - see http://esamultimedia.esa.int/docs/gsp/completed/comp_a_99_A93.pdf ,“CAN application in avionics”, page 17: “Discrete realisation of the ISO non galvanic interface”. It uses Schottky diodes - I don’t know if normal small-signal diodes can be used instead.

The MCP2551 (http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010405) is cheap and is by far the easiest way to go forward.

Ok Guys ! thanks for all these precisions
Next time I try to look on the wiki before :wink:
thanks Peter for your detailed answer

Is there any news about interfacing GHI products with NMEA2K?