Welcome to Tesla Motors Club
Discuss Tesla's Model S, Model 3, Model X, Model Y, Cybertruck, Roadster and More.
Register

Model 3: Geek mode (CANbus, OBD2)

This site may earn commission on affiliate links.
Wat vreemd dat de OBD-toegang bij Tesla via draadaftakking moet gebeuren, ik dacht dat fabrikanten via EU(?) regelgeving verplicht waren een bepaalde minimale set via een standaard OBDII stekker én protocol beschikbaar te maken? Dat om vendor lock-in (wat Tesla dus inderdaad opname fronten doet) voor reparaties te voorkomen.
Ik kan begrijpen dat in de standaard set nog (?) niets zit wat EV-gerelateerd is, dus begrijp dat mensen dan ook nog toegang willen tot de ruwe data, maar die standaard OBDII stekker zou m.i. wel aanwezig moeten zijn.

OBD is verplicht voor brandstofauto's, niet voor EVs.
 
Ik ben bezig met logging van de CAN-bus in mijn Model3 naar de onboard RaspberryPI4.
Dit om mijn mysql database te verrijken met data die niet uit Teslafi API komt.

Ik gebruik JWardell's CANbus ID & Datasheet Model 3 CAN bus IDs and data
Vooralsnog goedkope ELM327 bluetooth, serial verbinding op /dev/rfcomm0 en met eigen python-script de ATMA uitlezen met wat filters/masks

Sommige simpele codes kom ik prima aan uit, zoals bijvoorbeeld datum in CAN-ID 318:
Code:
root@tesla-rpi4:/storage# cat candump2.log | grep 318 | tail -3
318 13 0B 14 00 16 1B 03 81
318 13 0B 2C 00 16 1B 0D A3
318 13 0B 2E 00 16 1B 07 9F
root@tesla-rpi4:/storage#

1e veld na index 318, 13 hex = 19 decimaal = jaar, klopt
2e veld na index 318, 0B hex = 11 decimaal = november, klopt etc etc

Maar bij een hoop velden snap ik de berekeningen niet en krijg ik hoe ik reken ook geen logische waardes.

Code:
root@tesla-rpi4:/storage# cat candump2.log | grep 321 | tail -3 
321 DF 65 A7 58 02 58 00 00 <DATA ERROR
321 E0 65 A7 58 02 58 00 00 <DATA ERROR
321 E0 65 A7 58 02 58 00 00 <DATA ERROR
root@tesla-rpi4:/storage#

Bijvoorbeeld Data1, omschrijving: "CoolantTempBatteryInlet C u10 SB 0 scale 0.125 offset -40"

E0 hex is 224 decimaal. Wat betekend u10 SB0 scale 0.125 offset -40 ?
U10 is unsigned-10 bit neem ik aan? maar, dan blijft dat gewoon 224 toch? -40 is dat het dus eigenlijk 224+40= 264 moet zijn, dan scale 0.125 is
dat 0.125*264, dat geeft 33 graden? dat lijkt me niet te kloppen. zowel niet in celcius als fahrenheit.

Kan iemand meer uitleg geven, of een howto/url over hoe je berekeningen doet als:

-> u8 SB 16 scale 1 offset -100
-> 10 bit unsigned, startbit 10, scale 0.1
-> u14 SB 48 scale 0.128

Ik probeer kloppende/geloofwaardige uitkomsten te krijgen ;)
 
Maar bij een hoop velden snap ik de berekeningen niet en krijg ik hoe ik reken ook geen logische waardes.
Ik probeer kloppende/geloofwaardige uitkomsten te krijgen ;)
[/QUOTE]

Vergeet het hele byte concept bij Tesla, ze werken met (meestal) 64 bits blobs samengesteld uit (dan) 8 bytes.
Dus een 10 of 12bits waarde kan op een willekeurige (niet byte grens) plaats voorkomen.
Dat is ook de schrijfwijze die gehanteerd wordt:

