# Project 2 — Finite State Machines

<p class="block-synopsis">Turn the distance sensor you calibrated at Lesson 22 into the range channel of a fire-control system: implement the SEARCH / DETECT / LOCK engagement state machine on your Arduino Due, with a Moore telemetry output, a Mealy weapon-release output guarded by two interlocks, and the target-loss edges a real sensor forces you to think about.</p>

:::{admonition} At a glance
:class: key-concept

Work days are **Lessons 26 and 27**; **groups of 2**. **Lesson 26 is Parts 1–4** (wiring,
the diagram, the table, the transitions); **Lesson 27 is Parts 5–6** (the outputs and the
demo). Worth **3 project points** — one for the demo and code walkthrough, one for the
diagram and table, one for the discussion questions. **One group submission** to the
Gradescope assignment **Project 2**, with three files: your sketch (`.ino`), your completed
transition-table workbook (`.xlsx`), and one PDF with your diagram, your documentation
statement and both names. The four discussion questions are answered **individually**, in
their own Gradescope assignment, **Project 2 Discussion Questions**. **Gradescope is
authoritative for both deadlines.**

**GenAI is authorized up to Level 4** — co-create and revise, as defined in the AW GenAI
Policy. That is **looser than the Lesson 22 lab**, which was Level 3. You are responsible
for demonstrating understanding of anything you take from generative AI.
:::

## The Scenario

You are building the engagement logic of a short-range fire-control system, and you are
building it out of the parts on your bench:

| On the bench | In the scenario |
| --- | --- |
| Sharp IR sensor on `A0` | the **seeker's range channel** — how far away the target is |
| Serial Monitor | the **scope display** — one status line per engagement tick |
| Your keyboard | the **operator console** — lock and pickle (weapon-release consent) commands |
| Jumper from pin `2` to `GND` | the **master arm plug** — inserted is ARMED, absent is SAFE |
| `DAC1`, read by a DMM | **telemetry to the weapons panel** — a status voltage another subsystem reads |
| `LED_BUILTIN` | the **launch indicator** |

At Lesson 24 you saw *safe, searching, locked, engaged* listed as an everyday FSM whose
transitions are safety-critical. This is a machine of that kind — here arming is an interlock
*input*, not a state. The difference is that this one runs on your
board, off a sensor you calibrated yourself, and the transitions are yours to get right.

:::{admonition} Educational exercise
:class: warning

This scenario does **not** represent an actual weapon system, its interlocks, or its
release logic.
:::

## Start With the Demo

Open the FSM Explorer and select the **Mealy · Fire Control Radar** tab:

**<https://usafa-ece.org/apps/fsm-demo/>**

**This is the machine you are about to build in hardware:** the same three states with the
same encodings, the same five inputs, the same priority order inside each state, and both
target-loss edges. Each bubble shows its state's telemetry voltage, and FIRE
($\text{LOCK} \cdot P \cdot E \cdot M$) belongs on an *arrow*, not in a bubble.

Out of the box the demo steps the specification itself. Set $D$, $E$ and $M$ with their
checkboxes and press **Step** to advance one tick. $L$ and $P$ are one-shot buttons, and
pressing one while the demo is stopped *is* a step: one press is one tick with that key in
it, so do not follow it with **Step** as well. (While the demo is running, the press waits
for the next tick.) The machine moves exactly as your board should. Under the status line,
an event line prints the same `*** MISSILE AWAY ***` and `NO FIRE` messages your Serial
Monitor will, the launch indicator strobes on the shot, and on the next step the demo
reacquires the target that is still sitting there.

:::{admonition} Use the demo to test your logic, not to copy it
:class: key-concept

The demo's transition arcs, their labels, its reference transition table and its **Show
Answer** button sit behind an **Instructor reveal** that your instructor runs in class. The
diagram and the table are one of your three project points, so on your own, use the demo
to check the work you have already done:

- **Predict, then step.** Set the inputs, read the next state and FIRE off your own table
  and diagram, then step the demo and compare. Every disagreement is a row to fix.
