Считать значение скорости с CAN автомобиля и подать меандр на панель приборов.
- Войдите на сайт для отправки комментариев
Задача: взять значение скорости из 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]
А вот этот вариант меняет меандр скачками . Но частота стабильна и не пропадает.
Хотя если опять же таки вручную подставить значение , то генерация меандра с шагом в 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]
вставьте код по правилам форума, чтобы были номера строк. Без номеров невозможно указать на ошибки в коде
[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][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]в коде #4 у вас логическая ошибка - строки с 29 по 40 можно смело выкинуть, они вообще ничего не делают. проверки переменных бесполезны, на результат они не влиют никак
я не силен в библиотеке mcp2515.h ? но как по другому присвоить переменной "а" значение первого байта сообщения с id 0х4A0 ? (сигнал скорости из CAN шины ). строки 29-30. И если в PWM послать нулевую частоту , то на выходе получим 500 Гц. Поэтому если сигнал скорости 0 то, чтобы спидометр не сходил с ума выбираем скважность 0 либо 255. Значения не имеет . b=a тоже можно убрать. Но сути это не меняет. иногда генерация меандра пропадает. а в коде #3 движется ступенчато.
я не силен в библиотеке mcp2515.h ?
да причем тут библиотека, когда у вас в коде логическая несуразица накручена. Зачем в строчках с 31 по 38 вы что-то там сравниваете, если в строке 41 skv устанавливается в значение 128 НЕЗАВИСИМО отпредыдущих условных операторов?
я дико извиняюсь. 41 строка не нужна . это я случайно написал, когда экспериментировал подставляя вместо кан значения вручную.
может так ?
#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; } } } }а в другом коде достаточно одну скобку переставить, кмк:
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); } } }чтобы 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; // обновим старое значение скорости } } } }#10 проверил . Отлично работает. Стабильно. Огромное спасибо b707!!! И спасибо всем за помощь. Остальные варианты попробую откатать в ближайшее время.
судя по всему мои исправления не работают, эх зря старался))
судя по всему мои исправления не работают, эх зря старался))
не переживай :) - мне просто повезло
судя по всему мои исправления не работают, эх зря старался))
почему не работают? еще не проверял....
#9 .К сожалению по прежнему работает с перебоями. Иногда пропадает генерация меандра.
а #11?
а #11?
не успел.
успешно испытали на www.carlife.by
успешно испытали на www.carlife.by
то есть взяли на бесплатном форуме код, потом продали клиенту? - молодцы
Да еще и свой сайт тут пиарят.
Вообще-то никакой код никому не продавали. Делали для своей ауди. Не наша специфика. За 20 лет работы впервые понадобился такой костыль. Все современные машины общаются по CAN, также как и эта. Но бод боком валялась старая панель ( древняя не умеющая общаться по CAN). Вот для себя и решили впихнуть невпихуемое. Ни какой клиент за такое денег не заплатит, при наличии кучи б/ушных панелей. У нас автосервис, и сайт пиарить никакой нужды нет. А координаты оставил на случай если кто заинтересуется (в чем я сильно сомневаюсь) и вдруг возникнут вопросы. Да и продвигать авторемонт на этом ресурсе?.....Затея глупая.....Но за помощь еще раз благодарю.