├── .gitignore ├── ELM327.cpp ├── ELM327.h ├── ELM327.zip ├── LICENSE ├── README.md ├── build.sh └── doc ├── ELM327.rst ├── Makefile ├── _build ├── doctrees │ ├── ELM327.doctree │ ├── environment.pickle │ └── index.doctree └── html │ ├── .buildinfo │ ├── ELM327.html │ ├── _sources │ ├── ELM327.txt │ └── index.txt │ ├── _static │ ├── ajax-loader.gif │ ├── basic.css │ ├── comment-bright.png │ ├── comment-close.png │ ├── comment.png │ ├── default.css │ ├── doctools.js │ ├── down-pressed.png │ ├── down.png │ ├── file.png │ ├── jquery.js │ ├── minus.png │ ├── plus.png │ ├── pygments.css │ ├── searchtools.js │ ├── sidebar.js │ ├── underscore.js │ ├── up-pressed.png │ ├── up.png │ └── websupport.js │ ├── genindex.html │ ├── index.html │ ├── objects.inv │ ├── search.html │ └── searchindex.js ├── _static └── .test ├── _templates └── .test ├── conf.py ├── index.rst └── make.bat /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | *.lib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app 22 | -------------------------------------------------------------------------------- /ELM327.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 David Irvine 2 | * 3 | * This program is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | * 16 | */ 17 | 18 | 19 | 20 | #include "ELM327.h" 21 | 22 | byte Elm327::begin(){ 23 | ELM_PORT.begin(ELM_BAUD_RATE); 24 | char data[20]; 25 | runCommand("AT E0",data,20); 26 | return runCommand("AT SP 0",data,20); 27 | } 28 | 29 | byte Elm327::engineLoad(byte &load){ 30 | byte status; 31 | byte values[1]; 32 | status=getBytes("01","41","04",values,1); 33 | if (status != ELM_SUCCESS){ 34 | return status; 35 | } 36 | load=values[0]*100/255; 37 | return ELM_SUCCESS; 38 | } 39 | 40 | byte Elm327::coolantTemperature(int &temp){ 41 | byte status; 42 | byte values[1]; 43 | status=getBytes("01","41","05",values,1); 44 | if (status != ELM_SUCCESS){ 45 | return status; 46 | } 47 | temp=values[0]-40; 48 | return ELM_SUCCESS; 49 | } 50 | 51 | byte Elm327::getFuelTrim(const char *pid, int &percent){ 52 | byte status; 53 | byte values[1]; 54 | status=getBytes("01","41",pid,values,1); 55 | if (status != ELM_SUCCESS){ 56 | return status; 57 | } 58 | percent=(values[0] - 128) * 100/128; 59 | return ELM_SUCCESS; 60 | } 61 | 62 | byte Elm327::fuelTrimBank1ShortTerm(int &percent){ 63 | return getFuelTrim("06",percent); 64 | } 65 | byte Elm327::fuelTrimBank1LongTerm(int &percent){ 66 | return getFuelTrim("07",percent); 67 | } 68 | byte Elm327::fuelTrimBank2ShortTerm(int &percent){ 69 | return getFuelTrim("08",percent); 70 | } 71 | byte Elm327::fuelTrimBank2LongTerm(int &percent){ 72 | return getFuelTrim("09",percent); 73 | } 74 | 75 | byte Elm327::fuelPressure(int &pressure){ 76 | byte status; 77 | byte values[1]; 78 | char mode[]="01"; 79 | char chkMode[]="41"; 80 | char pid[]="0A"; 81 | status=getBytes("01","41","0A",values,1); 82 | if (status != ELM_SUCCESS){ 83 | return status; 84 | } 85 | pressure=values[0]*3; 86 | return ELM_SUCCESS; 87 | } 88 | 89 | byte Elm327::intakeManifoldAbsolutePressure(byte &pressure){ 90 | byte status; 91 | byte values[1]; 92 | status=getBytes("01","41","0B",values,1); 93 | if (status != ELM_SUCCESS){ 94 | return status; 95 | } 96 | pressure=values[0]; 97 | return ELM_SUCCESS; 98 | } 99 | 100 | byte Elm327::engineRPM(int &rpm){ 101 | byte status; 102 | byte values[2]; 103 | status=getBytes("01","41","0C",values,2); 104 | if (status != ELM_SUCCESS){ 105 | return status; 106 | } 107 | rpm=((values[0]*256)+values[1])/4; 108 | return ELM_SUCCESS; 109 | } 110 | 111 | byte Elm327::vehicleSpeed(byte &speed){ 112 | byte status; 113 | byte values[1]; 114 | status=getBytes("01","41","0D",values,1); 115 | if (status != ELM_SUCCESS){ 116 | return status; 117 | } 118 | speed=values[0]; 119 | return ELM_SUCCESS; 120 | } 121 | byte Elm327::timingAdvance(int &advance){ 122 | byte status; 123 | byte values[1]; 124 | status=getBytes("01","41","0E",values,1); 125 | if (status != ELM_SUCCESS){ 126 | return status; 127 | } 128 | advance=values[0]/2-64; 129 | return ELM_SUCCESS; 130 | } 131 | 132 | byte Elm327::intakeAirTemperature(int &temperature){ 133 | byte status; 134 | byte values[1]; 135 | status=getBytes("01","41","0F",values,1); 136 | if (status != ELM_SUCCESS){ 137 | return status; 138 | } 139 | temperature=values[0]-40; 140 | return ELM_SUCCESS; 141 | } 142 | 143 | byte Elm327::MAFAirFlowRate(unsigned int &rate){ 144 | byte status; 145 | byte values[2]; 146 | status=getBytes("01","41","10",values,2); 147 | if (status != ELM_SUCCESS){ 148 | return status; 149 | } 150 | rate = ((256 * values[0]) + values[1])/100 ; 151 | return ELM_SUCCESS; 152 | } 153 | 154 | byte Elm327::throttlePosition(byte &position){ 155 | byte status; 156 | byte values[1]; 157 | status=getBytes("01","41","11",values,1); 158 | if (status != ELM_SUCCESS){ 159 | return status; 160 | } 161 | position=(values[0]*100)/255; 162 | return ELM_SUCCESS; 163 | } 164 | 165 | byte Elm327::o2SensorBank1Sensor1(byte &voltage, byte &trim){ 166 | return o2sensorRead("14", voltage, trim); 167 | } 168 | byte Elm327::o2SensorBank1Sensor2(byte &voltage, byte &trim){ 169 | return o2sensorRead("15", voltage, trim); 170 | } 171 | byte Elm327::o2SensorBank1Sensor3(byte &voltage, byte &trim){ 172 | return o2sensorRead("16", voltage, trim); 173 | } 174 | byte Elm327::o2SensorBank1Sensor4(byte &voltage, byte &trim){ 175 | return o2sensorRead("17", voltage, trim); 176 | } 177 | byte Elm327::o2SensorBank2Sensor1(byte &voltage, byte &trim){ 178 | return o2sensorRead("18", voltage, trim); 179 | } 180 | byte Elm327::o2SensorBank2Sensor2(byte &voltage, byte &trim){ 181 | return o2sensorRead("19", voltage, trim); 182 | } 183 | byte Elm327::o2SensorBank2Sensor3(byte &voltage, byte &trim){ 184 | return o2sensorRead("1A", voltage, trim); 185 | } 186 | byte Elm327::o2SensorBank2Sensor4(byte &voltage, byte &trim){ 187 | return o2sensorRead("1B", voltage, trim); 188 | } 189 | 190 | byte Elm327::o2sensorRead(const char *bank, byte &voltage, byte &trim){ 191 | byte status; 192 | byte values[2]; 193 | status=getBytes("01","41",bank,values,2); 194 | if (status != ELM_SUCCESS){ 195 | return status; 196 | } 197 | voltage = values[0] / 200; 198 | trim=( values[1] * 100 ) / 128; 199 | return ELM_SUCCESS; 200 | } 201 | 202 | 203 | byte Elm327::auxiliaryInputStatus(bool &auxStatus){ 204 | byte status; 205 | byte values[1]; 206 | status=getBytes("01","41","1E",values,1); 207 | if (status != ELM_SUCCESS){ 208 | return status; 209 | } 210 | auxStatus=getBit(values[0], 1); 211 | return ELM_SUCCESS; 212 | } 213 | 214 | byte Elm327::engineRunTime(unsigned int &runTime){ 215 | byte status; 216 | byte values[2]; 217 | status=getBytes("01","41","1F",values,2); 218 | if (status != ELM_SUCCESS){ 219 | return status; 220 | } 221 | runTime=(values[0]*256)+values[1]; 222 | return ELM_SUCCESS; 223 | } 224 | 225 | byte Elm327::distanceMIL(unsigned int &distance){ 226 | byte status; 227 | byte values[2]; 228 | status=getBytes("01","41","21",values,2); 229 | if (status != ELM_SUCCESS){ 230 | return status; 231 | } 232 | distance=(values[0]*256)+values[1]; 233 | return ELM_SUCCESS; 234 | } 235 | 236 | byte Elm327::relativeFuelRailPressure(unsigned int &pressure){ 237 | byte status; 238 | byte values[2]; 239 | status=getBytes("01","41","22",values,2); 240 | if (status != ELM_SUCCESS){ 241 | return status; 242 | } 243 | pressure=((values[0]*256)+values[1])*0.079; 244 | return ELM_SUCCESS; 245 | } 246 | 247 | byte Elm327::absoluteFuelRailPressure(unsigned int &pressure){ 248 | byte status; 249 | byte values[2]; 250 | status=getBytes("01","41","23",values,2); 251 | if (status != ELM_SUCCESS){ 252 | return status; 253 | } 254 | pressure=((values[0]*256)+values[1])*10; 255 | return ELM_SUCCESS; 256 | } 257 | 258 | 259 | byte Elm327::o2S1WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 260 | return o2WRVoltage("24", equivRatio, voltage); 261 | } 262 | byte Elm327::o2S2WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 263 | return o2WRVoltage("25", equivRatio, voltage); 264 | } 265 | byte Elm327::o2S3WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 266 | return o2WRVoltage("26", equivRatio, voltage); 267 | } 268 | byte Elm327::o2S4WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 269 | return o2WRVoltage("27", equivRatio, voltage); 270 | } 271 | byte Elm327::o2S5WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 272 | return o2WRVoltage("28", equivRatio, voltage); 273 | } 274 | byte Elm327::o2S6WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 275 | return o2WRVoltage("29", equivRatio, voltage); 276 | } 277 | byte Elm327::o2S7WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 278 | return o2WRVoltage("2A", equivRatio, voltage); 279 | } 280 | byte Elm327::o2S8WRVoltage(unsigned int &equivRatio, unsigned int &voltage){ 281 | return o2WRVoltage("2B", equivRatio, voltage); 282 | } 283 | byte Elm327::o2WRVoltage(const char *sensor, unsigned int &equivRatio, unsigned int &voltage){ 284 | byte status; 285 | byte values[4]; 286 | status=getBytes("01","41",sensor,values,4); 287 | if (status != ELM_SUCCESS){ 288 | return status; 289 | } 290 | equivRatio=((values[0] * 256)+ values[1])*2/65535; // or ((A*256)+B)/32768 291 | voltage=((values[2]*256)+values[3])*8/65535;// or ((C*256)+D)/8192; 292 | return ELM_SUCCESS; 293 | } 294 | 295 | byte Elm327::commandedEGR(byte &egr){ 296 | byte status; 297 | byte values[1]; 298 | status=getBytes("01","41","2C",values,1); 299 | if (status != ELM_SUCCESS){ 300 | return status; 301 | } 302 | egr=(100 * values[0])/255; 303 | return ELM_SUCCESS; 304 | } 305 | 306 | byte Elm327::EGRError(int &error){ 307 | byte status; 308 | byte values[1]; 309 | status=getBytes("01","41","2D",values,1); 310 | if (status != ELM_SUCCESS){ 311 | return status; 312 | } 313 | error =(values[0]-128)*100/128; 314 | return ELM_SUCCESS; 315 | } 316 | 317 | byte Elm327::commandedEvaporativePurge(byte &purge){ 318 | byte status; 319 | byte values[1]; 320 | status=getBytes("01","41","2E",values,1); 321 | if (status != ELM_SUCCESS){ 322 | return status; 323 | } 324 | purge= (100 * values[0])/255; 325 | return ELM_SUCCESS; 326 | } 327 | 328 | byte Elm327::fuelLevel(byte &level){ 329 | byte status; 330 | byte values[1]; 331 | status=getBytes("01","41","2F",values,1); 332 | if (status != ELM_SUCCESS){ 333 | return status; 334 | } 335 | level= (100 * values[0])/255; 336 | return ELM_SUCCESS; 337 | } 338 | 339 | byte Elm327::warmUpsSinceLastCleared(byte &warmUps){ 340 | byte status; 341 | byte values[1]; 342 | status=getBytes("01","41","30",values,1); 343 | if (status != ELM_SUCCESS){ 344 | return status; 345 | } 346 | warmUps=values[0]; 347 | return ELM_SUCCESS; 348 | } 349 | 350 | byte Elm327::distanceSinceLastCleared(unsigned int &distance){ 351 | byte status; 352 | byte values[2]; 353 | status=getBytes("01","41","31",values,2); 354 | if (status != ELM_SUCCESS){ 355 | return status; 356 | } 357 | distance=(values[0]*256) + values[1]; 358 | return ELM_SUCCESS; 359 | } 360 | 361 | byte Elm327::evapPressure(int &pressure){ 362 | byte status; 363 | byte values[2]; 364 | status=getBytes("01","41","32",values,2); 365 | if (status != ELM_SUCCESS){ 366 | return status; 367 | } 368 | pressure=(256*(values[0]-128) + values[1])/4; 369 | return ELM_SUCCESS; 370 | } 371 | 372 | byte Elm327::fuelInjectionTiming(float &position) 373 | { 374 | byte status; 375 | byte values[2]; 376 | status = getBytes("01", "41", "5D", values, 2); 377 | if (status != ELM_SUCCESS){ 378 | return status; 379 | } 380 | position = ((float)((values[0] * 256) + values[1]) - 26.880) / 128; 381 | return ELM_SUCCESS; 382 | } 383 | 384 | byte Elm327::engineFuelRate(float &rate) 385 | { 386 | byte status; 387 | byte values[2]; 388 | status = getBytes("01", "41", "5E", values, 2); 389 | if (status != ELM_SUCCESS){ 390 | return status; 391 | } 392 | rate = ((float)(values[0] * 256) + values[1])*0.05; 393 | return ELM_SUCCESS; 394 | } 395 | 396 | byte Elm327::driverDemandEngineTorque(byte &torque) 397 | { 398 | byte status; 399 | byte values[1]; 400 | status = getBytes("01", "41", "61", values, 1); 401 | if (status != ELM_SUCCESS){ 402 | return status; 403 | } 404 | torque = values[0] - 125; 405 | return ELM_SUCCESS; 406 | } 407 | 408 | byte Elm327::actualEngineTorque(byte &torque) 409 | { 410 | byte status; 411 | byte values[1]; 412 | status = getBytes("01", "41", "62", values, 1); 413 | if (status != ELM_SUCCESS){ 414 | return status; 415 | } 416 | torque = values[0] - 125; 417 | return ELM_SUCCESS; 418 | } 419 | 420 | 421 | byte Elm327::barometricPressure(byte &pressure){ 422 | byte status; 423 | byte values[1]; 424 | status=getBytes("01","41","33",values,1); 425 | if (status != ELM_SUCCESS){ 426 | return status; 427 | } 428 | pressure=values[0]; 429 | return ELM_SUCCESS; 430 | } 431 | 432 | 433 | byte Elm327::o2WRCurrent(const char *sensor, unsigned int &equivRatio, int ¤t){ 434 | byte status; 435 | byte values[4]; 436 | status=getBytes("01","41",sensor,values,4); 437 | if (status != ELM_SUCCESS){ 438 | return status; 439 | } 440 | equivRatio=((values[0] * 256)+ values[1])*2/32768; 441 | current=((values[2]*256)+values[3])*8/265-128; 442 | return ELM_SUCCESS; 443 | } 444 | 445 | byte Elm327::o2S1WRCurrent(unsigned int &equivRatio, int ¤t){ 446 | return o2WRCurrent("34",equivRatio,current); 447 | } 448 | byte Elm327::o2S2WRCurrent(unsigned int &equivRatio, int ¤t){ 449 | return o2WRCurrent("35",equivRatio,current); 450 | } 451 | byte Elm327::o2S3WRCurrent(unsigned int &equivRatio, int ¤t){ 452 | return o2WRCurrent("36",equivRatio,current); 453 | } 454 | byte Elm327::o2S4WRCurrent(unsigned int &equivRatio, int ¤t){ 455 | return o2WRCurrent("37",equivRatio,current); 456 | } 457 | byte Elm327::o2S5WRCurrent(unsigned int &equivRatio, int ¤t){ 458 | return o2WRCurrent("38",equivRatio,current); 459 | } 460 | byte Elm327::o2S6WRCurrent(unsigned int &equivRatio, int ¤t){ 461 | return o2WRCurrent("39",equivRatio,current); 462 | } 463 | byte Elm327::o2S7WRCurrent(unsigned int &equivRatio, int ¤t){ 464 | return o2WRCurrent("3A",equivRatio,current); 465 | } 466 | byte Elm327::o2S8WRCurrent(unsigned int &equivRatio, int ¤t){ 467 | return o2WRCurrent("3B",equivRatio,current); 468 | } 469 | 470 | byte Elm327::catalystTemperatureBank1Sensor1(int &temperature) 471 | { 472 | return catTemperature("3C", temperature); 473 | } 474 | byte Elm327::catalystTemperatureBank2Sensor1(int &temperature) 475 | { 476 | return catTemperature("3D", temperature); 477 | } 478 | byte Elm327::catalystTemperatureBank1Sensor2(int &temperature) 479 | { 480 | return catTemperature("3E", temperature); 481 | } 482 | byte Elm327::catalystTemperatureBank2Sensor2(int &temperature) 483 | { 484 | return catTemperature("3F", temperature); 485 | } 486 | 487 | byte Elm327::catTemperature(const char *sensor, int &temperature){ 488 | byte status; 489 | byte values[2]; 490 | status=getBytes("01","41",sensor,values,2); 491 | if (status != ELM_SUCCESS){ 492 | return status; 493 | } 494 | temperature=((values[0]*256)+values[1])/10 - 40; 495 | return ELM_SUCCESS; 496 | } 497 | 498 | byte Elm327::controlModuleVoltage(unsigned int &voltage){ 499 | byte status; 500 | byte values[2]; 501 | status=getBytes("01","41","42",values,2); 502 | if (status != ELM_SUCCESS){ 503 | return status; 504 | } 505 | voltage=((values[0]*256)+values[1])/1000; 506 | return ELM_SUCCESS; 507 | } 508 | 509 | byte Elm327::absoluteLoadValue(unsigned int &load){ 510 | byte status; 511 | byte values[2]; 512 | status=getBytes("01","41","43",values,2); 513 | if (status != ELM_SUCCESS){ 514 | return status; 515 | } 516 | load=((values[0]*256)+values[1])*100/255; 517 | return ELM_SUCCESS; 518 | } 519 | 520 | byte Elm327::commandEquivalenceRatio(float &ratio){ 521 | byte status; 522 | byte values[2]; 523 | status=getBytes("01","41","44",values,2); 524 | if (status != ELM_SUCCESS){ 525 | return status; 526 | } 527 | ratio=((values[0]*256)+values[1])/32768; 528 | return ELM_SUCCESS; 529 | } 530 | 531 | 532 | byte Elm327::relativeThrottlePosition(byte &position){ 533 | byte status; 534 | byte values[1]; 535 | status=getBytes("01","41","45",values,1); 536 | if (status != ELM_SUCCESS){ 537 | return status; 538 | } 539 | position=(100*values[0])/255; 540 | return ELM_SUCCESS; 541 | } 542 | 543 | byte Elm327::ambientAirTemperature(int &temperature){ 544 | byte status; 545 | byte values[1]; 546 | status=getBytes("01","41","46",values,1); 547 | if (status != ELM_SUCCESS){ 548 | return status; 549 | } 550 | temperature=values[0]-40; 551 | return ELM_SUCCESS; 552 | } 553 | 554 | byte Elm327::absoluteThrottlePositionB(byte &position){ 555 | byte status; 556 | byte values[1]; 557 | status=getBytes("01","41","47",values,1); 558 | if (status != ELM_SUCCESS){ 559 | return status; 560 | } 561 | position=(100*values[0])/255; 562 | return ELM_SUCCESS; 563 | } 564 | byte Elm327::absoluteThrottlePositionC(byte &position){ 565 | byte status; 566 | byte values[1]; 567 | status=getBytes("01","41","48",values,1); 568 | if (status != ELM_SUCCESS){ 569 | return status; 570 | } 571 | position=(100*values[0])/255; 572 | return ELM_SUCCESS; 573 | } 574 | byte Elm327::acceleratorPedalPositionD(byte &position){ 575 | byte status; 576 | byte values[1]; 577 | status=getBytes("01","41","49",values,1); 578 | if (status != ELM_SUCCESS){ 579 | return status; 580 | } 581 | position=(100*values[0])/255; 582 | return ELM_SUCCESS; 583 | } 584 | byte Elm327::acceleratorPedalPositionE(byte &position){ 585 | byte status; 586 | byte values[1]; 587 | status=getBytes("01","41","4A",values,1); 588 | if (status != ELM_SUCCESS){ 589 | return status; 590 | } 591 | position=(100*values[0])/255; 592 | return ELM_SUCCESS; 593 | } 594 | byte Elm327::acceleratorPedalPositionF(byte &position){ 595 | byte status; 596 | byte values[1]; 597 | status=getBytes("01","41","4B",values,1); 598 | if (status != ELM_SUCCESS){ 599 | return status; 600 | } 601 | position=(100*values[0])/255; 602 | return ELM_SUCCESS; 603 | } 604 | byte Elm327::commandedThrottleActuator(byte &position){ 605 | byte status; 606 | byte values[1]; 607 | status=getBytes("01","41","4C",values,1); 608 | if (status != ELM_SUCCESS){ 609 | return status; 610 | } 611 | position=(100*values[0])/255; 612 | return ELM_SUCCESS; 613 | } 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | byte Elm327::getBytes( const char *mode, const char *chkMode, const char *pid, byte *values, unsigned int numValues){ 622 | char data[64]; 623 | byte status; 624 | char hexVal[]="0x00"; 625 | char cmd[6]; 626 | cmd[0]=mode[0]; 627 | cmd[1]=mode[1]; 628 | cmd[2]=' '; 629 | cmd[3]=pid[0]; 630 | cmd[4]=pid[1]; 631 | cmd[5]='\0'; 632 | 633 | status=runCommand(cmd,data,64); 634 | if ( status != ELM_SUCCESS ) 635 | { 636 | return status; 637 | }; 638 | 639 | // Check the mode returned was the one we sent 640 | if ( data[0]!=chkMode[0] 641 | or data[1]!=chkMode[1] 642 | or data[3]!=pid[0] 643 | or data[4]!=pid[1] ){ 644 | return ELM_GARBAGE; 645 | } 646 | 647 | // For each byte expected, package it up 648 | int i=0; 649 | for (int i=0; i 675 | // has been returned. 676 | // 677 | counter=0; 678 | timeOut=millis()+ELM_TIMEOUT; 679 | found=false; 680 | while (!found && counter<( dataLength ) && millis()' ){ 685 | found=true; 686 | data[counter]='\0'; 687 | }else{ 688 | ++counter; 689 | } 690 | } 691 | } 692 | // If there is still data pending to be read, raise OVERFLOW error. 693 | if (!found && counter>=dataLength) 694 | { 695 | // Send a character, this should cancel any operation on the elm device 696 | // so that it doesnt spuriously inject a response during the next 697 | // command 698 | ELM_PORT.print("XXXXXXXXX\r\r\r"); 699 | delay(300); 700 | return ELM_BUFFER_OVERFLOW; 701 | } 702 | 703 | // If not found, and there is still buffer space, then raise no response error. 704 | if (!found && counter= 0) 774 | ; // do nothing 775 | } 776 | 777 | /** returns the value of the specified bit p in byte b 778 | */ 779 | bool Elm327::getBit(byte b, byte p) 780 | { 781 | b<<=(7-p); 782 | if (b>=127){ 783 | return true; 784 | } 785 | return false; 786 | } 787 | 788 | -------------------------------------------------------------------------------- /ELM327.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2011 David Irvine 2 | * 3 | * This program is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | * 16 | */ 17 | 18 | 19 | #ifndef ELM327_h 20 | #define ELM327_h 21 | #include "Arduino.h" 22 | 23 | #ifndef ELM_TIMEOUT 24 | #warning "ELM_TIMEOUT must be defined." 25 | #define ELM_TIMEOUT 9000 26 | #endif 27 | 28 | #ifndef ELM_BAUD_RATE 29 | #warning "ELM_BAUD_RATE must be defined" 30 | #define ELM_BAUD_RATE 9600 31 | #endif 32 | 33 | #ifndef ELM_PORT 34 | #warning "ELM_PORT is not defined, using default value" 35 | #define ELM_PORT Serial 36 | #endif 37 | 38 | #define ELM_SUCCESS 0 39 | 40 | #define ELM_NO_RESPONSE 1 41 | 42 | #define ELM_BUFFER_OVERFLOW 2 43 | 44 | #define ELM_GARBAGE 3 45 | 46 | #define ELM_UNABLE_TO_CONNECT 4 47 | 48 | #define ELM_NO_DATA 5 49 | 50 | 51 | 52 | 53 | class Elm327 54 | { 55 | public: 56 | 57 | 58 | byte begin(); 59 | byte getVersion(String &rev); 60 | byte getIgnMon(bool &powered); 61 | byte getVoltage(float &voltage); 62 | byte engineLoad(byte &load); 63 | 64 | 65 | /** 66 | * Gets the Coolant Temperature. Reads PID 05 from the OBD interface and sets 67 | * temp to the value returned after conversion. 68 | * @param[out] temp Signed integer value is set to the coolant temperature. 69 | * - Minimum: -40 70 | * - Maximum Value: 215 71 | * - Units: °C 72 | */ 73 | byte coolantTemperature(int &temp); 74 | 75 | 76 | /** 77 | * Gets the fuel trim for bank 1 in the short term. Reads PID 06 from the OBD 78 | * interface and sets percent to the value returned after conversion. 79 | * @param[out] percent - Signed integer is set to the percent fuel trim. 80 | * - Minimum Value: -100 81 | * - Maximum Value: 99.2 82 | * - Units: % 83 | */ 84 | byte fuelTrimBank1ShortTerm(int &percent); 85 | 86 | 87 | /** 88 | * Gets the fuel trim for bank 2 in the short term. Reads PID 07 from the OBD 89 | * interface and sets percent to the value returned after conversion. 90 | * @param[out] percent - Signed integer is set to the percent fuel trim. 91 | * - Minimum Value: -100 92 | * - Maximum Value: 99.2 93 | * - Units: % 94 | */ 95 | byte fuelTrimBank2ShortTerm(int &percent); 96 | 97 | 98 | /** 99 | * Gets the fuel trim for bank 1 in the long term. Reads PID 08 from the OBD 100 | * interface and sets percent to the value returned after conversion. 101 | * @param[out] percent - Signed integer is set to the percent fuel trim. 102 | * - Minimum Value: -100 103 | * - Maximum Value: 99.2 104 | * - Units: % 105 | */ 106 | byte fuelTrimBank1LongTerm(int &percent); 107 | 108 | 109 | /** 110 | * Gets the fuel trim for bank 2 in the long term. Reads PID 09 from the OBD 111 | * interface and sets percent to the value returned after conversion. 112 | * @param[out] percent - Signed integer is set to the percent fuel trim. 113 | * - Minimum Value: -100 114 | * - Maximum Value: 99.2 115 | * - Units: % 116 | */ 117 | byte fuelTrimBank2LongTerm(int &percent); 118 | 119 | 120 | /** 121 | * Gets the fuel pressure. Reads PID 0A from the OBD interface and sets pressure 122 | * to the value returned after conversion. 123 | * @param[out] pressure - Signed integer is set to the fuel pressure. 124 | * - Minimum Value: 0 125 | * - Maximum Value: 765 126 | * - Units: kPa (Absolute) 127 | */ 128 | byte fuelPressure(int &pressure); 129 | 130 | 131 | /** 132 | * Gets the Intake Manifold Absolute Pressure. Reads PID 0B from the OBD 133 | * inteface and sets pressure to the value returned after conversion. 134 | *@param[out] pressure Byte set to the manifold pressure 135 | * - Minimum Value: 0 136 | * - Maximum Value: 255 137 | * - Units: kPa (Absolute) 138 | */ 139 | byte intakeManifoldAbsolutePressure(byte &pressure); 140 | 141 | 142 | /** 143 | * Gets the current engine RPM. Reads PID 0C from the OBD Interface and 144 | * sets rpm to the value returned after conversion. 145 | * @param[out] rpm Unsigned integer is set to the current engine rpm. 146 | * - Minimum Value: 0 147 | * - Maximum Value: 16,383 148 | * - Units: RPM 149 | */ 150 | byte engineRPM(int &rpm); 151 | 152 | 153 | /** 154 | * Gets the current speed of the vehicle in km/h. Reads PID 0D form the OBD 155 | * interface and sets speed to the value returned after conversion. 156 | * @param[out] speed Byte is set to the current speed of the vehicle. 157 | * - Minimum Value: 0 158 | * - Maximum Value: 255 159 | * - Units: km/h 160 | */ 161 | byte vehicleSpeed(byte &speed); 162 | 163 | 164 | /** 165 | * Gets the timing advance of the vehicle relative to TDC on the number one cylinder. 166 | * Reads PID 0E from the OBD interface and sets advance to the value returned after 167 | * conversion. 168 | * @param[out] advance Integer set to the timing advance value. 169 | * - Minimum Value: -64 170 | * - Maximum Value: 63.5 171 | * - Units: ° from TDC 172 | */ 173 | byte timingAdvance(int &advance); 174 | 175 | 176 | /** 177 | * Gets the intake air temperature. Reads PID 0F from the OBD interface and sets 178 | * temperature to the value returned after conversion. 179 | * @param[out] temperature Integer set to the intake air temperature 180 | * - Minimum Value: -40 181 | * - Maximum Value: 215 182 | * - °C 183 | */ 184 | byte intakeAirTemperature(int &temperature); 185 | 186 | 187 | /** 188 | * Gets the Manifold Absolute Flow (MAF) rate. Reads PID 10 from the OBD interface 189 | * and sets rate to the value returned after conversion. 190 | * @param[out] rate Integer value set to the flow rate. 191 | * - Minimum Value: -40 192 | * - Maximum Value: 215 193 | * - °C 194 | */ 195 | byte MAFAirFlowRate(unsigned int &rate); 196 | 197 | 198 | /** 199 | * Gets the current throttle position. Reads PID 11 from the OBD interface 200 | * and sets position to the value returned after conversion. 201 | * @param[out] position Byte containing throttle position. 202 | * - Minimum Value: 0 203 | * - Maximum Value: 100 204 | * - % 205 | */ 206 | byte throttlePosition(byte &position); 207 | byte o2SensorBank1Sensor1(byte &voltage, byte &trim); 208 | byte o2SensorBank1Sensor2(byte &voltage, byte &trim); 209 | byte o2SensorBank1Sensor3(byte &voltage, byte &trim); 210 | byte o2SensorBank1Sensor4(byte &voltage, byte &trim); 211 | byte o2SensorBank2Sensor1(byte &voltage, byte &trim); 212 | byte o2SensorBank2Sensor2(byte &voltage, byte &trim); 213 | byte o2SensorBank2Sensor3(byte &voltage, byte &trim); 214 | byte o2SensorBank2Sensor4(byte &voltage, byte &trim); 215 | byte o2sensorRead(const char *bank, byte &voltage, byte &trim); 216 | byte auxiliaryInputStatus(bool &auxStatus); 217 | byte engineRunTime(unsigned int &runTime); 218 | byte distanceMIL(unsigned int &distance); 219 | byte relativeFuelRailPressure(unsigned int &pressure); 220 | byte absoluteFuelRailPressure(unsigned int &pressure); 221 | byte o2S1WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 222 | byte o2S2WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 223 | byte o2S3WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 224 | byte o2S4WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 225 | byte o2S5WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 226 | byte o2S6WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 227 | byte o2S7WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 228 | byte o2S8WRVoltage(unsigned int &equivRatio, unsigned int &voltage); 229 | byte commandedEGR(byte &egr); 230 | byte EGRError(int &error); 231 | byte commandedEvaporativePurge(byte &purge); 232 | byte fuelLevel(byte &level); 233 | byte warmUpsSinceLastCleared(byte &warmUps); 234 | byte distanceSinceLastCleared(unsigned int &distance); 235 | byte evapPressure(int &pressure); 236 | byte barometricPressure(byte &pressure); 237 | byte o2S1WRCurrent(unsigned int &equivRatio, int ¤t); 238 | byte o2S2WRCurrent(unsigned int &equivRatio, int ¤t); 239 | byte o2S3WRCurrent(unsigned int &equivRatio, int ¤t); 240 | byte o2S4WRCurrent(unsigned int &equivRatio, int ¤t); 241 | byte o2S5WRCurrent(unsigned int &equivRatio, int ¤t); 242 | byte o2S6WRCurrent(unsigned int &equivRatio, int ¤t); 243 | byte o2S7WRCurrent(unsigned int &equivRatio, int ¤t); 244 | byte o2S8WRCurrent(unsigned int &equivRatio, int ¤t); 245 | byte catalystTemperatureBank1Sensor1( int &temperature); 246 | byte catalystTemperatureBank2Sensor1( int &temperature); 247 | byte catalystTemperatureBank1Sensor2( int &temperature); 248 | byte catalystTemperatureBank2Sensor2( int &temperature); 249 | byte controlModuleVoltage(unsigned int &voltage); 250 | byte absoluteLoadValue(unsigned int &load); 251 | byte commandEquivalenceRatio(float &ratio); 252 | byte relativeThrottlePosition(byte &position); 253 | byte ambientAirTemperature(int &temperature); 254 | byte absoluteThrottlePositionB(byte &position); 255 | byte absoluteThrottlePositionC(byte &position); 256 | byte acceleratorPedalPositionD(byte &position); 257 | byte acceleratorPedalPositionE(byte &position); 258 | byte acceleratorPedalPositionF(byte &position); 259 | byte commandedThrottleActuator(byte &position); 260 | byte fuelInjectionTiming(float &position); 261 | byte engineFuelRate(float &rate); 262 | byte driverDemandEngineTorque(byte &torque); 263 | byte actualEngineTorque(byte &torque); 264 | private: 265 | byte o2WRVoltage(const char *sensor, unsigned int &equivRatio, unsigned int &voltage); 266 | byte o2WRCurrent(const char *sensor, unsigned int &equivRatio, int ¤t); 267 | byte catTemperature(const char *sensor, int &temperature); 268 | byte getBytes( const char *mode, const char *chkMode, const char *pid, byte *values, unsigned int numValues); 269 | byte runCommand(const char *cmd, char *data, unsigned int dataLength); 270 | bool getBit(byte b, byte p); 271 | byte getFuelTrim(const char *pid, int &percent); 272 | void flush(); 273 | }; 274 | 275 | 276 | #endif 277 | 278 | 279 | -------------------------------------------------------------------------------- /ELM327.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/ELM327.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | arduino-ELM327 2 | ============== 3 | 4 | ELM327 Library for Arduino 5 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -e ELM327.zip ] && rm ELM327.zip 3 | zip ELM327.zip ELM327.h ELM327.cpp 4 | 5 | 6 | -------------------------------------------------------------------------------- /doc/ELM327.rst: -------------------------------------------------------------------------------- 1 | MACROS 2 | ====== 3 | .. c:macro:: ELM_TIMEOUT 4 | 5 | The timeout in milliseconds to wait for a response from the ELM device. 6 | If this timeout is reached before a prompt is returned then functions 7 | will return ELM_NO_RESPONSE. 8 | 9 | .. c:macro:: ELM_BAUD_RATE 10 | 11 | 12 | The BAUD rate to use when communicating with the ELM device. Generally 13 | this is 9600 however it can be changed in both hardware and software. 14 | This setting is the speed that the ELM device will use at startup. 15 | 16 | 17 | .. c:macro:: ELM_PORT 18 | 19 | 20 | The serial port/device that the ELM327 chip is connected to. 21 | 22 | 23 | .. c:macro:: ELM_SUCCESS 24 | 25 | 26 | Return code when communication with the ELM device returned succesfully 27 | 28 | 29 | .. c:macro:: ELM_NO_RESPONSE 30 | 31 | Return code when communication with the ELM device failed as there was 32 | no response. 33 | 34 | .. c:macro:: ELM_BUFFER_OVERFLOW 35 | 36 | 37 | Return code when the ELM device returned more data than the given buffer 38 | was able to hold. 39 | 40 | 41 | 42 | .. c:macro:: ELM_GARBAGE 43 | 44 | Return code when the ELM device returns unexpected data. This is 45 | usually when the response does not contain byte values, or contains 46 | unexpected output. 47 | 48 | .. c:macro:: ELM_UNABLE_TO_CONNECT 49 | 50 | Return code when the ELM device is unable to connect to the vehicle 51 | The ELM327 has tried all of the available protocols, and could not 52 | detect a compatible one. This could be because your vehicle uses an 53 | unsupported protocol, or could be as simple as forgetting to turn the 54 | ignition key on. Check all of your connections, and the ignition, 55 | then try the command again. 56 | 57 | .. c:macro:: ELM_NO_DATA 58 | 59 | Return code when the ELM device returns NO DATA. The IC waited for 60 | the period of time that was set by AT ST, and detected no response 61 | from the vehicle. It may be that the vehicle had no data to offer 62 | for that particular PID, that the mode requested was not supported, 63 | that the vehicle was attending to higher priority issues, or in the 64 | case of the CAN systems, the filter may have been set so that the 65 | response was ignored, even though one was sent. If you are certain 66 | that there should have been a response, try increasing the ST time 67 | (to be sure that you have allowed enough time for the ECU to 68 | respond), or restoring the CAN filter to its default setting. 69 | 70 | Classes 71 | ======= 72 | 73 | .. cpp:class:: Elm327 74 | 75 | Interface for the ELM327 multi-function OBDII Interpreter IC. Providing 76 | both a low level interface to run commands directly on the IC, and a 77 | higher level API that provides convenience functions to read from the OBD2 78 | PIDS, read and reset error codes, and otherwise interrogate the connected 79 | vehicle. 80 | 81 | :High Level API: 82 | 83 | The high levle API provides an easy to use way to get OBD metrics from 84 | the vehicle. All high level functions return the status, and set one or 85 | more variables to the converted values. 86 | 87 | Regardless of the API level used, the constants for timeout, BAUD rate and 88 | port must be configured, prior to including the ELM327 header. 89 | 90 | The Elm class contains all the methods used to interact with the ELM device, 91 | this must be initialized using the begin() method. All methods (including 92 | begin) return the status. This is a byte, with constants defined for SUCCESS 93 | TIMEOUT, etc. 94 | 95 | To read a value from the OBD controller, call the method with an appropriate 96 | variable. Upon success the variable will contain the converted value.:: 97 | 98 | #define ELM_TIMEOUT 9000 99 | #define ELM_BAUD_RATE 9600 100 | #define ELM_PORT Serial3 101 | #include 102 | 103 | Elm327 Elm; 104 | byte status; 105 | int temperature; 106 | 107 | status=Elm.begin(); 108 | if (status != ELM_SUCCESS){ 109 | Serial.print("Elm begin failed with error: "); 110 | Serial.println(status); 111 | } 112 | 113 | status=Elm.coolantTemperature(temperature); 114 | if (status == ELM_SUCCESS){ 115 | Serial.print("Coolant Temperature: "); 116 | Serial.println(temperature); 117 | }else{ 118 | Serial.print("Elm begin failed with error: "); 119 | Serial.println(status); 120 | } 121 | 122 | :Low Level API: 123 | 124 | In addition to being able to query common OBD parameters, it is possible 125 | to run arbitrary commands directly on the ELM device, or request PIDS and 126 | raw commands. 127 | 128 | To run an arbitrary command on the ELM device, runCommand can be used. 129 | This will run the given command and wait until the prompt is returned or 130 | ELM_TIMEOUT is reached. The buffer is filled with any data returned from 131 | the ELM controller. 132 | 133 | You can also request byte values, for example if you are running a command 134 | that will return a series of bytes, getBytes can be used. This runs the 135 | command, and parses the output into an array of bytes.:: 136 | 137 | #include 138 | status=Elm.begin(); 139 | if (status != ELM_SUCCESS){ 140 | 141 | Serial.print("Elm begin failed with error: "); 142 | Serial.println(status); 143 | } 144 | byte values[1]; 145 | status=getBytes("01","41","05",values,1); 146 | if (status != ELM_SUCCESS){ 147 | Serial.print("Failed to get value for Temperature: "); 148 | Serial.println(status); 149 | } else{ 150 | Serial.print ("Elm returned: "); 151 | Serial.println(values[0], HEX); 152 | Serial.print ("Converted to degrees this is: "); 153 | Serial.print(values[0]-40,DEC); 154 | } 155 | 156 | .. cpp:function:: byte Elm327::begin() 157 | 158 | Configures the ELM Device by sending a series of commands: 159 | - Reset 160 | - Echo Off 161 | - Auto detect connection. 162 | 163 | :return: ELM_SUCCESS when the ELM device returned the anticipated response. Else returns an ELM error code. 164 | 165 | .. cpp:function:: byte Elm327::getVersion(String &rev) 166 | 167 | Issues the ATI command to the ELM device. The ATI command 168 | causes the chip to identify itself, by printing the startup 169 | product ID string (currently ‘ELM327 v1.3a’). Software can 170 | use this to determine exactly which integrated circuit it is 171 | talking to, without having to reset the IC. 172 | 173 | :param String rev: String used to store the revision and identifier. 174 | 175 | .. cpp:function:: byte Elm327::getIgnMon(bool &powered) 176 | 177 | Issues the AT IGN command to the elm device. This command provides 178 | a means of checking the voltage level at pin 15. It assumes that 179 | the logic level is related to the ignition voltage, so if the input 180 | is at a high level, then rev shall be set to true (On) where as a 181 | low level shall set rev to false. (Off) 182 | 183 | :param bool powered: Boolean value that is set to the ignition status. 184 | 185 | .. cpp:function:: byte Elm327::getVoltage(float &voltage) 186 | 187 | Issues the AT RV command to the Elm device. This initiates the 188 | reading of the voltage present at pin 2, and the conversion of it to 189 | a decimal voltage. By default, it is assumed that the input is 190 | connected to the voltage to be measured through a 47KΩ and 10KΩ 191 | resistor divider (with the 10KΩ connected from pin 2 to Vss), and that 192 | the ELM327 supply is a nominal 5V. This will allow for the measurement 193 | of input voltages up to about 28V, with an uncalibrated accuracy of 194 | typically about 2%. 195 | 196 | :param float voltage: Float that is set to the detected voltage. 197 | 198 | .. cpp:function:: byte Elm327::engineLoad(byte &load) 199 | 200 | Gets the Calculated Engine Load. Reads PID 04 from the OBD interface and sets 201 | load to the the value returned after conversion. 202 | 203 | :param byte load: value is set to the calculated Engine Load. 204 | - Minimum value: 0 205 | - Maximum value: 100 206 | - Units: % 207 | 208 | .. cpp:function:: byte Elm327::coolantTemperature(int &temp) 209 | 210 | Gets the Coolant Temperature. Reads PID 05 from the OBD interface and sets 211 | temp to the value returned after conversion. 212 | 213 | :param int temp: Signed integer value is set to the coolant temperature. 214 | - Minimum: -40 215 | - Maximum Value: 215 216 | - Units: °C 217 | 218 | .. cpp:function:: byte Elm327::fuelTrimBank1ShortTerm(int &percent) 219 | 220 | Gets the fuel trim for bank 1 in the short term. Reads PID 06 from the OBD 221 | interface and sets percent to the value returned after conversion. 222 | 223 | :param int percent: Signed integer is set to the percent fuel trim. 224 | - Minimum Value: -100 225 | - Maximum Value: 99.2 226 | - Units: % 227 | 228 | .. cpp:function:: byte Elm327::fuelTrimBank2ShortTerm(int &percent) 229 | 230 | Gets the fuel trim for bank 2 in the short term. Reads PID 07 from the OBD 231 | interface and sets percent to the value returned after conversion. 232 | 233 | :param int percent: Signed integer is set to the percent fuel trim. 234 | - Minimum Value: -100 235 | - Maximum Value: 99.2 236 | - Units: % 237 | 238 | .. cpp:function:: byte Elm327::fuelTrimBank1LongTerm(int &percent) 239 | 240 | Gets the fuel trim for bank 1 in the long term. Reads PID 08 from the OBD 241 | interface and sets percent to the value returned after conversion. 242 | 243 | :param int percent: Signed integer is set to the percent fuel trim. 244 | - Minimum Value: -100 245 | - Maximum Value: 99.2 246 | - Units: % 247 | 248 | .. cpp:function:: byte Elm327::fuelTrimBank2LongTerm(int &percent) 249 | 250 | Gets the fuel trim for bank 2 in the long term. Reads PID 09 from the OBD 251 | interface and sets percent to the value returned after conversion. 252 | 253 | :param int percent: Signed integer is set to the percent fuel trim. 254 | - Minimum Value: -100 255 | - Maximum Value: 99.2 256 | - Units: % 257 | 258 | .. cpp:function:: byte Elm327::fuelPressure(int &pressure) 259 | 260 | Gets the fuel pressure. Reads PID 0A from the OBD interface and sets pressure 261 | to the value returned after conversion. 262 | 263 | :param int pressure: Signed integer is set to the fuel pressure. 264 | - Minimum Value: 0 265 | - Maximum Value: 765 266 | - Units: kPa (Absolute) 267 | 268 | .. cpp:function:: byte Elm327::intakeManifoldAbsolutePressure(byte &pressure) 269 | 270 | Gets the Intake Manifold Absolute Pressure. Reads PID 0B from the OBD 271 | interface and sets pressure to the value returned after conversion. 272 | 273 | :param byte pressure: Byte set to the manifold pressure 274 | - Minimum Value: 0 275 | - Maximum Value: 255 276 | - Units: kPa (Absolute) 277 | 278 | .. cpp:function:: byte Elm327::engineRPM(int &rpm) 279 | 280 | Gets the current engine RPM. Reads PID 0C from the OBD Interface and 281 | sets rpm to the value returned after conversion. 282 | 283 | :param unsigned int rpm: Unsigned integer is set to the current engine rpm. 284 | - Minimum Value: 0 285 | - Maximum Value: 16,383 286 | - Units: RPM 287 | 288 | .. cpp:function:: byte Elm327::vehicleSpeed(byte &speed) 289 | 290 | Gets the current speed of the vehicle in km/h. Reads PID 0D form the OBD 291 | interface and sets speed to the value returned after conversion. 292 | 293 | :param byte speed: Byte is set to the current speed of the vehicle. 294 | - Minimum Value: 0 295 | - Maximum Value: 255 296 | - Units: km/h 297 | 298 | .. cpp:function:: byte Elm327::timingAdvance(int &advance) 299 | 300 | Gets the timing advance of the vehicle relative to TDC on the number one cylinder. 301 | Reads PID 0E from the OBD interface and sets advance to the value returned after 302 | conversion. 303 | 304 | :param int advance: Integer set to the timing advance value. 305 | - Minimum Value: -64 306 | - Maximum Value: 63.5 307 | - Units: ° from TDC 308 | 309 | .. cpp:function:: byte Elm327::intakeAirTemperature(int &temperature) 310 | 311 | Gets the intake air temperature. Reads PID 0F from the OBD interface and sets 312 | temperature to the value returned after conversion. 313 | 314 | :param int temperature: Integer set to the intake air temperature 315 | - Minimum Value: -40 316 | - Maximum Value: 215 317 | - °C 318 | 319 | .. cpp:function:: byte Elm327::MAFAirFlowRate(unsigned int &rate) 320 | 321 | Gets the Manifold Absolute Flow (MAF) rate. Reads PID 10 from the OBD interface 322 | and sets rate to the value returned after conversion. 323 | 324 | :param int rate: Integer value set to the flow rate. 325 | - Minimum Value: -40 326 | - Maximum Value: 215 327 | - °C 328 | 329 | .. cpp:function:: byte Elm327::hrottlePosition(byte &position) 330 | 331 | Gets the current throttle position. Reads PID 11 from the OBD interface 332 | and sets position to the value returned after conversion. 333 | 334 | :param byte position: Byte containing throttle position. 335 | - Minimum Value: 0 336 | - Maximum Value: 100 337 | - % 338 | 339 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor1(byte &voltage, byte &trim) 340 | 341 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor2(byte &voltage, byte &trim) 342 | 343 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor3(byte &voltage, byte &trim) 344 | 345 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor4(byte &voltage, byte &trim) 346 | 347 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor1(byte &voltage, byte &trim) 348 | 349 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor2(byte &voltage, byte &trim) 350 | 351 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor3(byte &voltage, byte &trim) 352 | 353 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor4(byte &voltage, byte &trim) 354 | 355 | .. cpp:function:: byte Elm327::o2sensorRead(const char *bank, byte &voltage, byte &trim) 356 | 357 | .. cpp:function:: byte Elm327::auxiliaryInputStatus(bool &auxStatus) 358 | 359 | .. cpp:function:: byte Elm327::engineRunTime(unsigned int &runTime) 360 | 361 | .. cpp:function:: byte Elm327::distanceMIL(unsigned int &distance) 362 | 363 | .. cpp:function:: byte Elm327::relativeFuelRailPressure(unsigned int &pressure) 364 | 365 | .. cpp:function:: byte Elm327::absoluteFuelRailPressure(unsigned int &pressure) 366 | 367 | .. cpp:function:: byte Elm327::o2S1WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 368 | 369 | .. cpp:function:: byte Elm327::o2S2WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 370 | 371 | .. cpp:function:: byte Elm327::o2S3WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 372 | 373 | .. cpp:function:: byte Elm327::o2S4WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 374 | 375 | .. cpp:function:: byte Elm327::o2S5WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 376 | 377 | .. cpp:function:: byte Elm327::o2S6WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 378 | 379 | .. cpp:function:: byte Elm327::o2S7WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 380 | 381 | .. cpp:function:: byte Elm327::o2S8WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 382 | 383 | .. cpp:function:: byte Elm327::commandedEGR(byte &egr) 384 | 385 | .. cpp:function:: byte Elm327::EGRError(int &error) 386 | 387 | .. cpp:function:: byte Elm327::commandedEvaporativePurge(byte &purge) 388 | 389 | .. cpp:function:: byte Elm327::fuelLevel(byte &level) 390 | 391 | .. cpp:function:: byte Elm327::warmUpsSinceLastCleared(byte &warmUps) 392 | 393 | .. cpp:function:: byte Elm327::distanceSinceLastCleared(unsigned int &distance) 394 | 395 | .. cpp:function:: byte Elm327::evapPressure(int &pressure) 396 | 397 | .. cpp:function:: byte barometricPressure(byte &pressure) 398 | 399 | .. cpp:function:: byte Elm327::o2S1WRCurrent(unsigned int &equivRatio, int ¤t) 400 | 401 | .. cpp:function:: byte Elm327::o2S2WRCurrent(unsigned int &equivRatio, int ¤t) 402 | 403 | .. cpp:function:: byte Elm327::o2S3WRCurrent(unsigned int &equivRatio, int ¤t) 404 | 405 | .. cpp:function:: byte Elm327::o2S4WRCurrent(unsigned int &equivRatio, int ¤t) 406 | 407 | .. cpp:function:: byte Elm327::o2S5WRCurrent(unsigned int &equivRatio, int ¤t) 408 | 409 | .. cpp:function:: byte Elm327::o2S6WRCurrent(unsigned int &equivRatio, int ¤t) 410 | 411 | .. cpp:function:: byte Elm327::o2S7WRCurrent(unsigned int &equivRatio, int ¤t) 412 | 413 | .. cpp:function:: byte Elm327::o2S8WRCurrent(unsigned int &equivRatio, int ¤t) 414 | 415 | .. cpp:function:: byte Elm327::catalystTemperatureBank1Sensor1( int &temperature) 416 | 417 | .. cpp:function:: byte Elm327::catalystTemperatureBank2Sensor1( int &temperature) 418 | 419 | .. cpp:function:: byte Elm327::catalystTemperatureBank1Sensor2( int &temperature) 420 | 421 | .. cpp:function:: byte Elm327::catalystTemperatureBank2Sensor2( int &temperature) 422 | 423 | .. cpp:function:: byte Elm327::controlModuleVoltage(unsigned int &voltage) 424 | 425 | .. cpp:function:: byte Elm327::absoluteLoadValue(unsigned int &load) 426 | 427 | .. cpp:function:: byte Elm327::commandEquivalenceRatio(float &ratio) 428 | 429 | .. cpp:function:: byte Elm327::relativeThrottlePosition(byte &position) 430 | 431 | .. cpp:function:: byte Elm327::ambientAirTemperature(int &temperature) 432 | 433 | .. cpp:function:: byte Elm327::absoluteThrottlePositionB(byte &position) 434 | 435 | .. cpp:function:: byte Elm327::absoluteThrottlePositionC(byte &position) 436 | 437 | .. cpp:function:: byte Elm327::acceleratorPedalPositionD(byte &position) 438 | 439 | .. cpp:function:: byte Elm327::acceleratorPedalPositionE(byte &position) 440 | 441 | .. cpp:function:: byte Elm327::acceleratorPedalPositionF(byte &position) 442 | 443 | .. cpp:function:: byte Elm327::commandedThrottleActuator(byte &position) 444 | 445 | .. cpp:function:: byte Elm327::getBytes( const char *mode, const char *chkMode, const char *pid, byte *values, unsigned int numValues) -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sphinx.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinx.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/sphinx" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sphinx" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /doc/_build/doctrees/ELM327.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/doctrees/ELM327.doctree -------------------------------------------------------------------------------- /doc/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /doc/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /doc/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 17ecd1a8e739f0914ef1ca4d4c90bc21 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /doc/_build/html/_sources/ELM327.txt: -------------------------------------------------------------------------------- 1 | MACROS 2 | ====== 3 | .. c:macro:: ELM_TIMEOUT 4 | 5 | The timeout in milliseconds to wait for a response from the ELM device. 6 | If this timeout is reached before a prompt is returned then functions 7 | will return ELM_NO_RESPONSE. 8 | 9 | .. c:macro:: ELM_BAUD_RATE 10 | 11 | 12 | The BAUD rate to use when communicating with the ELM device. Generally 13 | this is 9600 however it can be changed in both hardware and software. 14 | This setting is the speed that the ELM device will use at startup. 15 | 16 | 17 | .. c:macro:: ELM_PORT 18 | 19 | 20 | The serial port/device that the ELM327 chip is connected to. 21 | 22 | 23 | .. c:macro:: ELM_SUCCESS 24 | 25 | 26 | Return code when communication with the ELM device returned succesfully 27 | 28 | 29 | .. c:macro:: ELM_NO_RESPONSE 30 | 31 | Return code when communication with the ELM device failed as there was 32 | no response. 33 | 34 | .. c:macro:: ELM_BUFFER_OVERFLOW 35 | 36 | 37 | Return code when the ELM device returned more data than the given buffer 38 | was able to hold. 39 | 40 | 41 | 42 | .. c:macro:: ELM_GARBAGE 43 | 44 | Return code when the ELM device returns unexpected data. This is 45 | usually when the response does not contain byte values, or contains 46 | unexpected output. 47 | 48 | .. c:macro:: ELM_UNABLE_TO_CONNECT 49 | 50 | Return code when the ELM device is unable to connect to the vehicle 51 | The ELM327 has tried all of the available protocols, and could not 52 | detect a compatible one. This could be because your vehicle uses an 53 | unsupported protocol, or could be as simple as forgetting to turn the 54 | ignition key on. Check all of your connections, and the ignition, 55 | then try the command again. 56 | 57 | .. c:macro:: ELM_NO_DATA 58 | 59 | Return code when the ELM device returns NO DATA. The IC waited for 60 | the period of time that was set by AT ST, and detected no response 61 | from the vehicle. It may be that the vehicle had no data to offer 62 | for that particular PID, that the mode requested was not supported, 63 | that the vehicle was attending to higher priority issues, or in the 64 | case of the CAN systems, the filter may have been set so that the 65 | response was ignored, even though one was sent. If you are certain 66 | that there should have been a response, try increasing the ST time 67 | (to be sure that you have allowed enough time for the ECU to 68 | respond), or restoring the CAN filter to its default setting. 69 | 70 | Classes 71 | ======= 72 | 73 | .. cpp:class:: Elm327 74 | 75 | Interface for the ELM327 multi-function OBDII Interpreter IC. Providing 76 | both a low level interface to run commands directly on the IC, and a 77 | higher level API that provides convenience functions to read from the OBD2 78 | PIDS, read and reset error codes, and otherwise interrogate the connected 79 | vehicle. 80 | 81 | :High Level API: 82 | 83 | The high levle API provides an easy to use way to get OBD metrics from 84 | the vehicle. All high level functions return the status, and set one or 85 | more variables to the converted values. 86 | 87 | Regardless of the API level used, the constants for timeout, BAUD rate and 88 | port must be configured, prior to including the ELM327 header. 89 | 90 | The Elm class contains all the methods used to interact with the ELM device, 91 | this must be initialized using the begin() method. All methods (including 92 | begin) return the status. This is a byte, with constants defined for SUCCESS 93 | TIMEOUT, etc. 94 | 95 | To read a value from the OBD controller, call the method with an appropriate 96 | variable. Upon success the variable will contain the converted value.:: 97 | 98 | #define ELM_TIMEOUT 9000 99 | #define ELM_BAUD_RATE 9600 100 | #define ELM_PORT Serial3 101 | #include 102 | 103 | Elm327 Elm; 104 | byte status; 105 | int temperature; 106 | 107 | status=Elm.begin(); 108 | if (status != ELM_SUCCESS){ 109 | Serial.print("Elm begin failed with error: "); 110 | Serial.println(status); 111 | } 112 | 113 | status=Elm.coolantTemperature(temperature); 114 | if (status == ELM_SUCCESS){ 115 | Serial.print("Coolant Temperature: "); 116 | Serial.println(temperature); 117 | }else{ 118 | Serial.print("Elm begin failed with error: "); 119 | Serial.println(status); 120 | } 121 | 122 | :Low Level API: 123 | 124 | In addition to being able to query common OBD parameters, it is possible 125 | to run arbitrary commands directly on the ELM device, or request PIDS and 126 | raw commands. 127 | 128 | To run an arbitrary command on the ELM device, runCommand can be used. 129 | This will run the given command and wait until the prompt is returned or 130 | ELM_TIMEOUT is reached. The buffer is filled with any data returned from 131 | the ELM controller. 132 | 133 | You can also request byte values, for example if you are running a command 134 | that will return a series of bytes, getBytes can be used. This runs the 135 | command, and parses the output into an array of bytes.:: 136 | 137 | #include 138 | status=Elm.begin(); 139 | if (status != ELM_SUCCESS){ 140 | 141 | Serial.print("Elm begin failed with error: "); 142 | Serial.println(status); 143 | } 144 | byte values[1]; 145 | status=getBytes("01","41","05",values,1); 146 | if (status != ELM_SUCCESS){ 147 | Serial.print("Failed to get value for Temperature: "); 148 | Serial.println(status); 149 | } else{ 150 | Serial.print ("Elm returned: "); 151 | Serial.println(values[0], HEX); 152 | Serial.print ("Converted to degrees this is: "); 153 | Serial.print(values[0]-40,DEC); 154 | } 155 | 156 | .. cpp:function:: byte Elm327::begin() 157 | 158 | Configures the ELM Device by sending a series of commands: 159 | - Reset 160 | - Echo Off 161 | - Auto detect connection. 162 | 163 | :return: ELM_SUCCESS when the ELM device returned the anticipated response. Else returns an ELM error code. 164 | 165 | .. cpp:function:: byte Elm327::getVersion(String &rev) 166 | 167 | Issues the ATI command to the ELM device. The ATI command 168 | causes the chip to identify itself, by printing the startup 169 | product ID string (currently ‘ELM327 v1.3a’). Software can 170 | use this to determine exactly which integrated circuit it is 171 | talking to, without having to reset the IC. 172 | 173 | :param String rev: String used to store the revision and identifier. 174 | 175 | .. cpp:function:: byte Elm327::getIgnMon(bool &powered) 176 | 177 | Issues the AT IGN command to the elm device. This command provides 178 | a means of checking the voltage level at pin 15. It assumes that 179 | the logic level is related to the ignition voltage, so if the input 180 | is at a high level, then rev shall be set to true (On) where as a 181 | low level shall set rev to false. (Off) 182 | 183 | :param bool powered: Boolean value that is set to the ignition status. 184 | 185 | .. cpp:function:: byte Elm327::getVoltage(float &voltage) 186 | 187 | Issues the AT RV command to the Elm device. This initiates the 188 | reading of the voltage present at pin 2, and the conversion of it to 189 | a decimal voltage. By default, it is assumed that the input is 190 | connected to the voltage to be measured through a 47KΩ and 10KΩ 191 | resistor divider (with the 10KΩ connected from pin 2 to Vss), and that 192 | the ELM327 supply is a nominal 5V. This will allow for the measurement 193 | of input voltages up to about 28V, with an uncalibrated accuracy of 194 | typically about 2%. 195 | 196 | :param float voltage: Float that is set to the detected voltage. 197 | 198 | .. cpp:function:: byte Elm327::engineLoad(byte &load) 199 | 200 | Gets the Calculated Engine Load. Reads PID 04 from the OBD interface and sets 201 | load to the the value returned after conversion. 202 | 203 | :param byte load: value is set to the calculated Engine Load. 204 | - Minimum value: 0 205 | - Maximum value: 100 206 | - Units: % 207 | 208 | .. cpp:function:: byte Elm327::coolantTemperature(int &temp) 209 | 210 | Gets the Coolant Temperature. Reads PID 05 from the OBD interface and sets 211 | temp to the value returned after conversion. 212 | 213 | :param int temp: Signed integer value is set to the coolant temperature. 214 | - Minimum: -40 215 | - Maximum Value: 215 216 | - Units: °C 217 | 218 | .. cpp:function:: byte Elm327::fuelTrimBank1ShortTerm(int &percent) 219 | 220 | Gets the fuel trim for bank 1 in the short term. Reads PID 06 from the OBD 221 | interface and sets percent to the value returned after conversion. 222 | 223 | :param int percent: Signed integer is set to the percent fuel trim. 224 | - Minimum Value: -100 225 | - Maximum Value: 99.2 226 | - Units: % 227 | 228 | .. cpp:function:: byte Elm327::fuelTrimBank2ShortTerm(int &percent) 229 | 230 | Gets the fuel trim for bank 2 in the short term. Reads PID 07 from the OBD 231 | interface and sets percent to the value returned after conversion. 232 | 233 | :param int percent: Signed integer is set to the percent fuel trim. 234 | - Minimum Value: -100 235 | - Maximum Value: 99.2 236 | - Units: % 237 | 238 | .. cpp:function:: byte Elm327::fuelTrimBank1LongTerm(int &percent) 239 | 240 | Gets the fuel trim for bank 1 in the long term. Reads PID 08 from the OBD 241 | interface and sets percent to the value returned after conversion. 242 | 243 | :param int percent: Signed integer is set to the percent fuel trim. 244 | - Minimum Value: -100 245 | - Maximum Value: 99.2 246 | - Units: % 247 | 248 | .. cpp:function:: byte Elm327::fuelTrimBank2LongTerm(int &percent) 249 | 250 | Gets the fuel trim for bank 2 in the long term. Reads PID 09 from the OBD 251 | interface and sets percent to the value returned after conversion. 252 | 253 | :param int percent: Signed integer is set to the percent fuel trim. 254 | - Minimum Value: -100 255 | - Maximum Value: 99.2 256 | - Units: % 257 | 258 | .. cpp:function:: byte Elm327::fuelPressure(int &pressure) 259 | 260 | Gets the fuel pressure. Reads PID 0A from the OBD interface and sets pressure 261 | to the value returned after conversion. 262 | 263 | :param int pressure: Signed integer is set to the fuel pressure. 264 | - Minimum Value: 0 265 | - Maximum Value: 765 266 | - Units: kPa (Absolute) 267 | 268 | .. cpp:function:: byte Elm327::intakeManifoldAbsolutePressure(byte &pressure) 269 | 270 | Gets the Intake Manifold Absolute Pressure. Reads PID 0B from the OBD 271 | interface and sets pressure to the value returned after conversion. 272 | 273 | :param byte pressure: Byte set to the manifold pressure 274 | - Minimum Value: 0 275 | - Maximum Value: 255 276 | - Units: kPa (Absolute) 277 | 278 | .. cpp:function:: byte Elm327::engineRPM(int &rpm) 279 | 280 | Gets the current engine RPM. Reads PID 0C from the OBD Interface and 281 | sets rpm to the value returned after conversion. 282 | 283 | :param unsigned int rpm: Unsigned integer is set to the current engine rpm. 284 | - Minimum Value: 0 285 | - Maximum Value: 16,383 286 | - Units: RPM 287 | 288 | .. cpp:function:: byte Elm327::vehicleSpeed(byte &speed) 289 | 290 | Gets the current speed of the vehicle in km/h. Reads PID 0D form the OBD 291 | interface and sets speed to the value returned after conversion. 292 | 293 | :param byte speed: Byte is set to the current speed of the vehicle. 294 | - Minimum Value: 0 295 | - Maximum Value: 255 296 | - Units: km/h 297 | 298 | .. cpp:function:: byte Elm327::timingAdvance(int &advance) 299 | 300 | Gets the timing advance of the vehicle relative to TDC on the number one cylinder. 301 | Reads PID 0E from the OBD interface and sets advance to the value returned after 302 | conversion. 303 | 304 | :param int advance: Integer set to the timing advance value. 305 | - Minimum Value: -64 306 | - Maximum Value: 63.5 307 | - Units: ° from TDC 308 | 309 | .. cpp:function:: byte Elm327::intakeAirTemperature(int &temperature) 310 | 311 | Gets the intake air temperature. Reads PID 0F from the OBD interface and sets 312 | temperature to the value returned after conversion. 313 | 314 | :param int temperature: Integer set to the intake air temperature 315 | - Minimum Value: -40 316 | - Maximum Value: 215 317 | - °C 318 | 319 | .. cpp:function:: byte Elm327::MAFAirFlowRate(unsigned int &rate) 320 | 321 | Gets the Manifold Absolute Flow (MAF) rate. Reads PID 10 from the OBD interface 322 | and sets rate to the value returned after conversion. 323 | 324 | :param int rate: Integer value set to the flow rate. 325 | - Minimum Value: -40 326 | - Maximum Value: 215 327 | - °C 328 | 329 | .. cpp:function:: byte Elm327::hrottlePosition(byte &position) 330 | 331 | Gets the current throttle position. Reads PID 11 from the OBD interface 332 | and sets position to the value returned after conversion. 333 | 334 | :param byte position: Byte containing throttle position. 335 | - Minimum Value: 0 336 | - Maximum Value: 100 337 | - % 338 | 339 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor1(byte &voltage, byte &trim) 340 | 341 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor2(byte &voltage, byte &trim) 342 | 343 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor3(byte &voltage, byte &trim) 344 | 345 | .. cpp:function:: byte Elm327::o2SensorBank1Sensor4(byte &voltage, byte &trim) 346 | 347 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor1(byte &voltage, byte &trim) 348 | 349 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor2(byte &voltage, byte &trim) 350 | 351 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor3(byte &voltage, byte &trim) 352 | 353 | .. cpp:function:: byte Elm327::o2SensorBank2Sensor4(byte &voltage, byte &trim) 354 | 355 | .. cpp:function:: byte Elm327::o2sensorRead(const char *bank, byte &voltage, byte &trim) 356 | 357 | .. cpp:function:: byte Elm327::auxiliaryInputStatus(bool &auxStatus) 358 | 359 | .. cpp:function:: byte Elm327::engineRunTime(unsigned int &runTime) 360 | 361 | .. cpp:function:: byte Elm327::distanceMIL(unsigned int &distance) 362 | 363 | .. cpp:function:: byte Elm327::relativeFuelRailPressure(unsigned int &pressure) 364 | 365 | .. cpp:function:: byte Elm327::absoluteFuelRailPressure(unsigned int &pressure) 366 | 367 | .. cpp:function:: byte Elm327::o2S1WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 368 | 369 | .. cpp:function:: byte Elm327::o2S2WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 370 | 371 | .. cpp:function:: byte Elm327::o2S3WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 372 | 373 | .. cpp:function:: byte Elm327::o2S4WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 374 | 375 | .. cpp:function:: byte Elm327::o2S5WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 376 | 377 | .. cpp:function:: byte Elm327::o2S6WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 378 | 379 | .. cpp:function:: byte Elm327::o2S7WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 380 | 381 | .. cpp:function:: byte Elm327::o2S8WRVoltage(unsigned int &equivRatio, unsigned int &voltage) 382 | 383 | .. cpp:function:: byte Elm327::commandedEGR(byte &egr) 384 | 385 | .. cpp:function:: byte Elm327::EGRError(int &error) 386 | 387 | .. cpp:function:: byte Elm327::commandedEvaporativePurge(byte &purge) 388 | 389 | .. cpp:function:: byte Elm327::fuelLevel(byte &level) 390 | 391 | .. cpp:function:: byte Elm327::warmUpsSinceLastCleared(byte &warmUps) 392 | 393 | .. cpp:function:: byte Elm327::distanceSinceLastCleared(unsigned int &distance) 394 | 395 | .. cpp:function:: byte Elm327::evapPressure(int &pressure) 396 | 397 | .. cpp:function:: byte barometricPressure(byte &pressure) 398 | 399 | .. cpp:function:: byte Elm327::o2S1WRCurrent(unsigned int &equivRatio, int ¤t) 400 | 401 | .. cpp:function:: byte Elm327::o2S2WRCurrent(unsigned int &equivRatio, int ¤t) 402 | 403 | .. cpp:function:: byte Elm327::o2S3WRCurrent(unsigned int &equivRatio, int ¤t) 404 | 405 | .. cpp:function:: byte Elm327::o2S4WRCurrent(unsigned int &equivRatio, int ¤t) 406 | 407 | .. cpp:function:: byte Elm327::o2S5WRCurrent(unsigned int &equivRatio, int ¤t) 408 | 409 | .. cpp:function:: byte Elm327::o2S6WRCurrent(unsigned int &equivRatio, int ¤t) 410 | 411 | .. cpp:function:: byte Elm327::o2S7WRCurrent(unsigned int &equivRatio, int ¤t) 412 | 413 | .. cpp:function:: byte Elm327::o2S8WRCurrent(unsigned int &equivRatio, int ¤t) 414 | 415 | .. cpp:function:: byte Elm327::catalystTemperatureBank1Sensor1( int &temperature) 416 | 417 | .. cpp:function:: byte Elm327::catalystTemperatureBank2Sensor1( int &temperature) 418 | 419 | .. cpp:function:: byte Elm327::catalystTemperatureBank1Sensor2( int &temperature) 420 | 421 | .. cpp:function:: byte Elm327::catalystTemperatureBank2Sensor2( int &temperature) 422 | 423 | .. cpp:function:: byte Elm327::controlModuleVoltage(unsigned int &voltage) 424 | 425 | .. cpp:function:: byte Elm327::absoluteLoadValue(unsigned int &load) 426 | 427 | .. cpp:function:: byte Elm327::commandEquivalenceRatio(float &ratio) 428 | 429 | .. cpp:function:: byte Elm327::relativeThrottlePosition(byte &position) 430 | 431 | .. cpp:function:: byte Elm327::ambientAirTemperature(int &temperature) 432 | 433 | .. cpp:function:: byte Elm327::absoluteThrottlePositionB(byte &position) 434 | 435 | .. cpp:function:: byte Elm327::absoluteThrottlePositionC(byte &position) 436 | 437 | .. cpp:function:: byte Elm327::acceleratorPedalPositionD(byte &position) 438 | 439 | .. cpp:function:: byte Elm327::acceleratorPedalPositionE(byte &position) 440 | 441 | .. cpp:function:: byte Elm327::acceleratorPedalPositionF(byte &position) 442 | 443 | .. cpp:function:: byte Elm327::commandedThrottleActuator(byte &position) 444 | -------------------------------------------------------------------------------- /doc/_build/html/_sources/index.txt: -------------------------------------------------------------------------------- 1 | .. . documentation master file, created by 2 | sphinx-quickstart on Fri May 23 16:53:34 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Arduino ELM327's documentation! 7 | =============================== 8 | 9 | Interface for the ELM327 multi-function OBDII Interpreter IC. Providing 10 | both a low level interface to run commands directly on the IC, and a 11 | higher level API that provides convenience functions to read from the OBD2 12 | PIDS, read and reset error codes, and otherwise interrogate the connected 13 | vehicle. 14 | 15 | Contents: 16 | 17 | .. toctree:: 18 | :maxdepth: 4 19 | 20 | ELM327 21 | 22 | 23 | Indices and tables 24 | ================== 25 | 26 | * :ref:`genindex` 27 | * :ref:`modindex` 28 | * :ref:`search` 29 | 30 | -------------------------------------------------------------------------------- /doc/_build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /doc/_build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | } 56 | 57 | div.sphinxsidebar ul { 58 | list-style: none; 59 | } 60 | 61 | div.sphinxsidebar ul ul, 62 | div.sphinxsidebar ul.want-points { 63 | margin-left: 20px; 64 | list-style: square; 65 | } 66 | 67 | div.sphinxsidebar ul ul { 68 | margin-top: 0; 69 | margin-bottom: 0; 70 | } 71 | 72 | div.sphinxsidebar form { 73 | margin-top: 10px; 74 | } 75 | 76 | div.sphinxsidebar input { 77 | border: 1px solid #98dbcc; 78 | font-family: sans-serif; 79 | font-size: 1em; 80 | } 81 | 82 | div.sphinxsidebar #searchbox input[type="text"] { 83 | width: 170px; 84 | } 85 | 86 | div.sphinxsidebar #searchbox input[type="submit"] { 87 | width: 30px; 88 | } 89 | 90 | img { 91 | border: 0; 92 | max-width: 100%; 93 | } 94 | 95 | /* -- search page ----------------------------------------------------------- */ 96 | 97 | ul.search { 98 | margin: 10px 0 0 20px; 99 | padding: 0; 100 | } 101 | 102 | ul.search li { 103 | padding: 5px 0 5px 20px; 104 | background-image: url(file.png); 105 | background-repeat: no-repeat; 106 | background-position: 0 7px; 107 | } 108 | 109 | ul.search li a { 110 | font-weight: bold; 111 | } 112 | 113 | ul.search li div.context { 114 | color: #888; 115 | margin: 2px 0 0 30px; 116 | text-align: left; 117 | } 118 | 119 | ul.keywordmatches li.goodmatch a { 120 | font-weight: bold; 121 | } 122 | 123 | /* -- index page ------------------------------------------------------------ */ 124 | 125 | table.contentstable { 126 | width: 90%; 127 | } 128 | 129 | table.contentstable p.biglink { 130 | line-height: 150%; 131 | } 132 | 133 | a.biglink { 134 | font-size: 1.3em; 135 | } 136 | 137 | span.linkdescr { 138 | font-style: italic; 139 | padding-top: 5px; 140 | font-size: 90%; 141 | } 142 | 143 | /* -- general index --------------------------------------------------------- */ 144 | 145 | table.indextable { 146 | width: 100%; 147 | } 148 | 149 | table.indextable td { 150 | text-align: left; 151 | vertical-align: top; 152 | } 153 | 154 | table.indextable dl, table.indextable dd { 155 | margin-top: 0; 156 | margin-bottom: 0; 157 | } 158 | 159 | table.indextable tr.pcap { 160 | height: 10px; 161 | } 162 | 163 | table.indextable tr.cap { 164 | margin-top: 10px; 165 | background-color: #f2f2f2; 166 | } 167 | 168 | img.toggler { 169 | margin-right: 3px; 170 | margin-top: 3px; 171 | cursor: pointer; 172 | } 173 | 174 | div.modindex-jumpbox { 175 | border-top: 1px solid #ddd; 176 | border-bottom: 1px solid #ddd; 177 | margin: 1em 0 1em 0; 178 | padding: 0.4em; 179 | } 180 | 181 | div.genindex-jumpbox { 182 | border-top: 1px solid #ddd; 183 | border-bottom: 1px solid #ddd; 184 | margin: 1em 0 1em 0; 185 | padding: 0.4em; 186 | } 187 | 188 | /* -- general body styles --------------------------------------------------- */ 189 | 190 | a.headerlink { 191 | visibility: hidden; 192 | } 193 | 194 | h1:hover > a.headerlink, 195 | h2:hover > a.headerlink, 196 | h3:hover > a.headerlink, 197 | h4:hover > a.headerlink, 198 | h5:hover > a.headerlink, 199 | h6:hover > a.headerlink, 200 | dt:hover > a.headerlink { 201 | visibility: visible; 202 | } 203 | 204 | div.body p.caption { 205 | text-align: inherit; 206 | } 207 | 208 | div.body td { 209 | text-align: left; 210 | } 211 | 212 | .field-list ul { 213 | padding-left: 1em; 214 | } 215 | 216 | .first { 217 | margin-top: 0 !important; 218 | } 219 | 220 | p.rubric { 221 | margin-top: 30px; 222 | font-weight: bold; 223 | } 224 | 225 | img.align-left, .figure.align-left, object.align-left { 226 | clear: left; 227 | float: left; 228 | margin-right: 1em; 229 | } 230 | 231 | img.align-right, .figure.align-right, object.align-right { 232 | clear: right; 233 | float: right; 234 | margin-left: 1em; 235 | } 236 | 237 | img.align-center, .figure.align-center, object.align-center { 238 | display: block; 239 | margin-left: auto; 240 | margin-right: auto; 241 | } 242 | 243 | .align-left { 244 | text-align: left; 245 | } 246 | 247 | .align-center { 248 | text-align: center; 249 | } 250 | 251 | .align-right { 252 | text-align: right; 253 | } 254 | 255 | /* -- sidebars -------------------------------------------------------------- */ 256 | 257 | div.sidebar { 258 | margin: 0 0 0.5em 1em; 259 | border: 1px solid #ddb; 260 | padding: 7px 7px 0 7px; 261 | background-color: #ffe; 262 | width: 40%; 263 | float: right; 264 | } 265 | 266 | p.sidebar-title { 267 | font-weight: bold; 268 | } 269 | 270 | /* -- topics ---------------------------------------------------------------- */ 271 | 272 | div.topic { 273 | border: 1px solid #ccc; 274 | padding: 7px 7px 0 7px; 275 | margin: 10px 0 10px 0; 276 | } 277 | 278 | p.topic-title { 279 | font-size: 1.1em; 280 | font-weight: bold; 281 | margin-top: 10px; 282 | } 283 | 284 | /* -- admonitions ----------------------------------------------------------- */ 285 | 286 | div.admonition { 287 | margin-top: 10px; 288 | margin-bottom: 10px; 289 | padding: 7px; 290 | } 291 | 292 | div.admonition dt { 293 | font-weight: bold; 294 | } 295 | 296 | div.admonition dl { 297 | margin-bottom: 0; 298 | } 299 | 300 | p.admonition-title { 301 | margin: 0px 10px 5px 0px; 302 | font-weight: bold; 303 | } 304 | 305 | div.body p.centered { 306 | text-align: center; 307 | margin-top: 25px; 308 | } 309 | 310 | /* -- tables ---------------------------------------------------------------- */ 311 | 312 | table.docutils { 313 | border: 0; 314 | border-collapse: collapse; 315 | } 316 | 317 | table.docutils td, table.docutils th { 318 | padding: 1px 8px 1px 5px; 319 | border-top: 0; 320 | border-left: 0; 321 | border-right: 0; 322 | border-bottom: 1px solid #aaa; 323 | } 324 | 325 | table.field-list td, table.field-list th { 326 | border: 0 !important; 327 | } 328 | 329 | table.footnote td, table.footnote th { 330 | border: 0 !important; 331 | } 332 | 333 | th { 334 | text-align: left; 335 | padding-right: 5px; 336 | } 337 | 338 | table.citation { 339 | border-left: solid 1px gray; 340 | margin-left: 1px; 341 | } 342 | 343 | table.citation td { 344 | border-bottom: none; 345 | } 346 | 347 | /* -- other body styles ----------------------------------------------------- */ 348 | 349 | ol.arabic { 350 | list-style: decimal; 351 | } 352 | 353 | ol.loweralpha { 354 | list-style: lower-alpha; 355 | } 356 | 357 | ol.upperalpha { 358 | list-style: upper-alpha; 359 | } 360 | 361 | ol.lowerroman { 362 | list-style: lower-roman; 363 | } 364 | 365 | ol.upperroman { 366 | list-style: upper-roman; 367 | } 368 | 369 | dl { 370 | margin-bottom: 15px; 371 | } 372 | 373 | dd p { 374 | margin-top: 0px; 375 | } 376 | 377 | dd ul, dd table { 378 | margin-bottom: 10px; 379 | } 380 | 381 | dd { 382 | margin-top: 3px; 383 | margin-bottom: 10px; 384 | margin-left: 30px; 385 | } 386 | 387 | dt:target, .highlighted { 388 | background-color: #fbe54e; 389 | } 390 | 391 | dl.glossary dt { 392 | font-weight: bold; 393 | font-size: 1.1em; 394 | } 395 | 396 | .field-list ul { 397 | margin: 0; 398 | padding-left: 1em; 399 | } 400 | 401 | .field-list p { 402 | margin: 0; 403 | } 404 | 405 | .optional { 406 | font-size: 1.3em; 407 | } 408 | 409 | .versionmodified { 410 | font-style: italic; 411 | } 412 | 413 | .system-message { 414 | background-color: #fda; 415 | padding: 5px; 416 | border: 3px solid red; 417 | } 418 | 419 | .footnote:target { 420 | background-color: #ffa; 421 | } 422 | 423 | .line-block { 424 | display: block; 425 | margin-top: 1em; 426 | margin-bottom: 1em; 427 | } 428 | 429 | .line-block .line-block { 430 | margin-top: 0; 431 | margin-bottom: 0; 432 | margin-left: 1.5em; 433 | } 434 | 435 | .guilabel, .menuselection { 436 | font-family: sans-serif; 437 | } 438 | 439 | .accelerator { 440 | text-decoration: underline; 441 | } 442 | 443 | .classifier { 444 | font-style: oblique; 445 | } 446 | 447 | abbr, acronym { 448 | border-bottom: dotted 1px; 449 | cursor: help; 450 | } 451 | 452 | /* -- code displays --------------------------------------------------------- */ 453 | 454 | pre { 455 | overflow: auto; 456 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 457 | } 458 | 459 | td.linenos pre { 460 | padding: 5px 0px; 461 | border: 0; 462 | background-color: transparent; 463 | color: #aaa; 464 | } 465 | 466 | table.highlighttable { 467 | margin-left: 0.5em; 468 | } 469 | 470 | table.highlighttable td { 471 | padding: 0 0.5em 0 0.5em; 472 | } 473 | 474 | tt.descname { 475 | background-color: transparent; 476 | font-weight: bold; 477 | font-size: 1.2em; 478 | } 479 | 480 | tt.descclassname { 481 | background-color: transparent; 482 | } 483 | 484 | tt.xref, a tt { 485 | background-color: transparent; 486 | font-weight: bold; 487 | } 488 | 489 | h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { 490 | background-color: transparent; 491 | } 492 | 493 | .viewcode-link { 494 | float: right; 495 | } 496 | 497 | .viewcode-back { 498 | float: right; 499 | font-family: sans-serif; 500 | } 501 | 502 | div.viewcode-block:target { 503 | margin: -1px -10px; 504 | padding: 0 10px; 505 | } 506 | 507 | /* -- math display ---------------------------------------------------------- */ 508 | 509 | img.math { 510 | vertical-align: middle; 511 | } 512 | 513 | div.body div.math p { 514 | text-align: center; 515 | } 516 | 517 | span.eqno { 518 | float: right; 519 | } 520 | 521 | /* -- printout stylesheet --------------------------------------------------- */ 522 | 523 | @media print { 524 | div.document, 525 | div.documentwrapper, 526 | div.bodywrapper { 527 | margin: 0 !important; 528 | width: 100%; 529 | } 530 | 531 | div.sphinxsidebar, 532 | div.related, 533 | div.footer, 534 | #top-link { 535 | display: none; 536 | } 537 | } -------------------------------------------------------------------------------- /doc/_build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /doc/_build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/comment-close.png -------------------------------------------------------------------------------- /doc/_build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/comment.png -------------------------------------------------------------------------------- /doc/_build/html/_static/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: sans-serif; 18 | font-size: 100%; 19 | background-color: #11303d; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: #1c4e63; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: #ffffff; 40 | color: #000000; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | div.footer { 45 | color: #ffffff; 46 | width: 100%; 47 | padding: 9px 0 9px 0; 48 | text-align: center; 49 | font-size: 75%; 50 | } 51 | 52 | div.footer a { 53 | color: #ffffff; 54 | text-decoration: underline; 55 | } 56 | 57 | div.related { 58 | background-color: #133f52; 59 | line-height: 30px; 60 | color: #ffffff; 61 | } 62 | 63 | div.related a { 64 | color: #ffffff; 65 | } 66 | 67 | div.sphinxsidebar { 68 | } 69 | 70 | div.sphinxsidebar h3 { 71 | font-family: 'Trebuchet MS', sans-serif; 72 | color: #ffffff; 73 | font-size: 1.4em; 74 | font-weight: normal; 75 | margin: 0; 76 | padding: 0; 77 | } 78 | 79 | div.sphinxsidebar h3 a { 80 | color: #ffffff; 81 | } 82 | 83 | div.sphinxsidebar h4 { 84 | font-family: 'Trebuchet MS', sans-serif; 85 | color: #ffffff; 86 | font-size: 1.3em; 87 | font-weight: normal; 88 | margin: 5px 0 0 0; 89 | padding: 0; 90 | } 91 | 92 | div.sphinxsidebar p { 93 | color: #ffffff; 94 | } 95 | 96 | div.sphinxsidebar p.topless { 97 | margin: 5px 10px 10px 10px; 98 | } 99 | 100 | div.sphinxsidebar ul { 101 | margin: 10px; 102 | padding: 0; 103 | color: #ffffff; 104 | } 105 | 106 | div.sphinxsidebar a { 107 | color: #98dbcc; 108 | } 109 | 110 | div.sphinxsidebar input { 111 | border: 1px solid #98dbcc; 112 | font-family: sans-serif; 113 | font-size: 1em; 114 | } 115 | 116 | 117 | 118 | /* -- hyperlink styles ------------------------------------------------------ */ 119 | 120 | a { 121 | color: #355f7c; 122 | text-decoration: none; 123 | } 124 | 125 | a:visited { 126 | color: #355f7c; 127 | text-decoration: none; 128 | } 129 | 130 | a:hover { 131 | text-decoration: underline; 132 | } 133 | 134 | 135 | 136 | /* -- body styles ----------------------------------------------------------- */ 137 | 138 | div.body h1, 139 | div.body h2, 140 | div.body h3, 141 | div.body h4, 142 | div.body h5, 143 | div.body h6 { 144 | font-family: 'Trebuchet MS', sans-serif; 145 | background-color: #f2f2f2; 146 | font-weight: normal; 147 | color: #20435c; 148 | border-bottom: 1px solid #ccc; 149 | margin: 20px -20px 10px -20px; 150 | padding: 3px 0 3px 10px; 151 | } 152 | 153 | div.body h1 { margin-top: 0; font-size: 200%; } 154 | div.body h2 { font-size: 160%; } 155 | div.body h3 { font-size: 140%; } 156 | div.body h4 { font-size: 120%; } 157 | div.body h5 { font-size: 110%; } 158 | div.body h6 { font-size: 100%; } 159 | 160 | a.headerlink { 161 | color: #c60f0f; 162 | font-size: 0.8em; 163 | padding: 0 4px 0 4px; 164 | text-decoration: none; 165 | } 166 | 167 | a.headerlink:hover { 168 | background-color: #c60f0f; 169 | color: white; 170 | } 171 | 172 | div.body p, div.body dd, div.body li { 173 | text-align: justify; 174 | line-height: 130%; 175 | } 176 | 177 | div.admonition p.admonition-title + p { 178 | display: inline; 179 | } 180 | 181 | div.admonition p { 182 | margin-bottom: 5px; 183 | } 184 | 185 | div.admonition pre { 186 | margin-bottom: 5px; 187 | } 188 | 189 | div.admonition ul, div.admonition ol { 190 | margin-bottom: 5px; 191 | } 192 | 193 | div.note { 194 | background-color: #eee; 195 | border: 1px solid #ccc; 196 | } 197 | 198 | div.seealso { 199 | background-color: #ffc; 200 | border: 1px solid #ff6; 201 | } 202 | 203 | div.topic { 204 | background-color: #eee; 205 | } 206 | 207 | div.warning { 208 | background-color: #ffe4e4; 209 | border: 1px solid #f66; 210 | } 211 | 212 | p.admonition-title { 213 | display: inline; 214 | } 215 | 216 | p.admonition-title:after { 217 | content: ":"; 218 | } 219 | 220 | pre { 221 | padding: 5px; 222 | background-color: #eeffcc; 223 | color: #333333; 224 | line-height: 120%; 225 | border: 1px solid #ac9; 226 | border-left: none; 227 | border-right: none; 228 | } 229 | 230 | tt { 231 | background-color: #ecf0f3; 232 | padding: 0 1px 0 1px; 233 | font-size: 0.95em; 234 | } 235 | 236 | th { 237 | background-color: #ede; 238 | } 239 | 240 | .warning tt { 241 | background: #efc2c2; 242 | } 243 | 244 | .note tt { 245 | background: #d6d6d6; 246 | } 247 | 248 | .viewcode-back { 249 | font-family: sans-serif; 250 | } 251 | 252 | div.viewcode-block:target { 253 | background-color: #f4debf; 254 | border-top: 1px solid #ac9; 255 | border-bottom: 1px solid #ac9; 256 | } -------------------------------------------------------------------------------- /doc/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s == 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node) { 70 | if (node.nodeType == 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { 74 | var span = document.createElement("span"); 75 | span.className = className; 76 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 77 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 78 | document.createTextNode(val.substr(pos + text.length)), 79 | node.nextSibling)); 80 | node.nodeValue = val.substr(0, pos); 81 | } 82 | } 83 | else if (!jQuery(node).is("button, select, textarea")) { 84 | jQuery.each(node.childNodes, function() { 85 | highlight(this); 86 | }); 87 | } 88 | } 89 | return this.each(function() { 90 | highlight(this); 91 | }); 92 | }; 93 | 94 | /** 95 | * Small JavaScript module for the documentation. 96 | */ 97 | var Documentation = { 98 | 99 | init : function() { 100 | this.fixFirefoxAnchorBug(); 101 | this.highlightSearchWords(); 102 | this.initIndexTable(); 103 | }, 104 | 105 | /** 106 | * i18n support 107 | */ 108 | TRANSLATIONS : {}, 109 | PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, 110 | LOCALE : 'unknown', 111 | 112 | // gettext and ngettext don't access this so that the functions 113 | // can safely bound to a different name (_ = Documentation.gettext) 114 | gettext : function(string) { 115 | var translated = Documentation.TRANSLATIONS[string]; 116 | if (typeof translated == 'undefined') 117 | return string; 118 | return (typeof translated == 'string') ? translated : translated[0]; 119 | }, 120 | 121 | ngettext : function(singular, plural, n) { 122 | var translated = Documentation.TRANSLATIONS[singular]; 123 | if (typeof translated == 'undefined') 124 | return (n == 1) ? singular : plural; 125 | return translated[Documentation.PLURALEXPR(n)]; 126 | }, 127 | 128 | addTranslations : function(catalog) { 129 | for (var key in catalog.messages) 130 | this.TRANSLATIONS[key] = catalog.messages[key]; 131 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 132 | this.LOCALE = catalog.locale; 133 | }, 134 | 135 | /** 136 | * add context elements like header anchor links 137 | */ 138 | addContextElements : function() { 139 | $('div[id] > :header:first').each(function() { 140 | $('\u00B6'). 141 | attr('href', '#' + this.id). 142 | attr('title', _('Permalink to this headline')). 143 | appendTo(this); 144 | }); 145 | $('dt[id]').each(function() { 146 | $('\u00B6'). 147 | attr('href', '#' + this.id). 148 | attr('title', _('Permalink to this definition')). 149 | appendTo(this); 150 | }); 151 | }, 152 | 153 | /** 154 | * workaround a firefox stupidity 155 | */ 156 | fixFirefoxAnchorBug : function() { 157 | if (document.location.hash && $.browser.mozilla) 158 | window.setTimeout(function() { 159 | document.location.href += ''; 160 | }, 10); 161 | }, 162 | 163 | /** 164 | * highlight the search words provided in the url in the text 165 | */ 166 | highlightSearchWords : function() { 167 | var params = $.getQueryParameters(); 168 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 169 | if (terms.length) { 170 | var body = $('div.body'); 171 | if (!body.length) { 172 | body = $('body'); 173 | } 174 | window.setTimeout(function() { 175 | $.each(terms, function() { 176 | body.highlightText(this.toLowerCase(), 'highlighted'); 177 | }); 178 | }, 10); 179 | $('') 181 | .appendTo($('#searchbox')); 182 | } 183 | }, 184 | 185 | /** 186 | * init the domain index toggle buttons 187 | */ 188 | initIndexTable : function() { 189 | var togglers = $('img.toggler').click(function() { 190 | var src = $(this).attr('src'); 191 | var idnum = $(this).attr('id').substr(7); 192 | $('tr.cg-' + idnum).toggle(); 193 | if (src.substr(-9) == 'minus.png') 194 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 195 | else 196 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 197 | }).css('display', ''); 198 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 199 | togglers.click(); 200 | } 201 | }, 202 | 203 | /** 204 | * helper function to hide the search marks again 205 | */ 206 | hideSearchWords : function() { 207 | $('#searchbox .highlight-link').fadeOut(300); 208 | $('span.highlighted').removeClass('highlighted'); 209 | }, 210 | 211 | /** 212 | * make the url absolute 213 | */ 214 | makeURL : function(relativeURL) { 215 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 216 | }, 217 | 218 | /** 219 | * get the current relative url 220 | */ 221 | getCurrentURL : function() { 222 | var path = document.location.pathname; 223 | var parts = path.split(/\//); 224 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 225 | if (this == '..') 226 | parts.pop(); 227 | }); 228 | var url = parts.join('/'); 229 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 230 | } 231 | }; 232 | 233 | // quick alias for translations 234 | _ = Documentation.gettext; 235 | 236 | $(document).ready(function() { 237 | Documentation.init(); 238 | }); 239 | -------------------------------------------------------------------------------- /doc/_build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /doc/_build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/down.png -------------------------------------------------------------------------------- /doc/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/file.png -------------------------------------------------------------------------------- /doc/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/minus.png -------------------------------------------------------------------------------- /doc/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irvined1982/arduino-ELM327/5e2f621a3b6093defc63d89dc5ca9a9857cf8856/doc/_build/html/_static/plus.png -------------------------------------------------------------------------------- /doc/_build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #eeffcc; } 3 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 8 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 9 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 10 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 11 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 14 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 15 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 16 | .highlight .go { color: #333333 } /* Generic.Output */ 17 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 18 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 19 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 20 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 21 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 22 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 23 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 24 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 25 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #902000 } /* Keyword.Type */ 27 | .highlight .m { color: #208050 } /* Literal.Number */ 28 | .highlight .s { color: #4070a0 } /* Literal.String */ 29 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 30 | .highlight .nb { color: #007020 } /* Name.Builtin */ 31 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #60add5 } /* Name.Constant */ 33 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 34 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 35 | .highlight .ne { color: #007020 } /* Name.Exception */ 36 | .highlight .nf { color: #06287e } /* Name.Function */ 37 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 38 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 39 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 40 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 41 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 42 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 44 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 45 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 46 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 47 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 48 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 49 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 50 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 51 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 52 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 53 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 54 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 55 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 56 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 57 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 58 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 59 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 60 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 61 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 62 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /doc/_build/html/_static/searchtools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * searchtools.js_t 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilties for the full-text search. 6 | * 7 | * :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | 13 | /** 14 | * Porter Stemmer 15 | */ 16 | var Stemmer = function() { 17 | 18 | var step2list = { 19 | ational: 'ate', 20 | tional: 'tion', 21 | enci: 'ence', 22 | anci: 'ance', 23 | izer: 'ize', 24 | bli: 'ble', 25 | alli: 'al', 26 | entli: 'ent', 27 | eli: 'e', 28 | ousli: 'ous', 29 | ization: 'ize', 30 | ation: 'ate', 31 | ator: 'ate', 32 | alism: 'al', 33 | iveness: 'ive', 34 | fulness: 'ful', 35 | ousness: 'ous', 36 | aliti: 'al', 37 | iviti: 'ive', 38 | biliti: 'ble', 39 | logi: 'log' 40 | }; 41 | 42 | var step3list = { 43 | icate: 'ic', 44 | ative: '', 45 | alize: 'al', 46 | iciti: 'ic', 47 | ical: 'ic', 48 | ful: '', 49 | ness: '' 50 | }; 51 | 52 | var c = "[^aeiou]"; // consonant 53 | var v = "[aeiouy]"; // vowel 54 | var C = c + "[^aeiouy]*"; // consonant sequence 55 | var V = v + "[aeiou]*"; // vowel sequence 56 | 57 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 58 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 59 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 60 | var s_v = "^(" + C + ")?" + v; // vowel in stem 61 | 62 | this.stemWord = function (w) { 63 | var stem; 64 | var suffix; 65 | var firstch; 66 | var origword = w; 67 | 68 | if (w.length < 3) 69 | return w; 70 | 71 | var re; 72 | var re2; 73 | var re3; 74 | var re4; 75 | 76 | firstch = w.substr(0,1); 77 | if (firstch == "y") 78 | w = firstch.toUpperCase() + w.substr(1); 79 | 80 | // Step 1a 81 | re = /^(.+?)(ss|i)es$/; 82 | re2 = /^(.+?)([^s])s$/; 83 | 84 | if (re.test(w)) 85 | w = w.replace(re,"$1$2"); 86 | else if (re2.test(w)) 87 | w = w.replace(re2,"$1$2"); 88 | 89 | // Step 1b 90 | re = /^(.+?)eed$/; 91 | re2 = /^(.+?)(ed|ing)$/; 92 | if (re.test(w)) { 93 | var fp = re.exec(w); 94 | re = new RegExp(mgr0); 95 | if (re.test(fp[1])) { 96 | re = /.$/; 97 | w = w.replace(re,""); 98 | } 99 | } 100 | else if (re2.test(w)) { 101 | var fp = re2.exec(w); 102 | stem = fp[1]; 103 | re2 = new RegExp(s_v); 104 | if (re2.test(stem)) { 105 | w = stem; 106 | re2 = /(at|bl|iz)$/; 107 | re3 = new RegExp("([^aeiouylsz])\\1$"); 108 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 109 | if (re2.test(w)) 110 | w = w + "e"; 111 | else if (re3.test(w)) { 112 | re = /.$/; 113 | w = w.replace(re,""); 114 | } 115 | else if (re4.test(w)) 116 | w = w + "e"; 117 | } 118 | } 119 | 120 | // Step 1c 121 | re = /^(.+?)y$/; 122 | if (re.test(w)) { 123 | var fp = re.exec(w); 124 | stem = fp[1]; 125 | re = new RegExp(s_v); 126 | if (re.test(stem)) 127 | w = stem + "i"; 128 | } 129 | 130 | // Step 2 131 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 132 | if (re.test(w)) { 133 | var fp = re.exec(w); 134 | stem = fp[1]; 135 | suffix = fp[2]; 136 | re = new RegExp(mgr0); 137 | if (re.test(stem)) 138 | w = stem + step2list[suffix]; 139 | } 140 | 141 | // Step 3 142 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 143 | if (re.test(w)) { 144 | var fp = re.exec(w); 145 | stem = fp[1]; 146 | suffix = fp[2]; 147 | re = new RegExp(mgr0); 148 | if (re.test(stem)) 149 | w = stem + step3list[suffix]; 150 | } 151 | 152 | // Step 4 153 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 154 | re2 = /^(.+?)(s|t)(ion)$/; 155 | if (re.test(w)) { 156 | var fp = re.exec(w); 157 | stem = fp[1]; 158 | re = new RegExp(mgr1); 159 | if (re.test(stem)) 160 | w = stem; 161 | } 162 | else if (re2.test(w)) { 163 | var fp = re2.exec(w); 164 | stem = fp[1] + fp[2]; 165 | re2 = new RegExp(mgr1); 166 | if (re2.test(stem)) 167 | w = stem; 168 | } 169 | 170 | // Step 5 171 | re = /^(.+?)e$/; 172 | if (re.test(w)) { 173 | var fp = re.exec(w); 174 | stem = fp[1]; 175 | re = new RegExp(mgr1); 176 | re2 = new RegExp(meq1); 177 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 178 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 179 | w = stem; 180 | } 181 | re = /ll$/; 182 | re2 = new RegExp(mgr1); 183 | if (re.test(w) && re2.test(w)) { 184 | re = /.$/; 185 | w = w.replace(re,""); 186 | } 187 | 188 | // and turn initial Y back to y 189 | if (firstch == "y") 190 | w = firstch.toLowerCase() + w.substr(1); 191 | return w; 192 | } 193 | } 194 | 195 | 196 | 197 | /** 198 | * Simple result scoring code. 199 | */ 200 | var Scorer = { 201 | // Implement the following function to further tweak the score for each result 202 | // The function takes a result array [filename, title, anchor, descr, score] 203 | // and returns the new score. 204 | /* 205 | score: function(result) { 206 | return result[4]; 207 | }, 208 | */ 209 | 210 | // query matches the full name of an object 211 | objNameMatch: 11, 212 | // or matches in the last dotted part of the object name 213 | objPartialMatch: 6, 214 | // Additive scores depending on the priority of the object 215 | objPrio: {0: 15, // used to be importantResults 216 | 1: 5, // used to be objectResults 217 | 2: -5}, // used to be unimportantResults 218 | // Used when the priority is not in the mapping. 219 | objPrioDefault: 0, 220 | 221 | // query found in title 222 | title: 15, 223 | // query found in terms 224 | term: 5 225 | }; 226 | 227 | 228 | /** 229 | * Search Module 230 | */ 231 | var Search = { 232 | 233 | _index : null, 234 | _queued_query : null, 235 | _pulse_status : -1, 236 | 237 | init : function() { 238 | var params = $.getQueryParameters(); 239 | if (params.q) { 240 | var query = params.q[0]; 241 | $('input[name="q"]')[0].value = query; 242 | this.performSearch(query); 243 | } 244 | }, 245 | 246 | loadIndex : function(url) { 247 | $.ajax({type: "GET", url: url, data: null, 248 | dataType: "script", cache: true, 249 | complete: function(jqxhr, textstatus) { 250 | if (textstatus != "success") { 251 | document.getElementById("searchindexloader").src = url; 252 | } 253 | }}); 254 | }, 255 | 256 | setIndex : function(index) { 257 | var q; 258 | this._index = index; 259 | if ((q = this._queued_query) !== null) { 260 | this._queued_query = null; 261 | Search.query(q); 262 | } 263 | }, 264 | 265 | hasIndex : function() { 266 | return this._index !== null; 267 | }, 268 | 269 | deferQuery : function(query) { 270 | this._queued_query = query; 271 | }, 272 | 273 | stopPulse : function() { 274 | this._pulse_status = 0; 275 | }, 276 | 277 | startPulse : function() { 278 | if (this._pulse_status >= 0) 279 | return; 280 | function pulse() { 281 | var i; 282 | Search._pulse_status = (Search._pulse_status + 1) % 4; 283 | var dotString = ''; 284 | for (i = 0; i < Search._pulse_status; i++) 285 | dotString += '.'; 286 | Search.dots.text(dotString); 287 | if (Search._pulse_status > -1) 288 | window.setTimeout(pulse, 500); 289 | } 290 | pulse(); 291 | }, 292 | 293 | /** 294 | * perform a search for something (or wait until index is loaded) 295 | */ 296 | performSearch : function(query) { 297 | // create the required interface elements 298 | this.out = $('#search-results'); 299 | this.title = $('

' + _('Searching') + '

').appendTo(this.out); 300 | this.dots = $('').appendTo(this.title); 301 | this.status = $('

').appendTo(this.out); 302 | this.output = $('