DIY Electric Car Forums banner

Tesla 10Kw Open Source Charger Controller

130K views 645 replies 35 participants last post by  Kevin Sharpe  
Ah sorry :) On the wiring diagram it says "FC CAN". Not sure what that is....
The chargers seem to be found on the powertrain CAN bus (BUS3). The same one that the inverters are on. The FC CAN seems to actually be single wire CAN from the super charger port. It runs to the BMS and charger and while I can't find it right now I believe it goes to the charge port too. Their schematics can be tough to follow - one device will have its pinout spread across 12 pages.
 
I took a look at your logs. Its hard to see much in there yet as really nothing is hooked up and so you have very limited information to find. The obvious immediately interesting things would be the pack voltage/current and the AC mains voltage/current. I would imagine that all of the boards report these things.

It seems like even absent a log from a car you might be able to provide AC voltage to a module and perhaps even vary that voltage a bit to see if we can find the difference in the CAN traffic. Likewise, at a different time you might be able to provide voltage on the output of the charger in order to find where it reports the battery voltage that the module is seeing. This can likewise be varied to help find the difference. I'd think it would be pretty safe to do both tests with fusing. It'd sure help to narrow down some of the traffic you're seeing. I'm not sure why each module needs 15 messages. They must transmit an awful lot of information in there! Probably there would be temperatures as well. Do you happen to have a hair dryer for your luxurious locks? Perhaps you could heat one of the modules up and see what that does to the CAN messages.
 
Please include the ability to update the firmware externally... I don't fancy removing the charger each time :)
I wrote a CAN based bootloader for the Due at one point. I'll bet it could be improved, fixed up, and used for this kind of thing. I wrote it when attempting to create a motor controller with a SAM3X processor. Well, that turned out to not be the best idea but I could do firmware upgrades without having to open up the controller's case.

And finally, can we have programable I/O on any spare pins so we can cope with all the things we've forgotten? iirc Collin/Jack at EVTV developed some innovative hardware that can be configured to support lots different I/O requirements and I believe that's available open source.
Well, I copied an existing design that had a push/pull output system. But, it had issues with phantom pulses on start up and it would have allowed shorting the power bus. It would have taken more work to make it really nice so I kind of gave up on that and instead went to some source and some sink outputs which are separate. But, I would think it'd be possible to put a standard optocoupler input and a sink output on the same pin pretty easily. Then people could use the digital I/O pins for either input or output but would be limited to sink outputs. That still could be a viable strategy. But, in reality I'm kind of dumb when it comes to hardware designs so I'd imagine it'd be a good idea to trust Damien to come up with something that works. ;)
 
It does, this time little edian, byte 3*256+byte 2. (guys if i get my big and little edian messed up please let me know :))

Scaling 0.01V per bit
No, you're right. 0x207 bytes 0 - 1 are the mains voltage in big endian format with a seemingly 0.033333 scaling factor. It could be 0.03125 (1/32). I could be convinced of either and we'd need an accurate measurement of the voltage at peak to be sure.

And 0x227 bytes 2-3 certainly do seem to be pack voltage in little endian format. A scaling factor of 0.01 gives a max voltage of about 324V. But, he said he went up to 350v. That would require a scaling factor of 1/92 or 0.010869565. That seems kind of far fetched. I don't know what's up with the pack voltage reading. I think you've got to be right about the 0.01 scaling factor but it just doesn't quite provide the voltage I expect.

I find this very odd because people don't normally mix big and little endian from the same device. Usually people try to keep things mostly either big or little on the bus to keep things simpler. But, it is possible that the consumer of each message is a different device and that those separate devices have a different endianness.
 
ID 0x207 0x1A 0xE6 0x00

so 00E6 = 230v :)

Max value 1FF = 511v
I agree, that looks nicer and smoother than the previous guess of the first two bytes being a 16 bit integer in big endian. Attached is a PDF graphing both on top of each other. You can see that they match *very* closely but that the new 9 bit version is smoother. I also graphed byte 0 as it tracks the mains voltage pretty much exactly but with a small value. It doesn't appear to be current as it is constant when voltage is constant.

