CAN Part 9 - CRCs and Incrementing Counters (Bucket Filling Technique in XNet)

As this blog series gets longer these intros become less meaningful.  The intent of the into is to summarize all the information covered in the previous blog posts, but by now we've basically crammed a year or so of practical CAN knowledge into 8 blog posts.  As a result trying to summarize it two sentences really practical.  Just know lots of CAN stuff has been talked about, and this post is going to build on top of the previous knowledge of reading and writing raw CAN frames, as well as the in depth XNet discussed in Part 6.  In this blog post we are going to cover the incrementing counter and CRC that sometimes takes place in automotive communications, as well as ways of satisfying these requirements using hardware timing on XNet devices.

Incrementing Counters

In automotive based CAN, it is not uncommon to have a rolling counter on some signals in a CAN Frame.  The purpose is to ensure the integrity of data being sent, by incrementing a value with every transmission of the frame.  Then any device on the bus can read all frames being transmitted, and can determine if the device is still talking, and still performing the task of incrementing the counter, which may give some insight into the status of the device.  If a listener on the CAN bus still sees frames coming in, but they are not incrementing, then I can know that some part of the device is still functioning and I might be able to better understand the devices status.  Here is an example of an incrementing counter:

Time 0.000 ID 0x10 Payload: 0x00 00 00 00 00 00 00 00
Time 0.010 ID 0x10 Payload: 0x00 00 00 00 00 00 00 01
Time 0.020 ID 0x10 Payload: 0x00 00 00 00 00 00 00 02
Time 0.030 ID 0x10 Payload: 0x00 00 00 00 FF 00 00 03
Time 0.040 ID 0x10 Payload: 0x00 00 00 00 FF AB 00 00
Time 0.050 ID 0x10 Payload: 0x00 00 00 00 00 AB 00 01
Time 0.060 ID 0x10 Payload: 0x00 00 00 00 FF AB 00 02

Here we see that the last byte in the payload counts from 00 to 03, and then resets back to 00.  The other bytes of the payload may change or they may not, but that last byte must be incrementing every time it is sent, and in our example that is every 10ms.

Being a listener on a CAN bus, and determining if another device is still talking isn't too difficult to do in any API.  For most APIs you can just read all frames, pull out the counter value and compare it to the previous counter value that was read.  For XNet things can be a bit easier since we can perform a buffered read on Signals or on Frames getting all values that have been sitting in the buffer.

But if we are to simulate a device on the bus, and are required to increments a value, then the timing of our software is going to be much more critical.  Most devices looking for an incrementing counter have a relatively short timeout and may go into a faulty state if our software doesn't write the incrementing values in a timely manor.  It is not uncommon to have timing requirements of calculating the new CAN frame value, and sending a new one out every 10ms.  In Windows the reliability of timing is always a struggles.  In any general purpose operating system many other application might be trying to get the CPUs to perform their work.  Having a 10ms timing requirement is possible in software timing, but will likely have lots of jitter sometimes maybe taking 20ms, or more on overloaded systems.

So what's the solution?  Well some CAN hardware have the ability to automatically retransmit CAN frames on the hardware level, which doesn't require software to continually perform functions to keep the transmission going.  When we explored the XNet API in Part 6 we saw that some of the modes like Single Point allowed us to perform the write once, and then the database would handle how often the data would actually be written.

If we use a write mode like Single Point then we can be sure the data will go out every 10ms since it is hardware timed, but what we be able to do is change the value with every frame going out.  For this level of control what we are going to need is Queued mode.

Concept of Filling a Bucket

If we want to use XNet to allow for control over every frame going out, and have the timing be hardware controlled we are going to need something like this example illustration:

At the start of the application start we want to write several frames into a buffer which will be sent one at a time by the hardware.  The amount of frames put into this buffer doesn't matter too much, we just want to ensure that the buffer doesn't reach zero elements before we are able to put more in.

At 10ms the first frame goes out, then 20ms the next then 30ms the next.  This timing of transmission is handled by the hardware, but this only works if there are still more items in the buffer to send.  If there are no more frames in the write queue then the transmission will stop.  This means as the bucket is being emptied we need to make sure we fill it back up with another write function.

Now we see that at 40ms the next frame goes out, but what our software needs to do is ensure the bucket (or queue) never gets emptied completely, and adds some more frames to be sent out.  We need to keep track internally of the last value we wrote back at Time = 0 and start writing more adding one to the last written.  In our example we last wrote 01, so the next write needs to start at 02, so we write 02, 03, 00, and 01.  This is what I call the bucket filling technique, where the frames are being written one at a time, but we add new frames to be written every so often.  The timing of our write call isn't critical at all and in our example we first added 6 frames, so we need to write more within 60ms since that is how long it will take for the queue to be emptied.

Now that we have the concept lets look at how this appears in LabVIEW

Basic XNet Bucket Example

Here is a basic example which closely follows the images from earlier.  Here we are sending 8 bytes on a periodic CAN frame, with the first byte being a counter which goes from 0 to 3 back back to 0.  Bytes 2 through 8 come from the Payload control.  The VI will add 10 frames to the queue, and then periodically check to see how many are in the queue.  If the number of pending items is less than 10 this VI adds 10 more.  One downside of this is that a value change on the Payload may not be seen on the CAN bus until the remaining pending items are sent.  There are some more advanced techniques like flushing the buffer on a value change of the other payload bytes but then there is more work to know what the counter value should be.

Payload CRC

As discussed in Part 2 the CAN frame has a very basic CRC built in which ensures that the message is received properly.  In some automotive applications an additional CRC can be added to ensure the data being received is correct and from a device that is still communicating.  In all instances I've seen this implemented this is done with the last byte of the payload.  The particular algorithm for generating the CRC can vary, but the SAE J1850 standard uses a polynomial of 0x1D, so we will use that for this example.

With this in mind we have another reason we may need to calculate the data for each frame.  If we have an incrementing counter, and we have a CRC, then the CRC is going to change with every frame sent, since the counter will change with every frame sent.  In addition to this the payload may change, and the CRC will need to change when that occurs too.  Luckily there's an example for that too.  This is very similar to the previous example except the last byte is used for the CRC, and the CRC is calculated using a VI found in the XNet Tools package which I originally found on the NI forums here.

This is pretty similar to the last example except there we take bytes 1 through 7, perform a CRC, and then use that as the last byte in the payload.

Non-XNet Solution

So lets say you don't have XNet hardware, and can't push frames into a queue that get sent out on hardware timing.  Does this mean you can't perform an incrementing counter and CRC?  No it just means that the timing needs to be done in software, and as a result a decent amount of jitter will be seen.  Your code will typically sit in a small while loop waiting for some amount of time to go by, and then send the next frame.  On Windows you can expect jitter on the order of 10ms or so.  You may get lucky and have no jitter, but because Windows is a general purpose operating system you can never guarantee timing.  If your requirement is to send out a frame every 100ms or more software timing will probably work just fine.

Part 10

Part 10 describes an undocumented, but awesome feature of the XNet hardware.  This feature allows for uploading code to the hardware and having it execute at run-time.  The only good example I have of this is to perform CRC and Counter incrementing functionality.  But what this means is this functionality can be handled completelly on the XNet hardware and requires no periodic functions to run in your LabVIEW program.  This frees up CPU resources, and makes coding easier.  This feature could have other benefits in the future if NI ever chooses to fully support it.