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

Tesla Wall Connector load sharing protocol

This site may earn commission on affiliate links.
I've finished decoding the 11 new commands in the new firmware. Although two of them are clearly intended to stop/start charge, they mostly just flip the main relays and fail to send a CAN message to the car telling it to start or stop. When the TWC stops charging, the ring around the car plug continues flashing green for ~30 seconds, goes blue for a couple seconds (presumably asking the TWC to resume charging), green for a bit longer, then red. After that, start charge command will not start charging again until you re-plug the car.

Basically, it looks like Tesla failed to test that stop/start charge actually works with a Tesla vehicle. WTF?? I can't really imagine how or why they could make such an error, especially since they had it working in firmware from 2016. My only possible theory is that maybe it somehow works with the newest Tesla vehicles but not with my 2014 car? Or they threw it in with no real testing because it's not used during normal operation? Or maybe it's like an emergency stop where they don't care if the car can be started again, but then why include a start command?

I put the TWC in legacy communication mode (DIP switch 2 off) and then I can successfully stop and start charge via the commands, but it's no more effective than ceasing communication with the TWC until the car stops charging. After some random number of stops, the car will refuse to start again until it's re-plugged. I also found the stop/start tests caused the car UI to change to a 30A limit instead of 40A at some point and it did not return to 40A upon re-plugging.

I ran tests using a 2017 TWC and a March 2018 TWC that the new firmware came with - both behaved the same. I also tried other things like setting the charge rate to 0A before stop charge and using the FCE7 command to reset the CAN network before stopping or before starting charge. Nothing made a difference.

None of the other new commands has anything to do with stop/start charging. The other nine commands will:
1) Enter a test state where all LEDs turn green and an orange LED in the middle stays on. Car will actually charge in this state, in which case the LEDs stream green but orange LED in middle remains lit.
2) Exit test state.
3) Return four bytes at memory location 8CF0 and 8CF1. These bytes are always zero in any state I could think to test.
4) Get state of the plug. Returns 0 when unplugged, 1 when charging, 3 when plugged in but not charging (for any reason, including error). It can also return 2 but I could not find a state where 2 was returned. Works with fake car in legacy communication mode as well.
5) Get firmware version including build number. Returns 4.5.3.2 with March 2018 TWC. Also returns TWCID of the unit. The old firmware version command returns only 4.5.3 and does not include TWCID.
6) Return (S)TSN plus the TWCID of the unit.
7) Return first 7 characters of VIN number of connected car. If DIP 2 is off (legacy communication mode) or fake car is plugged in, returns all zeros.
8) Return next 7 characters of VIN.
9) Return last characters of VIN.

So the new firmware still doesn't solve the stop/start charge problem or give us battery state. *sigh* But I can update TWCManager to display whether a car is plugged in or not, and to use the VIN number of the plugged car to stop/start the correct car using car API commands.


@CDragon : can you find a trace of that in the firmware ?

Nothing in the firmware checks if GPIO 34 is high or low, so it probably connects to a peripheral that does something when it's high or low. There is only one function in the latest firmware that does anything with GPIO 34: It sets GPIO 34 low as well as setting many other GPIO pins high or low, accesses a number of memory addresses of unknown function, and does something different depending on whether Serial Peripheral Interface A (SPI A) Status Register bit 0x20 is set or not.

What is your firmware version? You can find out using http://<raspberry pi address>/index.php?sendTWCMsg=FB1B&submit=1

If it returns 4.5.3, please get me the extended firmware version using: http://<raspberry pi address>/index.php?sendTWCMsg=FBEC7777<TWCID of slave>&submit=1
 
Last edited:
"...
What is your firmware version? You can find out using ..."
Answer:
————————————————————————————————————
Get firmware version: FB1B
Response: FD 1B 04 05 03 00 00 00 00 00 00 00 00 27
Decoded response
Firmware version: 4.5.3
————————————————————————————————————
Get (S)TSN (serial number): FB19
Response: FD 19 41 31 38 47 30 30 30 XX XX XX XX 6B
Decoded response
(S)TSN: A18G000XXXX (manufactured between Mar 26th and Apr 8th 2018, TWCID 4580)
————————————————————————————————————
Get model: FB1A
Response: FD 1A 45 56 57 32 54 33 32 48 4C FF 00 8A
Decoded response
Model: EVW2T32HL
————————————————————————————————————
http://raspberrypi.local/index.php?sendTWCMsg=FBEC7777XXXX&submit=1
Response: FD EC 45 80 04 05 03 02 00 00 00 00 00 00 00 BF
————————————————————————————————————
 
Finally I got my PV installed end of the week and all of this starting to make real sense now.
I need to thank cdragon again and again, because I could never figure out the script on my own!

I Modified the script to work with my Fronius Symo 7.0-3-M.
This inverter has a builtin network connection via Wifi or LAN cable and an API that delivers json.

In case someone needs to replicate this I put my changes here.
So I made the following modifications (please excuse my bad skills!):

Add import requests module to get the data. I do not know if this is really necessary, but it works this way - finally...
open vim and edit the python script
vim.tiny /home/pi/TWC/TWCManager.py
Code:
# Remaining bytes always contain a value of 0.

import serial
import time
import re
import subprocess
import queue
import random
import math
import struct
import sys
import traceback
import sysv_ipc
import json
import requests


##########################
#
# Configuration parameters

Install the module on the pi linux image:
Code:
sudo apt-get install python3-requests-oauthlib

I commented the original code and put my changes in it.
I put all here, to show the complete section without hassle with some diff nonsense writing. 192.168.0.251 is the IP of my inverter, modify it to yours if needed.
Code:
                    # The curl command used below can be used to communicate
                    # with almost any web API, even ones that require POST
                    # values or authentication. The -s option prevents curl from
                    # displaying download stats. -m 4 prevents the whole
                    # operation from taking over 4 seconds. If your service
                    # regularly takes a long time to respond, you'll have to
                    # query it in a thread that sets a variable to be used here.
                    # If we delay over 26ish seconds here, slave TWCs will
                    # decide we've disappeared and stop charging.
                    #greenEnergyData = run_process('curl -s -m 4 "http://127.0.0.1/history/export.csv?T=1&D=0&M=1&C=1"')

                    # In case, greenEnergyData will contain something like this:
                    #   MTU, Time, Power, Cost, Voltage
                    #   Solar,11/11/2017 14:20:43,-2.957,-0.29,124.3
                    # The only part we care about is -2.957 which is negative
                    # kWh currently being generated. When 0kWh is generated, the
                    # negative disappears so we make it optional in the regex
                    # below.
                    #m = re.search(b'^Solar,[^,]+,-?([^, ]+),', greenEnergyData, re.MULTILINE)
                    #if(m):
                    #    solarWh = int(float(m.group(1)) * 1000)
 
                    # Decode into an object

                    r = requests.get('http://192.168.0.251/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceID=1&DataCollection=CommonInverterData' ,timeout=4)
                    if(r):
                        solarPowerObject = r.json()
                        solarWh = solarPowerObject['Body']['Data']['PAC']['Value']

                    # Real time AC being fed into the mains
                    if(solarWh):
 
  • Informative
Reactions: laalves911
I get problems when the inverter shuts down at night and the network ip is unreachable.
The script fails at this time and is no longer functional.

I could come up with the solution of checking the reachability of the inverter with the module "tcping", but I am unsure if that is really needed...
May someone skilled take a look? First I thought the line "if (r): would be enough, but obviously it is not...

Code:
# pip3 install tcping
>>> from tcping import Ping
# Ping(host, port, timeout)
>>> ping = Ping('212.69.63.54', 22, 60)
>>> ping.ping(3)
Connected to 212.69.63.54[:22]: seq=1 time=23.71 ms
Connected to 212.69.63.54[:22]: seq=2 time=24.38 ms
Connected to 212.69.63.54[:22]: seq=3 time=24.00 ms
 
  • Informative
Reactions: laalves911
I've my EU wallconnector running in 16A master mode. Is there a way to get information out of it like firmware version or VIN of the connected car while running TWCManager in slave mode? Since I don't have any solar installation I don't need to regulate any charging current but if I can only get data out of the wallconnector while in slave mode I'll have to switch roles here.
 
I Modified the script to work with my Fronius Symo 7.0-3-M.
This inverter has a builtin network connection via Wifi or LAN cable and an API that delivers json.

In case someone needs to replicate this I put my changes here.


Code:
                    r = requests.get('http://192.168.0.251/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceID=1&DataCollection=CommonInverterData' ,timeout=4)
                    if(r):
                        solarPowerObject = r.json()
                        solarWh = solarPowerObject['Body']['Data']['PAC']['Value']

                    # Real time AC being fed into the mains
                    if(solarWh):

@Nietschy I also have a fronious inverter and smart meter - getting the real time excess current is only half the solution. Have you modified the rest of the code so that the amount of charge actually changes appropriately?

Working through the logic - assuming you are making 5kw of power from the panels and your house is consuming 2kw, then prior to charging you have 3kw of excess. On the first loop the excess mains current means the car charges at 3kw (as desired).
However on the second loop, the AC fed to the mains is now 0 (5kw solar = 2kw house + 3kw car + 0 excess). The Fronius can't distinguish between the house and the car, it simply reports a load = 5kw. If you base the charge current off the excess mains reading, 0 excess causes it to stop charging.

As written, CDragon's code doesn't store the current car current. I modified mine (very inelegantly) so that there is a persistent variable that stores "last_current_to_car", then there is a loop that says "new current to car = last_current_to_car + excess/240".

@CDragon it would be great if you could make this a toggle in the settings or similar, for everyone who has real time load monitoring capabilities as well as real time solar output monitoring.
 
Last edited:
@Nietschy I also have a fronious inverter and smart meter - getting the real time excess current is only half the solution. Have you modified the rest of the code so that the amount of charge actually changes appropriately?

Hi gingerbeer.
Thank you for your question.
I must say that I do not follow the used current for my charging habits. My power draw for the house is pretty much stable at a 200W all the time. (except when cooking) I switch charging off, or reduce the charging speed manually at this time.

cdragon put a varibale for the amps used in the house, I just put 1A in there and be done with it.
And whats funny is, that my AP1 car, can charge with more than 16A if using only 1 phase!
Currently I charge the car with the TWC with only one phase from 6A - 25A. It is working perfectly so far.

I have a power meter installed in my junction box on the wall, but only for the heat pump for the house. This meter knows if there is something left after the car AND the whole house and acts accordingly to that with heating water and/or just the floors of the house.
I am thinking about tripping into the RS484 of this device in the future, but for now it just works this way.
 
Since yesterday, I am a proud owner of the modification from this thread. I run into some problems but could solve most of them myself.

1. The suggested USB RS485 component comes with 6 wires cable but the colours to use are not black/red but orange (D+) and yellow (D-). Someone might mix that up as me when not paying attention. Maybe worth to update the manual for that.

2. I own a SolarEdge solar system and managed to write the part for the green-energy-tracking myself (API access over SolarEdge Monitoring Platform) - I will share in another post. However, I noticed that that part is not paying attention to the 3-phase charging I am using. When charging with 3 phases, I assume, I have to calculate it as...

maxAmpsToDivideAmongSlaves = (solarW / 240 / 3) + greenEnergyAmpsOffset

3. As I use 3 phase charging with 16A each line, I have to use wiringMaxAmpsAllTWCs=16 or do I have to take that * 3 ?

Anyway, thanks a lot for providing this!
 
  • Like
Reactions: UlrA
check_green_energy for SolarEdge solar systems:
  1. Login to your account on https://monitoring.solaredge.com/
  2. Click Admin -> Site Access -> API Access and generate API or copy that if you have one already
  3. Edit TWCManager.py and make the following changes...
lines to changed in check_green_energy() function...​

