Skip to content

Commit a570d2c

Browse files
committed
docs: add project README and supplementary documentation images for HW3
1 parent baa45ac commit a570d2c

31 files changed

Lines changed: 291 additions & 0 deletions

‎HW3/README.md‎

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
# ⚙️ HW3: Embedded Systems, Timers, EXTI Interrupts & Sensor LCD Interfacing
2+
3+
> **Course:** Instrumentation Engineering (Spring 2026 / 1405)
4+
> **Instructor:** Dr. Nayeri
5+
> **Student:** Amirali Dehghani (ID: 810102443)
6+
> **Microcontroller:** STM32F103 Series (ARM Cortex-M3)
7+
> **Tools:** STM32CubeIDE, STM32 HAL Library, Proteus 8 Professional, LaTeX
8+
> **Files Included:** C Source Code (`main.c`), STM32 Config (`.ioc`), Executables (`.hex`), Proteus Files (`.pdsprj`), Demonstration Videos (`.mp4`), Images (`img/`), and Solved Lab Report (`.pdf`).
9+
10+
---
11+
12+
## 📖 Overview
13+
14+
Homework 3 transitions into embedded microcontrollers (STM32F103) for industrial data acquisition, timing control, actuator driving, and visual display interfacing:
15+
1. **Elevator Floor Indicator (7-Segment & EXTI Interrupts):** GPIO configuration for Common Cathode 7-Segment display, continuous 0–9 sequential floor cycling, and **External Interrupts (EXTI)** for emergency floor holds (`Floor 1` and `Floor 9`).
16+
2. **DC Motor Speed & Direction Control (PWM TIM2 + L298 Driver + ADC):** Timer configuration for $1\text{ kHz}$ PWM generation, mathematical Prescaler & Auto-Reload calculations, 12-bit ADC potentiometer speed scaling, L298 H-Bridge driver interfacing, and EXTI direction toggling.
17+
3. **15-Second Precision Countdown System (TIM2 Interrupts + 16x2 LCD + Alarm):** Hardware timer interrupt callback ($500\text{ ms}$ tick), synchronous $1\text{ Hz}$ LED blinking & Buzzer beeping, continuous alarm on expiration ($0\text{ s}$), real-time 16x2 LCD display, and instant `LogicState` reset.
18+
4. **Automatic Industrial Sensor Identification System (12-Bit ADC + Alphanumeric LCD):** Multi-sensor simulation via potentiometer sampling with a 12-bit ADC ($0.8\text{ mV}$ resolution over $3.3\text{ V}$ range), automatic identification of **LM35 Temperature**, **HIH-4000 Humidity**, **MPX4115 Pressure**, and **MQ-135 Gas** sensors, and formatted LCD readout.
19+
20+
---
21+
22+
## 📂 Directory Structure
23+
24+
```text
25+
HW3/
26+
├── Q1/
27+
│ ├── main.c # Source code for 7-Segment Elevator & EXTI emergency hold
28+
│ ├── Q1.pdsprj # Proteus schematic (STM32 + 7-Segment + Buttons)
29+
│ ├── HW3-1.hex # Compiled binary firmware
30+
│ └── HW3-1.ioc # STM32CubeMX pinout & clock configuration
31+
├── Q2/
32+
│ ├── main.c # Source code for PWM DC motor speed & direction control
33+
│ ├── Q2.pdsprj # Proteus schematic (STM32 + L298 Driver + DC Motor + Pot)
34+
│ ├── Q2.hex # Compiled binary firmware
35+
│ └── Q2.ioc # STM32CubeMX configuration (TIM2 PWM + ADC1 + EXTI)
36+
├── Q3/
37+
│ ├── main.c # Source code for 15s Timer Interrupt countdown system
38+
│ ├── Q3.pdsprj # Proteus schematic (STM32 + 16x2 LCD + Buzzer + LED)
39+
│ ├── Q3.hex # Compiled binary firmware
40+
│ └── Q3.ioc # STM32CubeMX configuration (TIM2 Interrupt + GPIO)
41+
├── Q4/
42+
│ ├── main.c # Source code for Auto Sensor Classifier & Physical Unit LCD
43+
│ ├── q4.pdsprj # Proteus schematic (STM32 + Active Pot + 16x2 LCD)
44+
│ ├── Q4.hex # Compiled binary firmware
45+
│ └── Q4.ioc # STM32CubeMX configuration (ADC1 12-Bit + GPIO LCD)
46+
├── LCD Files/
47+
│ ├── lcd.c # HD44780 LCD HAL driver implementation
48+
│ └── lcd.h # HD44780 LCD library header
49+
├── Video/
50+
│ ├── Q1.mp4 # Video demonstration for Question 1
51+
│ ├── Q2.mp4 # Video demonstration for Question 2
52+
│ ├── Q3.mp4 # Video demonstration for Question 3
53+
│ └── Q4.mp4 # Video demonstration for Question 4
54+
├── img/
55+
│ ├── q1-1.png - q1-5-9.png # Pinouts, schematics & 7-Segment floor counting frames (0-9)
56+
│ ├── q2-1.png - q2-4-2.png # TIM2 PWM pinouts, L298 connections & motor rotation plots
57+
│ ├── q3-1.png - q3-3.png # Countdown LCD schematic, active state & zero-alarm hold
58+
│ └── q4-1.png - q4-6.png # ADC pinout & LCD readings for LM35, HIH4000, MPX4115, MQ135
59+
├── Inst_HW3.pdf # Original Assignment Question Paper
60+
└── Inst-HW3-810102443.pdf # Complete Solved Lab Report (PDF)
61+
```
62+
63+
---
64+
65+
## 💻 C Source Code & HAL Implementation Analysis
66+
67+
---
68+
69+
### 🔹 Question 1: Elevator Floor Indicator (`Q1/main.c`)
70+
71+
#### **Code Architecture & Register Manipulation:**
72+
- **7-Segment Hex Look-up Table:**
73+
```c
74+
uint8_t segCode[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
75+
```
76+
Pre-computed Common Cathode hex codes mapping digits `0` through `9` to GPIOA pins `PA0..PA6`.
77+
78+
- **Atomic ODR Register Update:**
79+
To update segment outputs without altering high GPIOA pins, atomic bitmasking is performed on the Output Data Register:
80+
```c
81+
GPIOA->ODR = (GPIOA->ODR & 0xFF80) | segCode[currentNumber];
82+
```
83+
84+
- **State Machine & EXTI Interrupt Callbacks:**
85+
```c
86+
volatile uint8_t systemState = 0; // State 0: Init (Floor 0), State 1: Running, State 2: Emergency 1, State 3: Emergency 9
87+
88+
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
89+
if (GPIO_Pin == GPIO_PIN_1) {
90+
systemState = 2; // Immediate hold on Floor 1
91+
} else if (GPIO_Pin == GPIO_PIN_2) {
92+
systemState = 3; // Immediate hold on Floor 9
93+
}
94+
}
95+
```
96+
The asynchronous EXTI callbacks interrupt the $1000\text{ ms}$ `HAL_Delay` loop immediately, guaranteeing zero-latency emergency stopping.
97+
98+
| Figure 1.1: STM32CubeIDE Pinout Configuration | Figure 1.2: Proteus Circuit Schematic |
99+
| :---: | :---: |
100+
| ![Q1 Pinout](img/q1-1.png) | ![Q1 Schematic](img/q1-2.png) |
101+
102+
| Figure 1.3: Floor 0 (Initial) | Figure 1.4: Floor 5 (Cycling) | Figure 1.5: Emergency Hold Floor 1 (`EXTI1`) | Figure 1.6: Emergency Hold Floor 9 (`EXTI2`) |
103+
| :---: | :---: | :---: | :---: |
104+
| ![Floor 0](img/q1-3.png) | ![Floor 5](img/q1-4-5.png) | ![Emergency 1](img/q1-5-1.png) | ![Emergency 9](img/q1-5-9.png) |
105+
106+
---
107+
108+
### 🔹 Question 2: DC Motor Speed & Direction Control (`Q2/main.c`)
109+
110+
#### **Theoretical Prescaler & PWM Frequency Math:**
111+
Target PWM frequency: $f_{\text{PWM}} = 1\text{ kHz}$ on a $f_{\text{TIM}} = 36\text{ MHz}$ timer clock:
112+
$$f_{\text{PWM}} = \frac{f_{\text{TIM}}}{(\text{PSC} + 1) \times (\text{ARR} + 1)} = \frac{36 \times 10^6}{(35 + 1) \times (999 + 1)} = \frac{36 \times 10^6}{36000} = \mathbf{1000\text{ Hz}}$$
113+
114+
#### **C Implementation Highlights:**
115+
- **Timer & ADC Initialization:**
116+
```c
117+
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
118+
```
119+
120+
- **ADC Sampling & Dynamic PWM Scaling Loop:**
121+
```c
122+
HAL_ADC_Start(&hadc1);
123+
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {
124+
adcValue = HAL_ADC_GetValue(&hadc1);
125+
}
126+
HAL_ADC_Stop(&hadc1);
127+
128+
// Mappings: 12-bit ADC (0..4095) -> PWM Duty Cycle ARR range (0..1000)
129+
pwmValue = (adcValue * 1000) / 4095;
130+
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwmValue);
131+
```
132+
133+
- **H-Bridge Direction Control & EXTI Inversion:**
134+
```c
135+
volatile uint8_t motorDirection = 0;
136+
137+
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
138+
if (GPIO_Pin == GPIO_PIN_0) {
139+
motorDirection = !motorDirection; // Toggle direction on button press
140+
}
141+
}
142+
```
143+
The main loop evaluates `motorDirection` and sets L298 driver input pins `PA2` (`IN1`) and `PA3` (`IN2`) accordingly.
144+
145+
| Figure 2.1: TIM2 PWM & ADC Pinout Config | Figure 2.2: L298 Motor Driver Proteus Schematic |
146+
| :---: | :---: |
147+
| ![Q2 Pinout](img/q2-1.png) | ![Q2 Schematic](img/q2-2.png) |
148+
149+
| Figure 2.3: Clockwise Rotation & Speed Adjustment | Figure 2.4: Counter-Clockwise Inversion (`EXTI`) |
150+
| :---: | :---: |
151+
| ![CW Rotation](img/q2-3-1.png) | ![CCW Rotation](img/q2-4-2.png) |
152+
153+
---
154+
155+
### 🔹 Question 3: 15-Second Precision Countdown System (`Q3/main.c`)
156+
157+
#### **Timer Interrupt Callbacks & Sub-Second Ticking:**
158+
TIM3 is configured with Prescaler $\text{PSC} = 35999$ and Period $\text{ARR} = 499$, generating a hardware interrupt callback every **$500\text{ ms}$** ($2\text{ Hz}$ tick).
159+
160+
- **Synchronous Alarm & Clock Management in `HAL_TIM_PeriodElapsedCallback`:**
161+
```c
162+
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
163+
if (htim->Instance == TIM3) {
164+
if (isRunning == 1) {
165+
if (countdown > 0) {
166+
timerTick++;
167+
if (timerTick % 2 == 1) { // 500ms ON state
168+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // LED ON
169+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // Buzzer ON
170+
} else { // 500ms OFF state (Full 1s elapsed)
171+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // LED OFF
172+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); // Buzzer OFF
173+
countdown--;
174+
}
175+
} else { // Expiration (0s): Latch Alarm Continuously
176+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
177+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
178+
}
179+
}
180+
}
181+
}
182+
```
183+
184+
- **LCD Rendering & Hardware LogicState Reset in `main()`:**
185+
```c
186+
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {
187+
if (isRunning == 0 && countdown == 15) isRunning = 1;
188+
} else {
189+
isRunning = 0; countdown = 15; // Reset countdown to 15s
190+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
191+
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
192+
}
193+
194+
if (countdown != last_countdown) {
195+
sprintf(lcdBuffer, "Time: %02d ", countdown);
196+
Lcd_cursor(&lcd, 0, 0);
197+
Lcd_string(&lcd, lcdBuffer);
198+
last_countdown = countdown;
199+
}
200+
```
201+
202+
| Figure 3.1: Countdown System Proteus Schematic |
203+
| :---: |
204+
| ![Q3 Schematic](img/q3-1.png) |
205+
206+
| Figure 3.2: Countdown Active (T-minus 8s, Blinking/Beeping) | Figure 3.3: Expiration Alarm Hold (0s, Continuous Alarm) |
207+
| :---: | :---: |
208+
| ![Countdown Active](img/q3-2.png) | ![Expiration Alarm](img/q3-3.png) |
209+
210+
---
211+
212+
### 🔹 Question 4: Automatic Multi-Sensor Classifier (`Q4/main.c`)
213+
214+
#### **ADC Sampling & Real-Time Sensor Classification Code:**
215+
- **Quantization Voltage Formula:**
216+
$$\text{sensorVoltage} = \frac{\text{adcValue} \times 3.3\text{ V}}{4095.0}$$
217+
218+
- **Conditional Multi-Sensor Classification & Formatting:**
219+
```c
220+
HAL_ADC_Start(&hadc1);
221+
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {
222+
adcValue = HAL_ADC_GetValue(&hadc1);
223+
sensorVoltage = (adcValue * 3.3f) / 4095.0f;
224+
}
225+
HAL_ADC_Stop(&hadc1);
226+
227+
if (sensorVoltage >= 0.0f && sensorVoltage < 1.0f) {
228+
sprintf(sensorName, "Temp: LM35");
229+
physicalValue = 100.0f * sensorVoltage;
230+
sprintf(unit, "C");
231+
} else if (sensorVoltage >= 1.0f && sensorVoltage < 2.0f) {
232+
sprintf(sensorName, "Hum: HIH-4000");
233+
physicalValue = 33.3f * sensorVoltage;
234+
sprintf(unit, "%%");
235+
} else if (sensorVoltage >= 2.0f && sensorVoltage < 3.0f) {
236+
sprintf(sensorName, "Pres: MPX4115");
237+
physicalValue = 100.0f * sensorVoltage;
238+
sprintf(unit, "hPa");
239+
} else if (sensorVoltage >= 3.0f && sensorVoltage <= 3.3f) {
240+
sprintf(sensorName, "Air: MQ-135");
241+
physicalValue = 100.0f * (sensorVoltage / 3.3f);
242+
sprintf(unit, "%%");
243+
}
244+
245+
sprintf(line1, "%-16s", sensorName);
246+
sprintf(line2, "Val: %.2f %s ", physicalValue, unit);
247+
Lcd_cursor(&lcd, 0, 0); Lcd_string(&lcd, line1);
248+
Lcd_cursor(&lcd, 1, 0); Lcd_string(&lcd, line2);
249+
```
250+
251+
| Voltage Window ($V$) | Classified Sensor | Physical Formula | LCD Line 1 / Line 2 Output |
252+
| :---: | :---: | :---: | :---: |
253+
| **$0.00 - 0.99\text{ V}$** | **LM35 Temperature** | $\text{Temp} = 100 \times V$ | `Temp: LM35` / `Val: 50.00 C` |
254+
| **$1.00 - 1.99\text{ V}$** | **HIH-4000 Humidity** | $\text{Humidity} = 33.3 \times V$ | `Hum: HIH-4000` / `Val: 49.95 %` |
255+
| **$2.00 - 2.99\text{ V}$** | **MPX4115 Pressure** | $\text{Pressure} = 100 \times V$ | `Pres: MPX4115` / `Val: 250.00 hPa` |
256+
| **$3.00 - 3.30\text{ V}$** | **MQ-135 Air Quality** | $\text{Air Quality} = \frac{V}{3.3} \times 100$ | `Air: MQ-135` / `Val: 100.00 %` |
257+
258+
| Figure 4.1: STM32 ADC & LCD Pinout Config | Figure 4.2: Proteus Circuit Diagram |
259+
| :---: | :---: |
260+
| ![Q4 Pinout](img/q4-1.png) | ![Q4 Schematic](img/q4-2.png) |
261+
262+
| Figure 4.3: LM35 Temp ($0.50\text{ V} \to 50.00^\circ\text{C}$) | Figure 4.4: HIH4000 Humidity ($1.50\text{ V} \to 49.95\%$) |
263+
| :---: | :---: |
264+
| ![LM35 LCD](img/q4-3.png) | ![HIH4000 LCD](img/q4-4.png) |
265+
266+
| Figure 4.5: MPX4115 Pressure ($2.50\text{ V} \to 250.00\text{ hPa}$) | Figure 4.6: MQ-135 Air Quality ($3.30\text{ V} \to 100.00\%$) |
267+
| :---: | :---: |
268+
| ![MPX4115 LCD](img/q4-5.png) | ![MQ135 LCD](img/q4-6.png) |
269+
270+
---
271+
272+
## 💻 How to Build & Simulate
273+
274+
### 1. Building Firmware in STM32CubeIDE
275+
1. Open **STM32CubeIDE**.
276+
2. File $\to$ Open Projects from File System $\to$ Select target folder (`HW3/Q1`, `HW3/Q2`, `HW3/Q3`, or `HW3/Q4`).
277+
3. Build Project (`Ctrl + B`). The output `.hex` binary will generate automatically in `Debug/`.
278+
279+
### 2. Running Proteus Simulation
280+
1. Launch **Proteus 8 Professional**.
281+
2. Open target `.pdsprj` file from `HW3/Q1/`, `HW3/Q2/`, `HW3/Q3/`, or `HW3/Q4/`.
282+
3. Double-click the STM32 microcontroller component and ensure **Program File** points to the corresponding `.hex` file.
283+
4. Press **Play** to start real-time simulation. Demonstration MP4 videos are also available in `HW3/Video/`.
284+
285+
---
286+
287+
<div align="center">
288+
289+
**[Go back to Main Repository README](../README.md)**
290+
291+
</div>

‎HW3/img/q1-1.png‎

1.88 MB
Loading

‎HW3/img/q1-2.png‎

91.9 KB
Loading

‎HW3/img/q1-3.png‎

1.88 MB
Loading

‎HW3/img/q1-4-0.png‎

1.88 MB
Loading

‎HW3/img/q1-4-1.png‎

1.88 MB
Loading

‎HW3/img/q1-4-2.png‎

1.88 MB
Loading

‎HW3/img/q1-4-3.png‎

1.88 MB
Loading

‎HW3/img/q1-4-4.png‎

1.88 MB
Loading

‎HW3/img/q1-4-5.png‎

1.88 MB
Loading

0 commit comments

Comments
 (0)