- **Hunt the corners.** Lose the target from DETECT and from LOCK. Pickle from outside the
  envelope, with the master arm safe, and with both. Fire, then step once more.
- **Check your equations.** If you derive next-state and FIRE equations from your table,
  enter them in the **Student Logic** card and press **Test All Rows**. The demo checks them
  against the machine and lists the input combinations where they disagree, without telling
  you the right answer.
:::

**The two target-loss edges are part of the stated spec, and you are graded on producing a
correct diagram and table from it — loss edges included.** They must appear on your state
diagram, in your transition table, and in your code, and your instructor will ask you to
demonstrate both.

## The Machine You Will Build

### States and the Moore output

Three states, encoded in **two bits** — exactly the situation you set up at Lesson 25 and
in the Objective 2.8 reading, and with exactly the same leftover code:

| State | $Q_1 Q_0$ | The seeker is… | Telemetry on `DAC1` |
| --- | --- | --- | --- |
| **SEARCH** | `00` | scanning; nothing inside the detection gate | **0.8 V** |
| **DETECT** | `01` | tracking a target, not locked onto it | **1.6 V** |
| **LOCK** | `10` | holding the target, ready to be committed | **2.4 V** |
| *(illegal)* | `11` | never entered by design — see the guard below | — |

The weapons panel reads that voltage to know what the seeker is doing. It depends on the
state and on nothing else.

### Inputs, read once every 2 s tick

| Signal | Name | Where it comes from | It is **1** when |
| --- | --- | --- | --- |
| $D$ | target detected | your calibrated `distanceCm()` | $d \leq 12.0$ cm — the **detection gate** |
| $E$ | in engagement envelope | the same distance | $d \leq 6.0$ cm — the **engagement envelope** |
| $M$ | master arm | the arming plug on pin `2`, read `INPUT_PULLUP` | the plug is **inserted** (the pin reads LOW) |
| $L$ | lock command | `l` or `L` in the Serial Monitor | the key arrived since the last tick |
| $P$ | pickle — weapon release consent | `p` or `P` in the Serial Monitor | the key arrived since the last tick |

Three things about that table are worth a second look.

**The envelope sits inside the gate.** $6.0 \leq 12.0$, so $E$ true forces $D$ true. If your
status line ever shows `D=0 E=1`, your two thresholds are the wrong way round.

**The master arm is fail-safe by construction.** `INPUT_PULLUP` ties the pin HIGH through an
internal resistor, so an *empty socket reads HIGH*, which we define as SAFE. Inserting the
plug pulls the pin to GND — LOW — which is ARMED. A pulled plug, a broken wire, or a pin
you forgot to configure all read SAFE. The system fails toward not shooting. Wiring it the
other way round (jumper to $+3.3$ V for ARMED) would mean a **disconnected wire arms the
weapon**, which is why nothing real is wired that way.

**$L$ and $P$ are one-shots.** Keys you press between ticks sit in the serial receive
buffer until the next tick reads them. Each key sets its flag once; both flags are cleared
at the end of the tick that consumed them. Holding a key down does not hold the input high.

### Transitions — the requirements

You will produce the transition table yourself. Here is the behavior it must describe.
**The order of the checks inside each state is part of the specification** — write them as
`if` / `else if` in the order given, or the machine will do the wrong thing on the ticks
where two conditions are true at once.

**From SEARCH**

1. If $D$ — go to **DETECT**.
2. Otherwise stay in SEARCH.

Nothing else happens in SEARCH. A lock command with no target is not a transition.

**From DETECT**

1. If **not** $D$ — the target is lost. Go to **SEARCH**.
2. Else if $L$ — go to **LOCK**.
3. Else stay in DETECT.

Loss is tested *before* lock on purpose: **you cannot lock onto something you can no longer
see.**

**From LOCK**

1. If **not** $D$ — the target is lost. Break lock and go to **SEARCH**.
2. Else if $P$ **and** $E$ **and** $M$ — a valid weapon release. Assert **FIRE**, then go to
   **SEARCH**: the target has been serviced.
