Arduino + MCP2515

can-control
Offline
Зарегистрирован: 28.01.2020

Здравствуйте, друзья! Помогите разобраться в фильтрации кан сообщений. Использую несколько модулей состоящих из ардуино про мини и mcp2515+mcp2551. Эти модули использую в своем автомобиле. В теории все работает, но на практике жуткие тормоза. Использую библиотеку "mcp_can". Кроме моих модулей в сети кан общаются еще штатные модули(н\р приборная панель). Там тормозов не замечено.

Вот в таком варианте работает безупречно. Тормозов нет. Но тут можно принять сообщение только с одним ID.

#include <mcp_can.h>
#include <SPI.h>

uint8_t temp_buf[8] = {0,0,0,0,0,0,0,0}; 

MCP_CAN CAN(10);                                  

void setup()
{
  CAN.begin(CAN_250KBPS);              
  CAN.init_Mask(0, 0, 0x3ff);                        
  CAN.init_Mask(1, 0, 0x3ff);
  CAN.init_Filt(0, 0, 0x64);
}

void loop()
{  
   if (CAN_MSGAVAIL == CAN.checkReceive())            
    {
       CAN.readMsgBuf(&len, temp_buf);    
            
       if (temp_buf[0] == 1) { digitalWrite(4, HIGH); } else { digitalWrite(4, LOW); }
       
       if (temp_buf[1] == 1) { digitalWrite(5, HIGH); } else { digitalWrite(5, LOW); }
       
       if (temp_buf[2] == 1) { digitalWrite(6, HIGH); } else { digitalWrite(6, LOW); }
   }
}

Если принимать сообщения с разными ID, то начинаются проскакивание сообщений. Сообщения пропускаются, а на практике это выливается в задержки ответной реакции в принимающей стороне (переключение выходов).

#include <mcp_can.h>
#include <SPI.h>

uint8_t temp_buf[8]   =  {0,0,0,0,0,0,0,0}; 
uint8_t buf_1[8]      =  {0,0,0,0,0,0,0,0}; 
uint8_t buf_2[8]      =  {0,0,0,0,0,0,0,0}; 

MCP_CAN CAN(10);                                  

void setup()
{
  CAN.begin(CAN_250KBPS);              
  CAN.init_Mask(0, 0, 0x3ff);                        
  CAN.init_Mask(1, 0, 0x3ff);
  CAN.init_Filt(0, 0, 0x64);
  CAN.init_Filt(1, 0, 0x75);
}

void loop()
{  
   if (CAN_MSGAVAIL == CAN.checkReceive())            
    {
       CAN.readMsgBuf(&len, temp_buf);    
           if(CAN.getCanId() == 0x64)
            {
              for(int i = 0; i<len; i++) {  buf_1[i] = temp_buf[i]; }
           }

          if(CAN.getCanId() == 0x75)
            {
              for(int i = 0; i<len; i++) {  buf_2[i] = temp_buf[i]; }
            }
     }

       if (buf_1[0] == 1) { digitalWrite(4, HIGH); } else { digitalWrite(4, LOW); }
       
       if (buf_1[1] == 1) { digitalWrite(5, HIGH); } else { digitalWrite(5, LOW); }
       
       if (buf_1[2] == 1) { digitalWrite(6, HIGH); } else { digitalWrite(6, LOW); }



       if (buf_2[0] == 1) { digitalWrite(7, HIGH); } else { digitalWrite(7, LOW); }
       
       if (buf_2[1] == 1) { digitalWrite(8, HIGH); } else { digitalWrite(8, LOW); }
       
       if (buf_2[2] == 1) { digitalWrite(9, HIGH); } else { digitalWrite(9, LOW); }
   
}

Понятно, что используется больше тактов для цикла присваивания, но задержка получения данных всегда с разной длительностью. Может сразу принять сообщение, а может и через некоторое время.

MaksVV
Offline
Зарегистрирован: 06.08.2015
#include <mcp_can.h>
#include <SPI.h>
MCP_CAN CAN(10);                                  

void setup()
{
  CAN.begin(CAN_250KBPS);              
  CAN.init_Mask(0, 0, 0x3ff);                        
  CAN.init_Mask(1, 0, 0x3ff);
  CAN.init_Filt(0, 0, 0x64);
  CAN.init_Filt(1, 0, 0x75);
}

