What’s your fortune?

Description:
In this one, I tried to create a pulsating effect (as in a fortune-teller’s crystal orb) with a ping-pong ball as a diffuser. I wanted to vary the heart-rate, the baseline intensity and the amplitude of the heartbeat using the potentiometers. I also had to be mindful of how bright my blue LED. One important lesson was to write the code from start to finish even if some of the code can be reused from another source on the internet.

Components
Cotton/wool
1 ping pong ball
3 potentiometers
3 LEDs (Red, Green and Blue)
3 Resistors (220 ohms each)
Arduino UNO
Breadboard and cables

Code


int heartRatePin = A0; // this controls tempo/delay
int heartRate = 0;

int beatWidthPin = A1; // this controls amplitude of the beat
int beatWidth = 0;

int intensityPin = A2; // this controls baseline brightness around which the amplitude is then set
int intensity = 0;

int crest = 0;
int trough = 0;

// initializing the LEDs
int ledPinGreen = 9;
int ledPinBlue = 10;
int ledPinRed = 11;

void setup(){
  // declaring pins as OUTPUTS
  pinMode(ledPinGreen, OUTPUT);
  pinMode(ledPinBlue, OUTPUT);
  pinMode(ledPinRed, OUTPUT);

  Serial.begin(9600); 
}

void driveColor(int pinColor, int c, int t, int hr){
  // this will be the cookie-cutter function for starting LEDs and then fading LEDs
  int startLED = t;
  // int difference = (c-t)/20;
  for (startLED = t; startLED <= c; startLED +=30){
    analogWrite(pinColor, startLED);
    delay(90);
  }
  delay(hr);
  for (startLED = c; startLED >= t; startLED -=30){
    analogWrite(pinColor, startLED);
    delay(90);
  }
  
//  analogWrite(pinColor, c); // don't launch this yet.
//  Serial.println("LED brightness value (crest): ");
//  Serial.println(c);
//  Serial.println("Heart Rate: ");
//  Serial.println(hr);
//  delay(hr);
//  analogWrite(pinColor, t);
//  Serial.println("LED brightness value (trough): ");
//  Serial.println(t);
//  Serial.println("\n");
//  delay(hr);
}

void loop(){
  intensity = analogRead(intensityPin);
  intensity = intensity/4; // intensity can now take values from 0 to 255
  beatWidth = analogRead(beatWidthPin);
  beatWidth = beatWidth/8; // reducing the domain for amplitudes
  // beatWidth can now only take values from 0 to ~32

  heartRate = analogRead(heartRatePin);
  heartRate = 2*heartRate;
  // this will be used across the LEDs to inform delay

  Serial.println("Intensity: ");
  Serial.println(intensity);
  Serial.println("Beat width: ");
  Serial.println(beatWidth);
//  Serial.println("Heart Rate: ");
//  Serial.println(heartRate);
//  Serial.println("--------------");

  
  crest = intensity + beatWidth;
  trough = intensity - beatWidth;

  // setting the wave limits
  // edge case truth table:
  // when both intensity and beat are MAXIMUM, 
    // crest goes beyond 255, trough is okay.
  // when both intensity and beat are MINIMUM,
    // crest is okay (extreme value = 0), but trough goes below 0.
  // when intensity is HIGH but beat is LOW,
    // crest can go beyond 255, trough is still okay
  // when intensity is LOW, but beat is HIGH,
    // crest is okay, but trough again goes below 0

  // Conclusion: handle cases for trough < 0 and crest going above 255
  // INDEPENDENTLY.

  if ((crest >=0) && (trough >=0)){
    if (crest < 255 ){
      if (trough > 0){
        driveColor(ledPinGreen, crest, trough, heartRate);
        delay(100);
        driveColor(ledPinBlue, crest/2, trough, heartRate);
        delay(100);
        driveColor(ledPinRed, crest, trough, heartRate);
        Serial.println(crest);
        Serial.println(trough);
      }
      else{
        driveColor(ledPinGreen, crest, 0, heartRate);
        delay(100);
        driveColor(ledPinBlue, crest/2, 0, heartRate);
        delay(100);
        driveColor(ledPinRed, crest, 0, heartRate);
        Serial.println(crest);
        Serial.println(0);
      }
    }

    else{
      // set your crests to 255 explicitly
      if (trough > 0){
        driveColor(ledPinGreen, 255, trough, heartRate);
        delay(100);
        driveColor(ledPinBlue, 255/2, trough, heartRate);
        delay(100);
        driveColor(ledPinRed, 255, trough, heartRate);
        Serial.println(255);
        Serial.println(trough);
      }
      else{
        driveColor(ledPinGreen, 255, 0, heartRate);
        delay(100);
        driveColor(ledPinBlue, 255/2, 0, heartRate);
        delay(100);
        driveColor(ledPinRed, 255, 0, heartRate);
        Serial.println(255);
        Serial.println(0);
      }
    }
    
  }

  else{

    //debugger
    Serial.println("Crests and Troughs are now: ");
    Serial.println(crest);
    Serial.println(trough);
    Serial.println("----------------------------");
    delay(2000);
  }
}

IMG_20160921_000834

Leave a Reply