I'm using a sonar sensor to detect proximity, and need to control the brightness of an LED strip in direct relationship to the distance detected. For example, as someone moves toward the sonar, the strip needs to dim.

I'm using map() to do it now crudely but it's way too abrupt and I'm not sure how best to achieve the effect I'm looking for. Ideally, as the person moves toward the light, it very smoothly fades out in relationship to the person's movement/pace.

Initial thoughts / questions:

-- Can I use a more refined number type to set the LED brightness other than int? -- Do I need to do something more complex where I detect the delta in the person's movement and use the loop to fade the LED from one value to another? Seems complicated...

Any help / ideas on this would be much appreciated! Existing code is below if it helps. Claudia

//variables needed to store values
long pulse, inches, cm;

int frontPin = 6;    // front strip connected to PWN pin 5
long interval = 8000; // interval at which to do something (milliseconds)
int val;

void setup() {
  //This opens up a serial connection to shoot the results back to the PC console
  pinMode(frontPin, OUTPUT);
  pinMode(pwPin, INPUT);

void loop() {
    //Used to read in the pulse that is being sent by the MaxSonar device.
  //Pulse Width representation with a scale factor of 147 uS per Inch.

  pulse = pulseIn(pwPin, HIGH);
  //147uS per inch
  inches = pulse/147;
  //change inches to centimetres
  cm = inches * 2.54;

  if (inches < 36){

void detect(){
  Serial.print("in, ");

  val = inches;
  val = map(val, 6, 36, 0, 255);

  analogWrite(frontPin, val);
  Serial.print("mapped value is ");



1 Answer 1


The biggest problem is that by forcing the code to use integral inches you've restricted it to 31 discrete values. And since the brightness response of a PWMed LED is non-linear you effectively have very large steps in brightness when the LED is dim.

pulseIn() has much more flexibility with regards to its range so use the raw value directly instead of converting it to "pretty" values.

val = map(pulse, ..., ..., 0, 255);
  • I agree about the step size, however sub-inch measurement may not be a full solution. Non-linear mapping may be needed. Something in the time domain, which ramps the level up or down one step at a time (with delay) to seek a function of the current distance or recent average thereof might or might not also help. Commented Jan 4, 2015 at 17:54
  • Thanks Ignacio!! I gave it a shot and it needs a little tweaking but gets me closer. However, to Chris' point, it still seems a little abrupt as it shifts. Chris - any tips on approach to what you're talking about? I think that's where I probably need to go...
    – claudybee
    Commented Jan 4, 2015 at 22:51
  • @claudybee: Implement a lookup table using one of the formulas in the linked question. Don't be afraid to use more than 256 values if it ends up working better. Commented Jan 5, 2015 at 1:52

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.