PCB design: ESP32 to CAN supporting ESPHome / Matter

I have tried the USB for uploading new firmware on one of the SEEED Xaio C3 modules and it worked fine, it shows up as a JTAG serial port on the box running ESPHome. At the time there were some issues with using the port for viewing the logs with a wired connection.

My view is if the end product does not need to use the USB for power and the USB would only be used for programming then get rid of it. I just put a 4 pin header on the board connected to power and the uart pins and use an external USB-serial converter for programming.

My latest board used an ESP32-C3-01M to save a bit of space, it has a 4 pin header and a switch on GPIO 9 for programming.


prog

I have used a similar flanged case from Ebay that is 130mm x 68mm x 50mm outside with a 93.5mm x 61.5mm inside compartment.

I have a Visio drawing of it if it matches your AliEx ones.

thank you for the drawing. Looking at alibaba, the cases are basically made by one manufacturer and sold in customized versions (like the box for SONOFF switches). Unfortunately, I found several drawings and most of them differ in size :confused:

So I will just wait until I can properly measure the boxes :slight_smile:

About USB. At the first shot, I will try to support both (direct USB programming and USB/UART), selectable by jumpers. For the “end product” in mind, I guess this will be more a “more professional” evaluation kit for ESP32 to general CAN devices. So if someone wants to develop for a new device, it is always good to have a UART directly on board. The additional costs are around 1.5€, if 10 boards are assembled.

Next two weeks are stressful at work / home, so I cannot promise updates, until the boxes arrive

1 Like

Finished placement and routing. Updated the first post with images and updated features

Switched to 2x USB 2.0 Type C (one is directly attached to the ESP, one goes to the CH340C USB → UART IC

I just was about to order the PCB at JLCPCB, but the MCP2515 CAN controller is not in stock any more. Will wait a couple of days. If it is still out of stock, I will hand-solder it (ETA ~ 2-4 weeks for first prototypes)

In the git repo there are schematics as pdf, the BOM as excel and the case drawing with my measurements.

@gaz99 : Apparently our boxes do not match. Here is what I measured - sorry for the bad drawing :slight_smile:

Next ToDo: Read about licensing before pushing the EasyEDA project to github

FYI - rough pricing indication:

For 5 PCBs JLCPCB charges around 100€ including economy shipment to germany.
Excluding:

  • ESP Wroom (~3€/pc, if JLCPCB assembles this, the assembly would be labeled as “standard”, not “economy”, adding additional 23€ to setup costs). Will buy them separately and solder manually for the 5 prototypes
  • CAN controller (out of stock, ~2€),
  • 5.08mm screw terminals (~1€)
  • Relay and 0…10V controller
  • connectors for testing (push- in and the 2x5p 2mm headers)

Hardware prices could drop by down to 23 € / fully assembled PCB if more than 10 pcs are ordered. So if you are interested, write me a PM and I will consider a second, cost optimised version

~Martin

Looks good, only comment from a quick look is that the DC in trace is very small.

Design is now ready for manufacturing. Increased the DC power traces a bit (0.508 mm)

All design files are in the github repo. Will do the open hardware licencing stuff later

  • found & fixed some bugs
    – use ideal diodes instead of simple diodes to prevent voltage drop from 5V below 4.75V (min voltage reg). Simulation files are in the github
    – use 50V capable capacitors instead of 6.3V capable for 10V analog output stuff and its 24V power supply
    – use MCP2515 in a larger SO package (TSSOP was not available any more)

Will order at JLCPCB, soon. Already ordered 5 C3 Wroom modules at mouser :wink:

little update:

  • got all parts
  • JLCPCB order will hopefully arrive next week:)

Looking forward to your success message :). nice project

…TADAAA!

Used to control my ventilation system (second use for the PCB):

I fully assembled three of the PCBs (waiting for a delivery with more 2mm pin headers …)

Made several (minor) mistakes, but nothing some thread wire could not fix :slight_smile:

Findings in a nutshell:

  • I apparently suck at measuring things, but I guess 2 screws are enough to stabilize the PCB.
  • Programming via UART (CH340) and native USB works. (Fun-fact: DOUBLE-crossing UART is not better than NOT crossing them, but that was thread-wire-able…)
  • More minor stuff:
    – Chose inductors for smoothing the power supply with too small current capability (3mA, should be >200mA).
    – Switched Labels for USB Prog and UART
    – connected wrong pin for the relay (fixed by thread wire…)
    – RX Led is on by default, because the CAN bus RX is at logical ‘1’ when no dominant bits are send (–> invert LED)
  • Alive LED should be driven by a transistor and not directly by Pin0

Will do some documentation / cleanup the next weeks. At the moment I am not sure, if I will do the next revision with EasyEDA or better try KiCAD. Compared to my bread-and-butter Altium designer EasyEDA was okay-ish at first while doing the Schematics but a nightmare routing…

I already implemented the second usage of the board (control my ventilation system. ESP32 sketch is here: GitHub - mkaiser/ESPHome_ventilation_system_ctrl: Control ventilation systems (e.g. Tecalor TVZ170 TVZ 370, Wolf CWL-300/400 Excellent)

Back to CAN-Bus:

  • Connection to MCP2515 CAN controller works. Used a CAN-Listener sketch to sniff the Heatpump’s communication.

When trying to compile my code for the ESP32-C3, I get linker errors, because appartently there are issues with gcc vs.IDF data type declaration stuff:

Linking /data/heatpump-c3/.pioenvs/heatpump-c3/firmware.elf
/data/cache/platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/riscv32-esp-elf/8.4.0/../../../../riscv32-esp-elf/bin/ld: /data/heatpump-c3/.pioenvs/heatpump-c3/src/main.cpp.o: in function `esphome::api::ExecuteServiceArgument* std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<esphome::api::ExecuteServiceArgument const*, std::vector<esphome::api::ExecuteServiceArgument, std::allocator<esphome::api::ExecuteServiceArgument> > >, esphome::api::ExecuteServiceArgument*>(__gnu_cxx::__normal_iterator<esphome::api::ExecuteServiceArgument const*, std::vector<esphome::api::ExecuteServiceArgument, std::allocator<esphome::api::ExecuteServiceArgument> > >, __gnu_cxx::__normal_iterator<esphome::api::ExecuteServiceArgument const*, std::vector<esphome::api::ExecuteServiceArgument, std::allocator<esphome::api::ExecuteServiceArgument> > >, esphome::api::ExecuteServiceArgument*)':
/data/cache/platformio/packages/[email protected]+2021r2-patch5/riscv32-esp-elf/include/c++/8.4.0/bits/stl_uninitialized.h:82: undefined reference to `long esphome::api::get_execute_arg_value<long>(esphome::api::ExecuteServiceArgument const&)'

/data/cache/platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/riscv32-esp-elf/8.4.0/../../../../riscv32-esp-elf/bin/ld: /data/heatpump-c3/.pioenvs/heatpump-c3/src/main.cpp.o: in function `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::vector(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)':
/data/cache/platformio/packages/[email protected]+2021r2-patch5/riscv32-esp-elf/include/c++/8.4.0/bits/stl_vector.h:462: undefined reference to `long esphome::api::get_execute_arg_value<long>(esphome::api::ExecuteServiceArgument const&)'

/data/cache/platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/riscv32-esp-elf/8.4.0/../../../../riscv32-esp-elf/bin/ld: /data/heatpump-c3/.pioenvs/heatpump-c3/src/main.cpp.o: in function `void esphome::api::UserServiceBase<long, long, long>::execute_<0, 1, 2>(std::vector<esphome::api::ExecuteServiceArgument, std::allocator<esphome::api::ExecuteServiceArgument> >, esphome::seq<0, 1, 2>)':
/config/esphome/.esphome/build/heatpump-c3/src/esphome/components/api/user_services.h:57: undefined reference to `long esphome::api::get_execute_arg_value<long>(esphome::api::ExecuteServiceArgument const&)'

/data/cache/platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/riscv32-esp-elf/8.4.0/../../../../riscv32-esp-elf/bin/ld: /data/heatpump-c3/.pioenvs/heatpump-c3/src/main.cpp.o: in function `esphome::api::ListEntitiesServicesArgument::ListEntitiesServicesArgument()':
/config/esphome/.esphome/build/heatpump-c3/src/esphome/components/api/api_pb2.h:836: undefined reference to `esphome::api::enums::ServiceArgType esphome::api::to_service_arg_type<long>()'

/data/cache/platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/riscv32-esp-elf/8.4.0/../../../../riscv32-esp-elf/bin/ld: /data/heatpump-c3/.pioenvs/heatpump-c3/src/main.cpp.o: in function `esphome::api::UserServiceBase<long, long, long>::encode_list_service_response()':
/config/esphome/.esphome/build/heatpump-c3/src/esphome/components/api/user_services.h:35: undefined reference to `esphome::api::enums::ServiceArgType esphome::api::to_service_arg_type<long>()'


/data/cache/platformio/packages/[email protected]+2021r2-patch5/bin/../lib/gcc/riscv32-esp-elf/8.4.0/../../../../riscv32-esp-elf/bin/ld: /config/esphome/.esphome/build/heatpump-c3/src/esphome/components/api/user_services.h:35: undefined reference to `esphome::api::enums::ServiceArgType esphome::api::to_service_arg_type<long>()'
collect2: error: ld returned 1 exit status
*** [/data/heatpump-c3/.pioenvs/heatpump-c3/firmware.elf] Error 1
========================= [FAILED] Took 211.38 seconds =========================

It looks like the issues described here, but I did not have time to investigate / test more.

Any help would be much appreciated and I could focus more on the fun-hardware-stuff :slight_smile:

My test yaml is here: ESPHome config for CAN at ESP32 C3 . Results in linker errors :/ · GitHub
Just copy / paste the yaml and compile it. The error should be the one shown above

~Martin

2 Likes

Hey there,

Mostly finished the PCB bringup and documentation before going on vacation.

See here for the schematic errata: GitHub - mkaiser/ESP32-CAN: PCB with ESP32 and CAN bus. For controlling CAN-devices like heatpumps via ESPHome

Altough the first revision runs great after minor PCB fixes, I will make a new revision in a couple of month.

For this I want to use the new ESP32 C6 Mini, which is getting “more available” now

I am also considering the MCP251863 CAN FD Controller with included transceivers. Selecting the CAN mode (internal ESP32 or MCP2518) is still possible by Jumper. But I am a bit afraid of the ESPHome Software support, that will be required. But taken into the consideration that the well-known and widely-used MCP2515 chip is at EOL, this will be the future proof solution.

Could someone help me with the MCP2518?

Any more suggestions / ideas?

Also I did not have any time to fix the linker issues described in my last posts…

2 Likes

little update:
got it compiling and working with this workaround: api services remote_transmitter compile error esp32c3 #2 · Issue #3564 · esphome/issues · GitHub

Could not test the internal CAN controller, yet, because the ESPHomes ESP32_CAN component does not support the 20kbit/s, which is required by the heatpump:

It is a an internal ESP issue, as the ESP32-C3 actually supports this speed (the old ESP32 do not).

See Two-Wire Automotive Interface (TWAI) - ESP32-C3 - — ESP-IDF Programming Guide latest documentation

(search for " TWAI_TIMING_CONFIG_20KBITS"

1 Like

code using INTERNAL CAN controller is compiling now.

(we need 20 Kbit/s for the heatpump, which is supported, yet)

Will test soon and hopefully go upstream fast

2 Likes

internal CAN is working now :slight_smile:

when the ESPHome component changes (ESP CAN) are accepted upstream (takes me 1-2weeks I guess), the external CAN controller can be completely omitted

One issue came up today: When the CAN PCB is powered via 16-18V heatpump CAN Bus and the heatpumps power is switched on, the CAN Bus power supplied by the heatpump dropps and causes the heatpump to reboot.

That never happens, if the CAN PCB is powered via USB or the external FEK sensor is attached. So I guess Tecalor /Stiebel used a highly cost-optimized power supply, which cannot take on additional 200mW (est. max @ boot for the CAN PCB)

1 Like

So external Power Supply will be needed? Correct me if I’m wrong, but the CAN bus is not designed to supply devices with power, so such problems are to be expected. How is an external control panel connected to the heat pump? Is there not still somewhere a power source to tap?

The CAN bus itself does not specify a power supply. CAN Bus is just about the two wires with differential data lines.

The heatpump provides the 16-18V power supply for the WPMi (that control display on the pump device itself) and additonaly for the external control panel “FEK”.

I am investigating more… If I connect the power of my CAN device at run-time (not recommended! :wink: ) it works. If I make a cold reboot of the heatpump by triggering the RCD, it does not work.

Maybe it just needs some slow-start stuff (activate the WLAN after 3min in case of a cold boot or sth. like this)

Yes maybe just too much peak current at startup. Too bad I can’t support more.

@ mkai What a coincidence, I wrote under another post, virtually exactly the same idea and am also working on my own board, but specifically tailored to the problem Stiebel and FEK.

The software / proof of concept WPM3 and FEK run error-free for a week although I change the data on the bus. The problem with the power supply I had with the WPM13 also. More than the FEK and it breaks down immediately. Therefore the idea was POE, external 12-48 volts or 230V to use. To use directly the supply voltage of the controller would be best, because thus everything runs through a fuse and starts at the same time.

It seems that quite a few people are actually addressing the problem. Perhaps one should bundle the resources or connect the posts. My background would be a master in computer science, so the programming work would not be a problem. With the PCB design I am not so experienced.

Post: Configured my ESPHome with MCP2515 CAN-Bus for Stiebel Eltron heating pump - #158 by Robot007

Thank you very much for the pointer,

The code from robot007 looks very good - will do some testing the next days.

Without the FEK it the power supply by the heatpump itself works very well. If your Man-in-the-middle attack works (Configured my ESPHome with MCP2515 CAN-Bus for Stiebel Eltron heating pump - #158 by Robot007), the FEK has no benefits any more and the power supply from the heatpump would be enough.

Why do you suggest POE? I currently run the PCB with 5V and it is very stable :slight_smile:

I had many thoughts on implementing POE stuff on PCBs, but altough there are many open source arduino PCB examples, the effort to get all the parts assembled from a PCB manufacturer like Jlcpcb was to high. Pricing more than 200€ / 5 Pcbs.

Btw. I created a discord channel for this project, maybe a good place to directly exchange ideas on PCB design

Hi mkai,

I stumbled accross your PCB because I search one for my project.
I will install a modern car multimedia head unit in an old camper which has only legacy 12V signaling. I wrote an ESP application which will control the head unit via CAN.

I need at leat four 12V capable GPIO inputs to have no extra wiring. They should be protected with for example TVS diodes to avoid damage through voltage spikes during cranking.

Is it possible to include these in your new PCB design?

More information about my project here: Crash_Override/Easylink_CAN_Waker: Wake up a Easylink (A-IVI) car multimedia system by CAN for using it on a table. - GIT Repository Bit-Cloud

Cheers