Hi Michael,

So I've written something to poll the SOC%.

At this stage I'm trying to debug.  I'm running my code - I configured for my BMWI3 module and my car.

I set log level debug v-bmwi3, log level verbose canlog, and log level canopen.

I can see that can1 is running - I'm sending some packets (I had it poll once per 60 seconds and indeed I'm sending one packet per minute).  

can can1 status says:

OVMS# can can1 status
CAN:       can1
Mode:      Active
Speed:     500000
DBC:       none
Interrupts:                5557
Rx pkt:                    5548
Rx err:                       0
Rx ovrflw:                    0
Tx pkt:                       9
Tx delays:                    0
Tx err:                       0
Tx ovrflw:                    0
Wdg Resets:                   0
Err Resets:                   0
Wdg Timer:                    0 sec(s)
Err flags: 0x00000000

I put "ESP_LOGD(TAG, "BMWI3: got SOC=%3.1f%%", soc);" in my code after parsing the SOC.

But I'm not seeing that log message in the console.

Can I enable a trace of CAN1 (without drowning my box!).  Can I see what gets transmitted?

Thanks,
Steve




On Sat, 12 Dec 2020 at 13:49, Michael Balzer <dexter@expeedo.de> wrote:
Steve,

use the vehicle_obdii module to get into OBD polling on the OVMS.

