Introduction
During class, we were asked to complete, in pairs, three exercises in order to get more familiar with the serial communication between Arduino and p5.js. The exercises asked the following:
EXERCISE 01: ARDUINO TO P5 COMMUNICATION
Make something that uses only one sensor on Arduino and makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on Arduino is controlled by p5.
EXERCISE 02: P5 TO ARDUINO COMMUNICATION
Make something that controls the LED brightness from p5.
EXERCISE 03: BI-DIRECTIONAL COMMUNICATION
Take the gravity wind example and make it so:
-
- Every time the ball bounces, one LED lights up and then turns off
- And you can control the wind from one analog sensor
Therefore, in order to complete the assignment effectively, we split it respectively, and we communicated along the execution, since we needed to make sure we were not only following instructions adequately, but that we could finish on time.
Exercise #1 and #2 – Marcos Hernández
For this assignment, there was not any tweaking of the code done in the file provided (W11_01_Bidirectional_Com.ino) alongside the class presentation in Week 12.
So, for the set-up, I just prepared the Arduino in a way that it functions with the code without being modified, since it already did everything needed for these two exercises. Although, in p5.js, I duplicated the example that we were provided on class to work with. Likewise, I did make changes since it would not replicate what was needed for exercise #1 and #2.
After setting up the Arduino, we have the following:
And with this code in p5.js that is modified so as every time the circle is clicked, the red LED gets turn on as well as having the possibility of moving it horizontally with a potentiometer via analog values:
let rVal = 0;
let alpha = 255;
let left = 0; // True (1) if mouse is being clicked on left side of screen
let right = 0; // True (1) if mouse is being clicked on right side of screen
function setup() {
createCanvas(640, 480);
textSize(18);
}
function draw() {
// one value from Arduino controls the background's red color
background(255)
// the other value controls the text's transparency value
fill(255, 0,0)
if (!serialActive) {
text("Press Space Bar to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
// Print the current values
text('rVal = ' + str(rVal), 20, 50);
text('alpha = ' + str(alpha), 20, 70);
}
// click on one side of the screen, one LED will light up
// click on the other side, the other LED will light up
if (mouseIsPressed) {
if (mouseX > rVal-50 && mouseX < rVal+50 && mouseY > height/2-50 && mouseY < height/2+50) {
right = 1;
}
} else {
right = 0;
}
ellipse(rVal, height/2, 50,50)
}
function keyPressed() {
if (key == " ") {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
// This function will be called by the web-serial library
// with each new line of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 2) {
// only store values here
// do everything with those values in the main draw loop
// We take the string we get from Arduino and explicitly
// convert it to a number by using int()
// e.g. "103" becomes 103
rVal = int(fromArduino[0]);
alpha = int(fromArduino[1]);
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = left + "," + right + "\n";
writeSerial(sendToArduino);
}
}
We have the following result observed in the video:
After completing these exercises, I started to feel more confident as to how I will work on my final project.
Exercise #3 – Marwan AbdElhameed
This one is particular was challenging. Basically, the sensor data is sent to Arduino after mapping it to -1,1, then the Y position of the ball is sent to the Arduino and checked if it was >330. If it is, the LED at is switched to HIGH.
The code found in p5.js:
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
function setup() {
createCanvas(640, 360);
noFill();
position = createVector(width/2, 0);
velocity = createVector(0,0);
acceleration = createVector(0,0);
gravity = createVector(0, 0.5*mass);
wind = createVector(0,0);
}
function draw() {
if (!serialActive) {
text("Press s to select Serial Port", 20, 30);
} else {
text("Connected", 20, 30);
// Print the current values
text('rVal = ' + str(rVal), 20, 50);
text('alpha = ' + str(alpha), 20, 70);
}
background(255);
applyForce(wind);
applyForce(gravity);
velocity.add(acceleration);
velocity.mult(drag);
position.add(velocity);
acceleration.mult(0);
ellipse(position.x,position.y,mass,mass);
if (position.y > height-mass/2) {
velocity.y *= -0.9; // A little dampening when hitting the bottom
position.y = height-mass/2;
}
}
function applyForce(force){
// Newton's 2nd law: F = M * A
// or A = F / M
let f = p5.Vector.div(force, mass);
acceleration.add(f);
}
function keyPressed(){
if (keyCode==LEFT_ARROW){
wind.x=-1;
}
if (keyCode==RIGHT_ARROW){
wind.x=1;
}
if (key==' '){
mass=random(15,80);
position.y=-mass;
velocity.mult(0);
}
if (key == 's') {
// important to have in order to start the serial connection!!
setUpSerial();
}
}
function readSerial(data) {
////////////////////////////////////
//READ FROM ARDUINO HERE
////////////////////////////////////
if (data != null) {
// make sure there is actually a message
// split the message
let fromArduino = split(trim(data), ",");
// if the right length, then proceed
if (fromArduino.length == 1) {
wind = int(fromArduino[0]);
}
//////////////////////////////////
//SEND TO ARDUINO HERE (handshake)
//////////////////////////////////
let sendToArduino = position.y + "\n";
writeSerial(sendToArduino);
}
}
The code sent to the Arduino:
int leftLedPin = 2;
void setup() {
// Start serial communication so we can send data
// over the USB connection to our p5js sketch
Serial.begin(9600);
// We'll use the builtin LED as a status output.
// We can't use the serial monitor since the serial connection is
// used to communicate to p5js and only one application on the computer
// can use a serial port at once.
pinMode(LED_BUILTIN, OUTPUT);
// Outputs on these pins
pinMode(leftLedPin, OUTPUT);
// Blink them so we can check the wiring
digitalWrite(leftLedPin, HIGH);
delay(200);
digitalWrite(leftLedPin, LOW);
// start the handshake
while (Serial.available() <= 0) {
digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
Serial.println("0,0"); // send a starting message
delay(300); // wait 1/3 second
digitalWrite(LED_BUILTIN, LOW);
delay(50);
}
}
void loop() {
// wait for data from p5 before doing something
while (Serial.available()) {
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int left = Serial.parseInt();
if(left>=330){
digitalWrite(leftLedPin, HIGH);
}
if (Serial.read() == '\n') {
digitalWrite(leftLedPin, left);
int sensor = analogRead(A0);
sensor = map(sensor,0,1023,-1,1);
Serial.println(sensor);
}
}
digitalWrite(leftLedPin, LOW);
}
After sending the setting up the Arduino, sending the code and using the one that was written in p5.js, we have the following result:
Conclusion
Working on Arduino, at first sight, might appear scary and too technical. But with these exercises, both my teammate and I feel more comfortable with the Arduino world. As they say, the hardest step will always be the first, and the rest, should be left to curiousness.