2022-04-08 23:03:19 +00:00
/*
; Project : Open Vehicle Monitor System
2022-04-15 14:17:12 +00:00
; Date : 15 th Apr 2022
2022-04-08 23:03:19 +00:00
;
2022-04-15 14:17:12 +00:00
; ( C ) 2022 Carsten Schmiemann
2022-04-08 23:03:19 +00:00
;
; 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 .
*/
2022-04-15 14:17:12 +00:00
2022-04-08 23:03:19 +00:00
# include "ovms_log.h"
# 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-14 22:35:23 +00:00
# include "ph2_poller.h"
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 ) ;
// Zoe CAN bus runs at 500 kbps
RegisterCanBus ( 1 , CAN_MODE_ACTIVE , CAN_SPEED_500KBPS ) ;
// Poll Specific PIDs
2022-04-16 22:02:50 +00:00
POLLSTATE_OFF ;
2022-04-16 02:51:35 +00:00
2022-04-10 18:30:54 +00:00
PollSetPidList ( m_can1 , renault_zoe_polls ) ;
2022-04-18 18:26:15 +00:00
PollSetThrottling ( 10 ) ;
2022-04-08 23:03:19 +00:00
PollSetResponseSeparationTime ( 20 ) ;
// init metrics:
2022-04-18 00:16:56 +00:00
mt_pos_odometer_start = MyMetrics . InitFloat ( " zph2.v.pos.odometer.start " , SM_STALE_MID , 0 , Kilometers ) ;
mt_bus_awake = MyMetrics . InitBool ( " zph2.v.bus.awake " , SM_STALE_MIN , false ) ;
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 ) ;
mt_main_phases = MyMetrics . InitString ( " zph2.c.main.phases " , SM_STALE_MID , 0 ) ;
mt_inv_status = MyMetrics . InitString ( " zph2.m.inverter.status " , SM_STALE_MID , 0 ) ;
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 ) ;
mt_aux_power_consumer = MyMetrics . InitFloat ( " zph2.c.aux.power.consumer " , SM_STALE_MID , 0 , Watts ) ;
mt_aux_power_ptc = MyMetrics . InitFloat ( " zph2.c.aux.power.ptc " , SM_STALE_MID , 0 , Watts ) ;
mt_inv_hv_voltage = MyMetrics . InitFloat ( " zph2.m.inverter.voltage " , SM_STALE_MID , 0 , Volts ) ;
mt_inv_hv_current = MyMetrics . InitFloat ( " zph2.m.inverter.current " , SM_STALE_MID , 0 , Amps ) ;
mt_bat_max_charge_power = MyMetrics . InitFloat ( " zph2.b.max.charge.power " , SM_STALE_MID , 0 , kW ) ;
mt_hvac_compressor_speed = MyMetrics . InitFloat ( " zph2.h.compressor.speed " , SM_STALE_MID , 0 ) ;
mt_hvac_compressor_pressure = MyMetrics . InitFloat ( " zph2.h.compressor.pressure " , SM_STALE_MID , 0 , kPa ) ;
mt_hvac_compressor_power = MyMetrics . InitFloat ( " zph2.h.compressor.power " , SM_STALE_MID , 0 , Watts ) ;
mt_hvac_compressor_mode = MyMetrics . InitString ( " zph2.h.compressor.mode " , SM_STALE_MID , 0 ) ;
2022-04-18 18:26:15 +00:00
mt_pos_car_trip = MyMetrics . InitFloat ( " zph2.v.pos.car.trip " , SM_STALE_MID , 0 , Kilometers ) ;
2022-04-18 00:16:56 +00:00
2022-04-18 01:13:01 +00:00
// get values from config store
m_range_ideal = MyConfig . GetParamValueInt ( " xrz2 " , " rangeideal " , 350 ) ;
m_battery_capacity = MyConfig . GetParamValueInt ( " xrz2 " , " battcapacity " , 52000 ) ;
2022-04-18 18:26:15 +00:00
m_UseCarTrip = MyConfig . GetParamValueBool ( " xrz2 " , " UseCarTrip " , false ) ;
2022-04-18 12:32:33 +00:00
StandardMetrics . ms_v_bat_range_ideal - > SetValue ( m_range_ideal , Kilometers ) ;
2022-04-18 01:13:01 +00:00
2022-04-08 23:03:19 +00:00
// BMS configuration:
2022-04-16 21:11:29 +00:00
BmsSetCellArrangementVoltage ( 96 , 1 ) ;
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 ) ;
2022-04-16 02:51:35 +00:00
BmsSetCellDefaultThresholdsTemperature ( 4.0 , 5.0 ) ;
2022-04-16 04:00:59 +00:00
# ifdef CONFIG_OVMS_COMP_WEBSERVER
WebInit ( ) ;
# endif
2022-04-08 23:03:19 +00:00
}
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
}
/**
* Handles incoming CAN - frames on bus 1
*/
void OvmsVehicleRenaultZoePh2 : : IncomingFrameCan1 ( CAN_frame_t * p_frame ) {
uint8_t * data = p_frame - > data . u8 ;
2022-04-17 07:53:08 +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-16 19:22:38 +00:00
//ESP_LOGD(TAG, "Status CAN Bus: %s", mt_bus_awake->AsBool() ? "true" : "false");
2022-04-16 17:55:43 +00:00
2022-04-16 12:41:36 +00:00
// Poll reply gives 0x83 0xc0 that means zoe is sleeping and CAN gateway does not respond to anything
2022-04-16 18:40:40 +00:00
if ( mt_bus_awake - > AsBool ( ) & & data [ 0 ] = = 0x83 & & data [ 1 ] = = 0xc0 ) {
2022-04-13 20:16:04 +00:00
ESP_LOGI ( TAG , " Zoe has gone to sleep (CAN Gateway NAK response) " ) ;
mt_bus_awake - > SetValue ( false ) ;
2022-04-16 12:41:36 +00:00
StandardMetrics . ms_v_env_awake - > SetValue ( false ) ;
StandardMetrics . ms_v_env_charging12v - > SetValue ( false ) ;
StandardMetrics . ms_v_pos_speed - > SetValue ( 0 ) ;
2022-04-17 23:11:40 +00:00
StandardMetrics . ms_v_bat_12v_current - > SetValue ( 0 ) ;
StandardMetrics . ms_v_charge_12v_current - > SetValue ( 0 ) ;
2022-04-18 11:25:47 +00:00
StandardMetrics . ms_v_bat_current - > SetValue ( 0 ) ;
2022-04-13 20:16:04 +00:00
POLLSTATE_OFF ;
2022-04-16 12:41:36 +00:00
}
//There are some free frames on wakeup and start and stop charging.... I try to use them to see if Car is awake and charging, see /Reference/ZOE_Ph2_xxx text files
2022-04-16 18:40:40 +00:00
if ( ! mt_bus_awake - > AsBool ( ) & & ( data [ 0 ] = = 0x05 | | data [ 0 ] = = 0x06 | | data [ 0 ] = = 0x07 ) ) { //listen for SingleFrames (0x0) with length of 5-7
2022-04-16 12:41:36 +00:00
ESP_LOGI ( TAG , " Zoe woke up (CAN Bus activity detected) " ) ;
2022-04-16 23:16:40 +00:00
mt_bus_awake - > SetValue ( true ) ; ;
2022-04-16 12:41:36 +00:00
StandardMetrics . ms_v_env_awake - > SetValue ( true ) ;
StandardMetrics . ms_v_env_charging12v - > SetValue ( true ) ;
POLLSTATE_ON ;
}
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-16 19:22:38 +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-12 17:57:30 +00:00
2022-04-08 23:03:19 +00:00
// 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 ;
2022-04-14 22:35:23 +00:00
// ****** BCM *****
2022-04-17 11:15:50 +00:00
case 0x765 :
2022-04-14 22:35:23 +00:00
IncomingBCM ( type , pid , rxbuf . data ( ) , rxbuf . size ( ) ) ;
2022-04-08 23:03:19 +00:00
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-13 23:38:32 +00:00
// ****** HVAC *****
2022-04-17 11:15:50 +00:00
case 0x764 :
2022-04-13 23:38:32 +00:00
IncomingHVAC ( type , pid , rxbuf . data ( ) , rxbuf . size ( ) ) ;
2022-04-08 23:03:19 +00:00
break ;
2022-04-14 22:35:23 +00:00
// ****** UCM *****
2022-04-17 11:15:50 +00:00
case 0x76D :
2022-04-14 22:35:23 +00:00
IncomingUCM ( type , pid , rxbuf . data ( ) , rxbuf . size ( ) ) ;
2022-04-18 18:26:15 +00:00
break ;
// ****** CLUSTER *****
case 0x763 :
IncomingCLUSTER ( type , pid , rxbuf . data ( ) , rxbuf . size ( ) ) ;
2022-04-08 23:03:19 +00:00
break ;
}
}
2022-04-17 09:17:54 +00:00
int OvmsVehicleRenaultZoePh2 : : calcMinutesRemaining ( float charge_voltage , float charge_current ) {
float bat_soc = StandardMetrics . ms_v_bat_soc - > AsFloat ( 100 ) ;
float remaining_wh = m_battery_capacity * 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 ) ;
}
2022-04-17 11:48:30 +00:00
//Handle Charging values
2022-04-18 17:21:09 +00:00
void OvmsVehicleRenaultZoePh2 : : ChargeStatistics ( ) {
2022-04-17 09:17:54 +00:00
float charge_current = StandardMetrics . ms_v_bat_current - > AsFloat ( 0 , Amps ) ;
float charge_voltage = StandardMetrics . ms_v_bat_voltage - > AsFloat ( 0 , Volts ) ;
float battery_power = StandardMetrics . ms_v_bat_power - > AsFloat ( 0 , kW ) ;
float charger_power = StandardMetrics . ms_v_charge_power - > AsFloat ( 0 , kW ) ;
2022-04-17 23:07:32 +00:00
float ac_current = StandardMetrics . ms_v_charge_current - > AsFloat ( 0 , Amps ) ;
string ac_phases = mt_main_phases - > AsString ( ) ;
2022-04-17 09:17:54 +00:00
2022-04-17 11:48:30 +00:00
if ( CarIsCharging ! = CarLastCharging ) {
if ( CarIsCharging ) {
StandardMetrics . ms_v_charge_kwh - > SetValue ( 0 ) ;
StandardMetrics . ms_v_charge_inprogress - > SetValue ( CarIsCharging ) ;
} else {
StandardMetrics . ms_v_charge_inprogress - > SetValue ( CarIsCharging ) ;
}
}
CarLastCharging = CarIsCharging ;
2022-04-18 17:21:09 +00:00
if ( ! StandardMetrics . ms_v_charge_pilot - > AsBool ( ) | | ! StandardMetrics . ms_v_charge_inprogress - > AsBool ( ) | | ( charge_current < = 0.0 ) ) {
2022-04-17 09:17:54 +00:00
return ;
}
if ( charge_voltage > 0 & & charge_current > 0 ) {
float power = charge_voltage * charge_current / 1000.0 ;
float energy = power / 3600.0 * 10.0 ;
StandardMetrics . ms_v_charge_kwh - > SetValue ( StandardMetrics . ms_v_charge_kwh - > AsFloat ( ) + energy ) ;
int minsremaining = calcMinutesRemaining ( charge_voltage , charge_current ) ;
2022-04-17 12:25:03 +00:00
StandardMetrics . ms_v_charge_duration_range - > SetValue ( minsremaining / 10 , Minutes ) ;
2022-04-18 01:13:01 +00:00
ESP_LOGV ( TAG , " Charge time remaining: %d mins at %f kW, AC current: %f A with %s " , minsremaining / 10 , charger_power , ac_current , ac_phases . c_str ( ) ) ;
2022-04-17 09:17:54 +00:00
2022-04-17 12:25:03 +00:00
StandardMetrics . ms_v_charge_efficiency - > SetValue ( fabs ( battery_power / charger_power ) * 100.0 ) ;
2022-04-17 09:17:54 +00:00
ESP_LOGD ( TAG , " Charger efficiency %f " , StandardMetrics . ms_v_charge_efficiency - > AsFloat ( 100 ) ) ;
}
}
2022-04-18 17:21:09 +00:00
void OvmsVehicleRenaultZoePh2 : : EnergyStatistics ( ) {
float voltage = StandardMetrics . ms_v_bat_voltage - > AsFloat ( 0 , Volts ) ;
float current = StandardMetrics . ms_v_bat_current - > AsFloat ( 0 , Amps ) ;
float power = voltage * current / 1000.0 ;
StandardMetrics . ms_v_bat_power - > SetValue ( power * - 1.0f ) ;
if ( power ! = 0.0 & & StandardMetrics . ms_v_env_on - > AsBool ( ) ) {
float energy = power / 3600.0 ;
if ( energy < 0.0f )
StandardMetrics . ms_v_bat_energy_used - > SetValue ( StandardMetrics . ms_v_bat_energy_used - > AsFloat ( ) - energy ) ;
else
StandardMetrics . ms_v_bat_energy_recd - > SetValue ( StandardMetrics . ms_v_bat_energy_recd - > AsFloat ( ) + energy ) ;
}
}
void OvmsVehicleRenaultZoePh2 : : Ticker10 ( uint32_t ticker ) {
if ( StandardMetrics . ms_v_charge_pilot - > AsBool ( ) & & ! StandardMetrics . ms_v_env_on - > AsBool ( ) ) {
ChargeStatistics ( ) ;
} else {
EnergyStatistics ( ) ;
}
}
2022-04-18 01:13:01 +00:00
void OvmsVehicleRenaultZoePh2 : : Ticker1 ( uint32_t ticker ) {
2022-04-18 18:26:15 +00:00
if ( StandardMetrics . ms_v_env_on - > AsBool ( ) & & ! CarIsDriving & & ! m_UseCarTrip ) {
2022-04-18 17:21:09 +00:00
CarIsDriving = true ;
//Start trip after power on
StandardMetrics . ms_v_pos_trip - > SetValue ( 0 ) ;
mt_pos_odometer_start - > SetValue ( StandardMetrics . ms_v_pos_odometer - > AsFloat ( 0 ) ) ;
StandardMetrics . ms_v_bat_energy_used - > SetValue ( 0 ) ;
StandardMetrics . ms_v_bat_energy_recd - > SetValue ( 0 ) ;
}
2022-04-18 18:26:15 +00:00
if ( StandardMetrics . ms_v_env_on - > AsBool ( ) & & ! m_UseCarTrip ) {
2022-04-18 01:13:01 +00:00
StandardMetrics . ms_v_pos_trip - > SetValue ( StandardMetrics . ms_v_pos_odometer - > AsFloat ( 0 ) - mt_pos_odometer_start - > AsFloat ( 0 ) ) ;
}
2022-04-18 18:48:43 +00:00
if ( m_UseCarTrip ) {
StandardMetrics . ms_v_pos_trip - > SetValue ( mt_pos_car_trip - > AsFloat ( ) ) ;
}
2022-04-18 18:58:15 +00:00
StandardMetrics . ms_v_bat_range_est - > SetValue ( ( m_range_ideal / ( StandardMetrics . ms_v_bat_soc - > AsFloat ( 1 ) * 0.01 ) ) , Kilometers ) ;
2022-04-18 01:13:01 +00:00
}
2022-04-08 23:03:19 +00:00
class OvmsVehicleRenaultZoePh2Init {
public : OvmsVehicleRenaultZoePh2Init ( ) ;
} MyOvmsVehicleRenaultZoePh2Init __attribute__ ( ( init_priority ( 9000 ) ) ) ;
2022-04-15 14:17:12 +00:00
OvmsVehicleRenaultZoePh2Init : : OvmsVehicleRenaultZoePh2Init ( )
{
ESP_LOGI ( TAG , " Registering Vehicle: Renault Zoe Ph2 (9000) " ) ;
2022-04-10 18:30:54 +00:00
MyVehicleFactory . RegisterVehicle < OvmsVehicleRenaultZoePh2 > ( " RZ2 " , " Renault Zoe Ph2 " ) ;
2022-04-15 14:17:12 +00:00
}