You begin by defining the poll requests to be sent in at least one array of type OvmsVehicle::poll_pid_t. A request consists of
  • the transmission address (CAN ID), this may be a specific address or the broadcast address 0x7df
  • the expected response address (CAN ID), or 0 in case of a broadcast
  • the type of the request; OBD also calls this "mode", e.g. 0x22, there are preprocessor definitions for all supported types, e.g. 0x22 = VEHICLE_POLL_TYPE_OBDIIEXTENDED
  • optionally the PID to access (depending on the request type, may be none / 8 bit / 16 bit)
  • the poll interval; this may be specified for up to 4 vehicle states (normally used to switch intervals according to the car's operation mode, like sleeping / driving / charging)
  • optionally the CAN bus to use for the request
For your example of polling the SOC, this would be:
  • transmission address: 0x6F1
  • response address: 0x607
  • type: 0x22 or VEHICLE_POLL_TYPE_OBDIIEXTENDED
  • PID: 0xDDBC
  • poll interval: as you like, e.g. { 0, 10, 60 } -- assuming for sleeping, driving, charging
End the array with an all zero entry. The poller will automatically loop over the list.

Call OvmsVehicle::PollSetPidList() to set the array to be used, call OvmsVehicle::PollSetState() to set the vehicle state (defining the poll intervals).

Override OvmsVehicle::IncomingPollReply() with your result processing. The method will be called by the framework for each response part. The framework also supplies polling state variables you can use (see vehicle.h). A typical pattern to collect multiple frames is:

void OvmsVehicleRenaultTwizy::IncomingPollReply(
  canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t length, uint16_t mlremain)
{
  string& rxbuf = twizy_obd_rxbuf;

  // init / fill rx buffer:
  if (m_poll_ml_frame == 0) {
    rxbuf.clear();
    rxbuf.reserve(length + mlremain);
  }
  rxbuf.append((char*)data, length);
  if (mlremain)
    return;
 
  // complete:
  switch (pid) {
    …

This pattern collects the payload in a string buffer, regardless of the length.

Decoding and converting the payload to metrics is up to you, but normally is simple.

For your example:

  …
  // complete:
  switch (pid) {
    case
0xDDBC: {
      unsigned int soc_raw = ((unsigned int)rxbuf[0] << 8) | (unsigned int)rxbuf[1];
      float soc = soc_raw / 10.0f;
      StdMetrics.ms_v_bat_soc->SetValue(soc);
      break;
    }


On your question:

2020-11-15 10:34:36.474 <-- 607␣F1␣03␣7F␣22␣78␣⏎            // this is some unrelated packet?

Actually it's related, it's the first reply of the device and means "I'm busy, but stand by, results will come soon". The poller handles these.

If you want to follow the poller operation, activate debug logging for the vehicle module: log level debug vehicle

There's more on the poller, but that should get you going.

Regards,
Michael


Am 12.12.20 um 10:19 schrieb Steve Davies:
Hi,

Can I ask someone to help me get started with pulling data off the OBD-2 on the I3.

I have info on what works via an LM327 and I know the pids, but it would help me for some pointers as to how to do it on the OVMS.

You know - the goal to get the first one working.

Here's an example definition - the SOC of the main battery.  This is extracted from decompiling a definition file for ediasbas/ediasblib:

(The "_EN" text is translated using Google cloud translate so the German is the original)

The "job" is defined like so:

         {
            "SERVICE" : "22",
            "ID" : "0xDDBC",
            "DIV" : "-",
            "INFO" : "aktueller Anzeige Soc",
            "RES_TABELLE" : "RES_0xDDBC_D",
            "ARG_TABELLE" : "-",
            "EINHEIT" : "-",
            "DATENTYP" : "-",
            "ARG" : "ANZEIGE_SOC",
            "LABEL" : "-",
            "ADD" : "-",
            "MUL" : "-",
            "INFO_EN" : "current advertisement Soc",
            "L/H" : "-",
            "RESULTNAME" : "-",
            "NAME" : "-",
            "SG_ADR" : "-"
         },

The "results" are defined like so:

      "RES_0XDDBC_D" : [
         {
            "DIV" : "10.0",
            "INFO_EN" : "current advertisement Soc",
            "DATENTYP" : "unsigned int",
            "EINHEIT" : "%",
            "INFO" : "aktueller Anzeige Soc",
            "MASKE" : "-",
            "RESULTNAME" : "STAT_ANZEIGE_SOC_WERT",
            "L/H" : "high",
            "MUL" : "1.0",
            "ADD" : "0.0",
            "NAME" : "-"
         },
         {
            "NAME" : "-",
            "ADD" : "0.0",
            "MUL" : "1.0",
            "L/H" : "high",
            "RESULTNAME" : "STAT_MAXIMALE_ANZEIGE_SOC_WERT",
            "INFO" : "obere Grenze des Anzeige Soc",
            "MASKE" : "-",
            "INFO_EN" : "upper limit of the display Soc",
            "EINHEIT" : "%",
            "DATENTYP" : "unsigned int",
            "DIV" : "10.0"
         },
         {
            "RESULTNAME" : "STAT_MINIMALE_ANZEIGE_SOC_WERT",
            "L/H" : "high",
            "MUL" : "1.0",
            "NAME" : "-",
            "ADD" : "0.0",
            "DIV" : "10.0",
            "INFO_EN" : "lower limit of the display Soc",
            "EINHEIT" : "%",
            "DATENTYP" : "unsigned int",
            "INFO" : "untere Grenze des Anzeige Soc",
            "MASKE" : "-"
         }
      ],

I read it that three unsigned ints (16 bits each) are returned.
Each is divided by 10 to return a "%".


I traced an app that can retrieves this parameter using an LM327 based OBD2 interface.

That app initialises the LM327 like so:

2020-11-15 10:34:28.831 --> ATD Return all settings to default
2020-11-15 10:34:28.849 --> ATE0 Disable command echo
2020-11-15 10:34:28.861 --> ATH1 Show CAN message headers
2020-11-15 10:34:28.875 --> ATAL Allow long messages
2020-11-15 10:34:28.887 --> ATPBE101 Set programmable param 0x2c to 0xE1, 0x2d to 0x01
       - 2c=0xE1:
          - 11 bit IDs
          - variable data-length code
          - 11 or 29 bit received IDs
          - use data format ISO 15765-4 (CAN)
       - 2d=0x01
          - Use rate divisor of 1
2020-11-15 10:34:28.901 --> ATSPB Use protocol USER1 CAN (as set above I think)
2020-11-15 10:34:28.949 --> ATBI Bypass initialisation - apparently a bad idea... ?
2020-11-15 10:34:28.964 --> ATSH6F1 Set header bytes to 0x6F1 ( 0x06F1 ? )
2020-11-15 10:34:28.978 --> ATAT0 Disable adaptive timing - wait up to ATSF time
2020-11-15 10:34:28.992 --> ATSTFF Maximum wait



Then, when it fetches this PID it does the following:

2020-11-15 10:34:35.101 --> ATCRA607⏎                       // Listen for 0x607
2020-11-15 10:34:35.114 <-- OK⏎⏎>
2020-11-15 10:34:35.115 --> ATCEA07⏎                        // "extended address" 0x07 [matches 607?]
2020-11-15 10:34:35.127 <-- OK⏎⏎>
2020-11-15 10:34:35.129 --> ATFCSH6F1⏎                      // Flow control header
2020-11-15 10:34:35.141 <-- OK⏎⏎>
2020-11-15 10:34:35.143 --> ATFCSD07300800⏎                 // Flow control data
2020-11-15 10:34:35.156 <-- OK⏎⏎>
2020-11-15 10:34:35.157 --> ATFCSM1⏎                        // Flow control mode
2020-11-15 10:34:35.170 <-- OK⏎⏎>

2020-11-15 10:34:36.367 --> 22␣DD␣BC⏎                       // asking for "extended" PID 0xDDBC
2020-11-15 10:34:36.474 <-- 607␣F1␣03␣7F␣22␣78␣⏎            // this is some unrelated packet?
2020-11-15 10:34:36.539 <-- 607␣F1␣10␣09␣62␣DD␣BC␣02␣4C␣⏎   // reply --> 0x24C = 588 = 58.8 SOC
     607␣F1␣21␣03␣A6␣00␣69␣FF␣FF␣⏎                          // 0x03A6 = = 93.4%, 0x0069 = 10.5%
2020-11-15 10:34:37.598 <-- ⏎>

Remember the LM327 takes the sent bytes and wraps with into a full CAN message - though I'm not sure exactly how that comes out - I presume that "extended address" goes in somewhere.

--> 22 DD BC is the PID
<-- 2 part reply.  First has the SOC.  Second has 0x03A6 (934) and 0x0069 (105)

First int is 588 or 58.8% which is the physical SOC of the battery.
934 is 93.4 which is the physical SOC level which the car displays as "100%" (i3 keeps some headroom "reserved").
105 is 10.5 which is the physical SOC level that the car displays as 0%.

I'd appreciate some help to give me a head-start to be able to retrieve this attribute on the OVMS box.

Thanks,
Steve


_______________________________________________
OvmsDev mailing list
OvmsDev@lists.openvehicles.com
http://lists.openvehicles.com/mailman/listinfo/ovmsdev

-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
_______________________________________________
OvmsDev mailing list
OvmsDev@lists.openvehicles.com
http://lists.openvehicles.com/mailman/listinfo/ovmsdev