- 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
For this exercise, we used a potentiometer as our analog sensor. The Arduino program sends the reading from the sensor over to p5, where it is mapped to the range [ellipseWidth/2, canvasWidth-ellipseWidth/2]. The mapped value is then used to determine the x position of the center of the ellipse. Since nothing on Arduino is controlled by p5, p5 sends dummy data that is ignored by p5 to maintain the two-way handshake.
// ===== P5 ========= let diameter = 60; let sensorVal; // read from p5 transmitted message function setup() { createCanvas(640, 480); sensorVal = 1023/2; } function draw() { background(220); if (!serialActive) { text("Press Space Bar to select Serial Port", 20, 30); } else { text("Connected", 20, 30); } fill(0); ellipse(map(sensorVal, 0, 1023, diameter/2, width-diameter/2), height/2, diameter, diameter) } // === ARDUINO ==== void loop() { // wait for data from p5 before doing something while(Serial.available()){ digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data int _ = Serial.parseInt(); // get dummy variable sent over by p5 if(Serial.read() == '\n'){ delay(5); int sensor = analogRead(A1); // read sensor value delay(5); Serial.println(sensor); // send sensor value } } digitalWrite(LED_BUILTIN, LOW); }
2. Make something that controls the LED brightness from p5
For this exercise, we created a slider that controls the brightness of the LED. The range of the slider matches that of the LED analog value ranges, from 0 to 255. Hence, we only had to send that value over to the Arduino. Once received, the Arduino program writes that value to the LED PWM pin in an analog fashion. For visualization, our p5 sketch draws a circle whose diameter is proportional to the LED brightness.
// ===== p5 ====== let slider; function setup() { createCanvas(640, 480); sensorVal = 1023/2; slider = createSlider(0, 255, 0); } function draw() { background(0); fill(0,0,255); noStroke(); let diameter = map(slider.value(), 0, 255, 0, height); ellipse(width/2, height/2, diameter, diameter); fill(255); if (!serialActive) { text("Press Space Bar to select Serial Port", 20, 30); } else { text("Connected", 20, 30); } } function keyPressed() { if (key == " ") { setUpSerial(); } } function readSerial(data) { if (data != null) { let sendToArduino = slider.value() + '\n'; print(sendToArduino) writeSerial(sendToArduino); } } // ===== ARDUINO ===== void loop() { // analogWrite(leftLedPin, pwm); // wait for data from p5 before doing something while (Serial.available()) { digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data pwm = Serial.parseInt(); // get dummy variable sent over by p5 if (Serial.read() == '\n') { delay(5); analogWrite(rightLedPin, pwm); delay(5); Serial.println("0"); } } digitalWrite(LED_BUILTIN, LOW); }
3. 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
We needed to establish bi-directional meaningful data exchange in this exercise. The first is to send the Arduino a signal from p5 when the ball hits the ground. This is done by checking if the bottom portion of the ellipse touches the canvas’s lower boundary position.y + mass/2 == height
. If this evaluates to true, a signal of 1 is sent over. Otherwise, 0 is sent. When the Arduino program receives the signal, it turns the LED on or off accordingly. Similarly, the Arduino sends the value of the potentiometer (our chosen sensor) over to p5, where it gets mapped to the range [-1, 1]. The mapped value is set towind.x.
The closer the potentiometer value is to the extremes, the stronger the wind effect on the ball. Sensor values below 512 also get mapped to negative values, and the ball motion trajectory goes leftward. Otherwise, the wind effect goes in the opposite direction.
// ===== p5 ======= let velocity; let gravity; let position; let acceleration; let wind; let drag = 0.99; let mass = 50; let analogVal = 0; let dir = 0; 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() { background(220); applyForce(wind); applyForce(gravity); velocity.add(acceleration); velocity.mult(drag); position.add(velocity); acceleration.mult(0); if (!serialActive) { text("Press S to select Serial Port", 20, 30); } else { text("Connected", 20, 30); } fill(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) { if (data != null) { // make sure there is actually a message let fromArduino = data; // if the right length, then proceed if (fromArduino.length > 0) { analogVal = int(data); } wind.x = map(analogVal, 0, 1023, -1, 1); let sendToArduino; if (position.y + mass/2 == height){ sendToArduino = 1 + '\n'; } else{ sendToArduino = 0 + '\n'; } writeSerial(sendToArduino); } } // ======= Arduino ====== void loop() { // wait for data from p5 before doing something while (Serial.available()) { digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data ledState = Serial.parseInt(); // get ball bounce indicator from p5.js if (Serial.read() == '\n') { // turn on LED accrodingly if (ledState == 1){ digitalWrite(rightLedPin, HIGH); } else{ digitalWrite(rightLedPin, LOW); } currSensorVal = analogRead(A1); // read sensor value Serial.println(currSensorVal); // send sensor value } } digitalWrite(LED_BUILTIN, LOW); }