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]