# Reverse engineering the Lexus GS450h Inverter/Converter



## xp677 (Oct 15, 2017)

Hi all,

My first post here after spending a while reading the various threads on this forum. And it's going to be a long one!

I've owned a few GS450h cars over the years and recently ended up with a FD RX7 shell. I'm looking at turning it into an EV using GS450h hardware, due to the low cost, availability, size/form factor, and power output, which all seem to suit my needs.

I purchased a used GS450h motor drive unit ("transmission" / "gearbox") and an inverter at the end of last year and have only just had a chance to look at it.

Having read through the forum thread from bigmouse here, I knew it was possible to communicate with this unit. It seems that there isn't much information about them in the public domain, but the below post form hilux.2sv is a great starting point:



hilux.2sv said:


> We now have some more information after studying the wiring diagrams and DTC repair documents.
> 
> Signals from HVC-ECU to INVERTER/CONVERTER:
> Pin 23/22 HTM+/- --> MOSI, differential using CAN transceiver, about 60...100 bytes (1.6ms), 120Ohm termination on both ends
> ...


This is useful info, when compared to the connector on the inverter unit (all pictures are click-for-big!):





I pulled the unit apart to inspect the board. I drew a brief schematic for the relevant parts:





The board appears to use a proprietary transceiver, a DENSO SE617. There is no datasheet for this unit. I guessed the pin names from examination of the board.

A pair of 62R resistors with a capacitor to ground, and a dual choke (common mode, I guess, there is no info on the product code) provides the only protection and noise suppression.

The microcontroller used is a NED 76F0080GC. Again, no datasheet or specs for this.

The 5V rail for the transceivers is shared with the microcontroller, the resolver-to-digital converters, and some other parts, here's a brief look at it, I didn't examine too far, I guess it's a buck converter from the 12v input. Not much in the way of noise suppression?





I'll likely piggyback off of this 5V supply for my own controller.




So, the control signals....

It appears to be SPI over LVDS. Basically using a differential signal to extend the range/reliability of SPI in noisy environments. As hilux.2sv said above, the Toyota names for the pins are likely alternate names for MOSI, MISO, CLK.


HTM = High-voltage ecu To Motor-generator ecu - since the HV ECU (the Hybrid ECU) in the car is the master, this is MOSI. This is the signal which we will need to replicate to control the inverter.

MTH = Motor-generator ecu To High-voltage ecu - This is MISO. From this we get status updates back from the inverter.

CLK = This is the SPI clock. The Lexus system uses a 500KHz clock. The data packets from MOSI and MISO don't generally exceed 100 bytes, and I've managed to get stable packets without overlap from as low as 250KHz. Data from MTH will output in time with this clock (on a rising edge)

REQ = this is the status request line from the inverter. For the Lexus, this is a 1ms high pulse followed by a 3ms space, basically a 250Hz square wave at 25% duty cycle. In reality, the inverter outputs a packet of around 100 bytes whenever it detects the leading edge of a pulse, so a CS or SS line can be used to trigger this. The pulse can be helf high for the duration of the packet, or as long as you like. One pulse = one packet.

When talking about high and low here, I am referring to the differential signal. Since these are normally inverting, in reality the microcontroller likely receives a low pulse to trigger a packet output.



I set up the inverter on the bench, and fed it the following:


12V to both 12V pins
0V to both 0V pins
ILKI and ILKO both grounded (not sure this matters yet)
HSDN to 12V (not sure this matters yet)
Shorting wire in the interlock connector for the AC compressor (not sure this matters yet)
250KHz square wave to CLK+ and -
250Hz square wave at 25% duty cycle to REQ+ and -.
Logic analyser to CLK, REQ and MTH. All 3 of the - line are tied together by this, they don't seem to mind (they really do mind if you do this on the car, however!)

A typical packet looks like below:



The packet follows the SPI convention, with a start bit, 8 data bits, and a stop bit, as below:



The packet is 100 bytes wide, with many bytes being 0. A typical packet looks like below:


```
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,11111111,11111111,00000000,00000000,00100100,01100000,00000000,00000000,10011000,00000000,00000000,00000000,00000001,11001000,01000000,00000000,00000000,00000000,00000000,10000000,00000000,00000100,00000000,00000001,10000011,10111111,11111111,11111111,11111111,01101011,01010000,00000000,00000000,00011000,10011000,00000000,00000000,00000100,01110010,11110001,00001000,00000000,00000000,00000000,00000001,01001000,01000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,10000000,10100000,00000000,10000000,00000000,00011000,00000000,00011000,00000000,00000000,11010111,10000000,00000000,00100000,11111111,00000000,01110011,00011011,10110000
```

After sampling a few hundred of these, it seems that the inverter output (for an inverter on the bench with no motor connected) is below:




I ran the same test with the inverter connected to the car. I am only able to connect to one of the 4 lines at a time, id I try multiple, the - lines ground through the logic analyser and causes the car to generate a DTC and disable the hybrid system. I tried using diodes on the grounds to allow for some separation, this worked, but the data I received was corrupt.

I'll attach an Excel file showing a few hundred packets of the inverter both on the bench and on the car.

I also did the same to the HTM line, to see what the hybrid ECU sends the inverter on startup. As expected, the first few (hundred!) packets are unique, and then it seems to settle down. Again, it's in the spreadsheet.

Next up is to request torque from the motors (shift into R or D and move the car) and see how the states change.

I'm also starting to get parts together to talk to this unit with a microcontroller, rather than a signal generator and logic analyser. I purchase a TI SN65LVDT41PW LVDS Transceiver which contains 4x transmitters and 1x receiver. I have a spare Teensy 3.2 which I plan to use to replicate the CLK and REQ lines, and hopefully this can read packets back from the inverter and log changes in a more elegant way (it takes about an hour to convert the bit-stream from the analyser to a format which can be read by Excel!)

Of course, any knowledge on this subject would be greatly appreciated! I'm somewhat of a novice at programming, and have barely touched SPI, hopefully I'll be able to build something useable to control this unit!

Thanks


----------



## xp677 (Oct 15, 2017)

I've spent the day looking into communication to this unit. From what I've seen/read online about SPI, it seems that SPI does not use start and stop bits. Also, SPI only transmits clock pulses as data is being requested. This unit accepts a "constant" clock, and outputs a 100 x 10-bit packet each time the REQ line is triggered. The clock runs constantly throughout. I also noticed that if the clock stops momentarily, the data keeps flowing without a clock pulse.

Because of this, I cannot read this as a SPI signal. My attempts to use a microcontroller set to transmit/receive SPI result in the microcontroller outputting 8 clock pulses, then a brief pause, then another 8 clock pulses, etc. This results in data being received, but the data is corrupt - the microcontroller just receives what was being sent at the time it attempted to read from the inverter.

Another interesting thing is that the inverter board waits for 39 clock pulses after receiving a REQ pulse, and starts to output on the 40th pulse.

I'm now looking at how to receive (and later transmit!) this bit stream. I can generate the clock pulses and REQ pulses easily, but to receive data synced to the clock pulses? 'm not sure how. I'm currently using a Teensy 3.2, the digital input pins are too "slow" to receive this data. Since the clock is at 500KHz, I'm currently looking to check for a 0 or 1 at my "data in" pin every 2us. The inverter sends data on a rising edge of the clock pulse.

All I really need to do is be able to grab this entire packet in a 1000-long array or similar, I can likely remove the start and stop bits and bit-shift the remainder into an array of integer variables afterwards.

Of course, I also need to be able to do the same in reverse, to talk to this unit.

Attached is the following images (click for big)

1. An overview of the data received.
2. A close-up of the start of each packet
3. A close-up of the middle of each packet, where things are more interesting than "00000000"

Note that since this is a differential signal, it is likely inverted, so the 1 11111111 0 you see in the first packet is actually "0 00000000 1". I am not using a differential transceiver right now, although I do have one on the way.


----------



## MattsAwesomeStuff (Aug 10, 2017)

I know Damien has dabbles with Lexus inverters, not sure if it's this one.

He doesn't post much here anymore, but there's a Lexus sub-forum on the OpenInverter forums.

https://openinverter.org/forum/viewforum.php?f=14

A bunch of the EE guys moved over there a year ago when our forum here was crippled for a few months.


----------



## xp677 (Oct 15, 2017)

That's great, thanks!


----------



## hilux.2sv (Nov 28, 2017)

Hi,
that's great that someone else is working on the GS450h/LS600h system. With Bigmouse his help we got the transmission / inverter running with our own control module.
It's not SPI, it's a synchronous serial communication. You have to use a micro-controller with USART for that. So the Teensy doesn't work, but a Arduino Due does.
CLK is continues 500kHz regardless of transmission. Transmission and reception is not aligned. transmission starts on falling edge of REQ and reception some time after rising edge of REQ. It doesn't matter how narrow or long the REQ pulse is.
You can use basically any 5V CAN transceiver for that (4 of course, one for each signal). Because most transceivers have a dominant time out detection after 1ms, you REQ pulse can not be longer than this 1ms. That's like the OEM Lexus/Toyota timing. You can make it much shorter, if you want.
I used an ATxmega128A1U with external SDRAM for testing and capturing the HVC-Bus datastream. The USARTs with connected DMA channels work really great for the HVC-Bus.
Transmission data are 80 bytes, reception 100 as far as I remember for the GS450h/LS600h. The last 2 bytes are the checksum over all data bytes.
A big problem is enabling and controlling the internal HV DC/DC converter. Up to now we didn't get this working. But would be helpful for supply 288V to the 12V DC/DC converter, AC compressor and heater. A lower voltage battery charger could be used for charging the HV battery pack if this is working.


----------



## rmay635703 (Oct 23, 2008)

https://ecomodder.com/forum/showthread.php/hot-rodding-toyota-mgr-29878.html

https://endless-sphere.com/forums/viewtopic.php?t=78540

I’ve seen threads on the Toyota mgr before, only one culminated in an mgr powered go cart


----------



## xp677 (Oct 15, 2017)

hilux.2sv said:


> Hi,
> that's great that someone else is working on the GS450h/LS600h system. With Bigmouse his help we got the transmission / inverter running with our own control module.
> It's not SPI, it's a synchronous serial communication. You have to use a micro-controller with USART for that. So the Teensy doesn't work, but a Arduino Due does.
> CLK is continues 500kHz regardless of transmission. Transmission and reception is not aligned. transmission starts on falling edge of REQ and reception some time after rising edge of REQ. It doesn't matter how narrow or long the REQ pulse is.
> ...


This is great info, many thanks!

I've been in touch with the people at PJRC (Teensy manufacturers) and it seems that indeed the Teensy can't handle USART. Shame as I planned to mount it inside the inverter casing next to the inverter PCB.

I've got a Due in a box somewhere, if I can find it then I'll start again with that!

Thanks for the tips on the communication protocol. It all aligns with the measurements I've taken.

I've been reading up on USART implementation on various Arduino units. I actually came to the same conclusion that I'd need a Mega or Due for this, as I need more than one UART (I need to talk CAN bus as well as to the serial monitor as well!). The Due is actually a good fit, as it uses 3.3v logic, which pairs well with the 3.3v transceivers in the inverter.

Good to hear that regular CAN transceivers work, I imagine they would. I've gone ahead and ordered a SN65LVDT41PW from TI, this unit has 4 transmitters and one receiver, which I think will make for a simplified PCB.

Good to hear that the checksum is just a sum of the other bytes in the packet! Do you know the format of the checksum? i.e byte 99 or byte 100 the most significant byte?

Information on configuring the Arduino units for USART seems thin on the ground. I've found one forum post that talks about disabling a clock pin and handing control of it over to the UART to allow it to generate the synchronous clock. If this how you managed it as well? Are you able to help with the code for this? It doesn't seem very familiar!

I haven't looked at the converter (yet). To be honest it's out of the scope of this project, for now at least. I'm not sure if you can set the voltage through the USART packets, I imagine not, I imagine it is set at 650v <> 288v on the inverter PCB. I imagine that the signals within the unit may need to be intercepted.

In fact, do you have a list of which bytes of the packet are for what? I noticed that there are some which change depending on inverter state, etc, but some of them I'm not sure about. Are they temperature readouts? Resolver readouts, etc?

