Webasto HVH50

Introduction and miscellaneous that we haven't created categories for, yet
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

EV_Builder wrote: Tue Feb 27, 2024 6:47 am Time to fed it HV , 12Vdc and turn it on?
HA! Yes. I am not sure what ID is the write ID though, so I guess I can modify the code to run through all IDs 0-64 . . .
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

OK! So I reinstated the royhen99 code with some modifications and hooked everything up to water, 320V and 12V and ground. I had the controller run through all IDs on the lin.order command and used ID 39 for the lin.response, since this is the only ID that does not return -1. Power set for 1000, Temp set for 100 and UDC in was around 320V.

Code: Select all

#include "lin_bus.h"

// Create an IntervalTimer object 
IntervalTimer myTimer;

int ledState = LOW;                // ledState used to set the LED
unsigned long interval = 200000;   // interval at which to blinkLED to run every 0.2 seconds

LIN lin;

int lin_cs = 32; // cs and serial port set for skpang LIN / FDCAN board
int led1 = 23;
int lin_fault = 28;

uint16_t Power = 1000; // set to required power
uint8_t  Temperature = 100; //set to required temperature
uint16_t tmpheater = 0;
uint16_t udcheater = 0;
uint16_t powerheater = 0;

uint8_t CRC = 0;
uint8_t orderID = 0;
//uint8_t responseID = 0;

uint8_t data[8];

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(lin_fault,INPUT);
  pinMode(lin_cs, OUTPUT);
  digitalWrite(lin_cs, HIGH); // enable MCP2004 LIN transceiver
  digitalWrite(LED_BUILTIN, HIGH);
  
  Serial.begin(115200);
  //Serial.print("HVH50 Heater demo");
  
  //lin.begin(&Serial3, 9600);
  lin.begin(&Serial3, 19200); /// Change to this for 19200 /////
  delay(1000);
  pinMode(led1,OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);
  
  myTimer.begin(blinkLED, interval);
}

void loop() {
  // heater
  SendLin();
  delay(1000); // wait 1000ms
  //Serial.print(" Heater test\n");

}

void blinkLED() {
  ledState = !ledState;
  
  digitalWrite(LED_BUILTIN, ledState);
  digitalWrite(led1, ledState);
}

  static void SendLin()
{
   for (orderID = 0; orderID < 64; orderID++) {

   static bool read = true;
   uint8_t data[8];
   delay(1000); // wait 1000ms
   uint8_t lindata[] = {uint8_t(Power/40), uint8_t(Temperature+40), 0, 8};
   lin.order(orderID, lindata, 4, lin2x); 
   delay(100);
  if (lin.response(39, data, 8, lin2x) >=0) // -1 indicates crc error, 19200
     {
     tmpheater = data[1] - 40;
     udcheater = data[4] | (data[5] & 3) << 8;
     powerheater =((data[5] >> 2) | (data[6] << 8)) * 20;
     Serial.print("orderID:");    
     Serial.print(orderID);
     Serial.print(",");
     Serial.print("Temp:");
     Serial.print(tmpheater);
     Serial.print(",");
     Serial.print("Udc:");
     Serial.print(udcheater);
     Serial.print(",");
     Serial.print("Power:");
     Serial.println(powerheater);
     Serial.print("CRC:");    
     Serial.print(CRC);
     Serial.print(",");
     }
   else if (read)
   {
      lin.order(orderID, lindata, 4, lin2x); 
   }
   else
   {
      uint8_t lindata[] = {uint8_t(Power/40), uint8_t(Temperature+40), 0, 8};
      lin.order(orderID, lindata, 4, lin2x); 
      //Serial.print("\n Sending power and temperature");
   }

   read = !read;
  }
}
The Serial Monitor began working FINALLY and the readings looked like this.

Code: Select all

CRC:0,orderID:0,Temp:21,Udc:60,Power:400
CRC:0,orderID:1,Temp:21,Udc:60,Power:400
CRC:0,orderID:2,Temp:21,Udc:60,Power:400
CRC:0,orderID:3,Temp:21,Udc:60,Power:400
CRC:0,orderID:4,Temp:21,Udc:60,Power:400
CRC:0,orderID:5,Temp:21,Udc:60,Power:400
CRC:0,orderID:6,Temp:21,Udc:60,Power:400
CRC:0,orderID:7,Temp:21,Udc:60,Power:400
CRC:0,orderID:8,Temp:21,Udc:60,Power:400
CRC:0,orderID:9,Temp:21,Udc:60,Power:400
CRC:0,orderID:10,Temp:21,Udc:60,Power:400
CRC:0,orderID:11,Temp:21,Udc:60,Power:400
CRC:0,orderID:12,Temp:21,Udc:60,Power:400
CRC:0,orderID:13,Temp:21,Udc:60,Power:400
CRC:0,orderID:14,Temp:21,Udc:60,Power:400
CRC:0,orderID:15,Temp:21,Udc:60,Power:400
CRC:0,orderID:16,Temp:21,Udc:60,Power:400
CRC:0,orderID:17,Temp:21,Udc:60,Power:400
CRC:0,orderID:18,Temp:21,Udc:60,Power:400
CRC:0,orderID:19,Temp:21,Udc:60,Power:400
CRC:0,orderID:20,Temp:21,Udc:60,Power:400
CRC:0,orderID:21,Temp:21,Udc:60,Power:400
CRC:0,orderID:22,Temp:21,Udc:60,Power:400
CRC:0,orderID:23,Temp:21,Udc:60,Power:1040
CRC:0,orderID:24,Temp:21,Udc:60,Power:400
CRC:0,orderID:25,Temp:21,Udc:60,Power:400
CRC:0,orderID:26,Temp:21,Udc:60,Power:400
CRC:0,orderID:27,Temp:21,Udc:60,Power:400
CRC:0,orderID:28,Temp:21,Udc:60,Power:400
CRC:0,orderID:29,Temp:21,Udc:60,Power:400
CRC:0,orderID:30,Temp:21,Udc:60,Power:400
CRC:0,orderID:31,Temp:21,Udc:60,Power:400
CRC:0,orderID:32,Temp:21,Udc:60,Power:400
CRC:0,orderID:33,Temp:21,Udc:60,Power:400
CRC:0,orderID:34,Temp:21,Udc:60,Power:400
CRC:0,orderID:35,Temp:21,Udc:60,Power:400
CRC:0,orderID:36,Temp:21,Udc:60,Power:400
CRC:0,orderID:37,Temp:21,Udc:60,Power:400
CRC:0,orderID:38,Temp:21,Udc:60,Power:400
CRC:0,orderID:39,Temp:21,Udc:60,Power:1040
CRC:0,orderID:40,Temp:21,Udc:60,Power:400
CRC:0,orderID:41,Temp:21,Udc:60,Power:400
CRC:0,orderID:42,Temp:21,Udc:60,Power:400
CRC:0,orderID:43,Temp:21,Udc:60,Power:400
CRC:0,orderID:44,Temp:21,Udc:60,Power:400
CRC:0,orderID:45,Temp:21,Udc:60,Power:400
CRC:0,orderID:46,Temp:21,Udc:60,Power:400
CRC:0,orderID:47,Temp:21,Udc:60,Power:400
CRC:0,orderID:48,Temp:21,Udc:60,Power:400
CRC:0,orderID:49,Temp:21,Udc:60,Power:400
CRC:0,orderID:50,Temp:21,Udc:60,Power:400
CRC:0,orderID:51,Temp:21,Udc:60,Power:400
CRC:0,orderID:52,Temp:21,Udc:60,Power:400
CRC:0,orderID:53,Temp:21,Udc:60,Power:400
CRC:0,orderID:54,Temp:21,Udc:60,Power:400
CRC:0,orderID:55,Temp:21,Udc:60,Power:400
CRC:0,orderID:56,Temp:21,Udc:60,Power:400
CRC:0,orderID:57,Temp:21,Udc:60,Power:400
CRC:0,orderID:58,Temp:21,Udc:60,Power:400
CRC:0,orderID:59,Temp:21,Udc:60,Power:400
CRC:0,orderID:60,Temp:21,Udc:60,Power:1040
CRC:0,orderID:61,Temp:21,Udc:60,Power:400
CRC:0,orderID:62,Temp:21,Udc:60,Power:400
CRC:0,orderID:63,Temp:21,Udc:60,Power:400
I am working to correct the information being spit out from Serial Monitor. I changed up the code to print out each of the numbered data lines [1]-[8] and this is the printout:

Code: Select all

61,0,0,61,192,0,100,1

61,0,0,60,192,0,100,0

61,0,0,60,192,0,100,1

61,0,0,60,192,0,100,0

61,0,0,60,192,0,100,1

61,0,0,60,192,0,101,0

61,0,0,60,192,0,100,1

61,0,0,60,192,0,100,0

61,0,0,61,192,0,99,1

61,0,0,61,192,0,99,0

61,0,0,60,192,0,101,1

61,0,0,60,192,0,100,0

61,0,0,60,192,0,101,1

I am curious why the final data byte 8 goes back and forth between 0 and 1. The wiki page lists the 8 bytes out. I wonder if the 0,1 back and forth is trying to turn the heater on, but it is not appearing in the correct location.

Code: Select all

 	Status
          	4=running	
          	Outlet temp
		Scaling as above	
		Inlet temp	-	
		Voltage LSB	
		Voltage MSB - 2 bits
		Power LSB - 6 bits / Power MSB 1 digit=20W	
		Unknown
For some reason, the formula in the STM32 version used to decode the data is not giving me accurate info:


Interesting to me that the data readouts by each number are different that the printout of the linRXdata repones of:

Code: Select all

59, 0, 114, 58, 64,0, 239, 0
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

I HAVE HOT WATER!!!!!!

So I went to bed last night thinking about what I was missing and woke up with the thought that there might be info hidden in DATA[0] since DATA[1] was used to calculate temp and I recall Johan mentioning that the on status would be in byte 0, so I modified the code to print out DATA[0] through DATA [8] using lin.response ID 39 and running through all of the lin.order IDs.

I ran this code:

Code: Select all

#include "lin_bus.h"



// Create an IntervalTimer object

IntervalTimer myTimer;



int ledState = LOW;                // ledState used to set the LED

unsigned long interval = 200000;   // interval at which to blinkLED to run every 0.2 seconds



LIN lin;



int lin_cs = 32; // cs and serial port set for skpang LIN / FDCAN board

int led1 = 23;

int lin_fault = 28;



uint16_t Power = 40; // set to required power

uint8_t  Temperature = 85; //set to required temperature

uint16_t tmpheater = 0;

uint16_t udcheater = 0;

uint16_t powerheater = 0;



uint8_t CRC = 0;

uint8_t orderID = 0;

uint8_t responseID = 0;



//uint8_t data[8];



uint8_t linTXdata[4] = { 0, 0, 0, 0 };  // 40W, 45C, heater on

uint8_t linRXdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

//uint8_t CRC = 0;

//uint8_t orderID = 0;

//uint8_t responseID = 0;



void setup() {

  pinMode(LED_BUILTIN, OUTPUT);

  pinMode(lin_fault,INPUT);

  pinMode(lin_cs, OUTPUT);

  digitalWrite(lin_cs, HIGH); // enable MCP2004 LIN transceiver

  digitalWrite(LED_BUILTIN, HIGH);

 

  Serial.begin(115200);

  //Serial.print("HVH50 Heater demo");

 

  //lin.begin(&Serial3, 9600);

  lin.begin(&Serial3, 19200); /// Change to this for 19200 /////

  delay(1000);

  pinMode(led1,OUTPUT);

    digitalWrite(LED_BUILTIN, LOW);

 

  myTimer.begin(blinkLED, interval);

}



void loop() {

  // heater

  SendLin();

  delay(100); // wait 100ms

  //Serial.print(" Heater test\n");



}



void blinkLED() {

  ledState = !ledState;

 

  digitalWrite(LED_BUILTIN, ledState);

  digitalWrite(led1, ledState);

}



  static void SendLin()

{

   for (orderID = 0; orderID < 64; orderID++) {





   static bool read = true;

   uint8_t data[8];

   delay(1000); // wait 1000ms

   lin.order(34, linTXdata, 4, lin2x);

   delay(100);

   CRC = lin.response(39, linRXdata, 8, lin2x);

   lin.response(39, linRXdata, 8, lin2x); //>=0) // -1 indicates crc error, 19200

     {

     tmpheater = linRXdata[1] - 40;

     udcheater = linRXdata[4] | (linRXdata[5] & 3) << 8;

     powerheater =((linRXdata[5] >> 2) | (linRXdata[6] << 8)) * 20;

     //Serial.print("orderID:"); 

     //Serial.print(orderID);

     //Serial.print(",");

     Serial.print("Temp:");

     Serial.print(tmpheater);

     Serial.print(",");

     Serial.print("Udc:");

     Serial.print(udcheater);

     Serial.print(",");

     Serial.print("Power:");

     Serial.println(powerheater);

     Serial.print("CRC:"); 

     Serial.println(CRC);

     Serial.print(linRXdata[0]);

     Serial.print(",");

     Serial.print(linRXdata[1]);

     Serial.print(",");

     Serial.print(linRXdata[2]);

     Serial.print(",");

     Serial.print(linRXdata[2]);

     Serial.print(",");

     Serial.print(linRXdata[4]);

     Serial.print(",");

     Serial.print(linRXdata[5]);

     Serial.print(",");

     Serial.print(linRXdata[6]);

     Serial.print(",");

     Serial.print(linRXdata[7]);

     Serial.print(",");

     Serial.println(linRXdata[8]);

     //Serial.println(data);

  

     }

   //else if (read)

  // {

      lin.order(34, linTXdata, 4, lin2x);

   //}

  // else

   {

      //uint8_t linTXdata[] = {uint8_t(Power/40), uint8_t(Temperature+40), 0, 8};

      lin.order(34, linTXdata, 4, lin2x);

      //Serial.print("\n Sending power and temperature");

   }



   read = !read;

  }

}

with this response:

Code: Select all

orderID:30,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,238,27

orderID:31,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,238,27

orderID:32,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,237,27

orderID:33,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,237,27

orderID:34,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,239,27

orderID:35,Temp:19,Udc:58,Power:320

CRC:0

128,59,0,0,58,64,0,110,27

orderID:36,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,237,27

orderID:37,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,0,58,64,0,237,27
DATA[0] showed 0s until ID 35 and it jumped to 128 at that point. Therefore, I assumed ID34 was causing the change in DATA[0].

I then modified the lin.order command to ID34 with the lin.response on ID39 and water started to heat.

Here is the code I was running:

Code: Select all




#include "lin_bus.h"



// Create an IntervalTimer object

IntervalTimer myTimer;



int ledState = LOW;               // ledState used to set the LED

unsigned long interval = 200000;  // interval at which to blinkLED to run every 0.2 seconds



LIN lin;



uint16_t Power = 400; // set to required power

uint8_t Temperature = 100; //set to required temperature



int lin_cs = 32;  // pin 23 for my LIN board

int led1 = 23;

int lin_fault = 28;



uint8_t linTXdata[4] = { Power, Temperature, 0, 8 };  // 40W, 45C, heater on

uint8_t linRXdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

uint8_t CRC = 0;

uint8_t orderID = 0;

uint8_t responseID = 0;



void setup() {

  pinMode(LED_BUILTIN, OUTPUT);

  pinMode(lin_fault, INPUT);

  pinMode(lin_cs, OUTPUT);

  digitalWrite(lin_cs, HIGH);  // enable MCP2004 LIN transceiver

  digitalWrite(LED_BUILTIN, HIGH);



  Serial.begin(115200);



  lin.begin(&Serial3, 19200);  // or

  //lin.begin(&Serial3, 9600);

  delay(1000);

  pinMode(led1, OUTPUT);

  digitalWrite(LED_BUILTIN, LOW);

}



void loop() {

  //for (orderID = 0; orderID < 64; orderID++) {

    //for (responseID = 0; responseID < 64; responseID++) {



      lin.order(34, linTXdata, 4, lin2x);

      delay(100);



      CRC = lin.response(39, linRXdata, 8, lin2x);

      delay(100);

      Serial.print(34, HEX);

      Serial.print("\t");

      Serial.print(39, HEX);

      Serial.print("\t");

      Serial.println(CRC, HEX);

      for (int i = 0; i < 8; i++) {           // display the raw data

      Serial.print(linRXdata[i]);

      Serial.print("\t");

      Serial.print("\t");

      Serial.print(" ");

      Serial.println();



      delay(10);

    }

  }

