394 lines
12 KiB
C++
394 lines
12 KiB
C++
/*
|
|
; Project: Open Vehicle Monitor System
|
|
; Date: 29th December 2017
|
|
;
|
|
; (C) 2017 Geir Øyvind Vælidalo <geir@validalo.net>
|
|
;
|
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
; of this software and associated documentation files (the "Software"), to deal
|
|
; in the Software without restriction, including without limitation the rights
|
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
; copies of the Software, and to permit persons to whom the Software is
|
|
; furnished to do so, subject to the following conditions:
|
|
;
|
|
; The above copyright notice and this permission notice shall be included in
|
|
; all copies or substantial portions of the Software.
|
|
;
|
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
; THE SOFTWARE.
|
|
*/
|
|
#include "vehicle_kiasoulev.h"
|
|
|
|
static const char *TAG = "v-kiasoulev";
|
|
|
|
/**
|
|
* Incoming poll reply messages
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingPollReply(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
//ESP_LOGW(TAG, "%03x TYPE:%x PID:%02x %x %02x %02x %02x %02x %02x %02x %02x %02x", m_poll_moduleid_low, type, pid, length, data[0], data[1], data[2], data[3],
|
|
// data[4], data[5], data[6], data[7]);
|
|
switch (m_poll_moduleid_low)
|
|
{
|
|
// ****** SJB *****
|
|
case 0x779:
|
|
IncomingSJB(bus, type, pid, data, length, mlremain);
|
|
break;
|
|
|
|
// ****** OBC ******
|
|
case 0x79c:
|
|
IncomingOBC(bus, type, pid, data, length, mlremain);
|
|
break;
|
|
|
|
// ****** TPMS ******
|
|
case 0x7de:
|
|
IncomingTPMS(bus, type, pid, data, length, mlremain);
|
|
break;
|
|
|
|
// ******* VMCU ******
|
|
case 0x7ea:
|
|
IncomingVMCU(bus, type, pid, data, length, mlremain);
|
|
break;
|
|
|
|
// ***** BMC ****
|
|
case 0x7ec:
|
|
IncomingBMC(bus, type, pid, data, length, mlremain);
|
|
break;
|
|
|
|
// ***** LDC ****
|
|
case 0x7cd:
|
|
IncomingLDC(bus, type, pid, data, length, mlremain);
|
|
break;
|
|
|
|
default:
|
|
ESP_LOGD(TAG, "Unknown module: %03x", m_poll_moduleid_low);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming messages from TPMS poll.
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingTPMS(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
uint8_t bVal;
|
|
uint32_t lVal;
|
|
|
|
switch (pid)
|
|
{
|
|
case 0x06:
|
|
if (m_poll_ml_frame == 0)
|
|
{
|
|
lVal = CAN_UINT32(4);
|
|
SET_TPMS_ID(0, lVal);
|
|
}
|
|
else if (m_poll_ml_frame == 1)
|
|
{
|
|
bVal = CAN_BYTE(0);
|
|
if (bVal > 0) StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, TO_PSI(bVal), PSI);
|
|
StdMetrics.ms_v_tpms_temp->SetElemValue(MS_V_TPMS_IDX_FL, TO_CELCIUS(CAN_BYTE(1)), Celcius);
|
|
lVal = (kia_tpms_id[1] & 0x000000ff) | (CAN_UINT32(4) & 0xffffff00);
|
|
SET_TPMS_ID(1, lVal);
|
|
}
|
|
else if (m_poll_ml_frame == 2)
|
|
{
|
|
lVal = (uint32_t) CAN_BYTE(0) | (kia_tpms_id[1] & 0xffffff00);
|
|
SET_TPMS_ID(1, lVal);
|
|
bVal = CAN_BYTE(1);
|
|
if (bVal > 0) StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, TO_PSI(bVal), PSI);
|
|
StdMetrics.ms_v_tpms_temp->SetElemValue(MS_V_TPMS_IDX_FR, TO_CELCIUS(CAN_BYTE(2)), Celcius);
|
|
lVal = (kia_tpms_id[2] & 0x0000ffff) | (CAN_UINT32(5) & 0xffff0000);
|
|
SET_TPMS_ID(2, lVal);
|
|
|
|
}
|
|
else if (m_poll_ml_frame == 3)
|
|
{
|
|
lVal = ((uint32_t) CAN_UINT(0)) | (kia_tpms_id[2] & 0xffff0000);
|
|
SET_TPMS_ID(2, lVal);
|
|
bVal = CAN_BYTE(2);
|
|
if (bVal > 0) StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, TO_PSI(bVal), PSI);
|
|
StdMetrics.ms_v_tpms_temp->SetElemValue(MS_V_TPMS_IDX_RL, TO_CELCIUS(CAN_BYTE(3)), Celcius);
|
|
lVal = (kia_tpms_id[3] & 0x00ffffff) | ((uint32_t) CAN_BYTE(6) << 24);
|
|
SET_TPMS_ID(3, lVal);
|
|
|
|
} else if (m_poll_ml_frame == 4) {
|
|
lVal = (CAN_UINT24(0)) | (kia_tpms_id[3] & 0xff000000);
|
|
SET_TPMS_ID(3, lVal);
|
|
bVal = CAN_BYTE(3);
|
|
if (bVal > 0) StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, TO_PSI(bVal), PSI);
|
|
StdMetrics.ms_v_tpms_temp->SetElemValue(MS_V_TPMS_IDX_RR, TO_CELCIUS(CAN_BYTE(4)), Celcius);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming messages from On Board Charger-poll
|
|
*
|
|
* - OBC-voltage
|
|
* - Pilot signal duty cycle
|
|
* - Charger temperature
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingOBC(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
switch (pid)
|
|
{
|
|
case 0x02:
|
|
if (m_poll_ml_frame == 1)
|
|
{
|
|
kia_obc_ac_voltage = (float) CAN_UINT(2) / 10.0;
|
|
//} else if (vehicle_poll_ml_frame == 2) {
|
|
//ks_obc_ampere = ((UINT) can_databuffer[4 + CAN_ADJ] << 8)
|
|
// | (UINT) can_databuffer[5 + CAN_ADJ];
|
|
}
|
|
else if (m_poll_ml_frame == 2)
|
|
{
|
|
m_obc_pilot_duty->SetValue( (float) CAN_BYTE(6) / 3.0 );
|
|
}
|
|
else if (m_poll_ml_frame == 3)
|
|
{
|
|
StdMetrics.ms_v_charge_temp->SetValue( (float) (CAN_BYTE(0)+CAN_BYTE(1)+CAN_BYTE(2))/3, Celcius );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming messages from VMCU-poll
|
|
*
|
|
* - Gear shifter position
|
|
* - VIN
|
|
* - RPM
|
|
* - Motor temperature
|
|
* - Inverter temperature
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingVMCU(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
INT base;
|
|
uint8_t bVal;
|
|
|
|
switch (pid)
|
|
{
|
|
case 0x00:
|
|
if (m_poll_ml_frame == 1)
|
|
{
|
|
ks_shift_bits.value = CAN_BYTE(3);
|
|
}
|
|
break;
|
|
|
|
case 0x02:
|
|
// VIN (multi-line response):
|
|
if (type == VEHICLE_POLL_TYPE_OBDIIVEHICLE)
|
|
{
|
|
base = m_poll_ml_offset - length;
|
|
|
|
for (bVal = 0; (bVal < length) && ((base + bVal)<sizeof (m_vin)); bVal++)
|
|
if(base+bVal>0) m_vin[base + bVal-1] = CAN_BYTE(bVal);
|
|
if (m_poll_ml_remain == 0 && base+bVal>=0) m_vin[base + bVal] = 0;
|
|
|
|
//Set VIN
|
|
StandardMetrics.ms_v_vin->SetValue(m_vin);
|
|
}
|
|
if (type == VEHICLE_POLL_TYPE_OBDIIGROUP)
|
|
{
|
|
if (m_poll_ml_frame == 1)
|
|
{
|
|
//StdMetrics.ms_v_mot_rpm->SetValue( ((uint16_t)CAN_BYTE(5)<<8) | (uint16_t)CAN_BYTE(6) );
|
|
}
|
|
else if (m_poll_ml_frame == 3)
|
|
{
|
|
StdMetrics.ms_v_mot_temp->SetValue( TO_CELCIUS(CAN_BYTE(4)), Celcius);
|
|
StdMetrics.ms_v_inv_temp->SetValue( TO_CELCIUS(CAN_BYTE(5)), Celcius );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming messages from BMC-poll
|
|
*
|
|
* - Pilot signal available
|
|
* - ChaDeMo / J1772
|
|
* - Battery current
|
|
* - Battery voltage
|
|
* - Battery module temp 1-8
|
|
* - Cell voltage max / min + cell #
|
|
* + more
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingBMC(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
UINT base;
|
|
uint8_t bVal;
|
|
|
|
switch (pid)
|
|
{
|
|
case 0x01:
|
|
// diag page 01: skip first frame (no data)
|
|
if (m_poll_ml_frame > 0) {
|
|
if (m_poll_ml_frame == 1) // 02 21 01 - 21
|
|
{
|
|
m_c_power->SetValue( (float)CAN_UINT(1)/100.0, kW);
|
|
bVal = CAN_BYTE(5);
|
|
StdMetrics.ms_v_charge_pilot->SetValue((bVal & 0x80) > 0);
|
|
ks_charge_bits.ChargingChademo = ((bVal & 0x40) > 0);
|
|
ks_charge_bits.ChargingJ1772 = ((bVal & 0x20) > 0);
|
|
ks_battery_current = (ks_battery_current & 0x00FF)
|
|
| ((UINT) CAN_BYTE(6) << 8);
|
|
}
|
|
else if (m_poll_ml_frame == 2) // 02 21 01 - 22
|
|
{
|
|
ks_battery_current = (ks_battery_current & 0xFF00) | (UINT) CAN_BYTE(0);
|
|
StdMetrics.ms_v_bat_current->SetValue((float)ks_battery_current/10.0, Amps);
|
|
StdMetrics.ms_v_bat_voltage->SetValue((float)CAN_UINT(1)/10.0, Volts);
|
|
StdMetrics.ms_v_bat_power->SetValue(StdMetrics.ms_v_bat_current->AsFloat(Amps)*StdMetrics.ms_v_bat_voltage->AsFloat(Volts), Watts);
|
|
BmsRestartCellTemperatures();
|
|
BmsSetCellTemperature(0, CAN_BYTE(3));
|
|
BmsSetCellTemperature(1, CAN_BYTE(4));
|
|
BmsSetCellTemperature(2, CAN_BYTE(5));
|
|
BmsSetCellTemperature(3, CAN_BYTE(6));
|
|
StdMetrics.ms_v_bat_temp->SetValue(((float)CAN_BYTE(3) + CAN_BYTE(4) +
|
|
CAN_BYTE(5) + CAN_BYTE(6)) / 4.0, Celcius);
|
|
|
|
}
|
|
else if (m_poll_ml_frame == 3) // 02 21 01 - 23
|
|
{
|
|
BmsSetCellTemperature(4, CAN_BYTE(0));
|
|
BmsSetCellTemperature(5, CAN_BYTE(1));
|
|
BmsSetCellTemperature(6, CAN_BYTE(2));
|
|
BmsSetCellTemperature(7, CAN_BYTE(4));
|
|
//TODO What about the 30kWh-version?
|
|
|
|
m_b_cell_volt_max->SetValue((float)CAN_BYTE(5)/50.0, Volts);
|
|
m_b_cell_volt_max_no->SetValue(CAN_BYTE(6));
|
|
|
|
}
|
|
else if (m_poll_ml_frame == 4) // 02 21 01 - 24
|
|
{
|
|
m_b_cell_volt_min->SetValue((float)CAN_BYTE(0)/50.0, Volts);
|
|
m_b_cell_volt_min_no->SetValue(CAN_BYTE(1));
|
|
ks_battery_fan_feedback = CAN_BYTE(2);
|
|
ks_charge_bits.FanStatus = CAN_BYTE(3) & 0xF;
|
|
StdMetrics.ms_v_bat_12v_voltage->SetValue ((float)CAN_BYTE(4)/10.0 , Volts);
|
|
kia_battery_cum_charge_current = (kia_battery_cum_charge_current & 0x0000FFFF) | ((uint32_t) CAN_UINT(5) << 16);
|
|
|
|
}
|
|
else if (m_poll_ml_frame == 5) // 02 21 01 - 25
|
|
{
|
|
kia_battery_cum_charge_current = (kia_battery_cum_charge_current & 0xFFFF0000) | ((uint32_t) CAN_UINT(0));
|
|
kia_battery_cum_discharge_current = CAN_UINT32(2);
|
|
kia_battery_cum_charge = (kia_battery_cum_charge & 0x00FFFFFF) | ((uint32_t) CAN_BYTE(6)) << 24;
|
|
}
|
|
else if (m_poll_ml_frame == 6) // 02 21 01 - 26
|
|
{
|
|
kia_battery_cum_charge = (kia_battery_cum_charge & 0xFF000000) | ((uint32_t) CAN_UINT24(0));
|
|
kia_battery_cum_discharge = CAN_UINT32(3);
|
|
}
|
|
else if (m_poll_ml_frame == 7) // 02 21 01 - 27
|
|
{
|
|
kia_battery_cum_op_time = CAN_UINT32(0) / 3600;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x02: //Cell voltages
|
|
case 0x03:
|
|
case 0x04:
|
|
// diag page 02-04: skip first frame (no data)
|
|
if(m_poll_ml_frame==0 && pid==2) BmsRestartCellVoltages();
|
|
if(m_poll_ml_frame>0)
|
|
{
|
|
base = ((pid-2)*32) + (m_poll_ml_frame-1) * 7;
|
|
for (bVal = 0; bVal < length && ((base + bVal)<96); bVal++)
|
|
{
|
|
//ESP_LOGI(TAG, "[%d %d] = %f", pid, base+bVal, (float)CAN_BYTE(bVal) * 0.02);
|
|
BmsSetCellVoltage((uint8_t)(base + bVal), (float)CAN_BYTE(bVal) * 0.02);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x05:
|
|
if (m_poll_ml_frame == 1)
|
|
{
|
|
base = 95;
|
|
for (bVal = 0; bVal < length && ((base + bVal)<96); bVal++)
|
|
{
|
|
if(CAN_BYTE(bVal)!=0 ) // For 30kWh version.
|
|
{
|
|
//ESP_LOGI(TAG, "[%d %d] = %f", pid, base+bVal, (float)CAN_BYTE(bVal) * 0.02);
|
|
BmsSetCellVoltage((uint8_t)(base + bVal), (float)CAN_BYTE(bVal) * 0.02);
|
|
}
|
|
}
|
|
|
|
m_b_inlet_temperature->SetValue( CAN_BYTE(5) );
|
|
m_b_min_temperature->SetValue( CAN_BYTE(6) );
|
|
}
|
|
else if (m_poll_ml_frame == 2)
|
|
{
|
|
m_b_max_temperature->SetValue( CAN_BYTE(0) );
|
|
}
|
|
else if (m_poll_ml_frame == 3)
|
|
{
|
|
//ks_air_bag_hwire_duty = can_databuffer[5 + CAN_ADJ];
|
|
m_b_heat_1_temperature->SetValue( CAN_BYTE(5) );
|
|
m_b_heat_2_temperature->SetValue( CAN_BYTE(6) );
|
|
}
|
|
else if (m_poll_ml_frame == 4)
|
|
{
|
|
m_b_cell_det_max->SetValue( (float)CAN_UINT(0)/10.0 );
|
|
m_b_cell_det_max_no->SetValue( CAN_BYTE(2) );
|
|
m_b_cell_det_min->SetValue( (float)CAN_UINT(3)/10.0 );
|
|
m_b_cell_det_min_no->SetValue( CAN_BYTE(5) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming messages from LDC-poll
|
|
*
|
|
* - LDC out voltage
|
|
* - LDC out current
|
|
* - LDC in voltage
|
|
* - LDC temperature
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingLDC(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
switch (pid)
|
|
{
|
|
case 0x01:
|
|
// 12V system
|
|
ks_ldc_enabled = (CAN_BYTE(0) & 0x07) != 0;
|
|
if( CAN_BYTE(0)==0x07 )
|
|
{
|
|
m_ldc_out_voltage->SetValue( CAN_BYTE(1) / 10.0 );
|
|
m_ldc_out_current->SetValue( CAN_BYTE(2) );
|
|
m_ldc_in_voltage->SetValue( CAN_BYTE(3) * 2 );
|
|
m_ldc_temperature->SetValue( CAN_BYTE(4) - 100 );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming messages from SJB-poll
|
|
*/
|
|
void OvmsVehicleKiaSoulEv::IncomingSJB(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
|
|
{
|
|
//ESP_LOGW(TAG, "779X %02x %02x %02x %02x %02x %02x %02x %02x %02x", pid, m_poll_ml_frame, CAN_BYTE(0), CAN_BYTE(1), CAN_BYTE(2), CAN_BYTE(3), CAN_BYTE(4), CAN_BYTE(5), CAN_BYTE(6));
|
|
switch (pid)
|
|
{
|
|
case 0x04:
|
|
if (m_poll_ml_frame == 1)
|
|
{
|
|
//ESP_LOGW(TAG, "779 8 21 %02x %02x %02x %02x %02x %02x %02x", CAN_BYTE(0), CAN_BYTE(1), CAN_BYTE(2), CAN_BYTE(3), CAN_BYTE(4), CAN_BYTE(5), CAN_BYTE(6));
|
|
}
|
|
break;
|
|
}
|
|
}
|