I have a Toyota scan tool, it gives me a great deal of information from the inverter including heatsink temperatures, resolver angles and rpm, motor torques, etc. Of course, with all the data changing all at once, it's a matter of educated guesswork to reverse engineer!

Of course, any info would be greatly appreciated.


----------



## xp677 (Oct 15, 2017)

rmay635703 said:


> https://ecomodder.com/forum/showthread.php/hot-rodding-toyota-mgr-29878.html
> 
> https://endless-sphere.com/forums/viewtopic.php?t=78540
> 
> I’ve seen threads on the Toyota mgr before, only one culminated in an mgr powered go cart


This is very cool. It uses the rear motor from the RX400h, which I believe is powered from the same inverter as the motor-generator unit (I believe the RX inverters have a third motor output).

This would be great to drop in a smaller, lower powered car such as a Beetle, Mini, etc. Not sure where the batteries would go, though


----------



## hilux.2sv (Nov 28, 2017)

synchronous full duplex USART communication
one start bit - 8 data bits, LSB first - one stop bit 

checksum = byte80*256 + byte79 (most significant byte: 80, should be little endian)
checksum calculation = byte1+byte2+...+byte77+byte78


Use a 5V CAN transceivers (like in your schematic of the inverter) which have 3.3V IO levels. For me the Microchip MCP2562FD-E/SN (separate IO supply pin) works great. It's an CAN-FD transceiver, but that doesn't matter.


Arduino doesn't support synchronous USART configuration, but it's easy to enable this (for DUE):


#define REQPIN 9 

void setup_hvcbus(void) 
{ 
// set REQ pin to output high as default 
digitalWrite(REQPIN, HIGH); 
pinMode(REQPIN, OUTPUT); 

// Synchronous Serial on AT91SAM3X8E (USART0 TXD pin TXD0 --> Serial1 "ARDUINO DUE TX1/D18") 
// Synchronous Serial on AT91SAM3X8E (USART0 RXD pin RXD0 --> Serial1 "ARDUINO DUE RX1/D19") 
Serial1.begin(250000); // 500kHz, set to 250000 due to different baudrate calculation for synchronous mode, Serial1.begin() uses asynchronous baudrate calculation


// Synchronous Serial on AT91SAM3X8E (USART0 CLK pin SCK0 --> Serial1 "ARDUINO DUE SDA1/D70") 
PIOA->PIO_ABSR |= 1<<17; // set peripheral B (--> USART0 SCK0) 
PIOA->PIO_PDR |= 1<<17; // let peripheral control pin (--> USART0 SCK0) 
USART0->US_MR |= 1<<4 | 1<<8 | 1<<18; // set CLK/8, synchronous mode, enable SCK clock output 
}


----------



## hilux.2sv (Nov 28, 2017)

Attention:
uC output levels are inverted for the CAN transceivers, like for any UART output

high level --> 0, idle
low level --> 1

REQ triggers:
transistion from high level to low level --> trigger MTH transmission (uC RX)
transistion from low level to High level --> trigger HTM transmission (uC TX)

maximum time of uC REQ low level (H->L to L->H) < 1ms (CAN transceiver dominant time-out detection, depents on CAN transceiver, look in the datasheet)

OEM repetition rate is 4ms. Not sure if the inverter cares about it. Don't think so.


----------



## xp677 (Oct 15, 2017)

This is all very helpful info. I couldn't find my Due so I have another in the mail. I found a strip of NXP TJA1050s and have hooked them up to the board and everything seems to work fine. I'll order a load of MCP2562-E's anyway, the separate supply pin would be useful as I assume the inverter uses 5v for the differential signals?

The inverter doesn't care about the gap between REQ pulses, if you make it short enough it will overlap into the previous transmission without a care. It's more down to how often you want to receive a packet.

Thank you for the initialization info, I don't have the Due yet but I guess the code will look something like:


