## Analog to Digital Converters ![breadboard](breadboard.png) This project lets you control a couple of LEDs with a potentiometer and a capacitive touch sensor, while reading out the values of the Analog to Digital Converter (ADC) from the potentiometer. The breadboard diagram there is cursed. I diagrammed it exactly as I wired it. It looked a LOT less ugly in reality. ## Lessons Learned - How potentiometers actually work (surprise: it's more complicated than I thought, as usual) - How an ADC works - How the ESP32-S3 ADC in particular works - How to build a Flash ADC on a breadboard - How integrated circuits measure capacitance ## Measuring potentiometers I've had some prior experience working with potentiometers in electric guitars, but never really did much beyond wiring them and comparing the way they colored the tone of the guitar. I knew that they are essentially adjustable resistors, but beyond that, I never really did much with them. ``` GND LOAD SUPPLY 1 2 3 | | | ``` The project connects a potentiometer's pin 3 to the 3.3V power rail and the wiper (pin 2) to the ADC input pin (pin 1) of the ESP32-S3. It reads the computed value of the Analog to Digital Converter from that pin. Reading those values out and printing them on the serial UART was really easy, but I wanted to verify the numbers. The voltage measurement should be easy to check with a voltmeter. I assumed that I could check across pins 1 and 3 and, as I adjust the potentiometer, I would see the output voltage on the GND side adjust. Wrong! The voltage across pins 3 and 1 stays constant as the brush moves along the potentiometer's range. The difference can only be measured across the load and supply pins (1 and 2). This is because the wiper physically moves between the points 1 and 2 which is how the resistance changes, so there will only be a visible difference between the wiper and ground. That didn't make sense with my previous understanding of potentiometers as "adjustable resistors", because that understanding was incomplete. Potentiometers are adjustable resistors (just like a rheostat), but with 3 pins, they're acting as two resistors in series like a voltage divider. Inside a potentiometer, there's a resistive element that stretches all the way from pin 3 to pin 1. Think of it like a resistor that's been stretched out. The wiper, attached to pin 2, is less like a resistor adjuster, and more like a probe that contacts the resistive material at various points along its length. The further away from 3 and closer to 1 we get, the higher that resistance value gets. The wiper itself isn't actually introducing significant resistance, and is not therefore significantly changing the potential difference between 1 and 3. It's just putting in a tap at the point where the wiper contacts the resistive track. Now if you connect the load pin to something that is ACTUALLY drawing a load, rather than something like an ADC that really isn't drawing much at all, then current will be pulled from the wiper contact point and the voltage observed at the wiper pin will sag. This isn't really a necessary detail for this project, but it's something to keep in mind for future projects where we might put something like a motor on a potentiometer. ## How an ADC works The ESP32 GPIO pins understand `HIGH` and `LOW`. So if we want to say "How wide has the user opened that potentiometer over there?", the GPIO pins can only tell us "fully open" or "fully closed" (keeping in mind that the specific voltage that the GPIO pin understands as `HIGH` and `LOW` may or may not directly correspond to the fully open and fully closed position of the potentiometer). To do that, we need to use an Analog to Digital Converter (ADC) to express the analog value as a magnitude between 0 and V, rather than ON and OFF. An ADC measures the voltage on an input and returns a digital value as an integer having precision P in bits. So if an ADC returns a reading with a precision of 12 bits, the reading can range from 0 (being 0v) to 4095 (being 100% of the possible input voltage). An ADC is a collection of circuits that perform this job as a single package, whether integrated on the chip, or as a separate discrete component. There's a bunch of different ways this can be done, but the general theory is that the ADC is a circuit that takes an input voltage and expresses it as an integer representing a quantity between 0 and 100% of the potential maximum. One of the simplest ADCs to implement is called a Flash ADC, and that one is simple enough we can build it on a breadboard. I can't build this one yet - I need to come back to this when some components arrive in the mail. - Need to come back and build a flash ADC when my components get here ## How the ESP32-S3 ADC works The ESP32-S3 has two ADCs on the package that both perform in the same fashion. Per the technical reference manual > Two 12-bit Successive Approximation ADCs (SAR ADCs) controlled by five dedicated controllers that can input analog signals from total of 20 channels. The SAR ADCs can operate in a high-performance mode or a low-power mode. ![ESP32-S3 SAR ADC diagram](esp32sdcadc.png) The Successive Approximation ADCs are independent circuits that work similar to a binary search algorithm, searching for the digital value that corresponds to the voltage measurement within the maximum range. Basically the ADCs say: 1. Is the voltage over 1.6v? 2. If so, is it over 2.4v? 3. If not, is it over 2.0? 4. If not, is it over 2.2? .... and it keeps doing this, walking down into smaller and smaller slices of the maximum possible value, until it figures out where the right value is. It does this independently of the CPU; each ADC has its own clocks, arbiter, registers, timers, threshold monitors, etc etc. However it does cooperate with the ULP coprocessor (an ultra low power coprocessor that still runs when the CPU is in deep sleep mode); the ULP triggers the SAR ADC measurements and reads the results, and it has a bunch of registers related to managing the RTC and ADC and their associated interrupts. Honestly the ULP is a fascinating little device in itself. ## Measuring Capacitance