Canbus + MCP2515 docs (#823)

This commit is contained in:
Daniel Schramm 2020-12-21 20:27:24 +01:00 committed by GitHub
parent fe6f68f150
commit a913c627c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 463 additions and 0 deletions

369
components/canbus.rst Normal file
View File

@ -0,0 +1,369 @@
.. _canbus:
CAN bus
=======
.. seo::
:description: Instructions for setting up an CAN bus in ESPHome
:image: canbus.png
:keywords: CAN
Controller Area Network (CAN bus) is a serial bus protocol to connect individual systems and sensors
as an alternative to conventional multi-wire looms.
It allows automotive components to communicate on a single or dual-wire networked data bus up to 1Mbps.
CAN is an International Standardization Organization (ISO) defined serial communications bus originally
developed for the automotive industry to replace the complex wiring harness with a two-wire bus. The
specification calls for high immunity to electrical interference and the ability to self-diagnose and repair
data errors. These features have led to CANs popularity in a variety of industries including building
automation, medical, and manufacturing.
The current ESPHome implementation supports single frame data transfer. In this way you may send and
receive data frames up to 8 bytes.
With this you can transmit the press of a button or the feedback from a sensor on the bus.
All other devices on the bus will be able to get this data to switch on/off a light or display the
transmitted data.
The CAN bus itself has only two wires named Can High and Can Low or CanH and CanL. For the ESPHome
CAN bus to work you need to select the device that has the physical CAN bus implemented.
At this moment only the MCP2515 driver is supported. You can configure multiple busses.
Any can bus node can transmit data at any time, and any node can send any ``can_id`` value and any
node can receive any can_id too. Is up to you how to organize the can_id values. You can setup a can
bus network where each node has a can id which will use to broadcast data about itself, if a node
should, e.g. turn on a light, it can listen for can messages with the can id assigned to it.
So you can have several nodes being able to control a light in e.g. node 20.
Base CAN Bus Configuration
--------------------------
Each canbus platform extends this configuration schema.
.. code-block:: yaml
# Example configuration entry
canbus:
- platform: ...
can_id: 4
on_frame:
- can_id: 500
use_extended_id: False
then:
- lambda: |-
std::string b(x.begin(), x.end());
ESP_LOGD("can id 500", "%s", &b[0] );
Configuration variables:
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
- **can_id** (**Required**, integer): default *can id* used for transmitting frames.
- **use_extended_id** (*Optional*, boolean): default *False* identifies the type of *can_id*:
*False*: Standard 11 bits IDs, *True*: Extended 29 bits ID
- **bit_rate** (*Optional*, one of the supported bitrates= defaults to ``125KBPS``.
- 5KBPS
- 10KBPS
- 20KBPS
- 31K25BPS
- 33KBPS
- 40KBPS
- 50KBPS
- 80KBPS
- 83K3BPS
- 95KBPS
- 100KBPS
- 125KBPS
- 200KBPS
- 250KBPS
- 500KBPS
- 1000KBPS
Automations:
- **on_frame** (*Optional*, :ref:`Automation <automation>`): An automation to perform when ability
CAN Frame is received. See below.
.. _canbus-on-frame:
``on_frame``
************
This automation will be triggered when a can frame is received. A variable ``x`` of type
``std::vector<uint8_t>`` is passed to the automation for use in lambdas.
.. note::
Messeges this node sends to te same ID will not show up as reveived messages.
.. code-block:: yaml
canbus:
- platform: ...
on_frame:
- can_id: 43 # the received can_id
then:
- if:
condition:
lambda: 'return (x.size() > 0) ? x[0] == 0x11 : false;'
then:
light.toggle: light1
Transmit Frame Action
*********************
The can bus can transmit frames by means of the ``canbus.send`` action.
There are several forms to use it:
.. code-block:: yaml
on_...:
- canbus.send:
data: [ 0x10, 0x20, 0x30 ]
canbus_id: my_mcp2515 # optional if you only have 1 canbus device
can_id: 23 # override the can_id configured in the can bus
on_...:
- canbus.send: [ 0x11, 0x22, 0x33 ]
- canbus.send: 'hello'
# Templated, return type is std::vector<uint8_t>
- canbus.send: !lambda
return {0x00, 0x20, 0x42};
Configuration variables:
- **data** (*Required*, binary data): Data to transmit, up to 8 bytes or
characters are supported by can bus per frame.
- **canbus_id** (*Optional*): Optionally set the can bus id to use for transmitting
the frame. Not needed if you are using only 1 can bus.
- **can_id** (*Optional*, int): Allows to override the can id configured in
the can bus device.
- **use_extended_id** (*Optional*, boolean): default *False* identifies the type of *can_id*:
*False*: Standard 11 Bit IDs, *True*: Extended 29Bit ID
MCP2515
-------
The MCP2515 is a spi device and therfore you must first add the configuration for the spi bus to your file.
You need to have an :ref:`SPI bus <spi>` in your configuration with both the **mosi_pin** and **miso_pin** set.
For wireing up the MSP2515 please refer to the section below.
- **cs_pin** (**Required**, :ref:`Pin Schema <config-pin_schema>`): Is used to tell the receiving SPI device
when it should listen for data on the SPI bus. Each device has an individual ``CS`` line.
Sometimes also called ``SS``.
- **clock** (*Optional*): One of ``8MHZ``, ``16MHZ`` or ``20MHZ``. Clock crystal used on the MCP2515 device.
Defaults to ``8MHZ``.
- **mode** (*Optional*): Operation mode. Default ot ``NORMAL``
- NORMAL: Normal operation
- LOOPBACK: Loopback mode can be used to just test you spi connections to the device
- LISTENONLY: only receive data
.. code-block:: yaml
# Example configuration entry
canbus:
- platform: mcp2515
cs_pin: D5
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] );
- light.turn_off: light_1
- can_id: 501
then:
- light.turn_on:
id: light_1
brightness: !lambda "return (x.size() > 0) ? (float) x[0]/255 : 0;"
Wiring options
---------------
Easiest approach is to just use fully assembled boards and just add one resistor in the MISO line.
This runs MOSI, SCK and CS out of specification which is nearly never a problem.
.. figure:: images/canbus_mcp2515_resistor.png
:align: center
:target: ../_images/canbus_mcp2515_resistor.png
A more advanced option is to fully convert the 5V and 3.3V logic levels with a level shifter.
.. figure:: images/canbus_mcp2515_txs0108e.png
:align: center
:target: ../_images/canbus_mcp2515_txs0108e.png
Extended ID
-----------
Standard IDs and Extended IDs can coexist on the same segment.
.. note::
It is important to know that for example Standard 0x123 and Extended 0x123 are different addesses.
This example shows how the different ID types are used in the configuration for transmission and receiving.
For the IDs decimal or hexadecimal notation is possible:
0x000 - 0x7ff / 0-2047 for Standard IDs only.
0x00000000 - 0x1fffffff / 0-536870911 for Extended IDs.
.. code-block:: yaml
# Transmission of extended and standard ID 0x100 every second
time:
- platform: sntp
on_time:
- seconds: /1
then:
- canbus.send:
# Extended ID explicit
use_extended_id: True
can_id: 0x100
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
- canbus.send:
# Standard ID by default
can_id: 0y100
data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]
canbus:
- platform: mcp2515
id: my_mcp2515
spi_id: McpSpi
cs_pin: GPIO14
can_id: 0x1fff
use_extended_id: True
bit_rate: 125kbps
on_frame:
- can_id: 0x123
use_extended_id: True
then:
- lambda: |-
std::string b(x.begin(), x.end());
ESP_LOGD("can extended id 0x123", "%s", &b[0] );
- can_id: 0x123
then:
- lambda: |-
std::string b(x.begin(), x.end());
ESP_LOGD("can standard id 0x123", "%s", &b[0] );
Binary Sensor Example
---------------------
Example for the following application:
Button is connected on a can node which sends an A message on ID 0x100 with payload 0x01 for contact closed and 0x00 for contact open.
.. code-block:: yaml
spi:
id: McpSpi
clk_pin: GPIO16
mosi_pin: GPIO5
miso_pin: GPIO4
binary_sensor:
- platform: template
name: "CAN Bus Button"
id: "can_bus_button"
canbus:
- platform: mcp2515
id: my_mcp2515
spi_id: McpSpi
cs_pin: GPIO14
can_id: 4
bit_rate: 125kbps
on_frame:
- can_id: ${0x100}
then:
- lambda: |-
if(x.size() > 0) {
switch(x[0]) {
case 0x0: id(can_bus_button).publish_state(false); break; // button release
case 0x1: id(can_bus_button).publish_state(true); break; // button down
}
}
Cover Example
-------------
Example for following application:
Buttons are connected on the CAN-Node and also the motor is connected via CAN.
.. epigraph::
| **Button 1:** ID 0x50B - 1 byte payload
| (0: Button release, 1: Button down, 2: long down, 3: long release, 4 double click)
| **Button 2:** ID 0x50C - 1 byte payload
| (0: Button release, 1: Button down, 2: long down, 3: long release, 4 double click)
| **Motor:** ID 0x51A - 1 byte payload
| (0: off, 1: open, 2: close)
.. code-block:: yaml
spi:
id: McpSpi
clk_pin: GPIO16
mosi_pin: GPIO5
miso_pin: GPIO4
canbus:
- platform: mcp2515
id: my_mcp2515
spi_id: McpSpi
cs_pin: GPIO14
can_id: 4
bit_rate: 125kbps
on_frame:
- can_id: 0x50c
then:
- lambda: |-
if(x.size() > 0) {
auto call = id(TestCover).make_call();
switch(x[0]) {
case 0x2: call.set_command_open(); call.perform(); break; // long pressed
case 0x1: // button down
case 0x3: call.set_command_stop(); call.perform(); break; // long released
case 0x4: call.set_position(1.0); call.perform(); break; // double click
}
}
- can_id: 0x50b
then:
- lambda: |-
if(x.size() > 0) {
auto call = id(TestCover).make_call();
switch(x[0]) {
case 0x2: call.set_command_close(); call.perform(); break; // long pressed
case 0x1: // button down
case 0x3: call.set_command_stop(); call.perform(); break; // long released
case 0x4: call.set_position(0.0); call.perform(); break; // double click
}
}
cover:
- platform: time_based
name: "MyCanbusTestCover"
id: TestCover
device_class: shutter
has_built_in_endstop: true
open_action:
- canbus.send:
data: [ 0x01 ]
canbus_id: my_mcp2515
can_id: 0x51A
open_duration: 2min
close_action:
- canbus.send:
data: [ 0x02 ]
canbus_id: my_mcp2515
can_id: 0x51A
close_duration: 2min
stop_action:
- canbus.send:
data: [ 0x00 ]
canbus_id: my_mcp2515
can_id: 0x51A
See Also
--------
- :apiref:`spi/spi.h`
- :ghedit:`Edit`

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

93
images/canbus.svg Normal file
View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="135mm"
height="60mm"
viewBox="0 0 135 60"
version="1.1"
id="svg100"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="canbus.svg">
<defs
id="defs94" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="377.23571"
inkscape:cy="206.93478"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata97">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Laag 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-237)">
<path
d="m 16.440094,239.55732 100.197636,-0.82276 c 7.87458,-0.0647 14.25779,8.06718 14.25779,18.01748 v 19.94787 c 0,9.9503 -6.38398,17.95186 -14.25779,18.01651 l -100.197636,0.82277 c -7.8745723,0.0647 -14.2585483,-8.0662 -14.2585483,-18.0165 v -19.94792 c 0,-9.95124 6.383809,-18.01745 14.2577863,-18.01745 z"
id="path69"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssssssc"
style="stroke-width:0.85861504" />
<path
d="m 16.440094,239.55732 100.342446,-0.33525 c 7.87473,-0.0255 14.25779,8.06715 14.25779,18.01745 v 19.94792 c 0,9.9503 -6.38383,17.9902 -14.25779,18.01649 l -100.342446,0.33526 c -7.8747113,0.0255 -14.2585483,-8.0662 -14.2585483,-18.0165 v -19.94792 c 0,-9.95124 6.383809,-18.01745 14.2577863,-18.01745 z"
stroke-miterlimit="10"
id="path71"
inkscape:connector-curvature="0"
style="fill:none;stroke:#000000;stroke-width:1.14453387;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10"
sodipodi:nodetypes="cssssssssc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:36.63424301px;line-height:1.25;font-family:'Arial Rounded MT Bold';-inkscape-font-specification:'Arial Rounded MT Bold, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.85861504"
x="19.823954"
y="250.492"
id="text114"
transform="scale(0.8895678,1.1241414)"><tspan
sodipodi:role="line"
id="tspan112"
x="19.823954"
y="250.492"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:36.63424301px;line-height:1.25;font-family:'Arial Rounded MT Bold';-inkscape-font-specification:'Arial Rounded MT Bold, ';fill:#ffffff;stroke-width:0.85861504">CAN</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.48880768px;line-height:1.25;font-family:'Arial Rounded MT Bold';-inkscape-font-specification:'Arial Rounded MT Bold, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.86666292"
x="-352.34537"
y="87.275421"
id="text118"
transform="matrix(0,-0.80144605,1.2477446,0,0,0)"><tspan
sodipodi:role="line"
id="tspan116"
x="-352.34537"
y="87.275421"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.48880768px;font-family:'Arial Rounded MT Bold';-inkscape-font-specification:'Arial Rounded MT Bold, ';fill:#ffffff;stroke-width:0.86666292">BUS</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -77,6 +77,7 @@ Core Components
I²C Bus, components/i2c, i2c.svg
SPI Bus, components/spi, spi.svg
UART Bus, components/uart, uart.svg
CAN Bus, components/canbus, canbus.svg
OTA Updates, components/ota, system-update.svg
Logger, components/logger, file-document-box.svg