//}

//}



Serial Plotter:


Code: Select all

22    27    0

128      

95      

2      

116      

91      

80      

0      

22      

22    27    0

128      

95      

2      

114      

91      

80      

0      

24      

22    27    0

32      

95      

0      

114      

91      

80      

0      

122      

22    27    0

32      

95      

0      

115      

91      

80      

0      

121





22    27    0

32      

89      

0      

117      

89      

80      

0      

127 



22    27    0

32      

88      

0      

115      

88      

80      

0      

131



22    27    0

32      

84      

0      

116      

83      

80      

0      

139      



22    27    0

32      

84      

0      

115      

83      

80      

0      

140



22    27    0

32      

82      

0      

116      

81      

80      

0      

143      



22    27    0

32      

82      

0      

115      

81      

80      

0      

144



22    27    0

32      

80      

0      

116      

80      

80      

0      

146



22    27    0

32      

80      

0      

116      

79      

80      

0      

147



22    27    0

32      

79      

0      

116      

78      

80      

0      

149      





22    27    0

32      

79      

0      

115      

78      

80      

0      

150 

Not sure why the 128 in the first bit drops to 32 at some point, but it did not affect the heating as far as I could tell. You can see that the final bit seems to increase over time and I am pretty sure is the temperature. I pasted examples along the way of the number increasing. With an offset of 40, I assume the temps are between 80 and 110 C. I will need to work on the formulas for the output on serial plotter, but I assume those are just for my knowledge and do not affect the heating of the water.

This was only on the VOLVO HVH50 heater out of a CX90, so I will need to sniff the other heaters for their lin.response ID and then lin.order ID, but now I have the blueprints and steps to do it.

--------------------------

THANK YOU THANK YOU THANK YOU ROYHEN99! I would not have been able to do this without your help. You created the initial coding and talked me though the issues I was having and taught me about hoe to code on my own! Thank you Johan for forging the path on the STM32 version to allow us to have the blueprints we needed. The guys at the Teensy forum were invaluable with the lin2x fix, the linbus.cpp fix, the sketches to sniff out a response ID and just teaching me enough that I could experiment on my own to get to this place.

I will update the wiki page with the info for this VOLVO heater. I have two other heaters (from Chrysler Pacificas I believe) and will try to sniff them out as well and will update the wiki page if I figure them out.
royhen99
Posts: 261
Joined: Sun Feb 20, 2022 4:23 am
Location: N. Wiltshire. UK
Has thanked: 22 times
Been thanked: 130 times

Re: Webasto HVH50

Post by royhen99 »

Good to see that you are getting heat but I think you are looking at the status ID data rather than the measurement ID. From your update in the wiki this seemed a posibility and checking back in some of the previous data there was also a response on ID 23. Maybe check if ID 23 is Read Meas and 39 is Read Status command. Status is 3 bytes so only data[0] to [2] will be valid values.

Couple of other points: you set power to 400 and wrote to an 8 bit variable which has maximum vaule of 255 ( the power set was actually (400-256)*40 = 5760W). The receive array is 8 bytes so only data[0] to data[7] are valid, data[8} is whatever (random) value is in the next memory address.
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

royhen99 wrote: Mon Mar 04, 2024 12:25 am you set power to 400 and wrote to an 8 bit variable
If that is the case, do I need to change it from 8 to 16? The heater can handle up to 5000W on the HVH50 and 7000W on the HVH70.

If I use the max 8 bit value of 255, by the formula of (255-256)*40 = -40, right???
royhen99 wrote: Mon Mar 04, 2024 12:25 am Maybe check if ID 23 is Read Meas and 39 is Read Status command
I will do this for sure and let you know.
royhen99
Posts: 261
Joined: Sun Feb 20, 2022 4:23 am
Location: N. Wiltshire. UK
Has thanked: 22 times
Been thanked: 130 times

Re: Webasto HVH50

Post by royhen99 »

jsimonkeller wrote: Mon Mar 04, 2024 4:58 am If I use the max 8 bit value of 255, by the formula of (255-256)*40 = -40, right???
No, the simplist way it to put the code back to how it was originally with the power sent over LIN the required power / 40.

The 400 - 256 is just truncating a 9 bit number to 8 bits, it's not a general formula for calculating the power. 400 = 0x190, truncating to 8 bits gives 0x90 which is 144, i.e. 400 - 256.
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

I am now convinced I got heated water through dumb luck and wish to re-create it but with solid understanding and the ability to re-create it on command. I went back to the beginning and followed all of our steps again. This time, I used the the scope to help me. At this point, I have confirmed that ID 39 is the Lin Read with 7 bits showing on the scope and ID 23 is the LIN READ STATUS with 3 bits showing. This happens with Lin.Response and the heater powered on with and without HV.
PXL_20240323_221355235.jpg
Now I assumed that 34 was the proper ID for Lin.Order because when I was sending all IDs the day I got heat, the data at byte 0 jumped from 0 to 118 and then held at 32. I have not been able to recreate this, though.

Code: Select all

orderID:33,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,115,58,64,0,237,27

orderID:34,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,115,58,64,0,239,27

orderID:35,Temp:19,Udc:58,Power:320

CRC:0

128,59,0,115,58,64,0,110,27

orderID:36,Temp:19,Udc:58,Power:320

CRC:0

0,59,0,115,58,64,0,237,27
I have tried 34 and 35 with no success. I am now considering whether I should be focusing on how the heater initiates and what I might have done accidentally. I am looking at timing and synch. Looking at the node attributes in the HVH100 LDF file, I see:

Code: Select all

