Re: Outlander rear motor and inverter
Posted: Tue Aug 13, 2024 10:16 am
Looks like I might be investing in a long steel bar to do some experiments 
openinverter Community
https://openinverter.org:443/forum/
Hm... i am thinking of connecting to my other inverter and sensing unknown wires for transient signal when putting it in short. Of course i would be doing this with 48Vdc power supply...
Hi , Just want to ask about your RSDN post, does it mean you apply +12V to RSDN if you want to shutdown? and cutoff/dont connect RSDN if yiu want to enable/start the motor? thanksaot93 wrote: ↑Thu May 20, 2021 11:00 pm For me it was bad connection between inverter and motor ( Resolver)
I metered every pin on the inverter to check against the values listed in the service manual (see attached)
Note that RSDN should be pulled low.
Once that was sorted it all worked very easy, no particular sequence.
2021-05-20 23_58_10-[W_M]OUTLANDER PHEV (GG#).png
Connect 12V power to IGCT and 0V to GND.OutlanderTry wrote: ↑Sat Jan 10, 2026 6:05 pm .....
Connected to the grey inverter socket as in ewiki.
GND, CAN H L, IGCT, and RSDN to GND.
....
The second very important question is, is it possible to get CAN data just by connecting these 5 pins?
I swapped low and high, but I don't think it's related to high voltage.rstevens81 wrote: ↑Sun Jan 11, 2026 4:45 pm Try switching can low/high around there's some contradiction on the wiki when you look at both diagrams
Thanks 4 your speedy answerearber333 wrote: ↑Sun Jan 11, 2026 5:07 pm Connect 12V power to IGCT and 0V to GND.
RSDN should NOT see 12V when in normal operation!
You should use a propper power supply, 5A at least. I suspect inverter can go into brownout if not enough power
When you connect to CAN H/L you need to terminate connection on at least one end if not on both ends. Transciever inside inverter is not terminated.
How my car is connected to inverter
1. I provide 12 ignition through the key to IGCT pin and 0V to GND
At this time VCU is online and in ready mode. This means it is actively sending 0x285 telegram at 30ms in drive mode
There is NO CAN from inverter at this time!
2. When i provide START pulse precharge relay raises voltage and then DC+ contactor goves HV. You should see active inverter CAN reports then
I use charger CAN signal to verify correct voltage just a precaution with precharge
3. When i put car in drive mode all inverter messages are flying on the CAN bus
To summarize;
1. You need to connect 12V to IGCT
2. You need to connect HV to inverter (by precharge)
3. Inverter CAN reports are active when HV is online.
4. Only then you can read and command inverter with your VCU
EDIT: I went out in the -10°C cold to demonstrate this via screen grab... it says -6 but i assure you it is lower than that...
0x289 is one of the inverter CAN reports
0x285 is BMS heartbeat that all Mitsu components require for operation
I sugget you make all connections with your motor, resolver and HV first in your workshop as you would in the car. Then start the "car".
Hold on.arber333 wrote: ↑Sun Jan 11, 2026 5:07 pm Connect 12V power to IGCT and 0V to GND.
RSDN should NOT see 12V when in normal operation!
You should use a propper power supply, 5A at least. I suspect inverter can go into brownout if not enough power
When you connect to CAN H/L you need to terminate connection on at least one end if not on both ends. Transciever inside inverter is not terminated.
How my car is connected to inverter
1. I provide 12 ignition through the key to IGCT pin and 0V to GND
At this time VCU is online and in ready mode. This means it is actively sending 0x285 telegram at 30ms in drive mode
There is NO CAN from inverter at this time!
2. When i provide START pulse precharge relay raises voltage and then DC+ contactor goves HV. You should see active inverter CAN reports then
I use charger CAN signal to verify correct voltage just a precaution with precharge
3. When i put car in drive mode all inverter messages are flying on the CAN bus
To summarize;
1. You need to connect 12V to IGCT
2. You need to connect HV to inverter (by precharge)
3. Inverter CAN reports are active when HV is online.
4. Only then you can read and command inverter with your VCU
EDIT: I went out in the -10°C cold to demonstrate this via screen grab... it says -6 but i assure you it is lower than that...
0x289 is one of the inverter CAN reports
0x285 is BMS heartbeat that all Mitsu components require for operation
I sugget you make all connections with your motor, resolver and HV first in your workshop as you would in the car. Then start the "car".
Hm... strangeOutlanderTry wrote: ↑Sun Jan 11, 2026 6:51 pm .....
I did not connect any HV
I am not sending any data
BUT
I am now receiving data
What is going on here?
I'm also using more power than in the very first test.
Can anyone confirm that the device draws 450mA in standby mode and not 200mA?
....
I love the new 2026 calendarOutlanderTry wrote: ↑Sun Jan 11, 2026 7:20 pm Now the world has loosing the Game
in the Future we drive the Outlander Engine with ESP32 Web Interface
Don't let the mouse slip out of your hand when accelerating.
...
Yes its very strangearber333 wrote: ↑Sun Jan 11, 2026 7:22 pm Hm... strange
I connect car saux battery with ignition so i provide inverter, OBC and heater with 12V so it is more than 1A.
But even if i provide 12V and 0x285 telegram i only get response from inverter is when i give it HV via precharge process.
To verify this i use ECAN USB interface
https://www.ebay.com/itm/315582425941
or
https://www.aliexpress.com/item/1005010 ... in_prod%3A
########################arber333 wrote: ↑Sun Jan 11, 2026 7:28 pm I love the new 2026 calendar![]()
I already have my ESP32 VCU interface ready.
Dual CAN
3x protected outputs
5x ULN2003 outputs
5x digital inputs
2x analog inputs via the ADS1115 i2C interface
I only need to provide the code... i am only a ME so very slow in coding...![]()
I updated files in my ESP32 repositoryOutlanderTry wrote: ↑Sun Jan 11, 2026 7:40 pm ########################
Very IMportant
I love the new 2026 calendar
where can i buy that ?
########################
can you sendme ESP32 VCU interface
as pdf and schematic ?
Yes i can draw max 200A from battery with OEM setupRomale wrote: ↑Mon Jan 12, 2026 9:00 am O.I. management greatly expands the scope of available use. with it, I got 350 amperes of battery current with this small inverter, it seems to me that controlling the can bus will not give such a result. I also get a higher speed than in the Mitsubishi itself initially.
Hello, thank you.arber333 wrote: ↑Mon Jan 12, 2026 7:32 am I updated files in my ESP32 repository
https://github.com/arber333/ESP32-VCU/tree/main
Search for the latest version 2.4 and 2.5
2.4 is meant for application with 2x CAN ports controling chademo fast charging or receiving BMS updates
2.5 is simpler, only single CAN but it can drive more PWM outputs
I put schematic on paper somewhere and i would have to redraw it. I will add schematic at a later time. For now let the pcb file guide you.
It was drawn with Designspark PCB.
There are also pinouts for VCU that i envisioned. You can certainly adapt them to your use...
If you want a single blank PCB board for testing i can quickly send you one...
Code: Select all
#include <Arduino.h>
#include "driver/twai.h"
// Pins für ESP32 & SN65HVD230
#define TX_PIN GPIO_NUM_16
#define RX_PIN GPIO_NUM_17
// Gemeinsam genutzte Variablen
volatile uint16_t TorqueVal = 10000;
volatile bool motorRunning = false;
volatile unsigned long startTime = 0;
const uint16_t TorqueNeutral = 10000;
//#############################################################
// SETTINGS
int TorqMaxRange = 33;
const unsigned long RunTimeMax_ms = 4000;
// SETTINGS
//#############################################################
byte motorFunction = 0x03;
int lastSecondsPrint = -1;
volatile int16_t currentRPM = 0;
float currentVoltage = 0;
volatile int16_t maxRPM = 0;
volatile float currentPhase1 = 0;
volatile float currentPhase2 = 0;
volatile float maxPhase1 = 0;
volatile float maxPhase2 = 0;
// TWAI Konfiguration
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_PIN, RX_PIN, TWAI_MODE_NORMAL);
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
// Task-Handles
TaskHandle_t TaskCanSendHandle;
TaskHandle_t TaskCanRecvHandle;
TaskHandle_t TaskSerialHandle;
void sendCAN(uint32_t id, uint8_t len, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
twai_message_t msg;
msg.identifier = id;
msg.extd = 0;
msg.rtr = 0;
msg.data_length_code = len;
msg.data[0] = d0; msg.data[1] = d1; msg.data[2] = d2; msg.data[3] = d3;
msg.data[4] = d4; msg.data[5] = d5; msg.data[6] = d6; msg.data[7] = d7;
twai_transmit(&msg, pdMS_TO_TICKS(10));
}
// --- TASK 1: CAN SENDEN & LOGGING (CORE 1) ---
void TaskCanSendLoop(void *pvParameters)
{
unsigned long lastSendTime = 0;
for (;;)
{
unsigned long currentTime = millis();
unsigned long elapsedTime = currentTime - startTime;
if (motorRunning)
{
if (elapsedTime >= RunTimeMax_ms)
{
motorRunning = false;
TorqueVal = TorqueNeutral;
lastSecondsPrint = -1;
Serial.print("Core 1: Motor Stopp.");
Serial.print(" | Maximal RPM: ");
Serial.print(maxRPM);
Serial.print(" | Max Ph1: "); Serial.print(maxPhase1, 1); Serial.print(" A");
Serial.print(" | Max Ph2: "); Serial.print(maxPhase2, 1); Serial.println(" A");
// Werte für den nächsten Lauf zurücksetzen
maxRPM = 0;
maxPhase1 = 0;
maxPhase2 = 0;
}
else
{
float remainingSeconds = (RunTimeMax_ms - elapsedTime + 499) / 1000;
if (remainingSeconds != lastSecondsPrint && remainingSeconds > 0)
{
if (TorqueVal > 10000) Serial.print("-> Motor rueckwaerts ");
else Serial.print("-> Motor vorwaerts ");
Serial.print(", Rest: ");
Serial.print(remainingSeconds);
Serial.print("Sek.");
Serial.print(" | Aktuelle RPM: ");
Serial.print(currentRPM);
Serial.print(" | VCB: ");
Serial.print(currentVoltage, 1);
Serial.print(" V");
Serial.print(" | Ph1: ");
Serial.print(currentPhase1,1);
Serial.print(" A | Ph2: ");
Serial.print(currentPhase2,1);
Serial.println(" A");
lastSecondsPrint = remainingSeconds;
}
}
}
// Senden alle 100ms (Timing aus deinem Code)
if (currentTime - lastSendTime >= 50)
{
lastSendTime = currentTime;
uint8_t tHi = highByte(TorqueVal);
uint8_t tLo = lowByte(TorqueVal);
byte currentFunc = motorRunning ? motorFunction : 0x00;
sendCAN(0x371, 8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
sendCAN(0x286, 8, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x21, 0x00);
sendCAN(0x285, 8, 0x00, 0x00, 0x14, 0x39, 0x91, 0xFE, 0x0C, 0x10);
sendCAN(0x287, 8, tHi, tLo, tHi, tLo, tHi, tLo, currentFunc, 0x00);
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
// --- TASK 2: SCHNELLER CAN EMPFANG (CORE 0, PRIO 5) ---
void TaskCanRecvLoop(void *pvParameters)
{
twai_message_t rx_msg;
for (;;)
{
// Wir nutzen die High-Speed Schleife aus deinem Code
while (twai_receive(&rx_msg, pdMS_TO_TICKS(1)) == ESP_OK)
{
if (rx_msg.identifier == 0x289)
{
// Byte 2 ist MSB, Byte 3 ist LSB
uint16_t rawRpm = (rx_msg.data[2] << 8) | rx_msg.data[3];
currentRPM = rawRpm - 20000;
// abs() nutzen wir nur zum Vergleich, gespeichert wird die echte Zahl
if (abs(currentRPM) > abs(maxRPM))
{
maxRPM = currentRPM;
}
// VCB: Byte 4 ist MSB, Byte 5 ist LSB
uint16_t rawVoltage = (rx_msg.data[4] << 8) | rx_msg.data[5];
// Da dein Log 3420 zeigt, teilen wir durch 10.0f für 342.0V
currentVoltage = rawVoltage / 10.0f;
}
else if (rx_msg.identifier == 0x732)
{
// Phase 1: Byte 0 ist MSB, Byte 1 ist LSB
uint16_t rawPh1 = (rx_msg.data[0] << 8) | rx_msg.data[1];
// Phase 2: Byte 2 ist MSB, Byte 3 ist LSB
uint16_t rawPh2 = (rx_msg.data[2] << 8) | rx_msg.data[3];
// Offset laut DBC ist -1000.
// Wir nehmen den Rohwert, ziehen 1000 ab und teilen durch 10.0f,
// um auf die 5A aus SavvyCAN zu kommen (Dezi-Ampere).
currentPhase1 = (float)(rawPh1 - 1000) ;
currentPhase2 = (float)(rawPh2 - 1000) ;
// Vergleich über den Betrag (abs), aber Speichern des echten Werts (inkl. Vorzeichen)
if (abs(currentPhase1) > abs(maxPhase1)) {
maxPhase1 = currentPhase1;
}
if (abs(currentPhase2) > abs(maxPhase2)) {
maxPhase2 = currentPhase2;
}
}
}
vTaskDelay(pdMS_TO_TICKS(1)); // Minimaler Delay für Core-Stabilität
}
}
// --- TASK 3: SERIELLE EINGABE (CORE 0, PRIO 1) ---
void TaskSerialInputLoop(void *pvParameters)
{
for (;;)
{
if (Serial.available() > 0)
{
int inputVal = Serial.parseInt();
if (inputVal != 0)
{
if (inputVal > 0 && inputVal > TorqMaxRange) inputVal = TorqMaxRange;
else if (inputVal < 0 && inputVal < -TorqMaxRange) inputVal = -TorqMaxRange;
TorqueVal = TorqueNeutral + inputVal;
startTime = millis();
motorRunning = true;
Serial.println("#########################################################");
Serial.print("Core 0: Motor Start Torq: ");
Serial.println(TorqueVal);
}
}
vTaskDelay(pdMS_TO_TICKS(100)); // Reicht für Tastatur locker aus
}
}
void setup()
{
Serial.begin(115200);
delay(1000);
Serial.println("Outlander Inverter Tester @BAVARIANSuperGuy was here @MIT");
Serial.println("Input: -35 bis 35 | Runtime: 4 Sek.");
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK && twai_start() == ESP_OK)
{
Serial.println("CAN-Bus bereit.");
}
// Task 1: Senden auf CORE 1
xTaskCreatePinnedToCore(TaskCanSendLoop, "CAN_Send", 4096, NULL, 5, &TaskCanSendHandle, 1);
// Task 2: Empfangen auf CORE 0 (Hohe Priorität)
xTaskCreatePinnedToCore(TaskCanRecvLoop, "CAN_Recv", 4096, NULL, 5, &TaskCanRecvHandle, 0);
// Task 3: Serial Input auf CORE 0 (Niedrige Priorität)
xTaskCreatePinnedToCore(TaskSerialInputLoop, "Serial_In", 4096, NULL, 1, &TaskSerialHandle, 0);
}
void loop()
{
vTaskDelete(NULL);
}