Skip to content

15. Interface and application programming

1. Arduino Serial Communication – Basic Control

To begin with, I used the Arduino IDE to perform basic serial communication. I connected three LEDs to a board I designed during the Input/Output week. Using simple serial commands sent from the Serial Monitor, I could:

  • Turn ON/OFF individual LEDs by typing commands like LED1_ON, LED2_OFF, etc.
  • Control all three simultaneously with multi-command inputs.

// Define LED pins
const int led1 = 26;
const int led2 = 27;
const int led3 = 28;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  Serial.begin(9600);
  Serial.println("Send commands like: LED1 ON");
}

void loop() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    command.trim();

    if (command == "LED1 ON") digitalWrite(led1, HIGH);
    else if (command == "LED1 OFF") digitalWrite(led1, LOW);
    else if (command == "LED2 ON") digitalWrite(led2, HIGH);
    else if (command == "LED2 OFF") digitalWrite(led2, LOW);
    else if (command == "LED3 ON") digitalWrite(led3, HIGH);
    else if (command == "LED3 OFF") digitalWrite(led3, LOW);
    else Serial.println("Invalid command");
  }
}

This was a straightforward and effective way to test basic communication between a PC and microcontroller using Serial.print() and Serial.read() functions.


2. Processing IDE – Graphical User Interface

I used Processing IDE to create a simple GUI for serial control:

  • Six buttons control ON/OFF states for three LEDs.
  • Clicking a button sends a command to the Arduino.

Arduino Code:

const int led1 = 26;
const int led2 = 27;
const int led3 = 28;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    command.trim();

    if (command == "LED1 ON") digitalWrite(led1, HIGH);
    else if (command == "LED1 OFF") digitalWrite(led1, LOW);
    else if (command == "LED2 ON") digitalWrite(led2, HIGH);
    else if (command == "LED2 OFF") digitalWrite(led2, LOW);
    else if (command == "LED3 ON") digitalWrite(led3, HIGH);
    else if (command == "LED3 OFF") digitalWrite(led3, LOW);
  }
}

Processing Code:

import processing.serial.*;

Serial myPort;

Button[] buttons = new Button[6];
String[] labels = {
  "LED1 ON", "LED1 OFF",
  "LED2 ON", "LED2 OFF",
  "LED3 ON", "LED3 OFF"
};

void setup() {
  size(400, 300);
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[2], 9600);

  for (int i = 0; i < 6; i++) {
    buttons[i] = new Button(50 + (i % 2) * 150, 50 + (i / 2) * 70, 120, 50, labels[i]);
  }
}

void draw() {
  background(240);
  for (Button b : buttons) {
    b.display();
  }
}

void mousePressed() {
  for (Button b : buttons) {
    if (b.isClicked(mouseX, mouseY)) {
      myPort.write(b.label + "\n");
      println("Sent: " + b.label);
    }
  }
}

class Button {
  float x, y, w, h;
  String label;

  Button(float x, float y, float w, float h, String label) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.label = label;
  }

  void display() {
    fill(200);
    rect(x, y, w, h);
    fill(0);
    textAlign(CENTER, CENTER);
    text(label, x + w/2, y + h/2);
  }

  boolean isClicked(float mx, float my) {
    return mx > x && mx < x + w && my > y && my < y + h;
  }
}


Input Device Interface

I added a Hall effect sensor interface with a real-time bar visualization in Processing.

Arduino Code:

const int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);
  Serial.println(sensorValue);
  delay(10);
}

Processing Code:

import processing.serial.*;

Serial myPort;
int sensorValue = 0;

void setup() {
  size(500, 200);
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[2], 9600);
  myPort.bufferUntil('\n');
}

void draw() {
  background(255);

  fill(0);
  textAlign(CENTER);
  text("Hall Sensor Slider", width / 2, 30);

  float mappedWidth = map(sensorValue, 0, 1023, 0, width - 60);

  fill(220);
  rect(30, 100, width - 60, 30, 10);

  fill(0, 150, 255);
  rect(30, 100, mappedWidth, 30, 10);

  fill(0);
  textAlign(LEFT);
  text("Value: " + sensorValue, 30, 90);
}

