mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 13:34:54 +01:00
Native ESP32 CAN support (#1629)
Co-authored-by: Guillermo Ruffino <glm.net@gmail.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
27364ee72c
commit
5026bc7a78
6 changed files with 217 additions and 0 deletions
|
@ -58,6 +58,7 @@ esphome/components/esp32/* @esphome/core
|
|||
esphome/components/esp32_ble/* @jesserockz
|
||||
esphome/components/esp32_ble_server/* @jesserockz
|
||||
esphome/components/esp32_camera_web_server/* @ayufan
|
||||
esphome/components/esp32_can/* @Sympatron
|
||||
esphome/components/esp32_improv/* @jesserockz
|
||||
esphome/components/esp8266/* @esphome/core
|
||||
esphome/components/exposure_notifications/* @OttoWinter
|
||||
|
|
0
esphome/components/esp32_can/__init__.py
Normal file
0
esphome/components/esp32_can/__init__.py
Normal file
39
esphome/components/esp32_can/canbus.py
Normal file
39
esphome/components/esp32_can/canbus.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import canbus
|
||||
from esphome.const import CONF_ID, CONF_RX_PIN, CONF_TX_PIN
|
||||
from esphome.components.canbus import CanbusComponent, CanSpeed, CONF_BIT_RATE
|
||||
|
||||
CODEOWNERS = ["@Sympatron"]
|
||||
DEPENDENCIES = ["esp32"]
|
||||
|
||||
esp32_can_ns = cg.esphome_ns.namespace("esp32_can")
|
||||
esp32_can = esp32_can_ns.class_("ESP32Can", CanbusComponent)
|
||||
|
||||
# Currently the driver only supports a subset of the bit rates defined in canbus
|
||||
CAN_SPEEDS = {
|
||||
"50KBPS": CanSpeed.CAN_50KBPS,
|
||||
"100KBPS": CanSpeed.CAN_100KBPS,
|
||||
"125KBPS": CanSpeed.CAN_125KBPS,
|
||||
"250KBPS": CanSpeed.CAN_250KBPS,
|
||||
"500KBPS": CanSpeed.CAN_500KBPS,
|
||||
"1000KBPS": CanSpeed.CAN_1000KBPS,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = canbus.CANBUS_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(esp32_can),
|
||||
cv.Optional(CONF_BIT_RATE, default="125KBPS"): cv.enum(CAN_SPEEDS, upper=True),
|
||||
cv.Required(CONF_RX_PIN): pins.internal_gpio_input_pin_number,
|
||||
cv.Required(CONF_TX_PIN): pins.internal_gpio_output_pin_number,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await canbus.register_canbus(var, config)
|
||||
|
||||
cg.add(var.set_rx(config[CONF_RX_PIN]))
|
||||
cg.add(var.set_tx(config[CONF_TX_PIN]))
|
123
esphome/components/esp32_can/esp32_can.cpp
Normal file
123
esphome/components/esp32_can/esp32_can.cpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
#ifdef USE_ESP32
|
||||
#include "esp32_can.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <driver/can.h>
|
||||
|
||||
// WORKAROUND, because CAN_IO_UNUSED is just defined as (-1) in this version
|
||||
// of the framework which does not work with -fpermissive
|
||||
#undef CAN_IO_UNUSED
|
||||
#define CAN_IO_UNUSED ((gpio_num_t) -1)
|
||||
|
||||
namespace esphome {
|
||||
namespace esp32_can {
|
||||
|
||||
static const char *const TAG = "esp32_can";
|
||||
|
||||
static bool get_bitrate(canbus::CanSpeed bitrate, can_timing_config_t *t_config) {
|
||||
switch (bitrate) {
|
||||
case canbus::CAN_50KBPS:
|
||||
*t_config = (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS();
|
||||
return true;
|
||||
case canbus::CAN_100KBPS:
|
||||
*t_config = (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS();
|
||||
return true;
|
||||
case canbus::CAN_125KBPS:
|
||||
*t_config = (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS();
|
||||
return true;
|
||||
case canbus::CAN_250KBPS:
|
||||
*t_config = (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS();
|
||||
return true;
|
||||
case canbus::CAN_500KBPS:
|
||||
*t_config = (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS();
|
||||
return true;
|
||||
case canbus::CAN_1000KBPS:
|
||||
*t_config = (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ESP32Can::setup_internal() {
|
||||
can_general_config_t g_config =
|
||||
CAN_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, CAN_MODE_NORMAL);
|
||||
can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL();
|
||||
can_timing_config_t t_config;
|
||||
|
||||
if (!get_bitrate(this->bit_rate_, &t_config)) {
|
||||
// invalid bit rate
|
||||
this->mark_failed();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Install CAN driver
|
||||
if (can_driver_install(&g_config, &t_config, &f_config) != ESP_OK) {
|
||||
// Failed to install driver
|
||||
this->mark_failed();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start CAN driver
|
||||
if (can_start() != ESP_OK) {
|
||||
// Failed to start driver
|
||||
this->mark_failed();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) {
|
||||
if (frame->can_data_length_code > canbus::CAN_MAX_DATA_LENGTH) {
|
||||
return canbus::ERROR_FAILTX;
|
||||
}
|
||||
|
||||
uint32_t flags = CAN_MSG_FLAG_NONE;
|
||||
if (frame->use_extended_id) {
|
||||
flags |= CAN_MSG_FLAG_EXTD;
|
||||
}
|
||||
if (frame->remote_transmission_request) {
|
||||
flags |= CAN_MSG_FLAG_RTR;
|
||||
}
|
||||
|
||||
can_message_t message = {
|
||||
.flags = flags,
|
||||
.identifier = frame->can_id,
|
||||
.data_length_code = frame->can_data_length_code,
|
||||
};
|
||||
if (!frame->remote_transmission_request) {
|
||||
memcpy(message.data, frame->data, frame->can_data_length_code);
|
||||
}
|
||||
|
||||
if (can_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
|
||||
return canbus::ERROR_OK;
|
||||
} else {
|
||||
return canbus::ERROR_ALLTXBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
canbus::Error ESP32Can::read_message(struct canbus::CanFrame *frame) {
|
||||
can_message_t message;
|
||||
|
||||
if (can_receive(&message, 0) != ESP_OK) {
|
||||
return canbus::ERROR_NOMSG;
|
||||
}
|
||||
|
||||
frame->can_id = message.identifier;
|
||||
frame->use_extended_id = message.flags & CAN_MSG_FLAG_EXTD;
|
||||
frame->remote_transmission_request = message.flags & CAN_MSG_FLAG_RTR;
|
||||
frame->can_data_length_code = message.data_length_code;
|
||||
|
||||
if (!frame->remote_transmission_request) {
|
||||
size_t dlc =
|
||||
message.data_length_code < canbus::CAN_MAX_DATA_LENGTH ? message.data_length_code : canbus::CAN_MAX_DATA_LENGTH;
|
||||
memcpy(frame->data, message.data, dlc);
|
||||
}
|
||||
|
||||
return canbus::ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace esp32_can
|
||||
} // namespace esphome
|
||||
|
||||
#endif
|
29
esphome/components/esp32_can/esp32_can.h
Normal file
29
esphome/components/esp32_can/esp32_can.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esphome/components/canbus/canbus.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace esp32_can {
|
||||
|
||||
class ESP32Can : public canbus::Canbus {
|
||||
public:
|
||||
void set_rx(int rx) { rx_ = rx; }
|
||||
void set_tx(int tx) { tx_ = tx; }
|
||||
ESP32Can(){};
|
||||
|
||||
protected:
|
||||
bool setup_internal() override;
|
||||
canbus::Error send_message(struct canbus::CanFrame *frame) override;
|
||||
canbus::Error read_message(struct canbus::CanFrame *frame) override;
|
||||
|
||||
int rx_{-1};
|
||||
int tx_{-1};
|
||||
};
|
||||
|
||||
} // namespace esp32_can
|
||||
} // namespace esphome
|
||||
|
||||
#endif
|
|
@ -2472,6 +2472,11 @@ text_sensor:
|
|||
id: glob_int
|
||||
value: '0'
|
||||
- canbus.send:
|
||||
canbus_id: mcp2515_can
|
||||
can_id: 23
|
||||
data: [0x10, 0x20, 0x30]
|
||||
- canbus.send:
|
||||
canbus_id: esp32_internal_can
|
||||
can_id: 23
|
||||
data: [0x10, 0x20, 0x30]
|
||||
- platform: template
|
||||
|
@ -2509,6 +2514,7 @@ rtttl:
|
|||
|
||||
canbus:
|
||||
- platform: mcp2515
|
||||
id: mcp2515_can
|
||||
cs_pin: GPIO17
|
||||
can_id: 4
|
||||
bit_rate: 50kbps
|
||||
|
@ -2525,6 +2531,25 @@ canbus:
|
|||
lambda: 'return x[0] == 0x11;'
|
||||
then:
|
||||
light.toggle: ${roomname}_lights
|
||||
- platform: esp32_can
|
||||
id: esp32_internal_can
|
||||
rx_pin: GPIO04
|
||||
tx_pin: GPIO05
|
||||
can_id: 4
|
||||
bit_rate: 50kbps
|
||||
on_frame:
|
||||
- can_id: 500
|
||||
then:
|
||||
- lambda: |-
|
||||
std::string b(x.begin(), x.end());
|
||||
ESP_LOGD("canid 500", "%s", &b[0] );
|
||||
- can_id: 23
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return x[0] == 0x11;'
|
||||
then:
|
||||
light.toggle: ${roomname}_lights
|
||||
|
||||
teleinfo:
|
||||
id: myteleinfo
|
||||
|
|
Loading…
Reference in a new issue