/* Week 2a (paired) — SENSOR -> FILTER -> ALERT pipeline. Wokwi, ST Nucleo-C031C6.
* Library Manager -> + Add -> "STM32duino FreeRTOS". Serial only (no wiring).
*
* SENSOR is PROVIDED and FIXED (below). You and your partner build FILTER and ALERT and,
* TOGETHER, design the queue that connects them. Fill in the Interface Agreement first.
*/
#include <STM32FreeRTOS.h>
#include "sensor_contract.h"
/* ==================== PROVIDED — SENSOR (do not change) ====================
* SENSOR posts a SensorSample_t on rawQ every 250 ms. The stream is realistic-but-messy:
* - normal readings, PLUS
* - REAL events you SHOULD alert on: a fever (temp ~38.6 C), a desat (SpO2 ~89 %)
* - SENSOR GLITCHES that are INVALID and must be rejected: temp 250 C, SpO2 0 %
* A good FILTER drops the glitches so ALERT only ever judges real, valid data.
*/
QueueHandle_t rawQ; // SENSOR -> FILTER (item size = sizeof(SensorSample_t))
static void SensorTask(void *pv) {
(void)pv; uint32_t seq = 0;
for (;;) {
seq++;
SensorSample_t s;
s.seq = seq; s.t_ms = seq * 250u;
s.temp_c = 37.0f;
s.spo2_pct = 98.0f;
s.hr_bpm = (uint16_t)(74 + (seq % 5));
if (seq % 11 == 0) s.temp_c = 38.6f; // REAL fever -> should alert
if (seq % 13 == 0) s.spo2_pct = 89.0f; // REAL desat -> should alert
if (seq % 7 == 0) s.temp_c = 250.0f; // GLITCH (invalid) -> FILTER should reject
if (seq % 17 == 0) s.spo2_pct = 0.0f; // GLITCH (invalid) -> FILTER should reject
xQueueSend(rawQ, &s, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(250));
}
}
/* TEMPORARY scaffold: prints the raw stream so you can SEE what SENSOR produces.
* DELETE this task AND its xTaskCreate in setup() once FILTER is consuming rawQ. */
static void RawPrinterTask(void *pv) {
(void)pv; SensorSample_t s;
for (;;) if (xQueueReceive(rawQ, &s, portMAX_DELAY) == pdTRUE) {
Serial.print("RAW seq="); Serial.print(s.seq);
Serial.print(" temp="); Serial.print(s.temp_c);
Serial.print(" spo2="); Serial.print(s.spo2_pct);
Serial.print(" hr="); Serial.println(s.hr_bpm);
}
}
/* ============ YOUR PAIR CONTRACT — design this TOGETHER ============
* Define the message FILTER produces and ALERT consumes, and the queue between you.
* Agree on field names, TYPES, UNITS, and MEANING before you write any task code.
*
* typedef struct {
* // ... your agreed fields ...
* } FilteredSample_t;
*
* QueueHandle_t filtQ; // FILTER -> ALERT
*/
/* ==================== STUDENT A — FILTER ====================
* Consume rawQ. Reject glitches (invalid readings). Optionally smooth. Send your
* FilteredSample_t on filtQ so ALERT only ever sees clean, valid data.
* Incorporate a yellow LED when data is thrown out.
* Make sure you share your .json with your partner.*/
/* ==================== STUDENT B — ALERT ====================
* Consume filtQ. Apply thresholds. Print the decision (OK / HIGH / CRITICAL).
* Suggested thresholds (you may change them): temp >= 38.0 -> HIGH, spo2 < 90 -> CRITICAL.
* Incorporate a red LED when an an Alert is triggered.
* Make sure you share your .json with your partner.*/
void setup() {
Serial.begin(115200);
rawQ = xQueueCreate(8, sizeof(SensorSample_t)); // provided
// TODO(pair): filtQ = xQueueCreate(8, sizeof(FilteredSample_t));
xTaskCreate(SensorTask, "SENSOR", 256, NULL, 2, NULL); // provided
xTaskCreate(RawPrinterTask, "RAW", 256, NULL, 1, NULL); // TEMP — delete once FILTER works
vTaskStartScheduler();
}
void loop() {}