Skip to content

14. Interface and Application Programming

This week, I focused on learning how to create interfaces that allow users to interact with hardware through application programming..

Understanding the basics

What are interfaces?

Interfaces are points where different parts of a system connect and interact. In computing, an interface is a set of functions or rules that define how software components talk to each other. It creates a clear boundary, allowing them to share information or request services without needing to understand each other’s internal details.

What is API?

API stands for Application Programming Interface.It is a set of rules that allows different software applications to talk to each other. It defines how requests and responses should be made, so one program can use features or data from another without knowing how it's built.

How API works?

Processing using the Xiao RP2040

Processing is a software used to make simple graphics and interactive screens, like sliders or buttons, on your computer. When you connect them using a USB cable, you can use Processing to send commands from your computer to the Xiao, or get data from the Xiao and show it on your screen. This helps you make fun and useful projects where the computer and hardware work together.

I was confused at the beginning so I referred Jesal Sir's documentation

For doing this I will be using the PCB which I made during week 8

You can download the application from the the processing website

Mouse click: Led on/off

Code for the Arduino IDE
#include <Adafruit_NeoPixel.h>

#define NUMPIXELS 1
#define PIXELPOWER 11
#define PIXELPIN 12

Adafruit_NeoPixel pixel(NUMPIXELS, PIXELPIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(9600); // Set baud rate to match with Processing or Serial Monitor
  pinMode(PIXELPOWER, OUTPUT);
  digitalWrite(PIXELPOWER, HIGH);

  pixel.begin();
  pixel.show(); // Initialize all pixels to 'off'
}

void loop() {
  if (Serial.available() >= 2) { // Wait until 2 bytes are available
    int g = Serial.read(); // read green
    int r = Serial.read(); // read red

    Serial.print("Red: ");
    Serial.print(r);
    Serial.print(" Green: ");
    Serial.println(g);

    pixel.setPixelColor(0, pixel.Color(r, g, 128)); // fixed blue value
    pixel.show();
    delay(200);

    pixel.setPixelColor(0, pixel.Color(0, 0, 0)); // turn off
    pixel.show();
}
}

Code for the processing
import processing.serial.*;

Serial serial;

void setup() {
  size(300, 300); // Set the size of the canvas
  String portName = Serial.list()[0]; // Get the first available serial port
  serial = new Serial(this,portName, 9600); // Open the serial port
  print(Serial.list()[0]);
}

void draw() {
  // Draw the canvas
  background(255);
  ellipse(width/2, height/2, 100, 100); // Draw a circle representing the LED

  // Check for mouse click
  if (mousePressed) {
    if (dist(mouseX, mouseY, width/2, height/2) < 50) {
      serial.write('1'); // Send '1' to turn on the LED
    } else {
      serial.write('0'); // Send '0' to turn off the LED
    }
  }
}

Colour spectrum

After trying basic color changes, I moved on to a more fun idea — using a color spectrum! I made a program in Processing that shows a colorful screen. When I clicked on any part of it, the computer picked the color at that spot and sent its red, green, and blue (RGB) values to the Xiao RP2040.

Note: I noticed that the LED flickers briefly before showing the correct color. It seems like the color changes quickly a couple of times before settling on the final shade.

Code for the Arduino IDE
#include <Adafruit_NeoPixel.h>
#define numpixels 1
#define pixelpower 11
#define pixelpin 12
Adafruit_NeoPixel pixel(numpixels, pixelpin, NEO_GRB + NEO_KHZ800);


void setup() {
  Serial.begin(9600); // Set the baud rate to match the Processing sketch

  pinMode(pixelpower, OUTPUT);
  pixel.begin();
  digitalWrite(pixelpower, HIGH);

}

void loop() {
  if (Serial.available())
  {
    char g = Serial.read();
    char r = Serial.read();
    Serial.print(r);
    Serial.print(" ");
    Serial.println(g);

    int r_ = int(r);
    int g_ = int(g);

    pixel.setPixelColor(0, pixel.Color(r_, g_, 128));
    pixel.show();
    delay(200);
    pixel.setPixelColor(0, pixel.Color(0, 0, 0));
    pixel.show();
  }
}
Code for the processing

import processing.serial.*;

Serial serial;

void setup() {

  size(400, 400); // Set the size of the canvas
  String portName = Serial.list()[0]; // Get the first available serial port
  serial = new Serial(this, portName, 9600); // Open the serial port
  print(Serial.list()[0]);

  int step = 50;
  noStroke();

  //drawing the colour interface
  for (int j = 0; j<=height; j+=step/2)
  {
    for (int i = 0; i<=width; i+=step/2)
    {
      int r = i;
      int g = j;
      int r_ = int(map(r, 0, width, 0, 255));
      int g_ = int(map(g, 0, height, 0, 255));
      fill(r_, g_, 128);
      ellipse(r, g, step, step);
      //print("g = ", r," g = ", g, " ");
    }
  }
}

void draw() {

  if (mousePressed) {

    //picking up colour based on location

    int r_ = int(map(mouseX, 0, width, 0, 255));
    int g_ = int(map(mouseY, 0, height, 0, 255));
    serial.write(r_);
    serial.write(g_);
    print(r_, " ", g_, " ");
    println();
  }
}

Mixing Mouse LED Toggle and Color Control

Earlier, I explored two projects: first, using mouse clicks in Processing to turn an Arduino LED on and off, and second, controlling a NeoPixel’s color by mapping mouse position to RGB values. Now to explore further and I am interested in combining these ideas for more complex interactivity.

So I want to control the color of a NeoPixel LED using your mouse position. When you move your mouse on the screen, the horizontal position controls the red color intensity, and the vertical position controls the green color intensity of the LED.

Code for Arduino IDE
#include <Adafruit_NeoPixel.h>

#define NUMPIXELS 1
#define PIXELPOWER 11
#define PIXELPIN 12

Adafruit_NeoPixel pixel(NUMPIXELS, PIXELPIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(9600);
  pinMode(PIXELPOWER, OUTPUT);
  digitalWrite(PIXELPOWER, HIGH);

  pixel.begin();
  pixel.show();
}

void loop() {
  if (Serial.available() >= 2) {
    int r = Serial.read(); // read red first
    int g = Serial.read(); // then green

    Serial.print("Red: ");
    Serial.print(r);
    Serial.print(" Green: ");
    Serial.println(g);

    pixel.setPixelColor(0, pixel.Color(r, g, 128)); // fixed blue
    pixel.show();
  }
  // No delay and no turning off here, color updates on every input
}

Code for Processing
import processing.serial.*;

Serial serial;

void setup() {
  size(300, 300);
  String portName = Serial.list()[0];
  serial = new Serial(this, portName, 9600);
  println("Using port: " + portName);
}

void draw() {
  background(255);

  // Map mouseX to red (0-255), mouseY to green (0-255)
  int r = int(map(mouseX, 0, width, 0, 255));
  int g = int(map(mouseY, 0, height, 0, 255));

  // Draw color preview circle
  fill(r, g, 128);
  ellipse(width/2, height/2, 100, 100);

  // Send the RGB values continuously to Arduino
  // but limit sending to avoid overwhelming serial buffer
  if (frameCount % 5 == 0) { 
    serial.write(r);
    serial.write(g);
  }

  // Draw some instructions
  fill(0);
  textAlign(CENTER);
  text("Move mouse to change Red and Green", width/2, height - 40);
  text("Red (X): " + r, width/2, height - 25);
  text("Green (Y): " + g, width/2, height - 10);
}

Blynk

Blynk.io is a platform that allows you to control and monitor hardware projects like Arduino, ESP32, or RP2040 boards using your smartphone.

You can download it here: Blynk.io

Our college subject “IoT” happened at the same time as the interface and application week. I’m thankful to Chinmay Sir , for showing us the steps and helping us learn how to do it properly.

Process

You start off by creating a new template.

I am using ESP8266. So add the project name and hardware and click on done.

Once that is done create a datastream. Go to Datastream>New Datastream>Virtual pin

In the virtual datastream, you can add different components that will connect your app interface to the hardware. I decided to use a switch to turn an LED on and off, and also control the LED brightness using PWM with a potentiometer.

The 3 Datastreams should look like this.

Note: The Potentiometer should have a range of 0 to 1023 as that is the size of the ADC of the NodeMCU.

Once that is done click on the web dashboard>edit to find the below screen with various widgets.

You just have to drag and dropthe widgets. The slider is for the potentiometer,gauge for PWM and the switch for the push button

After saving you will be directed to the web dashboard

Next you need to create a device. Go to Device>New device

Choose from template option

Create a new device

Once created edit each of the widget to add specifications.

Add switch settings to the datastream: Led

Add pwm settings to the datastream: Pwm

Add Potentiometer settings to the datastream: Potentiometer

Once done save and apply

Once done copy the below code to Arduino IDE

Note: Make sure to add the copied Template ID, Template name and BLYNK_AUTH_TOKEN in the code

Code
//--------------------------------------------------------------------------------------------------------------------------
//Datastreams on Blynk - 
// V0 - Potentiometer
// V1 - LED Switch
// V2 - PWM LED
//--------------------------------------------------------------------------------------------------------------------------
#define BLYNK_TEMPLATE_ID "TMPL3shupF3mn"
#define BLYNK_TEMPLATE_NAME "Iot"
#define BLYNK_AUTH_TOKEN "qF_TOBMw_8c_WNhkkGPdliCHj13nZb9c"
//--------------------------------------------------------------------------------------------------------------------------
// Comment this out to disable prints and save space
#define BLYNK_PRINT Serial
//--------------------------------------------------------------------------------------------------------------------------
// Initialize required libraries 
#include             
#include 
//--------------------------------------------------------------------------------------------------------------------------
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "HONOR_X9b_5G";    // Wifi name. Case, space sensitive  
char pass[] = "shrey231004";  // Wifi passowrd. Case, space sensitive. Set password to "" for open networks.
//--------------------------------------------------------------------------------------------------------------------------
int potValue = A0;  // Assign pin A0 to read potentiometer value