3. Else if $L$ — the operator has broken lock manually. Go back to **DETECT**; the target is
   still there.
4. Else stay in LOCK.

A pickle that fails an interlock — $P$ with $E$ false, or $P$ with $M$ false — is **not a
transition**. The machine stays in LOCK and says why (below).

**The illegal state.** Two bits hold four codes and you are using three, so `11` exists in
the hardware whether your design uses it or not. The starter sketch provides the guard that
forces any state that is not one of the three legal codes to **SEARCH**, and you must leave
it in place. It forces SEARCH specifically because SEARCH is the state farthest from a shot
and the only one that claims nothing about a target: **a corrupted state must fail safe.**

### Building your transition table

Build your table in the template workbook,
[ECE215_Project2_TransitionTable_Template.xlsx](../_static/ECE215_Project2_TransitionTable_Template.xlsx).
It holds one row per rule, in the shape below. Each input column takes `1` (the input must
be 1), `0` (it must be 0) or `x` (this row does not care). The first row is done to show the
format; every `?` is yours.

| # | Present state | $Q_1 Q_0$ | $D$ | $E$ | $M$ | $L$ | $P$ | Next state | $Q_1^+ Q_0^+$ | FIRE |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| 1 | SEARCH | `00` | 1 | x | x | x | x | DETECT | `01` | 0 |
| 2 | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
| 3 | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
| … | | | | | | | | | | |

You decide how many rows LOCK needs; that is the point of the exercise. Every row must have
a defined next state, and a state's rows must together cover every combination of the five
inputs, so that no combination leaves the machine without a rule.

Rows are tried **top to bottom**, and the **first match wins**, exactly like the `if` /
`else if` chain you write in Section 3. Write a row so that it excludes the rows above it
where that is natural: the DETECT lock row carries a `1` under $D$, not an `x`, so the row
says on its own that you lock only onto a target you can see. A LOCK row that comes after
the FIRE row does not have to spell out "not ($P \cdot E \cdot M$)". It applies only when
the FIRE row did not match, and that is exactly what your code does too.

The autograder reads your workbook the same way. A state and input combination that no row
covers is a **failure**, named by the state and the inputs. A row that can **never** match,
because the rows above it already cover every combination it claims, comes back as a
**note**.

### Outputs — one Moore, one Mealy

This is the distinction Quiz 7 asks you about, and your machine now carries **one of each**:

| Output | Kind | Depends on | Behavior |
| --- | --- | --- | --- |
| **Telemetry voltage** on `DAC1` | ? | ? | 0.8 V / 1.6 V / 2.4 V — one per state |
| **FIRE** | ? | ? | `*** MISSILE AWAY ***` on the Serial Monitor, and `LED_BUILTIN` strobes on that tick (10 flashes at 10 Hz) |

Discussion Question 1 asks you to justify these two classifications from the definitions and
from your code — fill the table in once you can.

FIRE is asserted only when **all four** of these hold at the same time: the machine is in
**LOCK**, the operator pressed **$P$**, the target is inside the envelope (**$E$**), and the
master arm plug is inserted (**$M$**).

A pickle in LOCK that fails an interlock prints a denial and changes nothing (the two checks run in priority order):

- in **LOCK**, with $P$ and $D$ and **not** $E$ → `NO FIRE -- OUTSIDE ENVELOPE`
- in **LOCK**, with $P$ and $D$ and **not** $M$ → `NO FIRE -- MASTER ARM SAFE`

The LOCK qualifier is load-bearing. A pickle in **DETECT**, with a target in front of the
sensor, the master arm inserted and the target inside the envelope, was never a candidate
for anything: the machine is not locked, so it must print no denial and must not fire. A
pickle typed in SEARCH with no target in sight stays silent too, but $D = 0$ already sees to
that; the DETECT case is the one that needs the qualifier. The autograder checks it, with a
pickle in DETECT while a target is present and a pickle on the tick a target first appears.

Check the **envelope first, then the master arm** — so a pickle with both interlocks open
reports the envelope. If you prefer the other order, that is fine, but then say so
explicitly, and be consistent across your diagram, your table, and your code.

