Wednesday, September 11, 2019

J1939 CAN bus and the Thomson Electak HD

For awhile I wanted to see if the standard CAN bus chip set and Arduino programs could interface with J1939 CAN bus.  I was betting it could but wanted to prove it.  I got the opportunity to borrow an industrial actuator that utilized J1939 protocol.  It is an Thomson Electrak HD actuator with the CAN bus option.  Here is a link to the product page of the one I used. (link)  It was part number HD24B045-0150CNO2MNS.


After a little research it appears J1939 uses the same physical layer (wiring, pulses etc.) as the standard automotive high speed CAN bus network.  Which meant the hardware should work.  But would the standard Arduino programs be able to decode the data stream?  Long story short.  Yes it can.

The hardware I used was an Arduino mega with a can bus shield based on the MCP2515 and MCP2551 chip set.  This is pretty typical for Arduino CAN bus shields.  Like the spark fun or seeed studio shields which I’ve used in the past.  Though the shield I used for this project was one I had previously put together from components.  And of course, I included two 120 ohm terminating resistors.

First thing I found trying to read the data stream was that the baud rate of the Thomson HD actuator was 250 kbps.  After some looking it appears that J1939 may support both 250 and 500 kbps.  But perhaps 250 kbps is more popular.  Either way once I set the baud rate to 250 kbps I could capture a CAN data stream for a few seconds every time the unit was powered up.

Decoding the Actuators feedback message

J1939 uses extended ID format.  Most of the CAN streams I’ve messed with were standard ID format.  But the extended format is not a problem and it just shows as a longer ID.  I had downloaded the instruction manual for the actuator and it specified what the data was in the message packets.  But it assumed one has in-depth knowledge of J1939.  Which I didn’t.  I wasn’t sure if the data was big endian or little endian or what.  And how that would work with the Arduino CAN shield software.  Best way to know is to look at sample the data.  Which I did.

Turns out the bytes of the message ID come out in the correct order.  But the data bytes need to be reversed.  Guess that would be the byte order is little endian.  Or in other words, the first byte received is the smallest value in the message.  If writing the bytes down as they come out we'd do it from right to left instead of left to right.  The order of the bits within each byte was standard order.    Probably easier to see with an example.


Say we get the CAN message from the actuator of:  ID: 19EFFF13,   Data: DD 01 80 01 C1 FF FF

Decoding the ID
  • The first 2 bytes: 0x19EF is a combination of a few things.  But in this case it tells us it's the feedback message from the actuator. (Priority 6 and PDU of 0x01EF00)
  • The third byte: 0xFF is the destination address.  FF is a broadcast message.
  • The last byte: 0x13 is the source ID.  In this case the address of the actuator.
Decoding the Data bytes

Once the bit and byte order were sorted out setting up a program to read and decode the messages was just a matter of extracting and combining the right bits and conversion factors as described in the actuator’s instruction manual.  Below is a visual showing how the bytes are decoded (click to see it bigger).

Yes the Arduino with a CAN shield can read the J1939 can bus data.  But can it talk to the actuator and make it move? 

Sending Commands to the actuator:

Between the actuators instruction manual and some J1939 info I found on the net, came to the conclusion that the ID needed to command the actuator would be 18EFxxyy.  The xx being the actuators address (default is 0x13) and yy being the address of my sending device.  The address of the sending device looked like it could be anything except the highest couple of values.  I chose 0xAA for my controller address.  The resulting ID for my command message was then 0x18EF13AA.  Now for data bytes.

Similar to decoding the feedback message.  Creating the command message was done in a simlar manner.  In the command message there are several attributes to be chosen.  I’ll give a brief description of each.
  • The position desired for the actuator to move to.  Any value could be chosen between zero and it’s maximum stroke.  But it turned out it needed to be a greater than about 2mm to 5mm from it’s current position for it to actually make a move. 
  • The maximum current the actuator is allowed to use.  This value had to be in the range 1 Amp to the maximum amp draw rating of the actuator.  If not in this range the actuator would respond with an error.  And if more current was used during a move then the value set here, the actuator would throw an error and stop.  Found it best to just set this value to the Max value for the unit. In my case 12.5 Amps and leave it be.  But this could be a trick feature if trying to do some load limiting logic.
  • Speed desired.  This value could be from 20% to 100%.  This was a fun one to play with.  Changing it could make the actuator move fast or slow.  I even tried changing the speed while it was already moving. And that worked too.
  • Motion enable.  This flag has to be 1 for the actuator to move.  Really the only reason to set it to zero is to clear errors or if just sending a message to keep the actuator awake and not wanting to risk moving it.
 The following image shows how the values are converted to the data bytes. (click to see it bigger)
 

To command the actuator with the above settings I’d send ID:
18EF13AA with Data A1 42 1F 15 00 00 00.

Attempting to send different values I found that I’d often get error flags in the actuator feedback message and at times the actuator wouldn’t move.  To clear the error messages I’d have to send a command message with valid parameters and the motion flag set to “0”.  Then I could go back to trying sending the message with the move flag set to “1” to move it.  After playing with it for a bit I found a setup that would work and keep everything happy. 

Here are the basics of what I found keeps everything happy

The parameters must be within the proper ranges in the command message.
  • Amps: between 1 and the max amps for the unit.  (Suggest setting the amps to the max of the unit.)
  • Position: From 0 mm to the max stroke of the unit (150 mm  in my case).
  • Speed: Between 20% and 100%
Don’t let the actuator fall asleep unintentionally
  • The actuator requires constant bus traffic to stay awake (destination FF or the actuator’s address)
  • If the actuator falls asleep and then receives a message it will go through Address claim procedure again.
  • Sending a command message every 2s or less will keep it awake.
Reply to the address claim messages (ID: 18EEFF13, Data: 01 00 60 44 00 FF 00 80)
  • When the actuator wakes or is powered up it sends and address claim message. If it is not followed by an command message within 400 ms an overload flag will automatically set.  Then the error will have to be cleared before the actuator can move.
  • Seems the best practice is to reply to all address claims from the actuator immediately with an command message.  Then keep sending a valid command message every 2s or less.  Probably a good idea to set motion flag zero on initial responses to ensure no movement is made unexpectedly.  And as a bonus the message will clear any errors if there were any.
  • The standard address claim message from the actuator is ID: 18EEFF13, Data: 01 00 60 44 00 FF 00 80.  The last byte of the ID could change if there are address conflicts or if the actuator is hardwired to a different address.  But the data bytes of the address claim are ALWAYS the same.  I set up my program to look for those data bytes and then take the last byte of the ID in that message as the address for the actuator.  Then used that address to form the ID of the commands sent to the actuator.  Oh and I have the Arduino reply to the address claim message with a command with motion set to zero right after getting the claim message. 
Using the above I could get the actuator to power up or wake up perfectly every time.  No errors or problems.

Conclusion

This was an interesting and fun little project.  With the CAN interface it was really easy to run the actuator with the Arduino.  And the variable speed feature was way cool.  Made me want to build something with one.  Maybe an Arduino controlled solar tracker?  I dunno.

14 comments:

  1. Replies
    1. Hi, I am interested in the code for this application. Thanks!

      Delete
    2. Thomson has released a CAN open version of this actuator. In my opinion it's much easier to interface for non J1939 applications. I'd suggest looking at that instead if software is needed.

      Delete
    3. I have the need to operate a couple of these actuators with arduino. Can you share your source code? Also, can you explain the difference if using can open vs j1939?
      Thanks

      Delete
    4. CAN open is a freely available CAN spec. J1939 is SAE and will charge you for the spec. Google can provide more. But basically it's the different between Pascal and C+ languages. They can basically do the same thing.

      Delete
  2. Thanks for the article. Using your guidelines, I was able to get the arduino to control the actuators. without these guidelines, I'm not sure I would have ever gotten there.

    ReplyDelete
    Replies
    1. Hello Josiah, my name is Manuel, I am doing my final project for the university and exactly the same thing happens to me, I try to control two actuators with CANopen, could you provide me with the code to see how you did it? Thank you very much in advance!

      Delete
    2. Hello Manuel, This blog was done with a J1939 actuator not a CAN open so it's code will be of no use at all. If you have an Arduino with a CAN shield connect it up as the Shield manufacturer suggests using the CAN program they provide. Once you have the arduino picking up CAN messages from the Actuator then the installation manual here: https://www.thomsonlinear.com/downloads/actuators/Electrak_HD_Installation_Operation_mnen.pdf
      explains how to turn the message into values and what to send to make the actuator move.

      Delete
  3. Hi there, i read your article with great interest.
    Just starting with a similar thomson actuator project.
    Can you share your source code? Thanks in advance

    ReplyDelete
    Replies
    1. I could but in my experience it will generate more questions than answers as attempting to decode what I wrote is likely harder than writing up new code of your own. However if you want to look (no support will be provided) here is one program I wrote that made the actuator move back and forth varying the speed. Core is basically the same. https://drive.google.com/drive/folders/1RFRgiqumsVt657V4geAX-RX4FyoJ2GGm?usp=sharing

      Delete
  4. Hi thaniel. The sourcecode worked out of the box, thank you very much. Only when sending commands to the actuator it is not moving. with pleasure i will pay for your further assistance.

    ReplyDelete
  5. Hi Thaniel can you advise me which board you were using so i can try with the same one

    ReplyDelete
    Replies
    1. It's one I made myself. My prediction of sharing my code has come true:

      "in my experience it will generate more questions than answers as attempting to decode what I wrote"

      And a reminder:

      "no support will be provided"

      Your best path forward is to start with the code designed for your CAN bus shield. If you can't modify that code there are lots of Arduino forums out there that can give you tips editing that standard code so it can decode and encode messages into a CAN stream.

      Delete