ARDUINO ↔ P5.JS
Week 08 - 10/26/2022
Serial IMU Output to p5.js | p5.webserial
p5.webserial is more direct and easier to use, however it only works in Chrome or Edge. One of the advantages is that it does not need a third-party application (such as p5.serialcontrol from Week07’s lab) to communicate with Arduino.
In the first part of the lab, I focused on reading the Internal Motion Unit (IMU), which is a nano 33 Iot built-in sensor and translating to p5.js in order to determine its heading, pitch, and roll.
const int buttonPin = 2; // digital input void setup() { // configure the serial connection: Serial.begin(9600); // configure the digital input: pinMode(buttonPin, INPUT); } void loop() { // read the first analog sensor: int sensorValue = analogRead(A0); // print the results: Serial.print(sensorValue); Serial.print(","); // read the second analog sensor: sensorValue = analogRead(A1); // print the results: Serial.print(sensorValue); Serial.print(","); // read the button: sensorValue = digitalRead(buttonPin); // print the results: Serial.println(sensorValue); }
Arduino:
// variable to hold an instance of the p5.webserial library: const serial = new p5.WebSerial(); // HTML button object: let portButton; let inData; // for incoming serial data let outData; // for outgoing data // variables for the circle to be drawn: let locH, locV; let circleColor = 255; function setup() { createCanvas(400, 300); // make the canvas // check to see if serial is available: if (!navigator.serial) { alert("WebSerial is not supported in this browser. Try Chrome or MS Edge."); } // if serial is available, add connect/disconnect listeners: navigator.serial.addEventListener("connect", portConnect); navigator.serial.addEventListener("disconnect", portDisconnect); // check for any ports that are available: serial.getPorts(); // if there's no port chosen, choose one: serial.on("noport", makePortButton); // open whatever port is available: serial.on("portavailable", openPort); // handle serial errors: serial.on("requesterror", portError); // handle any incoming serial data: serial.on("data", serialEvent); serial.on("close", makePortButton); } function draw() { background(0); // black background fill(circleColor); // fill depends on the button ellipse(locH, locV, 50, 50); // draw the circle } // if there's no port selected, // make a port select button appear: function makePortButton() { // create and position a port chooser button: portButton = createButton("choose port"); portButton.position(10, 10); // give the port button a mousepressed handler: portButton.mousePressed(choosePort); } // make the port selector window appear: function choosePort() { serial.requestPort(); } // open the selected port, and make the port // button invisible: function openPort() { // wait for the serial.open promise to return, // then call the initiateSerial function serial.open().then(initiateSerial); // once the port opens, let the user know: function initiateSerial() { console.log("port open"); } // hide the port button once a port is chosen: if (portButton) portButton.hide(); } // read any incoming data as a byte: function serialEvent() { // read a string from the serial port // until you get carriage return and newline: var inString = serial.readStringUntil("\r\n"); //check to see that there's actually a string there: if (inString) { // split the string on the commas: var sensors = split(inString, ","); if (sensors.length > 2) { // if there are three elements // element 0 is the locH: locH = map(sensors[0], 0, 1023, 0, width); // element 1 is the locV: locV = map(sensors[1], 0, 1023, 0, height); // element 2 is the button: circleColor = 255 - sensors[2] * 255; } } } // pop up an alert if there's a port error: function portError(err) { alert("Serial port error: " + err); } // try to connect if a new serial port // gets added (i.e. plugged in via USB): function portConnect() { console.log("port connected"); serial.getPorts(); } // if a port is disconnected: function portDisconnect() { serial.close(); console.log("port disconnected"); }
p5.js:
The result went well. I think the most difficult part is to fully understand how Serial Handshaking works. I am looking forward to applying it to some real-time motion projects in the future.
Two-Way Serial Communication
This part did not go well. Initially I tried to connect the breadboard and at least write part of the code in Arduino, since I think I understand the principle and the steps. However, I failed — it did not work at all. I did need to consult the lab page.
For some reason, after my failure, when I used the exact code from the lab page, the result was not correct either. The code worked, but the outcome was not as the same as it should be. I did not even reach the Handshaking part — I am still trying to debug it.
When the board is put flat on the table, the circle would not show at all. When I tip it over even for a little bit, the circle shows in the corner. According to the code, it should not work like that. It might be a connection problem.
When the problem is solved, I would like to integrate it in one of my p5.js sketches, in which each potentiometer will be able to control either x or y axis on the canvas. The sketch then will be more interactive than being controlled by a mouse.
UPDATE: PROBLEM SOLVED. It was the map.
video 1
video 2
figure 1