Recitation 8
Task 1 Documentation
30 minutes before the recitation class, I and my partner entered the classroom and started to do the recitation project. Task 1 was actually very straightforward. I first connected the two potentiometers to the circuit in A0 and A1, as had been done many times in classes. Then, I used the SerialRecord example SendMultipleValues as a basis to write an Arduino sketch that reads their values and sends them serially. Here is the code:
#include "SerialRecord.h" SerialRecord writer(2); void setup() { Serial.begin(9600); } void loop() { int sensorValue = analogRead(A0); int sensorValue1 =analogRead(A1); writer[0] = sensorValue; writer[1] = sensorValue1; writer.send(); delay(10); }
And then I used the SerialRecord example ReceiveMultipleValues as a basis to write a Processing sketch that draws a circle and reads those two analog values from Arduino. And a circle will change its position according to the two potentiometers. I did not meet with any difficulties in this step. Here is the video recording:
It worked smoothly. Here is the Processing code:
import processing.serial.*; import osteele.processing.SerialRecord.*; float py; float px; Serial serialPort; SerialRecord serialRecord; void setup() { size(640, 360); background(102); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); ellipseMode(CENTER); // 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); } 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(255); ellipse(x, y, 20, 20); }
Then I moved to the next step, which was drawing sketches using the two potentiometers. Again, it was quite analogous to the previous step, in that it just changed ellipses into lines. But it has something new, which was the involvement of previous Xs and previous Ys. Here is the code of Processing in this step:
import processing.serial.*; import osteele.processing.SerialRecord.*; float py; float px; Serial serialPort; SerialRecord serialRecord; void setup() { size(640, 360); background(102); 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); } 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(255); line(x, y, px, py); px=x; py=y; }
And here is the video recording of my project:
Then I partnered with Siwei Chen and progressed to task 2.
Task 2 Documentation
This task is a hard nut to crack. The first challenge we met with was that: when I was programming the bouncing of the ball, the sketch reserved and showed all the previous locations of the circle. Luckily, we figured out by ourselves that we could use the function “background” at the beginning of “void draw()” instead of just putting one in “void setup()”.
Then, it was a delay between Processing and Arduino. Specifically, I finished the Processing code of changing values every time the circle reaches the edge of the screen, as well as the Arduino code that alters the angle of the servos every time it receives the number 1 from Processing. But we found that there were some delays between the two codes, making the product seem weird eventually. It was like this:
And the code was like this:
(Processing)
import processing.serial.*; import osteele.processing.SerialRecord.*; Serial serialPort; SerialRecord serialRecord; int x=75; int direction=20; int radius=75; void setup() { fullScreen(); background(0); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); serialRecord = new SerialRecord(this, serialPort, 2); ellipseMode(CENTER); } void draw() { fill(0); rect(0, 0, width, height); noStroke(); // display instructions fill(255); ellipse(x, height/2, 2*radius, 2*radius); if (x<radius||x>width-radius) { direction*=-1; } x=x+direction; if (x<radius) { serialRecord.values[0] = 1; } else serialRecord.values[0] = 0; if (x>width-radius) { serialRecord.values[1] = 1; } else serialRecord.values[1] = 0; serialRecord.send(); }
(Arduino)
#include <Servo.h> #include "SerialRecord.h" Servo servo1; Servo servo2; SerialRecord reader(2); void setup() { Serial.begin(9600); servo1.attach(9); servo2.attach(10); } void loop() { reader.read(); if (reader[0] == 1) { servo1.write(120); delay(100); }else servo1.write(60); if (reader[1] == 1) { servo2.write(60); delay(100); }else servo2.write(120); }
Then we asked the professor, and he instructed us that the problem was that Processing was sending signals to Arduino too quickly, such that every time values [0] and [1] were being sent to let Arduino alter the state of servos, Processing quickly changed them back to let Arduino not do that. So I applied the method of the previous state to decrease the frequency of Processing sending signals to Arduino. And Rudi told us to use “if(reader. read())” instead of “reader. read()”. I don’t know why, and he said he didn’t as well.
Finally, we made it by reforming the code, with the help of the two professors. Here is the video recording of our final product:
And here is the final version of the codes:
(Arduino)
#include <Servo.h> #include "SerialRecord.h" Servo servo1; Servo servo2; SerialRecord reader(2); void setup() { Serial.begin(9600); servo1.attach(9); servo2.attach(10); } void loop() { if (reader.read()) { if (reader[0] == 1) { servo1.write(120); delay(100); servo1.write(60); } if (reader[1] == 1) { servo2.write(60); delay(100); servo2.write(120); } } }
(Processing)
import processing.serial.*; import osteele.processing.SerialRecord.*; int pre1, pre2; Serial serialPort; SerialRecord serialRecord; int x=75; int direction=20; int radius=75; void setup() { fullScreen(); background(0); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); serialRecord = new SerialRecord(this, serialPort, 2); ellipseMode(CENTER); } void draw() { fill(0); rect(0, 0, width, height); noStroke(); // display instructions fill(255); ellipse(x, height/2, 2*radius, 2*radius); if (x<radius||x>width-radius) { direction*=-1; } x=x+direction; if (x<radius) { serialRecord.values[0] = 1; } else serialRecord.values[0] = 0; if (x>width-radius) { serialRecord.values[1] = 1; } else serialRecord.values[1] = 0; if (serialRecord.values[0]!=pre1||serialRecord.values[1]!=pre2) { serialRecord.send(); } pre1=serialRecord.values[0]; pre2=serialRecord.values[1]; }