Add GPIO12 startup/activity heartbeat LED behavior
This commit is contained in:
11
include/heartbeat.h
Normal file
11
include/heartbeat.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef HEARTBEAT_H
|
||||
#define HEARTBEAT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void setupHeartbeat();
|
||||
void startupHeartbeatBlink(uint8_t count = 5);
|
||||
void triggerHeartbeatBlink();
|
||||
void updateHeartbeat();
|
||||
|
||||
#endif
|
||||
71
src/heartbeat.cpp
Normal file
71
src/heartbeat.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <Arduino.h>
|
||||
#include "heartbeat.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t HEARTBEAT_PIN = 12;
|
||||
constexpr uint16_t STARTUP_ON_MS = 120;
|
||||
constexpr uint16_t STARTUP_OFF_MS = 120;
|
||||
constexpr uint16_t ACTIVITY_ON_MS = 45;
|
||||
constexpr uint16_t ACTIVITY_OFF_MS = 70;
|
||||
constexpr uint16_t TRIGGER_THROTTLE_MS = 35;
|
||||
constexpr uint8_t MAX_PENDING_BLINKS = 6;
|
||||
|
||||
uint8_t pendingBlinks = 0;
|
||||
uint32_t phaseStartMs = 0;
|
||||
uint32_t lastTriggerMs = 0;
|
||||
bool ledOn = false;
|
||||
}
|
||||
|
||||
void setupHeartbeat() {
|
||||
pinMode(HEARTBEAT_PIN, OUTPUT);
|
||||
digitalWrite(HEARTBEAT_PIN, LOW);
|
||||
ledOn = false;
|
||||
phaseStartMs = millis();
|
||||
}
|
||||
|
||||
void startupHeartbeatBlink(uint8_t count) {
|
||||
for (uint8_t i = 0; i < count; ++i) {
|
||||
digitalWrite(HEARTBEAT_PIN, HIGH);
|
||||
delay(STARTUP_ON_MS);
|
||||
digitalWrite(HEARTBEAT_PIN, LOW);
|
||||
delay(STARTUP_OFF_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void triggerHeartbeatBlink() {
|
||||
const uint32_t now = millis();
|
||||
if (now - lastTriggerMs < TRIGGER_THROTTLE_MS) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastTriggerMs = now;
|
||||
if (pendingBlinks < MAX_PENDING_BLINKS) {
|
||||
pendingBlinks++;
|
||||
}
|
||||
}
|
||||
|
||||
void updateHeartbeat() {
|
||||
const uint32_t now = millis();
|
||||
|
||||
if (pendingBlinks == 0) {
|
||||
if (ledOn) {
|
||||
ledOn = false;
|
||||
digitalWrite(HEARTBEAT_PIN, LOW);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ledOn && (now - phaseStartMs >= ACTIVITY_OFF_MS)) {
|
||||
ledOn = true;
|
||||
phaseStartMs = now;
|
||||
digitalWrite(HEARTBEAT_PIN, HIGH);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ledOn && (now - phaseStartMs >= ACTIVITY_ON_MS)) {
|
||||
ledOn = false;
|
||||
phaseStartMs = now;
|
||||
digitalWrite(HEARTBEAT_PIN, LOW);
|
||||
pendingBlinks--;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include "config.h"
|
||||
#include "heartbeat.h"
|
||||
#include "motor.h"
|
||||
#include "webserver.h"
|
||||
|
||||
@@ -36,6 +37,9 @@ void setupWiFi() {
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
|
||||
setupHeartbeat();
|
||||
startupHeartbeatBlink(5);
|
||||
|
||||
Serial.println("\n=============================");
|
||||
Serial.println(" Dual BTS7960 Motor Controller");
|
||||
@@ -61,5 +65,6 @@ void loop() {
|
||||
handleWebServer();
|
||||
motor1.update(); // Update current sensing and logging for motor 1
|
||||
motor2.update(); // Update current sensing and logging for motor 2
|
||||
updateHeartbeat();
|
||||
delay(1);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#include <Arduino.h>
|
||||
#include <WebServer.h>
|
||||
#include "heartbeat.h"
|
||||
#include "motor.h"
|
||||
#include "config.h"
|
||||
|
||||
WebServer server(HTTP_PORT);
|
||||
|
||||
static void sendWithHeartbeat(int code, const char* contentType, const String& content) {
|
||||
triggerHeartbeatBlink();
|
||||
server.send(code, contentType, content);
|
||||
}
|
||||
|
||||
const char index_html[] PROGMEM = R"rawliteral(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -585,74 +591,74 @@ void handleRoot() {
|
||||
|
||||
void handleMotor1Drive() {
|
||||
if (!server.hasArg("value")) {
|
||||
server.send(400, "text/plain", "Missing value");
|
||||
sendWithHeartbeat(400, "text/plain", "Missing value");
|
||||
return;
|
||||
}
|
||||
|
||||
applyDriveValue(motor1, server.arg("value").toInt());
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
}
|
||||
|
||||
void handleMotor2Drive() {
|
||||
if (!server.hasArg("value")) {
|
||||
server.send(400, "text/plain", "Missing value");
|
||||
sendWithHeartbeat(400, "text/plain", "Missing value");
|
||||
return;
|
||||
}
|
||||
|
||||
applyDriveValue(motor2, server.arg("value").toInt());
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
}
|
||||
|
||||
void handleMotor1Speed() {
|
||||
if (server.hasArg("value")) {
|
||||
motor1.setSpeed(server.arg("value").toInt());
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
} else {
|
||||
server.send(400, "text/plain", "Missing value");
|
||||
sendWithHeartbeat(400, "text/plain", "Missing value");
|
||||
}
|
||||
}
|
||||
|
||||
void handleMotor1Direction() {
|
||||
if (server.hasArg("value")) {
|
||||
motor1.setDirection(server.arg("value").toInt());
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
} else {
|
||||
server.send(400, "text/plain", "Missing value");
|
||||
sendWithHeartbeat(400, "text/plain", "Missing value");
|
||||
}
|
||||
}
|
||||
|
||||
void handleMotor1Stop() {
|
||||
motor1.stop();
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
}
|
||||
|
||||
void handleMotor2Speed() {
|
||||
if (server.hasArg("value")) {
|
||||
motor2.setSpeed(server.arg("value").toInt());
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
} else {
|
||||
server.send(400, "text/plain", "Missing value");
|
||||
sendWithHeartbeat(400, "text/plain", "Missing value");
|
||||
}
|
||||
}
|
||||
|
||||
void handleMotor2Direction() {
|
||||
if (server.hasArg("value")) {
|
||||
motor2.setDirection(server.arg("value").toInt());
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
} else {
|
||||
server.send(400, "text/plain", "Missing value");
|
||||
sendWithHeartbeat(400, "text/plain", "Missing value");
|
||||
}
|
||||
}
|
||||
|
||||
void handleMotor2Stop() {
|
||||
motor2.stop();
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
}
|
||||
|
||||
void handleStop() {
|
||||
motor1.stop();
|
||||
motor2.stop();
|
||||
server.send(200, "text/plain", "OK");
|
||||
sendWithHeartbeat(200, "text/plain", "OK");
|
||||
}
|
||||
|
||||
void handleSpeed() {
|
||||
|
||||
Reference in New Issue
Block a user