Building a CAN API for Arduino DUE

CAN Shield - Due electrical schematic.

Arduino Due and CAN shield with termination resistors (120 ohm) mounted. The jumpers are selecting high-speed (0V-black) and disabling low-power (3V3-red) modes in the SN65HVD234 transceivers. The CANH (orange) and CANL (purple) bus terminals hooked for a loop test.

I was able to order a DUE today, so I'll join the ranks soon :slight_smile:

I really appreciate it, that you use both CAN-Transceivers! This will be great for using it as a Gateway!

I have my Due and now it's time to order the transceivers. I'm going to get both the 234 and 235's. Which ever ones I don't use in the car I'll use on the work bench. Thanks for tackling this.

Great for you keija and that_kid. Do as I did: Request a couple of samples of each transceiver to Atmel. I have some sample sketches running OK on my Due, using a combination of Atmel and Arduino library files. The goal is to occupy as much as Arduino files and as less as Atmel files as possible. I also hope to run my first real test these next days interfacing Due with a battery manager system (with XC167CI - by Infineon and AT91SAM7).

I wanted to share another of the tests I am working now with Arduino Due using the CAN shield. The test consists of making Due read CAN data from a commercial OBD II code reader. This will prepare the ground for more tests like convert Due as a OBD2 simulator system generating some DTC codes to be read by the code reader and finally to make Arduino Due read some real DTC codes from my car (Honda-Oddysey 2002) or any other car under OBD2.

As some of you know, ODB II stands for On Board Diagnostics, level 2. OBD II is a federally mandated engine & emissions management standard for all passenger cars sold in 1996 and beyond. ODB II uses CAN bus Dual Wire like Arduino Due (ISO 11898-1/SAE J2284).

For my first test I used an Actron CP9125 pocket scanner (with a 89C71CC01CA microcontroller and TJA1050 CAN transceiver).

Here a the schematic of interconnection between the code reader and Arduino Due and a picture of both systems. So far, Due can read from the reader ID 0x07DF the following data: 02 01 00 99 99 99 99 99 which is a request data to start reading DTC codes. I am very excited exploring CAN protocol in Arduino Due and OBD2 systems. I'd recommend to get ready if you want to embark on this journey.

Excellent news, I'm just waiting on my parts to arrive from mouser.com I was going to order the engineering samples but I needed some parts so I just went ahead and get it all. Next stop is to see if my local radio shack has the shield that you are using.

Hey guys. I'm interested in getting on board with the CAN protocol as well. I've done a lot of low level CAN drivers on the pic24, dspic, and pic32 along with the MCP2551 transceiver at work. I have a DUE coming in next week and just put in my order for TI samples of the two transceivers mentioned earlier in this thread (234 and 235).
What is the scope of this CAN library? I'd be more than willing to work the low level driver stuff and different implementations of it (interrupt based, polling based, different modes).

Hello downtown_sausage and welcome aboard! We are going to need your CAN skills soon. So far I have Due running CAN 2.0A but with a mixed Arduino-Atmel library. I hope to release a couple of simple sample sketches and a tentative CAN library in github very soon. I am following guidelines/advices from the Arduino team and Atmel but everybody is welcome here. The scope: once released the CAN library, we'll need as much people as possible to be involved and contribute with ideas, applications, improvements, fixing bugs, etc... remember, this is the first Arduino board with embedded CAN controllers: just transceivers between the board and real CAN device, so, a new Arduino Art is oncoming and a lot of work to do. Thanks!

Palliser, you might consider doing your development in the open on GitHub, even before you think it's at a good draft stage. No reason we can't start helping you out already!

Thank you peplin again for your interest in help with the CAN API development. Please, have just a little bit of patience. I hope to upload the CAN library and sample sketches on the next days. I am waiting on answers/revisions by Atmel/Arduino. And as I have said, try to build or have ready you own CAN transceivers shield; otherwise, it would be virtually impossible and even dangerous to try any communication test without it.

Like you and other Arduino users, I am more than willing to see a CAN API ready and all the discussion to come.

Palliser, are you developing the base CAN drivers based on Atmel example code at the moment? My plan was to write the CAN drivers from scratch, with different configurations options. After that is up and working, integrate that code into an Arduino library.

Hello Downtown_sausage, Yes. I wrote two sample sketches based on an Atmel sample for the SAM3X-EK. Currently, I am receiving direct support from Atmel/Arduino. They are adjusting some path needs and setting the correct dependencies before releasing it on github (Arduino libraries). At the end, all the drivers (including the transceiver one) should be into libsam of future IDE releases. Regarding your excellent initiative to build the driver, I don't know how easy could be to start from scratch a can driver for the SAM3X8E. The Atmel CAN controllers are hard-to-tame for me if compared with other (remember that there are a lot of MCUs out there with Cortex-M3 core and embedded CAN controller like STM32F10XX). It requires an orchestrated initialization between PMC, AIC, CLK and CAN controllers. The main idea is to build a consistent CAN library to take advantage as much as possible of features like interrupt/message handling, timing, wakeup/sleep, producer/consumer modes, etc... It's about a short time to have available the library but....it's up to you, feel free to contribute with your skills. And thank you!

