Hyper car hybrid
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
2006 Lexus, which have modified into a Phev, and ordered a transmission and inverter of the same model.
the numbers off inverter is G9200-30030.
the numbers off inverter is G9200-30030.
Re: Hyper car hybrid
Oh, trouble... It looks like toyota updates at 5ms intervals.daleread wrote: ↑Wed Mar 09, 2022 9:58 pm Download from here. logic 1.2.18 (not logic 2)
https://support.saleae.com/logic-softwa ... load-links
Then you can open Damien's logfiles
It is clocked at 500kHz - and the clocks don't let up, they just blast on through continuously
So reference line is very important to get the exact right bit for the message start. I'm not sure exactly how to hook that up to chip select lines for each receiver. Might need some logic chips, or some very fast interrupts.
If you can work out what the HTM data array maps to that would be great! I don't see how to do that without recording both data lines at the same time, and probably videoing the drive and figuring out how to sync it up.
Woodfie and I have used the vcu board to decode some MTH data. Adjusting bus voltage, heat gun pointed at temperature sensors that sort of thing.
Re: Hyper car hybrid
Same here Woolfie.
I found 2 magic buttons,
Under this window is "Attachments", you can add files and photos from there.
The second is the " quote marks in the top left to build a reply.
Its a bit like hacking

Re: Hyper car hybrid
The gs450_vcu Rx and Tx the data ok, use that code, don't re-invent the wheel, do you do Arduino code?If you can work out what the HTM data array maps to that would be great! I don't see how to do that without recording both data lines at the same time, and probably videoing the drive and figuring out how to sync it up.
I can unravel Damien's code for each relevant byte, and build the data array document. (has Damien already done this...?)
It will take me a few hours, but very worthwhile.
Give me a day or 2

