Skip to content

Instantly share code, notes, and snippets.

@ajfisher
Created July 2, 2011 23:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajfisher/1061793 to your computer and use it in GitHub Desktop.
Save ajfisher/1061793 to your computer and use it in GitHub Desktop.
Make an RGB LED show different colours based on range finder distance
/*
WARMER COOLER GAME
Use a ping sensor to determine distance and then depending on the distance,
show warmer or cooler colours.
Built using a ping))) Sensor and connected to a RGB display.
Uses the ping))) example in the base Arduino install, written by David Mellis & Tom Igoe
http://www.arduino.cc/en/Tutorial/Ping
*/
#define PING_PIN 7
#define RED 9
#define GREEN 10
#define BLUE 11
#define BLUE_LONG 400
#define BLUE_SHORT 175
#define GREEN_LONG 225
#define GREEN_SHORT 75
#define RED_LONG 125
#define RED_SHORT 0
void setup() {
// initialize serial communication:
Serial.begin(9600);
// set the LED off
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
// uses a common anode RGB LED (so +5v turns them off)
digitalWrite(RED, HIGH);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
}
void loop()
{
long distance;
distance = ping();
// now depending on the distances we map the colours on the LED.
// BLUE will be bright at about 350 cm fading out to 175cm
// GREEN will be bright about 225cm fading out to about 75cm
// RED will be faded at about 125cm getting bright to 0cm
if (distance > RED_LONG) {
digitalWrite(RED, HIGH);
} else {
analogWrite(RED, map(distance, RED_LONG, RED_SHORT, 255, 0));
}
if ((distance > GREEN_LONG) || (distance < GREEN_SHORT)) {
digitalWrite(GREEN, HIGH);
} else {
analogWrite(GREEN, map(distance, GREEN_LONG, GREEN_SHORT, 255, 0));
}
if ((distance > BLUE_LONG) || (distance < BLUE_SHORT)) {
digitalWrite(BLUE, HIGH);
} else {
analogWrite(BLUE, map(distance, BLUE_LONG, BLUE_SHORT, 255, 0));
}
Serial.print(distance);
Serial.print("cm");
Serial.println();
delay(100);
}
long ping() {
// returns the distance to the nearest object.
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, 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(PING_PIN, OUTPUT);
digitalWrite(PING_PIN, LOW);
delayMicroseconds(2);
digitalWrite(PING_PIN, HIGH);
delayMicroseconds(5);
digitalWrite(PING_PIN, 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(PING_PIN, INPUT);
duration = pulseIn(PING_PIN, HIGH);
// convert the time into a distance
return (microsecondsToCentimeters(duration));
}
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
@ajfisher
Copy link
Author

ajfisher commented Jul 2, 2011

This circuit assumes a Common Anode RGB LED. Wire up ANODE to +5V and the other connections to your PWM pins which must be driven LOW to turn the LED on. Driving PWM pins HIGH will turn the LED off.

Wire up an ultrasonic sensor to a digital input pin on the Arduino. Code for this is based on ping))) from Parallax and uses the public domain code written by David Mellis, edited by Tom Igoe.

@cdastan
Copy link

cdastan commented Aug 20, 2014

Hi there AJ, thanks for the code! I'm wondering how to change the code to work with a common cathode RGB LED. Is it a simple change from "digitalWrite(RED, HIGH);" to "digitalWrite(RED, LOW);" for each color? I have tried this and it doesn't seem to be working correctly so I am asking why and how other parts of the codes may require editing based on drawing from ground as opposed to +5V.

@paolajuvenal
Copy link

hi AJ! your code is great, we are trying to turn off the other 2 colors of light when the distance is at the specific color! can you help, pleaseeeeeeeeee!

@Bhavdeep13
Copy link

Hi can you tell me how we make Ultrasonic sensor colourful?
means can be add RGB LED Strip inside ultrasonic sensor?

@ajfisher
Copy link
Author

ajfisher commented Sep 7, 2020

@Bhavdeep13 I'm not certain exactly what you're trying to do however the section of code that changes the colour based on distance is this: https://gist.github.com/ajfisher/1061793#file-gistfile1-c-L52-L68

@ricauld
Copy link

ricauld commented May 3, 2024

Hi AJ. I am new to C++ programming and I am learning with Arduino.

I don't know if you can understand everything I explain, English is not my native language, but I will express myself as best as possible.

I have seen your project and I was inspired to do it for a final class project at the end of the year. I have seen similar projects on the internet. But I want to make it a step more complex and interesting. But I need guidance to understand where I can start because with what I see in other tutorials I can't understand how to make it work as I would like.

In your project I understand that it only works for 1 LED or a chain of LEDs in series that would behave the same (Depending on the distance, they all change color at the same time)

I am looking for a different behavior: in an LED strip (x numbers of LEDs) I want each LED to react independently showing the location of the object detected with the ultrasound sensor (4 ultrasound sensors in series).

For example: if the sensor detects something approaching from the right, the LEDs on the strip will begin to react from the right, and as the object moves from right to left, the LEDs will follow the detected object. At the same time, each LED shows the distance of the object by changing color as your project. It would be like a 1D display of an LED strip that shows both the location and distance of the object detected by the sensor, but in a fluid way, where each LED reacts to a specific angle and distance in real 3D space. Only it projects it two-dimensionally on an LED strip in a simplified way. (location and distance but on a single axis).

