159 lines
5.8 KiB
C++
159 lines
5.8 KiB
C++
|
/*
|
||
|
; Project: Open Vehicle Monitor System
|
||
|
; Date: 1th October 2018
|
||
|
;
|
||
|
; Changes:
|
||
|
; 1.0 Initial release
|
||
|
;
|
||
|
; (C) 2018 Martin Graml
|
||
|
; (C) 2019 Thomas Heuer
|
||
|
;
|
||
|
; 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.
|
||
|
;
|
||
|
; Most of the CAN Messages are based on https://github.com/MyLab-odyssey/ED_BMSdiag
|
||
|
; http://ed.no-limit.de/wiki/index.php/Hauptseite
|
||
|
|
||
|
const PROGMEM uint32_t rqID_BMS = 0x79B;
|
||
|
const PROGMEM uint32_t respID_BMS = 0x7BB;
|
||
|
const PROGMEM byte rqPartNo[2] = {0x21, 0xEF};
|
||
|
const PROGMEM byte rqIDpart[2] = {0x21, 0x80};
|
||
|
const PROGMEM byte rqBattHealth[2] = {0x21, 0x61};
|
||
|
const PROGMEM byte rqBattLimits[2] = {0x21, 0x01};
|
||
|
const PROGMEM byte rqBattHVContactorCycles[2] = {0x21, 0x02};
|
||
|
const PROGMEM byte rqBattState[2] = {0x21, 0x07};
|
||
|
const PROGMEM byte rqBattSOC[2] = {0x21, 0x08};
|
||
|
const PROGMEM byte rqBattSOCrecal[2] = {0x21, 0x25};
|
||
|
const PROGMEM byte rqBattTemperatures[2] = {0x21, 0x04};
|
||
|
const PROGMEM byte rqBattVoltages_P1[2] = {0x21, 0x41};
|
||
|
const PROGMEM byte rqBattVoltages_P2[2] = {0x21, 0x42};
|
||
|
const PROGMEM byte rqBattOCV_Cal[2] = {0x21, 0x05};
|
||
|
const PROGMEM byte rqBattCellResistance_P1[2] = {0x21, 0x10};
|
||
|
const PROGMEM byte rqBattCellResistance_P2[2] = {0x21, 0x11};
|
||
|
const PROGMEM byte rqBattIsolation[2] = {0x21, 0x29};
|
||
|
const PROGMEM byte rqBattMeas_Capacity[2] = {0x21, 0x0B};
|
||
|
const PROGMEM byte rqBattSN[2] = {0x21, 0xA0};
|
||
|
const PROGMEM byte rqBattCapacity_dSOC_P1[2] = {0x21, 0x12};
|
||
|
const PROGMEM byte rqBattCapacity_dSOC_P2[2] = {0x21, 0x13};
|
||
|
const PROGMEM byte rqBattCapacity_P1[2] = {0x21, 0x14};
|
||
|
const PROGMEM byte rqBattCapacity_P2[2] = {0x21, 0x15};
|
||
|
const PROGMEM byte rqBattBalancing[2] = {0x21, 0x16};
|
||
|
const PROGMEM byte rqBattLogData_P1[2] = {0x21, 0x30};
|
||
|
const PROGMEM byte rqBattProdDate[3] = {0x22, 0x03, 0x04};
|
||
|
*/
|
||
|
|
||
|
#include "ovms_log.h"
|
||
|
static const char *TAG = "v-smarteq";
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string>
|
||
|
#include <iomanip>
|
||
|
#include "pcp.h"
|
||
|
#include "ovms_metrics.h"
|
||
|
#include "ovms_events.h"
|
||
|
#include "ovms_config.h"
|
||
|
#include "ovms_command.h"
|
||
|
#include "metrics_standard.h"
|
||
|
#include "ovms_notify.h"
|
||
|
|
||
|
#include "vehicle_smarteq.h"
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Incoming poll reply messages
|
||
|
*/
|
||
|
void OvmsVehicleSmartEQ::IncomingPollReply(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t remain) {
|
||
|
|
||
|
// init / fill rx buffer:
|
||
|
if (m_poll_ml_frame == 0) {
|
||
|
m_rxbuf.clear();
|
||
|
m_rxbuf.reserve(length + remain);
|
||
|
}
|
||
|
m_rxbuf.append((char*)data, length);
|
||
|
if (remain)
|
||
|
return;
|
||
|
|
||
|
// response complete:
|
||
|
ESP_LOGV(TAG, "IncomingPollReply: PID %02X: len=%d %s", pid, m_rxbuf.size(), hexencode(m_rxbuf).c_str());
|
||
|
|
||
|
switch (m_poll_moduleid_low) {
|
||
|
case 0x7BB:
|
||
|
switch (pid) {
|
||
|
case 0x41: // rqBattVoltages_P1
|
||
|
PollReply_BMS_BattVolts(m_rxbuf.data(), m_rxbuf.size(), 0);
|
||
|
break;
|
||
|
case 0x42: // rqBattVoltages_P2
|
||
|
PollReply_BMS_BattVolts(m_rxbuf.data(), m_rxbuf.size(), 48);
|
||
|
break;
|
||
|
case 0x04: // rqBattTemperatures
|
||
|
PollReply_BMS_BattTemps(m_rxbuf.data(), 31);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case 0x793:
|
||
|
switch (pid) {
|
||
|
case 0x80: // rqIDpart OBL_7KW_Installed
|
||
|
//PollReply_BMS_BattVolts(m_rxbuf.data(), m_rxbuf.size(), 0);
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
ESP_LOGW(TAG, "IncomingPollReply: unhandled PID %02X: len=%d %s", pid, m_rxbuf.size(), hexencode(m_rxbuf).c_str());
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void OvmsVehicleSmartEQ::PollReply_BMS_BattVolts(const char* reply_data, uint16_t reply_len, uint16_t start) {
|
||
|
float CV;
|
||
|
static bool cellstat = false;
|
||
|
|
||
|
CV = (reply_data[0] * 256 + reply_data[1]);
|
||
|
if (CV == 5120 && start == 0) cellstat = false;
|
||
|
if (CV != 5120 && start == 0) cellstat = true;
|
||
|
|
||
|
if (cellstat) {
|
||
|
for(int n = 0; n < CELLCOUNT; n = n + 2){
|
||
|
CV = (reply_data[n] * 256 + reply_data[n + 1]);
|
||
|
CV = CV / 1024.0;
|
||
|
BmsSetCellVoltage((n/2) + start, CV);
|
||
|
|
||
|
ESP_LOGV(TAG, "CellVoltage: id=%d len=%F", (n/2)+start, CV);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsVehicleSmartEQ::PollReply_BMS_BattTemps(const char* reply_data, uint16_t reply_len) {
|
||
|
int16_t Temps[31];
|
||
|
float BMStemps[31];
|
||
|
|
||
|
for (uint16_t n = 0; n < (reply_len * 2); n = n + 2) {
|
||
|
int16_t value = reply_data[n] * 256 + reply_data[n + 1];
|
||
|
if (n > 4) {
|
||
|
//Test for negative min. module temperature and apply offset
|
||
|
if (Temps[1] & 0x8000) {
|
||
|
value = value - 0xA00; //minus offset
|
||
|
}
|
||
|
}
|
||
|
Temps[n / 2] = value;
|
||
|
BMStemps[n / 2] = value / 64.0;
|
||
|
mt_bms_temps->SetElemValues(0, 31, BMStemps);
|
||
|
}
|
||
|
}
|
||
|
|