```
#include <Metro.h>

#define PIN_REQ 6

Metro request_timer=Metro(4);

void setup() {

  pinMode(PIN_REQ, OUTPUT);
  digitalWrite(PIN_REQ, 1);
  
  Serial.begin(115200);
  Serial1.begin(250000);

  PIOA->PIO_ABSR |= 1<<17;
  PIOA->PIO_PDR |= 1<<17;
  USART0->US_MR |= 1<<4 | 1<<8 | 1<<18;
}

void loop() {

  byte mth_byte=0;
  byte mth_data[100]={0};
  
  if(request_timer.check())
  {
    digitalWrite(PIN_REQ,0);
    while(Serial1.available()) mth_data[mth_byte]=Serial1.read();
    digitalWrite(PIN_REQ,1);
  }

  Serial.println("\t0\t1\t2\t3\t4\t5\t6\t7\t8\t9");
  Serial.println("   ------------------------------------------------------------------------------");  
  for (int j=0;j<10;j++){
    Serial.print(j*10);if(j==0)Serial.print("0");Serial.print(" |\t");
    for (int k=0;k<10;k++){Serial.print(mth_data[j*10+k]);Serial.print("\t");}
    Serial.print("\n");
  }
}
```
No idea if this will work, hopefully it will do. I will also use Serial1 as I don't want to dive into the setup for the USART on this unit.

This code relies on the whole data packet being read before the timeout detection of the CAN transceiver. Maybe I should use another timer for the request pulse?

I spent the day pulling data from the HTM line while driving. Not easy when you have a laptop wired into the engine bay! I've found a few bytes which seem to relate to pedal position, I guess those are the MG1 and MG2 torque requests. I'm hoping that I can alter these (and the checksum) and leave everything else as it is There are quite a number of bytes which change "randomly", hopefully I can find a good resting value for those and leave them alone.


----------



## hilux.2sv (Nov 28, 2017)

The TJA1050 is fine because it accepts 3.3V signals. But use a resistor between the output of the TJA1050 and the DUE input, e.g. 1k.

Your initialization code looks good. I used the Serial1.available(), Serial1.read() and Serial1.write() functions, too.

But I think your MTH read function will not work as you expected. Try it like this:


```
#include <Metro.h>

#define PIN_REQ 6
Metro request_timer=Metro(4);    // 4ms

void setup()
{
     pinMode(PIN_REQ, OUTPUT);
     digitalWrite(PIN_REQ, 1);

     Serial.begin(115200);
     Serial1.begin(250000);

     PIOA->PIO_ABSR |= 1<<17;
     PIOA->PIO_PDR |= 1<<17;
     USART0->US_MR |= 1<<4 | 1<<8 | 1<<18;
}

void loop()
{
     byte mth_byte=0;
     byte mth_data[100]={0};

     unsigned long timestamp;
     unsigned short timestamp_diff;

     if(request_timer.check())
     {
         digitalWrite(PIN_REQ,0);
         timestamp=micros();
         mth_byte=0;

         do
         {
             timestamp_diff = micros() - timestamp;
             if(timestamp_diff >= 1000)               // 1ms
             {
                 digitalWrite(PIN_REQ,1);
             }
             if(Serial1.available())
             {
                 mth_data[mth_byte]=Serial1.read();   // default Serial Buffer Size is only 64 bytes, not enought to read the whole packet at once
                 mth_byte++;
             }
         }
         while((mth_byte<100)&&(timestamp_diff<3000))  // break after 3ms or if mth buffer full
     }


    // your code for transmitting data ...


}
```


----------



## ncjeeper (Dec 11, 2019)

Great work! I wonder would it be possible to use dual or quad rs485 drivers for the inverter interface. Was there a particular reason for the Sam Microcontroller?


----------



## hilux.2sv (Nov 28, 2017)

The micro-controller must have a synchronous serial interface (USART) with continuous clock output. Not all devices support synchronous serial communication and some (like STM32F...) switch the clock off when not transmitting.
The levels for RS485 and CAN are different. RS485 usually uses symmetric signaling while CAN doesn't. But you can archive a similar behavior with the RS485 transceivers by using the transmitter enable/disable pin. However signal levels are still different.
The Lexus inverter uses 5V CAN transceivers, so you should do too. Typical time-out detection of the CAN transceivers doesn't matter. Take care of the transceiver logic level when using a 3.3V controller. Choose a CAN transceiver which accepts the 3.3V levels (e.g. TJA1050) or has a dual supply (e.g. MCP2562FD).


