PCOMP: Final Project Progress

Due to the much earlier ICM final presentation, software development was almost done last week and I concentrated on the hardware development this week.

The goals I’ve achieved so far are like below:

  • Implemented multiplexers so that more than 30 LEDs can be manipulated individually
  • Developed flicking reactions of the LEDs so that they more look like real candle flames
  • Changed the microphone amplifier to a wind sensor
  • Developed an electronic match circuit

And followings are the sketches of the physical parts of this project:

[Wish candles]

#include <Tlc5940.h>
#include <tlc_config.h>

#define analogPinForRV    1   // change to pins you the analog pins are using
#define analogPinForTMP   0

const float zeroWindAdjustment =  .2; 
int TMP_Therm_ADunits;  
float RV_Wind_ADunits;   
float RV_Wind_Volts;
unsigned long lastMillis;
int TempCtimes100;
float zeroWind_ADunits;
float zeroWind_volts;
float WindSpeed_MPH;

#define TOTAL_LED 32
#define MAX_BRT 200
#define MIN_BRT 10

int b_init[] = {100, 70, 50, 60, 90, 80, 70, 90, 50, 100, 
  80, 60, 70, 100, 90, 80, 60, 50, 100, 70, 
  80, 90, 50, 100, 90, 60, 60, 70, 70, 80, 90, 100};

int dimming_init[] = {true, false, false, false, true, false, true, false, true, true, 
  true, false, true, false, true, false, true, false, true, false,
  true, true, false, true, false, false, true, true, false, false, true, true};

int spd[] = {5, 2, 1};

int b[TOTAL_LED];   // initial brightness
boolean dimming[TOTAL_LED];

int offLED;
int onLED;
int numOff;
boolean isBlown;

boolean ssrOpen;
boolean standby = false;
boolean reset = false;

int micValue;
int part;

int lightValue;

void initialise() {

  for(int i=0; i<TOTAL_LED; i++) {
    b[i] = b_init[i];
    dimming[i] = dimming_init[i];
  }

  offLED = 0;
  onLED = 0;
  numOff = 0;
  isBlown = false;

  ssrOpen = true;
  part = 0;

  standby = false;
  reset = false;
}

void setup() {

  Serial.begin(9600);

  initialise();
  ssrOpen = false;
  standby = true;
  offLED = TOTAL_LED;
  
  Tlc.init(0);

}

void loop() {

  if(ssrOpen) {
    readWind();

  }
  if(ssrOpen && WindSpeed_MPH > 3) {  
    isBlown = true;
    ssrOpen = false;
    if(part==0) numOff += 10;
    else if(part==1) numOff += 11;
    else numOff += 11;
    part++;
    WindSpeed_MPH = 0;
    
  }

  if(offLED < TOTAL_LED) {
    if(isBlown) {
      for(int i=0; i<TOTAL_LED; i++) {
        if(i==offLED) {
          boolean ended = blowout(i);
          if(ended) {
            offLED++;
            if(offLED >= numOff)  {
              isBlown = false;
              Serial.println(part);
              if(part<3) ssrOpen = true;
            }
          }
        }
        else if(i>offLED) flick(i);
        
        Tlc.set(i, b[i]);
      }
    }
    else {
      for(int i=numOff; i<TOTAL_LED; i++) {
        flick(i);

        Tlc.set(i, b[i]);
      }
    }
  
    Tlc.update();
  }
  
  if(Serial.available()) {
    char fromSerial = Serial.read();
    Serial.println(fromSerial);

    if(fromSerial == 'R') {
      standby = true;
    }
  }

  if(standby) {
    lightValue = analogRead(A2);
//    Serial.print("photocell: ");
//    Serial.println(lightValue);
    if(lightValue>910) {  
      standby = false;
      reset = true;
      Serial.println(0);
    }
  }

  if(reset) {
    if(onLED < TOTAL_LED) {
      boolean areAllCandlesOn = lightUp(onLED);
      if(areAllCandlesOn) onLED++;

      Tlc.set(onLED, b[onLED]);
    }
    else {
      initialise();
    }
    
    Tlc.update();
  }

  delay(10);
}

void readWind() {
  if (millis() - lastMillis > 200){   

    TMP_Therm_ADunits = analogRead(analogPinForTMP);
    RV_Wind_ADunits = analogRead(analogPinForRV);
    RV_Wind_Volts = (RV_Wind_ADunits *  0.0048828125);

    // these are all derived from regressions from raw data as such they depend on a lot of experimental factors
    // such as accuracy of temp sensors, and voltage at the actual wind sensor, (wire losses) which were unaccouted for.
    TempCtimes100 = (0.005 *((float)TMP_Therm_ADunits * (float)TMP_Therm_ADunits)) - (16.862 * (float)TMP_Therm_ADunits) + 9075.4;  

    zeroWind_ADunits = -0.0006*((float)TMP_Therm_ADunits * (float)TMP_Therm_ADunits) + 1.0727 * (float)TMP_Therm_ADunits + 47.172;  //  13.0C  553  482.39

    zeroWind_volts = (zeroWind_ADunits * 0.0048828125) - zeroWindAdjustment;  

   WindSpeed_MPH =  pow(((RV_Wind_Volts - zeroWind_volts) /.2300) , 2.7265);  

 //  Serial.println(WindSpeed_MPH);

   lastMillis = millis();    
  }
}

void flick(int iLed) {
  int spdIdx;
  if(iLed<10) spdIdx = 0;
  else if(iLed<21) spdIdx = 1;
  else spdIdx = 2;
  
  if(dimming[iLed]) {
    if(b[iLed] > MIN_BRT) {
      b[iLed]  = constrain((b[iLed]-spd[spdIdx]), MIN_BRT, MAX_BRT); 
    }
    else  dimming[iLed] = false;
  }
  else {
    if(b[iLed] < MAX_BRT) {
      b[iLed] = constrain((b[iLed]+spd[spdIdx]), MIN_BRT, MAX_BRT); //1;
    }
    else  dimming[iLed] = true;
  }
}

boolean blowout(int iLed) {
  b[iLed] = constrain((b[iLed]-15), 0, MAX_BRT);
  if(b[iLed] == 0) return true;
  else  return false;
}

boolean lightUp(int iLed) {
  b[iLed] = constrain((b[iLed]+10), 0, b_init[iLed]);
  if(b[iLed] >= b_init[iLed]) return true;
  else  return false;
}





In the above code, I used Tlc5940.h library to control the multiplexers and also used the example code of the wind sensor which was generated by the manufacturer to calculated the speed of the wind blown by the user.

Link of the Arduino sketch of the wind sensor manufacturer

[Electronic match]

#define LedPin 2

int mag = 1;
boolean stroke[2] = {false, false};
int cntStroke = 0;
int cntBurnOut = 0;

void setup() {
  pinMode(13, INPUT);
  pinMode(LedPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int tmp = digitalRead(13);
//  Serial.println(tmp);

  if((!stroke[1]) && (tmp!=mag)) {
    if(!stroke[0]) {
      mag = tmp;
      stroke[0] = true;
      Serial.println(tmp);
      Serial.print("stroke[0] = ");
      Serial.println(stroke[0]);
      digitalWrite(LedPin, HIGH);
      delay(10);
      digitalWrite(LedPin, LOW);
//      Serial.print("cntStroke = ");
//      Serial.println(cntStroke);
    }
    else {
      if( cntStroke <= 2 ) {
        
        mag = tmp;
        stroke[1] = true;

      Serial.println(tmp);
      Serial.print("cntStroke = ");
      Serial.println(cntStroke);
        Serial.println("ON");
      }
      else {
        stroke[0] = false;
        stroke[1] = false;
        Serial.print("TIME OVER: ");
        Serial.println(cntStroke);
        cntStroke = 0;
      }
    } 
  }

  if(stroke[0] && !stroke[1]) {
    if(cntStroke < 3) cntStroke++;
    else {
      stroke[0] = false;
      cntStroke = 0;
    }
  }

  if(stroke[1]) {
    digitalWrite(LedPin, HIGH);
    cntBurnOut++;
    
  }
  
  if(stroke[1] && (cntBurnOut>70)) {
    stroke[0] = false;
    stroke[1] = false;
    cntStroke = 0;
    cntBurnOut = 0;
    digitalWrite(LedPin, LOW);
    Serial.println("OFF");
  }

    delay(100);

}

 

About 90% of the technical part has been completed. The remaining job is adding two servos and two additional lights. On the top of that, we are focusing on the fabrication this week.

Leave a Reply

Your email address will not be published. Required fields are marked *