[Ovmsdev] Help me get my first data item on the I3

Michael Balzer dexter at expeedo.de
Sat Dec 12 19:48:38 HKT 2020


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 at 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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20201212/a4c60cb6/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 203 bytes
Desc: OpenPGP digital signature
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20201212/a4c60cb6/attachment-0001.sig>


More information about the OvmsDev mailing list