Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong RPM #185

Closed
supergraupe opened this issue Oct 17, 2023 · 16 comments
Closed

Wrong RPM #185

supergraupe opened this issue Oct 17, 2023 · 16 comments
Assignees
Labels
bug Something isn't working question Further information is requested

Comments

@supergraupe
Copy link

supergraupe commented Oct 17, 2023

Hi, I'm just trying to program a data logger for my motorbike.
It will combine GPS, Angle, rpm and kph.
SD for logging and a Display for setup and control.

Using ELM327 for rpm and kph.
Connection is established.
When I try to read rpm I always get the fix value 884.
In this LOG the ignition was on but the engine was not running.
Got the same when the engine is at different rpm.
Any idea?

#include "BluetoothSerial.h"
#include "ELMduino.h"

BluetoothSerial SerialBT;
#define ELM_PORT SerialBT
#define DEBUG_PORT Serial

ELM327 myELM327;

uint32_t rpm = 0;
// To change for a different ELM327
uint8_t MyBTAddress[6] = {0x66, 0x1E, 0x11,
                          0xEE, 0xAD, 0xAC};  // ELM MAC Adress

void setup() {
#if LED_BUILTIN
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
#endif

  DEBUG_PORT.begin(115200);

  ELM_PORT.begin("ArduHUD", true);
  ELM_PORT.setPin("1234");

  if (!ELM_PORT.connect(MyBTAddress)) {
    DEBUG_PORT.println("Couldn't connect to BT - Phase 1");
    while (1)
      ;
  }

  if (!myELM327.begin(ELM_PORT, true, 2000)) {
    Serial.println("Couldn't connect to OBD - Phase 2");
    while (1)
      ;
  }

  Serial.println("Connected to ELM327");
}

void loop() {
  float tempRPM = myELM327.rpm();

  if (myELM327.nb_rx_state == ELM_SUCCESS) {
    rpm = (uint32_t)tempRPM;
    Serial.println(rpm);
  } else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
    myELM327.printError();
}

LOG:
Clearing input serial buffer
Sending the following command/query: AT D
Received char: O
Received char: K
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: OK
Clearing input serial buffer
Sending the following command/query: AT Z
Received char: A
Received char: T
Received char: Z
Received char: \r
Received char: \r
Received char: \r
Received char: E
Received char: L
Received char: M
Received char: 3
Received char: 2
Received char: 7
Received char: _
Received char: v
Received char: 1
Received char: .
Received char: 5
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: ATZELM327v1.5
Clearing input serial buffer
Sending the following command/query: AT E0
Received char: A
Received char: T
Received char: E
Received char: 0
Received char: \r
Received char: O
Received char: K
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: ATE0OK
Clearing input serial buffer
Sending the following command/query: AT S0
Received char: O
Received char: K
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: OK
Clearing input serial buffer
Sending the following command/query: AT AL
Received char: O
Received char: K
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: OK
Clearing input serial buffer
Sending the following command/query: AT ST 00
Received char: O
Received char: K
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: OK
Clearing input serial buffer
Sending the following command/query: AT TP A0
Received char: O
Received char: K
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: OK
Connected to ELM327
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: S
Received char: E
Received char: A
Received char: R
Received char: C
Received char: H
Received char: I
Received char: N
Received char: G
Received char: .
Received char: .
Received char: .
Received char: \r
Timeout detected with overflow of 0ms
Received: SEARCHING...
ERROR: ELM_TIMEOUT
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 0
Received char: 0
Received char: 0
Received char: 0
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C0000
Expected response header: 410C
Single response detected
64-bit response: 0
responseByte_0: 0
responseByte_1: 0
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
884
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 0
Received char: 0
Received char: 0
Received char: 0
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C0000
Expected response header: 410C
Single response detected
64-bit response: 0
responseByte_0: 0
responseByte_1: 0
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
884

@supergraupe supergraupe added the question Further information is requested label Oct 17, 2023
@PowerBroker2
Copy link
Owner

Everything looks ok except for two things:

  • The first query times out (I don't think this should be an issue, but you could set the timeout inbegin() to be >10 sec or so to see if that fixes this)
  • Your vehicle seems to be reporting 0RPM for some reason. If the timeout edit above doesn't fix this, the issue might be with the vehicle itself

@PowerBroker2
Copy link
Owner

Wait, I see now that the RPM should actually be 0. I will need to investigate a little more. It would be helpful if you could add more debug prints, especially in conditionResponse() within the ELMduino.cpp file

@supergraupe
Copy link
Author

I put some additional debug code in conditionResponce().

if (numExpectedBytes > numPayChars) {
if (debugMode)
Serial.println(
F("WARNING: Number of expected response bytes is greater than the "
"number of payload chars returned by ELM327 - returning 0"));

return 0;

} else if (numExpectedBytes == numPayChars) {
if (debugMode) {
Serial.print("numExpectedBytes == numPayChars Response: ");
Serial.println(response);**
}
return ((response * scaleFactor) + bias);
}

// If there were more payload bytes returned than we expected, test the first
// and last bytes in the returned payload and see which gives us a higher
// value. Sometimes ELM327's return leading zeros and others return trailing
// zeros. The following approach gives us the best chance at determining where
// the real data is. Note that if the payload returns BOTH leading and
// trailing zeros, this will not give accurate results!

uint64_t leadingResponse = 0;
for (uint8_t i = 0; i < numExpectedBytes; i++) {
uint8_t payloadIndex = PAYLOAD_LEN - numPayChars + i;
uint8_t bitsOffset = 4 * (numExpectedBytes - i - 1);

leadingResponse |= (ctoi(payload[payloadIndex]) << bitsOffset);

}
if (debugMode) {
Serial.print("leading Responce: ");
Serial.println(leadingResponse);
}
uint64_t laggingResponse = 0;
for (uint8_t i = 0; i < numExpectedBytes; i++) {
uint8_t payloadIndex = PAYLOAD_LEN - numExpectedBytes + i;
uint8_t bitsOffset = 4 * (numExpectedBytes - i - 1);

laggingResponse |= (ctoi(payload[payloadIndex]) << bitsOffset);

}
if (debugMode) {
Serial.print("lagging Responce: ");
Serial.println(laggingResponse);
}

if (leadingResponse > laggingResponse)
return ((float)leadingResponse * scaleFactor) + bias;
return ((float)laggingResponse * scaleFactor) + bias;

And here is the result as logfile.
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 2
Received char: 2
Received char: B
Received char: 8
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C22B8
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 184
responseByte_1: 34
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 2
Received char: 4
Received char: 2
Received char: 0
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C2420
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 32
responseByte_1: 36
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 2
Received char: 3
Received char: 1
Received char: 4
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C2314
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 20
responseByte_1: 35
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884

The condition numExpectedBytes == numPayChars isn't valid in this example.
No debug info in the log.
No responce to main loop.

leading Responce is equal to lagging Responce.
responce only if they are not equal.
No responce to main loop

In the LOG is an additional \r.
May that is the reason?

@supergraupe
Copy link
Author

To see more details, I just extend the debug info.
numExpectedBytes
numPayChars

if (debugMode) {
Serial.print("numExpectedBytes: ");
Serial.println(numExpectedBytes);
Serial.print("numPayChars: ");
Serial.println(numPayChars);
}

if (numExpectedBytes > numPayChars) {
if (debugMode)
Serial.println(
F("WARNING: Number of expected response bytes is greater than the "
"number of payload chars returned by ELM327 - returning 0"));

return 0;

} else if (numExpectedBytes == numPayChars) {
if (debugMode) {
Serial.print("numExpectedBytes == numPayChars Response: ");
Serial.println(response);
}
return ((response * scaleFactor) + bias);
}

LOG:
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 1
Received char: 9
Received char: 7
Received char: C
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C197C
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 124
responseByte_1: 25
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
numExpectedBytes: 2
numPayChars: 4
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 1
Received char: 9
Received char: D
Received char: 8
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C19D8
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 216
responseByte_1: 25
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
numExpectedBytes: 2
numPayChars: 4
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884

Hope it will help.

@PowerBroker2
Copy link
Owner

Please format your code snippets properly, thanks

@supergraupe
Copy link
Author

Don't know how to format it.
Will try again.

@supergraupe
Copy link
Author

float ELM327::conditionResponse(const uint8_t &numExpectedBytes, const float &scaleFactor, const float &bias) {
if (numExpectedBytes > 8)
if (debugMode)
Serial.println(
F("WARNING: Number of expected response bytes is greater than 8 - "
"returning 0"));
return 0;
}
if (debugMode) {
Serial.print("numExpectedBytes: ");
Serial.println(numExpectedBytes);
Serial.print("numPayChars: ");
Serial.println(numPayChars);
}

if (numExpectedBytes > numPayChars) {
if (debugMode)
Serial.println(
F("WARNING: Number of expected response bytes is greater than the "
"number of payload chars returned by ELM327 - returning 0"));
return 0;
} else if (numExpectedBytes == numPayChars) {
if (debugMode) {
Serial.print("numExpectedBytes == numPayChars Response: ");
Serial.println(response);
}
return ((response * scaleFactor) + bias);
}

// If there were more payload bytes returned than we expected, test the first
// and last bytes in the returned payload and see which gives us a higher
// value. Sometimes ELM327's return leading zeros and others return trailing
// zeros. The following approach gives us the best chance at determining where
// the real data is. Note that if the payload returns BOTH leading and
// trailing zeros, this will not give accurate results!

uint64_t leadingResponse = 0;
for (uint8_t i = 0; i < numExpectedBytes; i++) {
uint8_t payloadIndex = PAYLOAD_LEN - numPayChars + i;
uint8_t bitsOffset = 4 * (numExpectedBytes - i - 1);
leadingResponse |= (ctoi(payload[payloadIndex]) << bitsOffset);
}
if (debugMode) {
Serial.print("leading Responce: ");
Serial.println(leadingResponse);
}
uint64_t laggingResponse = 0;
for (uint8_t i = 0; i < numExpectedBytes; i++) {
uint8_t payloadIndex = PAYLOAD_LEN - numExpectedBytes + i;
uint8_t bitsOffset = 4 * (numExpectedBytes - i - 1);
laggingResponse |= (ctoi(payload[payloadIndex]) << bitsOffset);
}
if (debugMode) {
Serial.print("lagging Responce: ");
Serial.println(laggingResponse);
}

if (leadingResponse > laggingResponse)
return ((float)leadingResponse * scaleFactor) + bias;
return ((float)laggingResponse * scaleFactor) + bias;
}

