Palakis / esphome-native-hdmi-cec

HDMI-CEC implementation for ESPHome
Other
40 stars 11 forks source link

Not working on Seeed Xiao ESP32-C3 #7

Closed segfly closed 3 months ago

segfly commented 3 months ago

Very nice library, I'm glad someone refined the work from existing authors.

However, it's not working for me on seeed_xiao_esp32c3. It reports successfully transmitting frames in the logs, but on my logic analyzer I don't see the pin state change at all. I had the same issue with johnboiles library, and for the longest time, I thought the code just didn't work.

After discovering your library, and seeing that it still did not work for me, I decided to try it on a Waveshare ESP32-S3-Zero with esp32-s3-devkitc-1 and it works fine.

So I am a bit perplexed what is going on, I've double and triple checked my physical connections, verified the pins work by testing other output components the same pin, tried all the pins available on the board, and still no output.

My config is very simple to test:

esphome:
  name: basic

esp32:
  board: seeed_xiao_esp32c3
  framework:
    type: arduino
  # board: esp32-s3-devkitc-1 # Works for Waveshare ESP32-S3-Zero
  # framework:
  #   type: arduino

logger:

binary_sensor:
  - platform: gpio
    name: "CEC Send"
    pin:
      number: GPIO9 # Xiao onboard button    
      # number: GPIO0 # Waveshare ESP32-S3-Zero onboard button
      inverted: true
      mode: INPUT_PULLUP
    on_press:
      hdmi_cec.send:
        destination: 0xF # Broadcast
        data: [0x36] # "Standby" opcode                

external_components:
  - source: github://Palakis/esphome-hdmi-cec

hdmi_cec:
  pin: GPIO4
  address: 0x4
  physical_address: 0x1000

Everything seems to be fine in the logs:

[D][binary_sensor:036]: 'CEC Send': Sending state ON
[D][hdmi_cec:204]: sending frame: 4F:36
[D][hdmi_cec:218]: HDMICEC::send(): frame sent and acknowledged
[W][component:237]: Component gpio.binary_sensor took a long time for an operation (53 ms).
[W][component:238]: Components should block for at most 30 ms.
[D][binary_sensor:036]: 'CEC Send': Sending state OFF

But only my S3 will actually output data, the C3 just sits there and pretends to have done something with the line staying high.

In fact, if I put an external pulldown resistor, it actually does something, just junk on when the CEC send is invoked, but it actually does something. So I'm thinking there must be something off with the way the pin is being configured. I tried manually setting some of the pin configuration, like INPUT_OUTPUT_OPEN_DRAIN, etc. but it has no effect - except 'inverted' which results in the error "[E][hdmi_cec:232]: HDMICEC::send(): send failed after five attempts"

Thanks in advance for any pointers as to what may be going on.

segfly commented 3 months ago

After much debugging and testing, I compared the HDMICEC::setup() to other components that did work for output on the C3. The main difference I found was the lack of pin_->setup(). Once I added this to HDMICEC::setup() method I could transmit frames on the C3.

I went back and tested this on my S3 as well, and it had no adverse effects. I don't have an RP2040 handy to test, but I doubt it would have an issue given all the other pin configuration by HDMICEC still occurs later for input/output mode.

As a side note, I went back and noticed that johnboiles library was also missing the pin_->setup(), which is probably why that library never worked for me on my C3 either.

segfly commented 3 months ago

Upon further testing (I missed a test case) the fix only resolves sending frames, not receiving frames. On the C3, it resets due to TG1WDT_SYS_RST after attempting to receive a frame in the ISR.

segfly commented 3 months ago

I ended up finding a workaround to the TG1WDT_SYS_RST issue I was getting on the on the C3:

esphome:
  name: basic
  platformio_options:
      board_build.flash_mode: dio

esp32:
  board: seeed_xiao_esp32c3
  framework:
    type: esp-idf

I ended up trying this combination because I noticed the ESP32 task watchdog is not enabled when using the esp-idf framework.

Along with the patch in PR #8, CEC receiving and sending frames now works as expected on the C3.

This is not ideal though, I actually wanted to use the Arduino framework for some library compatibility. I'm unsure why the TWDT is behaving so differently on the C3 than the S3. Perhaps moving the code in the ISR to the event loop would fix the issue. I might try that later, but it seems like that shouldn't be necessary.

Any pointers on a better fix for the TG1WDT_SYS_RST is appreciated.

ntzb commented 3 months ago

@segfly hi, thanks for the testing and info you provided. I want to use the C3 or S3 for this project, and noticed most boards have USB power input and both 5V and 3.3V outputs, which is great, because 3.3V is needed for the logic, and 5V is needed for pin 18, but I had concerns about it. is the 5V on these boards (C3 or S3) regulated? or does it come straight from the USB?

segfly commented 3 months ago

@ntzb Your question is off topic for these two issues. I recommend opening your own issue and @ mentioning people in comments there if you would like their input. I'll answer anyway this time... 🙂

ESP chips are 3.3V only, so any board that connects to USB will have to have an onboard regulator to bring the USB/VIN 5V down to 3.3V. 5V is not sent directly to the MCU in any a way. If 5V is needed for signaling, a level-shifter will be required.

Also note, that these boards typically only have a LDO regulator and will not boost the voltage from 3.3V up to 5V, so you can't connect 3.3V and expect 5V out.

But when in doubt, I recommend to always check the schematics.

The SEEED Xiao ESP32C3 has a robust circuit, that is fused from USB 5V, has reverse current protection diode for USB, and a LDO regulator. This can be seen in grid A1-A3: https://files.seeedstudio.com/wiki/XIAO_WiFi/Resources/Seeeduino-XIAO-ESP32C3-SCH.pdf

image

The Waveshare ESP32-S3-Zero (Which I like better for certain use-cases due to the onboard antenna and PSRAM), also has a LDO regulator, but it lacks the fuse and reverse current protection for the USB port. Not a problem if extra care is taken when plugging things into it. This can be seen in grid B4: https://files.waveshare.com/wiki/ESP32-S3-Zero/ESP32-S3-Zero-Sch.pdf

image

While the HDMI CEC can be safely wired directly to 3.3V IO pins, for extra protection you can add a logic-level mosfet, and if desired a quality fixed-voltage 3.3V LDO regulator (if you don't trust the onboard regulator).

According to STM32's documents (I know you are asking about ESPs, but the CEC signaling is the same), they recommend to use the mosfet with an external pull-up as it prevents an unpowered MCU from interfering with CEC line. As can be seen in Figure 329:

https://www.st.com/resource/en/reference_manual/rm0091-stm32f0x1stm32f0x2stm32f0x8-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

image

Be aware, that the 5V line from the HDMI pin may not source enough current to power your MCU. This will depend on the type of device connected. You may need to power your MCU externally if that is the case (it was in mine).

Hope that helps. Cheers.

ntzb commented 3 months ago

thanks @segfly. allow me to briefly respond (maybe I was misunderstood). my ultimate goal is having as small footprint as possible, for this project. for this reason, I chose the small ESPs that can fit into an HDMI breakout board case. there's no issue with sourcing 3.3V for the logic (I trust the the onboard regulator), the issue that I speak of, is providing 5V to pin 18, safely (under the footprint condition). following a bit real offtopic: at first I thought to implement this using esp01 with 2x ams1117 regulators, but since the esp-c3 boards are tiny, have 3.3V logic AND a 5V pin, they are perfect candidates for this project. now according to the seeed esp32 c3 documentation, the 5V pin has 5V from the USB, and according to the schematics you provided, it's NOT regulated (simply fused, which is current/power metered, rather than voltage metered). this means that if this 5V is connected to HDMI pin 18, and for whatever reason, the USB voltage is higher than 5V, damage will be done in the other end of the HDMI cable.

so to me, this means that to be safe, I should regulate the 5V (with or without the C3).

sorry for these offtopic posts (although in the small github hardware projects world, one might claim there's no such thing 😋)

segfly commented 3 months ago

@ntzb Okay, I see now. You want to drive the HDMI 5V from the USB 5V. That wasn't clear to me at first as this library is focused on the CEC signal.

I don't know your full project goals, but note that you don't need to tie the USB 5V to the HDMI 5V if you are only snooping/injecting CEC traffic between 2 devices. Just leave their 5V lines connected to each other.

But if you are doing point-to-point, then I see why you may need to drive the 5V, which as I understand it, is only needed if your device is the HDMI sink. If your device is an HDMI source, you shouldn't need to put 5V on that line.

So, assuming your device is an HDMI sink in a point-to-point configuration...

The ams1117 you mentioned has 1.2V dropout, so you are only going to get 3.8V (at best) from a 5V input anyway, and less than 3.8V if the 5V input sags for any reason. There are other LDO regulators with better characteristics, but it appears the minimum spec for the HDMI 5V line is 4.75V. This gets into the need for something like a buck-boost design, which is adding unnecessary complexity.

Because personally, I wouldn't go to the trouble of building regulating circuitry on top of the USB 5V supply - it's already regulated (obviously, to 5V per USB spec). If you don't trust your 5V USB power source, I'd just swap to a better source as it's easier.

If you have a quality USB 5v source, but really want extra over-voltage protection, there are simpler circuits. Using a zener diode with a breakdown voltage a bit more than 5V can be used to shutoff the 5V input. Someone already shared a nice design for this over on stackexchange: https://electronics.stackexchange.com/a/355483

image

Still, I think it's unnecessary if you have a high-quality USB 5V source. But for you, maybe it is worth the peace of mind.

ntzb commented 3 months ago

well my original questions was already answered in your first reply (C3 schematics), and now it does get pretty offtopic, but it's always nice to share ideas, so thanks.

I didn't want to place this project between two already speaking CEC devices, as I find CEC not a robust protocol, and if it works, I prefer not to touch it. I do want to get information coming from the protocol, and to send some commands, and my thought was to put a HDMI/CEC sink as you called it. it will be connected to one of the TV or AVR ports (and be powered by USB). since I already had my AVR HDMI board burnt a few years back, because of the shitty TV cable provider HDMI equipment, I do want to protect my equipment as much as possible. while I do only use USB sources I trust, sometimes family members can move that around unknowingly, or even I might forget one day, that this specific device should not be connected to "fast" USB charging ports (although these are getting really popular in recent years).

I absolutely didn't take into account the dropout of the ams1117, so that's out of the question. the suggested stackexchange solution is very cool, but I'd have to source the components, and the end result will probably be too big. maybe I'll just go with the C3's 5V pin... TBD

segfly commented 3 months ago

@ntzb One last word of caution as I don't want you to risk damage to your devices:

it will be connected to one of the TV or AVR ports (and be powered by USB).

Assuming these are HDMI input ports, this means your device is acting as an HDMI source. In such case, the HDMI sink supplies the 5V. You don't need (nor should) tie the USB 5V to the HDMI 5V. Just leave pin 18 on the HDMI disconnected.

But depending on how your TV/AVR behave, you may need the hot-plug line active which needs a pullup to 3.3V. You can just drive this from one of the MCU pins set to PULLUP mode.

I didn't want to place this project between two already speaking CEC devices, as I find CEC not a robust protocol, and if it works, I prefer not to touch it.

FYI, the CEC wire protocol is designed to be a shared bus. If you have unreliable CEC communications between devices, it's more likely the device manufacturer's poor firmware. They often have bugs or proprietary implementations in the CEC data frames. This is no fault of the the electrical connection/specification.

this specific device should not be connected to "fast" USB charging ports

This shouldn't be an issue as long as those fast USB charging ports are following spec (e.g. QC 2.0). They should never output a higher voltage without a proper handshake.

ntzb commented 3 months ago

Assuming these are HDMI input ports, this means your device is acting as an HDMI source. In such case, the HDMI sink supplies the 5V. You don't need (nor should) tie the USB 5V to the HDMI 5V. Just leave pin 18 on the HDMI disconnected.

I think it's the other way around, no?

4.2.7 +5V Power Signal The HDMI connector provides a pin allowing the Source to supply +5.0 Volts to the cable and Sink. All HDMI Sources shall assert the +5V Power signal whenever the Source is using the DDC or TMDS signals. The voltage driven by the Source shall be within the limits specified for TP1 voltage in Table 4-22. An HDMI Source shall have +5V Power signal over-current protection of no more than 0.5A. All HDMI Sources shall be able to supply a minimum of 55 mA to the +5V Power pin. A Sink shall not draw more than 50 mA of current from the +5V Power pin. When the Sink is powered on, it can draw no more than 10mA of current from the +5V Power signal. A Sink shall assume that any voltage within the range specified for TP2 voltage in Table 4-22 indicates that a Source is connected and applying power to the +5V Power signal. A Cable Assembly shall be able to supply a minimum of 50mA to the +5V Power pin to a Sink, even when connected to a Source supplying no more than 55mA. The return for the +5V Power signal is DDC/CEC Ground signal.

from https://engineering.purdue.edu/ece477/Archive/2012/Spring/S12-Grp10/Datasheets/CEC_HDMI_Specification.pdf

also

In order to ensure a robust HDMI power design, the power rail needs to be regulated in the event of a transient condition. The HDMI 2.1 spec provides full detail of the 5 V regulation requirements. In summary: The basic requirements for an HDMI source are: • Output voltage: 4.8 Vmin, 5.3 Vmax • Short Circuit Current: no more than 0.5 A • Shorting two HDMI Sources together shall not result in any damage A sink shall: • Not draw more than 55 mA from the power signal when powered on • Assume any voltage within 4.7 V and 5.3 V indicates a source is connected.

from https://www.ti.com/lit/an/snva412c/snva412c.pdf?ts=1716829897563 (it also talks extensively on protection of the 5V HDMI power in various cases, reiterating my concerns)

segfly commented 3 months ago

@ntzb I was finding conflicting information online when I responded earlier and didn't save the links. Ultimately, it seemed logical to me that the sink (like a TV) would supply the 5V to a device on the HDMI input so that a really small and efficient display source could just just plug into the port and not need any external power source.

Plus, optical HDMI cables need the 5V in order to power the fiber optic receiver electronics - but now that I think of it, such cables would need 5V at both ends to power the electronics.

The HDMI spec is hard to disagree with, so I am probably wrong in my assumption that the only the sink needs to provide the 5V.

If I were you, I'd break out my multi-meter at this point and probe the 5V line coming from the TV/AVR to verify what is going on. But more importantly, I'd just try sending CEC signals without connecting the 5V line to the MCU/USB 5V (but don't forget the HPD 3.3V line). It may just work with your sink devices and you can skip all the 5V complexity.