mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-06-06 04:48:27 +02:00
Canbus + MCP2515 including ExtID support (#1384)
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/optional.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace canbus {
|
||||
|
||||
enum Error : uint8_t {
|
||||
ERROR_OK = 0,
|
||||
ERROR_FAIL = 1,
|
||||
ERROR_ALLTXBUSY = 2,
|
||||
ERROR_FAILINIT = 3,
|
||||
ERROR_FAILTX = 4,
|
||||
ERROR_NOMSG = 5
|
||||
};
|
||||
|
||||
enum CanSpeed : uint8_t {
|
||||
CAN_5KBPS,
|
||||
CAN_10KBPS,
|
||||
CAN_20KBPS,
|
||||
CAN_31K25BPS,
|
||||
CAN_33KBPS,
|
||||
CAN_40KBPS,
|
||||
CAN_50KBPS,
|
||||
CAN_80KBPS,
|
||||
CAN_83K3BPS,
|
||||
CAN_95KBPS,
|
||||
CAN_100KBPS,
|
||||
CAN_125KBPS,
|
||||
CAN_200KBPS,
|
||||
CAN_250KBPS,
|
||||
CAN_500KBPS,
|
||||
CAN_1000KBPS
|
||||
};
|
||||
|
||||
class CanbusTrigger;
|
||||
template<typename... Ts> class CanbusSendAction;
|
||||
|
||||
/* CAN payload length definitions according to ISO 11898-1 */
|
||||
static const uint8_t CAN_MAX_DATA_LENGTH = 8;
|
||||
|
||||
/*
|
||||
Can Frame describes a normative CAN Frame
|
||||
The RTR = Remote Transmission Request is implemented in every CAN controller but rarely used
|
||||
So currently the flag is passed to and from the hardware but currently ignored to the user application.
|
||||
*/
|
||||
struct CanFrame {
|
||||
bool use_extended_id = false;
|
||||
bool remote_transmission_request = false;
|
||||
uint32_t can_id; /* 29 or 11 bit CAN_ID */
|
||||
uint8_t can_data_length_code; /* frame payload length in byte (0 .. CAN_MAX_DATA_LENGTH) */
|
||||
uint8_t data[CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)));
|
||||
};
|
||||
|
||||
class Canbus : public Component {
|
||||
public:
|
||||
Canbus(){};
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void loop() override;
|
||||
|
||||
void send_data(uint32_t can_id, bool use_extended_id, const std::vector<uint8_t> &data);
|
||||
void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
|
||||
void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
|
||||
void set_bitrate(CanSpeed bit_rate) { this->bit_rate_ = bit_rate; }
|
||||
|
||||
void add_trigger(CanbusTrigger *trigger);
|
||||
|
||||
protected:
|
||||
template<typename... Ts> friend class CanbusSendAction;
|
||||
std::vector<CanbusTrigger *> triggers_{};
|
||||
uint32_t can_id_;
|
||||
bool use_extended_id_;
|
||||
CanSpeed bit_rate_;
|
||||
|
||||
virtual bool setup_internal();
|
||||
virtual Error send_message(struct CanFrame *frame);
|
||||
virtual Error read_message(struct CanFrame *frame);
|
||||
};
|
||||
|
||||
template<typename... Ts> class CanbusSendAction : public Action<Ts...>, public Parented<Canbus> {
|
||||
public:
|
||||
void set_data_template(const std::function<std::vector<uint8_t>(Ts...)> func) {
|
||||
this->data_func_ = func;
|
||||
this->static_ = false;
|
||||
}
|
||||
void set_data_static(const std::vector<uint8_t> &data) {
|
||||
this->data_static_ = data;
|
||||
this->static_ = true;
|
||||
}
|
||||
|
||||
void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
|
||||
|
||||
void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
|
||||
|
||||
void play(Ts... x) override {
|
||||
auto can_id = this->can_id_.has_value() ? *this->can_id_ : this->parent_->can_id_;
|
||||
auto use_extended_id =
|
||||
this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_;
|
||||
if (this->static_) {
|
||||
this->parent_->send_data(can_id, use_extended_id, this->data_static_);
|
||||
} else {
|
||||
auto val = this->data_func_(x...);
|
||||
this->parent_->send_data(can_id, use_extended_id, val);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
optional<uint32_t> can_id_{};
|
||||
optional<bool> use_extended_id_{};
|
||||
bool static_{false};
|
||||
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||
std::vector<uint8_t> data_static_{};
|
||||
};
|
||||
|
||||
class CanbusTrigger : public Trigger<std::vector<uint8_t>>, public Component {
|
||||
friend class Canbus;
|
||||
|
||||
public:
|
||||
explicit CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const bool use_extended_id)
|
||||
: parent_(parent), can_id_(can_id), use_extended_id_(use_extended_id){};
|
||||
void setup() override { this->parent_->add_trigger(this); }
|
||||
|
||||
protected:
|
||||
Canbus *parent_;
|
||||
uint32_t can_id_;
|
||||
bool use_extended_id_;
|
||||
};
|
||||
|
||||
} // namespace canbus
|
||||
} // namespace esphome
|
||||
Reference in New Issue
Block a user