@patfelst
Copy link
Contributor

to format arduino code, just type three back ticks "```c++", then a new line and paste all your code. At the end, put a newline then three more back ticks.

Here's an example, except I replace backticks with another character so github doesn't format it so you can read it!

'''c++
your code here
many lines of c++ code
'''

for your logs
'''log
log output
log output
'''

@supergraupe
Copy link
Author

Got it.

float ELM327::conditionResponse(const uint8_t &numExpectedBytes,
                                const float &scaleFactor, const float &bias) {
  if (numExpectedBytes > 8) {
    if (debugMode)
      Serial.println(
          F("WARNING: Number of expected response bytes is greater than 8 - "
            "returning 0"));
    return 0;
  }
  if (debugMode) {
    Serial.print("numExpectedBytes: ");
    Serial.println(numExpectedBytes);
    Serial.print("numPayChars: ");
    Serial.println(numPayChars);
  }

  if (numExpectedBytes > numPayChars) {
    if (debugMode)
      Serial.println(
          F("WARNING: Number of expected response bytes is greater than the "
            "number of payload chars returned by ELM327 - returning 0"));
    return 0;
  } else if (numExpectedBytes == numPayChars) {
    if (debugMode) {
      Serial.print("numExpectedBytes == numPayChars Response: ");
      Serial.println(response);
    }
    return ((response * scaleFactor) + bias);
  }

  // If there were more payload bytes returned than we expected, test the first
  // and last bytes in the returned payload and see which gives us a higher
  // value. Sometimes ELM327's return leading zeros and others return trailing
  // zeros. The following approach gives us the best chance at determining where
  // the real data is. Note that if the payload returns BOTH leading and
  // trailing zeros, this will not give accurate results!

  uint64_t leadingResponse = 0;
  for (uint8_t i = 0; i < numExpectedBytes; i++) {
    uint8_t payloadIndex = PAYLOAD_LEN - numPayChars + i;
    uint8_t bitsOffset = 4 * (numExpectedBytes - i - 1);

    leadingResponse |= (ctoi(payload[payloadIndex]) << bitsOffset);
  }
  if (debugMode) {
    Serial.print("leading Responce: ");
    Serial.println(leadingResponse);
  }
  uint64_t laggingResponse = 0;
  for (uint8_t i = 0; i < numExpectedBytes; i++) {
    uint8_t payloadIndex = PAYLOAD_LEN - numExpectedBytes + i;
    uint8_t bitsOffset = 4 * (numExpectedBytes - i - 1);

    laggingResponse |= (ctoi(payload[payloadIndex]) << bitsOffset);
  }
  if (debugMode) {
    Serial.print("lagging Responce: ");
    Serial.println(laggingResponse);
  }

  if (leadingResponse > laggingResponse)
    return ((float)leadingResponse * scaleFactor) + bias;
  return ((float)laggingResponse * scaleFactor) + bias;
}
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 1
Received char: 9
Received char: 7
Received char: C
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C197C
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 124
responseByte_1: 25
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
numExpectedBytes: 2
numPayChars: 4
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884
Service: 1
PID: 12
Normal length query detected
Query string: 010C1
Clearing input serial buffer
Sending the following command/query: 010C1
Received char: 4
Received char: 1
Received char: 0
Received char: C
Received char: 1
Received char: 9
Received char: D
Received char: 8
Received char: \r
Received char: \r
Received char: >
Delimiter found.
All chars received: 410C19D8
Expected response header: 410C
Single response detected
64-bit response:
responseByte_0: 216
responseByte_1: 25
responseByte_2: 0
responseByte_3: 0
responseByte_4: 0
responseByte_5: 0
responseByte_6: 0
responseByte_7: 0
numExpectedBytes: 2
numPayChars: 4
leading Responce: 3536
lagging Responce: 3536
RPM (Loop): 884

@PowerBroker2
Copy link
Owner

I'll have to look into this a little more, but I think I see your particular issue:

Change:

  • if (numExpectedBytes > numPayChars) { to if (numExpectedBytes > (numPayChars / 2)) {
  • } else if (numExpectedBytes == numPayChars) { to } else if (numExpectedBytes == (numPayChars / 2)) {

I'm still wondering why the "leading/lagging" part of the code wasn't giving you 0 rpm, but the above updates should cause the else if to evaluate true and skip the "leading/lagging" portion

@PowerBroker2 PowerBroker2 added the bug Something isn't working label Oct 18, 2023
@supergraupe
Copy link
Author

Just changed it... and it works.

Tested it with rpm and kph.
Both fine.

Thanks for your support.

@DerKleinePunk
Copy link

@PowerBroker2
Understand than right there ist an Bug ? Why do not change the Code ?

@jimwhitelaw
Copy link
Collaborator

I'm encountering the same issue and I'm about to test the fix proposed above, but in the mean time, can someone help me understand why the value 884 is reported when this bug manifests? What's going on here? This might be more of a general programming question; I'm just not following what is happening that the same value is being returned regardless of the response from the ECU.

@PowerBroker2
Copy link
Owner

Each response char from the ELM327 is a nibble since the response format of the ELM327 is in hex. The code tries to test and see if you have more, less, or exactly the expected number of bytes received from the ELM327. However, we need to convert the number of hex nibbles to number of bytes by dividing by two for a valid comparison. This is where the main bug is and the above edits should fix it. There may be another bug causing the 884 issue, but I'll have to investigate more to figure it out.

@PowerBroker2
Copy link
Owner

I found the issue and fixed it. Try 3.1.0

@jimwhitelaw
Copy link
Collaborator

Thanks for the explanation and the fix. I will give it a go shortly.

DerKleinePunk pushed a commit to DerKleinePunk/ELMduino that referenced this issue Jan 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants