star strek tos enterprise Bussard parts
Print Profile(0)
Description
this is designed for the gambody enterprise model at 150%
the led ring is a ws2812 ring with 12 leds. easy to find on amazon etc. outer 50mm inner 36mm.
the arduino sketch i use is:
#include <FastLED.h>
// ---------- CONFIG ----------
#define LED_PIN 6
#define NUM_LEDS 12
#define LED_TYPE WS2812
#define COLOR_ORDER GRB // change to RGB if green looks wrong
// Global breathing brightness (applies to everything)
#define BRIGHT_MIN 150
#define BRIGHT_MAX 200
#define PULSE_MS 24
// Smooth rotation speed (higher = faster)
#define SPEED_LEDS_PER_SEC 12.0f // try 2.0..8.0 for slower/faster
// Frame rate control (how often we redraw). Lower = smoother (but more CPU)
#define FRAME_MS 15 // ~66 FPS
// -------- Per-color brightness (0-255) --------
#define CORE_BASE_SCALE 255
#define HOTSPOT_SCALE 255
#define GAP_SCALE 0 // 0 = OFF, >0 = faint ember glow
#define BLUE_SCALE 5
#define GREEN_SCALE 10
#define PINK_SCALE 20
#define CYAN_SCALE 5
#define PURPLE_SCALE 10
#define AMBER_SCALE 20
// ---------------------------------------------
// ---------------------------
CRGB leds[NUM_LEDS];
const CRGB coreRedOrange[6] = {
CRGB(255, 8, 0), // very hot red
CRGB(255, 3, 0), // deep red-orange
CRGB(235, 6, 0), // ember red
CRGB(220, 0, 0), // deep red glow
CRGB(255, 10, 1), // warm red ember
CRGB(200, 0, 0) // dark red
};
// Fixed accents for LEDs 1,3,5,7,9,11 (in order)
const CRGB accentFixed[6] = {
CRGB(0, 120, 255), // blue
CRGB(0, 255, 0), // green
CRGB(255, 0, 140), // pink
CRGB(0, 180, 255), // cyan
CRGB(180, 0, 255), // purple
CRGB(255, 190, 0) // amber
};
int bright = BRIGHT_MIN;
int brightStep = 1;
uint32_t lastPulse = 0;
uint32_t lastFrame = 0;
float hotspotPosF = 0.0f; // smooth position (0..NUM_LEDS)
uint8_t paletteOffset = 0;
static CRGB scale8(CRGB c, uint8_t s) {
c.nscale8_video(s);
return c;
}
void renderBasePattern() {
// Even LEDs = base orange/red (scaled)
for (uint8_t k = 0; k < 6; k++) {
leds[k * 2] = scale8(coreRedOrange[k], CORE_BASE_SCALE);
}
// Odd LEDs = fixed accents with individual scales
for (uint8_t k = 0; k < 6; k++) {
uint8_t ledIndex = (k * 2) + 1;
switch (k) {
case 0: leds[ledIndex] = scale8(accentFixed[k], BLUE_SCALE); break;
case 1: leds[ledIndex] = scale8(accentFixed[k], GREEN_SCALE); break;
case 2: leds[ledIndex] = scale8(accentFixed[k], PINK_SCALE); break;
case 3: leds[ledIndex] = scale8(accentFixed[k], CYAN_SCALE); break;
case 4: leds[ledIndex] = scale8(accentFixed[k], PURPLE_SCALE); break;
case 5: leds[ledIndex] = scale8(accentFixed[k], AMBER_SCALE); break;
}
}
}
void applyFourHotspotsWithSmoothGap(float posF) {
// We create 4 hotspots evenly spaced around the ring: +3, +6, +9
// Each hotspot is blended between two LEDs for smooth motion.
for (uint8_t i = 0; i < 4; i++) {
float p = posF + (float)(i * 3);
while (p >= NUM_LEDS) p -= NUM_LEDS;
uint8_t idxA = (uint8_t)p; // floor
uint8_t idxB = (idxA + 1) % NUM_LEDS; // next LED
float frac = p - (float)idxA; // 0..1
uint8_t wB = (uint8_t)(frac * 255.0f); // weight for B
uint8_t wA = 255 - wB; // weight for A
CRGB hot = scale8(coreRedOrange[(paletteOffset + i) % 6], HOTSPOT_SCALE);
// Add blended hotspot (overrides feel: we add strongly on top of base)
leds[idxA] += scale8(hot, wA);
leds[idxB] += scale8(hot, wB);
// Gap: one LED AFTER the hotspot direction. We approximate by forcing the
// nearest "after" LED to black (or ember) to keep the look.
// Choose the dominant LED (where hotspot mostly is).
uint8_t dom = (wA >= wB) ? idxA : idxB;
uint8_t gapIdx = (dom + 1) % NUM_LEDS;
if (GAP_SCALE == 0) {
leds[gapIdx] = CRGB::Black;
} else {
leds[gapIdx] = scale8(CRGB(80, 5, 0), GAP_SCALE);
}
}
}
void setup() {
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(bright);
FastLED.clear(true);
}
void loop() {
const uint32_t now = millis();
// Breathing brightness (global)
if (now - lastPulse >= PULSE_MS) {
lastPulse = now;
bright += brightStep;
if (bright >= BRIGHT_MAX) { bright = BRIGHT_MAX; brightStep = -1; }
if (bright <= BRIGHT_MIN) { bright = BRIGHT_MIN; brightStep = 1; }
FastLED.setBrightness(bright);
}
// Frame update for smooth motion
if (now - lastFrame >= FRAME_MS) {
float dt = (now - lastFrame) / 1000.0f;
lastFrame = now;
// Move smoothly
hotspotPosF += SPEED_LEDS_PER_SEC * dt;
while (hotspotPosF >= NUM_LEDS) {
hotspotPosF -= NUM_LEDS;
// Advance palette once per full revolution (optional but feels nice)
paletteOffset = (paletteOffset + 1) % 6;
}
// Render
renderBasePattern();
applyFourHotspotsWithSmoothGap(hotspotPosF);
FastLED.show();
}
}










Comment & Rating (0)