void loop()
{  
   if (CAN_MSGAVAIL == CAN.checkReceive())            
    {  
       byte buf[8] = {0};
       CAN.readMsgBuf(&len, temp_buf);    
       byte firstpin = 0;
       if(CAN.getCanId() == 0x64)  firstpin=4;
       if(CAN.getCanId() == 0x75)  firstpin=7;
       if(firstpin>0) 
         { 
           for(int i = 0; i<3; i++) 
              { 
                if (buf[i] == 1) digitalWrite(i+firstpin, HIGH); 
                else             digitalWrite(i+firstpin, LOW); 
              }
         }
            
     } 
}

 

can-control
Offline
Зарегистрирован: 28.01.2020

Спасибо, за ответ, но все не так просто. Согласен, пример не очень полно отражает картину. Немного поправлю: 

#include <mcp_can.h>
#include <SPI.h>

uint8_t temp_buf[8]   =  {0,0,0,0,0,0,0,0}; 
uint8_t buf_1[8]      =  {0,0,0,0,0,0,0,0}; 
uint8_t buf_2[8]      =  {0,0,0,0,0,0,0,0}; 
uint8_t val_1 = 0;
uint8_t val_2 = 0;

MCP_CAN CAN(10);                                  

void setup()
{
  CAN.begin(CAN_250KBPS);              
  CAN.init_Mask(0, 0, 0x3ff);                        
  CAN.init_Mask(1, 0, 0x3ff);
  CAN.init_Filt(0, 0, 0x64);
  CAN.init_Filt(1, 0, 0x75);
}

void loop()
{  
   if (CAN_MSGAVAIL == CAN.checkReceive())            
    {
       CAN.readMsgBuf(&len, temp_buf);    
           if(CAN.getCanId() == 0x64)
            {
              for(int i = 0; i<len; i++) {  buf_1[i] = temp_buf[i]; }
           }

          if(CAN.getCanId() == 0x75)
            {
              for(int i = 0; i<len; i++) {  buf_2[i] = temp_buf[i]; }
            }
     }

       if (buf_1[0] == 1) { val_1 = 0;}
       
       if (buf_1[1] == 1) { val_1 = 8;}

       if (buf_1[2] == 1) { val_1 = 11;}

       if (buf_1[3] == 1) { val_1 = 56;}

       if (buf_1[4] == 1) { val_1 = 31;}  
    
       if (buf_1[5] == 1) { val_1 = 67;}

       if (buf_1[6] == 1) { val_1 = 92;}

       if (buf_1[7] == 1) { val_1 = 3;}
   
      

       if (buf_2[0] == 1) { val_2 = 0;}
       
       if (buf_2[1] == 1) { val_2 = 65;}

       if (buf_2[2] == 1) { val_2 = 24;}

       if (buf_2[3] == 1) { val_2 = 17;}

       if (buf_2[4] == 1) { val_2 = 87;}

       if (buf_2[5] == 1) { val_2 = 70;}

       if (buf_2[6] == 1) { val_2 = 22;}

       if (buf_2[7] == 1) { val_2 = 5;}


   
}

 

Пример абстрактный! Отражающий логику работы. Периоды у посылок разные 100мс и 50мс. Более медленная посылка может приниматься очень долго, а может сразу проскочить.

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

очень корявый подход у вас. Что вы вообще хотите сделать? и что конкретно сейчас не получается? 

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

can-control пишет:

Пример абстрактный! Отражающий логику работы.

"отражающий логику "- это хорошо сказано. Точнее полное отсутсвие логики.

Макс правильно говорит - вставьте работу с пришедшими данными внутрь проверики условия на конкретный ID - внутрь IF строк 26 и 31. Вы же так делали в своем первом коде, который работал "безупречно" - зачем же вы тут нагородили какую-то околесицу?  Кстати, тогда и отдельный буфер для каждого ID станет не нужен.

Суд по коду - проблема тут не в том, что "КАН тормозит", а в плохом проектировании программы.

can-control
Offline
Зарегистрирован: 28.01.2020

Я хочу принимать сообщения из сети кан и работать с данными в этих сообщениях. Сейчас у меня происходит задержка в получении сообщений - то сообщение, которое чаще отправляется приходит, например 10 раз подряд, а второе, которое реже - один, а может и дольше не попадать в приемное устройство. могут и сразу оба придти.

can-control
Offline
Зарегистрирован: 28.01.2020

 

У меня сообщения от двух устройств одновременно. И с этими данными я работаю постоянно. Где тогда  полученные данных хранить?

can-control
Offline
Зарегистрирован: 28.01.2020

