Capstone: Data Acquisition and Control
This capstone combines analog input, digital processing, and analog-like output. The target system reads a sensor, filters and calibrates it, compares it with a setpoint, and drives an actuator command using PWM.
Learning Objectives
By the end of this capstone, you should be able to:
- define signal ranges for a complete acquisition and control path;
- implement fixed-point filtering and scaling;
- generate a bounded output command;
- verify the system with known input cases;
- document safety limits and failure behavior.
Prerequisites
- ADC resolution, reference voltage, input filtering, and calibration.
- PWM output basics and safe low-voltage driver practice.
- Fixed-point C arithmetic with integer scaling.
- Ability to test firmware with known input codes before connecting an actuator.
Task
Build a low-voltage temperature-control demonstrator. The deliverable is firmware plus a verification log, not a production thermal controller. The firmware must read a sensor, reject implausible inputs, convert ADC code to temperature, apply a proportional control rule, and output a bounded PWM command.
System Requirement
Build a temperature-control demonstrator:
- sensor input:
0.5 Vto2.5 Vequals0 degree Cto100 degree C; - ADC:
12-bit,3.3 Vreference; - setpoint:
45 degree C; - output:
0%to100%PWM command; - control rule: proportional only,
2%output per1 degree Cerror; - safety: command must be
0%if the sensor is disconnected or outside plausible range.
Control Calculations
For a 12-bit ADC with 3.3 V reference:
$$
V_{IN,mV} = \frac{code \times 3300}{4095}
$$
For this sensor:
$$
T_C = \frac{V_{IN,mV} - 500}{20}
$$
because the span is 2000 mV over 100 degree C, or 20 mV/degree C.
The proportional controller uses:
$$
error_C = T_{set} - T_{measured}
$$
$$
cmd = clamp(K_P e_C, 0, 100)
$$
with K_P = 2 %/degree C. If the sensor is implausible, the command must be 0% regardless of the calculated error.
Buildable Reference Code
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#define ADC_MAX 4095u
#define VREF_MV 3300u
#define SENSOR_MIN_MV 500u
#define SENSOR_MAX_MV 2500u
#define SETPOINT_CENTI 4500
#define KP_PERCENT_PER_C 2
static uint32_t adc_to_mv(uint16_t code) {
return ((uint32_t)code * VREF_MV + ADC_MAX / 2u) / ADC_MAX;
}
static bool sensor_plausible(uint32_t mv) {
return mv >= 400u && mv <= 2600u;
}
static int32_t mv_to_centi_c(uint32_t mv) {
if (mv <= SENSOR_MIN_MV) return 0;
if (mv >= SENSOR_MAX_MV) return 10000;
return (int32_t)((mv - SENSOR_MIN_MV) * 10000u /
(SENSOR_MAX_MV - SENSOR_MIN_MV));
}
static uint8_t control_percent(int32_t temp_centi) {
int32_t error_c = (SETPOINT_CENTI - temp_centi) / 100;
int32_t cmd = error_c * KP_PERCENT_PER_C;
if (cmd < 0) cmd = 0;
if (cmd > 100) cmd = 100;
return (uint8_t)cmd;
}
static void run_case(uint16_t code) {
uint32_t mv = adc_to_mv(code);
if (!sensor_plausible(mv)) {
printf("code=%u mv=%lu FAULT pwm=0\n", code, (unsigned long)mv);
return;
}
int32_t temp = mv_to_centi_c(mv);
printf("code=%u mv=%lu temp=%ld.%02ld pwm=%u%%\n",
code, (unsigned long)mv,
(long)(temp / 100), (long)(temp % 100),
control_percent(temp));
}
int main(void) {
run_case(621);
run_case(1861);
run_case(3102);
run_case(50);
return 0;
}
Expected Behavior
| Case | Meaning | Expected command |
|---|---|---|
code near 621 |
about 0 degree C |
high command, about 90% |
code near 1861 |
about 50 degree C |
0%, above setpoint |
code near 3102 |
about 100 degree C |
0% |
code near 50 |
implausible input | fault, 0% |
At startup, PWM output must remain disabled until at least one plausible sensor sample has been processed.
Verification Plan
- Unit-test conversion functions with known ADC codes.
- Confirm output command clamps between
0%and100%. - Inject implausible low and high sensor values.
- Measure raw ADC pin voltage and compare with logged millivolts.
- Check PWM frequency, duty cycle, and startup default.
- Run with the real actuator disabled first.
- Enable actuator through a current-limited or protected driver.
- Record noise and command stability near the setpoint.
Common Failure Symptoms
| Symptom | Likely cause |
|---|---|
| PWM turns on at reset | output default state or initialization order is unsafe |
| correct ADC mV but wrong temperature | calibration constants or integer scaling are wrong |
| command oscillates near setpoint | noisy input, too little filtering, or too much gain |
| command always 0% | sensor plausibility window too narrow or setpoint already exceeded |
| fault not detected on disconnect | missing pull behavior or open-circuit test case |
| actuator affects measurement | shared return path, EMI, or inadequate decoupling |
Debugging Guidance
- Log raw ADC code, millivolts, temperature, fault state, and PWM command separately.
- Test firmware with hard-coded ADC codes before enabling the ADC peripheral.
- Test ADC input with a bench voltage source before connecting the sensor.
- Scope PWM at the MCU pin and again at the driver input.
- Disable the actuator power path while validating control calculations.
- Inject low, high, open, and shorted sensor cases.
- Reduce proportional gain or add filtering only after the scaling is correct.
Safety Guidance
Use a low-voltage, current-limited load for learning. Do not connect mains heaters, high-current motors, or batteries without appropriate isolation, fusing, thermal cutoff, enclosure, and qualified review.
Common Mistakes
- Enabling the actuator before validating sensor plausibility.
- Forgetting PWM startup state.
- Filtering so heavily that control response becomes too slow.
- Ignoring sensor disconnect and short-circuit cases.
- Treating a proportional demo as a production thermal controller.
Extension Challenge
Add a moving-average or first-order IIR filter and compare step response against noise reduction. Then add a latched fault state that requires a manual reset after an implausible sensor reading.
Explained Solution
The firmware first converts ADC code to millivolts using the measured reference scale. It rejects values outside the plausible sensor range before control output is allowed. Plausible values are mapped linearly from 500 mV to 2500 mV, giving 0 degree C to 100 degree C. The proportional controller drives heating only when measured temperature is below the 45 degree C setpoint. Clamping prevents negative duty cycle above the setpoint and prevents commands above 100% when the measured temperature is far below the setpoint. The actuator remains disabled for implausible sensor readings and during initial startup.
Summary
A real data-acquisition system must convert physical voltage into engineering units, reject implausible values, filter noise, control an output, and fail safely.
Further Reading
- Microchip ADC and PWM peripheral application examples.
- Texas Instruments control-loop implementation notes.
- Analog Devices sensor signal-chain design resources.