Last active
December 29, 2015 00:49
-
-
Save JetForMe/7588527 to your computer and use it in GitHub Desktop.
Hacktacular parking ranging code. This was a fatigue-fueled throwaway effort for the Parking Ranger described here http://www.youtube.com/watch?v=lHSCSfiCXpA. The code sets up a color table, one entry per LED, and initializes everything else. It then sits in a loop, triggering the sensor and then measuring the resulting pulse width. It then conv…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Simple Arduino parking range display. | |
Designed for an Arduino MEGA 2560, connected via SPI0 (pins 51, 52) | |
to an LDP8806 52-LED strip, and a Parallax PING))) ultrasonic | |
sensor on pin 22. | |
*/ | |
#include "LPD8806.h" | |
#include "SPI.h" | |
/** | |
Set qLogging to 1 to turn on some debug logging that will | |
be visible in the Arduino IDE Serial Monitor. | |
*/ | |
#define qLogging 0 | |
/** | |
The timeout is a count of times through the main Arduino loop(). | |
The loop takes time to execute, plus a delay of 50 ms. There are | |
1200 50 ms intervals in one minute, so this delay is something more | |
than one minute. | |
*/ | |
const uint32_t kTimeout = 1200; | |
/** | |
The signal/sense pin for the Parallax PING))). | |
*/ | |
const int kPingPin = 22; | |
/** | |
This macro builds the 32-bit word used by the LDP8806 library to | |
set an LED’s color. | |
Note: My strip seems to have the color components in a different | |
order than that defined by the LDP8806 library. You might have | |
to experiment with this. | |
*/ | |
#define color(r, g, b) (((uint32_t)(b) | 0x80) << 16) \ | |
| (((uint32_t)(r) | 0x80) << 8) \ | |
| ((uint32_t)(g)) | 0x80 | |
/** | |
This color table is very simple, just three segments of solid | |
green, yellow, and red. The constant kC just makes it easier | |
to adjust the overall brightness of the LEDs. | |
A nicer table would have smoother transitions between each | |
segment. | |
*/ | |
const uint8_t kC = 100; | |
const uint8_t kNumLEDs = 52; | |
uint32_t | |
sFB[kNumLEDs] = | |
{ | |
// Green | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
color(0, kC, 0), | |
// Yellow | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
color(kC, kC, 0), | |
// Red | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
color(kC, 0, 0), | |
}; | |
/** | |
Static objects used in the rest of the code. | |
*/ | |
LPD8806 sStrip = LPD8806(kNumLEDs); | |
uint32_t sDelay; | |
/** | |
One-time Arduino initialization. | |
*/ | |
void | |
setup() | |
{ | |
#if qLogging | |
Serial.begin(115200); | |
Serial.println("Hello"); | |
#endif | |
sStrip.begin(); | |
sStrip.show(); | |
} | |
/** | |
Using the Parallax PING)) is straightforward. First the single | |
signal pin must be strobed with a high pulse, then it will | |
respond with a high pulse whose duration is proportional to | |
the measured range. | |
This method could use some low-pass filtering. | |
*/ | |
float | |
measureDistance() | |
{ | |
// Pulse the pin… | |
pinMode(kPingPin, OUTPUT); | |
digitalWrite(kPingPin, HIGH); | |
digitalWrite(kPingPin, LOW); | |
// Listen for the pulse… | |
pinMode(kPingPin, INPUT); | |
uint32_t pulseWidth = pulseIn(kPingPin, HIGH); | |
// The following code converts the sensor's measured | |
// range to cm. This value was derived experimentally, | |
// as the value provided by the Parallax PING))) documentation | |
// didn't seem to be correct. With three sample points, the | |
// result was pretty linear. There‘s probably some zero offset | |
// that should be considered, but wasn't for this quick project. | |
float d = pulseWidth * 0.0180272396098469; | |
return d; | |
} | |
/** | |
loop() is called repeatedly by the Arduino runtime. | |
*/ | |
void | |
loop() | |
{ | |
// Ping the sensor… | |
float d = measureDistance(); | |
// Convert this to a measurement from a point 300 cm away | |
// from the sensor, increasing toward the sensor (wall)… | |
d = 300 - d; | |
#if qLogging | |
Serial.print("Dist: "); | |
Serial.print(d); | |
Serial.print(" segment: "); | |
#endif | |
// Determine the segment. This allows individual segments | |
// of the strip to have different scaling with respect to | |
// the distance measured by the sensor. As it stands, they | |
// are roughly proportional. The first segment is 0 - 100 cm, | |
// and covers 22 LEDs. The second segment is 100 - 195 cm, | |
// and also covers 22 LEDs. The third segment is 195 - 205 cm, | |
// and covers the remaining 8 LEDs. | |
// | |
// top gets computed as the top LED to light, and the color | |
// of each LED below that is looked up in the color table. | |
uint8_t top = 0; | |
if (d < 0) // Off if more than 3 m away | |
{ | |
sDelay = 0; // Reset the timeout counter | |
#if qLogging | |
Serial.print("d < 0"); | |
#endif | |
} | |
else if (d < 100) | |
{ | |
top = 22 * d / 100; | |
#if qLogging | |
Serial.print("< 100: "); | |
#endif | |
} | |
else if (d < 195) | |
{ | |
top = 22 * (d - 100) / 95; | |
top += 22; | |
#if qLogging | |
Serial.print("< 195: "); | |
#endif | |
} | |
else | |
{ | |
top = 8 * (d - 195) / 10; | |
top += 44; | |
#if qLogging | |
Serial.print(">= 195: "); | |
#endif | |
} | |
// Ensure we don’t go past the end of the color table… | |
if (top > kNumLEDs) | |
{ | |
top = kNumLEDs; | |
} | |
#if qLogging | |
Serial.println(top); | |
#endif | |
// Increment the timeout timer. The timeout begins as soon | |
// as the sensor detects something within the 300 cm range | |
// defined above… | |
sDelay += 1; | |
// Prevent rollover of the timer by pegging it to the max value… | |
if (sDelay > kTimeout) | |
{ | |
sDelay = kTimeout; | |
} | |
// Update the LEDs… | |
for (uint16_t i = 0; i < kNumLEDs; ++i) | |
{ | |
uint32_t c = sFB[i]; | |
if (i < top && sDelay < kTimeout) // On LEDs (only if the timeout hasn’t expired) | |
{ | |
sStrip.setPixelColor(i, c); | |
} | |
else // Off LEDs | |
{ | |
sStrip.setPixelColor(i, 0); | |
} | |
} | |
// Write the new pixel values to the LED strip… | |
sStrip.show(); | |
// Delay a little bit before doing it all again. If | |
// you change this value, you’ll need to adjust the | |
// timeout count value… | |
delay(50); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment