hencou / esphome_components

Collection of own ESPhome components
25 stars 15 forks source link

Use alternate SPI Bus on ESP32 for NRF24 #15

Closed shbatm closed 1 year ago

shbatm commented 1 year ago

I'm trying to get this working on a new bridge prototype using a WT32-ETH01 board which is an ESP32 board with Ethernet. My problem is I need to get the NRF24 module to use alternate pins and an alternate SPI bus (hspi bus), as the normal VSPI default is not available due to the ethernet module and exposed pinout.

The NRF24 module allows the use of an alternate SPI bus, but I'm having trouble translating the C++ code to figure out where I would add the changes. Also, ESPHome allows the definition of an SPI bus, and I was wondering how hard it would be to configure the mi component to use an SPI bus defined elsewhere in ESPHome.

NRF24 Module Alternate SPI Bus (near bottom of page): https://nrf24.github.io/RF24/md_docs_arduino.html Overloaded Radio->begin method: https://nrf24.github.io/RF24/classRF24.html#a388fa99b0400ce0cd887f742ef53192b ESPHome Custom SPI Component: https://esphome.io/custom/spi.html ESPHome SPI Bus: https://esphome.io/components/spi.html

Desired Pinout:

#define MY_CE 2
#define MY_MISO 15
#define MY_MOSI 14
#define MY_SCLK 12
#define MY_SS   4

Any help would be greatly appreciated.

hencou commented 1 year ago

Hi Shbatm,

You need to change the call in https://github.com/hencou/esphome-milight/blob/main/src/lib/Radio/PL1167_nRF24.cpp on line 24 to "_radio.begin(SPIbus);". SPIbus is here your custom SPI bus variable. You create this variable at root level in https://github.com/hencou/esphome_components/blob/main/components/mi/mi.cpp and then include it in all child function calls up to that PL1167_nRF24 module.

I wouldn't mix it with the ESPhome SPI component.

shbatm commented 1 year ago

Thanks for the guidance. C++ pointers and references make my head spin...

I wasn't able to figure out how to back it all the way up to be able to define the pins in the settings/config, but this implementation is working:

https://github.com/shbatm/esphome-milight/blob/alternate_spi/src/lib/Radio/PL1167_nRF24.cpp

Comparison: https://github.com/hencou/esphome-milight/compare/main...shbatm:esphome-milight:alternate_spi?expand=1

Makes for a nice, compact ethernet bridge:

image

VladNord commented 1 year ago

Hi Shbatm,

You need to change the call in https://github.com/hencou/esphome-milight/blob/main/src/lib/Radio/PL1167_nRF24.cpp on line 24 to "_radio.begin(SPIbus);". SPIbus is here your custom SPI bus variable. You create this variable at root level in https://github.com/hencou/esphome_components/blob/main/components/mi/mi.cpp and then include it in all child function calls up to that PL1167_nRF24 module.

I wouldn't mix it with the ESPhome SPI component.

Nice Project, thanks! Is it possible to make feature for selection needed pins from yaml during ESPHome compilation(like CE and CSN) pins?

Thanks for the guidance. C++ pointers and references make my head spin...

I wasn't able to figure out how to back it all the way up to be able to define the pins in the settings/config, but this implementation is working:

https://github.com/shbatm/esphome-milight/blob/alternate_spi/src/lib/Radio/PL1167_nRF24.cpp

Comparison: https://github.com/hencou/esphome-milight/compare/main...shbatm:esphome-milight:alternate_spi?expand=1

Makes for a nice, compact ethernet bridge:

Can you please share your yaml after modifying?

shbatm commented 1 year ago

Nothing atypical from the example config right now until the settings are extended, other than configuring ethernet for my board (which is copied from the ESPHome website for my device). The second SPI is set by setting the pins in the #define statements highlighted int the compare link above.


substitutions:
  displayname: "MiLight Bridge Front"
  unique_id: "milight-bridge-front"

packages:
  device_base: !include common/device_config.yaml #api, ota, etc... 
  ethernet: !include common/ethernet.yaml

esp32:
  board: esp32doit-devkit-v1
  framework:
    type: arduino
    version: recommended

esphome:
  libraries:
    - milight=https://github.com/shbatm/esphome-milight#f3b1403

external_components:
  - source: github://hencou/esphome_components@main
    components: [mi]

mi:
  ce_pin: 2 #required, default: 4
  csn_pin: 4 #required, default: 15
  radio_interface_type: nrf24 #optional, default: nrf24, possible values: nrf24,lt8900
  packet_repeats: 50 #optional, default: 50
  listen_repeats: 20 #optional, default: 20
  state_flush_interval: 5000 #optional, default: 10000
  packet_repeat_throttle_threshold: 200 #optional, default: 200
  packet_repeat_throttle_sensitivity: 0 #optional, default: 0
  packet_repeat_minimum: 3 #optional, default: 3
  enable_automatic_mode_switching: false #optional, default: false
  rf24_power_level: MAX #optional, default: MAX, possible values: MIN, LOW, HIGH, MAX
  rf24_listen_channel: LOW #optional, default: LOW, possible values: LOW, MID, HIGH
  packet_repeats_per_loop: 10 #optional, default: 10
  rf24_channels: #optional, 1-3 values required when used, default: LOW-MID-HIGH, possible values: LOW, MID, HIGH
    - LOW
    - MID
    - HIGH
  on_command_received: #optional, useful to send remote commands to HA and process them further there in automations
    - homeassistant.event:
        event: esphome.mi_command_received
        data:
          device_id: !lambda "return format_hex(data.device_id);"
          group_id: !lambda "return data.group_id;"
          remote_type: !lambda "return data.remote_type.c_str();"
          command: !lambda "return data.command.c_str();"

light:
  # Just one of many
  - platform: mi
    default_transition_length: 0s
    name: "Front Landscaping All"
    remote_type: "rgb_cct"
    device_id: 0x511
    group_id: 1
hencou commented 1 year ago

Maybe we can introduce an extra yaml variable, something like "use_esp32_alternate_bus" because its only possible on an ESP32. When set that variable, we can set an platformio environment variable so that extra code for esp32 will only be compiled then.

hencou commented 1 year ago

I expect that something like this will work: Additional lines in yaml: image

And then in the modified PL1167_nRF24.cpp: image

VladNord commented 1 year ago

Nothing atypical from the example config right now until the settings are extended, other than configuring ethernet for my board (which is copied from the ESPHome website for my device). The second SPI is set by setting the pins in the #define statements highlighted int the compare link above.

Thank you!

I expect that something like this will work: Additional lines in yaml: image

And then in the modified PL1167_nRF24.cpp: image

PINs must be defined in PL1167_nRF24.cpp as before?

hencou commented 1 year ago

I have no ESP32 to test with, but it seems when using "_spiBus->begin();" the default pins for the (alternate) HSPI bus are already assigned. So it seems not needed to define the pins by "_spiBus->begin(SCK, MISO, MOSI, SS);"

VladNord commented 1 year ago

I have no ESP32 to test with, but it seems when using "_spiBus->begin();" the default pins for the (alternate) HSPI bus are already assigned. So it seems not needed to define the pins by "_spiBus->begin(SCK, MISO, MOSI, SS);"

Even if my SPI Pins are?

define MY_MISO 17

define MY_MOSI 18

define MY_SCLK 16

define MY_SS 5

Tried updated- not working. ESP reboots when send command from HA.

Sorry for noob questions.

shbatm commented 1 year ago

It hadn't even crossed my mind to use build flags. I'll update my code to allow the alternate default and custom pins to be sent in the build flags as well, similar to the Soft SPI option in NRF24:

https://nrf24.github.io/RF24/md_docs_arduino.html

https://github.com/espressif/arduino-esp32/blob/master/libraries/SPI/examples/SPI_Multiple_Buses/SPI_Multiple_Buses.ino

#define ALT_SPI_MISO_PIN 16
#define ALT_SPI_MOSI_PIN 15
#define ALT_SPI_SCK_PIN 14

I'll update later today when I get a chance

shbatm commented 1 year ago

@VladNord sorry it took so long to get back to this. I've updated my code to allow setting alternate pins on the HSPI bus (see the two PRs referenced above).

I've confirmed it's working on two Wireless Tag WT32-ETH01 devices.

You can test yourself with this:

esphome:
  libraries:
    - milight=https://github.com/shbatm/esphome-milight#2e28672
  platformio_options:
    build_flags:
      - "-D USE_ESP32_ALTERNATE_SPI"
      - "-D ALT_SPI_MISO_PIN=15"
      - "-D ALT_SPI_MOSI_PIN=14"
      - "-D ALT_SPI_SCLK_PIN=12"
      - "-D ALT_SPI_SS_PIN=4"

external_components:
  - source: github://hencou/esphome_components@main
    components: [mi]