Я согласен, что в #2 логики не особо много, но не знаю как показать, что сообщения нельзя в одну кучу смешивать.

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

can-control пишет:

У меня сообщения от двух устройств одновременно. И с этими данными я работаю постоянно. Где тогда  полученные данных хранить?

зачем их хранить? - насколько я вижу, по результатам приема вы включаете и выключаете выходы - так делайте это сразу

Что еще есть в прогграмме? Может дело в том, что у вас цикл ЛУП выполняется больше 50мс? - задержек или каких-то медленных действий в программе нет?

can-control
Offline
Зарегистрирован: 28.01.2020

b707 пишет:

can-control пишет:

У меня сообщения от двух устройств одновременно. И с этими данными я работаю постоянно. Где тогда  полученные данных хранить?

зачем их хранить? - насколько я вижу, по результатам приема вы включаете и выключаете выходы - так делайте это сразу

Что еще есть в прогграмме? Может дело в том, что у вас цикл ЛУП выполняется больше 50мс? - задержек или каких-то медленных действий в программе нет?

 

Программа для примера. Там не только входы - выходы. Данные из сообщения обрабатываются, с ними производятся определенные действия. 

В первом коде все работает, потому что фильтр отсекает все кроме нужного ID еще на уровне MCP. Когда фильтров больше одного начинается каша. Приход сообщений отлично видно через последовательный порт.

Вопрос был о фильтрах.

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

can-control пишет:

Вопрос был о фильтрах.

с фильтрами у вас все нормально.

Поэтому я и спрашиваю про программу. Вы зря не верите - но если у вас программа делает в цикле что-то еще и принимает ссобщение по КАН шине порядка раз в 50мс или реже - вы всегда будете принимать только более частое сообщение и лишь изредко то, что приходит реже.

А вот если оставить только один адрес - будет ощущение, что потерь нет, какие бы задержки не стояли.

Вы пробовали измерить, сколько миллисекунд у вас занимает испольнение цикла loop() ? - попробуйте, рузльтат может быть интерсеным

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

can-control пишет:
Я хочу принимать сообщения из сети кан и работать с данными в этих сообщениях.

так и делайте. Например так, возможно ваша проблема исчезнет при таком подходе. Только тестируйте именно этот код!

#include <mcp_can.h>
#include <SPI.h>

uint8_t val_1 = 0;
uint8_t val_2 = 0;

MCP_CAN CAN(10);                                  

void setup()
{
  CAN.begin(CAN_250KBPS);              
  CAN.init_Mask(0, 0, 0x3ff);                        
  CAN.init_Mask(1, 0, 0x3ff);
  CAN.init_Filt(0, 0, 0x64);
  CAN.init_Filt(1, 0, 0x75);
  Serial.begin (115200);
}

void loop()
{  
   if (CAN_MSGAVAIL == CAN.checkReceive())            
    {
       uint8_t temp_buf[8]   =  {0}; 
       CAN.readMsgBuf(&len, temp_buf);    
           if(CAN.getCanId() == 0x64)
              {
                if (temp_buf[0] == 1) { val_1 = 0;}
                if (temp_buf[1] == 1) { val_1 = 8;}
                if (temp_buf[2] == 1) { val_1 = 11;}
                if (temp_buf[3] == 1) { val_1 = 56;}
                if (temp_buf[4] == 1) { val_1 = 31;}  
                if (temp_buf[5] == 1) { val_1 = 67;}
                if (temp_buf[6] == 1) { val_1 = 92;}
                if (temp_buf[7] == 1) { val_1 = 3;}
                
              }

            if(CAN.getCanId() == 0x75)
              {
                if (temp_buf[0] == 1) { val_2 = 0;}
                if (temp_buf[1] == 1) { val_2 = 65;}
                if (temp_buf[2] == 1) { val_2 = 24;}
                if (temp_buf[3] == 1) { val_2 = 17;}
                if (temp_buf[4] == 1) { val_2 = 87;}
                if (temp_buf[5] == 1) { val_2 = 70;}
                if (temp_buf[6] == 1) { val_2 = 22;}
                if (temp_buf[7] == 1) { val_2 = 5;}
              }
        Serial.print (CAN.getCanId(), HEX); Serial.print (" "); Serial.println (millis());  
    }
}

 

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

can-control пишет:
Приход сообщений отлично видно через последовательный порт.

где это в вашем коде?! Так не пойдёт. Зачем выкладывать сюда другой код? Выкладывайте тот код, на котором вы выявили проблему.