1. Topic

Choosing an input frontend: optocoupler -> GPIO, optocoupler -> GPIO expander, optocoupler -> ADS1115, or optocoupler -> comparator/Schmitt trigger -> GPIO. Main idea: ADS1115 measures, a GPIO expander adds inputs, and a comparator/Schmitt trigger cleans up the signal.

2. Why this matters in a project

For traffic-light phases, the goal is not an attractive analog reading but a reliable fact: whether RED/YELLOW/GREEN is present, and whether there is a conflict, a broken connection, noise or a degraded input. The input may involve 220 V AC, 24 V DC, 12 V DC, a long cable, a noisy edge or a slow optocoupler.

3. Theory

Before choosing an IC, decide what you need: a fast 0/1 decision, analog diagnostics, an accurate timestamp, many channels, AC detection from pulses, or monitoring of an uncertain intermediate level.

  • Direct GPIO works well when the signal is already clean and there are few channels.
  • An MCP23017/TCA9555 GPIO expander works well for many already-clean discrete inputs. It does not filter a noisy signal.
  • ADS1115 is useful for slow diagnostics: min/max/avg, the voltage after an optocoupler, supply voltage, currents and confidence in HIGH/LOW. Its 860 SPS rate and multiplexed channels make it a weak choice for fast phase timestamps.
  • A comparator/Schmitt trigger is needed when the level after the optocoupler is slow, noisy or pulsating.

A useful architecture:

text
fast path:
  optocoupler -> pull-up/RC -> Schmitt/comparator -> GPIO/expander -> input_filter -> phase_detector
slow diagnostics:
  analog node -> ADS1115 -> analog_diag_task -> CLI/log/MQTT

4. Common mistakes

  1. Using ADS1115 as the primary fast phase detector.
  2. Expecting a GPIO expander to clean up a noisy signal.
  3. Putting ADS1115 and an expander on I2C without a single bus owner and a timeout.
  4. Ignoring the expander INT pin when the signal is already clean.
  5. Omitting i2c_nack, i2c_timeout and bus_reset counters.
  6. Making phase_event wait for a slow ADC.

5. Practical task

Create INPUT_FRONTEND_DECISION.md with these rules:

markdown
# Input frontend decision
Fast path:
opto -> pull-up/filter -> Schmitt/comparator -> MCU GPIO
Alternative for many channels:
opto -> pull-up/filter -> Schmitt/comparator -> GPIO expander -> I2C -> MCU
Slow diagnostics:
analog node -> ADS1115 -> min/max/avg -> CLI/telemetry
Rules:
1. Dirty analog signals must be cleaned before digital expanders.
2. Fast phase timestamp must not depend on slow ADC scan.
3. I2C errors must be visible in diagnostics.

6. Further reading and experiments

ESP-IDF I2C master driver, TI ADS1115 datasheet, MCP23017/TCA9555 datasheets, and the principles of Schmitt triggers, comparators and open-collector outputs.

You need fast edges from a conditioned signal and separate analog-level measurements. How should you split the paths?

Exercise

In an idealized model, ADS1115 runs at 860 SPS. How long is one conversion, and what is the maximum full-scan rate for 4 channels if I2C and switching time are ignored? Why does this not guarantee a fast edge timestamp?

Self-check criteria: Give units, both calculations and at least one additional source of delay.

Show the supplied answer

1/860 s ≈ 1.163 ms; 860/4 = 215 scans/s, about 4.651 ms per scan. Real transfers, switching and servicing add delay; an ADC measurement is not hardware edge capture.