// PROJECT 002

Aerosol Module Controller

Embedded firmware architecture for real-time aerosol (fog) distribution control in medical device sterilizer chambers. Multi-threaded FreeRTOS design on Atmel AVR32 with PWM actuators, ADC feedback sensing, and CANopen communication protocol for safety-critical sterilization operations.

Atmel AVR32C / EmbeddedFreeRTOSPWM / ADCCANopenReal-time Control
// SENSOR INPUTS ADC0: Pressure ADC1: Temperature ADC2: Flow Sensor GPIO: Safety I/O // AVR32 UC3C MCU Freq: 66 MHz RAM: 64 KB Flash: 256 KB FreeRTOS 10.2 // PWM OUTPUTS PWM0: Fog Pump PWM1: Flow Valve PWM2: Heater GPIO: Relays // COMMUNICATION STACK CAN Interface (500 kbps) CANopen DS301 Protocol TPDO: Telemetry RPDO: Commands
66CPU Freq (MHz)
256Flash (KB)
3PWM Channels
500CAN Speed (kbps)
MicrocontrollerAtmel AVR32 UC3C1512 · 32-bit ARM core @ 66 MHz
Memory256 KB Flash · 64 KB SRAM · 4 KB EEPROM
RTOSFreeRTOS 10.2 with 4 priority levels (Kernel, Control, Monitor, Idle)
ADC Channels12-bit SAR ADC · 3 active inputs (Pressure, Temperature, Flow)
PWM Modules3 TC (Timer/Counter) channels @ 16-bit precision · 1 kHz base frequency
CommunicationCAN 2.0B · CANopen DS301/DS305 with 4 TPDOs + 2 RPDOs
Safety FeaturesWatchdog Timer (WDT) · Brown-out Detection · Dual ADC measurements

System Architecture

The aerosol module controller implements a multi-threaded real-time control system on the Atmel AVR32 microcontroller. The firmware is structured into independent FreeRTOS tasks handling sensor acquisition, control algorithms, communication, and safety monitoring. Each task runs at its own priority level with deterministic timing guarantees.

Hardware Interface Layer

ADC Sensor Acquisition
Reads analog sensor inputs for chamber pressure, temperature, and flow rate measurements.
void adc_init(void) - Configures 12-bit SAR ADC - Sets channel 0–2 for pressure/temp/flow - Selects internal 2.5V reference - Enables differential mode for noise rejection
uint16_t adc_read_pressure(void)
Samples chamber pressure from ADC channel 0. Returns 12-bit raw value (0–4095 maps to 0–200 kPa).
// Reads ADC0, applies 1st-order IIR filter // 16x oversampling for noise reduction // Returns: Filtered pressure in 0.05 kPa resolution
uint16_t adc_read_temperature(void)
Acquires chamber temperature from thermistor input on ADC channel 1. Applies linearization correction for NTC thermistor.
// Reads ADC1 (NTC thermistor divider) // Applies Steinhart-Hart equation linearization // Returns: Temperature in 0.1°C resolution (0–134°C)
uint8_t adc_read_flow_sensor(void)
Monitors aerosol flow rate from turbine sensor. Counts pulses and converts to flow percentage.
// Reads ADC2 frequency from turbine sensor // Pulse counting over 100 ms window // Returns: Flow rate as 0–100% (proportional to Hz)

PWM Actuation & Control

void pwm_init(void)
Initializes three PWM outputs for fog pump, flow control valve, and heater element. Configures 16-bit timer/counters at 1 kHz base frequency.
// TC0 (Timer 0): Fog pump motor – Duty cycle 0–100% // TC1 (Timer 1): Proportional valve – Duty cycle 0–100% // TC2 (Timer 2): Heater resistor – Duty cycle 0–100% // All channels use center-aligned PWM for smooth control
void pwm_set_fog_pump(uint8_t duty_percent)
Sets fog pump motor PWM duty cycle to regulate aerosol concentration. Accepts 0–100% input with 1% resolution.
// Maps duty (0–100) to TC0 compare register // Applies rate limiting: max ΔDuty = 5% per cycle // Prevents motor inrush current // Input: duty_percent (0=off, 100=full)
void pwm_set_flow_valve(uint8_t duty_percent)
Modulates proportional flow control valve. Duty cycle controls aerosol delivery speed into chamber (0–100%).
// Maps duty (0–100) to TC1 compare register // Dead-band compensation: min 15% to overcome static friction // Hysteresis band: ±2% to prevent chatter // Input: duty_percent (0=closed, 100=full open)
void pwm_set_heater(uint8_t duty_percent)
Controls heating element for chamber temperature regulation. Uses Pulse-Width Modulation to limit peak power draw.
// Maps duty (0–100) to TC2 compare register // Frequency: 1 kHz (heater thermal time constant >> 1 ms) // Soft-start ramp: 20 ms to reach commanded duty // Safety limit: Max 100°C setpoint with 135°C hard limit

Control Algorithms