void setup() {
  pinMode(potValue, INPUT);                                 // Define pin A0 as input. (Potentiometer)
  pinMode(D4, OUTPUT);                                      // Define pin D4 as output. (LED_Switch)
  pinMode(D2, OUTPUT);                                      // Define pin D2 as output. (PWM_LED)
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);                          // Initialize Blynk parameters
}
//--------------------------------------------------------------------------------------------------------------------------
// Virtual Pin V1. This function takes value from pin V0 from Blynk and updates it on ESP board. 
BLYNK_WRITE(V1) {
 int pinValue = param.asInt(); // Assigning incoming value from pin V1 to a variable
  if (pinValue == 1) {         // 
   digitalWrite(D4, HIGH);      
  }
     else {
      digitalWrite(D4, LOW);
     }                        
}
//--------------------------------------------------------------------------------------------------------------------------
// Virtual Pin V2. This function takes value from pin V2 from Blynk and updates it on ESP board. 
BLYNK_WRITE(V2) {
 int PWMValue = param.asInt(); // Assigning incoming value from pin V2 to a variable
 analogWrite (D2,PWMValue);           
}
//--------------------------------------------------------------------------------------------------------------------------
void loop() {
  Blynk.run();
  int potValue  = analogRead(A0);    // Read analog value from potentiometer on pin A0
  Blynk.virtualWrite(V0, potValue);  // Sends Analog value to Gauge on datastream V0          
}

After that go to Library Manager> Blynk>Install

Go to the highlighted lines and laptop Wifi name and password

The above wasn't working so I changed the network

Circuit Diagram

I made the connections

Final

P5js

I used P5js during my first year of college when I was very new to the concept of creative coding.

P5js is an open-source JavaScript library designed to make creative coding easy and accessible — especially for artists, designers, beginners, and educators.

Version 1

In the first version of my code, I wanted to try something simple using the mouse. Like where every time I drag the mouse, a circle (ellipse) appears wherever the mouse goes.

This helped me understand how mouseDragged() works in p5.js. It allowed me to create a basic drawing tool — kind of like a brush that leaves a trail of circles while I drag the mouse.

Code


function setup() {
  createCanvas(400, 400);
}

function draw() {

  //background(220,10);
  fill(47,65,48,);
  //rect(25,87,56,200);
  noStroke();
  fill(6,100,110)
  ellipse(mouseX+random(-5,5), mouseY+random(-5,5),8,8);
}

Version 2

I wanted to make something more fun and interactive using the mouse. Something like

  • When I click the mouse, a circle appears at the mouse pointer. The color and size of the circle are random every time.
  • When I drag the mouse (click and move), it draws lines, like free-hand drawing.
  • When I just move the mouse without clicking, small faded circles appear and follow the pointer.
  • When I release the mouse, it shows the x and y position of where I left the mouse button.
  • When I click, it also shows a text saying where I clicked.

I used chatgpt to write this code

Code

let circles = [];

function setup() {
  createCanvas(600, 400);
  background(240);
  textSize(14);
  fill(0);
  text("Click, drag, move or release the mouse!", 20, 20);
}

function draw() {
  // No continuous drawing
}

// Create a new circle on click
function mousePressed() {
  let c = {
    x: mouseX,
    y: mouseY,
    r: random(10, 40),
    col: color(random(255), random(255), random(255))
  };
  circles.push(c);
  drawCircle(c);
}

function mouseReleased() {
  fill(0);
  text("Mouse released at (" + mouseX + ", " + mouseY + ")", 20, height - 20);
}

function mouseDragged() {
  stroke(0);
  line(pmouseX, pmouseY, mouseX, mouseY); // draw a line while dragging
}

function mouseMoved() {
  noStroke();
  fill(255, 50);
  ellipse(mouseX, mouseY, 10, 10); // faint trail as mouse moves
}

function mouseClicked() {
  fill(0);
  text("Mouse clicked at (" + mouseX + ", " + mouseY + ")", 20, height - 40);
}

function drawCircle(c) {
  noStroke();
  fill(c.col);
  ellipse(c.x, c.y, c.r * 2);
}


Group Assignmnet

Comparing Processing, Blynk and P5.js

Feature Processing p5.js Blynk
Type Desktop-based creative coding tool Web-based creative coding tool IoT (Internet of Things) platform
Programming Language Java-based JavaScript C++ for hardware + app interface
Runs On Desktop app Web browser Smartphone (app) + microcontroller (e.g. ESP32)
User Interface Simple code-based windows (drawings, buttons) Runs in browser window (interactive UI) Drag-and-drop interface in app (buttons, sliders)
Installation Needs desktop installation No installation, runs in browser Needs app on phone and library on microcontroller
Best For Visual art, simulations, prototyping Web art, live visuals, interactive websites IoT projects, smart home controls, sensor monitoring

Exercise files

Below are the files for:

Mouse to LED processing code

Mouse to LED Arduino code

Colour spectrum processing code

Colour spectrum Arduino code

Mouse and RGB Arduino code

Mouse and RGB Processing code

Blynk code