IOT ENTERPRISE ©
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);
}