**Both denials carry $D$**, and that is not decoration. A denial is a claim about a target
that is *still there*: "outside the envelope" only means something if there is something to
be outside it. On the tick a target disappears, $E$ goes false along with $D$, the machine
breaks lock to SEARCH — and it should say **nothing at all**, not complain about an envelope
it is no longer looking at. The starter hands your output function $D$ for exactly this.

### The status line

Every tick prints one line — your scope display:

```text
LOCK     d= 5.3 cm   D=1 E=1 ARM=1
```

You cannot debug a state machine whose state you cannot see. This line is provided; use it.

## Equipment

- **Arduino Due** and its **mini-USB cable** (the port labeled **USB Programming** — the middle of the three connectors on that edge — programs the board)
- **Sharp GP2Y0A51SK0F** distance sensor, wired white→`A0`, red→`5V`, black→`GND`
- **One jumper wire** for the master arm plug — pin `2` to `GND`
- **Two jumper wires** and a **digital multimeter** for the telemetry output — `DAC1` and `GND`
- A **flat target** you can move by hand, and a **ruler**
- **Your calibrated sketch from the Lesson 22 lab** — you need `CAL_K` and `CAL_B`

## Authorized Resources

Work in your **group of 2** only — not with cadets outside your group. You **may** use any
ECE 215/S course material from this semester, EI from ECE instructors, the Arduino website
([docs.arduino.cc/programming](https://docs.arduino.cc/programming/)), the starter sketch,
and internet resources. Internet resources must be **documented**.

You may use GenAI up to **Level 4** — co-create and revise, as defined in the AW GenAI
Policy. Note this is **looser than the Lesson 22 lab, which was Level 3**; check the policy
level per assignment rather than assuming a course default. You are responsible for
demonstrating understanding of anything you take from generative AI, and your instructor
will ask.

You may **not** use materials from previous semesters.

Document all collaboration, internet resources, and GenAI use in your submission.

## Part 1 — Wire the Two Deltas

Your sensor wiring from Lesson 22 does not change. Add two things to it.

1. **The master arm plug.** One jumper wire from digital pin **`2`** to any **`GND`** pin.
   Leave it *out* of the board to start with. `pinMode(2, INPUT_PULLUP)` is already in the
   starter sketch's `setup()`.
2. **The telemetry tap.** Put the DMM's **red** probe on **`DAC1`** and its **black** probe
   on **`GND`**, and set the meter to **DC volts**.

:::{admonition} `DAC1`, not `DAC0`, and not an analog input pin
:class: warning

`DAC1` is an **output**. Do not connect the sensor's white lead, the arming jumper, or
$+3.3$ V to it. The Due's pins are not 5 V tolerant, and the same rule that kept the sensor
safe at Lesson 22 applies here.
:::

**You should see** the DMM read about **0.55 V** the moment the sketch starts, before you
write anything — that is the DAC's floor, not zero. More on that below.

## Part 2 — Get the Starter Sketch Running

Open {download}`EngagementFSM_Starter.ino <../_static/EngagementFSM_Starter.ino>`. It is
laid out in five labeled sections:

| Section | Whose | What it holds |
| --- | --- | --- |
| **0 — CONFIG** | provided | pins, the 12.0 cm and 6.0 cm thresholds, the 2 s tick, the launch-indicator strobe (`FLASHES`, `FLASH_MS`), the ADC and DAC constants |
| **1 — PLUG IN** | **yours** | `CAL_K`, `CAL_B`, and the one line of `distanceCm()` |
| **2 — PLUMBING** | provided, do not modify | sensor read, serial one-shots, `masterArmed()`, `dacWriteVolts()`, `flashLaunchIndicator()`, `printStatus()`, the tick skeleton |
| **3 — TRANSITIONS** | **yours** | the `switch (state)` next-state logic |
| **4 — OUTPUTS** | **yours** | the Moore telemetry write and the Mealy FIRE |

**Do Section 1 first.** Copy `CAL_K` and `CAL_B` out of your Lesson 22 sketch and paste your
`distanceCm()` line back in. Until `CAL_K` is something other than `0.0` the sketch reports
`d= --- cm`, $D$ and $E$ are always 0, and the machine sits in SEARCH forever no matter
what you type — which looks exactly like broken state logic and is not.

**You should see** a line every 2 seconds, `SEARCH` with a real distance in it, and `D`
flipping to 1 when you bring the target inside 12 cm.

## Part 3 — Draw the Diagram, Then Build the Table

Do this before you write any state logic: the diagram on paper, the table in the workbook.

1. **Draw the state transition diagram.** Three bubbles with their `00`/`01`/`10` encodings
   and their telemetry voltages inside them, and one arrow for every rule in the
   requirements above — **including both target-loss edges**. FIRE is a Mealy output, so it
   goes **on its arrow**, not in a bubble.
2. **Fill in the transition table** in the template workbook, in the shape given above.
3. **Check the two together.** Every arrow on the diagram is a row in the table, and every
   row is an arrow. Walk each state and confirm that its conditions leave no input
   combination without a rule.

Debugging a table is far cheaper than debugging a program.

## Part 4 — Write the Transitions

Fill in the `switch (state)` in Section 3, one `case` at a time, in the priority order the
requirements give. Leave the illegal-state guard at the bottom alone.

Test each state as you go, using the status line and the fact that you control every input:

- **SEARCH → DETECT**: move the target inside 12 cm.
- **DETECT → SEARCH**: take it away again.
- **DETECT → LOCK**: type `'l'`.
- **LOCK → SEARCH**: take the target away while locked.
- **LOCK → DETECT**: type `'l'` again while locked, with the target still there.

**You should see** the state name in the status line change on the very next tick after the
input, and never change on a tick where no input changed.

## Part 5 — Write the Outputs

Fill in Section 4.

- **The Moore output**: call `dacWriteVolts()` with 0.8, 1.6, or 2.4 depending on the state,
  and confirm each one on the DMM. `dacWriteVolts()` already handles the Due's real output
  span for you — see Discussion Question 2 for why that mapping is not the obvious one.
- **The Mealy output**: when and only when all four conditions hold, print
  `*** MISSILE AWAY ***` and call `flashLaunchIndicator()`. That provided helper strobes
  `LED_BUILTIN` 10 times at 10 Hz (one second) inside the shot tick, and the tick still
  lasts 2 s. It is one call with no `else` branch: the LED stays dark on every tick that
  does not fire.
- **The two denials**: envelope first, then master arm.

**You should see** the DMM settle on a new voltage within one tick of every state change,
and the LED strobe on the shot tick and stay dark on every other tick.

## Part 6 — Rehearse the Demo

Run the script below end to end at least twice before you call your instructor over. It is
the same script you will be graded on, and it takes about a minute at a 2 s tick.

## The Demo Script

Your instructor will ask you to fly this engagement, and both of you should be able to
narrate what the machine is doing and why:

1. **Cold start.** Nothing in front of the sensor. Status reads `SEARCH`, DMM reads
   **0.8 V**, arming plug **out**.
2. **Acquire.** Bring the target in to about 10 cm. → **DETECT**, DMM **1.6 V**, status
   shows `D=1 E=0`.
3. **Lock.** Type `'l'`. → **LOCK**, DMM **2.4 V**.
4. **Refused pickle — SAFE.** With the plug still out, bring the target inside 6 cm so
   `E=1`, then type `'p'`. → `NO FIRE -- MASTER ARM SAFE`. Still LOCK, still 2.4 V.
5. **Arm.** Insert the arming plug. Status shows `ARM=1`. Nothing else changes.
6. **Refused pickle — outside the envelope.** Back the target out to about 10 cm so `E=0`,
   then type `'p'`. → `NO FIRE -- OUTSIDE ENVELOPE`. Still LOCK.
7. **Close and fire.** Bring the target back inside 6 cm and type `'p'`. →
   `*** MISSILE AWAY ***`, the LED strobes, and the machine returns itself to **SEARCH**.
   The DMM follows to 0.8 V **on the next tick** — the shot tick itself still reads 2.4 V
   (Moore).
8. **Target loss from DETECT.** Let the machine reacquire to DETECT, then wave the target
   away. → **SEARCH** on the next tick.
9. **Target loss from LOCK.** Reacquire, type `'l'` to get back to LOCK, then wave the target
   away. → **SEARCH**, break lock.

:::{admonition} After the shot, the machine reacquires — that is correct
:class: key-concept

At step 7 the target is still sitting in front of the sensor when the machine returns to
SEARCH, so the very next tick sees $D$ and moves it to DETECT. That is the machine doing
exactly what you told it to. Do not "fix" it. Be ready to explain it, because it is a good
question for your instructor to ask.
:::

## Discussion Questions

You answer these four **individually**, in their own Gradescope assignment, **Project 2
Discussion Questions**, not in your group's PDF; together they are the third project point.
They are printed here in full so you can read them ahead; Gradescope adds the answer
choices. Every answer is a multiple-choice pick or a number, and Gradescope grades each one
automatically.

**1. Moore, Mealy, or both?** Your machine carries two outputs: the **`DAC1` telemetry
voltage** and **FIRE**. Classify each one by the Objective 2.8 test, and check it against
your own Section 4: what does that output function actually need to be told? Each choice
pairs a classification with its justification, so you pick the one where both are right.

- **1.1** The `DAC1` telemetry voltage: Moore or Mealy, and why?
- **1.2** FIRE: Moore or Mealy, and why?

**2. What can the DAC actually put out?** The Due's DAC does **not** reach the rails: its
true output span is $\tfrac{1}{6}$ to $\tfrac{5}{6}$ of 3.3 V, or **0.55 V to 2.75 V**, and
`analogWrite()` defaults to **8-bit** resolution. The starter's `dacWriteVolts()`, provided
in Section 2, is what turns each voltage you ask for into a DAC code.

- **2.1** Compute the DAC's step size $\Delta V$ across that real span, in millivolts per
  step.
- **2.2** How many DAC steps separate adjacent telemetry voltages (0.8 V to 1.6 V, and
  1.6 V to 2.4 V)?
- **2.3** Suppose the design had specified 0.0 V / 1.0 V / 3.0 V for SEARCH, DETECT and LOCK
  instead, and Section 4 passed those three values to `dacWriteVolts()`. What would a DMM
  on `DAC1` read in the three states?

**3. What is one ADC count worth at the detection gate?** Use this calibration, not your
own, so that everyone works the same numbers: the sensor's datasheet fit to the Lesson 22
model $d = K/V + B$, with `CAL_K` = 6.20 cm·V and `CAL_B` = −0.75 cm. The Lesson 22 lab
gave you the Due's ADC step, $\Delta V = 3.22$ mV, and the detection gate is
$d = 12.0$ cm. You can get there either by evaluating $d = K/V + B$ at $V$ and again at
$V + \Delta V$ and subtracting, or by differentiating.

- **3.1** How many centimeters is one ADC count worth at $d = 12.0$ cm? Give the size of
  the step as a positive number.
- **3.2** The Lesson 22 lab held a calibration to $|\text{error}| \leq 0.5$ cm on held-out
  check points. With that much calibration bias allowed, which limits the accuracy of the
  detection decision more, **quantization** or **calibration bias**, and by roughly what
  factor?

**4. Why does the illegal state have to fail to SEARCH?** Two bits hold four codes and your
design uses three, so the code `11` exists in the hardware even though your design never
enters it. The starter's `nextState()` begins `int next = s;`, and its `switch` has a
`case` only for SEARCH, DETECT and LOCK, and no `default`; the provided guard at the
bottom then forces any other code to SEARCH. Suppose that guard were deleted and the
machine somehow ended up holding `11`.

- **4.1** What does a `nextState()` built this way do once the machine holds `11`?
- **4.2** Why does the guard force **SEARCH**, rather than DETECT or LOCK?

## Submission Requirements

This project is worth a total of **3 project points**.

- **(*1 Project Point*) Demonstrate your FSM and walk through your code** with your
  instructor. Each member of the group should expect to describe a part of the code. Your
  instructor will decide who is doing which parts of the walkthrough.
- **(*1 Project Point*) State transition diagram** and **corresponding state transition
  table**
- **(*1 Project Point*)** Answers to the four discussion questions, entered **individually**
  in the Gradescope assignment **Project 2 Discussion Questions**. Gradescope grades the 9
  parts automatically; each is worth one ninth of this point, so 6 of 9 earns two thirds of
  it, and your score is final: there is no correction step on the discussion questions.

Submit to the Gradescope programming assignment **Project 2**, once per group (add your
partner to the submission), with **three files**:

- **Your sketch**: the `.ino` file, as it runs on your board
- **Your transition table**: the completed template workbook (`.xlsx`)
- **One PDF** containing your **state transition diagram**, a **documentation statement**,
  and **both names**

*(Don't worry about a specific format for the PDF.)*

Gradescope runs an **autograder** on every submission. It runs your sketch in a simulation
of the board and reports on two things: whether your **sketch** flies the demo script and
the edge cases, and whether your **table** describes the machine and agrees with your code.
Read the report, fix what it finds, and resubmit as often as you like until the deadline.
It awards **no points by itself**: your instructor awards the first two project points above
and reads the report as evidence; the third comes from the discussion questions.

Then **each of you**, on your own, answers the four discussion questions in the Gradescope
assignment **Project 2 Discussion Questions**. That assignment is individual, not a group
submission, and your answers go there, not in the PDF.

**Check Gradescope for the exact deadline of each.**

## Submission Checklist

- [ ] Arming plug wired — jumper from pin `2` to `GND` — and the DMM on `DAC1` and `GND`
- [ ] `CAL_K` and `CAL_B` from the Lesson 22 lab plugged in and `distanceCm()` completed
- [ ] **State transition diagram** drawn — three states, **both target-loss edges**, FIRE on its arrow
- [ ] **Transition table** completed — every state against every input condition, in priority order
- [ ] Transitions written in Section 3, with the **illegal-state guard left in place**
- [ ] Moore telemetry verified on the DMM — 0.8 V, 1.6 V, 2.4 V
- [ ] Mealy FIRE verified — `MISSILE AWAY`, the LED strobe, and **both** refusal messages
- [ ] Both target-loss edges demonstrated — one from DETECT and one from LOCK
- [ ] Full demo script run for your instructor, **both partners** walking through code
- [ ] Documentation statement — collaboration, internet resources, and any GenAI use
- [ ] One PDF: the diagram, the documentation statement, **both names**
- [ ] **Group** submission to **Project 2** on Gradescope: `.ino`, `.xlsx`, PDF; autograder report read
- [ ] **Individual** submission to **Project 2 Discussion Questions** on Gradescope

## On to Block 3

You have now built the *decision* half of a fire-control system: given a range, when does
the machine call it a detection, and what is it allowed to do about it. Every one of those
decisions rested on a threshold, and every threshold rested on the calibration you fit at
Lesson 22.

Block 3 builds the other half — the **physics of the detection itself**. Where your $D$ was
a comparison against 12.0 cm, a radar's is a comparison of received signal against noise:
the radar range equation, signal-to-noise ratio, and the minimum detectable signal decide
whether there is anything to compare at all. And then electronic warfare attacks that
comparison directly — a jammer does not flip your $D$ bit, it raises the noise floor until
the seeker cannot honestly set it.

## Files

Starter sketch — {download}`EngagementFSM_Starter.ino <../_static/EngagementFSM_Starter.ino>`

Transition-table template — [ECE215_Project2_TransitionTable_Template.xlsx](../_static/ECE215_Project2_TransitionTable_Template.xlsx)

FSM Explorer, **Mealy · Fire Control Radar** tab —
<https://usafa-ece.org/apps/fsm-demo/>
