Skip to content

Instantly share code, notes, and snippets.

@JetForMe
Last active December 29, 2015 00:49
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 JetForMe/7588527 to your computer and use it in GitHub Desktop.
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…
/**
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