Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
415 lines (344 sloc)
11.6 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "sensor.h" | |
void setup() { | |
Serial.begin(9600); | |
// HWSERIAL.begin(9600); | |
leds.begin(); | |
leds.show(); | |
pinMode(PIR_PIN, INPUT_PULLUP); | |
pinMode(SERVO_PIN, OUTPUT); | |
pinMode(PIR_REMOTE_PIN, INPUT); | |
pinMode(BREATH_REMOTE_PIN, OUTPUT); | |
servo.attach(SERVO_PIN); //set up the servo on pin 3 | |
servo.write(servoOpenPos); //open flower to start | |
servo.detach(); | |
for (int i = 0; i < WIND_HIST_LEN; i++) { | |
windHistory[i] = 0; | |
} | |
#ifdef USE_IR_PROX | |
if (!pulse.isPresent()) { | |
Serial.print("No SI114x found on port "); | |
Serial.println(SI114_PORT); | |
} else { | |
Serial.println("setup"); | |
} | |
pulse.initPulsePlug(); //Initialize I2C bus | |
pulse.setLEDcurrents(6, 6, 6); //set prox sensor LED currents | |
pulse.setLEDdrive(4, 2, 1); //set which LEDs are active on which pulse | |
#endif | |
closeFlower(); | |
} | |
void setOnboardLEDs(uint8_t rValue, uint8_t gValue, uint8_t bValue) { | |
for (int i = 0; i < 60; i++) { | |
leds.setPixelColor(0, rValue, gValue, bValue); | |
leds.setPixelColor(1, rValue, gValue, bValue); | |
} | |
leds.show(); | |
} | |
int getRawWind() { | |
return analogRead(RAW_VOLT_ANALOG_WIND_SENSOR_PIN); | |
} | |
int getRawWindTemp() { | |
return analogRead(TEMPERATURE_ANALOG_WIND_SENSOR_PIN); | |
} | |
void openFlower() { | |
servoTargetPosition = servoOpenPos; | |
servoStartPosition = servoPosition; | |
flowerOpenStartTime = millis(); | |
ledStartColorR = ledCloseColorR; | |
ledStartColorG = ledCloseColorG; | |
ledStartColorB = ledCloseColorB; | |
ledEndColorR = ledOpenColorR; | |
ledEndColorG = ledOpenColorG; | |
ledEndColorB = ledOpenColorB; | |
fadeStartTime = millis(); | |
} | |
void closeFlower() { | |
servoTargetPosition = servoClosePos; | |
servoStartPosition = servoPosition; | |
flowerOpenStartTime = millis(); | |
ledStartColorR = ledOpenColorR; | |
ledStartColorG = ledOpenColorG; | |
ledStartColorB = ledOpenColorB; | |
ledEndColorR = ledCloseColorR; | |
ledEndColorG = ledCloseColorG; | |
ledEndColorB = ledCloseColorB; | |
fadeStartTime = millis(); | |
} | |
void updateLEDs() { | |
long now = millis(); | |
if (now - lastLedUpdateTime > ledUpdateInterval) { | |
lastLedUpdateTime = now; | |
long deltaT = now - fadeStartTime; | |
if (deltaT <= fadeTime) { | |
setOnboardLEDs( | |
(ledEndColorR - ledStartColorR) * deltaT / fadeTime + ledStartColorR, | |
(ledEndColorG - ledStartColorG) * deltaT / fadeTime + ledStartColorG, | |
(ledEndColorB - ledStartColorB) * deltaT / fadeTime + ledStartColorB | |
); | |
} else { | |
if (overallState == STATE_NEUTRAL) { | |
setOnboardLEDs( | |
ledCloseColorR, | |
ledCloseColorG, | |
ledCloseColorB | |
); | |
} else if (overallState == STATE_OPEN) { | |
setOnboardLEDs( | |
ledOpenColorR, | |
ledOpenColorG, | |
ledOpenColorB | |
); | |
} else if (overallState == STATE_PROX) { | |
setOnboardLEDs( | |
ledProxColorR, | |
ledProxColorG, | |
ledProxColorB | |
); | |
} | |
} | |
} | |
} | |
void updateFlowerServo() { | |
long deltaT = millis() - flowerOpenStartTime; | |
if (deltaT <= flowerOpenTime) { | |
if (!isOpenOrClosing) { | |
servo.attach(SERVO_PIN); //set up the servo on pin 3 | |
isOpenOrClosing = true; | |
} | |
servoPosition = (servoTargetPosition - servoStartPosition) * deltaT / flowerOpenTime + servoStartPosition; | |
servo.write(servoPosition); //Close flower to start | |
} else { | |
if (isOpenOrClosing) { | |
servo.detach(); | |
isOpenOrClosing = false; | |
} | |
} | |
} | |
const int samples = 4; // samples for smoothing 1 to 10 seem useful | |
// increase for smoother waveform (with less resolution) | |
float Avect = 0.0; | |
float Bvect = 0.0; | |
float Cvect = 0.0; | |
float Tvect, x, y, angle = 0; | |
// some printing options for experimentation (sketch is about the same) | |
//#define SEND_TO_PROCESSING_SKETCH | |
#define PRINT_RAW_LED_VALUES // prints Raw LED values for debug or experimenting | |
// #define PRINT_AMBIENT_LIGHT_SAMPLING // also samples ambient slight (slightly slower) | |
// good for ambient light experiments, comparing output with ambient | |
unsigned long lastMillis, red, IR1, IR2; | |
void printProx() { | |
} | |
float getWind() { | |
// This code is from Modern Devices | |
//Wind sensor globals | |
const float zeroWindAdjustment = .2; // negative numbers yield smaller wind speeds and vice versa. | |
int TMP_Therm_ADunits; //temp termistor value from wind sensor | |
float RV_Wind_ADunits; //RV output from wind sensor | |
float RV_Wind_Volts; | |
// int TempCtimes100; | |
float zeroWind_ADunits; | |
float zeroWind_volts; | |
float WindSpeed_MPH; | |
TMP_Therm_ADunits = analogRead(TEMPERATURE_ANALOG_WIND_SENSOR_PIN); | |
RV_Wind_ADunits = analogRead(RAW_VOLT_ANALOG_WIND_SENSOR_PIN); | |
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; | |
// This from a regression from data in the form of | |
// Vraw = V0 + b * WindSpeed ^ c | |
// V0 is zero wind at a particular temperature | |
// The constants b and c were determined by some Excel wrangling with the solver. | |
WindSpeed_MPH = pow(((RV_Wind_Volts - zeroWind_volts) / .2300) , 2.7265); | |
return WindSpeed_MPH; | |
} | |
int getUltrasonic(){ | |
return analogRead(ULTRASONIC_ANALOG_PIN); | |
} | |
void runWindAvgs() { | |
long now = millis(); | |
if (now - lastWindSampleTime > windSampleInterval) { | |
// Currently tuned to sample every 20ms roughly | |
int raw = getRawWind(); | |
lowWindAvg = lowWindAvg * lowWindAvgFactor + raw * (1 - lowWindAvgFactor); | |
highWindAvg = highWindAvg * highWindAvgFactor + raw * (1 - highWindAvgFactor); | |
lastBpassWind = bpassWind; | |
bpassWind = (int)(highWindAvg-lowWindAvg); | |
windHistory[windHistoryIndex] = bpassWind - lastBpassWind; | |
// Serial.print(" ---> Wind history #"); | |
// Serial.print(windHistoryIndex); | |
// Serial.print(": "); | |
// Serial.println(windHistory[windHistoryIndex]); | |
windHistoryIndex++; | |
if (windHistoryIndex >= WIND_HIST_LEN) windHistoryIndex = 0; | |
lastWindSampleTime = now; | |
} | |
} | |
int maxBpassHistory() { | |
int maxVal = -1000000; | |
for (int i = 0; i < WIND_HIST_LEN; i++) { | |
if (windHistory[i] > maxVal) maxVal = windHistory[i]; | |
} | |
return maxVal; | |
} | |
void runBreathDetection() { | |
int diffSum = 0; | |
for (int i = 0; i < WIND_HIST_LEN; i++) { | |
diffSum += windHistory[i]; | |
} | |
// Serial.print(" ---> runBreathDetection: "); | |
// Serial.print(breathState); | |
// Serial.print(" -> "); | |
// Serial.println(diffSum); | |
if (diffSum < -10 && breathState == REST) { | |
breathOn(); | |
} else if (diffSum > -2 && breathState == BREATH) { | |
breathOff(); | |
} | |
} | |
void breathOn() { | |
breathState = BREATH; | |
digitalWrite(BREATH_REMOTE_PIN, HIGH); | |
// HWSERIAL.print("B"); | |
// Serial.println("B"); | |
} | |
void breathOff() { | |
breathState = REST; | |
digitalWrite(BREATH_REMOTE_PIN, LOW); | |
// HWSERIAL.print("E"); | |
// Serial.println("E"); | |
} | |
void updatePIR() { | |
long now = millis(); | |
if (now < 5000) return; // Let the PIR setup | |
if (now - lastPIRSampleTime > pirSampleInterval) { | |
int value = digitalRead(PIR_PIN); | |
pirHistory[pirHistoryIndex] = value; | |
pirHistoryIndex++; | |
if (pirHistoryIndex >= PIR_HIST_LEN) pirHistoryIndex = 0; | |
PirState newState = PIR_ON; | |
for (int i = 0; i < PIR_HIST_LEN; i++) { | |
if (pirHistory[i] == 1) { | |
newState = PIR_OFF; | |
break; | |
} | |
} | |
pirState = newState; | |
if (pirState == PIR_ON) { | |
openTimeoutLastEvent = now; | |
} | |
lastPIRSampleTime = now; | |
} | |
} | |
void updateProx() { | |
long now = millis(); | |
if (now - lastUltraSampleTime > ultraSampleInterval) { | |
int ultraVal = (int)ultrasonic.Ranging(CM); | |
Serial.print(" ---> Ultrasonic: "); | |
Serial.println(ultraVal); | |
ultraHistory[ultraHistoryIndex] = ultraVal; | |
ultraHistoryIndex++; | |
if (ultraHistoryIndex >= ULTRA_HIST_LEN) ultraHistoryIndex = 0; | |
lastUltraSampleTime = now; | |
isProximate = false; | |
for (int i = 0; i < ULTRA_HIST_LEN; i++) { | |
if (ultraHistory[i] < ultraThres) { | |
isProximate = true; | |
break; | |
} | |
} | |
} | |
} | |
bool isProx() { | |
#ifdef FAKE_PROX | |
return true; | |
#else | |
return isProximate; | |
#endif | |
} | |
void evaluateState() { | |
switch (overallState) { | |
case STATE_NEUTRAL: { | |
// if (pirState == PIR_ON) { | |
if (remoteState == STATE_OPEN) { | |
overallState = STATE_OPEN; | |
// HWSERIAL.print("O"); | |
// Serial.println("O"); | |
openFlower(); | |
} | |
break; | |
} | |
case STATE_OPEN: { | |
// long now = millis(); | |
// if (now - openTimeoutLastEvent > openTimeout) { | |
if (remoteState == STATE_NEUTRAL) { | |
// HWSERIAL.print("C"); | |
// Serial.println("C"); | |
overallState = STATE_NEUTRAL; | |
closeFlower(); | |
} else if (isProx()) { | |
overallState = STATE_PROX; | |
// HWSERIAL.print("P"); | |
// Serial.println("P"); | |
} | |
break; | |
} | |
case STATE_PROX : { | |
if (remoteState == STATE_NEUTRAL) { | |
// HWSERIAL.print("C"); | |
// Serial.println("C"); | |
overallState = STATE_NEUTRAL; | |
closeFlower(); | |
} else if (!isProx()) { | |
overallState = STATE_OPEN; | |
breathOff(); | |
// HWSERIAL.print("F"); | |
// Serial.println("F"); | |
} else { | |
runBreathDetection(); | |
} | |
break; | |
} | |
} | |
} | |
void readRemoteState() { | |
long now = millis(); | |
if (now - lastRemotePIRRead > remotePIRReadInteval) { | |
int value = digitalRead(PIR_REMOTE_PIN); | |
if (value == HIGH) { | |
remoteState = STATE_OPEN; | |
} else { | |
remoteState = STATE_NEUTRAL; | |
} | |
lastRemotePIRRead = now; | |
} | |
// if (HWSERIAL.available() > 0) { | |
// uint8_t incomingByte; | |
// incomingByte = HWSERIAL.read(); | |
// // Serial.println(incomingByte, HEX); | |
// if (incomingByte == 'O') { | |
// remoteState = STATE_OPEN; | |
// } else if (incomingByte == 'C') { | |
// remoteState = STATE_NEUTRAL; | |
// } | |
// } | |
} | |
void loop() { | |
readRemoteState(); | |
updateLEDs(); | |
updateFlowerServo(); | |
// updatePIR(); | |
runWindAvgs(); | |
updateProx(); | |
evaluateState(); | |
// runBreathDetection(); | |
// if (millis() % 2000 < 1000) { | |
// runBreathDetection(); | |
// } else { | |
// Serial.print(runningAvg); | |
// Serial.print("\t"); | |
// Serial.println(pirState); | |
// } | |
} |