Week 7 – Midterm Documentation

Concept 

I made a snake type game in which you have to eat the ‘food’. In this case however, instead of growing bigger and having to avoid hitting yourself, in my game, the background is constantly changing, making it so that food moves its place every time.

I was inspired by retro-style games. I have an extension to play tetris on my chrome, and it is a pretty simple (but fun) game to play. It’s also a somewhat difficult game, and the more you play it the more you end up improving on the game. I wanted this game to be similar to my little tetris game. Just something quick and fun to play.

Image of the tetris game I have on my computer:

  • Describe how your project works and what parts you’re proud of (e.g. good technical decisions, good game design) 2-3 paragraphs

How my Project Works 

The white ‘food’ is set on a random function. Anytime the song hits two seconds, the background changes. I put the food in the background function so that it changes its position during the song.

The code detects when the purple touches the white, and increases the score based on that.  I was really happy that the input of the purple color to the white was instantaneous! Additionally, since the score adds up so fast, it’s pretty clear anytime the player ends up scoring points. I originally had a sound attached when the player touched it, but I think the score works well on its own.

I also really liked that the background changed color, I think it added a bit of an extra flair. And it also allowed me to show the player that when it gets to orange, the game will end. The actual time it ends is 30 seconds, but I think the color is a better indicator than an actual timer on the screen.

Code I’m Happy With

I’m really happy with how much of my work was my own. I understand fully how my code works and what I can change to change a single part of it.

I’m especially happy with how I figured out the loop! I didn’t have a proper tutorial for it, so its all my code.

function songBackground() { 
  //added a cue so that in every 2 secs, the background changes color
  for (let i = 0; i < 32.5; i += 2) {
    song.addCue(i, changeBackground, "orchid");
  }
  song.addCue(32.5, endGame);
}

I’m also really happy with the wall boundaries I have set up. There were so difficult to do but I knew I had to because of the amount of people who’d get themselves out of canvas.

checkBoundaries() {
    if (this.x < 0) {
      this.x = this.x * 0;
    } else if (this.x > width) {
      this.x = this.x - 10;
    }
    if (this.y < 40) {
      this.y = this.y + 10;
    } else if (this.y > height) {
      this.y = this.y - 10;
    }

Problems and Areas of Improvement

I ran into a ton of problems during this project! The code consistently messed me up and refused to work out. I was happy with just how much of the end result was actually planned. There were so many moments where I spent hours trying to code something specific, and the fact that it ended up working made me really happy.

The one thing that wouldn’t work for some reason is the image. I originally had a paintbrush I spent a while drawing to add to my code, but for some reason, it wouldn’t appear. Loading images (as well as sound) is already finicky with p5js, and I just couldn’t get it to work despite following instructions perfectly. I’m still frustrated I couldn’t! I spent an hour on that brush!

References

I used a ton of tutorials! So much so that I don’t think I could post them all here.

I watched Jason Erdreich’s videos on programming a retro-style game and the space invaders programming.

I watched the coding train’s videos on if, else statements. Sounds, image, the snake game, and also rewatched a ton of stuff I have already seen just to refresh myself (including object oriented programming!)

I also watched Patt Vira’s videos on collision, she was a massive help in that aspect.

I regularly checked references and searched up on p5js to see things to add to my code.

I very rarely used AI, and it was only when I had to search something on google and the ai overview popped up. I hate using it so I made sure to avoid it.

Week 7: MIDTERM PROJECT

Ever wanted to be LeBron James for 30 seconds? Well, now you can! For my interactive media midterm, I created a LeBron James simulator, a humorous experience designed to help you unleash yout inner LeBron. Using computer vision and ml5.js, I made a virtual basketball track the player’s index finger to control the game instead of the usual keyboard and mouse. The aim of the game is for the player to shoot as many hoops as they can in 30 seconds while LeBron-inspired encouragements flash across the screen. I gave the game a gold and purple color scheme to match the Los Angeles Lakers. For background music i used the instrumental of Pat Benatar’s Hit Me with Your Best Shot which adds that classic arcade feel.

The game was built using p5.js and the ml5.js HandPose model. When the player starts the game, their webcam is activated to begin tracking their hand. The game tracks the player’s index finger, which updates the basketball’s coordinates on the canvas. The player scores points by moving the ball into a hoop on the right side of the screen. The scoring system uses the dist() function to measure the distance between the ball and the hoop, while a Boolean variable called wasInsideHoop prevents the player from continuously scoring points by keeping the ball inside the hoop. I also used a basketball class to store the ball’s properties, such as its position and size, while methods update its location and draw it on the canvas.

The game uses three different states: the main menu, gameplay, and game over. Pressing Space starts the game, giving the player 30 seconds to score as many points as possible. Their final score determines which LeBron-inspired message they receive on the ending screen. Pressing R after the game ends takes the player back to the main menu without restarting the entire sketch. I also included a fullscreen mode that can be activated by pressing F.

One part that I am particularly proud of is the different ending quotes displayed depending on the player’s score. I used conditional statements to determine which message appears based on how well the player performed. I wanted these messages to add humor to the experience and make the game feel more entertaining, even when the player doesn’t score many points.

hat I struggled with most during development was getting the hand tracking to work. p5.js had recently received an update that removed the preload() function, which I had initially tried to use to load the HandPose model. This caused some issues with my original code, and I eventually had to use an asynchronous setup() function to initialize the model instead.

I also ran into some problems with sound, although these were unrelated to p5.js itself. I only wanted to use around 30 seconds of the song, but when I tried trimming the audio in QuickTime Player, it exported the file in .mov format instead of MP3. I ended up using GarageBand to trim and export the song, although its interface was more confusing to navigate. After some trial and error, I managed to get the music working in the game.

For improvements, i’d say that i want to add more challenges in the future. A defense mode would be fun. i would also maybe like to make it a full body tracking gamw instead of just hand tracking. The game could serve as an exercise outlet by needing the player to get up and move their whole body.

 

 

References:

P5.Js

ML5.JS handpose library

Music; Hit Me with Your Best Shot instrumental. Originally by Pat Benatar https://youtu.be/Dxb3HZPb5-c?si=3cGfPgRrMRDmHqPB

Image: Lebron James

https://www.pinterest.com/pin/lebron-james-standing-png-image–552957660533717293/

Developmental assistance: AI-assisted troubleshooting and code development, with testing and modifications during implementation

Week 3 – Reading and OOP exercise

Reading reflection

The part of interactivity that I really agree with is that it is a scale and not a binary. I believe interactivity is a huge aspect of how technology is perceived, and I am really interested in how it shapes the relationship between the user and the technology.  I believe interactivity doesn’t needs to be physical in its nature where a user has to press a button or a widget, but it is really about how involved they feel with the technology/or any other medium of interaction. The author then speaks about how they feel that reading is not interactive. I disagree with this part, and I believe that reading is highly interactive. In an era where there is so much online material/posts/apps/games to interact with I find reading to be highly interactive and not rushed. The author also speaks about how opening a fridge door is interactive, which is an interesting approach. I believe small everyday tasks have an interesting nuance to them and how their design matters I think it is in these tasks that we actually slow down. I don’t want to be philosophical about this, but I genuinely resonate with how interaction is people based like when communicating and dancing. As a sustained dialogue ambassador, I really agree with Crawford’s stance on how communication is interactive. Like as an ambassador, I have been trained to like communicate with participants and co-facilitators without the need of speaking, and letting silence set in and genuinely listening to everyone, including listening on different levels like their body language. This is also what interactivity looks like to me, so I think it does have different aspects to it, but it all comes down to how seen the user/person feels whether it is technical or not.

Coding Exercise

My inspiration for this code was the Ikigai concept in Japanese, where it means what you pursue in life has to be at the intersection of what you like and what you the world will need. I also really like the translucent aspect of this as well, and to me it appears to be like tainted glass.

Sources for images: https://www.istockphoto.com/photos/vertical-stained-glass-window
My Program

My code

I build this through the ikigai class I defined. The part of the code, I am proud of is how I integrated the translucency.

class IkigaiCircle {
  //it runs when a new circle is made
  constructor(x, y, col, appearAt) {
    //The centre of the circle
    this.x = x;
    this.y = y;
    //Colour name into a p5 colour
    this.col = color(col);
    //  a crucial part in helping us set the color to translucent
    this.col.setAlpha(100);
    // count value when this circle appears
    this.appearAt = appearAt;
  }

I started by drawing a single circle in the middle of the canvas, then added three more to build the ikigai diagram, using see-through colours so the overlaps would blend. To make it animate, I added a counter that goes up every frame and made each circle appear only after the counter reached a certain number. Once I noticed the four circles used almost the same code, I turned them into an IkigaiCircle class and moved the colours and positions into arrays, so a loop could create all four circles for me. Finally, I changed the background from grey to cream because the grey made the colours look dull.

Week 2 – Reading reflection

From the introduction, I had the following thoughts. Reas mentions of how chaos in major events in history like prevalence of quantum mechanics and world war 1  led to shifts in art. This made me question of whether chaos around AI will lead to shifts on how art is formed and viewed. Reas then continues talking about how software art is effected by noise while I understand what noise he is referring to; I think about how noise doesn’t allow me to focus while making art and how the same word could have such different impacts and meanings.

He then mentions Valentino Braitenberg as a neuro-atomist and his work about an imaginary robot to study about cognition. I really liked the crossover between art, math, and science. I read more into these robots and found how one robot’s motion was effected by temperature actually akined to the brownian motion. I really agree with the analogy here since the motion seemed so random when Reas modeled it; it links all back to nature even the randomness.

In the Order of Art, he also talks about making art of your own and I think that is what gives art life: individualism. I really found Mondrian’s evolution in artwork very humane too since we think about life or careers in something very linear or restricted, but seeing how his style emerged along with music in NewYork is a helpful in supporting that we can change paths, decisions, and expression and that is okay.

When Reas explores Computer Graphics, he varies the randomness which changes the art pattern and then shows examples of graphics which vary with different factors. For me, I worked with noise() particularly which brings in slight order in comparison to random(). If we were to talk quantitively, I still would lean into less randomness and more structure since an increased amount of disorder takes away what I want to communicate through artwork. I don’t really think there is an optimum balance as that would keep changing from project to project, here I really resonate with Mondrian’s view of art.

Week 2 – Computer Graphics

OVERVIEW

I was taking my makeup off with a cotton ball and found the strands of cotton to be the inspiration for the compute graphic. I went over the magazines as well but nothing in particular resonated, so I browsed more examples of computer graphics. This is when I came across Perlin noise which was a technique invented by Ken Perlin while working on his film: Tron. I was also very inspired by textures and blur, and how they add such personality. Ideally I was supposed to create a similar graphic.

sourced at https://genekogan.com/code/p5js-perlin-noise/

CODE HIGHLIGHT

The major part with the code was adjusting variables, I had a similar experience with drawing eyelashes for my self-portrait.

This is the main for loop that takes the noise field and the loop reads the noise field at the current position, converts that value to an angle, then uses cos and sin to turn the angle into a step of fixed length. It draws that segment, moves to its end, and repeats.

 for (i = 0; i < 20; i++) {
        n3 = noise(oldX * resolution, oldY * resolution) + 0.045;
        angle = map(n3, 0.3, 0.7, 0, PI * 4);

        newX = cos(angle) * len + oldX;
        newY = sin(angle) * len + oldY;
        line(oldX, oldY, newX, newY);
        oldX = newX;
        oldY = newY;
}

EMBEDDED SKETCH

 

HOW THIS WAS MADE

I divided this in 3 main sections with defining the canvas first, and then the variables which I will need to vary, and then the seed grid and reading the noise field. I also used different resources for the main algorithm like https://www.youtube.com/watch?v=Qf4dIN99e2w

by coding train and a walk through by Steve’s Masterclass. I read about the noise() function on GeekforGeeks and the p5j. website. The looping logic was learnt through youtube.

Initially, 2 nested loops help to walk a path of starting positions, and then saving the grid positions. A third nested loop works by reading the noise field at current position, turning that value into an angle, converting the angle into a step of length len via cos and sin, drawing the segment, and moving to the end of it and repeat. This loop runs for 20 times which gives it a wriggling tail, and the paths curve because the noise value is re-read at every step.

Reflection and Ideas for future work

I do still find the main idea of perlin noise to be complicated. However, I am very intrigued by how many intersections this sits at right now like how it is a noise field which means it includes bunch of vectors, but at the same time they are directed in terms of direction. I think I would like to take it as close as possible to the image I have shared and maybe an animated version.

Week 2 – Generative Artwork

Concept

For this assignment, I wanted to create something that moves and looks alive using the programming concepts and techniques that I know and have learned so far. The idea that came to me was to create a weather scene showing a house during rainy weather. This idea was inspired by the difference between the weather in my home country, Fiji, where it is currently the rainy season, and Abu Dhabi, where the weather is generally very sunny. I decided to represent these two different environments in the same artwork. I used concepts like arrays, loops, Boolean variables, functions, conditionals, randomness, and animation to create a lively artwork.

Click on it!

Code I am Proud of

function draw() {
  // To draw and move the raindrops
  if (raining == true) {

    // Goes through all 100 raindrops 
    for (let i = 0; i < 100; i++) {
      // To draw the current raindrop 
      drawRainDrop(i);

      // To move the current raindrop
      moveRainDrop(i);
    }
}
// Function for drawing individual raindrop
function drawRainDrop(i) {
  fill(50, 100, 255);
  noStroke();

  // For making each raindrop
  ellipse(rainDropX[i], rainDropY[i], 5, 10);
}

// Function for moving an individual raindrop
function moveRainDrop(i) {
  rainDropY[i] += 5;

  /* If the raindrop reaches the ground, Its moved back randomly to the top with a random x position also */
  if (rainDropY[i] > 500) {
    rainDropY[i] = random(-50,0);
    rainDropX[i] = random(0, width);
  }
}

The part of the code I am most proud of is the falling rain effect. It took me several attempts and a lot of thinking to figure out how I wanted the raindrops to behave. At first, I was thinking about how I could continuously generate new raindrops while older ones were still falling. I eventually realized that I did not actually need to create completely new raindrops every time. Instead, I could create 100 raindrops and continuously reuse them by changing their positions after they reached the ground.

The arrays were important for this because they allow the program to store the position of every raindrop. The for loop then goes through all 100 raindrops and updates each one. I particularly like this approach because there are only 100 raindrops being managed, but they can continue falling and respawning throughout the entire animation. This creates the impression of continuous rain without needing to continuously create more and more objects. I am also proud of use of randomness when the raindrops respawn. If every raindrop started at exactly the same x and y position, the rain would look artificial and repetitive. Randomizing the positions makes the scene look more natural. I was able to connect this programming technique to Casey Reas’ idea of Chance Operation. Rather than using randomness just because it was useful for the animation, I was able to think about randomness as part of the artistic design of the project.

Implementation

I created arrays called rainDropX and rainDropY to store the x and y positions of the 100 raindrops. These arrays allow the program to keep track of every raindrop individually. In the setup() function, I used a for loop to create 100 raindrops and give each one a random starting position. The x-position is randomly generated across the width of the canvas, while the y-position is randomly generated across the canvas. This means that when the program starts, the raindrops are already distributed throughout the scene.

The main animation happens inside the draw() function. I used a Boolean variable called raining to determine which weather condition should be displayed. When the program starts, it shows a rainy scene, and when the mouse is clicked, the rain stops and the scene changes to a sunny one. Clicking again brings the rain back. I used a for loop to go through all 100 raindrops every frame. For each raindrop, the program calls drawRainDrop(i) to draw it and moveRainDrop(i) to move it downward. The movement of each raindrop is relatively simple. Every frame, its y-position increases by 5.

Reflection

The most challenging part was creating the falling rain, but working through it helped me better understand how arrays and loops can be used to manage multiple objects at the same time. In the future, I would like to improve the project by making the transition between rainy and sunny weather smoother, perhaps adding moving clouds and lightning, and possibly adding sound effects. I would also like to experiment more with randomness and explore how I can use programming to create more interactive and visually interesting artwork. Overall, I am happy with the project because I was able to use the programming concepts I have learned to create something animated, interactive and personal.

 

Weel 1 Self Portrait photo

During my time of creating the self-portrait, I had to use the code practice from last class for reference; the reason being that the code would allow me to remember certain commands that I ended up using to make my portrait. For example, the commands from the practice code, “// Body fill(‘orange’) rect (etc.)” allowed me to get an idea of how I can create a body for my portrait which is then followed by creating said-rectangular body. This proved to be very helpful for me because what I was aiming for within my portrait was a kind of modern look; by modern look, I mean by how in most social media platforms, some people choose to have a blank profile picture that only depicts an almost rectangular body and circular head. It may sound boring, but I personally like to think of it as a reminder of how times around the world are so drastically different than how one can imagine. Speaking of circular head, i was originally going to use the “circle()” command to create my head, until I found out that the command best suitable for the requirement is the “ellipse” command since it had proven to me that it can create a far more accurate shape of the head for me. This wasn’t the only time I replaced a shape during the whole process, because when I was creating the nose, I almost went with an oval circular shaped nose. However, some part of me felt as if it were “too clownish” to say the least; hence why i decided to go with the triangle since it just felt more respectful with the nonchalant tone that i have been trying to keep up rather than a tone similar to that of an off-brand circus. As for eyes, my original goal was to create 2 big white circles and then create 2 smaller black circles that would be placed on top of the white ones in the middle; yet I remembered the “ellipse” command and how it would prove to be a more beneficial tool if it slipped horizontally, shrinked by eye-size, and then be placed in their respective spots all while the idea of 2 smaller black circles being centralized within the 2 white sclera of the eyes remained. Lastly, with the hair, this the most difficult for me, since I could not figure out which series of commands to use in order to replicate my hair as need be. Since I am not the most experienced artist in the room, I had no choice but to go forward with the decision to create those lines of hair that perhaps would at least resemble my short bangs.

Despite the headache from all the creation of shapes after shapes, a code series that I can’t help but feel happy about is the creation of the smiling mouth that you may see in the portrait. Before the mouth was even formed, I nearly went with the idea of using the “line()” command to form my mouth and perhaps stretch upwards. But of course, I would come to realize that the lines are meant to be nothing more than straight, thus enabling as incapable of being bent/altered further. When hope seemed lost, that is when I stumbled upon the command of “arc()” from the coding’s list of references. There, I would discover how certain arcs of line in this different command can be altered just in the way I desired! Thus, that is how I was able to get the smiling mouth as you would see here in the portrait!

Despite the work being done, I do want to mention that not only did I use the code practice and the coding site’s references as my guide, but I also had ai (one that I paid for), check my work to see if I must either change a coordinate or correct a common usually wrongly. This is because I saw that through my time working, my weakness has been second-guessing certain coordinates for certain shapes for too many unnecessary times. I just could not tell which coordinate was the right way to write in order to set the shape and/or color as I wanted. Therefore, that is why for each coordinate of each part of the portrait that I write, I would share it with the AI and simply hear its advice of what I can keep and what I must modify. Even though it has helped me recognize my mistakes, it still serve as a signal for me that what I should be working on for this class is a better understanding of how shapes must be correctly positioned/modified as for each project I work on. After all, this idea of improvement should help prepare me for possibly more complex projects that require more shapes somewhere in the future.

function setup() {
  createCanvas(640, 580);
}

function draw() {
  // background set-up
  background(135, 206, 235);
  // sun at the top right corner
  noStroke();
  fill("yellow")
  circle(40,40,180);

  // Head
  fill("tan");
  ellipse(300, 300, 250, 300);

  // Body
  noStroke();
  fill("green");
  rect(210, 430, 180, 220);
  
  // Hair 
  stroke("Black");
  strokeWeight(5);

  line(260, 190, 250, 150);
  line(280, 180, 275, 140);
  line(300, 175, 300, 135);
  line(320, 175, 320, 135);
  line(340, 180, 345, 140);
  line(360, 190, 370, 150);

  // Sclera of eyes
  fill("white");
  ellipse(250, 300, 65, 38);
  ellipse(350, 300, 65, 38);

  // Pupils of the eyes
  fill("black");
  circle(250, 300, 14);
  circle(350, 300, 14);

  // Nose
  fill("brown");
  triangle(300, 320, 285, 335, 315, 355);

  // Smiling mouth
  noFill();
  stroke("black");
  strokeWeight(5);
  arc(300, 370, 90, 60, 0, PI);
}

 

Inside Your Mind – Interactive Fluid Typography Experience and User Testing

As I was experimenting with m project, I built Inside Your Mind – a second-person psychological narrative experience created in p5.js. I felt like with the creativity I developed in the class Tinkercad would not be enough to show my ideas, altough I tried to make a project on Tinkercad I did not open fully with it, so I chose to do my interactive experinec in p5. The project moves away from game mechanics and goals, and toward something more expressive and open-ended: a guided journey through four emotional stages of the mind, rendered through fluid particle typography and sound.

The experience opens with a kinetic typography intro sequence a personal greeting, a typewriter reveal, a search bar that types “inside your mind” — before transitioning into the main particle world. From there, users navigate different stages of mind, noise, overthink, break and finally silence.

User Testing

User testing was conducted with participant who experienced the full interactive sequence from the intro through all four stages. My little brother.  Participant were observed interacting freely with no instructions given beyond “explore it.”

The response was overwhelmingly positive.

Tester consistently described the experience as something they hadn’t encountered before, not a game, not a website, something in between that felt genuinely immersive. My brother spent more time in the experience than expected, going back and forth between stages to compare how the particles moved differently in each one. The fluid typography was the element that resonated most strongly. Tester were drawn to how the text was simultaneously readable and alive. The sound design was a notable highlight. Tester immediately noticed that each stage sounded different, and several remarked that the cursor sounds made the experience feel tactile, like they were touching something. The wind sound in Stage 1, the water drops in Stage 2, the glitch crackle in Stage 3, and the bell chimes in Stage 4 each reinforced the emotional tone of that chapter which made it more cohesive.

Link to user testing video: https://drive.google.com/file/d/1y8koBlJ7WqWSgiGLDeGFhjZYJn5P-0Ib/view?usp=drivesdk

Areas noted for potential refinement:

I am considering to add an introduction to the experience explaining more about the interactivness, I am inspired by motion design, lately have been watching different motion design ad proposals for brands and I enjoyed the animations, so I would want to implement it to my project by learning and applying it.

Week 14 – Final Project (PawPortion)

🐾 PawPortion🐾 Smart Pet Feeding Assistant

Concept

I started this project from a very simple everyday problem: feeding a pet on time. It sounds like something that should be easy to remember, but in real life, routines can get busy, and small responsibilities can be delayed or forgotten. I did not want to make a fully automatic feeder because that would remove the user from the process completely. Instead, I wanted to create a system that supports the user while still keeping them involved in the act of care.

PawPortion is an interactive pet feeding assistant that combines an Arduino-controlled physical feeder with a p5.js digital dashboard. The system keeps track of feeding time, reminds the user when it is time to feed, and responds when the feeding action is completed. The project is not just about dispensing food. It is about creating a clear relationship between the user, the interface, and the physical machine.

The main idea behind PawPortion is assisted responsibility. The system does not take over the task entirely, but it helps make the task more visible, structured, and responsive. The user can see when the pet was last fed, when the next feeding should happen, and whether the feeding has been missed. The pet’s mood on the screen also changes depending on the state of the system, which makes the interaction feel more emotional and less robotic.

Video of Project

Images of Project


Schematic



Assembly Instructions 


User Testing Videos

During user testing, I wanted to see whether people could understand the system without me explaining every step. The main interaction was mostly clear. Users understood that the p5 dashboard was giving them feeding information, and they were able to recognize the “Feed Now” button as the main action. Once the servo moved and food was released, the connection between the digital interface and the physical feeder became much clearer.

One important issue appeared during testing with the IR sensor. I had placed a printed image near the sensor to guide the user, but the image made some people interpret the IR sensor as a physical button. Instead of triggering it by placing something near it, they tried to press it directly. The problem was not that the sensor failed. The problem was that my visual instruction gave the wrong impression.

This taught me that physical interaction is not only about whether the circuit works. It is also about how the user reads the object. A small label, icon, or printed sign can completely change how someone understands what they are supposed to do. After seeing this confusion, I changed the printed label so it was clearer that the sensor detects presence rather than pressure. This made the interaction easier to understand and reduced the need for verbal explanation.

How Does the Implementation Work?

Description of Interaction Design

The interaction is built around a cycle between the user, p5, and Arduino. First, the p5 dashboard tracks time and displays the feeding schedule. The user can see when the pet was last fed, when the next feeding is due, and how much time is left. This makes the system readable before anything physical happens.

When feeding time arrives, the dashboard changes state. The pet becomes hungry, and the status message tells the user that it is feeding time. This is meant to guide the user instead of forcing the system to act automatically. The user then presses the “Feed Now” button on the p5 interface, which sends a command to Arduino.

Arduino receives the command and moves the servo motor. The servo acts like a small door or gate that opens to release food, then closes again. When Arduino finishes dispensing, it sends a message back to p5. After p5 receives that message, the dashboard updates the last feeding time, resets the countdown, and changes the pet’s mood to happy.

If the user does not feed within the grace period, the system marks the feeding as missed. The pet becomes sad, which makes the missed action more visible. I wanted this to feel gentle, not dramatic, but still noticeable enough that the user understands the consequence of ignoring the schedule, and that they should probably feed their pet.

Description of Arduino Code

Github Full Code

The Arduino code controls the physical side of the project. It is responsible for reading the IR sensor, controlling the servo motor, and communicating back to p5 when feeding is complete. I used named constants for the pins instead of random numbers, which makes the code easier to understand and edit later.

Snippet: defining the sensor pin, servo pin, and servo object.

#include <Servo.h>

const int SENSOR_PIN = 7;

const int SERVO_PIN  = 6;

Servo tap_servo;

The main function in the Arduino code is dispenseFood(). This function opens the servo, waits while food is released, closes the servo, and then sends “DONE” to p5. This message is important because it tells the dashboard that the physical feeding action has finished.

Snippet: the feeding function that opens the servo, closes it, and sends confirmation to p5.

void dispenseFood() {

  isDispensing = true;

  tap_servo.write(110);

  delay(2000);

  tap_servo.write(0);

  delay(300);

  lastFedTime = millis();

  isDispensing = false;

  Serial.println("DONE");

}

The Arduino also listens for serial messages from p5. When p5 sends “FEED”, Arduino immediately calls the feeding function. This is what connects the digital button to the physical movement.

Snippet: receiving the FEED command from p5.

if (Serial.available() > 0) {

  String cmd = Serial.readStringUntil('\n');

  cmd.trim();

  if (cmd == "FEED") {

    dispenseFood();

  }

}

I also added a cooldown so the IR sensor does not trigger repeatedly if something stays in front of it. Without this, the servo could keep dispensing again and again. The cooldown makes the physical interaction more controlled.

Description of p5.js Code

 

The p5.js code controls the digital dashboard. It handles the schedule, the pet mood, the buttons, and the communication with Arduino. The dashboard shows the last feeding time, the next feeding time, and a countdown. It also shows the pet’s mood, which changes depending on what is happening.

Snippet: timing values for the feeding schedule.

const FEED_INTERVAL_SEC = 60;

const MISSED_GRACE_SEC = 15;

The main schedule logic checks whether feeding time has arrived. If there is still time left, the pet stays neutral. If feeding time has arrived but is still within the grace period, the pet becomes hungry. If the grace period passes, the pet becomes sad.

Snippet: schedule logic that updates the pet mood.

if (secUntilFeed > 0) {

  petMood = "neutral";

  if (serialConnected) {

    statusMsg = "Waiting for next feeding";

  }

} else if (secUntilFeed > -MISSED_GRACE_SEC) {

  petMood = "hungry";

  statusMsg = "Feeding time!";

} else {

  petMood = "sad";

  statusMsg = "Feeding missed!";

}

When the user clicks “Feed Now,” p5 sends the word “FEED” to Arduino through serial communication. I used a newline at the end because it helps Arduino read the command as one complete message.

Snippet: sending the FEED command to Arduino.

const encoder = new TextEncoder();

const writer = port.writable.getWriter();

await writer.write(encoder.encode("FEED\n"));

writer.releaseLock();

The p5 code also listens for messages from Arduino. When it receives “DONE”, it updates the dashboard. This is what makes the interface respond only after the physical action finishes.

Snippet: checking for DONE from Arduino.

if (line === "DONE") {

  onFeedingDone();

}

I also added fullscreen functionality using the F key. This makes the dashboard easier to present during the final demo and makes it feel more like a complete interface rather than just a small sketch window. The course documentation specifically mentions fullscreen and responsive resizing as part of final project programming considerations.

Description of Communication Between Arduino and p5.js

The communication between Arduino and p5.js is one of the most important parts of the project. The system works through a two-way serial communication loop. p5 sends “FEED” to Arduino, Arduino moves the servo to dispense food, and then Arduino sends “DONE” back to p5.

This means the dashboard does not simply assume that feeding happened. It waits for Arduino to confirm that the physical action was completed. This made the project feel more reliable because the screen and the machine were connected through actual feedback.

This was also one of the hardest parts of the project because if the serial communication failed, the entire interaction felt broken. The dashboard could look fine, and the Arduino could work alone, but the project only felt complete when both sides were speaking to each other correctly.

Aspects Of The Project I’m Proud Of 

One of the strongest parts of this project is how far it goes compared to where I started at the beginning of the course. If I had seen this project in week one, I genuinely would not have believed that I could build it. It combines physical computing, serial communication, a digital dashboard, user interaction, timing logic, an animated interface, and a mechanical feeding system. That feels ambitious for me, and I am proud that I was able to execute it in a way that actually works.

I am also proud of how complete the project feels as an experience. It is not just Arduino moving a servo, and it is not just a p5 interface on a screen. The two parts depend on each other. The dashboard guides the user, the Arduino performs the physical action, and the screen updates after receiving confirmation. That connection makes the project feel like a full interactive system.

Another part that I think worked well is the personality of the interface. The pet mood makes the system feel more alive, and it helps communicate the feeding state without needing complicated instructions. The sad, hungry, happy, and resting states make the dashboard easier to understand and more engaging.

I am also proud that I improved the project through user testing. The IR sensor confusion could have been ignored, but I used it as a design lesson. Changing the printed label made the interaction clearer, which showed me that the physical design and the code are equally important.

Resources Used

p5.js

https://p5js.org/reference/ https://p5js.org/tutorials/get-started/ https://www.youtube.com/watch?v=c3TeLi6Ns1E

Serial Communication

https://itp.nyu.edu/physcomp/labs/labs-serial-communication/lab-webserial-input-to-p5-

js/https://itp.nyu.edu/physcomp/labs/labs-serial-communication/lab-webserial-output-from-p5-

js/https://makeabilitylab.github.io/physcomp/communication/p5js-serial.html

https://medium.com/@yyyyyyyuan/tutorial-serial-communication-with-arduino-and-p5-js-cd39b3ac10ce

Servo Motor

https://docs.arduino.cc/tutorials/generic/basic-servo-control/

https://learn.adafruit.com/adafruit-arduino-lesson-14-servo-motors/overview

https://www.youtube.com/watch?v=1mDnaiEytAI

IR Sensor

https://arduinogetstarted.com/tutorials/arduino-infrared-obstacle-avoidance-sensor

https://projecthub.arduino.cc/aboda243/obstacle-detector-using-ir-module-tutorial-101320

https://www.youtube.com/watch?v=vi4hkrrkwkY

https://www.youtube.com/watch?v=ESqhOKgKt5c

AI Usage

I used AI as a support tool during the development of this project. The most important use was debugging my p5.js code, especially because this was one of my first larger coding projects involving serial communication between Arduino and p5. Debugging was difficult because problems could come from the Arduino code, the p5 code, the serial connection, or the browser. AI helped me break down the problem and understand where the issue might be coming from.

AI also helped me understand how to structure parts of the p5 dashboard, especially the schedule logic, and serial communication. I still tested, adjusted, and integrated the code myself to make sure it worked with my actual Arduino setup.

if (secUntilFeed > 0) {
  petMood = "neutral";

  if (serialConnected) {
    statusMsg = "Waiting for next feeding";
  }

} else if (secUntilFeed > -MISSED_GRACE_SEC) {
  petMood = "hungry";
  statusMsg = "Feeding time!";

} else {
  petMood = "sad";
  statusMsg = "Feeding missed!";
}

I also used AI to generate visual design elements for the project, including the PawPortion logo and printable signs for the physical machine. These visuals helped make the project feel more polished and easier for users to understand.

Challenges Faced and How I Tried to Overcome Them

The biggest challenge was serial communication between Arduino and p5. This was one of the first times I worked on a larger project where hardware and software had to communicate continuously. When something did not work, it was hard to know whether the problem was in the Arduino code, the p5 code, the USB connection, or the browser’s serial port.

I overcame this by testing each part separately. First, I tested the servo on Arduino by itself. Then I tested whether p5 could connect to the Arduino. Then I tested sending one simple command. After that, I tested receiving “DONE” back from Arduino. Breaking it into smaller steps made the project less overwhelming.

Another challenge was making the interaction clear to users. The IR sensor confusion showed me that a working sensor does not automatically mean a clear interaction. Users interpreted the printed image as a button because that was the visual language I accidentally created. I fixed this by changing the label and making the physical instruction clearer.

A third challenge was making the project feel polished. Since the project includes both physical and digital parts, it needed to look intentional from both sides. I worked on the dashboard design, printable labels, and project logo so the final setup felt like one system rather than separate pieces.

Future Improvements

If I had more time, I would improve the physical build of the feeder. I would make the container more stable, the food release cleaner, and the overall structure more durable. Right now, the prototype communicates the idea, but a more refined version could look and function more like a real product.

I would also improve the interface by adding sound feedback. For example, a small sound could play when feeding time arrives, when food is dispensed, or when feeding is missed. This would make the system more noticeable and more satisfying to use.

Another future improvement would be adding more customization to the schedule. Instead of using a short demo interval, the user could choose real feeding times, like morning and evening. This would make the system more practical outside of the class demo.

I would also conduct more user testing with people who have not seen the project before. Watching how people understand the physical setup, the IR sensor, and the dashboard would help me refine the interaction even more.

Overall, I am very very proud of how far i’ve come and can confidently say that this class was a very formative step for me in my university journey and the first step to taking on my passion for Interactive Media. 

Stipend Breakdown (50$):

Total Spend: 47.92$