So, what does byte 0 encode anyway? Inquiring minds want to know!

Edit: Byte 0 is essentially the mains voltage / 9. Still no idea why it's there.
 

Attachments

One of my great failures in life has been not getting Savvycan to run on linux. So i'm stuck with windoze. Did a 4 hour round trip last night to log a charge session. Guess what this morning? Bill decides to take a crap on my laptop. No more log files:mad:
Well, previously it was kind of a pain to compile SavvyCAN as it had external dependencies that you had to compile first and then place in the proper place. Now it just requires QT. I think it's easier to compile everywhere now and I know a lot of people do compile it themselves on linux. There are just so many LINUX variations that it's hard to come up with one executable that runs everywhere. I've thought about statically compiling the executable so that it has less dynamic library links that could mess up. At any rate, if you have GCC and QT 5.9 installed in LINUX you should now be able to easily compile it yourself.

It sucks that you lost your log files. I've thought about maybe adding a feature to do streaming logging so that it directly logs to file, flushing maybe every couple of seconds so that the most you'd lose during a crash is the last few seconds of log. There's no technical reason why this feature couldn't be added.
 
Ok so got a new CAN log during a charge.

Message 0x42c 42 c4 1f 4a fe 00 00 00

Guess so far :

Byte 2 and 3 I think have the charge current command. Measured 12.6A into the pack.
Well, without the log I'm just shooting in the dark but what about bytes 3 and 4 in little endian? That gives you a value of 0xFE4A which is -438. If all three modules are providing a third of the output current each then you'd expect right around 4.2 amps each. So, -438 could be the current in hundredths of an amp or -4.38A for that module.

It makes sense to me anyway. Maybe it's right, maybe it's wrong.
 
One remark would be, why would a charger use a signed command?
Not like this charger is setup to do bidirectional.
You might think so but I've seen them do it. Probably to keep the values in sync with the rest of the vehicle. Usually positive current is discharge and negative current is charge. So, keeping the chargers in negative range makes them work the same way as everything else when it comes to current reporting.
 
You played the capture back to one of the modules?

Going through the captures, bytes 1 (D2) and 4 (D5) are identical in all messages except 0x45C.

Messages 0x43C and 0x44C are identical

Attached the bytes from 0x42C
It's my guess that 0x42C controls the first module, 0x43C the second, and 0x44C the third. 0x45C is probably common to all three or something. If that guess is true then only the first module is getting activated so far. I'm not sure if that makes sense. 12.6A into a pack at 360v or so is 4.5kw which exceeds the rating of a single module. But, we don't know (or I don't know) the actual charge rate during this last log. It might not have been 12.6A. All I know is that you can see the charger ramp and then it stays constant but only in one message. As you said, the other two messages are the same but they don't seem to contain current requests in bytes 2-3 like the first message 0x42C does.

However, all three messages go through a pattern in bytes 0,1,4. It's always 0x42 in byte 0 for all three messages. Byte 1 starts out at 0x60 for all three. It then goes to 0xC4 for all three and at the same time. Byte 4 starts out as 0x64 for all three then transitions through 0x68 then 0x69 then 0x6D. The 0xC4 in byte 1 does not happen until byte 4 is 0x6D. We stay 0x6D for a bit then drop to 0x6C then go to 0xFC on all modules. Eventually 0x42C (first module???) goes to 0xFE in this byte. This seems to indicate that the module should be ready to start charging. About 8 seconds after the byte goes to 0xFE a charge ramp happens in bytes 2 and 3.

I'm attaching a graph that shows the charge ramp found in 0x42C bytes 2 and 3(little endian). Also in that graph is a mystery signal found in 0x45C bytes 0-1 which appears to be big endian and signed. It fairly closely matches the current ramp from 0x42C but it starts out hovering high and it goes negative for a little bit. I don't know what it means. Bytes 6-7 are similar to bytes 0-1 in 0x45C but they don't seem to quite make sense any way I try to graph them. Bytes 2-5 in 0x45C are fairly constant and I don't yet really have much of a guess at what they do.

But, to me it seems like the first three messages are commands and the fourth is a status feedback of some sort.
 

Attachments

Damien, what charger did you plug into?

Wallbox, type 2? Single phase 16A or three phase? Looks like the charger is being mind full of 16A AC current limit.

Looks like in 0x227 bye 4 (D5) and byte 5 (D6) are the current feedback, looks like DC current in mA.

Multiplying this with the battery voltage in the same message, 0x227 byte 2 (D3) and byte 3 (D4) it would give you power, however this seems to nude 3.7 Kw. I do not know if this would be unreasonable.

However it looks like as collin points out, 0x42C byte 2 (D3) and byte 3 (D4) contains a current demand, scaled a factor of 2.
Yes, all that seems to check out. I've created a DBC file that allows one to graph and investigate the values and all of that looks good and proper.

As Damien mentioned, treat the bytes as a row of binary.

Maybe these are just lucky numbers but, 0x42C 0x42 0xC4, if i take 0x2c4 I get 708, but you can trim the binary. 0010 1100 0100 to 010 1100 010 which is 354V or just about 3.7V per cell. But then again I might just be trying to make the numbers work.

AC current in 207 byte 5 (D6) and then bit 0 and 1 from byte 6 (D7) to make a 10bit integer, curve matches the dc current exactly, however it has a strange factor of 0.035amp per bit.
I don't think that 0x42 0xC4 encodes the pack voltage. 354v doesn't match the voltage reported in 0x227 bytes 2 and 3. The way it progresses doesn't look right either. But, not every guess can turn out. History has shown all my wrong guesses - it's all part of the fun.

But, yeah, I think you might be correct about the AC Current in byte 5 and 6.

I'm attaching the DBC file. It should have all the best guesses so far.
 

Attachments

That explains why only one of the charger modules is coming on, plus it explains the 16A phase limit.

Would expect a 16A AC phase limit to be sent to the module, however scaling is weird.

I think that allot can now be sussed out playing it back to one module and varying our findings. Does it look like the message has a checksum?
There appear to be no checksums to me. Usually anytime there is a checksum you also have a counter in the frame somewhere. There are no counters I can see and nothing that appears to be a checksum.

The master board does send current commands to the three modules so I don't know whether there is any form of current limit per phase sent beside that. It might just be that the commands in 0x4?C don't go above what the power source can provide.

A kind of interesting quirk of international power is that, in the US, we almost always have 40 or 50A service anywhere there is 240v power. Only our 120V outlets are 15 or 20A fused. We basically only use 240V for dryers, stoves, heaters, etc so we need a lot of juice and thus the outlets are all 50A. As such, in the US I'd expect that a charger that detects 230V would try to turn at least two of the charge modules on and draw around 7kw. But, that's kind of irrelevant to the discussion. I just thought it was interesting.
 
I'd have to guess voltage irregularities as well. It's possible that the charger listens to BMS messages and faults if the reported voltage from the BMS isn't pretty close to the voltage it measures itself. I'd probably do a check like that if I were them.

It sounds promising though! If it gets that far then that's a good sign. Maybe post a snippet of log of the bus from a little bit before the fault to a little bit after. It must be setting some sort of fault flag and maybe we can figure out what that fault flag means.
 
0x045C seems to have a checksum of some type in bytes 0,6 and possibly 7. If I can figure this out it should be possible to write an arduino sketch to drive this puppy:)
Nope. None of those bytes present themselves as a likely CRC or security byte. A proper CRC would have a roughly even distribution of values and almost always is coupled to a counter byte or nibble so that the traffic continuously changes and the CRC/Security byte can then detect trouble easily and quickly. None of that is present. It appears to be three signals with byte 5 and 6 always being zero. The signals are fairly constant too, there just isn't a lot of variation here. Personally I'd try hard coding the data bytes to just one set of values and transmit it over and over. I'm thinking the actually interesting stuff is in the other IDs. I don't know what 0x45C is but I don't think it's that important.