My reasoning intuits that I must transform or convert the analog signal of the ultrasound sensor array into a 2D map, something similar to a submarine sonar system and see how to transfer that data from the location and distance of the detected object to signals to the LEDs. .

I hope you understand and can advise me on ways to solve it. I hope I don't bother you too much if it's too complicated, thanks in advance.

@ajfisher
Copy link
Author

ajfisher commented May 4, 2024

Sounds like an intersting project @ricauld

So you need to consider the ultrasonic sensors and the LEDs as essentially two different things.

With the ultrasonic sensors, having an array of them is perfectly reasonable however you need to watch their detection arcs. The reason for this is that the way the ultrasonic sensors work is by sending out a high frequency "click" and it then times the response. If you have them close together, you can get situations of misreading because the second US sensor is "hearing" the sound the first one emitted. You can fix this by having them point in different directions or by creating sound baffles which will limit their arc.

Most modern cars have multiple US sensors in them but if you look where they are say at the rear of the car you'll see they are mounted to help minimise arc overlap but they also use expensive ones that can be both tuned to emit different frequencies as well as have narrow cones they detect in.

Once you solve the noise issue, it's really just a case of firing each one, getting the response and then building up a map of what each sensor can "see". If you know the fixed positions of the sensors and the distance to the target you can work out the angle using a simple trig calculation (cosine rule).

Now for the LEDs, the easiest way to tackle what you're thinking about is to use something like a WS2812 addressable LED strip (eg something like this: https://www.adafruit.com/category/168 - I have no affiliation to adafruit and these are standard LEDs you can get anywhere). The beauty of this is you essentially keep an array in memory of the RGB values for the number of LEDs you want to have (4, 40, 4000 - whatever works for your project) and with one data pin as well as power and ground you can send the data down to set the "pixels" how you want them.

After that, it's more or less what you indicated - creating a mapping function which translates from your signal data of ppositions into a combination of colour and position on your individual LEDs.

Personally, I'd get one sensor working with a couple of addressable LEDs to just work up a basic proof of concept, then focus on getting the calculations right on a multi-sensor array as that will be the challenging part of this. Once you have your data correct, sending the information to the LEDs is relatively straightforward as it's just an array + a library function on a single wire.

Sounds like good fun and you'll bump into a lot of edge cases with the sensor array which will make for a good learning project. Good luck and please post a link to your finished work!!!

@ricauld
Copy link

ricauld commented May 4, 2024

Thanks AJ. Frankly, I believed that I would not have an answer because of how old the publication is and its last message. But thank you very much for the attention and detailed information.

Thanks for the advice on the interference problem between sensors. It makes sense now that I think about it. I am not at all in-depth knowledge of all the electronics or physics involved, but if there is one thing I recognize, it is that by knowing how to think logically and by understanding fundamentals I can go far. But not having these tips can cause me to waste a lot of time figuring out just technical problems, so thank you very much for this.

As you say, I will limit myself to experimenting with a single generic sensor like the ones on the Arduino. Understanding how it works in its most simplified form, I would then see how to deal with it with arrays.
I don't even study in a branch of science, but arts... The little I intuited, and something told me that precisely mapping this data and more with more than 1 sensor implies somewhat advanced background mathematical work. But by attacking one problem at a time I will get to the end. You gave me another clue with the trig calculation (cosine rule). With that I have another important starting point. I should study this before even trying to program. Like I said, understanding the fundamentals takes anyone a long way. But the important thing is to understand what these fundamentals are and you have already given me 2 good bases. (Understand how the sensors work and their limitations as well as the mathematics behind the operation I am looking for).

Thanks for the reference on the LEDs. Do some research on these and get to look at the addressable LED strip from Adrafruit, among other brands. But I understand why you recommend it. They are widely used in the Maker community and I understand that they have a good library that is easy to understand and apply.

Any reference on how mapping functions are used or applied precisely for this case study?

Correct me if I'm wrong, but I suspect that it may have something to do with matrix data. This is what comes to mind although I don't even understand how matrices work, but if it goes that way, I already understand that I should study this and see how it is applied in programming language.

With having all the necessary theoretical foundations, I only have to learn how they work and then apply them. But unless I know about programming or advanced mathematics, I don't want to burden myself by searching for other topics far from what I need due to lack of theoretical knowledge.

Without a doubt I will share it as long as it takes me to understand and do it. I still have until the end of the year.

The idea is an artistic work of visualizing the concept of location and distance but only in a ''2D plane'' (LED strip). In a fluid and beautiful way. Something simple, but the idea is to express in its minimum the concepts of space in a simple dimension. Just as a graphic equalizer or VU meter works to represent sound frequency graphically, but with space.

@ajfisher
Copy link
Author

ajfisher commented May 4, 2024

No problems at all. I'm glad I can be of some assistance :)

In general terms, if you're only using 4 ultrasonic sensors you probably won't need some matrix maths to get something reasonable - especially in a linear plane. I certainly would start with just getting the data off each one and start to build up a sense of what data each sensor can "see" because ultimately you're going to resolve to a maximum of 4 values and from that you can start to determine the angles from the sensor to each obstacle in front.

If that doesn't give you enough data or resolution then you could look at more sensors or more complex mathematical transformations but I'd start from there and then see where it starts to break down in terms of the visualisation you're trying to build and add complexity as you need it I reckon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment