5 сент. 2025

ESP32 Считывает данные с датчика влажности и температуры, и в ID101, передает данные через CAN шину. В качестве драйвера CAN шины использоваться модуль MCP2515.

ESP32 Считывает данные с датчика влажности и температуры, и в ID101, передает данные через CAN шину. В качестве драйвера CAN шины использоваться модуль MCP2515.

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <mcp2515.h>

#define DHTPIN 4
#define DHTTYPE DHT22
#define CAN_CS 5
#define CAN_ID 0x101

DHT dht(DHTPIN, DHTTYPE);
MCP2515 mcp2515(CAN_CS);

struct can_frame canMsg;

// Структура данных для CAN сообщения
typedef struct {
  int16_t temperature;  // Температура * 100 (-327.68°C to +327.67°C)
  uint16_t humidity;    // Влажность * 100 (0.00% to 655.35%)
  uint8_t sensor_type;  // Тип датчика (0 = DHT11, 1 = DHT22)
  uint8_t error_code;   // Код ошибки
  uint16_t crc16;       // CRC16 для проверки целостности
} __attribute__((packed)) sensor_data_t;

void setup() {
  Serial.begin(115200);
  
  // Инициализация датчика
  dht.begin();
  
  // Инициализация CAN
  SPI.begin();
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();
  
  Serial.println("ESP32 DHT to CAN Converter Started");
  Serial.println("CAN ID: 0x101");
  Serial.println("Sending data every 2 seconds...");
  Serial.println("==================================");
}

void loop() {
  static unsigned long lastSendTime = 0;
  
  if (millis() - lastSendTime >= 2000) {
    readAndSendSensorData();
    lastSendTime = millis();
  }
  
  // Проверка входящих CAN сообщений
  checkIncomingCAN();
}

void readAndSendSensorData() {
  // Чтение данных с датчика
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();
  
  sensor_data_t sensorData;
  
  if (isnan(temp) || isnan(hum)) {
    // Ошибка чтения датчика
    sensorData.temperature = 0;
    sensorData.humidity = 0;
    sensorData.sensor_type = DHTTYPE;
    sensorData.error_code = 1; // Код ошибки
    Serial.println("DHT Sensor Error!");
  } else {
    // Успешное чтение
    sensorData.temperature = (int16_t)(temp * 100); // Сохраняем 2 знака после запятой
    sensorData.humidity = (uint16_t)(hum * 100);
    sensorData.sensor_type = DHTTYPE;
    sensorData.error_code = 0; // Нет ошибок
    
    Serial.printf("Temp: %.2f°C, Hum: %.2f%%\n", temp, hum);
  }
  
  // Расчет CRC
  sensorData.crc16 = calculateCRC16((uint8_t*)&sensorData, sizeof(sensorData) - 2);
  
  // Подготовка CAN сообщения
  canMsg.can_id = CAN_ID;
  canMsg.can_dlc = sizeof(sensorData);
  memcpy(canMsg.data, (uint8_t*)&sensorData, sizeof(sensorData));
  
  // Отправка CAN сообщения
  if (mcp2515.sendMessage(&canMsg) == MCP2515::ERROR_OK) {
    Serial.printf("CAN Sent - ID: 0x%03X, Data: ", CAN_ID);
    for (int i = 0; i < canMsg.can_dlc; i++) {
      Serial.printf("%02X ", canMsg.data[i]);
    }
    Serial.println();
  } else {
    Serial.println("CAN Send Error!");
  }
}

// Расчет CRC16
uint16_t calculateCRC16(uint8_t *data, uint8_t length) {
  uint16_t crc = 0xFFFF;
  for (uint8_t i = 0; i < length; i++) {
    crc ^= (uint16_t)data[i] << 8;
    for (uint8_t j = 0; j < 8; j++) {
      if (crc & 0x8000) {
        crc = (crc << 1) ^ 0x1021;
      } else {
        crc <<= 1;
      }
    }
  }
  return crc;
}

void checkIncomingCAN() {
  struct can_frame receivedMsg;
  
  if (mcp2515.readMessage(&receivedMsg) == MCP2515::ERROR_OK) {
    Serial.printf("CAN Received - ID: 0x%03X, Data: ", receivedMsg.can_id);
    for (int i = 0; i < receivedMsg.can_dlc; i++) {
      Serial.printf("%02X ", receivedMsg.data[i]);
    }
    Serial.println();
  }
}

// Функция для тестовой отправки данных
void sendTestData() {
  sensor_data_t testData;
  testData.temperature = 2350;  // 23.50°C
  testData.humidity = 655;      // 65.5%
  testData.sensor_type = DHTTYPE;
  testData.error_code = 0;
  testData.crc16 = calculateCRC16((uint8_t*)&testData, sizeof(testData) - 2);
  
  canMsg.can_id = CAN_ID;
  canMsg.can_dlc = sizeof(testData);
  memcpy(canMsg.data, (uint8_t*)&testData, sizeof(testData));
  
  mcp2515.sendMessage(&canMsg);
}

Craftum Сайт создан на Craftum