Skip to main content

Servo Profile Helmet

This example focuses on the 0.4.0 servo/profile workflow used by configurable helmet firmware.

Use this pattern when different helmets use the same firmware but need different servo positions, GPIO pins or lighting values.

Sketch Core

#include <ArmorLink.h>

ArmorLinkModule module(
"Helmet",
ArmorLinkModuleType::Helmet
);

struct HelmetConfig {
int servoCount = 2;
int openingDurationMs = 700;
int closingDurationMs = 700;
ArmorLinkServoConfig servo1{16, 10, 158, 500, 2400};
ArmorLinkServoConfig servo2{26, 170, 22, 500, 2400};
ArmorLinkServoConfig servo3{-1, 90, 90, 500, 2400};
};

HelmetConfig config;

void setup()
{
Serial.begin(115200);

module.profileTarget("muehliindustries.armorlink.helmet.v1");
module.profileName("Generic Two Servo Helmet");

module.config().addInt("servoCount", &config.servoCount, 2)
.label("Servo Count")
.section("Faceplate")
.rebootRequired()
.range(2, 3)
.step(1);

module.config().addInt("openingDurationMs", &config.openingDurationMs, 700)
.label("Opening Duration")
.section("Faceplate")
.semantic("servo.openingDuration")
.semanticGroup("faceplate")
.range(100, 5000)
.step(50);

module.config().addInt("closingDurationMs", &config.closingDurationMs, 700)
.label("Closing Duration")
.section("Faceplate")
.semantic("servo.closingDuration")
.semanticGroup("faceplate")
.range(100, 5000)
.step(50);

module.config()
.addServoConfig("servo1", &config.servo1)
.section("Servo 1")
.gpio(16)
.openPosition(10)
.closedPosition(158)
.pulseRange(500, 2400);

module.config()
.addServoConfig("servo2", &config.servo2)
.section("Servo 2")
.gpio(26)
.openPosition(170)
.closedPosition(22)
.pulseRange(500, 2400);

module.config()
.addServoConfig("servo3", &config.servo3)
.section("Servo 3")
.visibleWhen("servoCount", 3)
.gpio(-1)
.openPosition(90)
.closedPosition(90)
.pulseRange(500, 2400);

ArmorLinkOptions options;
options.nodeName = "Helmet";
options.enableGateway = true;
options.enableBle = true;
options.enableEspNow = true;
options.enableSerialCommands = true;
options.bleName = "ArmorLink Helmet";

ArmorLink.begin(module, options);
}

void loop()
{
ArmorLink.loop();
}

Why This Matters

The descriptor contains a stable profileTarget and servo semantic metadata. Setup tools can use this to:

  • Browse compatible helmet profiles.
  • Import known servo values.
  • Save a tuned setup as a profile.
  • Test servo positions through Web Serial.

Servo Safety

Start with unloaded servos or conservative positions. Confirm direction and travel before attaching the full faceplate mechanism.