2022-04-08 23:03:19 +00:00
|
|
|
/*
|
|
|
|
; Project: Open Vehicle Monitor System
|
|
|
|
; Date: 11th Sep 2019
|
|
|
|
;
|
|
|
|
; Changes:
|
|
|
|
; 1.0 Initial release
|
|
|
|
;
|
|
|
|
; (C) 2011 Michael Stegen / Stegen Electronics
|
|
|
|
; (C) 2011-2017 Mark Webb-Johnson
|
|
|
|
; (C) 2011 Sonny Chen @ EPRO/DX
|
|
|
|
; (C) 2018 Marcos Mezo
|
|
|
|
; (C) 2019 Thomas Heuer @Dimitrie78
|
|
|
|
;
|
|
|
|
; 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 "ovms_log.h"
|
|
|
|
static const char *TAG = "v-zoe-ph2";
|
|
|
|
|
|
|
|
#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 "ovms_peripherals.h"
|
|
|
|
#include "ovms_netmanager.h"
|
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
#include "vehicle_renaultzoe_ph2.h"
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-12 17:19:55 +00:00
|
|
|
#define SESSION_EXTDIAG 0x1003
|
2022-04-12 20:06:20 +00:00
|
|
|
#define SESSION_DEFAULT 0x1001
|
|
|
|
#define SESSION_AfterSales 0x10C0
|
2022-04-11 23:41:19 +00:00
|
|
|
|
2022-04-08 23:03:19 +00:00
|
|
|
// Pollstate 0 - POLLSTATE_OFF - car is off
|
|
|
|
// Pollstate 1 - POLLSTATE_ON - car is on
|
|
|
|
// Pollstate 2 - POLLSTATE_RUNNING - car is driving
|
|
|
|
// Pollstate 3 - POLLSTATE_CHARGING - car is charging
|
|
|
|
static const OvmsVehicle::poll_pid_t renault_zoe_polls[] = {
|
2022-04-12 18:37:40 +00:00
|
|
|
//***TX-ID, ***RX-ID, ***SID, ***PID, { Polltime (seconds) for Pollstate 0, 1, 2, 3}, ***CAN BUS Interface, ***FRAMETYPE
|
2022-04-11 22:09:57 +00:00
|
|
|
//LBC
|
2022-04-12 20:06:20 +00:00
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIISESSION, SESSION_DEFAULT, { 60, 60, 60, 60 }, 0, ISOTP_EXTFRAME }, // OBD Extended Diagnostic Session
|
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x9002, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // SOC
|
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x9003, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // SOH
|
2022-04-12 17:19:55 +00:00
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIGROUP, 0x9131, { 0, 60, 600, 60 }, 0, ISOTP_EXTFRAME }, // Temp Bat Module 1
|
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIGROUP, 0x9021, { 0, 60, 600, 60 }, 0, ISOTP_EXTFRAME }, // Cell Bat Module 1-62
|
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIGROUP, 0x9062, { 0, 60, 600, 60 }, 0, ISOTP_EXTFRAME }, // Cell Bat Module 63-96
|
2022-04-12 20:06:20 +00:00
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x9005, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Battery Voltage
|
2022-04-12 21:30:29 +00:00
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x925D, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Battery Current
|
2022-04-12 18:37:40 +00:00
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x91C8, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Battery Available Energy kWh
|
2022-04-12 18:01:59 +00:00
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x9243, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Energy charged kWh
|
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x9244, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Energy discharged kWh
|
|
|
|
{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x9246, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Energy regenerated kWh
|
2022-04-12 20:06:20 +00:00
|
|
|
//{ 0x18dadbf1, 0x18daf1db, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x21D9, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Charging State (1: Slow, 2: Fast, 3: Init Charging)
|
2022-04-11 22:09:57 +00:00
|
|
|
|
|
|
|
//EVC-HCM-VCM
|
2022-04-12 20:06:20 +00:00
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIISESSION, SESSION_EXTDIAG, { 60, 60, 60, 60 }, 0, ISOTP_EXTFRAME }, // OBD Extended Diagnostic Session
|
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x2006, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Odometer
|
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x21DF, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // 12Battery Current
|
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x2005, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // 12Battery Voltage
|
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x21D0, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // DCDC Temperature
|
2022-04-12 21:30:29 +00:00
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x20B4, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // DCDC Activation
|
2022-04-12 20:06:20 +00:00
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x21CF, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Inverter Status
|
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x303D, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // HV Battery Insulation Resistance
|
2022-04-12 21:30:29 +00:00
|
|
|
{ 0x18dadaf1, 0x18daf1da, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xF446, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Ambient Temperature
|
2022-04-11 22:09:57 +00:00
|
|
|
|
|
|
|
//Motor Inverter
|
2022-04-12 18:01:59 +00:00
|
|
|
{ 0x18dadff1, 0x18daf1df, VEHICLE_POLL_TYPE_OBDIISESSION, SESSION_EXTDIAG, { 60, 60, 60, 60 }, 0, ISOTP_EXTFRAME }, // OBD Extended Diagnostic Session
|
2022-04-12 17:19:55 +00:00
|
|
|
{ 0x18dadff1, 0x18daf1df, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x700F, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Stator Temperature 1
|
|
|
|
{ 0x18dadff1, 0x18daf1df, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x7010, { 0, 10, 10, 10 }, 0, ISOTP_EXTFRAME }, // Stator Temperature 2
|
2022-04-12 18:37:40 +00:00
|
|
|
|
|
|
|
//Navigation-UCC-ITM
|
2022-04-12 20:06:20 +00:00
|
|
|
{ 0x747, 0x767, VEHICLE_POLL_TYPE_OBDIISESSION, SESSION_DEFAULT, { 60, 60, 60, 60 }, 0, ISOTP_STD }, // OBD Extended Diagnostic Session
|
2022-04-12 18:37:40 +00:00
|
|
|
{ 0x747, 0x767, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x2109, { 0, 10, 10, 10 }, 0, ISOTP_STD }, // Volume Setting (for debug only)
|
2022-04-08 23:03:19 +00:00
|
|
|
POLL_LIST_END
|
|
|
|
};
|
|
|
|
|
2022-04-11 23:26:13 +00:00
|
|
|
|
2022-04-08 23:03:19 +00:00
|
|
|
OvmsVehicleRenaultZoePh2* OvmsVehicleRenaultZoePh2::GetInstance(OvmsWriter* writer /*=NULL*/)
|
|
|
|
{
|
|
|
|
OvmsVehicleRenaultZoePh2* zoe = (OvmsVehicleRenaultZoePh2*) MyVehicleFactory.ActiveVehicle();
|
|
|
|
string type = StdMetrics.ms_v_type->AsString();
|
2022-04-10 18:30:54 +00:00
|
|
|
if (!zoe || type != "RZ2") {
|
2022-04-08 23:03:19 +00:00
|
|
|
if (writer)
|
2022-04-10 18:30:54 +00:00
|
|
|
writer->puts("Error: Renault Zoe Ph2 vehicle module not selected");
|
2022-04-08 23:03:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return zoe;
|
|
|
|
}
|
|
|
|
|
2022-04-11 23:26:13 +00:00
|
|
|
|
2022-04-08 23:03:19 +00:00
|
|
|
OvmsVehicleRenaultZoePh2::OvmsVehicleRenaultZoePh2() {
|
2022-04-10 18:30:54 +00:00
|
|
|
ESP_LOGI(TAG, "Start Renault Zoe Ph2 vehicle module");
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
StandardMetrics.ms_v_type->SetValue("RZ2");
|
2022-04-08 23:03:19 +00:00
|
|
|
StandardMetrics.ms_v_charge_inprogress->SetValue(false);
|
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
MyConfig.RegisterParam("zph2", "Renault Zoe Ph2", true, true);
|
2022-04-08 23:03:19 +00:00
|
|
|
ConfigChanged(NULL);
|
|
|
|
|
|
|
|
// Zoe CAN bus runs at 500 kbps
|
|
|
|
RegisterCanBus(1, CAN_MODE_ACTIVE, CAN_SPEED_500KBPS);
|
|
|
|
|
|
|
|
// Poll Specific PIDs
|
2022-04-11 22:09:57 +00:00
|
|
|
POLLSTATE_ON;
|
2022-04-10 18:30:54 +00:00
|
|
|
PollSetPidList(m_can1, renault_zoe_polls);
|
2022-04-12 18:01:59 +00:00
|
|
|
PollSetThrottling(1);
|
2022-04-08 23:03:19 +00:00
|
|
|
PollSetResponseSeparationTime(20);
|
|
|
|
|
|
|
|
// init metrics:
|
2022-04-10 18:30:54 +00:00
|
|
|
mt_pos_odometer_start = MyMetrics.InitFloat("zph2.v.pos.odometer.start", SM_STALE_MID, 0, Kilometers);
|
2022-04-11 23:58:08 +00:00
|
|
|
mt_bus_awake = MyMetrics.InitBool("zph2.v.bus.awake", SM_STALE_MIN, true);
|
2022-04-10 18:30:54 +00:00
|
|
|
mt_available_energy = MyMetrics.InitFloat("zph2.v.avail.energy", SM_STALE_MID, 0, kWh);
|
|
|
|
mt_main_power_consumed = MyMetrics.InitFloat("zph2.c.main.power.consumed", SM_STALE_MID, 0, kWh);
|
2022-04-12 21:30:29 +00:00
|
|
|
mt_inv_status = MyMetrics.InitString("zph2.m.inverter.status", SM_STALE_MID, 0, Percentage);
|
2022-04-12 19:28:46 +00:00
|
|
|
mt_mot_temp_stator1 = MyMetrics.InitFloat("zph2.m.temp.stator1", SM_STALE_MID, 0, Celcius);
|
|
|
|
mt_mot_temp_stator2 = MyMetrics.InitFloat("zph2.m.temp.stator2", SM_STALE_MID, 0, Celcius);
|
2022-04-08 23:03:19 +00:00
|
|
|
|
|
|
|
// init commands:
|
2022-04-10 18:30:54 +00:00
|
|
|
cmd_zoe = MyCommandApp.RegisterCommand("zoe-ph2", "Renault Zoe Ph2");
|
2022-04-08 23:03:19 +00:00
|
|
|
|
|
|
|
// BMS configuration:
|
|
|
|
BmsSetCellArrangementVoltage(96, 8);
|
2022-04-10 18:30:54 +00:00
|
|
|
BmsSetCellArrangementTemperature(12, 1);
|
2022-04-08 23:03:19 +00:00
|
|
|
BmsSetCellLimitsVoltage(2.0, 5.0);
|
|
|
|
BmsSetCellLimitsTemperature(-39, 200);
|
|
|
|
BmsSetCellDefaultThresholdsVoltage(0.030, 0.050);
|
|
|
|
BmsSetCellDefaultThresholdsTemperature(4.0, 5.0);
|
|
|
|
|
|
|
|
#ifdef CONFIG_OVMS_COMP_WEBSERVER
|
|
|
|
WebInit();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
OvmsVehicleRenaultZoePh2::~OvmsVehicleRenaultZoePh2() {
|
2022-04-10 18:30:54 +00:00
|
|
|
ESP_LOGI(TAG, "Stop Renault Zoe Ph2 vehicle module");
|
2022-04-08 23:03:19 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_OVMS_COMP_WEBSERVER
|
|
|
|
WebDeInit();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles incoming CAN-frames on bus 1
|
|
|
|
*/
|
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingFrameCan1(CAN_frame_t* p_frame) {
|
|
|
|
uint8_t *data = p_frame->data.u8;
|
2022-04-10 18:30:54 +00:00
|
|
|
ESP_LOGI(TAG, "PID:%x DATA: %02x %02x %02x %02x %02x %02x %02x %02x", p_frame->MsgID, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-11 22:09:57 +00:00
|
|
|
/*
|
2022-04-08 23:03:19 +00:00
|
|
|
if (m_candata_poll != 1 && m_ready) {
|
|
|
|
ESP_LOGI(TAG,"Car has woken (CAN bus activity)");
|
|
|
|
mt_bus_awake->SetValue(true);
|
|
|
|
//StandardMetrics.ms_v_env_awake->SetValue(true);
|
|
|
|
m_candata_poll = 1;
|
|
|
|
if (m_enable_write) POLLSTATE_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_candata_timer = RZ_CANDATA_TIMEOUT;
|
2022-04-11 22:09:57 +00:00
|
|
|
*/
|
2022-04-08 23:03:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles incoming poll results
|
|
|
|
*/
|
2022-04-12 17:53:42 +00:00
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingPollReply(canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t remain) {
|
2022-04-08 23:03:19 +00:00
|
|
|
string& rxbuf = zoe_obd_rxbuf;
|
2022-04-11 23:26:13 +00:00
|
|
|
static uint32_t last_pid = -1;
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-12 17:57:30 +00:00
|
|
|
ESP_LOGV(TAG, "pid: %04x length: %d m_poll_ml_remain: %d m_poll_ml_frame: %d", pid, length, m_poll_ml_remain, m_poll_ml_frame);
|
|
|
|
|
2022-04-08 23:03:19 +00:00
|
|
|
if (pid != last_pid) {
|
2022-04-11 22:09:57 +00:00
|
|
|
ESP_LOGD(TAG, "pid: %04x length: %d m_poll_ml_remain: %d m_poll_ml_frame: %d", pid, length, m_poll_ml_remain, m_poll_ml_frame);
|
2022-04-08 23:03:19 +00:00
|
|
|
last_pid = pid;
|
|
|
|
m_poll_ml_frame=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// init / fill rx buffer:
|
|
|
|
if (m_poll_ml_frame == 0) {
|
|
|
|
rxbuf.clear();
|
|
|
|
rxbuf.reserve(length + remain);
|
|
|
|
}
|
|
|
|
rxbuf.append((char*)data, length);
|
|
|
|
|
|
|
|
if (remain)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (m_poll_moduleid_low) {
|
2022-04-11 22:09:57 +00:00
|
|
|
// ****** INV *****
|
|
|
|
case 0x18daf1df:
|
|
|
|
IncomingINV(type, pid, rxbuf.data(), rxbuf.size());
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
// ****** EVC *****
|
2022-04-11 22:09:57 +00:00
|
|
|
case 0x18daf1da:
|
2022-04-08 23:03:19 +00:00
|
|
|
IncomingEVC(type, pid, rxbuf.data(), rxbuf.size());
|
|
|
|
break;
|
|
|
|
// ****** BCB *****
|
2022-04-11 22:09:57 +00:00
|
|
|
case 0x18daf1de:
|
2022-04-08 23:03:19 +00:00
|
|
|
IncomingBCB(type, pid, rxbuf.data(), rxbuf.size());
|
|
|
|
break;
|
|
|
|
// ****** LBC *****
|
2022-04-11 22:09:57 +00:00
|
|
|
case 0x18daf1db:
|
2022-04-08 23:03:19 +00:00
|
|
|
IncomingLBC(type, pid, rxbuf.data(), rxbuf.size());
|
|
|
|
break;
|
2022-04-11 22:09:57 +00:00
|
|
|
// ****** UCH *****
|
|
|
|
case 0x765:
|
|
|
|
IncomingUCH(type, pid, rxbuf.data(), rxbuf.size());
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
// ****** PEB *****
|
|
|
|
case 0x77e:
|
|
|
|
IncomingPEB(type, pid, rxbuf.data(), rxbuf.size());
|
2022-04-12 18:37:40 +00:00
|
|
|
break;
|
|
|
|
// ****** Navigation-UCC-ITM *****
|
|
|
|
case 0x747:
|
|
|
|
IncomingUCC(type, pid, rxbuf.data(), rxbuf.size());
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-04-11 22:09:57 +00:00
|
|
|
* Handle incoming polls from the motor inverter
|
2022-04-08 23:03:19 +00:00
|
|
|
*/
|
2022-04-12 17:53:42 +00:00
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingINV(uint16_t type, uint16_t pid, const char* data, uint16_t len) {
|
2022-04-08 23:03:19 +00:00
|
|
|
switch (pid) {
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x700F: { // Motor temperature
|
2022-04-12 21:30:29 +00:00
|
|
|
StandardMetrics.ms_v_mot_temp->SetValue(float((CAN_UINT(0) - 40) * 0.001953125), Celcius);
|
|
|
|
mt_mot_temp_stator1->SetValue(float((CAN_UINT(0) - 40) * 0.001953125), Celcius);
|
|
|
|
ESP_LOGD(TAG, "700F INV ms_v_mot_temp: %f", float((CAN_UINT(0) - 40) * 0.001953125));
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 21:30:29 +00:00
|
|
|
case 0x7010: {
|
|
|
|
mt_mot_temp_stator2->SetValue(float((CAN_UINT(0) - 40) * 0.001953125), Celcius);
|
|
|
|
ESP_LOGD(TAG, "7010 INV mt_mot_temp_stator2: %f", float((CAN_UINT(0) - 40) * 0.001953125));
|
|
|
|
break;
|
2022-04-08 23:03:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Handle incoming polls from the EVC Computer
|
|
|
|
*/
|
2022-04-12 17:53:42 +00:00
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingEVC(uint16_t type, uint16_t pid, const char* data, uint16_t len) {
|
2022-04-08 23:03:19 +00:00
|
|
|
switch (pid) {
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x2006: { // Odometer (Total Vehicle Distance)
|
2022-04-08 23:03:19 +00:00
|
|
|
StandardMetrics.ms_v_pos_odometer->SetValue((float) CAN_UINT24(0), Kilometers);
|
2022-04-12 21:30:29 +00:00
|
|
|
ESP_LOGD(TAG, "2006 EVC ms_v_pos_odometer: %d", CAN_UINT24(0));
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 21:30:29 +00:00
|
|
|
case 0x29FD: {
|
|
|
|
StandardMetrics.ms_v_charge_12v_current->SetValue((float) (CAN_UINT(0) * 0.01 - 327.675));
|
|
|
|
ESP_LOGD(TAG, "29FD EVC ms_v_charge_12v_current: %d", CAN_UINT(0));
|
|
|
|
ESP_LOGD(TAG, "29FD EVC ms_v_charge_12v_current: %f", CAN_UINT(0) * 0.01 - 327.675);
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x2005: {
|
2022-04-12 21:30:29 +00:00
|
|
|
StandardMetrics.ms_v_charge_12v_voltage->SetValue((float) (CAN_UINT(0) * 0.01));
|
|
|
|
ESP_LOGD(TAG, "2005 EVC ms_v_charge_12v_voltage: %f", CAN_UINT(0) * 0.01);
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x21D0: {
|
2022-04-12 21:30:29 +00:00
|
|
|
StandardMetrics.ms_v_charge_12v_temp->SetValue((float) (CAN_UINT(0) - 40));
|
|
|
|
ESP_LOGD(TAG, "21D0 EVC ms_v_charge_12v_temp: %d", CAN_UINT(0) - 40));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x20B4: {
|
|
|
|
StandardMetrics.ms_v_env_charging12v->SetValue((bool) (CAN_BYTE(0)));
|
|
|
|
ESP_LOGD(TAG, "20B4 EVC ms_v_env_charging12v: %d", CAN_UINT(0));
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 21:30:29 +00:00
|
|
|
case 0x21CF: {
|
|
|
|
ESP_LOGD(TAG, "21CF EVC mt_inv_status: %d", CAN_UINT(0));
|
|
|
|
if CAN_UINT(0)) == 1 {
|
|
|
|
mt_inv_status->SetValue("Inverter off");
|
|
|
|
} else if CAN_UINT(0)) == 2 {
|
|
|
|
mt_inv_status->SetValue("Inverter on");
|
|
|
|
} else if CAN_UINT(0)) == 3 {
|
|
|
|
mt_inv_status->SetValue("Inverter decharging");
|
|
|
|
} else if CAN_UINT(0)) == 4 {
|
|
|
|
mt_inv_status->SetValue("Inverter alternator mode");
|
|
|
|
} else if CAN_UINT(0)) == 5 {
|
|
|
|
mt_inv_status->SetValue("Inverter ready to sleep");
|
|
|
|
} else {
|
|
|
|
mt_inv_status->SetValue("Inverter state unknown");
|
|
|
|
}
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x33F6: {
|
2022-04-12 17:19:55 +00:00
|
|
|
// ,7ec,24,31,1,40,0,°C,33F6,6233F6,ff,Temperature of the inverter given by PEB (CAN ETS)
|
2022-04-08 23:03:19 +00:00
|
|
|
ESP_LOGD(TAG, "7ec inv temp: %d", CAN_BYTE(0) - 40);
|
|
|
|
break;
|
|
|
|
}
|
2022-04-12 21:30:29 +00:00
|
|
|
case 0xF446: {
|
|
|
|
StandardMetrics.ms_v_env_temp->SetValue((float) (CAN_UINT(0) - 40));
|
|
|
|
ESP_LOGD(TAG, "F446 EVC ms_v_env_temp: %d", CAN_UINT(0));
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle incoming polls from the BCB Computer
|
|
|
|
*/
|
2022-04-12 17:53:42 +00:00
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingBCB(uint16_t type, uint16_t pid, const char* data, uint16_t len) {
|
2022-04-08 23:03:19 +00:00
|
|
|
switch (pid) {
|
|
|
|
case 0x504A: {
|
2022-04-12 17:19:55 +00:00
|
|
|
// 793,24,39,1,20000,0,W,504A,62504A,ff\n" // Mains active power consumed
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x5063: {
|
2022-04-12 17:19:55 +00:00
|
|
|
// 793,24,31,1,0,0,,5063,625063,ff\n"
|
2022-04-08 23:03:19 +00:00
|
|
|
// Supervisor state,0:Init;1:Wait;2:ClosingS2;3:InitType;4:InitLkg;5:InitChg;6:Charge;7:ZeroAmpMode;8:EndOfChg;9:OpeningS2;10:ReadyToSleep;11:EmergencyStop;12:InitChargeDF;13:OCPStop;14:WaitS2
|
|
|
|
/* rz_charge_state_local=CAN_BYTE(0);
|
|
|
|
m_b_temp1->SetValue((INT)rz_charge_state_local);
|
|
|
|
if (rz_charge_state_local==0) { // Init,Wait,ClosingS2,InitType,InitLkg,InitChg
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==1) { // Charge
|
|
|
|
SET_CHARGE_STATE("stopped");
|
|
|
|
} else if (rz_charge_state_local==2) { // Charge
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==3) { // Charge
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==4) { // Charge
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==5) { // Charge
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==6) { // Charge
|
|
|
|
SET_CHARGE_STATE("charging");
|
|
|
|
} else if (rz_charge_state_local==7) { // ZeroAmpMode
|
|
|
|
SET_CHARGE_STATE("topoff");
|
|
|
|
} else if (rz_charge_state_local==8) { // EndOfChg
|
|
|
|
SET_CHARGE_STATE("done");
|
|
|
|
} else if (rz_charge_state_local==9) { // OpeningS2
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==10) { // ReadyToSleep
|
|
|
|
SET_CHARGE_STATE("stopped");
|
|
|
|
} else if (rz_charge_state_local==11) { //EmergencyStopp
|
|
|
|
SET_CHARGE_STATE("stopped");
|
|
|
|
} else if (rz_charge_state_local==12) { //InitChargeDF
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} else if (rz_charge_state_local==13) { //OCPStop
|
|
|
|
SET_CHARGE_STATE("stopped");
|
|
|
|
} else if (rz_charge_state_local==14) { //WaitS2
|
|
|
|
SET_CHARGE_STATE("prepare");
|
|
|
|
} */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle incoming polls from the LBC Computer
|
|
|
|
*/
|
2022-04-12 17:53:42 +00:00
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingLBC(uint16_t type, uint16_t pid, const char* data, uint16_t len) {
|
2022-04-08 23:03:19 +00:00
|
|
|
switch (pid) {
|
2022-04-12 20:06:20 +00:00
|
|
|
case 0x9005: {
|
2022-04-12 21:30:29 +00:00
|
|
|
StandardMetrics.ms_v_bat_voltage->SetValue((float) (CAN_UINT(0) * 0.1));
|
|
|
|
ESP_LOGD(TAG, "9005 LBC ms_v_bat_voltage: %f", CAN_UINT(0) * 0.1);
|
2022-04-11 22:09:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 21:30:29 +00:00
|
|
|
case 0x925D: {
|
|
|
|
StandardMetrics.ms_v_bat_current->SetValue((float) ((CAN_UINT(0) - 1020) * 0.03125));
|
|
|
|
ESP_LOGD(TAG, "925D LBC ms_v_bat_current: %d", CAN_UINT(0));
|
|
|
|
ESP_LOGD(TAG, "925D LBC ms_v_bat_current: %f", ((CAN_UINT(0) - 1020) * 0.03125));
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 20:06:20 +00:00
|
|
|
case 0x9002: {
|
2022-04-12 19:28:46 +00:00
|
|
|
StandardMetrics.ms_v_bat_soc->SetValue((float) (CAN_UINT(0)) * 0.01);
|
2022-04-12 21:30:29 +00:00
|
|
|
ESP_LOGD(TAG, "9002 LBC ms_v_bat_soc: %f", CAN_UINT(0) * 0.01);
|
2022-04-11 22:09:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 20:06:20 +00:00
|
|
|
case 0x9003: {
|
2022-04-12 19:28:46 +00:00
|
|
|
StandardMetrics.ms_v_bat_soh->SetValue((float) (CAN_UINT(0) * 0.01));
|
2022-04-12 21:30:29 +00:00
|
|
|
ESP_LOGD(TAG, "9003 LBC ms_v_bat_soh: %f", CAN_UINT(0) * 0.01);
|
2022-04-11 22:09:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 20:06:20 +00:00
|
|
|
case 0x9243: {
|
|
|
|
StandardMetrics.ms_v_charge_kwh_grid_total->SetValue((float) (CAN_UINT24(0)));
|
|
|
|
ESP_LOGD(TAG, "9243 LBC ms_v_charge_kwh_grid_total: %d", CAN_UINT24(0));
|
|
|
|
break;
|
|
|
|
}
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x9244: {
|
2022-04-12 20:06:20 +00:00
|
|
|
StandardMetrics.ms_v_bat_energy_used->SetValue((float) (CAN_UINT24(0)));
|
|
|
|
ESP_LOGD(TAG, "9244 LBC ms_v_bat_energy_used: %d", CAN_UINT24(0));
|
2022-04-11 22:09:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x9246: {
|
2022-04-12 20:06:20 +00:00
|
|
|
StandardMetrics.ms_v_bat_energy_recd->SetValue((float) (CAN_UINT24(0)));
|
|
|
|
ESP_LOGD(TAG, "9246 LBC ms_v_bat_energy_recd: %d", CAN_UINT24(0));
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x04: {
|
2022-04-10 18:30:54 +00:00
|
|
|
for(int i=2; i<36; i+=3){
|
|
|
|
BmsSetCellTemperature( (i-2)/3, (INT)CAN_BYTE(i)-40 );
|
|
|
|
//ESP_LOGD(TAG, "temp %d - %d", (i-2)/3, (INT)CAN_BYTE(i)-40);
|
2022-04-08 23:03:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-04-12 19:28:46 +00:00
|
|
|
case 0x91C8: {
|
2022-04-11 22:09:57 +00:00
|
|
|
StandardMetrics.ms_v_charge_kwh->SetValue(float(CAN_UINT(0)));
|
2022-04-12 19:28:46 +00:00
|
|
|
ESP_LOGD(TAG, "91C8 LBC ms_v_charge_kwh: %d", CAN_UINT(0));
|
2022-04-11 22:09:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x9021: {
|
2022-04-08 23:03:19 +00:00
|
|
|
for(int i=0; i<124; i+=2){
|
|
|
|
float cell = (float)CAN_UINT(i)/1000;
|
|
|
|
BmsSetCellVoltage(i/2, cell);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-04-12 17:19:55 +00:00
|
|
|
case 0x9062: {
|
2022-04-08 23:03:19 +00:00
|
|
|
for(int i=0; i<68; i+=2){
|
|
|
|
float cell = (float)CAN_UINT(i)/1000;
|
|
|
|
BmsSetCellVoltage((i/2)+62, cell);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
char *buf = NULL;
|
|
|
|
size_t rlen = len, offset = 0;
|
|
|
|
do {
|
|
|
|
rlen = FormatHexDump(&buf, data + offset, rlen, 16);
|
|
|
|
offset += 16;
|
|
|
|
ESP_LOGW(TAG, "OBD2: unhandled reply [%02x %02x]: %s", type, pid, buf ? buf : "-");
|
|
|
|
} while (rlen);
|
|
|
|
if (buf)
|
|
|
|
free(buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-04-12 21:30:29 +00:00
|
|
|
* Handle incoming polls from the UCH Computer
|
2022-04-08 23:03:19 +00:00
|
|
|
*/
|
2022-04-12 17:53:42 +00:00
|
|
|
void OvmsVehicleRenaultZoePh2::IncomingUCH(uint16_t type, uint16_t pid, const char* data, uint16_t len) {
|
2022-04-08 23:03:19 +00:00
|
|
|
switch (pid) {
|
|
|
|
case 0x4B7C: {
|
|
|
|
// Todo
|
2022-04-12 17:19:55 +00:00
|
|
|
// //+"7bc,28,39,1,4094,0,N·m,4B7C,624B7C,ff,Electric brake wheels torque request\n" // Brake Torque
|
2022-04-08 23:03:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x4B7D: {
|
2022-04-12 17:19:55 +00:00
|
|
|
//"7bc,28,39,1,4094,0,N·m,4B7D,624B7D,ff,Total Hydraulic brake wheels torque request\n"
|
2022-04-08 23:03:19 +00:00
|
|
|
//m_v_hydraulic_brake_power->SetValue(float(CAN_12NIBL(28) -4094)*StdMetrics.ms_v_pos_speed->AsFloat()/3.6/1.28*2*3.141 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Takes care of setting all the state appropriate when the car is on
|
|
|
|
* or off. Centralized so we can more easily make on and off mirror
|
|
|
|
* images.
|
|
|
|
*/
|
|
|
|
void OvmsVehicleRenaultZoePh2::car_on(bool isOn) {
|
|
|
|
if (isOn && !StandardMetrics.ms_v_env_on->AsBool()) {
|
|
|
|
// Car is beeing turned ON
|
|
|
|
ESP_LOGI(TAG,"CAR IS ON");
|
|
|
|
StandardMetrics.ms_v_env_on->SetValue(isOn);
|
|
|
|
StandardMetrics.ms_v_env_awake->SetValue(isOn);
|
|
|
|
// Handle 12Vcharging
|
|
|
|
StandardMetrics.ms_v_env_charging12v->SetValue(true);
|
|
|
|
if (m_enable_write) POLLSTATE_RUNNING;
|
|
|
|
// Reset trip values
|
|
|
|
if (!m_reset_trip) {
|
|
|
|
StandardMetrics.ms_v_bat_energy_recd->SetValue(0);
|
|
|
|
StandardMetrics.ms_v_bat_energy_used->SetValue(0);
|
|
|
|
mt_pos_odometer_start->SetValue(StandardMetrics.ms_v_pos_odometer->AsFloat());
|
|
|
|
StandardMetrics.ms_v_pos_trip->SetValue(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(!isOn && StandardMetrics.ms_v_env_on->AsBool()) {
|
|
|
|
// Car is being turned OFF
|
|
|
|
ESP_LOGI(TAG,"CAR IS OFF");
|
|
|
|
if (!StandardMetrics.ms_v_charge_inprogress->AsBool()) {
|
|
|
|
StandardMetrics.ms_v_env_charging12v->SetValue(false);
|
|
|
|
if (m_enable_write) POLLSTATE_ON;
|
|
|
|
} else {
|
|
|
|
if (m_enable_write) POLLSTATE_CHARGING;
|
|
|
|
}
|
|
|
|
StandardMetrics.ms_v_env_on->SetValue( isOn );
|
|
|
|
StandardMetrics.ms_v_env_awake->SetValue( isOn );
|
|
|
|
StandardMetrics.ms_v_pos_speed->SetValue( 0 );
|
|
|
|
if (StandardMetrics.ms_v_pos_trip->AsFloat(0) > 0.1)
|
|
|
|
NotifyTrip();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OvmsVehicleRenaultZoePh2::Ticker1(uint32_t ticker) {
|
|
|
|
if (m_candata_timer > 0) {
|
|
|
|
if (--m_candata_timer == 0) {
|
|
|
|
// Car has gone to sleep
|
|
|
|
ESP_LOGI(TAG,"Car has gone to sleep (CAN bus timeout)");
|
|
|
|
mt_bus_awake->SetValue(false);
|
|
|
|
//StandardMetrics.ms_v_env_awake->SetValue(false);
|
|
|
|
StandardMetrics.ms_v_bat_12v_current->SetValue(0);
|
|
|
|
m_candata_poll = 0;
|
|
|
|
POLLSTATE_OFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HandleEnergy();
|
|
|
|
|
|
|
|
// Handle Tripcounter
|
|
|
|
if (mt_pos_odometer_start->AsFloat(0) == 0 && StandardMetrics.ms_v_pos_odometer->AsFloat(0) > 0.0) {
|
|
|
|
mt_pos_odometer_start->SetValue(StandardMetrics.ms_v_pos_odometer->AsFloat());
|
|
|
|
}
|
|
|
|
if (StandardMetrics.ms_v_env_on->AsBool() && StandardMetrics.ms_v_pos_odometer->AsFloat(0) > 0.0 && mt_pos_odometer_start->AsFloat(0) > 0.0) {
|
|
|
|
StandardMetrics.ms_v_pos_trip->SetValue(StandardMetrics.ms_v_pos_odometer->AsFloat(0) - mt_pos_odometer_start->AsFloat(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle v2Server connection
|
|
|
|
if (StandardMetrics.ms_s_v2_connected->AsBool()) {
|
|
|
|
m_reboot_ticker = 5 * 60; // set reboot ticker
|
|
|
|
}
|
|
|
|
else if (m_reboot_ticker > 0 && --m_reboot_ticker == 0) {
|
|
|
|
MyNetManager.RestartNetwork();
|
|
|
|
m_reboot_ticker = 5 * 60;
|
|
|
|
//MyBoot.Restart(); // restart Module
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OvmsVehicleRenaultZoePh2::Ticker10(uint32_t ticker) {
|
|
|
|
HandleCharging();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update derived energy metrics while driving
|
|
|
|
* Called once per second
|
|
|
|
*/
|
|
|
|
void OvmsVehicleRenaultZoePh2::HandleEnergy() {
|
|
|
|
float voltage = StandardMetrics.ms_v_bat_voltage->AsFloat(0, Volts);
|
|
|
|
float current = StandardMetrics.ms_v_bat_current->AsFloat(0, Amps);
|
|
|
|
|
|
|
|
// Power (in kw) resulting from voltage and current
|
|
|
|
float power = voltage * current / 1000.0;
|
|
|
|
|
|
|
|
StandardMetrics.ms_v_bat_power->SetValue(power * -1.0f);
|
|
|
|
|
|
|
|
// Are we driving?
|
|
|
|
if (power != 0.0 && StandardMetrics.ms_v_env_on->AsBool()) {
|
|
|
|
// Update energy used and recovered
|
|
|
|
float energy = power / 3600.0; // 1 second worth of energy in kwh's
|
|
|
|
if (energy < 0.0f)
|
|
|
|
StandardMetrics.ms_v_bat_energy_used->SetValue( StandardMetrics.ms_v_bat_energy_used->AsFloat() - energy);
|
|
|
|
else // (energy > 0.0f)
|
|
|
|
StandardMetrics.ms_v_bat_energy_recd->SetValue( StandardMetrics.ms_v_bat_energy_recd->AsFloat() + energy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update derived metrics when charging
|
|
|
|
* Called once per 10 seconds from Ticker10
|
|
|
|
*/
|
|
|
|
void OvmsVehicleRenaultZoePh2::HandleCharging() {
|
|
|
|
float limit_soc = StandardMetrics.ms_v_charge_limit_soc->AsFloat(0);
|
|
|
|
float limit_range = StandardMetrics.ms_v_charge_limit_range->AsFloat(0, Kilometers);
|
|
|
|
float max_range = StandardMetrics.ms_v_bat_range_full->AsFloat(0, Kilometers);
|
|
|
|
float charge_current = StandardMetrics.ms_v_bat_current->AsFloat(0, Amps);
|
|
|
|
float charge_voltage = StandardMetrics.ms_v_bat_voltage->AsFloat(0, Volts);
|
|
|
|
|
|
|
|
// Are we charging?
|
|
|
|
if (!StandardMetrics.ms_v_charge_pilot->AsBool() ||
|
|
|
|
!StandardMetrics.ms_v_charge_inprogress->AsBool() ||
|
|
|
|
(charge_current <= 0.0) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we have what is needed to calculate energy and remaining minutes
|
|
|
|
if (charge_voltage > 0 && charge_current > 0) {
|
|
|
|
// Update energy taken
|
|
|
|
// Value is reset to 0 when a new charging session starts...
|
|
|
|
float power = charge_voltage * charge_current / 1000.0; // power in kw
|
|
|
|
float energy = power / 3600.0 * 10.0; // 10 second worth of energy in kwh's
|
|
|
|
StandardMetrics.ms_v_charge_kwh->SetValue( StandardMetrics.ms_v_charge_kwh->AsFloat() + energy);
|
|
|
|
|
|
|
|
if (limit_soc > 0) {
|
|
|
|
// if limit_soc is set, then calculate remaining time to limit_soc
|
|
|
|
int minsremaining_soc = calcMinutesRemaining(limit_soc, charge_voltage, charge_current);
|
|
|
|
|
|
|
|
StandardMetrics.ms_v_charge_duration_soc->SetValue(minsremaining_soc, Minutes);
|
|
|
|
ESP_LOGV(TAG, "Time remaining: %d mins to %0.0f%% soc", minsremaining_soc, limit_soc);
|
|
|
|
}
|
|
|
|
if (limit_range > 0 && max_range > 0.0) {
|
|
|
|
// if range limit is set, then compute required soc and then calculate remaining time to that soc
|
|
|
|
float range_soc = limit_range / max_range * 100.0;
|
|
|
|
int minsremaining_range = calcMinutesRemaining(range_soc, charge_voltage, charge_current);
|
|
|
|
|
|
|
|
StandardMetrics.ms_v_charge_duration_range->SetValue(minsremaining_range, Minutes);
|
|
|
|
ESP_LOGV(TAG, "Time remaining: %d mins for %0.0f km (%0.0f%% soc)", minsremaining_range, limit_range, range_soc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculates minutes remaining before target is reached. Based on current charge speed.
|
|
|
|
* TODO: Should be calculated based on actual charge curve. Maybe in a later version?
|
|
|
|
*/
|
|
|
|
int OvmsVehicleRenaultZoePh2::calcMinutesRemaining(float target_soc, float charge_voltage, float charge_current) {
|
|
|
|
float bat_soc = StandardMetrics.ms_v_bat_soc->AsFloat(100);
|
|
|
|
if (bat_soc > target_soc) {
|
|
|
|
return 0; // Done!
|
|
|
|
}
|
|
|
|
float remaining_wh = m_battery_capacity * (target_soc - bat_soc) / 100.0;
|
|
|
|
float remaining_hours = remaining_wh / (charge_current * charge_voltage);
|
|
|
|
float remaining_mins = remaining_hours * 60.0;
|
|
|
|
|
|
|
|
return MIN( 1440, (int)remaining_mins );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ConfigChanged: reload single/all configuration variables
|
|
|
|
*/
|
|
|
|
void OvmsVehicleRenaultZoePh2::ConfigChanged(OvmsConfigParam* param) {
|
2022-04-10 18:30:54 +00:00
|
|
|
if (param && param->GetName() != "zph2")
|
2022-04-08 23:03:19 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Renault Zoe/Kangoo reload configuration");
|
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
m_enable_write = MyConfig.GetParamValueBool("zph2", "canwrite", false);
|
|
|
|
m_range_ideal = MyConfig.GetParamValueInt("zph2", "rangeideal", 160);
|
|
|
|
m_battery_capacity = MyConfig.GetParamValueInt("zph2", "battcapacity", 27000);
|
|
|
|
m_enable_egpio = MyConfig.GetParamValueBool("zph2", "enable_egpio", false);
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
m_reset_trip = MyConfig.GetParamValueBool("zph2", "reset.trip.charge", false);
|
|
|
|
m_vehicle_type = MyConfig.GetParamValueInt("zph2", "vehicle.type", 0);
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
StandardMetrics.ms_v_charge_limit_soc->SetValue((float) MyConfig.GetParamValueInt("zph2", "suffsoc", 0), Percentage );
|
|
|
|
StandardMetrics.ms_v_charge_limit_range->SetValue((float) MyConfig.GetParamValueInt("zph2", "suffrange", 0), Kilometers );
|
2022-04-08 23:03:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SetFeature: V2 compatibility config wrapper
|
|
|
|
* Note: V2 only supported integer values, V3 values may be text
|
|
|
|
*/
|
|
|
|
bool OvmsVehicleRenaultZoePh2::SetFeature(int key, const char *value) {
|
|
|
|
switch (key) {
|
|
|
|
case 10:
|
2022-04-10 18:30:54 +00:00
|
|
|
MyConfig.SetParamValue("zph2", "suffsoc", value);
|
2022-04-08 23:03:19 +00:00
|
|
|
return true;
|
|
|
|
case 11:
|
2022-04-10 18:30:54 +00:00
|
|
|
MyConfig.SetParamValue("zph2", "suffrange", value);
|
2022-04-08 23:03:19 +00:00
|
|
|
return true;
|
|
|
|
case 15:
|
|
|
|
{
|
|
|
|
int bits = atoi(value);
|
2022-04-10 18:30:54 +00:00
|
|
|
MyConfig.SetParamValueBool("zph2", "canwrite", (bits& 1)!=0);
|
2022-04-08 23:03:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return OvmsVehicle::SetFeature(key, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetFeature: V2 compatibility config wrapper
|
|
|
|
* Note: V2 only supported integer values, V3 values may be text
|
|
|
|
*/
|
|
|
|
const std::string OvmsVehicleRenaultZoePh2::GetFeature(int key) {
|
|
|
|
switch (key) {
|
|
|
|
case 10:
|
2022-04-10 18:30:54 +00:00
|
|
|
return MyConfig.GetParamValue("zph2", "suffsoc", STR(0));
|
2022-04-08 23:03:19 +00:00
|
|
|
case 11:
|
2022-04-10 18:30:54 +00:00
|
|
|
return MyConfig.GetParamValue("zph2", "suffrange", STR(0));
|
2022-04-08 23:03:19 +00:00
|
|
|
case 15:
|
|
|
|
{
|
2022-04-10 18:30:54 +00:00
|
|
|
int bits = ( MyConfig.GetParamValueBool("zph2", "canwrite", false) ? 1 : 0);
|
2022-04-08 23:03:19 +00:00
|
|
|
char buf[4];
|
|
|
|
sprintf(buf, "%d", bits);
|
|
|
|
return std::string(buf);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return OvmsVehicle::GetFeature(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// RenaultZoeInit
|
|
|
|
//
|
|
|
|
|
|
|
|
class OvmsVehicleRenaultZoePh2Init {
|
|
|
|
public: OvmsVehicleRenaultZoePh2Init();
|
|
|
|
} MyOvmsVehicleRenaultZoePh2Init __attribute__ ((init_priority (9000)));
|
|
|
|
|
|
|
|
OvmsVehicleRenaultZoePh2Init::OvmsVehicleRenaultZoePh2Init() {
|
2022-04-10 18:30:54 +00:00
|
|
|
ESP_LOGI(TAG, "Registering Vehicle: Renault Zoe Ph2 (9000)");
|
2022-04-08 23:03:19 +00:00
|
|
|
|
2022-04-10 18:30:54 +00:00
|
|
|
MyVehicleFactory.RegisterVehicle<OvmsVehicleRenaultZoePh2>("RZ2","Renault Zoe Ph2");
|
2022-04-08 23:03:19 +00:00
|
|
|
}
|