<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    Steve,<br>
    <br>
    use the <font face="monospace">vehicle_obdii</font> module to get
    into OBD polling on the OVMS.<br>
    <br>
    You begin by defining the poll requests to be sent in at least one
    array of type <font face="monospace">OvmsVehicle::poll_pid_t</font>.
    A request consists of<br>
    <ul>
      <li>the transmission address (CAN ID), this may be a specific
        address or the broadcast address 0x7df<br>
      </li>
      <li>the expected response address (CAN ID), or 0 in case of a
        broadcast</li>
      <li>the type of the request; OBD also calls this "mode", e.g.
        0x22, there are preprocessor definitions for all supported
        types, e.g. 0x22 = <font face="monospace">VEHICLE_POLL_TYPE_OBDIIEXTENDED</font></li>
      <li>optionally the PID to access (depending on the request type,
        may be none / 8 bit / 16 bit)</li>
      <li>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)</li>
      <li>optionally the CAN bus to use for the request<br>
      </li>
    </ul>
    For your example of polling the SOC, this would be:<br>
    <ul>
      <li>transmission address:<font face="monospace"> 0x6F1</font></li>
      <li>response address: <font face="monospace">0x607</font></li>
      <li>type: <font face="monospace">0x22</font> or <font
          face="monospace">VEHICLE_POLL_TYPE_OBDIIEXTENDED</font></li>
      <li>PID: <font face="monospace">0xDDBC</font></li>
      <li>poll interval: as you like, e.g. <font face="monospace">{ 0,
          10, 60 }</font> -- assuming for sleeping, driving, charging<br>
      </li>
    </ul>
    End the array with an all zero entry. The poller will automatically
    loop over the list.<br>
    <br>
    Call <font face="monospace">OvmsVehicle::PollSetPidList()</font> to
    set the array to be used, call <font face="monospace">OvmsVehicle::PollSetState()</font>
    to set the vehicle state (defining the poll intervals).<br>
    <br>
    Override <font face="monospace">OvmsVehicle::IncomingPollReply()</font>
    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 <font face="monospace">vehicle.h</font>).
    A typical pattern to collect multiple frames is:<br>
    <br>
    <font face="monospace">void
      OvmsVehicleRenaultTwizy::IncomingPollReply(<br>
        canbus* bus, uint16_t type, uint16_t pid, uint8_t* data, uint8_t
      length, uint16_t mlremain)<br>
      {<br>
        string& rxbuf = twizy_obd_rxbuf;<br>
      <br>
        // init / fill rx buffer:<br>
        if (m_poll_ml_frame == 0) {<br>
          rxbuf.clear();<br>
          rxbuf.reserve(length + mlremain);<br>
        }<br>
        rxbuf.append((char*)data, length);<br>
        if (mlremain)<br>
          return;<br>
        <br>
        // complete:<br>
        switch (pid) {<br>
          …<br>
    </font><br>
    This pattern collects the payload in a string buffer, regardless of
    the length.<br>
    <br>
    Decoding and converting the payload to metrics is up to you, but
    normally is simple.<br>
    <br>
    For your example:<br>
    <br>
    <font face="monospace">  …<br>
        // complete:<br>
        switch (pid) {<br>
          case </font><font face="monospace">0xDDBC: {<br>
            unsigned int soc_raw = ((unsigned int)rxbuf[0] << 8) |
      (unsigned int)rxbuf[1];<br>
            float soc = soc_raw / 10.0f;<br>
            StdMetrics.ms_v_bat_soc->SetValue(soc);<br>
            break;<br>
          }<br>
    </font><br>
    <br>
    On your question:<br>
    <br>
    <blockquote type="cite"><font face="monospace">2020-11-15
        10:34:36.474 <-- 607␣F1␣03␣7F␣22␣78␣⏎            // this is
        some unrelated packet?<br>
      </font></blockquote>
    <br>
    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.<br>
    <br>
    If you want to follow the poller operation, activate debug logging
    for the vehicle module: <font face="monospace">log level debug
      vehicle</font><br>
    <br>
    There's more on the poller, but that should get you going.<br>
    <br>
    Regards,<br>
    Michael<br>
    <br>
    <br>
    <div class="moz-cite-prefix">Am 12.12.20 um 10:19 schrieb Steve
      Davies:<br>
    </div>
    <blockquote type="cite"
cite="mid:CABFTEGUqV-uJJhgCy9JKvwYOmfBcqdD-OkqqFrUWWGB0=HOgJw@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr"><img
src="https://api2.activeinboxhq.com/1.0/anon/rr/3cfa1c481eaefb97aafad7ab1f4ae783"
          style="display:none !important" moz-do-not-send="true"
          width="1" height="1">Hi,
        <div><br>
        </div>
        <div>Can I ask someone to help me get started with pulling data
          off the OBD-2 on the I3.</div>
        <div><br>
        </div>
        <div>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.</div>
        <div><br>
        </div>
        <div>You know - the goal to get the first one working.</div>
        <div><br>
        </div>
        <div>Here's an example definition - the SOC of the main
          battery.  This is extracted from decompiling a definition file
          for ediasbas/ediasblib:</div>
        <div><br>
        </div>
        <div>(The "_EN" text is translated using Google cloud translate
          so the German is the original)</div>
        <div><br>
        </div>
        <div>The "job" is defined like so:</div>
        <div><br>
        </div>
        <div> <font face="monospace">        {<br>
                        "SERVICE" : "22",<br>
                        "ID" : "0xDDBC",<br>
                        "DIV" : "-",<br>
                        "INFO" : "aktueller Anzeige Soc",<br>
                        "RES_TABELLE" : "RES_0xDDBC_D",<br>
                        "ARG_TABELLE" : "-",<br>
                        "EINHEIT" : "-",<br>
                        "DATENTYP" : "-",<br>
                        "ARG" : "ANZEIGE_SOC",<br>
                        "LABEL" : "-",<br>
                        "ADD" : "-",<br>
                        "MUL" : "-",<br>
                        "INFO_EN" : "current advertisement Soc",<br>
                        "L/H" : "-",<br>
                        "RESULTNAME" : "-",<br>
                        "NAME" : "-",<br>
                        "SG_ADR" : "-"<br>
                     },<br>
          </font></div>
        <div><br>
        </div>
        <div>The "results" are defined like so:</div>
        <div><br>
        </div>
        <div><font face="monospace">      "RES_0XDDBC_D" : [<br>
                     {<br>
                        "DIV" : "10.0",<br>
                        "INFO_EN" : "current advertisement Soc",<br>
                        "DATENTYP" : "unsigned int",<br>
                        "EINHEIT" : "%",<br>
                        "INFO" : "aktueller Anzeige Soc",<br>
                        "MASKE" : "-",<br>
                        "RESULTNAME" : "STAT_ANZEIGE_SOC_WERT",<br>
                        "L/H" : "high",<br>
                        "MUL" : "1.0",<br>
                        "ADD" : "0.0",<br>
                        "NAME" : "-"<br>
                     },<br>
                     {<br>
                        "NAME" : "-",<br>
                        "ADD" : "0.0",<br>
                        "MUL" : "1.0",<br>
                        "L/H" : "high",<br>
                        "RESULTNAME" : "STAT_MAXIMALE_ANZEIGE_SOC_WERT",<br>
                        "INFO" : "obere Grenze des Anzeige Soc",<br>
                        "MASKE" : "-",<br>
                        "INFO_EN" : "upper limit of the display Soc",<br>
                        "EINHEIT" : "%",<br>
                        "DATENTYP" : "unsigned int",<br>
                        "DIV" : "10.0"<br>
                     },<br>
                     {<br>
                        "RESULTNAME" : "STAT_MINIMALE_ANZEIGE_SOC_WERT",<br>
                        "L/H" : "high",<br>
                        "MUL" : "1.0",<br>
                        "NAME" : "-",<br>
                        "ADD" : "0.0",<br>
                        "DIV" : "10.0",<br>
                        "INFO_EN" : "lower limit of the display Soc",<br>
                        "EINHEIT" : "%",<br>
                        "DATENTYP" : "unsigned int",<br>
                        "INFO" : "untere Grenze des Anzeige Soc",<br>
                        "MASKE" : "-"<br>
                     }<br>
                  ],<br>
          </font></div>
        <div><br>
        </div>
        <div>I read it that three unsigned ints (16 bits each) are
          returned.</div>
        <div>Each is divided by 10 to return a "%".</div>
        <div><br>
        </div>
        <div><br>
        </div>
        <div>I traced an app that can retrieves this parameter using an
          LM327 based OBD2 interface.</div>
        <div><br>
        </div>
        <div>That app initialises the LM327 like so:</div>
        <div><br>
        </div>
        <div><font face="monospace">2020-11-15 10:34:28.831 --> ATD
            Return all settings to default<br>
            2020-11-15 10:34:28.849 --> ATE0 Disable command echo<br>
            2020-11-15 10:34:28.861 --> ATH1 Show CAN message headers<br>
            2020-11-15 10:34:28.875 --> ATAL Allow long messages<br>
            2020-11-15 10:34:28.887 --> ATPBE101 Set programmable
            param 0x2c to 0xE1, 0x2d to 0x01<br>
                   - 2c=0xE1:<br>
                      - 11 bit IDs<br>
                      - variable data-length code<br>
                      - 11 or 29 bit received IDs<br>
                      - use data format ISO 15765-4 (CAN)<br>
                   - 2d=0x01<br>
                      - Use rate divisor of 1<br>
            2020-11-15 10:34:28.901 --> ATSPB Use protocol USER1 CAN
            (as set above I think)<br>
            2020-11-15 10:34:28.949 --> ATBI Bypass initialisation -
            apparently a bad idea... ?<br>
            2020-11-15 10:34:28.964 --> ATSH6F1 Set header bytes to
            0x6F1 ( 0x06F1 ? )<br>
            2020-11-15 10:34:28.978 --> ATAT0 Disable adaptive timing
            - wait up to ATSF time<br>
            2020-11-15 10:34:28.992 --> ATSTFF Maximum wait</font><br>
        </div>
        <div><font face="monospace"><br>
          </font></div>
        <div><br>
        </div>
        <div><font face="arial, sans-serif">Then, when it fetches this
            PID it does the following:</font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">2020-11-15 10:34:35.101 -->
            ATCRA607⏎                       // Listen for 0x607<br>
            2020-11-15 10:34:35.114 <-- OK⏎⏎><br>
            2020-11-15 10:34:35.115 --> ATCEA07⏎                     
              // "extended address" 0x07 [matches 607?]<br>
            2020-11-15 10:34:35.127 <-- OK⏎⏎><br>
            2020-11-15 10:34:35.129 --> ATFCSH6F1⏎                   
              // Flow control header<br>
            2020-11-15 10:34:35.141 <-- OK⏎⏎><br>
            2020-11-15 10:34:35.143 --> ATFCSD07300800⏎             
               // Flow control data<br>
            2020-11-15 10:34:35.156 <-- OK⏎⏎><br>
            2020-11-15 10:34:35.157 --> ATFCSM1⏎                     
              // Flow control mode<br>
            2020-11-15 10:34:35.170 <-- OK⏎⏎><br>
            <br>
            2020-11-15 10:34:36.367 --> 22␣DD␣BC⏎                   
               // asking for "extended" PID 0xDDBC<br>
            2020-11-15 10:34:36.474 <-- 607␣F1␣03␣7F␣22␣78␣⏎         
              // this is some unrelated packet?<br>
            2020-11-15 10:34:36.539 <--
            607␣F1␣10␣09␣62␣DD␣BC␣02␣4C␣⏎   // reply --> 0x24C = 588
            = 58.8 SOC<br>
                 607␣F1␣21␣03␣A6␣00␣69␣FF␣FF␣⏎                         
            // 0x03A6 = = 93.4%, 0x0069 = 10.5%<br>
            2020-11-15 10:34:37.598 <-- ⏎><br>
            <br>
            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.<br>
            <br>
            --> 22 DD BC is the PID<br>
            <-- 2 part reply.  First has the SOC.  Second has 0x03A6
            (934) and 0x0069 (105)<br>
            <br>
            First int is 588 or 58.8% which is the physical SOC of the
            battery.<br>
            934 is 93.4 which is the physical SOC level which the car
            displays as "100%" (i3 keeps some headroom "reserved").<br>
            105 is 10.5 which is the physical SOC level that the car
            displays as 0%.<br>
          </font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">I'd appreciate some help to give me
            a head-start to be able to retrieve this attribute on the
            OVMS box.</font></div>
        <div><font face="monospace"><br>
          </font></div>
        <div><font face="monospace">Thanks,</font></div>
        <div><font face="monospace">Steve</font></div>
        <div><font face="monospace"><br>
          </font></div>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
OvmsDev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:OvmsDev@lists.openvehicles.com">OvmsDev@lists.openvehicles.com</a>
<a class="moz-txt-link-freetext" href="http://lists.openvehicles.com/mailman/listinfo/ovmsdev">http://lists.openvehicles.com/mailman/listinfo/ovmsdev</a>
</pre>
    </blockquote>
    <br>
    <pre class="moz-signature" cols="72">-- 
Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
Fon 02333 / 833 5735 * Handy 0176 / 206 989 26</pre>
  </body>
</html>