- Added OBD-2 low level access (commands DA & DR)

- Changed USB serial speed to 1 Mbaud
This commit is contained in:
Michael Balzer 2017-07-08 20:57:45 +02:00
parent 53512ccf84
commit 883bbde7e5
3 changed files with 118 additions and 7 deletions

View file

@ -8,6 +8,8 @@ It's a port of my SEVCON core functionality from the [OVMS project](https://gith
**V2** now also supports the OVMS/Twizy tuning macro commands (i.e. `power`, `speed`, `recup` etc.) as well as profile management including saving to / loading from the Arduino EEPROM. Assuming this will be used by hardware hackers, the `brakelight` command has been included as well. Still missing from the OVMS command set is the `clear` command, this is planned to get included along with log access and output. Also missing are all dynamic adjustment functions, i.e. auto drive/recuperation power level following and kickdown.
**V2.1** adds support for low level OBD2 diag requests. Look out for DDT2000 XML files for device IDs, requests and data definitions. There is currently no parsing of the results, output is just the hex encoded data.
Read the OVMS user manual and command overview for details on all commands. You may also like to read the SEVCON Gen4 manual for some basic description of registers. The full register set is documented in the SEVCON master dictionary, which is ©SEVCON. It's contained in the SEVCON DVT package.
Most registers of interest for normal tuning can be found in the [Twizy SDO list](extras/Twizy-SDO-List.ods).
@ -26,8 +28,9 @@ Most registers of interest for normal tuning can be found in the [Twizy SDO list
To download, click the DOWNLOADS button in the top right corner, download the ZIP file. Extract the ZIP, open `TwizyCfg/TwizyCfg.ino` from Arduino IDE.
You will also need this library:
You will also need these libraries:
- [MCP_CAN_lib by Cory Fowler](https://github.com/coryjfowler/MCP_CAN_lib)
- [iso-tp by Heiko Krupp](https://github.com/dexterbg/iso-tp)
Enter your CAN module configuration in the `TwizyCfg_config.h` tab.
@ -39,7 +42,7 @@ Connect to the OBD2 port, switch on the Twizy, start the sketch & open the seria
The Arduino will display a help screen, then wait for your commands:
### Low level commands
### Low level CANopen commands
| Function | Command |
| --- | --- |
@ -82,6 +85,19 @@ The Arduino will display a help screen, then wait for your commands:
- See [Twizy profile converter](https://dexters-web.de/cfgconv)
### Low level OBD-2 commands
| Function | Command |
| --- | --- |
| Set OBD2 device address | `da <sendid> <receiveid>` |
| Send OBD2 request | `dr <hexstring>` |
- See [OBD-II PIDs](https://en.wikipedia.org/wiki/OBD-II_PIDs)
- See [Unified Diagnostic Services](https://en.wikipedia.org/wiki/Unified_Diagnostic_Services)
- Look out for DDT2000 (©Renault) XML files for Renault specific device IDs, requests and data structures
- Check [canbushack.com](http://canbushack.com/) for digging deeper
### Examples
- Get firmware version: `rs 100a 00` (if it's `0712.0003` or higher, the Twizy is locked)
@ -91,6 +107,8 @@ The Arduino will display a help screen, then wait for your commands:
- Set and apply a base64 profile: `set 0 3m9wg295ABozAAAAAAAAAAAuOkVbZVNFNRUrRVtlNSMbJGUAAAABAABlZQAAAAAA` (Twizy needs to be on, not in `GO`)
- Save current profile to EEPROM slot 1: `save 1`
- Reset SEVCON to default configuration: `reset`
- Read DTC from instrument cluster: `da 743 763`, then `dr 2113`
- Read battery health estimation from BMS: `da 79b 7bb`, then `dr 2161`
### Notes

View file

@ -10,19 +10,22 @@
*
* Libraries used:
* - MCP_CAN: https://github.com/coryjfowler/MCP_CAN_lib
* - iso-tp: https://github.com/dexterbg/iso-tp [https://github.com/altelch/iso-tp]
*
* License:
* This is free software under GNU Lesser General Public License (LGPL)
* https://www.gnu.org/licenses/lgpl.html
*
*/
#define TWIZY_CFG_VERSION "V2.0.1 (2017-07-01)"
#define TWIZY_CFG_VERSION "V2.1.0 (2017-07-08)"
#include <EEPROM.h>
#include <mcp_can.h>
#include <mcp_can_dfs.h>
#include <iso-tp.h>
#include "utils.h"
#include "CANopen.h"
#include "Tuning.h"
@ -32,6 +35,10 @@
// CAN interface:
MCP_CAN CAN(TWIZY_CAN_CS_PIN);
// ISO-TP:
IsoTp isotp(&CAN, TWIZY_CAN_IRQ_PIN);
struct Message_t tpMsg;
// Output buffers:
char net_scratchpad[200];
char net_msg_scratchpad[200];
@ -48,7 +55,8 @@ enum cfg_command_id {
cmdPreOp, cmdOp,
cmdSet, cmdReset, cmdGet, cmdInfo, cmdSave, cmdLoad,
cmdDrive, cmdRecup, cmdRamps, cmdRampLimits, cmdSmooth,
cmdSpeed, cmdPower, cmdTSMap, cmdBrakelight
cmdSpeed, cmdPower, cmdTSMap, cmdBrakelight,
cmdDiagAddress, cmdDiagRequest
};
enum cfg_command_mode {
@ -97,6 +105,9 @@ const cfg_command command_table[] PROGMEM = {
{ "TSMAP", cmdTSMap, modePreOp },
{ "BRAKELIGHT", cmdBrakelight, modePreOp },
{ "DA", cmdDiagAddress, modeOffline },
{ "DR", cmdDiagRequest, modeOffline },
};
#define COMMAND_COUNT (sizeof(command_table)/sizeof(cfg_command))
@ -173,6 +184,9 @@ bool exec(char *cmdline)
" tsmap <DNB> <pt1..4> -- set torque speed maps\n"
" brakelight <on> <off> -- set brakelight accel levels\n"
"\n"
" da <sendid> <recvid> -- set OBD2 device address\n"
" dr <hexstring> -- send OBD2 request\n"
"\n"
"See OVMS manual & command overview for details.\n"
"Note: <id> and <sub> are hexadecimal, <val> are decimal\n"
"Examples:\n"
@ -331,6 +345,82 @@ bool exec(char *cmdline)
break;
case cmdDiagAddress:
// DA tx_id_hex rx_id_hex
if (arguments = net_sms_nextarg(arguments))
arg[0] = (int)axtoul(arguments);
if (arguments = net_sms_nextarg(arguments))
arg[1] = (int)axtoul(arguments);
if (!arguments) {
s = stp_rom(s, "ERROR: Too few args");
}
else {
tpMsg.tx_id = arg[0];
tpMsg.rx_id = arg[1];
CAN.init_Filt(1, 0, tpMsg.rx_id << 16);
s = stp_rom(s, "OK");
}
go_op_onexit = false;
break;
case cmdDiagRequest:
// DR hexstring
if (arguments = net_sms_nextarg(arguments)) {
if (strlen(arguments) & 1) {
// input length is odd:
s = stp_rom(s, "ERROR: invalid hex string length");
}
else {
// parse hexstring into scratchpad:
t = (char *) net_msg_scratchpad;
maps[2] = 0;
while (arguments[0]) {
maps[0] = arguments[0];
maps[1] = arguments[1];
*t++ = axtoul(maps);
arguments += 2;
}
}
}
if (!arguments) {
s = stp_rom(s, "ERROR: Too few args");
}
else {
// send request:
tpMsg.Buffer = (uint8_t *)net_msg_scratchpad;
tpMsg.len = (t - (char *)net_msg_scratchpad);
if (err = isotp.send(&tpMsg)) {
s = stp_i(s, "ERROR: isotp.send error code ", err);
}
else {
// read response into scratchpad:
tpMsg.Buffer = (uint8_t *)net_msg_scratchpad;
tpMsg.len = 0;
isotp.receive(&tpMsg);
if (tpMsg.tp_state != ISOTP_FINISHED) {
s = stp_i(s, "ERROR: isotp.receive error code ", tpMsg.tp_state);
}
else {
// output response as hexstring:
Serial.print(net_scratchpad);
net_scratchpad[0] = 0;
for (i=0; i<tpMsg.len; i++) {
if ((byte)net_msg_scratchpad[i] < 0x10)
Serial.print(F("0"));
Serial.print((byte)net_msg_scratchpad[i], HEX);
}
break;
}
}
}
go_op_onexit = false;
break;
case cmdSet:
case cmdReset:
// SET [nr] [base64data]: set complete profile
@ -785,7 +875,7 @@ boolean stringComplete = false; // whether the string is complete
void setup() {
Serial.begin(115200);
Serial.begin(1000000);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

View file

@ -10,11 +10,14 @@
// 1 = show every SDO write
#define TWIZY_DEBUG 0
// Set your MCP clock frequency here:
// Set your CAN MCP clock frequency here:
#define TWIZY_CAN_MCP_FREQ MCP_16MHZ
// Set your SPI CS pin number here:
// Set your CAN CS pin number here:
#define TWIZY_CAN_CS_PIN 53
// Set your CAN IRQ pin here (0 = no IRQ):
#define TWIZY_CAN_IRQ_PIN 0
#endif // _TwizyCfg_config_h