Controlling LED w/ Proximity Sensor

Hello all,

I am trying to control various parameters of a WS2813 LED strip. In essence, I want to control the brightness (and other parameters) of the LED strip using a proximity sensor.

I have established the brightness of the LED Strip as int proxcont, but havent figured out how to establish it as a int/variable that can change when included in IF statements (like I attempted at the bottom of the code). As it stands, the brightness of the LED Strip is established in the beginning of the code and doesnt change during the IF statements.. Is there a way that the brightness value of the LED Strips can be controlled by an int? Am I coming at this from the wrong angle?

This is where I am at thus far:

#include <FastLED.h>
#include <NewPing.h>
#define LED_PIN 7
#define NUM_LEDS 151
#define CHIPSET WS2813
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define TEMPERATURE_1 Tungsten100W
#define TEMPERATURE_2 OvercastSky
#define PING_PIN 12 // Arduino pin tied to both trigger and echo pins on the ultrasonic sensor.
#define MAX_DISTANCE 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor dista
NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE);

int distance;

int proxcont = 0;

const int numReadings = 20 ;
int readings [ numReadings ] ;
int readIndex = 0;
int total = 0;
int average = 0;
int newValue = 0;
int lastpixel = 0;

// How many seconds to show each temperature before switching
#define DISPLAYTIME 20
// How many seconds to show black between switches
#define BLACKTIME 3

void setup() {
delay(1000); // power-up safety delay
Serial.begin(9600);
Serial.println("resetting");
LEDS.addLeds<WS2813,LED_PIN,RGB>(leds,NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(proxcont);

for(int thisReading = 0 ; thisReading < numReadings ; thisReading++) {
readings [ thisReading ] = 0 ; }

}

void loop()
{
distance = sonar.ping_cm();
delay(30); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
Serial.print("distance: ");
Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range)
Serial.println("cm");
delay(100);
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
fill_rainbow( leds + 0, NUM_LEDS - 5, --starthue, 20);

// Choose which 'color temperature' profile to enable.
uint8_t secs = (millis() / 1000) % (DISPLAYTIME * 2);
if( secs < DISPLAYTIME) {
FastLED.setTemperature( TEMPERATURE_1 ); // first temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
} else {
FastLED.setTemperature( TEMPERATURE_2 ); // second temperature
leds[0] = TEMPERATURE_2; // show indicator pixel
}

FastLED.show();
FastLED.delay(8);

if(distance > 0 && distance <= 5) {
proxcont = 10;
delay(30);
}
if(distance = 6 && distance < 10) {
proxcont = 30;
delay(30);
}
if(distance > 10) {
proxcont = 50;
delay(30);
}

}

but havent figured out how to establish it as a int/variable that can change when included in IF statements (like I attempted at the bottom of the code). As it stands, the brightness of the LED Strip is established in the beginning of the code and doesnt change during the IF statements..

The brightness of the strip is not bound to the value in proxcont. Changing the value in proxcont doesn't affect the brightness unless you call

 FastLED.setBrightness(proxcont);

again.

Through trial and error I got this code to work. The proximity readings in the serial monitor and effecting the brightness of the LED. Now I am wondering if there is a more efficient way to write the parameters of this code? I want the brightness to smoothly transition from 0 to 164 depending on the reading from the proximity sensor.

Using a series of these if statements and ints from 0-2 cm, 3-5 cm, 6-8 cm, etc all the way to ~100 cm seems inefficient and potentially could be buggy/glitchy... or maybe not, and thats the way to do it?

if(proxcont > 0 && proxcont <= 5) {
int a = 10;
FastLED.setBrightness(a);
delay(30);


#include <FastLED.h>
#include <NewPing.h>
#define LED_PIN 7
#define NUM_LEDS 151
#define CHIPSET WS2813
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define TEMPERATURE_1 Tungsten100W
#define TEMPERATURE_2 OvercastSky
#define PING_PIN 12 // Arduino pin tied to both trigger and echo pins on the ultrasonic sensor.
#define MAX_DISTANCE 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor dista
NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE);

int distance;
float proxcont = 0;
int cm = 0;

const int numReadings = 20 ;
int readings [ numReadings ] ;
int readIndex = 0;
int total = 0;
int average = 0;
int newValue = 0;
int lastpixel = 0;

// How many seconds to show each temperature before switching
#define DISPLAYTIME 20
// How many seconds to show black between switches
#define BLACKTIME 3

void setup() {
delay(1000); // power-up safety delay
Serial.begin(9600);
Serial.println("resetting");
LEDS.addLeds<WS2813,LED_PIN,RGB>(leds,NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(proxcont);

for(int thisReading = 0 ; thisReading < numReadings ; thisReading++) {
readings [ thisReading ] = 0 ; }

}

void loop()
{
distance = sonar.ping_cm();
proxcont = distance;
delay(30); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
Serial.print("distance: ");
Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range)
Serial.println("cm");
delay(100);
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
fill_rainbow( leds + 0, NUM_LEDS - 5, --starthue, 20);

// Choose which 'color temperature' profile to enable.
uint8_t secs = (millis() / 1000) % (DISPLAYTIME * 2);
if( secs < DISPLAYTIME) {
FastLED.setTemperature( TEMPERATURE_1 ); // first temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
} else {
FastLED.setTemperature( TEMPERATURE_2 ); // second temperature
leds[0] = TEMPERATURE_2; // show indicator pixel
}

FastLED.show();
FastLED.delay(8);

if(proxcont > 0 && proxcont <= 5) {
int a = 10;
FastLED.setBrightness(a);
delay(30);
}
if(proxcont > 5 && proxcont <= 15) {
int b = 50;
FastLED.setBrightness(b);
delay(30);
}
if(proxcont > 15 && proxcont <= 30) {
int c = 100;
FastLED.setBrightness(c);
delay(30);
}

}

Now I am wondering if there is a more efficient way to write the parameters of this code?

Yes. You get a distance reading. Then you assign that to proxcont. Then, you get another reading and print the value.

Just assign the value from the first call to sonar.ping_cm() to proxcont, and then print proxcont. You never use distance anywhere else, so you don't need it.

You never use the readings array, either, so kiss it goodbye, too.

You said yes, there are more efficient ways to write this code. Were you referring to more efficiency that can be found in assigning the proximity sensor value to the LED brightness value? Or were you saying that there are more efficient ways to write the long series of IF statements that I will need to write at the bottom of the sketch so that the proximity of my hand controls the brightness of the LED strip..

I caught your drift and deleted the distance int.. not necessary.

Now I am wondering if there is a more efficient way to write the code for the next part. The series of IF statements will eventually give me what I want, but is there an easier way to write an exponential code that responds to proxcont and changes the brightness of the LED strip accordingly without the seemingly endless series of IF statements...

This is what my code looks like right now. It works, in theory. It does what I told it to do and the brightness it responding to the proximity sensor reading. The new issue is the binary nature of this sketch. The transition from one state of brightness into the next state of brightness is too binary/cut and paste.. I would like it to "fade" better than it does so that the brightness transitions are smoother..

#include <FastLED.h>
#include <NewPing.h>
#define LED_PIN 7
#define NUM_LEDS 151
#define CHIPSET WS2813
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define TEMPERATURE_1 Tungsten100W
#define TEMPERATURE_2 OvercastSky
#define PING_PIN 12 // Arduino pin tied to both trigger and echo pins on the ultrasonic sensor.
#define MAX_DISTANCE 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor dista
NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE);

int proxcont = 0;

const int numReadings = 20 ;
int readings [ numReadings ] ;
int readIndex = 0;
int total = 0;
int average = 0;
int newValue = 0;
int lastpixel = 0;

// How many seconds to show each temperature before switching
#define DISPLAYTIME 20
// How many seconds to show black between switches
#define BLACKTIME 3

void setup() {
delay(1000); // power-up safety delay
Serial.begin(9600);
Serial.println("resetting");
LEDS.addLeds<WS2813,LED_PIN,RGB>(leds,NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(proxcont);

for(int thisReading = 0 ; thisReading < numReadings ; thisReading++) {
readings [ thisReading ] = 0 ; }

}

void loop()
{
proxcont = sonar.ping_cm();
delay(30); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
Serial.print("distance: ");
Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range)
Serial.println("cm");
delay(35);
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
fill_rainbow( leds + 0, NUM_LEDS - 5, --starthue, 20);

// Choose which 'color temperature' profile to enable.
uint8_t secs = (millis() / 1000) % (DISPLAYTIME * 2);
if( secs < DISPLAYTIME) {
FastLED.setTemperature( TEMPERATURE_1 ); // first temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
} else {
FastLED.setTemperature( TEMPERATURE_2 ); // second temperature
leds[0] = TEMPERATURE_2; // show indicator pixel
}

FastLED.show();
FastLED.delay(8);

if(proxcont > 0 && proxcont <= 1) {
int a = 160;
FastLED.setBrightness(a);
delay(30);
}
if(proxcont > 2 && proxcont <= 3) {
int b = 155;
FastLED.setBrightness(b);
delay(30);
}
if(proxcont > 4 && proxcont <= 5) {
int c = 150;
FastLED.setBrightness(c);
delay(30);
}
if(proxcont > 6 && proxcont <= 7) {
int d = 145;
FastLED.setBrightness(d);
delay(30);
}
if(proxcont > 8 && proxcont <= 9) {
int e = 140;
FastLED.setBrightness(e);
delay(30);
}
if(proxcont > 10 && proxcont <= 11) {
int f = 135;
FastLED.setBrightness(f);
delay(30);
}
if(proxcont > 12 && proxcont <= 13) {
int g = 130;
FastLED.setBrightness(g);
delay(30);
}
if(proxcont > 14 && proxcont <= 15) {
int h = 125;
FastLED.setBrightness(h);
delay(30);
}
if(proxcont > 16 && proxcont <= 17) {
int i = 120;
FastLED.setBrightness(i);
delay(30);
}
if(proxcont > 18 && proxcont <= 19) {
int j = 115;
FastLED.setBrightness(j);
delay(30);
}
if(proxcont > 20 && proxcont <= 21) {
int k = 110;
FastLED.setBrightness(k);
delay(30);
}
if(proxcont > 22 && proxcont <= 23) {
int l = 105;
FastLED.setBrightness(l);
delay(30);
}
if(proxcont > 24 && proxcont <= 25) {
int m = 100;
FastLED.setBrightness(m);
delay(30);
}
if(proxcont > 26 && proxcont <= 27) {
int n = 95;
FastLED.setBrightness(n);
delay(30);
}
if(proxcont > 28 && proxcont <= 29) {
int o = 90;
FastLED.setBrightness(o);
delay(30);
}
if(proxcont > 30 && proxcont <= 31) {
int p = 85;
FastLED.setBrightness(p);
delay(30);
}
if(proxcont > 32 && proxcont <= 33) {
int q = 80;
FastLED.setBrightness(q);
delay(30);
}
if(proxcont > 34 && proxcont <= 35) {
int r = 75;
FastLED.setBrightness(r);
delay(30);
}
if(proxcont > 36 && proxcont <= 37) {
int s = 70;
FastLED.setBrightness(s);
delay(30);
}
if(proxcont > 38 && proxcont <= 39) {
int t = 65;
FastLED.setBrightness(t);
delay(30);
}
if(proxcont > 40 && proxcont <= 41) {
int u = 60;
FastLED.setBrightness(u);
delay(30);
}

}

 proxcont = sonar.ping_cm();
  delay(30);                     // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  Serial.print("distance: ");
  Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");

