A signal-level generator with an ESP32
Designprosjekt 1 in NTNU's electronic-systems design course. The brief: take an
analog sinusoidal input X₁(t) and produce an output X₂(t) =
A·X₁(t), where A is set by a knob the user can turn. The whole
gain control runs through an ESP32 in the middle of the chain: analog in, analog
back out, software in between.
The pipeline
- Input: a 229 Hz, 75 mV-amplitude sine on the input.
- An analog gain & level-shift stage maps the bipolar signal into the ESP32 ADC's 0–3.3 V window.
- Inside the ESP32: read the signal sample and the potentiometer position; multiply; write to the 8-bit DAC.
- Output: the same sinusoid, attenuated or amplified by whatever the knob currently demands.
Numbers
- Max gain: 3300/(75·2) = 22 (≈ 26.85 dB).
- Max attenuation: (3300/255)/150 = 0.086 (≈ −21.28 dB).
- Resolution: the pot is read through a 12-bit ADC (4096 steps), so the gain control has a theoretical step of (26.85 − (−21.28))/4096 ≈ 0.0118 dB.
- SNR: measured on the analog front-end at roughly 24–28 dB, mostly limited by the input stage rather than the ESP32 itself.
The hot loop is a single line, intentionally:
void loop() {
dacWrite(25, ((int)analogRead(35) * (int)analogRead(potPin)) >> 16);
}
Casting to int32 before the multiply, then bit-shifting 16 places,
keeps the result in the DAC's 0–255 range without paying for a division. The
whole thing runs as fast as the ADC will allow.
Where it falls down, and the next step
At very low gain the DAC's quantisation dominates, and the output looks like a staircase between 0 and 6.47 mV. A passive smoothing stage on the output would clean that up considerably; that is the obvious next iteration.