// Lab Task 2 – UART Communication
// --- Pin definitions ---
const uint8_t LED_PIN = 28; // GP28 – external LED
const uint8_t POTI_PIN = 26; // GP26 – potentiometer (ADC0)
const uint8_t LED_BUILTIN_PIN = 25; // GP25 – onboard LED (heartbeat)
// --- State ---
bool ledState = false;
bool blinkMode = false;
uint16_t blinkInterval = 500;
uint32_t lastBlinkTime = 0;
bool blinkLedState = false;
// --- Heartbeat ---
uint32_t lastHeartbeatTime = 0;
const uint16_t HEARTBEAT_INTERVAL = 500;
void setup() {
Serial1.begin(115200); // UART0 – matches Wokwi Serial Monitor
Serial1.setTimeout(100); // prevents blocking on readStringUntil
pinMode(LED_PIN, OUTPUT);
pinMode(LED_BUILTIN_PIN, OUTPUT);
// NOTE: no pinMode for POTI_PIN – ADC pins must not be set to INPUT
digitalWrite(LED_PIN, LOW);
digitalWrite(LED_BUILTIN_PIN, LOW);
Serial1.println("UART Command Protocol Ready");
Serial1.println("Commands: ON, OFF, BLINK, NOBLINK, STATUS");
}
void loop() {
updateHeartbeat();
updateBlinkInterval();
if (blinkMode) updateBlink();
parseSerialCommands();
}
// --- Heartbeat ---
// Toggles onboard LED every 500 ms as a permanent sign of life
void updateHeartbeat() {
uint32_t now = millis();
if (now - lastHeartbeatTime >= HEARTBEAT_INTERVAL) {
lastHeartbeatTime = now;
digitalWrite(LED_BUILTIN_PIN, !digitalRead(LED_BUILTIN_PIN));
}
}
// --- Potentiometer -> blink interval ---
void updateBlinkInterval() {
static uint32_t lastRead = 0;
uint32_t now = millis();
if (now - lastRead < 100) return;
lastRead = now;
uint16_t potiValue = analogRead(POTI_PIN);
blinkInterval = 50 + (potiValue * 950UL) / 4095;
}
// --- Non-blocking blink ---
// Toggles external LED at current blinkInterval when blink mode is active
void updateBlink() {
uint32_t now = millis();
if (now - lastBlinkTime >= blinkInterval) {
lastBlinkTime = now;
blinkLedState = !blinkLedState;
digitalWrite(LED_PIN, blinkLedState ? HIGH : LOW);
ledState = blinkLedState;
}
}
// --- Serial command parser ---
// Reads line from Serial Monitor and executes matching command
void parseSerialCommands() {
if (Serial1.available()) {
String command = Serial1.readStringUntil('\n');
command.trim();
command.toUpperCase();
if (command == "ON") {
blinkMode = false;
ledState = true;
digitalWrite(LED_PIN, HIGH);
Serial1.println("ACK:ON");
}
else if (command == "OFF") {
blinkMode = false;
ledState = false;
digitalWrite(LED_PIN, LOW);
Serial1.println("ACK:OFF");
}
else if (command == "BLINK") {
blinkMode = true;
lastBlinkTime = millis();
blinkLedState = false;
Serial1.println("ACK:BLINK");
}
else if (command == "NOBLINK") {
blinkMode = false;
ledState = false;
digitalWrite(LED_PIN, LOW);
Serial1.println("ACK:NOBLINK");
}
else if (command == "STATUS") {
String status = "STATUS: LED=";
status += (ledState ? "ON" : "OFF");
if (blinkMode) {
status += " BLINKING@";
status += blinkInterval;
status += "ms";
}
Serial1.println(status);
}
else {
Serial1.print("ERROR: Unknown command '");
Serial1.print(command);
Serial1.println("'");
}
}
}