The very first project that got me started learning about microcontrollers was LED Tetherball. It was developed as a camp project for Burning Man, an interactive game folks could engage in while they wandered the city. It was a perfect learning project that got me exploring LEDs, batteries and sensors
You can see it in action on the playa at 1:10!
If you’re interested here is the code, and a link to the GitHub project.
[code]
/*
My 2nd attempt at HSB and acceleromter control. XYZ axes are added together to make a value that is then mapped to the HUE.
*/
const int numReadings = 25; // Sets number of readings (smoothing amount. I chose a very high number to start with)
// Setting up the smoothing int
int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
int brightnessValue = 0; // store a brightness value for constraining
//Analog read pins for Accelerometer
const int xPin = 0;
const int yPin = 1;
const int zPin = 2;
// Outputs for RGB channels. I am using 12v Analog RGB Tape
const int ledPinRed = 3; // Red LED connected to analogue out pin
const int ledPinGrn = 5; // Green LED connected to analogue out pin
const int ledPinBlu = 6; // Blue LED connected to analogue out pin
int accelVal = 0; // store the value coming from the accelerometer
// Constants to define the ranges.
const int hueRedLow = 0;
const int hueRedHigh = 255;
const int hueBlue = 170;
// The size of the angle of one sector (1/6 of a colour wheel), and of a complete
// cycle of the colour wheel.
const int angleMin = 0;
const int angleSector = 60;
const int angleMax = 360;
const int brightMin = 0;
const int brightMax = 255;
// Work variables.
// The accelValueHue value is mapped to the range 0 to 360 (degrees).
int accelValueHue;
// The hue is the range 0 (red) to 170 (blue) in rainbow
// mode or 255 (red) in colour wheel mode.
// The brightness ranges from 0 (dark) to 255 (full brightness)
int hue, brightness;
// The saturation is fixed at 255 (full) to remove blead-through of different
// colours.
// It could be linked to another potentiometer if a demonstration of hue
// is desired.
const int saturation = 255;
// step variable, this is the speed the hue value increases
int step = 1;
// placeholders for the RGB values
unsigned int r, g, b;
void setup()
{
// set a baud rate for serial monitoring
Serial.begin(9600);
// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
// Set LED pins to output.
pinMode(ledPinRed, OUTPUT);
pinMode(ledPinGrn, OUTPUT);
pinMode(ledPinBlu, OUTPUT);
// Poteniometer analogue pin is an input.
// pinMode(accelHue, INPUT);
// pinMode for accelerometer
pinMode(xPin, INPUT);
pinMode(yPin, INPUT);
pinMode(zPin, INPUT);
// TODO: mode switch in a digital input.
// pinMode(modeSwitchPin, INPUT);
}
void loop()
{
//read the analog values from the accelerometer and constrain the values
unsigned int xRead = analogRead(xPin); //changed from const int to unsigned just to see what happened. Not sure if this matters or not really.
unsigned int yRead = analogRead(yPin);
unsigned int zRead = analogRead(zPin);
/*
This next bit defines accelVal as an average of the X, Y and Z inputs
When using HSV Hue is what moves through the color spectrum as I understand it
so there's only one value that you need to adjust
I am adding up the values to give a single "movement" measurement
*/
accelVal = (xRead+yRead+zRead);
// define accelHue as accelVal constrained to 500 through 1200
// This was determined by monitoring accelVal while hitting the ball
// and identifying the higest and lowest values
int accelHue = constrain(accelVal, 500, 1200);
// This summing section is straight from Jason's code, I don't pretend to really know all it's details
// subtract the last reading:
total= total - readings[index];
// read from the sensor:
readings[index] = accelHue;
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;
// if we're at the end of the array...
if (index >= numReadings)
// ...wrap around to the beginning:
index = 0;
// calculate the average:
average = total / numReadings;
// The accelValueHue value is mapped to degrees - 0 to 300 - so max impact would take you halfway through the spectrum
accelValueHue = map(analogRead(average), 500, 1200, 0, 300);
// step defined as an ever increasing value
step += 1;
// Taking accelValueHue and defining hue
{
// Colour wheel mode (red to red, wrapped around in a cycle).
hue = step + map(accelValueHue, angleMin, angleMax, hueRedLow, hueRedHigh);
// loops the value around
if (step > 360) {
step -= 360;
}
if (hue > 360) {
hue -= 360;
}
// Maps the accelVal to a Brighness var, mapped to 0-255 inverted)
brightnessValue = constrain(accelVal, 1200, 500);
brightness = map(brightnessValue, 1200, 500, 10, 255);
}
// Using HSBtoRGB to send to the RGB outputs
HSBToRGB(hue, saturation, brightness, &r, &g, &b);
analogWrite(ledPinRed, r);
analogWrite(ledPinGrn, g);
analogWrite(ledPinBlu, b);
//Monitoring values.
Serial.print(" bright=");
Serial.print(brightness);
Serial.print(" hue=");
Serial.print(hue);
Serial.print(" red=");
Serial.print(r);
Serial.print(" green=");
Serial.print(g);
Serial.print(" blue=");
Serial.print(b);
Serial.print(" accelVal=");
Serial.print(accelVal);
Serial.print(" average=");
Serial.print(average);
Serial.print(" accelHue=");
Serial.print(accelHue);
Serial.println("");
delay(50);
}
// Flash Function prototype
void Flash()
{
analogWrite(brightness, 255);
delay(50);
analogWrite(brightness, 0);
delay(50);
}
// HSBtoRGB function
// This function taken from here:
// http://eduardofv.com/read_post/179-Arduino-RGB-LED-HSV-Color-Wheel-
void HSBToRGB(
unsigned int inHue, unsigned int inSaturation, unsigned int inBrightness,
unsigned int *oR, unsigned int *oG, unsigned int *oB )
{
if (inSaturation == 0)
{
// achromatic (grey)
*oR = *oG = *oB = inBrightness;
}
else
{
unsigned int scaledHue = (inHue * 6);
unsigned int sector = scaledHue >> 8; // sector 0 to 5 around the color wheel
unsigned int offsetInSector = scaledHue - (sector << 8); // position within the sector
unsigned int p = (inBrightness * ( 255 - inSaturation )) >> 8;
unsigned int q = (inBrightness * ( 255 - ((inSaturation * offsetInSector) >> 8) )) >> 8;
unsigned int t = (inBrightness * ( 255 - ((inSaturation * ( 255 - offsetInSector )) >> 8) )) >> 8;
switch( sector ) {
case 0:
*oR = inBrightness;
*oG = t;
*oB = p;
break;
case 1:
*oR = q;
*oG = inBrightness;
*oB = p;
break;
case 2:
*oR = p;
*oG = inBrightness;
*oB = t;
break;
case 3:
*oR = p;
*oG = q;
*oB = inBrightness;
break;
case 4:
*oR = t;
*oG = p;
*oB = inBrightness;
break;
default: // case 5:
*oR = inBrightness;
*oG = p;
*oB = q;
break;
}
}
}
[/code]
Leave a Reply
You must be logged in to post a comment.