Controlling LEDs with distance criteria

I've managed to splice together a sketch where gps calculates the distance to the location I set and when distance criteria is met, the simple 5mm led turns on. The way the led is activated is with simple digitalWrite.

            if (shortestDist < 2)  //meters 
            {
              digitalWrite(ledPin, HIGH);
            }

            else
            {                  
              digitalWrite(ledPin, LOW);
            }

However, I want to use a small neopixel strip (7 leds) that would progressively light up and change color depending on distance criteria, I would like to have 3 of them not just one.
Distance 1 = 8m
Distance 2 = 4m
Distance 3 = 2m

And the behavior of the strip could be something along the lines of
Distance 1 criteria met - first 2 leds are on
Distance 2 - 2 more leds are on
Distance 3 - all leds

And naturally if distance is increasing then they turn off by the same pattern, backwards :smiley:

I tried the hack approach and I think it works but perhaps someone can assist me to clean this code up a bit?

            if (shortestDist > 8)   
            {
              pixels.clear();
              pixels.setPixelColor(0, pixels.Color(0, 0, 0));
              pixels.setPixelColor(1, pixels.Color(0, 0, 0));
              pixels.setPixelColor(2, pixels.Color(0, 0, 0));
              pixels.setPixelColor(3, pixels.Color(0, 0, 0));
              pixels.setPixelColor(4, pixels.Color(0, 0, 0));
              pixels.setPixelColor(5, pixels.Color(0, 0, 0));
              pixels.setPixelColor(6, pixels.Color(0, 0, 0));
              pixels.show(); 
            }

            else if (shortestDist < 8)
            {                  
              pixels.clear();
              pixels.setPixelColor(0, pixels.Color(0, 250, 0));
              pixels.setPixelColor(1, pixels.Color(0, 250, 0));
              pixels.setPixelColor(2, pixels.Color(0, 0, 0));
              pixels.setPixelColor(3, pixels.Color(0, 0, 0));
              pixels.setPixelColor(4, pixels.Color(0, 0, 0));
              pixels.setPixelColor(5, pixels.Color(0, 0, 0));
              pixels.setPixelColor(6, pixels.Color(0, 0, 0));
              pixels.show(); 
            }  

            else if (shortestDist < 4)
            {                  
              pixels.clear();
              pixels.setPixelColor(0, pixels.Color(0, 250, 0));
              pixels.setPixelColor(1, pixels.Color(0, 250, 0));
              pixels.setPixelColor(2, pixels.Color(0, 250, 0));
              pixels.setPixelColor(3, pixels.Color(0, 250, 0));
              pixels.setPixelColor(4, pixels.Color(0, 0, 0));
              pixels.setPixelColor(5, pixels.Color(0, 0, 0));
              pixels.setPixelColor(6, pixels.Color(0, 0, 0));
              pixels.show(); 
            }

I didn't paste the last else if but I'm sure you get the gist of what I've done. Pretty sure it could be done better, more elegant or "clean" so to speak, anyone with the time to help me out, thank you in advance :smiley:

you should post your complete sketch
How should somebody else compile your code if you just provide some snippets?

Might think about using a loop for this type of stuff...

for (x = 0; x < 7; ++x)
   pixels.setPixelColor(x, pixels.Color(0, 0, 0));

You really need to post all of the code... it allows us to compile it and/or other questions you might have.

:smiley_cat:

Sorry, didn't want to paste all the tower of code here, here it is - https://pastebin.com/dwy2cMiM

The header files don't need to be expanded, so that's not a problem..

Use the 'tag' icon (</>) and paste the code within it.

:smiley_cat:

almost no user will download external code as this external code or the external website CAN be malicious

Do the tests in the opposite order. If you test for <8 first you will never execute <4 or <2 because they are also <8.

            if (shortestDist < 2)
            else if (shortestDist < 4)
            else if (shortestDist < 8)
            else 
1 Like

This codeversion does switch on / off all 7 LEDs depending on the value of distance
inside a single loop.

I don'thave Nepoixel atm so pixel-object outcommented
Code has serial output instead to show the principle how it works

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// Take it for granted at the moment scroll down to void setup
// start of macros dbg and dbgi
#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
// print only once when value has changed
#define dbgc(myFixedText, variableName) \
  do { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  } while (false);
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *


//#include
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 2;

int myDistance = 10;

void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}


void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();
}


void distanceToPixels(int p_distance) {
  //pixels.clear();
  for (byte i = 0; i < 7; i++) {
    dbg("for:",i);
    if (i < p_distance) {
      //pixels.setPixelColor(i, pixels.Color(0, 0, 0) );
    }
    else {
      //pixels.setPixelColor(i, pixels.Color(0, 250, 0) );
      Serial.print("Pixel No ");
      Serial.print(i);
      Serial.print("switched on");
    }
  }
  //pixels.show();
}

void loop() {
  BlinkHeartBeatLED(OnBoard_LED, 250);
  dbgi("1",myDistance,1000);
  if ( TimePeriodIsOver(MyTestTimer, 3000) ) {
    myDistance--;
    distanceToPixels(myDistance);
  }
}

best regards Stefan

This seems to be working properly! I had my "ifs" ordered the wrong way around and when the smallest distance criteria was met, the leds would blink in sync to what I presume is millis, perhaps had to do with the way I ordered the distances.

Using your example this works now. The only thing that's not clear is how to shorthand the LED strip setup.

For instance, when this distance is valid;

            if (shortestDist < 10)   
            {
              pixels.show();
              pixels.setPixelColor(0, pixels.Color(0, 250, 0));
              pixels.setPixelColor(1, pixels.Color(250, 0, 0));
              pixels.setPixelColor(2, pixels.Color(0, 0, 250));
              pixels.setPixelColor(3, pixels.Color(0, 250, 0));
              pixels.setPixelColor(4, pixels.Color(0, 0, 250));
              pixels.setPixelColor(5, pixels.Color(250, 0, 0));
              pixels.setPixelColor(6, pixels.Color(0, 250, 0));
            }

I'd like to have this bit more compact, so to speak. How would I achieve it, to use one line of code here that would call up this specific setup on the led strip?

            if (shortestDist < 10)   
            {
              pixels.show();
              pixels-preset1
            }

Something like this. I presume I should have some kind of rule applies in void setup?

const uint32_t Black = pixels.Color(0, 0, 0);
const uint32_t Red   = pixels.Color(250, 0, 0);
const uint32_t Green = pixels.Color(0, 250, 0);
const uint32_t Blue  = pixels.Color(0, 0, 250);

uint32_t presets[][7] = {
{Black, Black, Black, Black, Black, Black, Black),
{Blue, Black, Black, Black, Black, Black, Black),
{Green, Black, Black, Black, Black, Black, Black),
{Red, Black, Black, Black, Black, Black, Black),
{Red, Blue, Black, Black, Black, Black, Black),
{Red, Green, Black, Black, Black, Black, Black),
{Red, Red, Black, Black, Black, Black, Black),
};

Then you can use a loop to copy the presets to the pixels:

   for (int i=0; i<7; i++)
     pixels.setPixelColor(i, presets[n][i]);
1 Like

it should be possible even shorter by an if-condition

void distanceToPixels(int p_distance) {
  pixels.clear();
  for (byte i = 0; i < 7; i++) {

    if (i < p_distance) {
      pixels.setPixelColor(i, pixels.Color(0, 0, 0) );
    }
    else {
      pixels.setPixelColor(i, pixels.Color(0, 250, 0) );
      Serial.print("Pixel No ");
      Serial.print(i);
      Serial.print("switched on");
    }
  }
  pixels.show();
}

best regards Stefan

For some reason I couldn't get it do work, but I dug around and found something that kinda works...might not be as elegant.

if (shortestDist < 10)   
{              
byte i;
for (i = 0; i <= 2; i++) pixels.setPixelColor(i, 0, 0, 200);
for (i = 3; i <= 4; i++) pixels.setPixelColor(i, 0, 200, 0);
for (i = 5; i <= 6; i++) pixels.setPixelColor(i, 200, 0, 0);
pixels.show();
}

@lemilitza

If you take the effort of

ALWAYS

posting your complete sketch using

this method

The users here can really support you.

If you prefer to post too short message to be helpful
change over to WhatsApp, SnapChat or whatever social media you like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.