OVMS3/OVMS.V3/components/vehicle_smarteq/src/eq_can_poll.cpp

158 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);
}
}