void fog_concentration_control(uint8_t target_percent)
Implements fog concentration feedback controller. Closes loop on pump speed to achieve target aerosol density in chamber.
// Algorithm: PI controller on pump duty cycle // Setpoint: target_percent (0–100%) // Feedback: Flow sensor (ADC2) // Kp = 0.8, Ki = 0.15 (tuned for 200 ms response) // Output: Fog pump PWM duty 0–100%
void temperature_control(uint8_t target_celsius)
Temperature regulation using proportional heater control. Maintains chamber temperature within ±2°C of target setpoint.
// Algorithm: PI control on heater duty // Setpoint: target_celsius (0–134°C) // Feedback: NTC thermistor (ADC1, linearized) // Kp = 1.2, Ki = 0.08 (thermal time constant ~2 sec) // Output: Heater PWM duty 0–100% // Safety: Hard cutoff at 135°C via overshoot protection
void pressure_control(uint8_t target_kpa)
Chamber pressure regulation via proportional valve. Maintains differential pressure for efficient aerosol delivery.
// Algorithm: PI feedback control // Setpoint: target_kpa (0–200 kPa) // Feedback: Piezoresistive sensor (ADC0) // Kp = 0.6, Ki = 0.12 (response time ~300 ms) // Output: Flow valve PWM duty 0–100% // Interlock: Disabled if pump not running (pump_duty < 10%)

Real-time Task Scheduler

/* FreeRTOS Task Definitions */

// Task 1: Sensor Acquisition (50 ms period, Priority=2)
void vTaskSensorMonitor(void *pvParameters) {
    while (1) {
        uint16_t raw_pressure = adc_read_pressure();
        uint16_t raw_temp = adc_read_temperature();
        uint8_t raw_flow = adc_read_flow_sensor();
        
        // Update global control state
        g_sensor_state.pressure_kpa = (raw_pressure / 4095.0f) * 200.0f;
        g_sensor_state.temp_celsius = (raw_temp / 4095.0f) * 134.0f;
        g_sensor_state.flow_percent = raw_flow;
        
        // Safety checks
        if (g_sensor_state.pressure_kpa > 220) {
            gpio_set_high(GPIO_SAFETY_SHUTDOWN);  // Emergency stop
        }
        
        vTaskDelay(pdMS_TO_TICKS(50));
    }
}

// Task 2: Control Loop (100 ms period, Priority=3)
void vTaskControlLoop(void *pvParameters) {
    while (1) {
        fog_concentration_control(g_setpoint.fog_percent);
        temperature_control(g_setpoint.temp_celsius);
        pressure_control(g_setpoint.pressure_kpa);
        
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

// Task 3: CANopen Communication (50 ms period, Priority=2)
void vTaskCANopen(void *pvParameters) {
    while (1) {
        // Transmit TPDO (Telemetry)
        can_send_tpdo1(g_sensor_state);
        
        // Process RPDO (Commands)
        canopen_rpdo_handler();
        
        vTaskDelay(pdMS_TO_TICKS(50));
    }
}

// Task 4: Safety Monitor (20 ms period, Priority=1 - Highest)
void vTaskSafetyMonitor(void *pvParameters) {
    while (1) {
        // Watchdog kick
        wdt_reload();
        
        // Fault detection
        if (g_sensor_state.pressure_kpa < 50) {
            fault_handler(FAULT_LOW_PRESSURE);
        }
        if (g_sensor_state.temp_celsius > 140) {
            fault_handler(FAULT_OVERTEMP);
        }
        
        vTaskDelay(pdMS_TO_TICKS(20));
    }
}

CANopen Communication Protocol

The firmware implements CANopen DS301 protocol for integration with the sterilizer control system. Telemetry (TPDO) transmits sensor measurements every 50 ms, while command reception (RPDO) updates setpoints from the main controller.

TPDO1 (TX 0x181)SoC: 87.3% | Pressure: 120 kPa | Temp: 95°C | Flow: 75%
RPDO1 (RX 0x201)Fog Target: 75% | Pressure Target: 120 kPa | Temp Target: 95°C
RPDO2 (RX 0x301)Cycle Duration: 60 min | Mode: Running | Safety Enable: 1
Cycle Time50 ms (20 Hz message rate, non-blocking async CAN ISR)

Safety & Fault Handling

Development Environment & Tools

Memory Layout & Resource Allocation

// AVR32 UC3C Flash Allocation (256 KB)
0x00000000 — 0x00003FFF : Bootloader (16 KB)
0x00004000 — 0x0003FFFF : Application code + Data (228 KB)
0x00040000 — 0x00040FFF : EEPROM emulation (4 KB, wear-leveling)

// SRAM Allocation (64 KB)
0x20000000 — 0x2000FFFF : FreeRTOS heap + task stacks (20 KB)
0x20005000 — 0x200057FF : CAN message buffers (2 KB)
0x20006000 — 0x200067FF : ADC sample buffer (2 KB)
0x20007000 — 0x20007FFF : Persistent state storage (4 KB)

Performance Metrics & Timing Analysis

Sensor-to-Control Latency~15 ms (ADC acquisition + task switch)
Control Loop Update Rate100 Hz (10 ms period, jitter <1 ms)
CAN Message Latency~5 ms from sensor read to CAN transmission
Firmware Size~45 KB (compiled, with optimizations)
CPU Utilization~25% average (leaves 75% headroom for diagnostics)
Power Consumption~120 mW @ 66 MHz (typical operation)
← All Projects