Depending on which version of SavvyCAN you're using you could do lots of fun stuff to make the 0x45C message happen but always be static. If you have a recent enough version you could write a Javascript file that implements the suspected charging protocol directly and then edit it until it works. Or you can turn off transmission of 0x45C in the playback window and add it to the custom frames window triggered by your sending of one of the other messages. Or you could script just that part. Or you could use the fuzzing window but lock it to one ID (0x45C) and the bits you want set. Then fire that up at like 20ms and do your playback with just the other two. SavvyCAN has gotten really large and feature rich but unfortunately the jerk that wrote it never documented any of it. So if you have questions about how to do something just ask.
 
Basic Tesla charger question: Does the Tesla DC fast charge(and possible other DC fast charge protocols) go through the charger? If so, can it be enabled as well as the AC charging functions?
In general, no. I don't have in-depth knowledge of the Tesla super charger but how fast charging tends to work is that the car has contactors that connect the car's battery straight to the DC fast charger itself. The fast charger then has all the charger goodies in it and handles the current and voltage limiting outside the car. The car reads voltage and current itself and sends commands to the external charger about what it would like to do. In an emergency the car always has the option to open its contactors. So, the on-board charger really isn't involved in all this but the battery management system most certainly is. Now, that all holds for CHAdeMO which I do know about. But, I can't imagine the super charger is any different.
 
I suspect from the wiring diagrams and the complexity of the charger logic board that the charger handles the Supercharging control. One question for Colin : now can I tell the frequency of a message in Savvycan? going to attempt to write a simple program to get the charger to ramp up to 2A and stay there.
You can just look at timestamps but there are far more powerful options too. Under "RE Tools" you'll find "Frame Data Analysis" this window will tell you all sorts of things about a given ID - the number of bytes it has, the minimum time between frames, max time, average. It also can tell you which bits and bytes had changes and how many times a certain bit or byte had a certain value. But, I suppose you'd really be interested in the average inter-frame timing for each ID.
 
Is there any pin on the DUE that would be best to use for reading the evse pilot signal? Or can it use any digital pin?
Well, it'd probably be most efficient to use one of the timer/counter pins (TIOA or TIOB pins). They can count pules and such for you which makes it a lot easier - just let the hardware figure out the pilot duty cycle for you.

Otherwise any digital pin could work but you'd have to very quickly check the state of the pin several times per second. Or, integrate it into an analog signal and then read that signal with one of the analog pins.

So, I guess that's three options. Doing TC mode with a TIOA/B pin is a bit more complicated in software but not so bad. Probably the easiest in software option is to turn the PWM pilot signal into an analog signal but that's more hardware for you to put on the board.

Oh, and congrats on getting it to work! Before you know it you'll have the whole car running on custom logic boards. Autopilot next, right!?
 
huh.....I thought the Due had no data memory..
It doesn't exactly. But, you can write to the FLASH memory from within the program. This can be used as a form of data memory. However, unfortunately all of FLASH is zapped at once when you flash a new program to it so if you use FLASH memory it'll get zapped each and every time you upload a new program to it. That's SUPER annoying hence the use of an EEPROM chip.

The whole chip erase is more of a design issue with BOSSAC than anything else. If you wrote your own firmware updater it could rewrite only portions of FLASH and thus allow other parts to be used for storage. But, even then, the SAM3X has an erase pin and we all tend to expose it somewhere on the PCB. If someone pushes that button it's lights out for your stored settings in FLASH.
 
Maybe I missed it but did anyone ever post a reference for the connectors on a gen 2 charger? I'm interested in the best way to connect to the AC and DC sockets on the thing. I could probably easily figure out the AMPSeal connector on the other side. But, if someone has the part# it'd save me from looking it up. Thanks
 
Damien,

What is IC5 for? I've checked schematics and was thinking that this is for activation of 12V per charger module. But after closer investigation I see that 12V goes directly to all modules?

Sent from my Z1 using Tapatalk
IC5 is a transistor array that's used to create strong outputs from the board. It's used to do things like drive relays directly from the control board.