void serialEvent(Serial p) {
  String input = p.readStringUntil('\n');
  if (input != null) {
    input = trim(input);
    if (input.length() > 0) {
      sensorValue = int(input);
    }
  }
}


3. Robot Operating System (ROS) – Advanced Real-Time Interaction

a. IMU Visualization in ROS

I followed this tutorial: automaticaddison.com – BNO055

  • Used Arduino with BNO055 to publish quaternion orientation data to ROS.
  • Visualized in RViz for real-time movement tracking.

Arduino Code:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <ros.h>
#include <sensor_msgs/Imu.h>

Adafruit_BNO055 bno = Adafruit_BNO055(55);

ros::NodeHandle nh;
sensor_msgs::Imu imu_msg;
ros::Publisher imu_pub("imu/data", &imu_msg);

void setup() {
  nh.initNode();
  nh.advertise(imu_pub);

  if (!bno.begin()) {
    while (1);
  }

  delay(1000);
}

void loop() {
  imu::Quaternion quat = bno.getQuat();

  imu_msg.orientation.w = quat.w();
  imu_msg.orientation.x = quat.x();
  imu_msg.orientation.y = quat.y();
  imu_msg.orientation.z = quat.z();

  imu_msg.header.stamp = nh.now();
  imu_msg.header.frame_id = "imu_link";

  imu_pub.publish(&imu_msg);
  nh.spinOnce();
  delay(10);
}


b. Robot Arm Control (Hardware-in-the-Loop)

Tutorials used:
- How to Control a Robot Arm with ROS
- DIY Arduino Robot Arm

  • Synchronized real robot arm and virtual arm model using ROS.
  • Used joint state publishers and real-time inputs to simulate and control motion.

This was a great example of hardware-software integration using ROS and real-time feedback systems.


4. MIT App Inventor

MIT App Inventor is a free, web-based visual programming tool developed by the Massachusetts Institute of Technology (MIT). It enables users to build Android (and limited iOS) apps without writing traditional code.

Key Features

  • Block-based coding: Uses drag-and-drop blocks for logic, ideal for beginners.
  • Designer & Blocks Editor:
  • Designer: Create the app’s user interface.
  • Blocks Editor: Define behavior using logic blocks.
  • Real-time testing with the MIT AI2 Companion app.
  • Built-in components: Buttons, sensors, media, databases, connectivity (Bluetooth, Web), and more.

Educational Use

  • Widely used in schools to teach programming, logic, and mobile app development.
  • Supports STEM learning and global innovation challenges.

Pros

  • Easy to use and beginner-friendly.
  • Great for rapid prototyping.
  • No installation needed (runs in the browser).

Limitations

  • Limited support for iOS.
  • Not ideal for complex or high-performance apps.

MIT App Inventor empowers anyone to create mobile apps, especially useful in education, innovation, and social impact projects.

How to Use MIT App Inventor

  1. Go to the Website
  2. Visit https://appinventor.mit.edu

  1. Sign In
  2. Click “Create Apps”
  3. Sign in with a Google account

  1. Start a New Project
  2. Click “Start new project”
  3. Enter a name (e.g., Test)

  1. Design the Interface
  2. Drag components (buttons, labels, etc.) from the Palette to the Viewer
  3. Customize them in the Properties panel

Here, we add a button and a text box.

  1. Add Functionality
  2. Switch to the Blocks Editor
  3. Drag and connect logic blocks to define app behavior (e.g., what happens when a button is clicked)

When the button is pressed, it will turn green and display the text “Button Pressed.”

  1. Test the App
  2. Download the MIT AI2 Companion App on your phone
  3. Scan the QR code shown in the browser to live test your app

  1. Save or Export
  2. Save your project online automatically
  3. Use “Export” to download the .aia file
  4. Build an .apk file to install the app on Android devices

Last update: May 24, 2025