Task #1: Make a Processing Etch-A-Sketch Task
Trivial code and wiring.
However, it’s worth noting that instability with the sensor values, which perhaps has mutiple factors contributing to the problem. Unstable current output is probably one of the factors, plus the limited accuracy of ADC. One easy way out is to read the value every other second or two. The drawback is obvious too, that it stablizes the value at the stake of sensitivity. One more interesting observation from Rudi into Andy Ye’s computer, where a noticeable noise appear, is that connecting the computer to a power supply may potentially give rise to the noise. This makes perfect sense as industrial disturbance is always something that we should pay attention to in any kind of circuit experiments, especially those dealing with high-precision data.
#2: Bouncy Table Tennis
Trival code and wiring,
Though there’s a huge space for refinning the details. In the demo video, largely we see an animation that is linear. Linear animation are pale and dull, because we don’t anticipate things to move that way in our physical life. Picture a table tennis ball flying to you, you seize the chance and hit it back. Speed varys along the way. Ruled by Newton’s Second Law of motion, everything here on earth has something called acceleration! So, I decided to mimic the kinda feeling in the animation, making a namely non-linear motion.
The first solution that came into my mind, is to use math functions to control the speed. Since we were able to tell the exact x-coordinate of the ball, given an expression of speed-verse-displacement, we shall control the acceleration as we desire. Unfortunately, I found it impracticable. To control the fine osciliation, we need to specify the length the ball travels. However, processing runs in a digital way, meaning that it’s incontinuous so that I could not integrate the function to get the distance. Plus, the framerate is also not always a constant but subject to change. Although adapting a simple harmonic osciliation model may work, I don’t want to solve a second order differential equation for the constants needed to finely control the motion.
So, I turned to lerp(), namely a built-in function to do linear interpolation. With a single line that iterates the value like this,
i = lerp(i, -0.1*width, 0.02);
a linear motion can be easily realized.
With all that done, I thought it was pretty much it, until I noticed the inharmoniness occurred when the pats hit the ball. Think about playing table tennis, you cannot put your hand in its place to hit the ball. Only you draw your hand back a little bit in advance and wave your hand toward the ball, can one hit the ball hard.
Taking that into consideration, I decided to add a little more feature, allowing the servo hands to act as if they know the ball is coming. The logic is simple, changing the if conditionals so that the servos move a bit in advance like,
from
if (i>=width) {...}
to
if (i>=0.95*width) {...}
However, the conditonals gave rist to another problem, that the newly introduced interval condition instead of the moment condition, potentially caused the hands to move repeatedly during the period, which requires a design to let it move only once. Thus, I improved the conditonals as
if (i>=0.95*width && runChecker==0) {...}
Full code for reference (p≧w≦q)
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); } 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(8);
left.attach(9);
}
void loop() {
if (reader.read()) {
move = reader[0];
}
if (move==1) {
left.write(90);
delay(500);
left.write(0);
move = -1;
}
if (move==0) {
right.write(90);
delay(500);
right.write(0);
move = -1;
}
}
Leave a Reply