Dimming Lights with PING

greeitings, I am trying to control the brightness of some incandescent lights using Arduino and the Parallax PING ultra sonic sensor. the idea is that the closer an object gets to the sensor, the brighter the lights will get. Im fairly new to arduino, at the moment I have gotten the PING to light up some LEDs the closer I get to the sensor... i will post my code and a quick video shortly. SO any ideas?

Any help with hardware or code advice is welcome

I had thought about using LEDs, but im worried they wont get bright enough (i want this thing BRIGHT), but if LEDs are really the way to go, please let me know point me in the right direction.

Thank you!

EDIT: i was not able to get the video up... but here is my code for 4 LEDS..

#define led1 2
#define led2 3
#define led3 4
#define led4 5

const int pingPin = 7;

int duration;

void setup(){
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);

// initialize serial communication:
Serial.begin(9600);
}
void loop()
{
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm;
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
// convert the time into a distance

Serial.print(duration);
Serial.println();
delay(100);

digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);

//these values may need to be changed for your setup

if (duration < 11000){
digitalWrite(led4, HIGH);
}
if (duration < 8000){
digitalWrite(led3, HIGH);
}
if (duration < 5000){
digitalWrite(led2, HIGH);
}
if (duration < 1000){
digitalWrite(led1, HIGH);
}

delay(50);
}

You can get some really bright LEDs, a 3x3W cluster for example...

Just as a comment, the way you are doing it at the moment, you have single directional sensing with the range sensor. You could do it with capacitance sensing and sense distance of a person in any direction, it is not accurate to read a distance from but it is accurate enough to tell you if the person is close to it or not. If you stick in a big enough resistor then you can measure over 1m...

Mowcius

I built one with a velleman K8064 dc dimmer.

It has a 0-10v input that is translated to 0-220v. So shape your PING data to 0-256 and send it out over pwm.

Thats it, then you have to calibrate a lot. here is some messy code from my dimmer, maybe it's useful:

// PINS
int pwmPin = 9; 
int potPin = 0;
int pingPin = 7;

// MEM
int pwmVal = 1;
float potVal = 0;
float dimdim = 0;                        // vin: changed here to flaot

const int errorCorrectionSize = 5;
double errorCorrectionArr[errorCorrectionSize] = {0,0,0,0,0};
int errorCorrectionPos = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(pwmPin, OUTPUT); // sets the pins as output
  delay(100);
}


// Main program
void loop()
{

  long duration, cm;
  double distanceValue;

  duration = readSonar(7);
  distanceValue = 1-min(duration,4000)/4000.0;
//  Serial.print("  distanceValue : ");
//  Serial.print(distanceValue);
  distanceValue = errorCorrection(distanceValue);

  dimdim += (distanceValue-dimdim)/3;                        // vin: smoothing the value.... if you change the 6 to 1 there wont be any smoothing.... the bigger the number the smoother the v

  // CALIBRATE
  potVal = analogRead(potPin);    // read the value from the sensor
  float maxVal = 1 - ((potVal)/1024.0f);
  float endVal = max(dimdim-(1-maxVal),0)/maxVal;
//  endVal = sin(endVal*PI*0.5);                                  // sine amplified
  endVal = min(1,max(0,endVal));
  
  // WRITE TO DIMMER
  unsigned char pwmVal = min(255,max(0,endVal*255.0));
  analogWrite(pwmPin, pwmVal);                        // vin: added (int) conversion

/*
  Serial.print("  distanceValue : ");
  Serial.print(distanceValue);
  Serial.print("  maxVal : ");
  Serial.print(maxVal);
  Serial.print("  endVal : ");
  Serial.print(endVal);
  */
  
//  Serial.print("  pwmVal : ");
//  Serial.println((int)pwmVal);

//  Serial.print("    cm : ");
//  Serial.println(pingDistance(7));
  
  delay(100);
}


unsigned long pingDistance(int ultraSoundSignal){
  unsigned long echo = 0;
  unsigned long ultrasoundValue = 0;

  pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output
  digitalWrite(ultraSoundSignal, LOW); // Send low pulse
  delayMicroseconds(2); // Wait for 2 microseconds
  digitalWrite(ultraSoundSignal, HIGH); // Send high pulse
  delayMicroseconds(5); // Wait for 5 microseconds
  digitalWrite(ultraSoundSignal, LOW); // Holdoff
  pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
  digitalWrite(ultraSoundSignal, HIGH); // Turn on pullup resistor
  echo = pulseIn(ultraSoundSignal, HIGH); //Listen for echo
  ultrasoundValue = (echo / 58.138); //convert to CM then to inches
  return ultrasoundValue;
}


long readSonar( int signalpin) {
  int readsignal = 0;
  long counttime = 0;

  pinMode(signalpin, OUTPUT);
  digitalWrite(signalpin, LOW);
  digitalWrite(signalpin, HIGH);
  delayMicroseconds(4);
  digitalWrite(signalpin, LOW);

  pinMode(signalpin, INPUT);

  readsignal = digitalRead(signalpin);
  while (readsignal == LOW) {
    readsignal = digitalRead(signalpin);
  }

  counttime=0;
  while (readsignal == HIGH) {
    readsignal = digitalRead(signalpin);
    counttime++;
  }

  return counttime;
}

double errorCorrection(double val){
  errorCorrectionArr[errorCorrectionPos] = val;
  errorCorrectionPos++;
  errorCorrectionPos %= errorCorrectionSize;
  int i;
  double minVal = 1;
  double maxVal = 0;
  double addVal = 0;
  for(i=0;i<errorCorrectionSize;i++){
//    Serial.print("  ");
//    Serial.print(errorCorrectionArr[i]);
    addVal += errorCorrectionArr[i];
    minVal = min(errorCorrectionArr[i],minVal);
    maxVal = max(errorCorrectionArr[i],maxVal);
  }
  /*
  Serial.print("    addVal: ");
  Serial.print(addVal);
  Serial.print("  divider: ");
  Serial.print((double)(errorCorrectionSize-2));
  */
  addVal -= minVal;
  addVal -= maxVal;
  val = addVal/(double)(errorCorrectionSize-2);
//  Serial.print("  errorCorrectionPos : ");
//  Serial.print(errorCorrectionPos);  
  
  return val;
}

WOW, great thank you so much!

hi fubbi,
what add'l circuitry did you add to your pwm out? (ie: lp filter on the pwm output to ensure smooth dimming transitions?)

any pointers from your experience would be very much appreciated! (working on something similar) :slight_smile: