|
|
Line 68: |
Line 68: |
| #include <Servo.h> | | #include <Servo.h> |
| | | |
| // timing
| |
| unsigned long currentTime = 0;
| |
|
| |
| unsigned long lastTimeA = 0;
| |
| unsigned long lastTimeB = 0;
| |
| unsigned long lastTimeC = 0;
| |
| unsigned long lastTimeD = 0;
| |
| unsigned long lastTimeE = 0;
| |
| unsigned long lastTimeF = 0;
| |
|
| |
| const int baseServoDelayTimeA = 17300;
| |
| const int baseServoDelayTimeB = 11020;
| |
| const int baseServoDelayTimeC = 15400;
| |
| const int baseServoDelayTimeD = 12800;
| |
| const int baseServoDelayTimeE = 8400;
| |
| const int baseServoDelayTimeF = 6300;
| |
|
| |
| float randMultiplier = 1.0;
| |
|
| |
| long randNumber;
| |
|
| |
| //sensors
| |
| const float sensorTriggerValueA = 700;
| |
| const float sensorTriggerValueB = 520;
| |
| const float sensorTriggerValueC = 650;
| |
| const float sensorTriggerValueD = 880;
| |
| const float sensorTriggerValueE = 950;
| |
| const float sensorTriggerValueF = 1100;
| |
|
| |
| float getSensorValuePpm (int sensorPin);
| |
|
| |
| const int sensorA = 36;
| |
| const int sensorB = 39;
| |
| const int sensorC = 34;
| |
| const int sensorD = 35;
| |
| const int sensorE = 32;
| |
| const int sensorF = 33;
| |
|
| |
| float gasValueSensorA = getSensorValuePpm (sensorA);
| |
| float gasValueSensorB = getSensorValuePpm (sensorB);
| |
| float gasValueSensorC = getSensorValuePpm (sensorC);
| |
| float gasValueSensorD = getSensorValuePpm (sensorD);
| |
| float gasValueSensorE = getSensorValuePpm (sensorE);
| |
| float gasValueSensorF = getSensorValuePpm (sensorF);
| |
|
| |
| //servos
| |
| const int servoPinA = 19;
| |
| const int servoPinB = 18;
| |
| const int servoPinC = 05;
| |
| const int servoPinD = 17;
| |
| const int servoPinE = 16;
| |
| const int servoPinF = 04;
| |
|
| |
| Servo servoA;
| |
| Servo servoB;
| |
| Servo servoC;
| |
| Servo servoD;
| |
| Servo servoE;
| |
| Servo servoF;
| |
|
| |
| boolean isLeftA;
| |
| boolean isLeftB;
| |
| boolean isLeftC;
| |
| boolean isLeftD;
| |
| boolean isLeftE;
| |
| boolean isLeftF;
| |
|
| |
| //function declarations
| |
| void playSound(unsigned long &lastTime, int sensorPin, Servo &servo, float &gasValueSensor, boolean &isLeft, int baseServoDelayTime, float sensorTriggerValue);
| |
|
| |
| float getSensorValuePpm (int sensorPin);
| |
|
| |
| void setup() {
| |
| analogSetAttenuation(ADC_11db);
| |
| Serial.begin(9600);
| |
|
| |
| servoA.attach(servoPinA);
| |
| servoA.write(30);
| |
| isLeftA = true;
| |
|
| |
| servoB.attach(servoPinB);
| |
| servoB.write(30);
| |
| isLeftB = true;
| |
|
| |
| servoC.attach(servoPinC);
| |
| servoC.write(30);
| |
| isLeftC = true;
| |
|
| |
| servoD.attach(servoPinD);
| |
| servoD.write(30);
| |
| isLeftD = true;
| |
|
| |
| servoE.attach(servoPinE);
| |
| servoE.write(30);
| |
| isLeftE = true;
| |
|
| |
| servoF.attach(servoPinF);
| |
| servoF.write(30);
| |
| isLeftF = true;
| |
| }
| |
|
| |
| void loop() {
| |
| currentTime = millis();
| |
|
| |
| playSound(lastTimeA, sensorA, servoA, gasValueSensorA, isLeftA, baseServoDelayTimeA, sensorTriggerValueA);
| |
| playSound(lastTimeB, sensorB, servoB, gasValueSensorB, isLeftB, baseServoDelayTimeB, sensorTriggerValueB);
| |
| playSound(lastTimeC, sensorC, servoC, gasValueSensorC, isLeftC, baseServoDelayTimeC, sensorTriggerValueC);
| |
| playSound(lastTimeD, sensorD, servoD, gasValueSensorD, isLeftD, baseServoDelayTimeD, sensorTriggerValueD);
| |
| playSound(lastTimeE, sensorE, servoE, gasValueSensorE, isLeftE, baseServoDelayTimeE, sensorTriggerValueE);
| |
| playSound(lastTimeF, sensorF, servoF, gasValueSensorF, isLeftF, baseServoDelayTimeF, sensorTriggerValueF);
| |
| }
| |
|
| |
| //functions
| |
|
| |
| void playSound(unsigned long &lastTime, int sensorPin, Servo &servo, float &gasValueSensor, boolean &isLeft, int baseServoDelayTime, float sensorTriggerValue){
| |
|
| |
| //generate multiplier and adjust delaytime
| |
| randMultiplier = 0.7 + (random(0, 341) / 100.0);
| |
| int adjustedDelayTime = baseServoDelayTime * randMultiplier;
| |
|
| |
| if (currentTime - lastTime >= adjustedDelayTime){
| |
| // check if timing works
| |
| Serial.print("Random delayTime");
| |
| Serial.println(adjustedDelayTime);
| |
| Serial.println("Triggering sensor reaading");
| |
| gasValueSensor = getSensorValuePpm(sensorPin);
| |
| // check sensor value
| |
| Serial.print("Sensor Value: ");
| |
| Serial.println(gasValueSensor);
| |
|
| |
| if (gasValueSensor > sensorTriggerValue){
| |
| Serial.println("Triggering servo");
| |
| // move servo to play sound
| |
| if (isLeft == true){
| |
| servo.write(0);
| |
| isLeft = false;
| |
| Serial.println("right");
| |
| }
| |
| else{
| |
| servo.write(30);
| |
| isLeft = true;
| |
| Serial.println("left");
| |
| }
| |
| Serial.println("Servo moved. Last Time updated.");
| |
| }
| |
| // update lastTime
| |
| lastTime = currentTime;
| |
| }
| |
| }
| |
|
| |
| float getSensorValuePpm (int sensorPin) {
| |
| float voltage = analogRead(sensorPin) * (5.0 / 1023.0);
| |
| float RS_air = 10.0;
| |
| float RL = 2.0;
| |
| float ratio = RL / RS_air;
| |
| float RS = ((5.0 / voltage) - 1.0) * RL;
| |
| float ppm = 1000.0 * pow((RS / RS_air), ratio);
| |
| return ppm;
| |
| }
| |
|
| |
|
| ==Manual construction== | | ==Manual construction== |
| I was responsible for the structural and mechanical implementation of the project since my strengths lie far more in this area than in writing computer code. Additionally, unlike Hanna, I have the necessary resources at home to craft. | | I |
| | |
| We needed a mount that would allow the servo motors to hover above the guitar strings so they could pluck them individually. The servo motors had to be positioned at a certain distance from each other to avoid interfering with one another when striking the strings. We had already identified this issue through a cardboard prototype. Since guitar picks were to be attached to the motors, increasing the radius of the strike, it made sense to always leave two strings between those being played.
| |
| | |
| I decided to attach two motors to one bar. The construction sketch can be seen here:
| |
| | |
| Since I couldn’t guarantee millimeter-precise construction, and factors like the surface, variations in the way the picks were attached, or different motor models could create height differences, it was necessary to allow for fine adjustments to the height of the mount. For this, I used special adjustment screws that allow the height of the mounting beams to be individually adjusted on both sides. Unlike regular screws, these have two types of threads: the upper thread remains fixed in the wood, while the lower thread can be screwed in and out like a standard screw. This enables precise millimeter-level height adjustments to fit the conditions.
| |
| | |
| Additionally, the sensors had to be connected to the breadboard. To do this, I soldered cables—each consisting of three wires—of sufficient length to each of the six sensors. I then soldered a connector to each wire to facilitate easy attachment to the breadboard.
| |
|
| |
|
| * | | * |
| *
| |
| *
| |
| *
| |
|
| |
| ==The Plants ==
| |
|
| |
| *Hyacinth
| |
| *Euphorbia
| |
| *Fern
| |
| *Begonia
| |
| * Peperomia
| |
| *Alocasia
| |
|
| |
|
| =='''Exhibition'''== | | =='''Exhibition'''== |