Mitsubishi Outlander PHEV heater
Re: Mitsubishi Outlander PHEV heater
Got it working nicely now! Love the display output aswell - very useful!
- Bigpie
- Posts: 1757
- Joined: Wed Apr 10, 2019 8:11 pm
- Location: South Yorkshire, UK
- Has thanked: 80 times
- Been thanked: 410 times
Re: Mitsubishi Outlander PHEV heater
Nice
I am pretty pleased with the display.

BMW E91 2006
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
Re: Mitsubishi Outlander PHEV heater
It’s awesome and great work! I’d like to add a safety delay to switching off the water pump until the temp is back down to say 30 degrees C! Probably have to make it permantly live tho to ensure it runs even when the ignition is switched off. Either that or just get a delayed relay!
-
- Posts: 3554
- Joined: Mon Dec 24, 2018 1:37 pm
- Location: Slovenia
- Has thanked: 131 times
- Been thanked: 330 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
Hm... you could readback the heater CAN temp byte4 and run the pump when temp is higher than X. It would require a transistor and a relay, but you would have a circulation system independant of heat source. I wanted to built similar heating myself. On one side Outlander heater run by a DUE uC and on the other Webasto fuel heater. I wanted to use Webasto pump to also run when Outlander heater would be ON.Turbopete wrote: ↑Thu Dec 29, 2022 8:04 pm It’s awesome and great work! I’d like to add a safety delay to switching off the water pump until the temp is back down to say 30 degrees C! Probably have to make it permantly live tho to ensure it runs even when the ignition is switched off. Either that or just get a delayed relay!
Re: Mitsubishi Outlander PHEV heater
Interesting development today - the heater wouldnt start until the temperature got above -1 degrees C!
Re: Mitsubishi Outlander PHEV heater
I like this idea - it will be my next mini project i think!arber333 wrote: ↑Thu Dec 29, 2022 9:52 pm Hm... you could readback the heater CAN temp byte4 and run the pump when temp is higher than X. It would require a transistor and a relay, but you would have a circulation system independant of heat source. I wanted to built similar heating myself. On one side Outlander heater run by a DUE uC and on the other Webasto fuel heater. I wanted to use Webasto pump to also run when Outlander heater would be ON.
- Bigpie
- Posts: 1757
- Joined: Wed Apr 10, 2019 8:11 pm
- Location: South Yorkshire, UK
- Has thanked: 80 times
- Been thanked: 410 times
Re: Mitsubishi Outlander PHEV heater
Not at computer at min, is the temp feedback unsigned, I made that mistake early on, might not have pushed the change?
BMW E91 2006
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
- EV_Builder
- Posts: 1205
- Joined: Tue Apr 28, 2020 3:50 pm
- Location: The Netherlands
- Has thanked: 18 times
- Been thanked: 37 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
Maybe an takeover relais construction would perform better. So if relais of pump is switched on everything is fed/switched from that relais too.arber333 wrote: ↑Thu Dec 29, 2022 9:52 pm Hm... you could readback the heater CAN temp byte4 and run the pump when temp is higher than X. It would require a transistor and a relay, but you would have a circulation system independant of heat source. I wanted to built similar heating myself. On one side Outlander heater run by a DUE uC and on the other Webasto fuel heater. I wanted to use Webasto pump to also run when Outlander heater would be ON.
In that way when you turn of the car and pump runs it keeps running until it should turn off and everything will turn off then.
Converting an Porsche Panamera
see http://www.wdrautomatisering.nl for bespoke BMS modules.
see http://www.wdrautomatisering.nl for bespoke BMS modules.
-
- Posts: 261
- Joined: Sun Feb 20, 2022 4:23 am
- Location: N. Wiltshire. UK
- Has thanked: 22 times
- Been thanked: 130 times
Re: Mitsubishi Outlander PHEV heater
Temerature is unsigned in the version I have
//temperatures
unsigned int temp1 = msg.buf[3] - 40;
unsigned int temp2 = msg.buf[4] - 40;
//temperatures
unsigned int temp1 = msg.buf[3] - 40;
unsigned int temp2 = msg.buf[4] - 40;
- tom91
- Posts: 2293
- Joined: Fri Mar 01, 2019 9:15 pm
- Location: Bristol
- Has thanked: 199 times
- Been thanked: 524 times
Re: Mitsubishi Outlander PHEV heater
Yes it should be signed, as they have an offset of -40. so if the recieved value is lower then 40 it would just roll over.
- Peter
- Posts: 320
- Joined: Fri Dec 14, 2018 9:07 pm
- Location: North West Lancs, UK
- Been thanked: 9 times
Re: Mitsubishi Outlander PHEV heater
Hi Forum. For anyone interested I took the top off my PHEV heater.... cos I am nosey 
Pics reveal heater connections etc.

Pics reveal heater connections etc.
Re: Mitsubishi Outlander PHEV heater
Probably a very basic question but what does the coolant pump require more than just 12v and ground to run? I can see two signal wires in the loom that go to the VCU but I’m not sure what they do.
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
Does anyone know if the 7807A021 will operate the same?
It is going for a good price here
https://ebay.us/xxCqz2
It is going for a good price here
https://ebay.us/xxCqz2
- Bigpie
- Posts: 1757
- Joined: Wed Apr 10, 2019 8:11 pm
- Location: South Yorkshire, UK
- Has thanked: 80 times
- Been thanked: 410 times
Re: Mitsubishi Outlander PHEV heater
Looks the same as the one I've got in the Beetle.
BMW E91 2006
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
-
- Posts: 3554
- Joined: Mon Dec 24, 2018 1:37 pm
- Location: Slovenia
- Has thanked: 131 times
- Been thanked: 330 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
I used two different P/Ns and they both operate on the same commands.
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
Hi guysTurbopete wrote: ↑Tue Dec 20, 2022 5:17 pm Scratch that last question - i figured out that my code was still wrong! This is the code that i am using now:
Apologies for the untidyness - im learning!Code: Select all
#include <mcp_can.h> #include <SPI.h> #include <TaskScheduler.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // OLED display height, in pixels #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define INVERTPOT true #define OPENINVERTERCONTACTORS //uncomment to check can bus for Open Inverter opmode for contactors, prevents heating over precharge resistor #ifdef OPENINVERTERCONTACTORS unsigned long inverterLastRec; byte inverterStatus; #endif unsigned long temperatureLastRec; #define MAXTEMP 85 #define MINTEMP 40 unsigned int targetTemperature = 0; bool enabled = false; bool hvPresent = false; bool heating = false; int power = 20; int currentTemperature = 0; const int potPin = A0; const int ledPin = 3; long unsigned int canId; unsigned char len = 0; unsigned char buf[8]; char msgString[128]; // Array to store serial string #define CAN_INT 2 // Set INT to pin 2 MCP_CAN CAN(10); // Set CS to pin 10 void ms10Task(); void ms100Task(); void ms1000Task(); Task ms10(10, -1, &ms10Task); Task ms100(100, -1, &ms100Task); Task ms1000(1000, -1, &ms1000Task); Scheduler runner; void setup() { Serial.begin(115200); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } displayOff(); Serial.println("Outlander Heater Control"); pinMode(ledPin, OUTPUT); //while (CAN_OK != CAN.begin(CAN_500KBPS, MCP_8MHz)) // init can bus : baudrate = 500k //while (CAN_OK != CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ)) // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled. if(CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) // Serial.println("MCP2515 Initialized Successfully!"); Serial.println("CAN BUS Shield init ok!"); else // Serial.println("Error Initializing MCP2515..."); Serial.println("CAN BUS Shield init fail"); CAN.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data. pinMode(CAN_INT, INPUT); // Configuring pin for /INT input // Serial.println("MCP2515 Library Receive Example..."); Serial.println("CAN BUS Shield init ok!"); runner.init(); runner.addTask(ms10); ms10.enable(); runner.addTask(ms100); ms100.enable(); runner.addTask(ms1000); ms1000.enable(); } void displayTemperature(void) { display.clearDisplay(); display.setTextSize(3); // Draw 2X-scale text display.setTextColor(SSD1306_WHITE); display.setCursor(20, 10); display.print(currentTemperature); display.print("/"); display.print(targetTemperature); if (power == 2) { display.fillRect(0, 0, 10, SCREEN_HEIGHT, SSD1306_WHITE); } else if (power == 1) { display.fillRect(0, SCREEN_HEIGHT/2, 10, SCREEN_HEIGHT, SSD1306_WHITE); } display.display(); // Show initial text } void displayOff(void) { display.clearDisplay(); display.setTextSize(3); // Draw 2X-scale text display.setTextColor(SSD1306_WHITE); display.setCursor(40, 10); display.println(F("Off")); display.display(); // Show initial text } void ms10Task() { //send 0x285 uint8_t canData[8]; canData[0] = 0x00; canData[1] = 0x00; canData[2] = 0x14; canData[3] = 0x21; canData[4] = 0x90; canData[5] = 0xFE; canData[6] = 0x0C; canData[7] = 0x10; CAN.sendMsgBuf(0x285, 0, sizeof(canData), canData); } void ms100Task() { int sensorValue = analogRead(potPin); if (INVERTPOT) { if (sensorValue < 923) { enabled = true; } else { enabled = false; } } else { if (sensorValue > 100) { enabled = true; } else { enabled = false; } } //if heater is not sending feedback, disable it, safety and that if (millis() - temperatureLastRec > 1000) { enabled = false; Serial.println("No Temperature recieved"); } if (INVERTPOT) { targetTemperature = map(sensorValue, 1023, 100, MINTEMP, MAXTEMP); } else { targetTemperature = map(sensorValue, 100, 1023, MINTEMP, MAXTEMP); } //send 0x188 #ifdef OPENINVERTERCONTACTORS bool contactorsClosed = inverterStatus == 0x01; if (!contactorsClosed) { enabled = false; } #else bool contactorsClosed = true; #endif digitalWrite(ledPin, enabled); if (enabled) { displayTemperature(); } else { displayOff(); } if (contactorsClosed && enabled && currentTemperature < targetTemperature) { uint8_t canData[8]; canData[0] = 0x03; canData[1] = 0x50; canData[3] = 0x4D; canData[4] = 0x00; canData[5] = 0x00; canData[6] = 0x00; canData[7] = 0x00; //switch to lower power when reaching target temperature if (currentTemperature < targetTemperature - 10) { canData[2] = 0xA2; power = 2; } else { canData[2] = 0x32; power = 1; } CAN.sendMsgBuf(0x188, 0, sizeof(canData), canData); } else { power = 0; } } void ms1000Task() { Serial.println("Heater Status"); Serial.print("HV Present: "); Serial.print(hvPresent); Serial.print(" Heater Active: "); Serial.print(heating); Serial.print(" Water Temperature: "); Serial.print(currentTemperature); Serial.println("C"); Serial.println(""); Serial.println("Settings"); Serial.print(" Heating: "); Serial.print(enabled); Serial.print(" Desired Water Temperature: "); Serial.print(targetTemperature); Serial.print(" Inverter: "); Serial.print(inverterStatus); Serial.println(""); Serial.println(""); } void loop() { // put your main code here, to run repeatedly: runner.execute(); //if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming //{ //CAN.readMsgBuf(&canId, &len, buf); // read data, len: data length, buf: data buf //unsigned int canId = CAN.getCanId(); this line can be removed //if (canId == 0x398) { if(!digitalRead(CAN_INT)) // If CAN_INT pin is low, read receive buffer { CAN.readMsgBuf(&canId, &len, buf); // Read data: len = data length, buf = data byte(s) if((canId & 0x80000000) == 0x80000000) // Determine if ID is standard (11 bits) or extended (29 bits) sprintf(msgString, "Extended ID: 0x%.8lX DLC: %1d Data:", (canId & 0x1FFFFFFF), len); else sprintf(msgString, "Standard ID: 0x%.3lX DLC: %1d Data:", canId, len); //Serial.print(msgString); if((canId & 0x40000000) == 0x40000000){ // Determine if message is a remote request frame. sprintf(msgString, " REMOTE REQUEST FRAME"); //Serial.print(msgString); } else { for(byte i = 0; i<len; i++){ sprintf(msgString, " 0x%.2X", buf[i]); //Serial.print(msgString); } } // unsigned int canId = CAN.getCanId(); if (canId == 0x398) { //Heater status if (buf[5] == 0x00) { heating = false; power = 0; } else if (buf[5] > 0) { heating = true; } //hv status if (buf[6] == 0x09) { hvPresent = false; } else if (buf[6] == 0x00) { hvPresent = true; } //temperatures unsigned int temp1 = buf[3] - 40; unsigned int temp2 = buf[4] - 40; if (temp2 > temp1) { currentTemperature = temp2; } else { currentTemperature = temp1; } temperatureLastRec = millis(); } #ifdef OPENINVERTERCONTACTORS if (canId == 0x02) { inverterLastRec = millis(); inverterStatus = buf[0]; } #endif } #ifdef OPENINVERTERCONTACTORS // if(inverterLastRec + 500 < millis()) { // inverterStatus = 0; // } #endif }
My heater has arrived and I'm setting up a test station to confirm I can control it before ripping the car apart. But I need a little guidance with the Arduino side of things as I'm pretty clueless at programming. I have the sketch above from Turbopete on a nano and can see it sending 0285 message so hopefully that bit is OK. This sketch seems to include control for a display but I cannot find any thread showing details of model or how it was connected.
Also can anyone please advise the resistance of the POT and how to connect it? It looks like the wiper of the POT is on A0 but where does the other side go? Is it just 5V?
EDIT: I did a search for Adafruit 128 x 32 OLED displays and found this. https://www.adafruit.com/product/4440
Is this the right one?
Thanks guys
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
I only managed an hour or so at it today but managed to get hot water pumping.
I could see 10A at 250V
I only had a 4k7 pot connected between ground and A0 so not sure if that is suitable as I think the heat requested was around 85C and it wouldn't drop below that. I think I could see a 10k pot in a previous photo from Jamie so I'll dig one out and give it a go. Does this sound correct?

I only had a 4k7 pot connected between ground and A0 so not sure if that is suitable as I think the heat requested was around 85C and it wouldn't drop below that. I think I could see a 10k pot in a previous photo from Jamie so I'll dig one out and give it a go. Does this sound correct?
- Bigpie
- Posts: 1757
- Joined: Wed Apr 10, 2019 8:11 pm
- Location: South Yorkshire, UK
- Has thanked: 80 times
- Been thanked: 410 times
Re: Mitsubishi Outlander PHEV heater
Pot size irrelevant, connect one side to gnd, other to vcc and wiper to A0
BMW E91 2006
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
ZombieVerter
GS450h
Outlander Charger DC/DC
Renault Kangoo 36kWh battery
FOCCCI CCS
-
- Posts: 3554
- Joined: Mon Dec 24, 2018 1:37 pm
- Location: Slovenia
- Has thanked: 131 times
- Been thanked: 330 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
I dont fuss with the pot. I simply use a digital input and internal CAN loop. I use this for the pump too. So when heater temp is lower than 50deg i request full power, when it is at 50deg i lower this to halfh and when heater reaches 55deg i terminate the request. This keeps heater output at 50deg in general which saves kWh acc to Q = m*c*dT. I may up the temp to 60deg if this will not be enough.Alibro wrote: ↑Sun Feb 04, 2024 5:07 pm I only had a 4k7 pot connected between ground and A0 so not sure if that is suitable as I think the heat requested was around 85C and it wouldn't drop below that. I think I could see a 10k pot in a previous photo from Jamie so I'll dig one out and give it a go. Does this sound correct?
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
Thanks guys,
Doing family stuff atm but will have another look later.
Doing family stuff atm but will have another look later.
-
- Posts: 965
- Joined: Sun Feb 23, 2020 9:24 am
- Location: Northern Ireland
- Has thanked: 362 times
- Been thanked: 217 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
It works a treat!!!
I connected the 4k7 pot as instructed and commented out the Openinverter precharge safety checks and it works perfectly with the water temp following the requested temp.
I already have a 12V circuit which only goes live after the main positive contactor kicks in so I'll use that to power the heater when it is installed.
I've also ordered a couple of OLED displays so I'll have a go at getting them to work.
Thanks again guys for your help with this as I'm very much standing on your shoulders here.
I was a little surprised at how hot the case of the heater got and couldn't help thinking it is a pity to loose all that heat but I suspect I'm too late trying to capture it as I would need to have custom designed some kind of enclosure with fans.

I connected the 4k7 pot as instructed and commented out the Openinverter precharge safety checks and it works perfectly with the water temp following the requested temp.
I already have a 12V circuit which only goes live after the main positive contactor kicks in so I'll use that to power the heater when it is installed.
I've also ordered a couple of OLED displays so I'll have a go at getting them to work.
Thanks again guys for your help with this as I'm very much standing on your shoulders here.
I was a little surprised at how hot the case of the heater got and couldn't help thinking it is a pity to loose all that heat but I suspect I'm too late trying to capture it as I would need to have custom designed some kind of enclosure with fans.
My coding skills are virtually zero so now I have it working I think I'll leave well alone.arber333 wrote: ↑Sun Feb 04, 2024 5:31 pm I dont fuss with the pot. I simply use a digital input and internal CAN loop. I use this for the pump too. So when heater temp is lower than 50deg i request full power, when it is at 50deg i lower this to halfh and when heater reaches 55deg i terminate the request. This keeps heater output at 50deg in general which saves kWh acc to Q = m*c*dT. I may up the temp to 60deg if this will not be enough.

-
- Posts: 3554
- Joined: Mon Dec 24, 2018 1:37 pm
- Location: Slovenia
- Has thanked: 131 times
- Been thanked: 330 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
Like i said heater wants to go all the way to 85deg if you let it. Thats a waste of power. I wanted to use a limit to lower this to 55 as the kj are less there = less kWh.
May i use your posted code to setup my loop instead of pot? It should work on any teensy...? Or do you use teensy?
-
- Posts: 3554
- Joined: Mon Dec 24, 2018 1:37 pm
- Location: Slovenia
- Has thanked: 131 times
- Been thanked: 330 times
- Contact:
Re: Mitsubishi Outlander PHEV heater
I went through the code quickly and eliminated anything connected with pot.
I used Heater_pin which is the same pin as A0 analog, only digital side... i think it is D14
Then i removed reading of desired temperature as i find it unneccesary. I removed cconnected conditional as well.
The way this code works is to transmitt complete 0x188 telegram each 100ms. If we toggle the switch to GND(pullup) it will command heater to turn ON. It reads its own temperature and govern the loop by 5deg hysteresis if not turning OFF when reaching 55deg. You can of course set any temperature in code. You could even use the pot to set variable for desired temperature and use a different pin to start the process. I may go and write another code...
See if it works directly as you can load the pot directly to GND to activate the pin with the same circuit. But i would change to toggle switch soon.
I used Heater_pin which is the same pin as A0 analog, only digital side... i think it is D14
Then i removed reading of desired temperature as i find it unneccesary. I removed cconnected conditional as well.
The way this code works is to transmitt complete 0x188 telegram each 100ms. If we toggle the switch to GND(pullup) it will command heater to turn ON. It reads its own temperature and govern the loop by 5deg hysteresis if not turning OFF when reaching 55deg. You can of course set any temperature in code. You could even use the pot to set variable for desired temperature and use a different pin to start the process. I may go and write another code...
See if it works directly as you can load the pot directly to GND to activate the pin with the same circuit. But i would change to toggle switch soon.
Code: Select all
#include <mcp_can.h>
#include <SPI.h>
#include <TaskScheduler.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define INVERTPOT true
#define OPENINVERTERCONTACTORS //uncomment to check can bus for Open Inverter opmode for contactors, prevents heating over precharge resistor
#ifdef OPENINVERTERCONTACTORS
unsigned long inverterLastRec;
byte inverterStatus;
#endif
unsigned long temperatureLastRec;
#define MAXTEMP 85
#define MINTEMP 40
bool enabled = false;
bool hvPresent = false;
bool heating = false;
int power = 20;
uint8_t Heatertemp = 0;
//const int potPin = A0;
const int Heater_pin = D14; //What is the equivalent digital input to A0?
const int ledPin = 3;
long unsigned int canId;
unsigned char len = 0;
unsigned char buf[8];
char msgString[128]; // Array to store serial string
#define CAN_INT 2 // Set INT to pin 2
MCP_CAN CAN(10); // Set CS to pin 10
void ms10Task();
void ms100Task();
void ms1000Task();
Task ms10(10, -1, &ms10Task);
Task ms100(100, -1, &ms100Task);
Task ms1000(1000, -1, &ms1000Task);
Scheduler runner;
void setup() {
Serial.begin(115200);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
displayOff();
Serial.println("Outlander Heater Control");
pinMode(ledPin, OUTPUT);
pinMode(Heater_pin,INPUT_PULLUP); // set Heater pin to input with using built in pull up resistor
//while (CAN_OK != CAN.begin(CAN_500KBPS, MCP_8MHz)) // init can bus : baudrate = 500k
//while (CAN_OK != CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ))
// Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
if(CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
// Serial.println("MCP2515 Initialized Successfully!");
Serial.println("CAN BUS Shield init ok!");
else
// Serial.println("Error Initializing MCP2515...");
Serial.println("CAN BUS Shield init fail");
CAN.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data.
pinMode(CAN_INT, INPUT); // Configuring pin for /INT input
// Serial.println("MCP2515 Library Receive Example...");
Serial.println("CAN BUS Shield init ok!");
runner.init();
runner.addTask(ms10);
ms10.enable();
runner.addTask(ms100);
ms100.enable();
runner.addTask(ms1000);
ms1000.enable();
}
void displayTemperature(void) {
display.clearDisplay();
display.setTextSize(3); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 10);
display.print(currentTemperature);
display.print("/");
// display.print(targetTemperature);
if (power == 2) {
display.fillRect(0, 0, 10, SCREEN_HEIGHT, SSD1306_WHITE);
} else if (power == 1) {
display.fillRect(0, SCREEN_HEIGHT/2, 10, SCREEN_HEIGHT, SSD1306_WHITE);
}
display.display(); // Show initial text
}
void displayOff(void) {
display.clearDisplay();
display.setTextSize(3); // Draw 2X-scale text
display.setTextColor(SSD1306_WHITE);
display.setCursor(40, 10);
display.println(F("Off"));
display.display(); // Show initial text
}
void ms10Task() {
//send 0x285
uint8_t canData[8];
canData[0] = 0x00;
canData[1] = 0x00;
canData[2] = 0x14;
canData[3] = 0x21;
canData[4] = 0x90;
canData[5] = 0xFE;
canData[6] = 0x0C;
canData[7] = 0x10;
CAN.sendMsgBuf(0x285, 0, sizeof(canData), canData);
}
void ms100Task() {
int sensorValue = analogRead(potPin);
// if (INVERTPOT) {
// if (sensorValue < 923) {
// enabled = true;
// } else {
// enabled = false;
// }
// } else {
// if (sensorValue > 100) {
// enabled = true;
// } else {
// enabled = false;
// }
// }
//if heater is not sending feedback, disable it, safety and that
if (millis() - temperatureLastRec > 1000) {
enabled = false;
Serial.println("No Temperature recieved");
}
// if (INVERTPOT) {
// targetTemperature = map(sensorValue, 1023, 100, MINTEMP, MAXTEMP);
// } else {
// targetTemperature = map(sensorValue, 100, 1023, MINTEMP, MAXTEMP);
// }
//send 0x188
#ifdef OPENINVERTERCONTACTORS
bool contactorsClosed = inverterStatus == 0x01;
if (!contactorsClosed) {
enabled = false;
}
#else
bool contactorsClosed = true;
#endif
digitalWrite(ledPin, enabled);
if (enabled) {
displayTemperature();
} else {
displayOff();
}
if (contactorsClosed && enabled) {
uint8_t canData[8];
if(digitalRead(Heater_pin) == LOW) { // if heater pin is ON
canData[0] = 0x03; }
else {
canData[0] = 0x00;
}
canData[1] = 0x50;
if(Heatertemp > 55) { // if temp is higher than 55deg
canData[2] = 0x00;
}
else if(Heatertemp > 50) { // if temp is higher than 50deg
canData[2] = 0x32; // seems to be current command (dec/10)
}
else {
canData[2] = 0xA2;
}
canData[3] = 0x40;
canData[4] = 0x00;
canData[5] = 0x00;
canData[6] = 0x00;
canData[7] = 0x00;
CAN.sendMsgBuf(0x188, 0, sizeof(canData), canData);
} else {
power = 0;
}
}
void ms1000Task() {
Serial.println("Heater Status");
Serial.print("HV Present: ");
Serial.print(hvPresent);
Serial.print(" Heater Active: ");
Serial.print(heating);
Serial.print(" Water Temperature: ");
Serial.print(Heatertemp);
Serial.println("C");
Serial.println("");
Serial.println("Settings");
Serial.print(" Heating: ");
Serial.print(enabled);
Serial.print(" Inverter: ");
Serial.print(inverterStatus);
Serial.println("");
Serial.println("");
}
void loop() {
// put your main code here, to run repeatedly:
runner.execute();
//if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
//{
//CAN.readMsgBuf(&canId, &len, buf); // read data, len: data length, buf: data buf
//unsigned int canId = CAN.getCanId(); this line can be removed
//if (canId == 0x398) {
if(!digitalRead(CAN_INT)) // If CAN_INT pin is low, read receive buffer
{
CAN.readMsgBuf(&canId, &len, buf); // Read data: len = data length, buf = data byte(s)
if((canId & 0x80000000) == 0x80000000) // Determine if ID is standard (11 bits) or extended (29 bits)
sprintf(msgString, "Extended ID: 0x%.8lX DLC: %1d Data:", (canId & 0x1FFFFFFF), len);
else
sprintf(msgString, "Standard ID: 0x%.3lX DLC: %1d Data:", canId, len);
//Serial.print(msgString);
if((canId & 0x40000000) == 0x40000000){ // Determine if message is a remote request frame.
sprintf(msgString, " REMOTE REQUEST FRAME");
//Serial.print(msgString);
} else {
for(byte i = 0; i<len; i++){
sprintf(msgString, " 0x%.2X", buf[i]);
//Serial.print(msgString);
}
}
// unsigned int canId = CAN.getCanId();
if (canId == 0x398) {
//Heater status
if (buf[5] == 0x00) {
heating = false;
power = 0;
} else if (buf[5] > 0) {
heating = true;
}
//hv status
if (buf[6] == 0x09) {
hvPresent = false;
} else if (buf[6] == 0x00) {
hvPresent = true;
}
//temperatures
unsigned int temp1 = buf[3] - 40;
unsigned int temp2 = buf[4] - 40;
if (temp2 > temp1) {
Heatertemp = temp2;
} else {
Heatertemp = temp1;
}
temperatureLastRec = millis();
}
#ifdef OPENINVERTERCONTACTORS
if (canId == 0x02) {
inverterLastRec = millis();
inverterStatus = buf[0];
}
#endif
}
#ifdef OPENINVERTERCONTACTORS
#endif
}