Считать значение скорости с CAN автомобиля и подать меандр на панель приборов.

guttman
Offline
Зарегистрирован: 03.09.2019

Задача: взять значение скорости из CAN шины автомобиля и подать меандр на вход сигнала скорости панели приборов автомобиля. 1 км/ч = 1 Гц.

Все работает за исключением одного маленького ньюанса: иногда совершенно хаотично пропадает меандр на 1 - 2 секунды. 

Если вместо значений CAN подставить значение вручную, то стабильная частота. Если создать цикл с увеличением или уменьшением "a" , то тоже стабильно работает. Но как только беру значение из шины автомобиля , появляется хаотичное пропадание меандра  . При этом само считанное значение скорости  из CAN актуально  в этот момент. 

ARDUINO NANO + CAN MCP2515

[code]
#include <PWM.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);
int32_t b = 1;
int pin = 9;
int skv = 0;
int a = 0;
void setup() {

  InitTimersSafe();

  Serial.begin(9600);

  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();

}

void loop() {
  pwmWrite(pin, skv);
  SetPinFrequencySafe(pin, b);

  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
  {
    if (canMsg.can_id == 0X4A0)
    {  a = canMsg.data[1];           }
      if (a != 0)
      {
        skv = 128;
      }
      else
      {
        skv = 0;
      }
    }
  }
 skv = 128;
b = a;

}
[/code]

 
 

 

guttman
Offline
Зарегистрирован: 03.09.2019

А вот этот вариант меняет меандр скачками . Но частота стабильна и не пропадает.

Хотя если опять же таки вручную подставить значение , то генерация меандра с шагом в 1 Гц происходит нормально.

Замена железа проблему не решает и характер проблемы не меняет.

 

 

[code]
const int out = 4; //выход на транзистор
int outState = LOW; //хранение статуса выхода
int b = 0;
int a = 0;  //данные скорости из кан
unsigned long previousMicros = 0;
unsigned long interval = 0;
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10);

void setup() {
  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();

  pinMode(out, OUTPUT);
}

void loop() {
  unsigned long currentMicros = micros();
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    if (canMsg.can_id == 0X4A0) {
      a = canMsg.data[1];
    }
    if (a != 0) {
      //a = b;

      interval = 500000 / a;
      if (currentMicros - previousMicros > interval) {
        previousMicros = currentMicros;
        if (outState == LOW)
          outState = HIGH;
        else
          outState = LOW;
        digitalWrite(out, outState);

      }
    }
  }
}
[/code]

 
 
b707
Offline
Зарегистрирован: 26.05.2017

вставьте код по правилам форума, чтобы были номера строк. Без номеров невозможно указать на ошибки в коде

guttman
Offline
Зарегистрирован: 03.09.2019
[code]
const int out = 4; //выход на транзистор
int outState = LOW; //хранение статуса выхода
int b = 0;
int a = 0;  //данные скорости из кан
unsigned long previousMicros = 0;
unsigned long interval = 0;
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10);


void setup() {
  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();

  pinMode(out, OUTPUT);
}

void loop() {
  unsigned long currentMicros = micros();
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    if (canMsg.can_id == 0X4A0) {
      a = canMsg.data[1];
    }
    if (a != 0) {
      //a = b;

      interval = 500000 / a;
      if (currentMicros - previousMicros > interval) {
        previousMicros = currentMicros;
        if (outState == LOW)
          outState = HIGH;
        else
          outState = LOW;
        digitalWrite(out, outState);


      }
    }
  }
}
[/code]

 

guttman
Offline
Зарегистрирован: 03.09.2019
[code]
#include <PWM.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);
int32_t b = 1;
int pin = 9;
int skv = 0;
int a = 0;
void setup() {

  InitTimersSafe();

  Serial.begin(9600);

  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();

}

void loop() {
  pwmWrite(pin, skv);
  SetPinFrequencySafe(pin, b);

  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
  {
    if (canMsg.can_id == 0X4A0)
    {  a = canMsg.data[1];           }
      if (a != 0)
      {
        skv = 128;
      }
      else
      {
        skv = 0;
      }
    }
  }
 skv = 128;
b = a;

}
[/code]

 

b707
Offline
Зарегистрирован: 26.05.2017

в коде #4 у вас логическая ошибка - строки с 29 по 40 можно смело выкинуть, они вообще ничего не делают. проверки переменных бесполезны, на результат они не влиют никак

guttman
Offline
Зарегистрирован: 03.09.2019

я не  силен в библиотеке mcp2515.h ? но как по другому присвоить переменной "а" значение первого байта сообщения с id 0х4A0 ? (сигнал скорости из CAN шины ). строки 29-30. И если в PWM послать нулевую частоту , то на выходе получим 500 Гц. Поэтому если сигнал скорости 0 то, чтобы спидометр не сходил с ума выбираем скважность 0 либо 255. Значения не имеет . b=a тоже можно убрать. Но сути это не меняет. иногда генерация меандра пропадает. а в коде #3 движется ступенчато.

b707
Offline
Зарегистрирован: 26.05.2017

guttman пишет:

я не  силен в библиотеке mcp2515.h ?

да причем тут библиотека, когда у вас в коде логическая несуразица накручена. Зачем в строчках с 31 по 38 вы что-то там сравниваете, если в строке 41 skv устанавливается в значение 128 НЕЗАВИСИМО отпредыдущих условных операторов?

guttman
Offline
Зарегистрирован: 03.09.2019

я дико извиняюсь. 41 строка не нужна . это я случайно написал, когда экспериментировал подставляя вместо кан значения вручную.  

MaksVV
Offline
Зарегистрирован: 06.08.2015

может так ?

#include <PWM.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);
const int PWMpin = 9;

void setup() 
{
  InitTimersSafe();
  Serial.begin(9600);
  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();
}

void loop() 
{
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
  {
    if (canMsg.can_id == 0X4A0)
    {
      byte Speed;
      static byte Speed_last;   // старое значение переменной скорости
      Speed = canMsg.data[1];
         if (Speed_last!=Speed)     // если значение скорости изменилось меняем частоту меандра
         {
          SetPinFrequencySafe(PWMpin, Speed);
          if (Speed!=0) pwmWrite(PWMpin, 128);  // если скорость больше нуля то скважность 50%
          else          pwmWrite(PWMpin, 0)  ;  // если скорость равна нулю то скважность в ноль
          Speed_last=Speed;
         }
    }
     
  }  
}

 

b707
Offline
Зарегистрирован: 26.05.2017

а в другом коде достаточно одну скобку переставить, кмк:

const int out = 4; //выход на транзистор
int outState = LOW; //хранение статуса выхода
int b = 0;
int a = 0;  //данные скорости из кан
unsigned long previousMicros = 0;
unsigned long interval = 0;
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10);


void setup() {
  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();

  pinMode(out, OUTPUT);
}

void loop() {
  unsigned long currentMicros = micros();
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
    if (canMsg.can_id == 0X4A0) {
      a = canMsg.data[1];
    }
}
    if (a != 0) {
      //a = b;

      interval = 500000 / a;
      if (currentMicros - previousMicros > interval) {
        previousMicros = currentMicros;
        if (outState == LOW)
          outState = HIGH;
        else
          outState = LOW;
        digitalWrite(out, outState);


      }
    }
  
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

чтобы pwmWrite постоянно не дёргать, наверное даже лучше так

#include <PWM.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);
const int PWMpin = 9;

void setup() 
{
  InitTimersSafe();
  Serial.begin(9600);
  mcp2515.reset();
  mcp2515.setBitrate (CAN_500KBPS,  MCP_8MHZ);
  mcp2515.setNormalMode();
}

void loop() 
{
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
  {
    if (canMsg.can_id == 0X4A0)
    {
      byte Speed;
      static byte Speed_last;       // старое значение скорости
      Speed = canMsg.data[1];
         if (Speed_last!=Speed)     // если значение скорости изменилось... 
         {
          SetPinFrequencySafe(PWMpin, Speed);  // ...меняем частоту меандра
                                     
          // если скорость стала больше нуля то скважность 50%
          if (Speed_last==0 && Speed >0) {pwmWrite(PWMpin, 128);}
          
          // если скорость стала равна нулю то скважность в ноль
          if (Speed_last> 0 && Speed==0) {pwmWrite(PWMpin,   0);}  
         Speed_last=Speed;          // обновим старое значение скорости
         }
    }
     
  }  
}

 

guttman
Offline
Зарегистрирован: 03.09.2019

#10 проверил . Отлично работает. Стабильно. Огромное спасибо b707!!! И спасибо всем  за помощь. Остальные варианты попробую откатать в ближайшее время.

MaksVV
Offline
Зарегистрирован: 06.08.2015

судя по всему мои исправления не работают, эх зря старался)) 

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

судя по всему мои исправления не работают, эх зря старался)) 

не переживай :) - мне просто повезло

guttman
Offline
Зарегистрирован: 03.09.2019

MaksVV пишет:

судя по всему мои исправления не работают, эх зря старался)) 

почему не работают? еще не проверял....

guttman
Offline
Зарегистрирован: 03.09.2019

#9 .К сожалению по прежнему работает с перебоями. Иногда пропадает генерация меандра.

MaksVV
Offline
Зарегистрирован: 06.08.2015

а #11?

guttman
Offline
Зарегистрирован: 03.09.2019

MaksVV пишет:

а #11?

не успел.

 

guttman
Offline
Зарегистрирован: 03.09.2019

успешно испытали на www.carlife.by

b707
Offline
Зарегистрирован: 26.05.2017

guttman пишет:

успешно испытали на www.carlife.by

то есть взяли на бесплатном форуме код, потом продали клиенту? - молодцы

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Да еще и свой сайт тут пиарят. 

guttman
Offline
Зарегистрирован: 03.09.2019

Вообще-то никакой код никому не продавали. Делали для своей ауди. Не наша специфика. За 20 лет работы впервые понадобился такой костыль. Все современные машины общаются по CAN, также как и эта. Но бод боком валялась старая панель ( древняя не умеющая общаться по CAN). Вот для себя  и решили впихнуть невпихуемое. Ни какой клиент за такое денег не заплатит, при наличии кучи б/ушных панелей. У нас автосервис, и сайт пиарить никакой нужды нет. А координаты оставил на случай если кто заинтересуется (в чем я сильно сомневаюсь)  и вдруг возникнут вопросы. Да и продвигать авторемонт на этом ресурсе?.....Затея глупая.....Но за помощь еще раз благодарю.