2023年5月9日 星期二

ESP32 + MCP2515 use CanHacker on CAN Bus system

在之前文章CAN BUS 通訊研究中, 利用了MEGA2560+MCP2515去做CAN BUS上接收和傳送資料. 最近看到一篇文章 可以用ESP32去做CAN BUS上的sniffer來分析.

CANHacker 參考 https://github.com/autowp/arduino-canhacker install library

其中是想利用他的windows端的軟體CANHackerV2.00.01.exe來做CAN bus analyzer

download link


功能傳輸圖:

上圖右邊是ESP32做控制, 左邊是MEGA2560
其中裡面燒得code是參照https://github.com/autowp/can-usb
線路圖

在燒錄can-usb時記得加入下圖紅線字以及disable loopback不然windows 端的軟體會找不到interface


焊接版本

//-----------------------------------------------------------------------------------
修改程式
Modify the original sample code to use ESP32 dual-core multiplex architecture FreeRTOS
//--------------------------------------------------------------------------------------
#include <can.h>
#include <mcp2515.h>

#include <CanHacker.h>
#include <CanHackerLineReader.h>
#include <lib.h>

#include <SPI.h>
#include <SoftwareSerial.h>
//----------------------------------------------------------------------
//------ESP32 CAN BUS setting ---------------------------------------
const int SPI_CS_PIN = 5;
const int INT_PIN = 21;
//---------------------------------------------------------------------
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif

const int SS_RX_PIN = 3;
const int SS_TX_PIN = 4;
//----------------------------------------------------------------
TaskHandle_t hled;
TaskHandle_t huart;
TaskHandle_t hcan;

CanHackerLineReader *lineReader = NULL;
CanHacker *canHacker = NULL;

SoftwareSerial softwareSerial(SS_RX_PIN, SS_TX_PIN);

void setup() {
  Serial.begin(115200);
  while (!Serial);
  SPI.begin();
  softwareSerial.begin(115200);

  Stream *interfaceStream = &Serial;
  Stream *debugStream = &softwareSerial;


  canHacker = new CanHacker(interfaceStream, debugStream, SPI_CS_PIN);

  canHacker->setClock(MCP_8MHZ);    // For 8MHz crystal oscillator
  //canHacker->enableLoopback(); // uncomment this for loopback
  lineReader = new CanHackerLineReader(canHacker);

  pinMode(INT_PIN, INPUT);
  //--------------- create task----------------------------------
  xTaskCreatePinnedToCore(
    vLEDTask, "LEDTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &hled //handle
    ,
    0);
  //----------------------------------------
  xTaskCreatePinnedToCore(
    vCANTask, "CANTask"
    ,
    1024 // Stack size
    ,
    NULL, 1 // Priority
    ,
    &hcan
    ,
    1);

  //Serial.println("Systom On!");

}
void loop() {
  /**
    CanHacker::ERROR error;

    if (digitalRead(INT_PIN) == LOW) {
      error = canHacker->processInterrupt();
      handleError(error);
    }

    error = lineReader->process();
    handleError(error);**/
}

static void vCANTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.println(F("CANTask at core:"));
  Serial.println(xPortGetCoreID());
  for (;;)
  {
    CanHacker::ERROR error;

    if (digitalRead(INT_PIN) == LOW) {
      error = canHacker->processInterrupt();
      handleError(error);
    }

    error = lineReader->process();
    handleError(error);
  }
  vTaskDelay(1);
}

static void vLEDTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.println(F("LEDTask at core:"));
  Serial.println(xPortGetCoreID());
  pinMode(LED_BUILTIN, OUTPUT);
  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
    vTaskDelay(200);
    digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
    vTaskDelay(200);
  }
}

void handleError(const CanHacker::ERROR error) {

  switch (error) {
    case CanHacker::ERROR_OK:
    case CanHacker::ERROR_UNKNOWN_COMMAND:
    case CanHacker::ERROR_NOT_CONNECTED:
    case CanHacker::ERROR_MCP2515_ERRIF:
    case CanHacker::ERROR_INVALID_COMMAND:
      return;

    default:
      break;
  }

  softwareSerial.print("Failure (code ");
  softwareSerial.print((int)error);
  softwareSerial.println(")");

  digitalWrite(SPI_CS_PIN, HIGH);
  pinMode(LED_BUILTIN, OUTPUT);

  while (1) {
    int c = (int)error;
    for (int i = 0; i < c; i++) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(500);
      digitalWrite(LED_BUILTIN, LOW);
      delay(500);
    }

    delay(2000);
  } ;
}

驗證影片
//------------------------------------------------------------
若有問題歡迎留言討論!!!
//------------------------------------------------------------
YouTube 影片




沒有留言:

張貼留言