EXERCISE 01: ARDUINO TO P5 COMMUNICATION
The task was to 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.
We utilized a simple set-up consisting of a potentiometer. We mapped its values to the x-position of the ellipse on p5. The ellipse moves across the x-axis as the potentiometer is turned.
Arduino Code:
void setup() { Serial.begin(9600); // Initialize serial communication at 9600 baud rate } void loop() { int sensorValue = analogRead(A0); // Read the value from the potentiometer Serial.println(sensorValue); // Send the value to the serial port followed by a newline character delay(50); // Delay to prevent overwhelming the serial buffer }
P5 Sketch:
let rVal = 0; let alpha = 255; function setup() { createCanvas(640, 480); textSize(18); } function draw() { background(255); if (!serialActive) { text("Press Space Bar to select Serial Port", 20, 30); } else { // Print the current values text('Potentiometer Value = ' + str(rVal), 20, 50); //text('alpha = ' + str(alpha), 20, 70); } let xpos = map(rVal, 0, 1023, 0, width); // Map the sensor value to the canvas width ellipse(xpos, height / 2, 50, 50); // Draw an ellipse at the mapped position } function keyPressed() { if (key == " ") { // important to have in order to start the serial connection!! setUpSerial(); } } function readSerial(data) { //////////////////////////////////// //READ FROM ARDUINO HERE //////////////////////////////////// if (data != null) { let fromArduino = split(trim(data), ","); // if the right length, then proceed if (fromArduino.length == 1) { rVal = int(fromArduino[0]); } } }
EXERCISE 02: P5 TO ARDUINO COMMUNICATION
Make something that controls the LED brightness from p5.
We used a slider in p5 and connected the led to a PWM pin. The slider controls the brightness level of the LED.
Arduino Code:
//Arduino Code // Week 11.2 Example of bidirectional serial communication // Inputs: // - A0 - sensor connected as voltage divider (e.g. potentiometer or light sensor) // - A1 - sensor connected as voltage divider // // Outputs: // - 2 - LED // - 5 - LED int leftLedPin = 10; int rightLedPin = 5; 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); pinMode(rightLedPin, OUTPUT); // Blink them so we can check the wiring digitalWrite(leftLedPin, HIGH); digitalWrite(rightLedPin, HIGH); delay(200); digitalWrite(leftLedPin, LOW); digitalWrite(rightLedPin, 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(); int right = Serial.parseInt(); if (Serial.read() == '\n') { analogWrite(leftLedPin, left); digitalWrite(rightLedPin, right); int sensor = analogRead(A0); delay(5); int sensor2 = analogRead(A1); delay(5); Serial.print(sensor); Serial.print(','); Serial.println(sensor2); } } digitalWrite(LED_BUILTIN, LOW); }
P5 Sketch:
Code:
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); ledSlider = createSlider(0, 255, 0); ledSlider.position(10, 40); ledSlider.style('width', '200px'); } function draw() { // one value from Arduino controls the background's red color //background(map(rVal, 0, 1023, 0, 255), 255, 200); background('white'); // the other value controls the text's transparency value fill('black'); 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); } left = ledSlider.value(); console.log(left); right = 0; // click on one side of the screen, one LED will light up // click on the other side, the other LED will light up } 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); } } //Arduino Code /* // Week 11.2 Example of bidirectional serial communication // Inputs: // - A0 - sensor connected as voltage divider (e.g. potentiometer or light sensor) // - A1 - sensor connected as voltage divider // // Outputs: // - 2 - LED // - 5 - LED int leftLedPin = 2; int rightLedPin = 5; 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); pinMode(rightLedPin, OUTPUT); // Blink them so we can check the wiring digitalWrite(leftLedPin, HIGH); digitalWrite(rightLedPin, HIGH); delay(200); digitalWrite(leftLedPin, LOW); digitalWrite(rightLedPin, 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(); int right = Serial.parseInt(); if (Serial.read() == '\n') { digitalWrite(leftLedPin, left); digitalWrite(rightLedPin, right); int sensor = analogRead(A0); delay(5); int sensor2 = analogRead(A1); delay(5); Serial.print(sensor); Serial.print(','); Serial.println(sensor2); } } digitalWrite(LED_BUILTIN, LOW); } */
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.
Arduino Code:
arduino code : //Arduino Code // Week 11.2 Example of bidirectional serial communication // Inputs: // - A0 - sensor connected as voltage divider (e.g. potentiometer or light sensor) // - A1 - sensor connected as voltage divider // // Outputs: // - 2 - LED // - 5 - LED int leftLedPin = 10; int rightLedPin = 5; 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); pinMode(rightLedPin, OUTPUT); // Blink them so we can check the wiring digitalWrite(leftLedPin, HIGH); digitalWrite(rightLedPin, HIGH); delay(200); digitalWrite(leftLedPin, LOW); digitalWrite(rightLedPin, 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(); int right = Serial.parseInt(); int left = abs(right-1); if (Serial.read() == '\n') { digitalWrite(leftLedPin,left); digitalWrite(rightLedPin, right); int sensor = analogRead(A0); delay(5); int sensor2 = analogRead(A1); delay(5); Serial.println(sensor); //Serial.print(','); //Serial.println(sensor2); } } digitalWrite(LED_BUILTIN, LOW); }
P5 Code:
/* adapted from: https://github.com/ongzzzzzz/p5.web-serial MIT License Copyright (c) 2022 Ong Zhi Zheng Copyright (c) 2022 Aaron Sherwood Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ let port, reader, writer; let serialActive = false; async function getPort(baud = 9600) { let port = await navigator.serial.requestPort(); // Wait for the serial port to open. await port.open({ baudRate: baud }); // create read & write streams textDecoder = new TextDecoderStream(); textEncoder = new TextEncoderStream(); readableStreamClosed = port.readable.pipeTo(textDecoder.writable); writableStreamClosed = textEncoder.readable.pipeTo(port.writable); reader = textDecoder.readable .pipeThrough(new TransformStream(new LineBreakTransformer())) .getReader(); writer = textEncoder.writable.getWriter(); return { port, reader, writer }; } class LineBreakTransformer { constructor() { // A container for holding stream data until a new line. this.chunks = ""; } transform(chunk, controller) { // Append new chunks to existing chunks. this.chunks += chunk; // For each line breaks in chunks, send the parsed lines out. const lines = this.chunks.split("\r\n"); this.chunks = lines.pop(); lines.forEach((line) => controller.enqueue(line)); } flush(controller) { // When the stream is closed, flush any remaining chunks out. controller.enqueue(this.chunks); } } async function setUpSerial() { noLoop(); ({ port, reader, writer } = await getPort()); serialActive = true; runSerial(); loop(); } async function runSerial() { try { while (true) { if (typeof readSerial === "undefined") { console.log("No readSerial() function found."); serialActive = false; break; } else { const { value, done } = await reader.read(); if (done) { // Allow the serial port to be closed later. reader.releaseLock(); break; } readSerial(value); } } } catch (e) { console.error(e); } } async function writeSerial(msg) { await writer.write(msg); }
p5 sketch: