Sparkfun OBDII — Arduino Uno застрял на скорости 832 об/мин — 13 км/ч

Я работаю над хобби-проектом с Sparkfun OBDII UART + Arduino Uno + ЖК-экраном 16x2, я пытаюсь считывать показания датчика RPM-Speed-Coolant Temprature-Oxy во время работы.

Страница продукта

Подключение OBDII к Arduino как: OBD TX-> АРДУИНО приемник OBD RX-> АРДУИНО TX OBD GND-> ЗАЗЕМЛЕНИЕ ARDUINO

Насколько я понимаю, плата OBDII выполняет всю работу, и она просто взаимодействует с Arduino через последовательный порт, они предоставили пример здесь: Руководство по подключению

У меня нет серийного ЖК-дисплея sparkfun, поэтому я изменил коды в соответствии с моим ЖК-дисплеем следующим образом;

#include <SoftwareSerial.h>
#include "DFRobot_RGBLCD.h"
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
DFRobot_RGBLCD lcd(16,2);  //16 символов и 2 строки шоу
char rxData[20];
char rxIndex=0;
int vehicleSpeed=0;
int vehicleRPM=0;
void setup()
{
lcd.init();
lcd.setRGB(colorR, colorG, colorB);
Serial.begin(9600);
lcd.clear();  
lcd.setCursor(0,0);
lcd.print("Hiz: ");
lcd.setCursor(0,1);
lcd.print("Devir: ");
delay(1500);
Serial.println("ATZ");
delay(2000);
Serial.flush();
}

void loop()
{
Serial.println("010D");
getResponse();
getResponse();
vehicleSpeed = strtol(&rxData[6],0,16);
lcd.setCursor(4,0);
lcd.print(vehicleSpeed);
lcd.print(" km/h");
delay(100);
Serial.flush();
Serial.println("010C");
getResponse();
getResponse();
vehicleRPM = ((strtol(&rxData[6],0,16)*256)+strtol(&rxData[9],0,16))/4;
lcd.setCursor(6,1);
lcd.print(vehicleRPM);
delay(100);
}
void getResponse(void){
  char inChar=0;
  while(inChar != '\r'){
    if(Serial.available() > 0){
      if(Serial.peek() == '\r'){
        inChar=Serial.read();
        rxData[rxIndex]='\0';
        rxIndex=0;
      }
      else{
        inChar = Serial.read();
        rxData[rxIndex++]=inChar;
      }
    }
  }
}

с приведенным выше кодом я считаю, что arduino получает последние обороты в минуту и скорость, прежде чем я выключу двигатель, который составляет 832 об / мин - 13 км / ч (на данный момент я не уверен, что arduino правильно получает значение скорости, потому что, когда я выключил двигатель, я была припаркована машина и скорость была 0 км/ч), в обычном случае, когда я завожу машину, обороты и скорость должны были измениться, но даже после того, как машина завелась, значение стоит на месте, оно не меняется.

Я купил адаптер Waveshare USB FTDI (TTL), чтобы выяснить, правильно ли эта плата взаимодействует с автомобилем или ПК, подключил usb ttl как; OBD TX-> ТТЛ-прием OBD RX-> ТТЛ-передача OBD GND-> ТТЛ ЗАЗЕМЛЕНИЕ

подключен к порту OBDII моей машины, открыл термин tera, подключился к COM20 (ttl определяется как com20 на ПК) и выполнил следующие команды, как предлагается в их руководстве;

ATZ -- карта успешно сброшена
ATRV -- вернул 12,4 В, как и должно быть, это напряжение моего аккумулятора
ATSP0 - автоматический поиск и выбор протокола автомобиля, он вернулся в порядке
010C -- Обороты автомобиля вернул 41 0C 00 00 (двигатель не запускался)
010C -- число оборотов автомобиля возвращается 41 0C 10 F4 (двигатель запущен -- обороты холостого хода около 1000 об/мин)
010D -- скорость машины вернулась 41 00 00
010D -- скорость машины вернула 41 00 00, оба значения одинаковы, потому что машина не движется :)

Согласно приведенному выше результату, плата в порядке и без проблем взаимодействует с автомобилем, ПК или Arduino.

Но когда я пытаюсь использовать arduino, когда я подключаю плату к своей машине и переключаю зажигание в режим работы от батареи, число оборотов в минуту составляет 832, а скорость - 13, и эти значения не обновляются, даже если я запускаю двигатель.

Что я делаю не так?

, 👍1


1 ответ


Лучший ответ:

1

после 1 недели попыток я наконец решил эту проблему :)

Как вы, ребята, знаете, у UNO есть 1 последовательный порт ввода-вывода, а плата Sparkfun OBDII не работает с тем же последовательным портом ввода-вывода (по крайней мере, я не мог), с uno при отправке команды через последовательный порт на плату obd вам нужно подождать минимум 3 секунды, чтобы отправить другую команду, иначе CAN-шина автомобиля думает, что вы отменили первую команду, возвращает ошибку STOPPED, но с MEGA это работает отлично, потому что mega имеет 3 последовательных порта ввода / вывода. Вы просто определяете Serial(TX)-Serial1(RX), и он отлично работает с задержкой 75 мс.

Вот рабочий код.

//Настраиваем кольцевой буфер
char rxData[20];
char rxIndex = 0;
int rpmstored = 0;

    void setup()
    {
      Serial.begin(9600); // печатает в последовательный монитор
      Serial1.begin(9600); //Аппаратное последовательное подключение к obdii uart
      OBD_init(); //инициирует связь obd
      delay(3000);
    }
   
    void loop()
{   
rpmstored = getRPM();
//int mph = (int)((getSPEED() * 10000L + 5) / 16090); // конвертируем в мили в час
// Serial.print (миль/час);
Serial.print("S:");
Serial.print (getSPEED());
Serial.print (",");
Serial.print("R:");
Serial.println (getRPM());
//Serial.print(",");
//Serial.print("W:");
//Serial.print (getWATERTEMP());
//Serial.print(",");
//Serial.print("O:");
//Serial.print (getOILTEMP());
//Serial.print(",");
//Serial.print("F:");
//Serial.print (getFUEL());
//Serial.print(",");
//Serial.print("V:");
//Serial.println (getVOLT());
delay(100);
Serial.flush();
    }
   
    void OBD_init(void)
    {
      // Подождите немного перед отправкой команды сброса на OBD-II-UART
      delay(2000);
      //Сброс OBD-II-UART
      Serial1.print("ATZ\r");
      // Подождите немного, прежде чем начать отправлять команды после сброса.
      delay(2);
      OBD_read();
      Serial1.print("ATE0\r");
      OBD_read();
      //Serial1.flush();
    }
   
    int getRPM(void)
    {
      //Запрос OBD-II-UART для оборотов автомобиля
      Serial1.flush();
      Serial1.print("010C\r");
      OBD_read();

      return ((strtol(&rxData[6], 0, 16) * 256) + strtol(&rxData[9], 0, 16)) / 4;
    }

    int getSPEED(void)
    {
      // Запросите OBD-II-UART скорость автомобиля
      Serial1.flush();
      Serial1.print("010D\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getOILTEMP(void)
    {
      // Запросите OBD-II-UART скорость автомобиля
      Serial1.flush();
      Serial1.print("015C\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getFUEL(void)
    {
      // Запросите OBD-II-UART скорость автомобиля
      Serial1.flush();
      Serial1.print("012F\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getVOLT(void)
    {
      // Запросите OBD-II-UART скорость автомобиля
      Serial1.flush();
      Serial1.print("0142\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16);
    }

    int getWATERTEMP(void)
    {
      //Запрос OBD-II-UART для температуры охлаждающей жидкости двигателя
      Serial1.flush();
      Serial1.print("0105\r");
      OBD_read();

      return strtol(&rxData[6], 0, 16) - 40;
    }
   
   
    void OBD_read(void)
    {
      char c;
      do {
        if (Serial1.available() > 0)
        {
          c = Serial1.read();
          if ((c != '>') && (c != '\r') && (c != '\n')) //Держите их вне нашего буфера
          {
            rxData[rxIndex++] = c; //Добавляем все что получаем в буфер
          }
        }
      } while (c != '>'); // ELM327 заканчивает свой ответ этим символом, поэтому, когда мы его получаем, мы выходим.
      rxData[rxIndex++] = '\0';//Преобразует массив в строку
      rxIndex = 0; //Установите это значение в 0, чтобы в следующий раз, когда мы вызывали чтение, мы получали "чистый буфер"
   
    }

Мне нужен только RPM & Скорость, поэтому я закомментировал другие параметры, но все протестировал и работает отлично.

,