Recitation 8: Serial Communication
In this recitation, we were asked to finish two tasks. The first one is to create a Processing Etch-A-Sketch. The second one is to create a ball with two hands bouncing it back and forth using Processing and servo motors.
Task #1: Make a Processing Etch-A-Sketch
In this task, we needed to make a painting pad on Processing with two potentiometers controlling the line’s location. First, I built up a circuit with two potentiometers and sent their values to the computer using SendMultipleValues as a basis.
#include "SerialRecord.h" SerialRecord writer(2); void setup() { Serial.begin(9600); } void loop() { int sensorValue1 = analogRead(A0); int sensorValue2 = analogRead(A1); writer[0] = sensorValue1; writer[1] = sensorValue2; writer.send(); delay(20); }
Then, I wrote a sketch on Processing and used two values to control the movement of a circle.
import processing.serial.*; import osteele.processing.SerialRecord.*; Serial serialPort; SerialRecord serialRecord; 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); } void draw() { background(0); 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); circle(x, y, 20); }
Everything went smoothly, so I jumped to the step where I needed to modify the circle into the line. The first thing I did was replace the circle with the line. However, the line was not as smooth as expected. I asked an IMA fellow for help, and it turned out that I needed to set the previous location of the line controlled by the potentiometers as the endpoint to get a smooth line. After modification, I got my own Etch-A-Sketch.
import processing.serial.*; import osteele.processing.SerialRecord.*; Serial serialPort; SerialRecord serialRecord; float px; float py; void setup() { size(500, 500); background(122); 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]; //line(value1, value2, value1, value2); float x = map(value1, 0, 1024, 0, width); float y = map(value2, 0, 1024, 0, height); //circle(x, y, 20); stroke(255); line(x, y, px, py); px = x; py = y;
Task #2
For this task, I teamed up with Harvey Luo. The rationale behind this game is the opposite of task 1, as we need to send the value from Processing to control the Arduino.
Our thought for this one was to create two values representing which side of the screen the ball hit, and the two values would control the corresponding servo motor to rotate a certain angle, like two servo motors hitting the ball back and forth.
We start with the Processing end. It did not take long before we met our first challenge. We did not know how to move the ball in the opposite direction once it hit the edge of the screen. Under the guidance of Professor Haider, we knew that by multiplying -1 with speedX, the ball could move to the other side.
We modified the ReceiveMultipleValues example in Arduino and ran our first trial. Nothing happened. We checked the code many times until one of the LA told us we didn’t insert the cable into the right slot of the servo motor.
After correction, we noticed that the servo motor only moved in one direction and stopped. We went back to the Processing code, checked it, and found that we wrote the function of serialRecord.send() outside the if() part, making the value sent only once.
if ( x > width - 25) { speedX = speedX * -1; serialRecord.values[0] = 0; } else if (x <25) { speedX =speedX * -1; serialRecord.values[0] = 1; } serialRecord.send()
We modified the code so that every time the value changed, Arduino would know and act accordingly.
if ( x > width - 25) { speedX = speedX * -1; serialRecord.values[0] = 0; serialRecord.send(); } else if (x <25) { speedX =speedX * -1; serialRecord.values[0] = 1; serialRecord.send();
We wanted the servo motor to stay still while the ball was on its way to the edge, so Professor Haider suggested we add one value that could not determine anything.
We got our Processing code as follows.
import processing.serial.*; import osteele.processing.SerialRecord.*; Serial serialPort; SerialRecord serialRecord; float x = 0; float speedX =25; void setup() { fullScreen(); String serialPortName = SerialUtils.findArduinoPort(); serialPort = new Serial(this, serialPortName, 9600); serialRecord = new SerialRecord(this, serialPort, 1); } void draw() { background(122); circle(x, height/2, 50); x=x + speedX; if ( x > width - 25) { speedX = speedX * -1; serialRecord.values[0] = 0; serialRecord.send(); } else if (x <25) { speedX =speedX * -1; serialRecord.values[0] = 1; serialRecord.send(); } else { serialRecord.values[0] = 2;//if the ball is in the middle nothing happens } //initial send position // store some values in serialTransport.values, and send them to the Arduino }
Regarding the Arduino end, we used two values to decide which servo motor should move and return to the initial angle.
#include "SerialRecord.h" #include Servo myservo; Servo myservo1; // Change this number to the number of values you want to receive SerialRecord reader(1); void setup() { Serial.begin(9600); myservo.attach(7); myservo1.attach(8); } void loop() { if (reader.read()) { if (reader[0] == 1) { myservo.write(180); delay(200); myservo.write(0); } if (reader[0] == 0) { myservo1.write(180); //initially we used pos instead of waving delay(200); myservo1.write(0); } } }
There, we made our first bouncing ball game. Due to the lack of time, we could make two hands or bats to attach to the motors to make it more real, but it was still a great job, and we learned a lot!