I see. I haven't looked at the Atmel CAN example drivers yet, but from my experience, chip manufacturer's code is generally pretty rubbish. If we want legitimate CAN applications for the Arduino, we will need to have an extremely solid base driver interface to work off. Don't want to build a house on a weak (inefficient) foundation.

To clarify my last post, I suggest we don't use Atmel's CAN drivers and instead work them from scratch. But if they are really good, then no need to mess with them. In reality, it will probably be a task of looking what they did and seeing if we can improve upon their driver implementation. If it's anything like the CAN processing on the PIC24/PIC32, you can probably offload much of the CAN receiving messages to a DMA channel, which will be key for efficiency. This could be done with TX too, but may not benefit too many applications. I should probably start reading the Atmel uC manual to see how they implement this stuff.

downtown_sausage we're working directly with the ATMEL engineer who wrote the examples in the first place. I suggest you coordinate with Palliser who we have put in touch with the engineer. there is a good chance to get the info straight from the source.

m

For a better understanding of the Atmel CAN controllers inside the SAM3X8E, I have dissected the initialization procedure required to let the

CAN controller interact (synchronize/listen) with the real world (CANH/CANL).

Document Sources:

  • Atmel doc 11057.pdf
  • Can Library from Atmel ASF.

System controllers used:

  • Power Management Controller (PMC)
  • Nested Vectored Interrupt Controller (NVIC)
  • CAN Controller (CAN)

CAN initialization procedure:

  1. CAN controller -> DISABLED after power-up reset.
  2. CAN controller clock -> ENABLED by PMC (via Low-Power Peripheral Bridge) for CAN peripheral IDs 43 (CAN0) and 44 (CAN1).
  3. CAN controller interrupt line -> ENABLED for mailbox X (API definition - CAN_IER_MBX) through CMSIS definitions (CANx_IRQn) in the embedded NVIC (NVIC_EnableIRQ).
  4. CAN controller initialized
    4.1. CAN_BR register (baudrate) -> SET. The following steps are performed:
    4.1.1 Check whether the baudrate prescale will be greater than the max divide value.
    4.1.2 Check whether the input MCK is too small.
    4.1.3 Initialize it as the minimum Time Quantum.
    4.1.4 Initialize the remainder as the max value. When the remainder is 0, get the right TQ number.
    4.1.5 Find out the approximate Time Quantum according to the baudrate.
    4.1.6 Calculate the baudrate prescale value.
    4.1.7 Get the right CAN BIT Timing group.
    4.1.8 Before modifying the CANBR register, disable the CAN controller.
    4.1.9 Write into the CAN baudrate register.

4.2. 8-CAN message mailboxes -> RESET. (CAN_MB_DISABLE_MODE) The following steps are performed:
4.2.1 Check the object type of the mailbox. If it's used to disable the mailbox, reset the whole mailbox.
4.2.2 Set the priority in Transmit mode.
4.2.3 Set the message ID and message acceptance mask for the mailbox in other modes.
4.2.4 Set up mailbox in one of the five different modes.
4.3. Configure a mailbox in reception (or consumer) mode
4.4. CAN autobaud listen mode -> SET in CAN_MR register (CAN_MR_ABM == 1)
4.5. CAN controller -> SET CANEN in CAN_MR register (CAN_MR_CANEN == 1)
At this stage, the internal CAN controller state machine is reset, error counters are reset to 0, error flags are reset to 0 and starts bus synchronization automatically by
scanning eleven recessive bits an then start listening to the network (real world).

I want to clarify that, even though the above initial procedure it might look over-elaborated, the nature of the CAN controller so requires. We, mortal thinkerers are used to a higher level language. My aim has been to bring here part of what's cooking regarding the CAN API, now in progress. But don't worry; at the end, a simpler solution to this whole approach will emerge.

Note: The CAN interruptions in SAM3X8E are implemented through CMSIS definitions in the embedded NVIC inside Cortex-M3 (Not from not existent AIC controller). I got confused because it would seem that some of the CAN controller sections in the SAM3X8E manual (doc11057) were from copy&paste sections of the SAM7X manual. The explanation could be that CORTEX-M3 inherited part of its functionality from the venerable ARM7.

Hi Palliser, any progress on this?

hello that_kid and thank you for ask.

For all those who have followed this post, I would like to inform you that we still working very hard building the API and runing tests, with the valuable help of Atmel. For obvious reasons (Christmas and New Year) we had few latencies but I hope that, as soon as possible, we will publish the library and sample sketches in github. On the other hand, I think it is timely and appropriate, to see from those that already have built their DIY pseudo CAN shields, to show us their progress. Thank y'all again for your patience.

Thanks for the update, I have my samples in but now I need to get a board to solder them to. My goal is to make my own board but that won't happen until I recover from my broken foot. Meanwhile I'm getting everything that I can ready to help with the testing.