mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +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/* @jesserockz
|
||||||
esphome/components/esp32_ble_server/* @jesserockz
|
esphome/components/esp32_ble_server/* @jesserockz
|
||||||
esphome/components/esp32_camera_web_server/* @ayufan
|
esphome/components/esp32_camera_web_server/* @ayufan
|
||||||
|
esphome/components/esp32_can/* @Sympatron
|
||||||
esphome/components/esp32_improv/* @jesserockz
|
esphome/components/esp32_improv/* @jesserockz
|
||||||
esphome/components/esp8266/* @esphome/core
|
esphome/components/esp8266/* @esphome/core
|
||||||
esphome/components/exposure_notifications/* @OttoWinter
|
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
|
id: glob_int
|
||||||
value: '0'
|
value: '0'
|
||||||
- canbus.send:
|
- canbus.send:
|
||||||
|
canbus_id: mcp2515_can
|
||||||
|
can_id: 23
|
||||||
|
data: [0x10, 0x20, 0x30]
|
||||||
|
- canbus.send:
|
||||||
|
canbus_id: esp32_internal_can
|
||||||
can_id: 23
|
can_id: 23
|
||||||
data: [0x10, 0x20, 0x30]
|
data: [0x10, 0x20, 0x30]
|
||||||
- platform: template
|
- platform: template
|
||||||
|
@ -2509,6 +2514,7 @@ rtttl:
|
||||||
|
|
||||||
canbus:
|
canbus:
|
||||||
- platform: mcp2515
|
- platform: mcp2515
|
||||||
|
id: mcp2515_can
|
||||||
cs_pin: GPIO17
|
cs_pin: GPIO17
|
||||||
can_id: 4
|
can_id: 4
|
||||||
bit_rate: 50kbps
|
bit_rate: 50kbps
|
||||||
|
@ -2525,6 +2531,25 @@ canbus:
|
||||||
lambda: 'return x[0] == 0x11;'
|
lambda: 'return x[0] == 0x11;'
|
||||||
then:
|
then:
|
||||||
light.toggle: ${roomname}_lights
|
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:
|
teleinfo:
|
||||||
id: myteleinfo
|
id: myteleinfo
|
||||||
|
|
Loading…
Reference in a new issue