search for greenEnergyData = run_process(... and replace with:
greenEnergyData = run_process('curl -s -m 60 "https://monitoringapi.solaredge.com/site/<YOUR_SITE_ID>/overview?api_key=<YOUR_API_KEY>')

search for m = re.search(b'... and replace with:

m = re.search(b'.*\"power\"\:[0-9\,\.]*)\}.*', greenEnergyData, re.MULTILINE)
 
  • Like
Reactions: UlrA
However, I noticed that that part is not paying attention to the 3-phase charging I am using. When charging with 3 phases, I assume, I have to calculate it as...

maxAmpsToDivideAmongSlaves = (solarW / 240 / 3) + greenEnergyAmpsOffset

3. As I use 3 phase charging with 16A each line, I have to use wiringMaxAmpsAllTWCs=16 or do I have to take that * 3 ?

Yes thats correct. You will need to multiply them by 3. The minimum charge rate would be 6A * 230V * 3 = 4.1kW.
Since my solar roof does not cope this most of the time, I just switched off 2 of the 3 breakers for the TWC in my junction box in the house. This way I can charge from 6A * 230V = 1380W, to 25A * 230V = 5750W on a single phase and I am quite happy with that.

For what I read on this thread, I am not the only one who does it this way.
 
  • Informative
Reactions: laalves911
Thanks @Nietschy :)

Would have been great is the protocol would also manage this and decide how many phases it uses. As far as I remember, at the end of the 100% capacity, either the car itself or the TWC decides anyway to only use 1 phase of the 3 as it can not load that fast anyway.
 
@CDragon Im not sure if its OK or even wanted to post suggestions here, but I try...

  1. Save history of all charges made (date/time + greenEnergy + "how much charged"). That way we would always know how much we charged at home today/this month/year... I think this would be a great feature to track how much the car charging took of the whole energy bill.
  2. Being able to set the amount of phases to charge with by protocol if that is even possible.

I have little to no experiences in phyton coding which makes it hard for me adding this myself.
 
in case anyone cares, I fixed my missing inverter host by night and json key errors when it is just dark outside with some try/except statements.

it is horrendous, but working as it seems.

add this to the imports on top:
Code:
import requests
from requests.exceptions import ConnectionError

and this at the bottom where the solar generation is measured:

Code:
                    # Decode into an object
                    try:
                        r = requests.get('http://192.168.0.251/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceID=1&DataCollection=CommonInverterData' ,timeout=2)
                        if(r):
                            solarPowerObject = r.json()
                        try:
                            solarWh = solarPowerObject['Body']['Data']['PAC']['Value']
                        except KeyError:
                            solarWh = 0
                            print("PAC key not found, inverter may have low input voltage")
                    except ConnectionError:
                        solarWh = 0
                        print("inverter host not found, inverter may be offline")

                    # Real time AC being fed into the mains
                    if(solarWh):

                        # Watts = Volts * Amps
                        # Car charges at 240 volts in North America so we figure
                        # out how many amps * 240 = solarWh and limit the car to
                        # that many amps.
                        maxAmpsToDivideAmongSlaves = (solarWh / 240) + \
                                                      greenEnergyAmpsOffset
  
                        if(debugLevel >= 1):
                            print("%s: Solar generating %dWh so limit car charging to:\n" \
                                 "          %.2fA + %.2fA = %.2fA." % \
                                 (time_now(), solarWh, (solarWh / 240),
                                 greenEnergyAmpsOffset, maxAmpsToDivideAmongSlaves))

                timeLastGreenEnergyCheck = now
 
  • Like
Reactions: laalves911
All - can someone point me to which 'data cable' you have used to load balance the two Wall Connectors? I just added a second Tesla and have a second wall connector coming our way and my electrician told me to order the data cable... I need about 30 ft between the 2 wall connectors.

Thank you!
 
Would be cool if the TWCManager could be purchased as a completed device; anyone out there with time on their hands want to make me one so I can just get it installed? I'm fine on the linux/networking side; just not on the physical construction of it :)

Same here! I started looking through the PDF and once I got to the part about soldering and creating the cables, I quickly gave up. If only Tesla would just have an API to change the amps on the car, that would make is so much easier.
 
Hi everyone,

I thought I'd share my mods to TWCManager for Powerwall users.

Firstly, many thanks to CDragon for this.

Basically I wanted to use Excess solar to charge the car but only when the Powerwall couldn't store it. As the Powerwall can charge at lower amps than the car, if you think of the curve of solar output through the day, we want to hold back some Powerwall chargin until the latter part of the day when it would not be possible to charge the car (as below 6A).

So this mod uses the Powerwall Gateway to read the solar production and grid export power. The grid export is added to any current TWC car charging power to give the new value for the available green energy. So if we start importing energy from the grid the TWC amps will reduce, and if we start exporting energy the amps will increase. I fixed a couple of problems the code was giving me that was preventing with the car charging handling - these are all commented. CDragon may find these useful for the base code.

If you look at the code, there are settings for your Powerwall Gateway IP address and the minimum Powerwall state of charge before we consider charging the car.

There is an additional module used by this for the API comms - you need to run this on the pi:

sudo python3 -m pip install requests

Here in the UK the sun is getting a bit scarce for decent testing. You can turn your Powerwall off using the switch on the side if you want to see how it tracks the grid exporting before you have a charged Powerwall - the Gateway will still work and provide TWCManager with the solar and export stats it needs.

Hope this is of use to others. Let me know if you like it / have any issues.
 

Attachments

  • TWCManager.zip
    46.7 KB · Views: 95