There are 13 bytes of data to make the inverter run (0,5,6,11,12,26,27,32,33,75,76,78,79)
Speed, bytes 0 75,76
MG1, bytes 5,6 11,12
MG2, bytes 26,27 32,33
CRC, bytes 78,79
I suspect the same data is in all inverters but probably grew larger through the generations
TBH, it look quite straight forward...
htm control bytes, to Inverter
Code: Select all
// Set up control array bytes for inverter message send
void control_inverter()
{
int speedSum=0;
if(timer_htm.check()) //prepare htm data
{
if(mth_good)
{
dc_bus_voltage=(((mth_data[82]|mth_data[83]<<8)-5)/2); //DC Bus Votage, Bytes 82,83
temp_inv_water=(mth_data[42]|mth_data[43]<<8); //Inverter Water Temperature, Bytes 42,43
temp_inv_inductor=(mth_data[86]|mth_data[87]<<8); //Inverter Inductor Temperature, Bytes 86,87
mg1_speed=mth_data[6]|mth_data[7]<<8; //MG1 Speed Bytes 6,7
mg2_speed=mth_data[31]|mth_data[32]<<8; //MG2 Speed Bytes 31,32
}
//gear=get_gear();
mg2_torque=get_torque(); // -3500 (reverse) to 3500 (forward)
mg1_torque=((mg2_torque*5)/4); //Cheat
if((mg2_speed>MG2MAXSPEED)||(mg2_speed<-MG2MAXSPEED))mg2_torque=0; //MG2 Stopped
if(gear==REVERSE)mg1_torque=0; //MG1 Stopped
//speed feedback
speedSum=mg2_speed+mg1_speed; //Total speed (RPM?)
speedSum/=113; //Total Speed Calc
htm_data[0]=(byte)speedSum; //Build SpeedSum Byte 0
htm_data[75]=(mg1_torque*4)&0xFF; //Build Torque Byte 75
htm_data[76]=((mg1_torque*4)>>8); //Build Torque Byte 76
//mg1
htm_data[5]=(mg1_torque*-1)&0xFF; //negative is forward Byte 5
htm_data[6]=((mg1_torque*-1)>>8); Byte 6
htm_data[11]=htm_data[5]; Byte 11 = Byte 5
htm_data[12]=htm_data[6]; Byte 12 = Byte 6
//mg2
htm_data[26]=(mg2_torque)&0xFF; //positive is forward Byte 26
htm_data[27]=((mg2_torque)>>8); Byte 27
htm_data[32]=htm_data[26]; Byte 32 = Byte 26
htm_data[33]=htm_data[27]; Byte 33 = Byte 27
//checksum
htm_checksum=0;
for(byte i=0;i<78;i++)htm_checksum+=htm_data[i]; //CRC
htm_data[78]=htm_checksum&0xFF; Byte 78, CRC
htm_data[79]=htm_checksum>>8; Byte 79, CRC (last byte)
}
Code: Select all
SerialDEBUG.print("MG1 - Speed: ");
SerialDEBUG.print(mg1_speed); //MG1
SerialDEBUG.print("rpm\tPosition: ");
SerialDEBUG.print(mth_data[12]|mth_data[13]<<8); //MG1 rpm Byte 12, 13 rpm
SerialDEBUG.print("\n");
SerialDEBUG.print("MG2 - Speed: "); //MG2
SerialDEBUG.print(mg2_speed);
SerialDEBUG.print("rpm\tPosition: ");
SerialDEBUG.print(mth_data[37]|mth_data[38]<<8); //MG2 rpm Byte 37,38
SerialDEBUG.print("\n");
SerialDEBUG.print("Water Temp:\t"); //Water Temperature
SerialDEBUG.print(temp_inv_water);
SerialDEBUG.print("c\nInductor Temp:\t" ); //Inductor Temperature
SerialDEBUG.print(temp_inv_inductor);
SerialDEBUG.print("c\nAnother Temp:\t");
SerialDEBUG.print(mth_data[88]|mth_data[89]<<8); //Water Temperature Byte 88,89
SerialDEBUG.print("c\nAnother Temp:\t");
SerialDEBUG.print(mth_data[41]|mth_data[40]<<8); //Inductor Temperature Byte 41,40 <<< wrong way around !
SerialDEBUG.print("c\n");
Code: Select all
v=pack voltage (0-700Volts)
i=current (0-1000Amps)
p=power (0-300kw)
m=mg1 rpm (0-10000rpm)
n=mg2 rpm (0-10000rpm)
o=mg1 temp (-20 to 120C)
r=mg2 temp (-20 to 120C)
q=oil pressure (0-100%)
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Here were the changes made to the gs450h _vcu code
2 separate throttles as described in above post.
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Here are some photos of the Siris Roadster.
The Mauve one is the Q211 recipient.
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Will get driveline pictures in daylight.
Front end at present is mk3 Cortina, am looking to install a double wishbone system , as yet un found...do you have any suggestions? What are you intending to use on RS200?
Front end at present is mk3 Cortina, am looking to install a double wishbone system , as yet un found...do you have any suggestions? What are you intending to use on RS200?
Re: Hyper car hybrid
Nice looking car, reminds me of a TR7, but way better. Is it a production or a kit car?Front end at present is mk3 Cortina, am looking to install a double wishbone system , as yet un found...do you have any suggestions? What are you intending to use on RS200?
I use MGTF hub carriers (classic mini) on the front on the RS200 with fabricated longer wishbones.
You can use the whole subframe from a MGF or MGTF, every thing is there for you in one lump.
I replace the hubs with Ford Fiesta 4x108 and use Audi bearings, and Wilwood 4 pot callipers.
I can share the CAD files if they are useful to you?
There are lots of photos here, scroll to the bottom of the page.
https://rsretro.smugmug.com/Chassis-Bod ... m/Chassis/ Thank you for the code, always looks simple when its done. Much appreciated.
I have been hacking into the Zombie Inverter for the Prius code, to move it into the GS450h_vcu.
I have documented the code and built a small spread sheet with the relevant byte transfers and where they are different between Lexus and Toyota.
The Prius Inverters are way cheaper than the Lexus, be great to get this working.
Here is the spreadsheet and code below that.
I am still checking through this stuff and I haven't tested it, yet.
Code: Select all
Function Description 450h Prius Comments
htm To Inverter GS450H.cpp [80] [100]
htm Speed Speed Sum 0 0
Speed Torque Sum Hi 76 76 75
Speed Torque Sum Lo 75 75 76
MG1 Torque Req Hi 5 5
MG1 Torque Req Lo 6 6
MG1 Torque Req Hi 11 11
MG1 Torque Req Lo 12 12
MG2 Torque Req Hi 26 Reverse 26
MG2 Torque Req Lo 27 Reverse 27
MG2 Torque Req Hi/2 Forward 28 new
MG2 Torque Req Lo/2 Forward 29 new
MG2 Torque Req Hi 32 30
MG2 Torque Req Lo 33 31
Regen Battery Hi 63 85 moved
Regen Battery Lo 64 86 moved
Discharge Battery Hi 65 87 moved
Discharge Battery Lo 66 88 moved
CRC CRC Hi 78 98 moved
CRC CRC Lo 79 99 moved
Constant 4 1
Constant 4 16 4 16
Constant 4 37 4 41
Constant 4 60 4 67
Constant 25 62 4 73
Constant 128 70 24 75
Constant 128,255 74 136 86
Constant 160 90
CRC 37 78 95 98
CRC 1 79 1 99
mth From Inverter [100] [120]
Data Rx Inc 1
MG1 Speed Hi 6 6
MG1 Speed Lo 7 7
MG1 rpm Hi 12
MG1 rpm Lo 13
MG2 Speed Hi 31
MG2 Speed Lo 32
MG2 rpm Hi 37 38 moved
MG2 rpm Lo 38 39 moved
Inverter Temp Hi 41 40
Inverter Temp Lo 40 41
Water Temp Hi 42 42
Water Temp Lo 43 43
Bus Voltage Hi 82 100 moved
Bus Voltage Lo 83 101 moved
Inverter Temp Hi 86 86
Inverter Temp Lo 87 87
Water Temp Hi 88
Water Temp Lo 89
CRC Hi 78 98
CRC Lo 79 99
Code: Select all
/*
* GS450h and Prius Zombie Inverter master
*
* Data exchange, using htm_state
* Step 0, Read data string from the Inverter, sync pin low
* Step 1, Send setup data string to Inverter with sync pin high, or sync pin low
* Step 2, Spare
* Step 3, Calc checksum and error LED, or decode data from Inveter
* Step 4, Calc torque required data and send to Inverter
*
* inv_status is the data pointer
*
* D.R. 10th March 2022
*
*/
#include "GS450H.h"
#include "hwinit.h"
#include "temp_meas.h"
#include <libopencm3/stm32/timer.h>
#include "anain.h"
#include "my_math.h"
#include "utils.h"
#define LOW_Gear 0
#define HIGH_Gear 1
#define AUTO_Gear 2
static uint8_t htm_state = 0;
static uint8_t inv_status = 1;//must be 1 for gs450h
uint16_t counter;
static uint16_t htm_checksum;
static uint8_t frame_count;
static int16_t mg1_torque, mg2_torque, speedSum;
bool statusInv=0;
int16_t GS450HClass::dc_bus_voltage;
int16_t GS450HClass::temp_inv_water;
int16_t GS450HClass::temp_inv_inductor;
int16_t GS450HClass::mg1_speed;
int16_t GS450HClass::mg2_speed;
//80 bytes out and 100 bytes back in (with offset of 8 bytes).
//100 bytes out and 80 bytes back in (for Prius Support).
static uint8_t mth_data[120];
//GS450h init data
static uint8_t htm_data_setup[100]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,25,0,0,0,0,0,0,0,128,0,0,0,128,0,0,0,37,1};
//GS450h woeking data
static uint8_t htm_data[100]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,0};
#if 0
// Not currently used
static uint8_t htm_data_setup_auris[100]= {0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x01};
#endif
// 0=Prius init data (from 0 to 6)
uint8_t htm_data_init[7][100]=
{ {0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,25,0,0,0,0,0,0,0,0,0,0,136,0,0,0,160,0,0,0,0,0,0,0,95,1},
{0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,25,0,0,0,0,0,0,0,0,0,0,136,0,0,0,160,0,0,0,0,0,0,0,95,1},
{0,30,0,0,0,0,0,18,0,154,250,0,0,0,0,97,4,0,0,0,0,0,173,255,82,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,75,25,60,246,52,8,0,0,0,0,0,0,138,0,0,0,168,0,0,0,1,0,0,0,72,7},
{0,30,0,0,0,0,0,18,0,154,250,0,0,0,0,97,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,75,25,60,246,52,8,0,0,0,0,0,0,138,0,0,0,168,0,0,0,2,0,0,0,75,5},
{0,30,0,0,0,0,0,18,0,154,250,0,0,0,0,97,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,75,25,60,246,52,8,0,0,0,0,0,0,138,0,0,0,168,0,0,0,2,0,0,0,75,5},
{0,30,0,0,0,0,0,18,0,154,250,0,0,255,0,97,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,255,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,255,4,73,25,60,246,52,8,0,0,255,0,0,0,138,0,0,0,168,0,0,0,3,0,0,0,70,9},
{0,30,0,2,0,0,0,18,0,154,250,0,0,16,0,97,0,0,0,0,0,0,200,249,56,6,165,0,136,0,63,0,16,0,0,0,63,0,16,0,3,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,16,0,75,12,45,248,21,6,0,0,16,0,0,0,202,0,211,0,16,0,0,0,134,16,0,0,130,10}
};
// Clock
void GS450HClass::setTimerState(bool desiredTimerState)
{
if (desiredTimerState != this->timerIsRunning)
{
if (desiredTimerState)
{
tim_setup(); //toyota hybrid oil pump pwm timer
tim2_setup(); //TOYOTA HYBRID INVERTER INTERFACE CLOCK
this->timerIsRunning=true; //timers are now running
}
else
{
// These are only used with the Totoa hybrid option.
timer_disable_counter(TIM2); //TOYOTA HYBRID INVERTER INTERFACE CLOCK
timer_disable_counter(TIM1); //toyota hybrid oil pump pwm timer
this->timerIsRunning=false; //timers are now stopped
}
}
}
// Torque required map (not used)
void GS450HClass::setTorqueTarget(int16_t torquePercent)
{
//map throttle for GS450HClass inverter
this->scaledTorqueTarget = utils::change(torquePercent, 0, 3040, 0, 3500);
}
// 100 ms code
void GS450HClass::run100msTask(uint8_t Lexus_Gear, uint16_t Lexus_Oil)
{
//update inverter status on web interface
Param::SetInt(Param::InvStat, GS450HClass::statusFB());
// Lexus only gearbox
if (Lexus_Gear == 1)
{
DigIo::SP_out.Clear();
DigIo::SL1_out.Clear();
DigIo::SL2_out.Clear();
//set high gear
Param::SetInt(Param::GearFB,HIGH_Gear);
}
// Lexus only gearbox
if (Lexus_Gear == 0)
{
DigIo::SP_out.Clear();
DigIo::SL1_out.Clear();
DigIo::SL2_out.Clear();
//set low gear
Param::SetInt(Param::GearFB,LOW_Gear);
}
setTimerState(true);
//map oil pump pwm to timer
uint16_t Lexus_Oil2 = utils::change(Lexus_Oil, 10, 80, 1875, 425);
//duty. 1000 = 52% , 500 = 76% , 1500=28%
timer_set_oc_value(TIM1, TIM_OC1, Lexus_Oil2);
//update web interface with status of gearbox PB feedbacks for diag purposes.
Param::SetInt(Param::Gear1,DigIo::gear1_in.Get());
Param::SetInt(Param::Gear2,DigIo::gear2_in.Get());
Param::SetInt(Param::Gear3,DigIo::gear3_in.Get());
//send GS450H inverter temp to web interface
Param::SetInt(Param::tmphs,GS450HClass::temp_inv_water);
static s32fp mTemps[2];
static s32fp tmpm;
//in the gs450h case we must read the analog temp values from sensors in the gearbox
int tmpmg1 = AnaIn::MG1_Temp.Get();
int tmpmg2 = AnaIn::MG2_Temp.Get();
mTemps[0] = TempMeas::Lookup(tmpmg1, TempMeas::TEMP_TOYOTA);
mTemps[1] = TempMeas::Lookup(tmpmg2, TempMeas::TEMP_TOYOTA);
//which ever is the hottest gets displayed
tmpm = MAX(mTemps[0], mTemps[1]);
Param::SetFlt(Param::tmpm,tmpm);
}
//////////////////////////////////////////////////////////////////////////
//Usart 2 DMA Transmit and Receive Section
//////////////////////////////////////////////////////////////////////////
// Write DMA data
static void dma_write(uint8_t *data, int size)
{
/*
* Using channel 7 for USART2_TX
*/
/* Reset DMA channel*/
dma_channel_reset(DMA1, DMA_CHANNEL7);
dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t)data);
dma_set_number_of_data(DMA1, DMA_CHANNEL7, size);
dma_set_read_from_memory(DMA1, DMA_CHANNEL7);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL7);
dma_set_peripheral_size(DMA1, DMA_CHANNEL7, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL7, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL7, DMA_CCR_PL_MEDIUM);
//dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
//dma_clear_interrupt_flags(DMA1, DMA_CHANNEL7, DMA_TCIF);
dma_enable_channel(DMA1, DMA_CHANNEL7);
usart_enable_tx_dma(USART2);
}
//DMA channel interupt 7 USART2_TX
volatile int transfered = 0;
void dma1_channel7_isr(void)
{
if ((DMA1_ISR &DMA_ISR_TCIF7) != 0)
{
//Interrupt Flag Clear Register
DMA1_IFCR |= DMA_IFCR_CTCIF7;
// Flag sucess
transfered = 1;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL7);
usart_disable_tx_dma(USART2);
dma_disable_channel(DMA1, DMA_CHANNEL7);
}
//DMA channel interupt 6 USART2_RX
static void dma_read(uint8_t *data, int size)
{
// Reset DMA channel
dma_channel_reset(DMA1, DMA_CHANNEL6);
dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (uint32_t)&USART2_DR);
dma_set_memory_address(DMA1, DMA_CHANNEL6, (uint32_t)data);
dma_set_number_of_data(DMA1, DMA_CHANNEL6, size);
dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6);
dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6);
dma_set_peripheral_size(DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_8BIT);
dma_set_memory_size(DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_8BIT);
dma_set_priority(DMA1, DMA_CHANNEL6, DMA_CCR_PL_LOW);
//dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6);
// dma_clear_interrupt_flags(DMA1, DMA_CHANNEL6, DMA_TCIF);
dma_enable_channel(DMA1, DMA_CHANNEL6);
usart_enable_rx_dma(USART2);
}
//DMA Interrupt Serial 2
volatile int received = 0;
void dma1_channel6_isr(void)
{
if ((DMA1_ISR &DMA_ISR_TCIF6) != 0)
{
DMA1_IFCR |= DMA_IFCR_CTCIF6;
received = 1;
}
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6);
usart_disable_rx_dma(USART2);
dma_disable_channel(DMA1, DMA_CHANNEL6);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//Dilbert's code here
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Prius data exchange init
void GS450HClass::SetPrius()
{
if (htm_state<5)
{
htm_state = 5; //Prius is steps 5 to 9
inv_status = 0; //must be 0 for Prius (data array)
}
}
//GS450h data exchange init
void GS450HClass::SetGS450H()
{
if (htm_state>4)
{
htm_state = 0; //GS450h are steps 0 to 4
inv_status = 1; //must be 1 for gs450h (data array)
}
}
// mth CRC
uint8_t GS450HClass::VerifyMTHChecksum(uint16_t len)
{
uint16_t mth_checksum=0;
for(int i=0; i<(len-2); i++)
mth_checksum+=mth_data[i];
if(mth_checksum==(mth_data[len-2]|(mth_data[len-1]<<8))) return 1;
else return 0;
}
// htm CRC
void GS450HClass::CalcHTMChecksum(uint16_t len)
{
uint16_t htm_checksum=0;
for(int i=0; i<(len-2); i++)htm_checksum+=htm_data[i];
htm_data[len-2]=htm_checksum&0xFF;
htm_data[len-1]=htm_checksum>>8;
}
// Sequencer
void GS450HClass::UpdateHTMState1Ms(int8_t gear)
{
// GS450h Sequence, Steps 0-4 -----------------------------------------------------------
//
// Step 0, Read data string[100] from the Inverter, sync pin low
// Step 1, Send setup data string[80] to Inverter with sync pin high, or sync pin low
// Step 2, Spare
// Step 3, Calc checksum and error LED, or decode data from Inveter
// Step 4, Calc torque required data and send to Inverter
// Sequencer
switch(htm_state)
{
case 0:
{
//read in mth data via dma. Probably need some kind of check dma complete flag here
dma_read(mth_data,100);
//HAL_GPIO_WritePin(HTM_SYNC_GPIO_Port, HTM_SYNC_Pin, 0);
DigIo::req_out.Clear();
//Next step
htm_state++;
}
break;
case 1:
{
//HAL_GPIO_WritePin(HTM_SYNC_GPIO_Port, HTM_SYNC_Pin, 1);
DigIo::req_out.Set();
// Inverter init
if(inv_status==0)
{
// if the transfer complete flag is set
if (dma_get_interrupt_flag(DMA1, DMA_CHANNEL7, DMA_TCIF))then send another packet
{
dma_clear_interrupt_flags(DMA1, DMA_CHANNEL7, DMA_TCIF);//clear the flag.
dma_write(htm_data,80); //HAL_UART_Transmit_IT(&huart2, htm_data, 80);
}
}
else
{
//HAL_UART_Transmit_IT(&huart2, htm_data_setup, 80);
dma_write(htm_data_setup,80);
// Wait for reply from Inverter <<<<<<<<<<
if(mth_data[1]!=0)
inv_status--;
}
htm_state++;
}
break;
case 2:
{
htm_state++;
}
break;
case 3:
{
// dma_get_interrupt_flag(DMA1, DMA_CHANNEL6, DMA_TCIF);
if(VerifyMTHChecksum(100)==0 || dma_get_interrupt_flag(DMA1, DMA_CHANNEL6, DMA_TCIF)==0)
{
//HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, 1 );
statusInv=0;
}
else
{
//HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, 0 );
//exchange data and prepare next HTM frame
dma_clear_interrupt_flags(DMA1, DMA_CHANNEL6, DMA_TCIF);
statusInv=1;
dc_bus_voltage=(((mth_data[82]|mth_data[83]<<8)-5)/2);
temp_inv_water=(mth_data[42]|mth_data[43]<<8);
temp_inv_inductor=(mth_data[86]|mth_data[87]<<8);
mg1_speed=mth_data[6]|mth_data[7]<<8;
mg2_speed=mth_data[31]|mth_data[32]<<8;
}
// CRC
mth_data[98]=0;
mth_data[99]=0;
htm_state++;
}
break;
case 4:
{
// -3500 (reverse) to 3500 (forward)
if(gear==0) mg2_torque=0;//Neutral
if(gear==32) mg2_torque=this->scaledTorqueTarget;//Drive
if(gear==-32) mg2_torque=this->scaledTorqueTarget*-1;//Reverse
// MG1 torque cheat
mg1_torque=((mg2_torque*5)/4);
//no mg1 torque in reverse.
if(gear==-32) mg1_torque=0;
//post processed final torue value sent to inv to web interface
Param::SetInt(Param::torque,mg2_torque);
//speed feedback
speedSum=mg2_speed+mg1_speed;
speedSum/=113;
uint8_t speedSum2=speedSum;
htm_data[0]=speedSum2;
htm_data[75]=(mg1_torque*4) & 0xFF;
htm_data[76]=((mg1_torque*4)>>8) & 0xFF;
//MG1
htm_data[5]=(mg1_torque*-1)&0xFF; //negative is forward
htm_data[6]=((mg1_torque*-1)>>8);
htm_data[11]=htm_data[5];
htm_data[12]=htm_data[6];
//MG2
htm_data[26]=(mg2_torque) & 0xFF; //positive is forward
htm_data[27]=((mg2_torque)>>8) & 0xFF;
htm_data[32]=htm_data[26];
htm_data[33]=htm_data[27];
// regen ability of battery
htm_data[63]=(-5000)&0xFF;
htm_data[64]=((-5000)>>8);
// discharge ability of battery
htm_data[65]=(27500)&0xFF;
htm_data[66]=((27500)>>8);
//checksum
htm_checksum=0;
for(int i=0; i<78; i++)htm_checksum+=htm_data[i];
htm_data[78]=htm_checksum&0xFF;
htm_data[79]=htm_checksum>>8;
// LED
if(counter>100)
{
//HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin );
counter = 0;
}
else
{
counter++;
}
// Reset to start of sequence
htm_state=0;
}
break;
/***** Demo code for Gen3 Prius/Auris direct communications! */
// Prius Sequence, Steps 5 to 9 ----------------------------------------------------------------------
//
// Step 5, Read data string[100] from the Inverter, sync pin low
// Step 6, Send setup data string[6][80] to Inverter with sync pin high, or sync pin low
// Step 7, Spare
// Step 8, Calc checksum and error LED, or decode data from Inveter
// Step 9, Calc torque required data and send to Inverter
case 5:
{
//read in mth data via dma. Probably need some kind of check dma complete flag here
dma_read(mth_data,120);
//HAL_GPIO_WritePin(HTM_SYNC_GPIO_Port, HTM_SYNC_Pin, 0);
DigIo::req_out.Clear();
// Next step
htm_state++;
}
break;
case 6:
{
//HAL_GPIO_WritePin(HTM_SYNC_GPIO_Port, HTM_SYNC_Pin, 1);
DigIo::req_out.Set();
if(inv_status>5)
{
// if the transfer complete flag is set then send another packet
if (dma_get_interrupt_flag(DMA1, DMA_CHANNEL7, DMA_TCIF))
{
dma_clear_interrupt_flags(DMA1, DMA_CHANNEL7, DMA_TCIF);//clear the flag.
dma_write(htm_data,100); //HAL_UART_Transmit_IT(&huart2, htm_data, 80);
}
}
else
{
//HAL_UART_Transmit_IT(&huart2, htm_data_setup,80);
dma_write(&htm_data_init[inv_status][0],100);
inv_status++;
if(inv_status==6)
{
//memcpy(htm_data, &htm_data_init[ inv_status ][0], 100);
}
}
htm_state++;
}
break;
Case 7:
{
htm_state++;
}
break;
case 8:
{
// dma_get_interrupt_flag(DMA1, DMA_CHANNEL6, DMA_TCIF);
if(VerifyMTHChecksum(120)==0 || dma_get_interrupt_flag(DMA1, DMA_CHANNEL6, DMA_TCIF)==0)
{
statusInv=0;
}
else
{
//exchange data and prepare next HTM frame
dma_clear_interrupt_flags(DMA1, DMA_CHANNEL6, DMA_TCIF);
statusInv=1;
dc_bus_voltage=(((mth_data[100]|mth_data[101]<<8)-5)/2);
temp_inv_water=(mth_data[42]|mth_data[43]<<8);
temp_inv_inductor=(mth_data[86]|mth_data[87]<<8);
mg1_speed=mth_data[6]|mth_data[7]<<8;
mg2_speed=mth_data[38]|mth_data[39]<<8;
}
// Clear CRC
mth_data[98]=0;
mth_data[99]=0;
// Next step
htm_state++;
}
break;
case 9:
{
// -3500 (reverse) to 3500 (forward)
if(gear==0) mg2_torque=0;//Neutral
if(gear==32) mg2_torque=this->scaledTorqueTarget;//Drive
if(gear==-32) mg2_torque=this->scaledTorqueTarget*-1;//Reverse
// MG1 torque calc cheat
mg1_torque=((mg2_torque*5)/4);
if(gear==-32) mg1_torque=0; //no mg1 torque in reverse.
Param::SetInt(Param::torque,mg2_torque);//post processed final torue value sent to inv to web interface
//speed feedback
speedSum=mg2_speed+mg1_speed;
speedSum/=113;
//Possibly not needed
//uint8_t speedSum2=speedSum;
//htm_data[0]=speedSum2;
//these bytes are used, and seem to be MG1 for startup, but can't work out the relatino to the
//bytes earlier in the stream, possibly the byte order has been flipped on these 2 bytes
//could be a software bug ?
htm_data[76]=(mg1_torque*4) & 0xFF;
htm_data[75]=((mg1_torque*4)>>8) & 0xFF;
//MG1
htm_data[5]=(mg1_torque)&0xFF; //negative is forward
htm_data[6]=((mg1_torque)>>8);
htm_data[11]=htm_data[5];
htm_data[12]=htm_data[6];
//MG2 the MG2 values are now beside each other!
htm_data[30]=(mg2_torque) & 0xFF; //positive is forward
htm_data[31]=((mg2_torque)>>8) & 0xFF;
// Drive
if(gear==32)
{
//forward direction these bytes should match
htm_data[26]=htm_data[30];
htm_data[27]=htm_data[31];
htm_data[28]=(mg2_torque/2) & 0xFF; //positive is forward
htm_data[29]=((mg2_torque/2)>>8) & 0xFF;
}
// Reverse
if(gear==-32)
{
//reverse direction these bytes should match
htm_data[28]=htm_data[30];
htm_data[29]=htm_data[31];
htm_data[26]=(mg2_torque/2) & 0xFF; //positive is forward
htm_data[27]=((mg2_torque/2)>>8) & 0xFF;
}
//This data has moved!
// regen ability of battery
htm_data[85]=(-5000)&0xFF;
htm_data[86]=((-5000)>>8);
// discharge ability of battery
htm_data[87]=(-10000)&0xFF;
htm_data[88]=((-10000)>>8);
//checksum
if(++frame_count & 0x01)
{
htm_data[94]++;
}
// Temp save Checksum
CalcHTMChecksum(100);
// Goto begining
htm_state=5;
}
break;
}
}
// Inverter Status
bool GS450HClass::statusFB()
{
return statusInv;
}
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Great work , and nicely built.
The Q211 will be an interesting variant for sure...I like.... it!!
Thanks for spreadsheet and code information.....and great to see that the Gen 4 prius inverters are getting closer to what the Lexus gs450h inverter is doing.
Thanks for spreadsheet and code information.....and great to see that the Gen 4 prius inverters are getting closer to what the Lexus gs450h inverter is doing.
Re: Hyper car hybrid
Well I feel a little silly. I've been trying to decode this as a SPI port. But it isn't one at all. "Synchronous Serial" so it has a Clock sent with it to get the bit rate, however the bytes are still encoded like asynchronous data - with a start and stop bit?! I hadn't seen that before.
First time using this logic analyser software. Here you can see the serial streams decoded as a normal asynchronous stream. I think it can quite happily be "sniffed" with a bulk standard serial port, set at 500kbps.
Which, again I am doubting myself, because the GS450H stuff is at 250kbps - is the Prius faster, or is 250kbps good enough?
Woodfie and I had decoded MTH data using the GS450H code modified to accept the 20 more bytes. I thought I was confident that the data had changed position. Here is what we came up with:
Code: Select all
/*
MTH Known: 0-119 bytes
dc voltages 100,101 102,103 was 82,83 stored as 0.5V (IQ1)
Water temperature 51
MG1 speed 10,11
MG2 speed 40,41
checksum 118,119
*/
Re: Hyper car hybrid
The GS450h htm is 80 bytes but the Prius Gen 3 htm is 100 bytes. ? ! - (mth GS=100, mth Prius=120).Woodfie and I had decoded MTH data using the GS450H code modified to accept the 20 more bytes. I thought I was confident that the data had changed position. Here is what we came up with:
This should align the GS450h 80 bytes with the Prius Gen 3 Inverter, or are u=you using Gen 4? (mth 120 bytes)
Code: Select all
Function Description 450h Prius Comments
htm To Inverter GS450H.cpp [80] [100]
htm Speed Speed Sum 0 0
Speed Torque Sum Hi 76 76 75
Speed Torque Sum Lo 75 75 76
MG1 Torque Req Hi 5 5
MG1 Torque Req Lo 6 6
MG1 Torque Req Hi 11 11
MG1 Torque Req Lo 12 12
MG2 Torque Req Hi 26 Reverse 26
MG2 Torque Req Lo 27 Reverse 27
MG2 Torque Req Hi/2 Forward 28 new
MG2 Torque Req Lo/2 Forward 29 new
MG2 Torque Req Hi 32 30
MG2 Torque Req Lo 33 31
Regen Battery Hi 63 85 moved
Regen Battery Lo 64 86 moved
Discharge Battery Hi 65 87 moved
Discharge Battery Lo 66 88 moved
CRC CRC Hi 78 98 moved
CRC CRC Lo 79 99 moved
Constant 4 1
Constant 4 16 4 16
Constant 4 37 4 41
Constant 4 60 4 67
Constant 25 62 4 73
Constant 128 70 24 75
Constant 128,255 74 136 86
Constant 160 90
CRC 37 78 95 98
CRC 1 79 1 99
mth From Inverter [100] [120]
Data Rx Inc 1
MG1 Speed Hi 6 6
MG1 Speed Lo 7 7
MG1 rpm Hi 12
MG1 rpm Lo 13
MG2 Speed Hi 31
MG2 Speed Lo 32
MG2 rpm Hi 37 38 moved
MG2 rpm Lo 38 39 moved
Inverter Temp Hi 41 40
Inverter Temp Lo 40 41
Water Temp Hi 42 42
Water Temp Lo 43 43
Bus Voltage Hi 82 100 moved
Bus Voltage Lo 83 101 moved
Inverter Temp Hi 86 86
Inverter Temp Lo 87 87
Water Temp Hi 88
Water Temp Lo 89
CRC Hi 78 98
CRC Lo 79 99
Re: Hyper car hybrid
In Damien's code its 250000.First time using this logic analyser software. Here you can see the serial streams decoded as a normal asynchronous stream. I think it can quite happily be "sniffed" with a bulk standard serial port, set at 500kbps.
Which, again I am doubting myself, because the GS450H stuff is at 250kbps - is the Prius faster, or is 250kbps good enough?
Could your 500000 be rising and falling edges therefore x2?
A Serial port, I use FDTI, has the speed. Maybe you should connect the CTS, RTS, DTR, to the clock and sync for your data capture, to synchronise the start and stop of each packet..
The GS450h_vcu code has
Serial1.begin(250000);
As the data speed for the Sync Serial transfer. Use a FDTI "TTL-232R-5V" for sniffing, they are the best around,
https://ftdichip.com/products/ttl-232r-5v/
https://ftdichip.com/wp-content/uploads ... CABLES.pdf
https://au.rs-online.com/web/p/developm ... es/6877770
RS Part number 687-7770
HTH
Re: Hyper car hybrid
This is what I have found, but not tested yet.This mapping doesn't seem to line up with the logic analyser captures from Damiens github. So I'm going to have to go back to the bench and confirm this.
Code: Select all
/*
MTH Known: 0-119 bytes
dc voltages 100,101 102,103 was 82,83 stored as 0.5V (IQ1) - 82,83=102,103
Water temperature 51 was 42,43 is still 42,43
MG1 speed 10,11 was 6,7 is now 6,7
MG2 speed 40,41 was 37,38 is now 38,39
checksum 118,119 was 98,99 is now 118,119
*/
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Nice looking car, reminds me of a TR7, but way better. Is it a production or a kit car?
Three Siris Roadsters were made, and four predecessors called Aurora Coupes. Not quite production, intention was to make available as a kit, or component car.
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Sorry picture inverter, corrected , lost it all, adjusted alignment, and still have it downside up.☹
Re: Hyper car hybrid
Its a cool looking car, I bet it goes like stink.
Thanks for sharing. What wheel pcd are you running?
And do you have any pics of the front suspension, I might be able to help a bit there?
Thanks for sharing. What wheel pcd are you running?
And do you have any pics of the front suspension, I might be able to help a bit there?
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Yes , It goes rather well, weighing 750kg empty, and appears to level hills to make it feel like the world is flat.
The act of fitting the Q211 , Hylander MG unit, as a front drive has only just become a reality, with the great efforts and help of Damien's Lexus_vcu, and/or Johu's T gen2 MG2 logic drive input.. Many thanks to them and this forum....Awesome way forward.....THANKS GUYS ..
Back to the associated mechanics ...PCD is 4.5 inches
It maybe possible to modify the subframe to allow drive shafts to passage from the Q211 to some other hub uprights, use another frame, as MGF as you suggested or custom build a new frame. Because of the Q211 electric motor "Bump" out front of the wheel centerline, the steering rack could be in the way...to be determined..
Re: Hyper car hybrid
I'm just saying what this logic analyser told me.daleread wrote: ↑Fri Mar 11, 2022 7:47 am In Damien's code its 250000.
Could your 500000 be rising and falling edges therefore x2?
...
The GS450h_vcu code hasCode: Select all
Serial1.begin(250000);
The tests with Woodfie we changed the numbers to 100 and 120, and moved the checksum to 118,119 (counting from 0).
Oh by the way - you've labelled it CRC, but what I am seeing is definitely a checksum, not CRC
Re: Hyper car hybrid
Woodfie
Front Suspension photos from MGF and used in RS200 to get front drive.
You could keep your suspension arms, take out the shock/spring and build a small tower, then put the shock/spring on top of the top arm.
Then change the stub axle for the MGF one.
It will also fix your steering.
Front Suspension photos from MGF and used in RS200 to get front drive.
You could keep your suspension arms, take out the shock/spring and build a small tower, then put the shock/spring on top of the top arm.
Then change the stub axle for the MGF one.
It will also fix your steering.
Re: Hyper car hybrid
CRC = Cyclic Redundancy Checksum, sometimes a polynomial.
For the Toyota/Lexus its just adding up all the bytes and throwing away the over flow above 65535
For the Toyota/Lexus its just adding up all the bytes and throwing away the over flow above 65535
Re: Hyper car hybrid
Front (Nissan Leaf Motor) setup with MGF hubs, driveshafts, steering
I will be building this over the next few weeks with a Q211, I have the chassis ready, will keep you posted
I will be building this over the next few weeks with a Q211, I have the chassis ready, will keep you posted
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Daleread
Thanks for the very informative info.
On the last drawing front on, what is the diameter of the green circle? as it closely indicates the height of lower inner suspension bushes to the top of the bonnet,
Thanks W
Thanks for the very informative info.
On the last drawing front on, what is the diameter of the green circle? as it closely indicates the height of lower inner suspension bushes to the top of the bonnet,
Thanks W
Re: Hyper car hybrid
Here are the dimensions of the RS200 for you
The the 605mm can be reduced to fit under your bonnet line, but the RS200 is similar to your car for the bonnet line.
The cross bar locks it al together.
The steering rack is moved to the back to give clearance for the MGR motor unit.
The the 605mm can be reduced to fit under your bonnet line, but the RS200 is similar to your car for the bonnet line.
The cross bar locks it al together.
The steering rack is moved to the back to give clearance for the MGR motor unit.
-
- Posts: 242
- Joined: Wed Mar 09, 2022 6:53 am
- Location: Auckland NZ
- Has thanked: 221 times
- Been thanked: 95 times
Re: Hyper car hybrid
Thanks for that, did a quick check to the outside top of my bonnet line, and is 550mm, presently have an inner panel, with moulded in spare tyre space, which would have to be dispensed with.....the 645mm would have to come down to around 500mm if the inner panel remained, could be a bit short for the coil over shock.
Looking favourable to have double springs to the lower arm, then would have to use hub assembly with lower ball joint designated to take load as cortina does.
Looking favourable to have double springs to the lower arm, then would have to use hub assembly with lower ball joint designated to take load as cortina does.