Skip to content

Commit

Permalink
Twizy: Sevcon monitoring & recording of torque & speed & motor details
Browse files Browse the repository at this point in the history
New commands:
- xrt mon start [<filename>]
- xrt mon stop
- xrt mon reset

New metrics:
xrt.i.cur.act          output current
xrt.i.frq.output       output frequency
xrt.i.frq.slip         slip frequency
xrt.i.pwr.act          output power
xrt.i.trq.act          output torque
xrt.i.trq.demand       torque user demand
xrt.i.trq.limit        torque limit
xrt.i.vlt.act          output voltage
xrt.i.vlt.bat          input voltage
xrt.i.vlt.cap          capacitor voltage
xrt.i.vlt.mod          voltage modulation
xrt.s.b.pwr.drv        max battery drive power by speed
xrt.s.b.pwr.rec        max battery recup power by speed
xrt.s.m.trq.drv        max motor drive torque by speed
xrt.s.m.trq.rec        max motor recup/brake torque by speed
  • Loading branch information
dexterbg committed Nov 10, 2018
1 parent 4a2bc1d commit ed53369
Show file tree
Hide file tree
Showing 10 changed files with 959 additions and 11 deletions.
4 changes: 4 additions & 0 deletions vehicle/OVMS.V3/components/ovms_webserver/assets/ovms.css
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ pre {
.panel-single .panel-footer {
padding: 10px;
}
.panel-single .form-horizontal .form-group {
margin-right: -10px;
margin-left: -10px;
}
}

@media (min-width: 992px) {
Expand Down
Binary file modified vehicle/OVMS.V3/components/ovms_webserver/assets/style.css.gz
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,15 @@ void OvmsVehicleRenaultTwizy::IncomingFrameCan1(CAN_frame_t* p_frame)
break;


case 0x629:
// --------------------------------------------------------------------------
// *** SEVCON status ***
// sent every 100 ms (10 per second) while SEVCON is running
if (m_sevcon)
m_sevcon->QueryMonitoringData();
break;


case 0x69F:
// --------------------------------------------------------------------------
// *** VIN ***
Expand Down
77 changes: 69 additions & 8 deletions vehicle/OVMS.V3/components/vehicle_renaulttwizy/src/rt_sevcon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ using namespace std;
*/

SevconClient::SevconClient(OvmsVehicleRenaultTwizy* twizy)
: m_sync(twizy->m_can1), m_async(twizy->m_can1)
: m_sync(twizy->m_can1), m_async(twizy->m_can1, 50)
{
ESP_LOGI(TAG, "sevcon subsystem init");

Expand All @@ -60,6 +60,9 @@ SevconClient::SevconClient(OvmsVehicleRenaultTwizy* twizy)

m_cfgmode_request = false;

InitMonitoring();
xTaskCreatePinnedToCore(SevconAsyncTaskEntry, "OVMS SevconAsync", 4*1024, (void*)this, 10, &m_asynctask, 1);

// register shell commands:

OvmsCommand *cmd_cfg = m_twizy->cmd_xrt->RegisterCommand("cfg", "SEVCON tuning", NULL, "", 0, 0, true);
Expand Down Expand Up @@ -101,6 +104,13 @@ SevconClient::SevconClient(OvmsVehicleRenaultTwizy* twizy)
cmd_cfg->RegisterCommand("querylogs", "Send SEVCON diag logs to server", shell_cfg_querylogs, "[which=1] [start=0]", 0, 2, true);
cmd_cfg->RegisterCommand("clearlogs", "Clear SEVCON diag logs", shell_cfg_clearlogs, "[which=99]", 0, 1, true);

OvmsCommand *cmd_mon = m_twizy->cmd_xrt->RegisterCommand("mon", "SEVCON monitoring", NULL, "", 0, 0, true);

cmd_mon->RegisterCommand("start", "Start monitoring", shell_mon_start, "[<filename>]", 0, 1, true);
cmd_mon->RegisterCommand("stop", "Stop monitoring", shell_mon_stop, "", 0, 0, true);
cmd_mon->RegisterCommand("reset", "Reset monitoring", shell_mon_reset, "", 0, 0, true);


// TODO:
// lock, unlock, valet, unvalet
// LATER:
Expand All @@ -113,6 +123,7 @@ SevconClient::SevconClient(OvmsVehicleRenaultTwizy* twizy)
using std::placeholders::_1;
using std::placeholders::_2;
MyEvents.RegisterEvent(TAG, "canopen.node.emcy", std::bind(&SevconClient::EmcyListener, this, _1, _2));
MyEvents.RegisterEvent(TAG, "sd.unmounting", std::bind(&SevconClient::UnmountListener, this, _1, _2));

m_kickdown_timer = xTimerCreate("RT kickdown", pdMS_TO_TICKS(100), pdTRUE, NULL, KickdownTimer);
}
Expand All @@ -123,6 +134,8 @@ SevconClient::~SevconClient()
xTimerDelete(m_kickdown_timer, 0);
if (m_faultqueue)
vQueueDelete(m_faultqueue);
if (m_asynctask)
vTaskDelete(m_asynctask);
}

SevconClient* SevconClient::GetInstance(OvmsWriter* writer /*=NULL*/)
Expand All @@ -135,6 +148,17 @@ SevconClient* SevconClient::GetInstance(OvmsWriter* writer /*=NULL*/)
}


void SevconClient::UnmountListener(string event, void* data)
{
// close monitor recording file:
if (m_mon_file) {
OvmsMutexLock lock(&m_mon_mutex);
fclose((FILE*)m_mon_file);
m_mon_file = NULL;
}
}


SevconJob::SevconJob(SevconClient* client)
{
m_client = client;
Expand Down Expand Up @@ -224,6 +248,38 @@ CANopenResult_t SevconClient::GetHeartbeat(CANopenJob& job, CANopenNMTState_t& v
return res;
}

CANopenResult_t SevconClient::SendRead(uint16_t index, uint8_t subindex, uint32_t* value)
{
CANopenResult_t res = CheckBus();
if (res != COR_OK)
return res;
return m_async.ReadSDO(m_nodeid, index, subindex, (uint8_t*)value, sizeof(uint32_t));
}

CANopenResult_t SevconClient::SendRead(uint16_t index, uint8_t subindex, int32_t* value)
{
CANopenResult_t res = CheckBus();
if (res != COR_OK)
return res;
return m_async.ReadSDO(m_nodeid, index, subindex, (uint8_t*)value, sizeof(int32_t));
}

CANopenResult_t SevconClient::SendRead(uint16_t index, uint8_t subindex, uint16_t* value)
{
CANopenResult_t res = CheckBus();
if (res != COR_OK)
return res;
return m_async.ReadSDO(m_nodeid, index, subindex, (uint8_t*)value, sizeof(uint16_t));
}

CANopenResult_t SevconClient::SendRead(uint16_t index, uint8_t subindex, int16_t* value)
{
CANopenResult_t res = CheckBus();
if (res != COR_OK)
return res;
return m_async.ReadSDO(m_nodeid, index, subindex, (uint8_t*)value, sizeof(int16_t));
}

CANopenResult_t SevconClient::SendWrite(uint16_t index, uint8_t subindex, uint32_t* value)
{
CANopenResult_t res = CheckBus();
Expand All @@ -241,12 +297,20 @@ CANopenResult_t SevconClient::SendRequestState(CANopenNMTCommand_t command)
}


void SevconClient::ProcessAsyncResults()
void SevconClient::SevconAsyncTaskEntry(void *pvParameters)
{
SevconClient *me = (SevconClient*)pvParameters;
me->SevconAsyncTask();
}

void SevconClient::SevconAsyncTask()
{
CANopenJob job;
while (m_async.ReceiveDone(job, 0) != COR_ERR_QueueEmpty) {
ESP_LOGD(TAG, "Sevcon async result for %s: %s",
CANopen::GetJobName(job).c_str(), GetResultString(job).c_str());
while (true) {
if (m_async.ReceiveDone(job, portMAX_DELAY) != COR_ERR_QueueEmpty) {
// ESP_LOGD(TAG, "Sevcon async result for %s: %s", CANopen::GetJobName(job).c_str(), GetResultString(job).c_str());
ProcessMonitoringData(job);
}
}
}

Expand Down Expand Up @@ -394,9 +458,6 @@ void SevconClient::Ticker1(uint32_t ticker)
// update metrics:
StdMetrics.ms_v_env_drivemode->SetValue((long) m_drivemode.u32);

// cleanup CANopen job result queue:
ProcessAsyncResults();

// Send fault alerts:
uint16_t faultcode;
while (xQueueReceive(m_faultqueue, &faultcode, 0) == pdTRUE) {
Expand Down
53 changes: 52 additions & 1 deletion vehicle/OVMS.V3/components/vehicle_renaulttwizy/src/rt_sevcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define __rt_sevcon_h__

#include "canopen.h"
#include "rt_sevcon_mon.h"

using namespace std;

Expand Down Expand Up @@ -94,6 +95,10 @@ struct __attribute__ ((__packed__)) cfg_profile
#define cfgvalue(VAL) ((uint8_t)((VAL)+1))


//
// SevconClient: main class
//

class OvmsVehicleRenaultTwizy;
class SevconJob;

Expand All @@ -117,6 +122,7 @@ class SevconClient : public InternalRamAllocated
public:
// Framework interface:
void EmcyListener(string event, void* data);
void UnmountListener(string event, void* data);
void SetStatus(bool car_awake);
void Ticker1(uint32_t ticker);

Expand All @@ -126,6 +132,15 @@ class SevconClient : public InternalRamAllocated
CANopenResult_t Read(CANopenJob& job, uint16_t index, uint8_t subindex, uint32_t& var) {
return Read(job, index, subindex, (uint8_t*)&var, 4);
}
CANopenResult_t Read(CANopenJob& job, uint16_t index, uint8_t subindex, int32_t& var) {
return Read(job, index, subindex, (uint8_t*)&var, 4);
}
CANopenResult_t Read(CANopenJob& job, uint16_t index, uint8_t subindex, uint16_t& var) {
return Read(job, index, subindex, (uint8_t*)&var, 2);
}
CANopenResult_t Read(CANopenJob& job, uint16_t index, uint8_t subindex, int16_t& var) {
return Read(job, index, subindex, (uint8_t*)&var, 2);
}
CANopenResult_t Write(CANopenJob& job, uint16_t index, uint8_t subindex, uint8_t* buf, size_t bufsize);
CANopenResult_t Write(CANopenJob& job, uint16_t index, uint8_t subindex, uint32_t value) {
return Write(job, index, subindex, (uint8_t*)&value, 0);
Expand All @@ -135,9 +150,14 @@ class SevconClient : public InternalRamAllocated

public:
// Asynchronous access:
CANopenResult_t SendRead(uint16_t index, uint8_t subindex, uint32_t* value);
CANopenResult_t SendRead(uint16_t index, uint8_t subindex, int32_t* value);
CANopenResult_t SendRead(uint16_t index, uint8_t subindex, uint16_t* value);
CANopenResult_t SendRead(uint16_t index, uint8_t subindex, int16_t* value);
CANopenResult_t SendWrite(uint16_t index, uint8_t subindex, uint32_t* value);
CANopenResult_t SendRequestState(CANopenNMTCommand_t command);
void ProcessAsyncResults();
static void SevconAsyncTaskEntry(void *pvParameters);
void SevconAsyncTask();

public:
// State management:
Expand Down Expand Up @@ -179,6 +199,12 @@ class SevconClient : public InternalRamAllocated
CANopenResult_t QueryLogs(int verbosity, OvmsWriter* writer, int which, int start, int* totalcnt, int* sendcnt);
CANopenResult_t ResetLogs(int which, int* retcnt);

public:
// Monitoring:
void InitMonitoring();
void QueryMonitoringData();
void ProcessMonitoringData(CANopenJob &job);
void SendMonitoringData();

public:
// Shell commands:
Expand All @@ -205,12 +231,21 @@ class SevconClient : public InternalRamAllocated

static void shell_cfg_querylogs(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv);
static void shell_cfg_clearlogs(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv);

static void shell_mon_start(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv);
static void shell_mon_stop(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv);
static void shell_mon_reset(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv);

private:
OvmsVehicleRenaultTwizy* m_twizy;
const int m_nodeid = 1;
CANopenClient m_sync;
CANopenAsyncClient m_async;
TaskHandle_t m_asynctask = 0;
sc_mondata m_mon = {};
bool m_mon_enable = false;
volatile FILE* m_mon_file = NULL;
OvmsMutex m_mon_mutex;

uint32_t m_sevcon_type;
cfg_drivemode m_drivemode;
Expand Down Expand Up @@ -252,6 +287,10 @@ class SevconClient : public InternalRamAllocated
#define SetValetMode(b) (StdMetrics.ms_v_env_valet->SetValue(b))


//
// SevconJob: SevconClient attached CANopenJob
//

class SevconJob : public InternalRamAllocated
{
public:
Expand All @@ -275,6 +314,18 @@ class SevconJob : public InternalRamAllocated
m_job.Init();
return m_client->Read(m_job, index, subindex, var);
}
CANopenResult_t Read(uint16_t index, uint8_t subindex, int32_t& var) {
m_job.Init();
return m_client->Read(m_job, index, subindex, var);
}
CANopenResult_t Read(uint16_t index, uint8_t subindex, uint16_t& var) {
m_job.Init();
return m_client->Read(m_job, index, subindex, var);
}
CANopenResult_t Read(uint16_t index, uint8_t subindex, int16_t& var) {
m_job.Init();
return m_client->Read(m_job, index, subindex, var);
}
CANopenResult_t Write(uint16_t index, uint8_t subindex, uint8_t* buf, size_t bufsize) {
m_job.Init();
return m_client->Write(m_job, index, subindex, buf, bufsize);
Expand Down
Loading

0 comments on commit ed53369

Please sign in to comment.