TASK #1:
In this part, the Arduino part went smoothly because all I have to do is building a circuit with two potentiometers, and respectively send the values, which I’m already quite familiar with.
However, it took me a while to finish the code of Processing. What I have to do is basically to keep track of the previous x and y values so that I can draw a line from there to the new x and y positions. In order to achieve that effect, I first set the initial value as 0 for both “x” and “y”. After that I respectively assigned two variants (namely “value1” and “value2” as you can see in the code below) to the received values, and then use the function “map()” to adjust the values so that they can be fit in the screen of Processing when we play the Etch-A-Sketch. Finally, I reset the values of “x” and “y” into the previous ones.
The interaction is quite interesting since it smartly combines Arduino and Processing to create something from scratch. It can serve as a foundational idea if I want to make an interactive project related to art someday.
Attached below is my code for Task #1:
Arduino:
/* SendMultipleValues This sketch repeatedly sends a record that contains two values: - The first value is the value of `millis()`, modulo 32768. - The second value is the analog value that is read from pin 9. If you attach a potentiometer to that pin, you can control this value by moving the pot. This sketch pairs well with the RecieveMultipleValues example from the Processing SerialRecord library <https://osteele.github.io/Processing_SerialRecord/>. Things to try: - Connect a second potentiometer to the Arduino, and send the values from both potentiometers. - Send the value from another sensor, such as temperature or proximity. by Oliver Steele, 2020-2022 This example code is in the public domain. */ #include "SerialRecord.h" // Change this number to send a different number of values SerialRecord writer(2); void setup() { Serial.begin(9600); //pinMode(6, INPUT); } void loop() { int sensorValue1 = analogRead(A0); int sensorValue2 = analogRead(A1); writer[0] = sensorValue1; writer[1] = sensorValue2; writer.send(); // This delay slows down the loop. This can make it easier to debug the // program. delay(10); }
Processing:
/** * Example sketch for the SerialRecord library for Processing. * * Receives two integers from the serial port, and uses them to control the x * and y position of a circle on the canvas. */ import processing.serial.*; import osteele.processing.SerialRecord.*; Serial serialPort; SerialRecord serialRecord; float px = 0; float py = 0; void setup() { size(500, 500); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); // If the Arduino sketch sends a different number of values, modify the number // `2` on the next line to match the number of values that it sends. serialRecord = new SerialRecord(this, serialPort, 2); background(0); } void draw() { serialRecord.read(); int value1 = serialRecord.values[0]; int value2 = serialRecord.values[1]; float x = map(value1, 0, 1024, 0, width); float y = map(value2, 0, 1024, 0, height); stroke(150); strokeWeight(10); line (px, py, x, y); px = x; py = y; //circle(x, y, 20); }
TASK #2:
My partner: Steve Lu
We finished the basic structures of the codes quickly based on the experience in Task #1 and what we’ve learnt from previous classes. However, when we stuck the servo motors, integrated the codes and ran them, the problem occurred. First, one servo motor moved in an opposite direction. What’s more, the motors failed to move precisely when the ball reaches the end. The first problem is easy to solve. We just need to change the position of that motor. But the second problem is rather tricky. Eventually, considering that the servo motor would take some time to react to the signal, we sent the signal when the ball is about to approach the end, instead of exactly when it reached the end, effectively solving the problem.
To make the work more interesting, we added the sound effects of table tennis and stuck two rackets (made of cardboard) on the servo motors, creating the effect of the computer playing table tennis, which is one of the most popular sports in NYUSH.
Our teamwork went well, I was in charge of the Processing part while Steve was in charge of Arduino. But still he gave me a lot of advice to optimize the code.
The principle of this interaction is about sending a value from Processing to Arduino. I think it quite creative though challenging. Compared to Task #1, Task #2 allows a seemingly automatic interaction, which also clearly shows the differences between two forms of signal sending.
Attached below are my codes for Task #2:
Arduino:
#include "SerialRecord.h" #include <Servo.h> Servo left; // create servo object to control a servo Servo right; int volume, prevolume; int move = -1; // Change this number to the number of values you want to receive SerialRecord reader(1); void setup() { Serial.begin(9600); right.attach(6); left.attach(3); } void loop() { if (reader.read()) { move = reader[0]; } if (move==1) { left.write(90); delay(200); left.write(0); move = -1; } if (move==0) { right.write(90); delay(200); right.write(0); move = -1; } }
Processing:
import processing.sound.*; import processing.serial.*; import osteele.processing.SerialRecord.*; float x, y; float i=0; boolean left = true, right = false; int runChecker = 0; SoundFile sample; Serial serialPort; SerialRecord serialRecord; void setup() { sample = new SoundFile(this, "Ping Pong Table Tennis Sound Effect.mp3"); sample.loop(); fullScreen(); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); serialRecord = new SerialRecord(this, serialPort, 1); //serialRecord.logToCanvas(false); } void draw() { //println(frameRate); background(0); circleBounce(); } void circleBounce() { if (i<=0) { left = true; right = false; } if (i>=0.95*width && runChecker==0) { serialRecord.values[0] = 1; serialRecord.send(); // send it! runChecker = 1; } if (i<=0.05*width && runChecker==1) { serialRecord.values[0] = 0; serialRecord.send(); // send it! runChecker = 0; } if (i>=width) { right = true; left = false; } if (left==true) { i = lerp(i, 1.1*width, 0.02); //x += -0.1*(0.4/width)*i*(i-width); } if (right==true) { i = lerp(i, -0.1*width, 0.02); //x -= -0.1*(0.4/width)*i*(i-width); } fill(255); ellipse(i, height/2, 70, 70); }