u12 sb10 betekent een unsigned 12 bits getal met startbit op bitpositie 10
bitpositie 10 is dus het tweede byte, 2 bit.

Let ook op endianness, dus de bytes komen in de 'verkeerde' volgorde binnen via de CANbus.
Dus ontvang je dit:
0x318 0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF dan staat er eigenlijk dit
0x318 0xFE 0xDC 0xBA 0x98 0x76 0x54 0x32 0x10
Bit 0 is dus de meest rechtse bit van de 0 (in dit geval dus een 0)
Bit 63 is de meest linkse bit van de F (in dit geval dus een 1)

Bij temperaturen wordt bijna altijd met een offset gewerkt zodat ook negatieve temperaturen doorgegeven kunnen worden.
Een offset van -40 bij een waarde van 0 is dus min 40, bij een waarde van 40 is het 0 graden etc.

E0 hex is 224 decimaal. Wat betekend u10 SB0 scale 0.125 offset -40 ?
U10 is unsigned-10 bit neem ik aan? maar, dan blijft dat gewoon 224 toch? -40 is dat het dus eigenlijk 224+40= 264 moet zijn, dan scale 0.125 is
dat 0.125*264, dat geeft 33 graden? dat lijkt me niet te kloppen. zowel niet in celcius als fahrenheit.

Als je 224 neemt en dan min de offset van 40 kom je op 184 * 0.125 = 23 graden ;-)
 
Last edited:
Vergeet het hele byte concept bij Tesla, ze werken met (meestal) 64 bits blobs samengesteld uit (dan) 8 bytes.
Let ook op endianness, dus de bytes komen in de 'verkeerde' volgorde binnen via de CANbus.

Okay het begint me iets duidelijker te worden.
Je zegt dus dat de 8 bytes gewoon reeksen zijn van 64 bits en dat ze zowel van links als van rechts kunnen beginnen
Moet ik dan de hex-waardes van de bytes eerst in binary omrekenen en dan met die bit offset aan de slag?

Het gekke van dat edian wat je noemt, ik snif niet rechtstreeks de CAN he, ik doe via OBD2 een ATMA request op de ATSP0 (auto), ik vraag me af of mijn OBD2 ELM327 stack het misschien al omdraait, want mijn 318 (datum/tijd) komt er zo uit:

318 13 0B 00 0C 16 3B 1D B3
318 13 0B 07 0C 16 3B 03 A0
318 13 0B 13 0C 16 3B 19 C2
318 13 0B 15 0C 16 3B 13 BE
318 13 0B 18 0C 16 3B 1D CB
318 13 0B 1B 0C 16 3B 13 C4

can-date.png


Onderste regel van hex naar decimaal:

byte 1 jaar: 13 -> 19
byte 2 maand: 0B -> 11
byte 3 second: 1B -> 27
byte 4 uur: 0C -> 12 (zal UTC zijn, het was tussen 13u50 - 13u56
byte 5 dag: 16 -> 22

Dus in dit geval lijkt dat helemaal niet endian/achterstevoren en klopt dit gewoon 'native'???

Maar ik zou toch nog even je hulp willen vragen om even 1 rijtje uit te leggen.
Mijn 261-reeks (12 volt accu shizzle):


CAN ID source device period (ms) Bytes Data 1 Data 2 Data 3 Data 4
0x261 94 8 12v Batt Voltage V u12 SB 0 scale 0.005444 12v Batt Temp C s16 SB 16 scale 0.01 12v Batt AmpHours AH u14 SB 32 scale 0.01 12v Batt Current A s16 SB 48 scale 0.005

12v.png



261 FE 19 06 05 09 40 12 00 <DATA ERROR
261 FD 19 06 05 09 40 39 00 <DATA ERROR
261 F8 19 05 05 09 40 FC FF <DATA ERROR
261 FC 19 05 05 09 40 38 00 <DATA ERROR
261 FD 19 05 05 09 40 39 00 <DATA ERROR
261 F8 19 05 05 09 40 13 00 <DATA ERROR
261 F8 19 05 05 09 40 EA FF <DATA ERROR
261 F8 19 05 05 09 40 E8 FF <DATA ERROR
261 F9 19 05 05 09 40 FC FF <DATA ERROR
261 F9 19 07 05 09 40 11 00 <DATA ERROR

(dat data error, is dat nog een puntje van aandacht??? ;)

Wat ik wil hebben is om te beginnen even de eerste waarde:
12v Batt Voltage V u12 SB 0 scale 0.005444

Als we weer uitgaan van onderste log regel

12v Batt Voltage V u12 SB 0 scale 0.005444
Unsigned 12 bits getal, startbit 0
F9 decimaal 249, binary 11111001 (dat zijn 8 bits), moet ik dan nog 3 bits uit de 2e byte halen (19 hex, 11001, 25 dec) ?
Maar hoe dan precies?

Als je een voorbeeldje zou willen geven van de ALLE 4 deze 12 volt-accu waardes (voltage, temp, amphours en current) uit de screenshot (met data uit mijn log) en hoe je eraan komt? Want daar zitten zowel signed als unsigned getallen in (van 12, 16 en 16 bits).

Alvast super bedankt voor je tijd ;)
 
Last edited:
Okay het begint me iets duidelijker te worden.
Je zegt dus dat de 8 bytes gewoon reeksen zijn van 64 bits en dat ze zowel van links als van rechts kunnen beginnen
Moet ik dan de hex-waardes van de bytes eerst in binary omrekenen en dan met die bit offset aan de slag?

Het gekke van dat edian wat je noemt, ik snif niet rechtstreeks de CAN he, ik doe via OBD2 een ATMA request op de ATSP0 (auto), ik vraag me af of mijn OBD2 ELM327 stack het misschien al omdraait, want mijn 318 (datum/tijd) komt er zo uit:


318 13 0B 1B 0C 16 3B 13 C4


Onderste regel van hex naar decimaal:

byte 1 jaar: 13 -> 19
byte 2 maand: 0B -> 11
byte 3 second: 1B -> 27
byte 4 uur: 0C -> 12 (zal UTC zijn, het was tussen 13u50 - 13u56
byte 5 dag: 16 -> 22

In dit geval komt het toevallig goed uit omdat de waardes op de bytegrens gebruikt worden.

Maar ik zou toch nog even je hulp willen vragen om even 1 rijtje uit te leggen.
Mijn 261-reeks (12 volt accu shizzle):

CAN ID source device period (ms) Bytes Data 1 Data 2 Data 3 Data 4
0x261 94 8 12v Batt Voltage V u12 SB 0 scale 0.005444 12v Batt Temp C s16 SB 16 scale 0.01 12v Batt AmpHours AH u14 SB 32 scale 0.01 12v Batt Current A s16 SB 48 scale 0.005

261 F9 19 07 05 09 40 11 00 <DATA ERROR

(dat data error, is dat nog een puntje van aandacht??? ;)

Wat ik wil hebben is om te beginnen even de eerste waarde:
12v Batt Voltage V u12 SB 0 scale 0.005444

Als we weer uitgaan van onderste log regel

12v Batt Voltage V u12 SB 0 scale 0.005444
Unsigned 12 bits getal, startbit 0
F9 decimaal 249, binary 11111001 (dat zijn 8 bits), moet ik dan nog 3 bits uit de 2e byte halen (19 hex, 11001, 25 dec) ?
Maar hoe dan precies?

Als je een voorbeeldje zou willen geven van de ALLE 4 deze 12 volt-accu waardes (voltage, temp, amphours en current) uit de screenshot (met data uit mijn log) en hoe je eraan komt? Want daar zitten zowel signed als unsigned getallen in (van 12, 16 en 16 bits).

Alvast super bedankt voor je tijd ;)

De data komt uit de CANbus als volgt:
ID byte0 byte1 byte2 etc.. t/m byte7
de bitvolgorde is dus zo
[7-6-5-4-3-2-1-0] [15-14-13-12-11-10-9-8] [23-22-21-20-19-18-17-16]... etc
Als je ziet wat er gebeurt ben je al op de helft.
Wil je alles achterelkaar plakken in de goede volgorde dan moet je de data dus omdraaien
stel je wilt 12 bits halen met als startbit0 dan zul je inderdaad de 8 bits van byte0 en de EERSTE 4 bits van byte1 (dat is een low nibble) moeten hebben.

Wil je minder bits uit een byte halen dan 8 dan zul je moeten maskeren. In dit geval wil je de bits 11-10-9-8 dus dan is je maskeer byte 0x0F (00001111) dus het is als volgt: BattVoltage = (byte1 & 0x0F) * 256 + byte1. Daarna nog wat scalen en evt offset verwerken.
Je kunt ipv * 256 ook de hele byte1 8 bits naar links shiften maar dan moet je er wel eerst een 16bits integer van maken.
De BattVoltage moet zoiezo een 16bits getal zijn anders valt alles er links weer af ;-)
 
Wil je minder bits uit een byte halen dan 8 dan zul je moeten maskeren. In dit geval wil je de bits 11-10-9-8 dus dan is je maskeer byte 0x0F (00001111) dus het is als volgt: BattVoltage = (byte1 & 0x0F) * 256 + byte1. Daarna nog wat scalen en evt offset verwerken.
Je kunt ipv * 256 ook de hele byte1 8 bits naar links shiften maar dan moet je er wel eerst een 16bits integer van maken.
De BattVoltage moet zoiezo een 16bits getal zijn anders valt alles er links weer af ;-)

Okay, het ging goed tot dit bovenstaande stukje. Dit klinkt even als 'terughalen op de 4, verdubbelen met boer/vrouw stift, elleboog op tafel' ;-)

Ik heb voor de voltage-waarde 12 bits nodig, dus heb nog 4 bits nodig uit byte1. Tot zover duidelijk
Hoe doe ik dit precies: BattVoltage = (byte1 & 0x0F) * 256 + byte1.

byte0 (F8) 11111000 in binary reversed 00011111
byte1 (19) 00011001 in binary reversed 10011000

Ik zie een & tussen byte1 en 0x0F, *256 (waar komt dat vandaan?) en + byte1 (in dec? of hex?) en mis ik hier niet byte0 ineens in het verhaal??

je zegt 'De BattVoltage moet zoiezo een 16bits getal zijn anders valt alles er links weer af' maar in het excelsheet staat dat het een unsigned 12 is met startbit 0 ???

We zijn er bijna, toch ;)
 
Okay, het ging goed tot dit bovenstaande stukje. Dit klinkt even als 'terughalen op de 4, verdubbelen met boer/vrouw stift, elleboog op tafel' ;-)

Ik heb voor de voltage-waarde 12 bits nodig, dus heb nog 4 bits nodig uit byte1. Tot zover duidelijk
Hoe doe ik dit precies: BattVoltage = (byte1 & 0x0F) * 256 + byte1.

byte0 (F8) 11111000 in binary reversed 00011111
byte1 (19) 00011001 in binary reversed 10011000

Ik zie een & tussen byte1 en 0x0F, *256 (waar komt dat vandaan?) en + byte1 (in dec? of hex?) en mis ik hier niet byte0 ineens in het verhaal??

je zegt 'De BattVoltage moet zoiezo een 16bits getal zijn anders valt alles er links weer af' maar in het excelsheet staat dat het een unsigned 12 is met startbit 0 ???

We zijn er bijna, toch ;)

Ik weet niet waarom je byte0 en byte1 reversed maar dat moet niet, gewoon zo laten staan.
Het ampersand (&) teken is een logische AND dat kun je gebruiken om bits te maskeren
Even een stukje binaire logica
AND
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

dus als byte1 is: 0001 1001 (dat is 0x19)
en je AND met : 0000 1111 (dat is dus 0x0F)
dan wordt het: 0000 1001 (dat is 0x09)

Dus dan wordt (byte1 & 0x0F) * 256 + byte0 (dit heb ik eerder fout neergezet)
(0x19 & 0x0F) * 256 + 0xF8
9 * 256 + 248 = 2552
De scale was 0,00544 dus dan is BattVoltage = 2552 * 0,00544 = 13,78V

Waarom vermenigvuldigen met 256 ?
Omdat byte1 de waarde *256 vertegenwoordigd in een 16-bits getal.
byte0 loopt immers van 0-255
byte1 loopt van 256- 65535, dus alles (in dit geval maar 4 bits) wat in byte1 staat met 256 vermenigvuldigen

Een waarom BattVoltage een 16bits getal moet zijn ?
Omdat een 8 bits getal te klein is en dan is een 16bits getal (2 bytes) de eerst volgende mogelijkheid.
Ook al maak je dan maar gebruik van 12 bits.
 
Last edited:
  • Like
Reactions: joverdijk
Ik denk/gok even dat de DLC (lengte) van 261 maar 7 bytes is en jij wil er 8 uitlezen ?
Vandaar dat de laatste byte7 ook 0x00 is
De elm327 doet dat. Veel meer dan een waarschuwing is het denk ik niet. Wanneer ik ATMA (of STMA met en obdlink) gebruikte op mijn Outlander canbus kreeg ik zo ook constant in de oorden. Beetje jammer want het versnelt alleen je buffer overrun.
 
Ik weet niet waarom je byte0 en byte1 reversed maar dat moet niet, gewoon zo laten staan..

Cool thanks voor de uitleg, nu snap ik het, en ik heb het even met een andere regel geprobeerd en dan kom ik op 13,91V uit, dus het lijkt nu te lukken en te kloppen.

Waarom ik het reversed deed, is posting van Amund7 (auteur ScanMyTesla) op teslaownersonline forum, die schreef (over een andere value trouwens):
- E0 is only 8 bits, you need another 2
- There is also Big Endian and Little Endian, so the question is does the next 2 bits go before or after?
- In any case you need the 2 rightmost bits of 0x65
- offset is -40, so it's not +40, but -40
- I think you multiply scale first, THEN add the offset

As I mentioned to you in PM, maybe an easy start is to convert the whole packet into a string of binary, then do a string cut to get your 10 bits, just get them in the right order. I think the correct order would be byte1-bit76543210, byte0-bit76543210


Vandaar dat ik de bytes aan het reversen was.
 
De elm327 doet dat. Veel meer dan een waarschuwing is het denk ik niet. Wanneer ik ATMA (of STMA met en obdlink) gebruikte op mijn Outlander canbus kreeg ik zo ook constant in de oorden. Beetje jammer want het versnelt alleen je buffer overrun.

Ja ik ben nu nog met een cheap ELM327 aan het klooien, krijg om de zoveel regels buffer full, gebruik ook nog geen filter/masks, ik hammer gewoon even een tijdje tot ik wat waardes heb, hoef nu toch nog niks realtime te hebben... eerst de data een beetje proberen om te rekenen en te interpreteren.

Ik had een obdlink mx-wifi maar dat is een kutding qua stabiliteit en ellende (zie ook hun support forum), omgeruild voor een LX, die is onderweg. Hoop daar *veel* meer snelheid en stabiliteit uit te krijgen.

Nu nog wat python scriptjes bij elkaar googlen/copy-paste-verbouw-prutsen om die waardes om te rekenen, masken, AND'en etc.
Ben een google-programmeur ;) Vroeger Hogere Informatica (HIO) gedaan, toen kon ik nog programmeren en heb ik al deze shizzle ook gehad, maar dat was *heel* veel grijze haren geleden....
 
Over dat reversen van de binaire getallen, inmiddels heeft daar ook iemand gereageerd dat dat niet moet:

12v Batt Voltage V u12 SB 0 scale 0.005444

Candump line:
261 F8 19 DA 04 07 40 20 00

I haven’t yet looked into decoding this CAN data, so I’m not the best resource, but it looks to me like you’re flipping the bit order when you shouldn’t mess with that. Just treat it as a Little Endian byte order.
In your example the first three bytes would be 0xDA19F8. The lower 12 bits are 0x9F8. Multiply by the scaling factor and you get 13.9.


Wat hij nu precies doet en waarom hij 3 bytes neemt??? Dit is weer andere manier dan prensel uitlegde.
maar byte 2 , 1 en 0 acher elkaar zetten DA 19 F8, en dan alleen 9F8 pakken (wat 2552 in decimal is) -> 2552 * 0.005444 = 13,89 V
dat lijkt inderdaad ook te werken. Is dit nou toeval ? Of komt het omdat het 12 bit is.. Want stel dat ik een 10 bit zou willen hebben, dan gaat dit bovenstaande niet op toch?
 
As I mentioned to you in PM, maybe an easy start is to convert the whole packet into a string of binary, then do a string cut to get your 10 bits, just get them in the right order. I think the correct order would be byte1-bit76543210, byte0-bit76543210

Vandaar dat ik de bytes aan het reversen was.

Maar wat hij zegt is hetzelfde als wat ik zeg :)

De afzonderlijke bytes komen via de CANbus in 'achterstevoren' order binnen dus dan moet ze weer in de juiste volgorde gezet worden. De bit ordening in de bytes blijft wel gewoon gelijk.
Ik gebruik die spreadsheets ook niet maar heb zelf een ander overzicht waar ik alles op bitvolgorde heb staan. Dat maakt het ook veel makkelijker om te zien als Tesla weer eens wat verandert omdat je dan de bitpatronen sneller ziet verschuiven.
 
Vroeger Hogere Informatica (HIO) gedaan, toen kon ik nog programmeren en heb ik al deze shizzle ook gehad, maar dat was *heel* veel grijze haren geleden....

De eerste HIO opleiding was in 1989/1990 en daar leerde je tenminste nog wat.
In ieder geval fatsoenlijk binair rekenen en in assembly programmeren plus alle hogere talen die gewoon standaard bagage horen te zijn als je enig recht van spreken denk te kunnen hebben.
Tegenwoordig is het nivo wat er van die opleidingen afkomt echt bagger, paar mooie bullshit bingo kreten, een fout pak aan en men noemt zich opeens ICT'er, maar iets echt kunnen is er niet meer bij... :)
 
Wat hij nu precies doet en waarom hij 3 bytes neemt??? Dit is weer andere manier dan prensel uitlegde.
maar byte 2 , 1 en 0 acher elkaar zetten DA 19 F8, en dan alleen 9F8 pakken (wat 2552 in decimal is) -> 2552 * 0.005444 = 13,89 V
dat lijkt inderdaad ook te werken. Is dit nou toeval ? Of komt het omdat het 12 bit is.. Want stel dat ik een 10 bit zou willen hebben, dan gaat dit bovenstaande niet op toch?

Hij gebruikt als voorbeeld 3 bytes, had ook gewoon alle 8 bytes kunnen nemen..
En ja dit snellere truukje werkt alleen op nibble of byte grenzen (4,8,12,16 etc) maar als je op bitnivo maskeert maakt dat allemaal niet uit dan kun je er ook 9 of 11 bits uittrekken. en is je masker 0x01, 0x03, 0x07, 0x0F voor resp 1,2,3,4 bits maskering.

Overigens gebruikt Amund een subroutine waarin hij een canmessage, type en lengte variabele, startpositie en dan nog een offset en scaling factor meegeeft. Het resultaat is dan het juiste antwoord in het juiste formaat. Als je die routine overneemt in whatever taal je iets aan het maken bent ben je zo klaar.