1

I'm trying to get a strip of Neopixels to circle through its length, one LED at a time, I want it to do it faster as the value received from the sensor increases

#include <FastLED.h>
#define NUM_LEDS    34
#define DATA_PIN    6
#define SENSOR_PIN  A0

int airPressure,
    barometricToRGB,
    frequency       = 0,
    high            = 0,
    low             = 600,
    interval        = 50;

long previousMillis = 0;

CRGB leds[NUM_LEDS];

void setup() {
  Serial.begin(115200);
  pinMode(SENSOR_PIN,INPUT);  
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop() {
  airPressure = analogRead(SENSOR_PIN);
  autoTune();

  unsigned long currentMillis = millis();
  Serial.print("frequency ");
  Serial.println(frequency);
  Serial.print("Time to beat ");
  Serial.println(frequency*interval);
  Serial.print("Last Called ");
  Serial.println(currentMillis - previousMillis);

  if(currentMillis - previousMillis > (frequency/interval)) {
    previousMillis = currentMillis;

    for (int i=0; i<NUM_LEDS; i++) {
          leds[i].setRGB( barometricToRGB, 68, 255/barometricToRGB);
          FastLED.show();
        }
  }
}

void autoTune() {
  if (airPressure < low) {
    low = airPressure;
  }
  if (airPressure > high) {
    high = airPressure;
  }
  barometricToRGB = map(airPressure, low, high, 1, 255);
  barometricToRGB = constrain(barometricToRGB, 1, 255);
  frequency = map(airPressure, low, high, 1, 100);
  frequency = constrain(frequency, 1, 100);

}

While I had managed to cause the color to change based on the sensor, I can't seem to understand how to control how fast it will go, every how long.

1
  • 1
    Can you copy and paste the code into the question please? It isn't long.
    – Nick Gammon
    Commented Oct 2, 2015 at 0:43

2 Answers 2

2

Ok, if I understood what you meant, you want that a single led in the ring is on and the refresh rate is dependent on the pressure, right?

If so, you did not write any "select this led" code, so it can't work.

I fixed a couple of things in your code. Mainly:

  1. added the circularity to the ring (with variable currentlyOnLed)
  2. fixed some types (use the byte unless you need a bigger type)
  3. removed some constrains, which were reduntant
  4. frequency*interval instead of frequency/interval (I guess it was a typo)
  5. I prefer summing the step instead of setting previousMillis to currentMillis, so you will not add error with time passing
  6. moved FastLED.show() outside the loop: I'm not sure about this, but I think that you don't need to call it every loop. I can't test it, anyway.

So, here is the fixed code. Let us know if it works for you

#include <FastLED.h>
#define NUM_LEDS    34
#define DATA_PIN    6
#define SENSOR_PIN  A0

int airPressure;
int high  = 0;
int low   = 600;
byte barometricToRGB;
int frequency = 0;
byte interval = 50;
byte currentlyOnLed;

long previousMillis = 0;

CRGB leds[NUM_LEDS];

void setup() {
    Serial.begin(115200);
    pinMode(SENSOR_PIN,INPUT);  
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
    currentlyOnLed = 0;
}

void loop() {
    airPressure = analogRead(SENSOR_PIN);
    autoTune();

    unsigned long currentMillis = millis();
    Serial.print("frequency ");
    Serial.println(frequency);
    Serial.print("Time to beat ");
    Serial.println(frequency*interval);
    Serial.print("Last Called ");
    Serial.println(currentMillis - previousMillis);

    if(currentMillis - previousMillis > (frequency*interval)) {
        previousMillis += (frequency*interval);

        //Set next on led
        if (currentlyOnLed >= NUM_LEDS - 1)
            currentlyOnLed = 0;
        else
            currentlyOnLed++;

        for (byte i=0; i<NUM_LEDS; i++) {
            if (i == currentlyOnLed)
                leds[i].setRGB( barometricToRGB, 68, 255/barometricToRGB);
            else
                leds[i] = CRGB::Black;
        }
        FastLED.show();
    }
}

void autoTune() {
    airPressure = constrain(airPressure, low, high);
    barometricToRGB = map(airPressure, low, high, 1, 255);
    frequency = map(airPressure, low, high, 1, 100);
}
2
  • That's amazing! This is very thorough, and thoughtful. Thank you so much
    – Nir Benita
    Commented Dec 1, 2015 at 16:01
  • You are welcome ;) and... I don't know if it is you or someone else who needs to accept the edits in the original post. I just added the code (so it was cleaner and, moreover, links can break)
    – frarugi87
    Commented Dec 1, 2015 at 17:27
1

Are these reversed?

high            = 0,
low             = 600,

It looks like high and low both get set to airPressure on the first pass through autoTune(). If the pressure drops after this, for example, low will track airPressure and high will stay the same.

Also, with frequency 1 to 100 and interval 50 the largest time difference is 2 milliseconds and the smallest is 0. Your loop could be taking 2 ms without the if statement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.