#include <FastLED.h>
#include <math.h> // Include math.h for sin() function
#define RINGS_LEDS 48
#define NUM_RING_LEDS 16 // Number of LEDs in the ring we're controlling
#define RING_LEDS_1 16
#define RING_LEDS_2 16
#define RING_LEDS_3 16
#define BLOW_RING_LEDS 16
#define BLOWER_PIN A3 // Use analog pin A3 as digital input
#define POTENTIOMETER_PIN A0
#define RINGS_LED_PIN 3
#define BLOW_RING_PIN 2
CRGB ringLeds[RINGS_LEDS];
CRGB blowRingLeds[BLOW_RING_LEDS];
// Variables for the LED noise effect
uint16_t noiseX = 0; // Coordinate in noise space
uint16_t noiseSpeed = 10; // Initial speed of the noise flow
// Variables for RPM calculation
volatile unsigned long revolutions = 0; // Volatile because it's modified in an ISR
unsigned long lastRPMTime = 0; // Time when RPM was last calculated
const unsigned long rpmInterval = 250; // RPM calculation interval in milliseconds
unsigned int rpm = 0; // Store calculated RPM
void setup() {
FastLED.addLeds<WS2811, RINGS_LED_PIN, BRG>(ringLeds, RINGS_LEDS);
FastLED.addLeds<WS2811, BLOW_RING_PIN, GRB>(blowRingLeds, BLOW_RING_LEDS);
Serial.begin(9600);
// Set BLOWER_PIN for input with pull-up (this makes it work as a digital pin)
//pinMode(BLOWER_PIN, INPUT_PULLUP);
pinMode(POTENTIOMETER_PIN, INPUT);
// Attach interrupt to count revolutions using BLOWER_PIN as a digital pin
//attachInterrupt(digitalPinToInterrupt(BLOWER_PIN), interruptFunction, RISING);
}
void loop() {
/*
unsigned long currentTime = millis();
// Calculate RPM every rpmInterval milliseconds without blocking
if (currentTime - lastRPMTime >= rpmInterval) {
// Calculate RPM based on the number of revolutions counted
unsigned long elapsedTime = currentTime - lastRPMTime;
lastRPMTime = currentTime; // Update lastRPMTime for the next interval
// Protect the revolutions count during read
noInterrupts();
unsigned long revs = revolutions;
revolutions = 0; // Reset the revolutions count
interrupts();
// Calculate RPM (revolutions per minute)
rpm = (revs * 60000) / elapsedTime; // Convert to RPM
// Debug output to the Serial monitor
Serial.print("RPM: ");
Serial.println(rpm);
// Map RPM to a suitable noise speed for LED effects
// Adjust the mapping range based on your expected RPM values
noiseSpeed = map(rpm, 0, 4000, 5, 50);
noiseSpeed = constrain(noiseSpeed, 5, 50); // Ensure noiseSpeed stays within bounds
}*/
noiseSpeed = map(rpm, 0, 4000, 5, 50);
noiseSpeed = constrain(noiseSpeed, 5, 50); // Ensure noiseSpeed stays within bounds
// Update the LED pattern based on the noise speed
EVERY_N_MILLISECONDS(30) {
fillNoise();
}
// Choose effect based on RPM
if (rpm == 0) {
updateSineEffect();
} else {
updateRotateEffect();
}
FastLED.show();
}
// Update the LEDs when RPM is 0
void updateSineEffect() {
float t = millis() / 1000.0; // Time in seconds
float frequency = 0.5; // Frequency in Hz (period of 2 seconds)
// Clear the first 12 LEDs
for (int i = 0; i < NUM_RING_LEDS; i++) {
blowRingLeds[i] = CRGB::Black;
}
for (int i = 0; i < 3; i++) {
int basePos = i * 5; // Base positions: 0, 4, 8
float phase = i * (TWO_PI / 3); // Phase offset for each LED
float sineValue = sin(TWO_PI * frequency * t); // Ranges from -1 to 1
// Map sineValue from -1..1 to 0..2
float offset = (sineValue + 1.0); // Ranges from 0 to 2
int intOffset = int(offset + 0.5); // Round to nearest integer (0, 1, 2)
int position = (basePos + intOffset) % NUM_RING_LEDS; // Ensure position within 0..11
blowRingLeds[position] = CRGB::Red; // Set to desired color
}
}
// Update the LEDs when RPM > 0
void updateRotateEffect() {
float t = millis() / 1000.0; // Time in seconds
// Calculate rotation speed based on RPM
float rotationSpeed = (rpm * 12.0) / 60.0; // Positions per second
int rotationPosition = int(t * rotationSpeed) % NUM_RING_LEDS;
// Clear the first 12 LEDs
for (int i = 0; i < NUM_RING_LEDS; i++) {
blowRingLeds[i] = CRGB::Black;
}
for (int i = 0; i < 3; i++) {
int basePos = i * 5; // Base positions: 0, 4, 8
int position = (basePos + rotationPosition) % NUM_RING_LEDS;
blowRingLeds[position] = CRGB(map(rpm, 0, 4000, 255, 0), 100, map(rpm, 0, 4000, 0, 255)); // Set to desired color
}
}
void fillNoise() {
for (int i = 0; i < RINGS_LEDS; i++) {
// Generate noise based on position in the array and time
uint8_t noiseValue = inoise8(i * 10, noiseX);
// Map the noise value to a color palette or brightness
ringLeds[i] = CHSV(noiseValue, 255, 255); // Use HSV for smooth color transitions
}
noiseX += noiseSpeed; // Move through noise space based on RPM
}
// Interrupt service routine (ISR) to count revolutions
void interruptFunction() {
revolutions++; // Increment revolutions each time the sensor is triggered
}