You are still calling sonar.ping_cm() twice. The second call, in the Serial.print() argument list should be replaced by proxcont.

You don't need to define a local variable to pass to the SetBrightness() method. You can pass a literal value.

There are two values of proxcont that result in the same block executing. Each block changes the value of the brightness by 5.

So, there is a nearly linear relationship between brightness and proxcont. brightness = 160 - 2.5 * proxcont. No if statements needed, unless you need that stairstep relationship between brightness and proxcont that you have now. (If you do, you can still define brightness in terms of proxcont/2 with a step of 5).

Nailed it! Thank you!

I added another IF statement that changes brightness to 0/off if the distance is above a certain distance or at 0.

Hello All,

I would like to control the color of my LED Strip using the information generated by my proximity sensor. I was able to complete this tasking using the brightness parameter of the LED Strip, but it hasn't been as straight forward transferring the logic to tweaking the color parameters of the LED Strip. Any Suggestions?

#include <FastLED.h>
#include <NewPing.h>
#define DATA_PIN 7
#define NUM_LEDS 155
#define CHIPSET WS2813
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define TEMPERATURE_1 MetalHalide
#define TEMPERATURE_2 MetalHalide
#define PING_PIN 12 // Arduino pin tied to both trigger and echo pins on the ultrasonic sensor.
#define MAX_DISTANCE 120 // Maximum distance we want to ping for (in centimeters). Maximum sensor dista
NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE);
int proxcont = 0;
const int numReadings = 20 ;
int readings [ numReadings ] ;
int readIndex = 0;
int total = 0;
int average = 0;
int newValue = 0;
int lastpixel = 0;

// How many seconds to show each temperature before switching
#define DISPLAYTIME 20
// How many seconds to show black between switches
#define BLACKTIME 3

void loop(){
proxcont = sonar.ping_cm();
int brightness = 160 - 2.5 * proxcont;
if(proxcont <= 0 ) {
brightness = 0; }
if(proxcont >= 64 ) {
brightness = 0; }

FastLED.setBrightness(brightness);
delay(29); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
Serial.print("distance: ");
Serial.print(proxcont); // Send ping, get distance in cm and print result (0 = outside set distance range)
Serial.println("cm");
delay(35);
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
fill_rainbow( leds + 0, NUM_LEDS - 5, --starthue, 20);

// Choose which 'color temperature' profile to enable.
uint8_t secs = (millis() / 1000) % (DISPLAYTIME * 2);

if( secs < DISPLAYTIME) {
FastLED.setTemperature( TEMPERATURE_1 ); // first temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
}

else {
FastLED.setTemperature( TEMPERATURE_2 ); // second temperature
leds[0] = TEMPERATURE_2; // show indicator pixel
}
FastLED.show();
FastLED.delay(29);
}

void setup() {
delay(1000); // power-up safety delay
Serial.begin(9600);
Serial.println("resetting");
LEDS.addLeds<WS2813,DATA_PIN,RGB>(leds,NUM_LEDS).setCorrection(TypicalLEDStrip);

for(int thisReading = 0 ; thisReading < numReadings ; thisReading++) {
readings [ thisReading ] = 0 ; }

}

You still have that useless array called readings. Why?

There is nothing in that code that changes the color of an LED based on proxcont.

What the heck does proxcont mean, anyway?