----------



## MattsAwesomeStuff (Aug 10, 2017)

This inverter and motor/gearbox is Damien's main project right now. Just the other day he was driving around in it for the first time.

I know XP677 is over there, but, might be worth the rest of your's time to check out what he's been up to.

https://www.youtube.com/watch?v=_V-V2q4AW4M


----------



## xp677 (Oct 15, 2017)

Hi everyone,

Yes, I did manage to figure all of this out, my progress is on the OpenInverter forum:

https://openinverter.org/forum/viewtopic.php?f=14&t=205

I shared my code and schematics with Damien, which he has used for further testing in his project, and he has produced a controller board for this inverter/motor combo. His version of my schematics (which are more useful, as mine were specific to my project), and a modified version of my code is available on his Github.

Anyone wanting to use this system in their own car can either buy a complete controller from Damien, buy a bare board and populate it themselves, or build their own custom board based on the schematics. I believe that all the necessary information is there.

There is still some development to do, I know Damien was looking at control of the two-speed transmission inside these units, and I am looking into the HV converter which lives inside the inverter/converter unit.

One difference between CAN and RS485, is that RS485 transmitter actively drive the lines to the recessive state, while CAN only drives to the dominant state. Since the inverter uses CAN transceivers at its end, I'd suggest the same for any homemade controller. I see no advantage of using RS485 for this.

As mentioned, the uC must have a USART available. There are many others which have this, including the ATMEGA2560, STM32F4 or F7, etc. The Due was a good all-round board for me, it has all the features I need (in fact, I ended up almost filling mine completely!) and performance needed for this project.

I used a MCP2562 for its 5V transmission, with a VIO of 3.3V to protect the microcontroller. I don't remember what Damien used, but it seems to work as well!


----------



## rmay635703 (Oct 23, 2008)

Just curious if anyone has gotten ahold of a Prius AWD rear transaxle and controller yet?

I have been looking at wreckers but the car is too new for me to locate yet in the hybrid desert of Wisconsin.

The Prii AWD is very similar tech as the gs450 but small enough to fit a certain 900lb car I would like to convert.

Otherwise, great stuff, love the thread, carry on.


----------



## brian_ (Feb 7, 2017)

rmay635703 said:


> Just curious if anyone has gotten ahold of a Prius AWD rear transaxle and controller yet?
> ...
> The Prii AWD is very similar tech as the gs450 but small enough to fit a certain 900lb car I would like to convert.


The Prius AWD is very different from the LS AWD, and I didn't know the GS hybrid was even available as an AWD; LS and GS are both normally RWD. The LS uses a longitudinal engine and transmission with a traditional AWD configuration using a transfer case behind the transmission; the GS uses the same transmission and so would use the same AWD system. In contrast, the transverse-engine Toyota (including Lexus) hybrids only drive the front wheels with the hybrid transaxle, and drive the rear wheels only electrically, using a separate transverse motor and single-speed transaxle for the rear axle.

The Prius "AWD-e" rear drive unit is very low power - much smaller and less powerful than the otherwise generally similar "AWD-i" units in the RAV4, Highlander, and Lexus RX hybrids. At least one article listed the Prius AWD-e unit as 7 horsepower. As the only motor, it might suit a go kart, but even a 900 pound car sounds marginal.


----------



## xp677 (Oct 15, 2017)

You'd need to know the contents of the HTM data stream to communicate with this unit. I suppose you could hire a car for a weekend to achieve this.


----------



## rmay635703 (Oct 23, 2008)

xp677 said:


> You'd need to know the contents of the HTM data stream to communicate with this unit. I suppose you could hire a car for a weekend to achieve this.


I haven’t located an AWD-e In Wisconsin of either persuasion including the original Highlander mgr which is the big brother to the AWD-e

My inspiration below
https://ecomodder.com/forum/showthread.php/hot-rodding-toyota-mgr-29878.html

Which is the RX400h which is identical in concept but larger and still slosh cooled.

From what I gather these are cooling limited, not power limited.


----------