Node_attributes {

  HVH_100{

    LIN_protocol = "2.0" ;
    configured_NAD = 0x5F ;
    product_id = 0x0, 0x0, 0 ;
    response_error = PTC_ResponseError ;
    P2_min = 10 ms ;
    ST_min = 10 ms ;
    configurable_frames {
      HV_He_01 = 0x401C ;
      HV_Hs_01 = 0x4030 ;
      HV_Hs_02 = 0x400C ;
I am not sure if any of this needs to be incorporated into the linbus.h or cpp file or my code that is not already there.

Assuming the LDF for the HVH100 is compatible with the HVH50, the frame structure shows:

Code: Select all

Frames {

  HV_He_01: 28, Controller, 4 {
    KL_HV_PTC_soll, 0 ;
    KL_PTC_ein, 8 ;
  }
  H
  V_Hs_01: 48, HVH_100, 8 {
    PTC_HV_I_ist, 0 ;
    PTC_HV_ERR, 8 ;
    PTC_HV_Status_PTC, 16 ;
    PTC_Status_UBatt, 19 ;
    PTC_ResponseError, 21 ;
    PTC_TimeOut_Fehler, 22 ;
    PTC_HV_Err_Heizkreis_1, 24 ;
    PTC_HV_Err_Heizkreis_2, 25 ;
    PTC_HV_Err_Heizkreis_3, 26 ;
    PTC_HV_Err_Leckagestrom, 27 ;
    PTC_HV_Err_Ueberstromabschaltung, 28 ;
    PTC_HV_Err_Temperaturschutz, 29 ;
    PTC_HV_Err_intern, 30 ;
    PTC_UBatt, 32 ;
    PTC_Temp_PCB, 40 ;
    PTC_HV_Heizmedium_Sensor_1, 48 ;
    PTC_HV_Heizmedium_Sensor_2, 56 ;

  }

  HV_Hs_02: 12, HVH_100, 8 {
    HVH_HV_Voltage, 32 ;
    HVH_HV_Voltage_Offset, 41 ;
    HVH_HV_Ilock_Status, 45 ;
    HVH_ParameterChange, 61 ;
    HVH_ErrMem_State, 62 ;
  }

}

Schedule_tables {
 ST1 {
    HV_He_01 delay 20 ms ;
    HV_Hs_01 delay 20 ms ;
    HV_Hs_02 delay 20 ms ;
  }
 DiagRequest {
    MasterReq delay 10 ms ;
  }
 DiagResponse {
    SlaveResp delay 10 ms ;
  }
}
With my German translator, it would seen that the ON command will appear at BIT 8, which is the first bit of the second Databyte and not the fourth one right?

Anyways, I am wondering if you had any ideas for a sketch to sniff this part out, now that we have definitive response and status IDs and try to cause some reaction on their parts or how to incorporate any of the info from the LDF to help us get a response again.

I also wonder if the 255 lin bit value for the initial/power request value needs to be sent before the heater will turn on?


image.png
espriev
Posts: 57
Joined: Mon Jan 02, 2023 5:32 pm

Re: Webasto HVH50

Post by espriev »

No luck making progress?
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

No luck yet. As it got hot in Nashville TN in May, I have not been in desperate need of heat (more a/c please) but I do not want to let this go until November, when I will need the heat again!
espriev
Posts: 57
Joined: Mon Jan 02, 2023 5:32 pm

Re: Webasto HVH50

Post by espriev »

I am going to open this thing up and trace out the circuit.
As I understand it, all that is happening is there is an IGBT on one side of each PTC element that acts like a switch, connecting it to one side of the HV.
The other side is always connected to the opposite polarity of the HV.
As PTC elements are self regulating, there is no temperature control, it just turns on more elements for more heat.
It may be simple to control the IGBTs with a +12VDC on/off and bypass all the software control, I certainly do not need it.
Webasto actually makes a version that is controlled with +12VDC directly, but good luck finding one to purchase!
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

espriev wrote: Mon Jul 08, 2024 4:55 pm I am going to open this thing up and trace out the circuit.
Just so you know, I did this as well a while back. Here is a photo of the board. I purchased an extra heater at a good price that was sold without warranty it was functioning. I opened in up and started checking for continuity and I was able to identify some of the pathways, such as the HVIL loop and the 12V line pathway to a dead end after the resistor at a small black chip (circled below), which might be the gateway that opens when the proper LIN command is received. I assume this could be bypassed, but I abandoned this in favor of learning how to program the LIN with a sealed unit. I also discovered that there is a GND wire in the 8 wire setup (#8) that I started using with the board outside of the metal case, just to make sure the board was getting a good GND signal. I actually got some sparks with the 12v only attached when the multimeter prong touched across a couple of lines accidentally. I agree that there should be a way to bypass the lockout of 12V on and off that is closed in programming.
PXL_20240218_000602671.jpg
espriev
Posts: 57
Joined: Mon Jan 02, 2023 5:32 pm

Re: Webasto HVH50

Post by espriev »

Thanks for showing that, it looks plenty complicated!
If only they would sell the 12VDC controlled model, or if there were information on what application it was used in...
With the help you have provided I will pursue getting the local college's programming school to take it on as a project.
jsimonkeller
Posts: 80
Joined: Sun Oct 30, 2022 2:21 am
Has thanked: 4 times
Been thanked: 9 times

Re: Webasto HVH50

Post by jsimonkeller »

Hello everyone. I have finally SOLVED the HV heater issue and can set out a path for anyone still trying to incorporate an HV coolant heater into their EV build.

After not having much luck with the various HV50 or HV70 heaters from various companies like Volvo and Chrysler, I looked into other options and found this company and their HV Heater.

https://www.auto-parkingheater.com/elec ... -cars.html Ask for Luda.

The form factor for this HV Heater is almost identical to the Webasto HV50/70, probably a little smaller actually. The cost, including international FedEx shipping to my home in the USA was under $350.00 AND it came with all of the mating connectors, already wired up. The LV connector is identical to the Webasto LV connector. The HV connector is similar to the Webasto one, but has a slightly different key at the top. Also, it is brand new and not harvested from a junked EV.

Best part about this is that it came with the manual and all of the LIN commands and IDs and baud rate and the proper LDF (Lin Description File) and tech support to get things working. I was able to salvage the code we started on this post and completed with the help of folks on the teensy forum site. I ran the final code tonight and it was heating the water on my test bench to 80C.
image.png
Here is the code for anyone that wants to go this route [UPDATED ON 8-19-24]:

Code: Select all

#include "lin_bus.h"

// Create an IntervalTimer object
IntervalTimer myTimer;

int ledState = LOW;               // ledState used to set the LED
unsigned long interval = 200000;  // interval at which to blinkLED to run every 0.2 seconds

uint16_t requestedpower = 0;
uint16_t actualpower = 0;
uint16_t inwatertemp = 0;
uint16_t outwatertemp = 0;
uint16_t lowvoltage = 0;
uint16_t currentconsumption = 0;

LIN lin;

int lin_cs = 32;  // cs and serial port set for skpang LIN / FDCAN board
int led1 = 23; // sk pang board builtin led
int lin_fault = 28;

uint8_t CRC = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(lin_fault, INPUT);
  pinMode(lin_cs, OUTPUT);
  digitalWrite(lin_cs, HIGH);  // enable MCP2004 LIN transceiver
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  //Serial.print("Heater demo");

  lin.begin(&Serial3, 19200);// Baud Rate for the SR02-2 Heater
  delay(100);  // wait 100ms
  pinMode(led1, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  myTimer.begin(blinkLED, interval);
}
  void loop() {
  // heater
  SendLin();
  delay(100); // wait 100ms
  //Serial.print(" Heater test\n");
}
void blinkLED() {
  ledState = !ledState;
  digitalWrite(LED_BUILTIN, ledState);
  digitalWrite(led1, ledState);
}
   static void SendLin()
{
  //static bool read = true;
  uint8_t data[8];
  delay(100); // wait 100ms

  // read ID27 register
  lin.response(0x27, data, 7, lin2x); //
  delay(10);

  // write ID33 register
  uint8_t lindata0[] = { 0x00, 0x10 };  // chechksum 0, counter 0, HvCooltHeatrEnadWhE2EHvchEnad = 1 which is 0x10 Hex
  lin.order(0x33, lindata0, 2, lin2x);
  delay(10);

  // write ID22 register again, HvWtrHeatrPwrCnsAllwd = 6000W based on top voltage of 350V for my car
  uint8_t lindata2[] = { 0x96, 0x78, 0xFF, 0xD0 };  // 6000w power, 80C target temp, max flow, enable
  lin.order(0x22, lindata2, 4, lin2x);
  delay(10);

  // read ID17 register
  lin.response(0x17, data, 3, lin2x);  // we need 10+10 bits according to spec, so request 3 bytes
  {
  requestedpower = data[1] * 20;//(20w/bit) offset
  actualpower = data[0] * 20;//(20w/bit) offset
  Serial.print("RequestedPower:");
  Serial.print(requestedpower);
  Serial.println(",");
  Serial.print("ActualPower:");
  Serial.print(actualpower);
  Serial.println("");
  }

  // read ID27 register
  lin.response(0x27, data, 7, lin2x);  // we need 56 bits according to spec, so request 7 bytes
  inwatertemp = data[4];//(1℃/bit) offset
  outwatertemp = data[1];//(1℃/bit) offset
  lowvoltage = data[3] / 10;//(0.1V/bit) offset
  currentconsumption = data[2] / 4;//(0.25A/bit) offset
  Serial.print("WaterTempIn:");
  Serial.print(inwatertemp);
  Serial.println(",");
  Serial.print("WaterTempOut:");
  Serial.print(outwatertemp);
  Serial.println(",");
  Serial.print("CurrentConsumption:");
  Serial.print(currentconsumption);
  Serial.println(",");
  Serial.print("LowVoltageReading:");
  Serial.print(lowvoltage);
  Serial.println("");
  Serial.println("");
  delay(500);
  }
The code will printout the following info in the serial monitor (below are pulled from the serial monitor at different points in time):

Code: Select all

RequestedPower:3520,
ActualPower:320
WaterTempIn:61,
WaterTempOut:61,
CurrentConsumption:1,
LowVoltageReading:13

RequestedPower:3680,
ActualPower:2180
WaterTempIn:120,
WaterTempOut:122,
CurrentConsumption:6,
LowVoltageReading:13

RequestedPower:1280,
ActualPower:1580
WaterTempIn:123,
WaterTempOut:124,
CurrentConsumption:4,
LowVoltageReading:13

RequestedPower:4000,
ActualPower:980
WaterTempIn:126,
WaterTempOut:127,
CurrentConsumption:3,
LowVoltageReading:12

Attachments
PXL_20240818_231437018.jpg
PXL_20240818_231428014.jpg
Post Reply