Anybody mess with the CAN Commanded Torque Message ID 0x1D4?

TickTock
Posts: 1701
Joined: Sat Jun 04, 2011 10:30 pm
Delivery Date: 31 May 2011
Leaf Number: 3626
Location: Queen Creek, Arizona
Contact: Website

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

JeremyW wrote:
weber wrote:In case anyone still cares about the 8-bit CRC in the Leaf's ID 0x1D4 CAN packets, my colleague Coulomb and I have reverse-engineered it. We used the excellent method described in New Zealander Greg Ewing's awesome paper, "Reverse-Engineering a CRC Algorithm".
http://www.cosc.canterbury.ac.nz/greg.ewing/essays/CRC-Reverse-Engineering.html

The polynomial is 0x85 using left shifts. It takes the bytes in little-endian order and the initial value and final XOR are both zero. The only place that I can find that this polynomial has been used before is in a Nintendo game controller.

We'd be very interested to know if anyone has any evidence that this actually contains a torque command from VCM to TMI. It looks to us like telemetry going the other way. We'd also be interested if anyone has any theories about what ID packet does contain the torque command.

Thank you so much for this. Seriously. I'm going to use it to "tune" my leaf. Oh yes.

Sweet! Nice job!

ernieskaggs
Posts: 1
Joined: Tue Oct 07, 2014 6:54 am
Delivery Date: 07 Oct 2014

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

I can't get the the checksum to match using polynomial 0x85. I programmed the rutine to check it myself so there could be a problem but it really seems like it is working correctly.

When you say little endian do you mean that the data should be check in this order D6 D5 D4 D3 D2 D1 D0:
For example, when I use the data posted here where:
D0:F7 D1:07 D2:00 D3:00 D4:07 D5:44 D6:30 CRC:70

My algorethem gives me a CRC of 0x6B

Let me post my code in case there is some sort of glaring problem:

X=0;

matrix[X+0]=((TEST.m_sWhichBit.m_aucData[6] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[6] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[6] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[6] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[6] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[6] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[6] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[6] & 0x01) >> 0);
X=X+8;
matrix[X+0]=((TEST.m_sWhichBit.m_aucData[5] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[5] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[5] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[5] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[5] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[5] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[5] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[5] & 0x01) >> 0);
X=X+8;
matrix[X+0]=((TEST.m_sWhichBit.m_aucData[4] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[4] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[4] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[4] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[4] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[4] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[4] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[4] & 0x01) >> 0);
X=X+8;
matrix[X+0]=((TEST.m_sWhichBit.m_aucData[3] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[3] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[3] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[3] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[3] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[3] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[3] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[3] & 0x01) >> 0);
X=X+8;
matrix[X+0]=((TEST.m_sWhichBit.m_aucData[2] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[2] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[2] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[2] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[2] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[2] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[2] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[2] & 0x01) >> 0);
X=X+8;
matrix[X+0]=((TEST.m_sWhichBit.m_aucData[1] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[1] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[1] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[1] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[1] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[1] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[1] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[1] & 0x01) >> 0);
X=X+8;
matrix[X+0]=((TEST.m_sWhichBit.m_aucData[0] & 0x80) >> 7);
matrix[X+1]=((TEST.m_sWhichBit.m_aucData[0] & 0x40) >> 6);
matrix[X+2]=((TEST.m_sWhichBit.m_aucData[0] & 0x20) >> 5);
matrix[X+3]=((TEST.m_sWhichBit.m_aucData[0] & 0x10) >> 4);
matrix[X+4]=((TEST.m_sWhichBit.m_aucData[0] & 0x08) >> 3);
matrix[X+5]=((TEST.m_sWhichBit.m_aucData[0] & 0x04) >> 2);
matrix[X+6]=((TEST.m_sWhichBit.m_aucData[0] & 0x02) >> 1);
matrix[X+7]=((TEST.m_sWhichBit.m_aucData[0] & 0x01) >> 0);
X=X+8;

matrix[X]=0;
matrix[X+1]=0;
matrix[X+2]=0;
matrix[X+3]=0;
matrix[X+4]=0;
matrix[X+5]=0;
matrix[X+6]=0;
matrix[X+7]=0;

Workingvalue= ((matrix[0]<<7) | (matrix[1]<<6) | (matrix[2]<<5) | (matrix[3]<<4) | (matrix[4]<<3) | (matrix[5]<<2) | (matrix[6]<<1) | (matrix[7]));
X=8;
while (X<=63){

while (((Workingvalue & 0x80)==0) && X<=63){
Workingvalue=(Workingvalue<<1)|matrix[X];
X++;}
Workingvalue=Workingvalue ^ (0x85);
Trace("%x", Workingvalue);
}

Trace("%x", Workingvalue);

weber
Posts: 6
Joined: Mon Aug 04, 2014 7:33 pm
Delivery Date: 04 Sep 2013

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

ernieskaggs wrote:When you say little endian do you mean that the data should be check in this order D6 D5 D4 D3 D2 D1 D0:

Sorry, Ernie. I may have used the wrong terminology, but I actually meant to process them in the order they are transmitted D0 D1 D2 D3 D4 D5 D6, where D7 is the CRC.

JeremyW
Posts: 1540
Joined: Sun Nov 13, 2011 12:53 am
Delivery Date: 23 Jun 2012
Leaf Number: 19136
Location: San Gabriel, CA

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

Weber and all, you might wanna take a look at EV can messages 1DB, 1DC, and 55B to see if 0x85 works for those too. The last byte looks like a CRC (values all over the place).

CRC stuff isn't clicking for me yet. I'll have to read that paper for like the 3rd or 4th time.
Former 2012 SL leasee 6/23/12 - 9/23/15
2000 Honda Insight for long trips

coulomb
Posts: 1
Joined: Thu Oct 09, 2014 5:08 pm

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

ernieskaggs,

I don't fully understand your code, so please ignore me if I've got this wrong. But it looks to me that you're using the 0x85 as an XOR value, but it's a generator polynomial (I hope I got that term right, see http://en.wikipedia.org/wiki/Cyclic_redundancy_check ). The value 0x85 determines which taps are present in a standard CRC algorithm; in this case, since 0x85 has three ones, there are three taps.

So it seems to me that your code needs rewriting from scratch. See if you can find some example code on the web, as we did. We tested algorithms in a spreadsheet, and I think I tried some C code, but Weber seemed to be getting more progress with the spreadsheet.

weber
Posts: 6
Joined: Mon Aug 04, 2014 7:33 pm
Delivery Date: 04 Sep 2013

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

Thanks Coulomb, I hadn't noticed that. Ernie, the XORing with the polynomial needs to be inside the loop, not outside. And it needs to be conditional on the value of the bit being shifted out of the working value. I think you want something like:

Code: Select all

`while (X<=63){    if ((Workingvalue & 0x80)==0) {        Workingvalue=(Workingvalue<<1)|matrix[X]; }    else {        Workingvalue=(Workingvalue<<1)|matrix[X];        Workingvalue=Workingvalue ^ 0x85; }    X++;}`

But note the fine details in this chapter of Ross Williams' excellent "A Painless Guide to CRC Error Detection Algorithms"

TickTock
Posts: 1701
Joined: Sat Jun 04, 2011 10:30 pm
Delivery Date: 31 May 2011
Leaf Number: 3626
Location: Queen Creek, Arizona
Contact: Website

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

FWIW, I cannot seem to make it work either. The above code does match the "SIMPLE" algorithm from the chapter, but I end up of 0x57 instead of 0x70. Below is the line-by-line computation and it seems correct for 0x85 poly, but no luck.

Code: Select all

`F7   01   00   00   07   44   30   70data    work1   01   000000011   03   000000111   07   000001111   0F   000011110   1E   000111101   3D   001111011   7B   011110111   F7   111101110   6B   011010110   D6   110101100   29   001010010   52   010100100   A4   101001000   CD   110011010   1F   000111111   3F   001111110   7E   011111100   FC   111111000   7D   011111010   FA   111110100   71   011100010   E2   111000100   41   010000010   82   100000100   81   100000010   87   100001110   8B   100010110   93   100100110   A3   101000110   C3   110000110   03   000000110   06   000001100   0C   000011000   18   000110000   30   001100000   60   011000000   C0   110000001   04   000001001   09   000010011   13   000100110   26   001001101   4D   010011010   9A   100110100   B1   101100010   E7   111001111   4A   010010100   94   100101000   AD   101011010   DF   110111110   3B   001110111   77   011101111   EF   111011110   5B   010110110   B6   101101100   E9   111010010   57   01010111`

weber
Posts: 6
Joined: Mon Aug 04, 2014 7:33 pm
Delivery Date: 04 Sep 2013

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

TickTock wrote:FWIW, I cannot seem to make it work either. The above code does match the "SIMPLE" algorithm from the chapter, but I end up of 0x57 instead of 0x70. Below is the line-by-line computation and it seems correct for 0x85 poly, but no luck.

F7 01 00 00 07 44 30 70

There are two problems there TickTock. First you transcribed the data wrong. That 01 should be 07. i.e.
F7 07 00 00 07 44 30 70
And second, you have to do 8 more turns of the crank after the data runs out, shifting in zeros, to flush it through.

TickTock
Posts: 1701
Joined: Sat Jun 04, 2011 10:30 pm
Delivery Date: 31 May 2011
Leaf Number: 3626
Location: Queen Creek, Arizona
Contact: Website

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

weber wrote:
TickTock wrote:FWIW, I cannot seem to make it work either. The above code does match the "SIMPLE" algorithm from the chapter, but I end up of 0x57 instead of 0x70. Below is the line-by-line computation and it seems correct for 0x85 poly, but no luck.

F7 01 00 00 07 44 30 70

There are two problems there TickTock. First you transcribed the data wrong. That 01 should be 07. i.e.
F7 07 00 00 07 44 30 70
And second, you have to do 8 more turns of the crank after the data runs out, shifting in zeros, to flush it through.

Gah! You know I tried turning the crank 8 more time, reversing the bits, and a bunch of other stuff. Even checked the data (but apparently not close enough). Thanks - that did it. I checked this as well as the other 7 examples in this thread and the CRC matches for all. Cool!

I did it in excel with the following line copied in one column (C) and the data in another column (labeled data).
Cell C11: =IF(C10>127,bitxor(bitand(C10*2,255)+data,poly),bitand(C10*2,255)+data)

I uploaded the spreadsheet here if anyone want to look at it. You have to enable macros for the bitwise functions to work. Change the number in cell H2 to point to the different examples on the examples tab.

palmermd
Posts: 2504
Joined: Fri Apr 23, 2010 3:19 pm
Delivery Date: 31 Mar 2011
Leaf Number: 1100011011
Location: Hermosa Beach, CA

Re: Anybody mess with the CAN Commanded Torque Message ID 0x

This is awesome. Thanks guys for sharing this information. I'm sure it will lead to some awesome applications for the Leaf.
Michael

Leaf since 31 March 2011
Driving electric since 1996

First Bar Loss
Second Bar Loss
Third Bar Loss
Fourth Bar Loss