PTC Heater Programming Help / Arduino Teensy 4.0

jsimonkeller

Well-known member
Hello all. I am new to the forum and have reviewed several posts and have not found exactly what I am looking for.

I have built an electric car out of an old Porsche 911 (1978) and I am implementing the Webasto HVH50 high voltage coolant heater into my build. I had been using an older PTC heater running off PWM, but that heater takes up too much space and stopped working and the Webasto fits nicely under the hood as an upgrade. Unfortunately, the Webasto HVH heaters are mostly run off LIN. Finding a PWM version has proven difficult, so I have given up on that route.

Additionally, there a wiki page on this heater with a lot of the same info:

https://openinverter.org/wiki/Webasto_HVH50

At the suggestion of the OpenInverter.Org moderator, I secured the Teensy 4.0 CAN FD And LIN Bus Breakout Board from SK Pang and have installed the Arduino IDE software, I am able to run the simple programming on my board, such as the LED blink speed and such, so I know everything is working as it should.

HERE IS MY ASK:

I would like to implement the LIN BUS programming into the TEENSY controller such that when I push the heater button in my car that turns on the 12V power to the WEBASTO and 5V power to the TEENSY, the heater will kick in and heat the coolant. I DO NOT NEED TO CONTROL THE TEMP. I just need it to kick on and it will heat to the maximum allowable heat until turned off. I also do NOT need any feedback for gauges or controls. This controller will NOT be a part of the overall CAN Network on the car that controls the gauges and Tesla inverter and Orion BMS. It will be standalone and solely function to TRANSMIT the frames to the heater to engage in heating the coolant. This heater is on a separate coolant loop from the rest of the car's cooling systems. It is truly standalone.

For the heater, we have determined the following:

- Byte 0 sets the power with a scaling factor of 40
- Byte 1 set the temperature setpoint in °C with an offset of 40
- Byte 2 is unused
- Byte 3 =8 heater on (i.e. bit 3 set)
- Baud Rate is 9600

The moderator of OI has implemented this programming into his stm32 software under the volvo branch on github.

The portion of the programming related to the heater command is as follows:

#include "linbus.h"

static LinBus* lin;

static void SendLin()
{
static bool read = true;

if (lin->HasReceived(22, 8))
{
uint8_t* data = lin->GetReceivedBytes();

Param::SetInt(Param::tmpheater, data[1] - 40);
Param::SetInt(Param::udcheater, data[4] | ((data[5] & 3) << 8));
Param::SetFlt(Param::powerheater, FP_FROMINT(((data[5] >> 2) | (data[6] << 8)) * 20) / 1000);
}

if (read)
{
lin->Request(22, 0, 0);
}
else
{
uint8_t lindata[4];
lindata[0] = Param::GetInt(Param::heatpowmax) / 40;
lindata[1] = Param::GetInt(Param::heatmax) + 40;
lindata[2] = 0;
lindata[3] = Param::GetInt(Param::eek:pmode) == MOD_RUN ? 8 : 0;

lin->Request(21, lindata, sizeof(lindata));
}

read = !read;
}

Obviously, I cannot just paste this into a sketch on IDE, so I would like to figure out how to take the above and create a loop that sends this static data to the heater as long as the teensy is powered on. I would love any direction anyone can provide to help me implement this programming.

As it is kicking into cold winter weather for me, I would like to be able to use the car in the coming months when things get nasty outside.

Thank you in advance.

jsimonkeller
 
Have you looked at the library below? It seems to be pretty well documented and there are examples of sending byte-oriented messages to a LIN slave. You should be able to translate the STM32 example into function calls for the Teensy library. When you post code, please use the "Code" formatting feature of the forum, so the indentation is preserved.

 
Thank you very much for the prompt rely and suggestion. Apologies for missing the "Code" formatting and will avoid that in the future.
 
Have you looked at the library below? It seems to be pretty well documented and there are examples of sending byte-oriented messages to a LIN slave. You should be able to translate the STM32 example into function calls for the Teensy library. When you post code, please use the "Code" formatting feature of the forum, so the indentation is preserved.
I wanted to keep everyone up to date on my progress. I used the examples to create some code that compiles (with warnings) and have been tweaking it, but I am not getting hot water. I am trying both the 9600 and 19200 baud rate.

Below is the code as it stands in case anyone sees anything that stands out to them.

Code:
  #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 Power = 175; // set to required power
uint8_t Temperature = 45; //set to required temperature
uint16_t tmpheater = 0;
uint16_t udcheater = 0;
uint16_t powerheater = 0;

LIN lin;

int lin_cs = 32; // set this to actual pin number used

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(lin_cs, OUTPUT);
  digitalWrite(lin_cs, HIGH);
 
  //Serial.begin(19200);
  //Serial.print("HVH50 Heater demo");
 
  myTimer.begin(blinkLED, interval);

  LIN l(&Serial1, 19200);
  lin = l;
 
}

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

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

  static void SendLin()
{
   static bool read = true;
   //int received = -1;
   uint8_t data[8];
if (lin.response(22, data, 8) >=0) // -1 indicates crc error
      {
         tmpheater = data[1] - 40;
         udcheater = data[4] | (data[5] & 3) << 8;
         powerheater =((data[5] >> 2) | (data[6] << 8)) * 20;
         Serial.print("\n Temp ");
         Serial.print(tmpheater);
         Serial.print("\n Udc ");
         Serial.print(udcheater);
         Serial.print("\n Power ");
         Serial.print(powerheater);
      }
   if (read)
   {
      lin.order(22, 0, 0);
   }
   else
   {
        uint8_t lindata[] = {(Power/40), (Temperature+40), 0, 8};
          lin.order(21, lindata, 4);
      Serial.print("\n Sending power and temperature");
   }

   read = !read;
}

If anyone sees anything that might be out of whack, let me know.

Attached is the PDF to the WEBASTO heater LIN function if you are interested.
 

Attachments

  • Webasto Lin.pdf
    228.6 KB · Views: 48
Looked through both LIN Description Files that you shared in message #101, buth ID 39 (DEC), 27 (HEX) is not mentioned as an ID that returns data (or can be sent data to, for that matter).

I was reviewing that as well. Of course, it is the earlier version of lin (lin 2.0), so not sure if that changes the lin2.x checksum or it would be same.

It is interesting though that all 3 heaters return a different CRC value. It could mean that we have to deal with 3 different firmware versions, which is not to our advantage.
Hopefully not, but I would assume the manual is accurate as a framework and the only changes would be their choices of which IDs to use and possibly the On/Off number. I guess we could build something to check for these on all IDs.

It would be nice if your source of the HVH100 LDF, also has an LDF of the HVH50.

I know! I asked at that forum, but no responses and I did a search on google, but nothing is coming up. Seems like there must be a repository somewhere!!!
 
Back
Top