17 Beginner Arduino Sensor Projects in 2025

Last updated on February 12th, 2025 at 01:28 pm

Are you looking to jump into the world of Arduino and explore fun, beginner-friendly projects? You’re in the right place! In this article, we’ll introduce 12 popular sensors and showcase 17 creative projects you can build around them. Whether you’re a hobbyist, student, or an aspiring engineer, these ideas will help you grasp fundamental concepts, practice coding skills, and gain hands-on experience with electronics.

1. PIR Sensor

A Passive Infrared (PIR) sensor detects motion by measuring changes in infrared light within its field of view. It’s commonly used in security systems and automatic lighting because it can sense the presence of humans or animals without physical contact.

Project 1: Motion Activated Light

In this project, you’ll use a PIR sensor to detect movement and turn on an LED (or any other light source). When no motion is detected, the light remains off, helping to conserve energy.

Components Required

  • Arduino board
  • PIR sensor module
  • Light Bulb
  • 2 Channel relay module
  • Jumper wires
  • Breadboard

Circuit Diagram

Motion Activated Bulb using PIR Sensor

Program

#define PIR_PIN 5     // Digital pin for PIR sensor
#define RELAY_PIN 12  // Digital pin for relay

unsigned long motionTimeout = 3000;  // Time in milliseconds to wait before turning off relay
unsigned long lastMotionTime = 0;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Configure PIR sensor pin as input
  pinMode(PIR_PIN, INPUT);

  // Configure relay pin as output
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH);  // Ensure relay is off initially (reverse logic)

  Serial.println("PIR Sensor and Relay Control Initialized");
}

void loop() {
  // Read PIR sensor state
  int pirState = digitalRead(PIR_PIN);

  if (pirState == HIGH) {
    // Motion detected: Turn ON the relay and reset the timer
    digitalWrite(RELAY_PIN, LOW);  // Turn ON relay (reverse logic)
    lastMotionTime = millis();     // Update the last motion detection time
    Serial.println("Motion detected: Relay ON");
  } else {
    // No motion: Check if timeout has elapsed
    if (millis() - lastMotionTime > motionTimeout) {
      digitalWrite(RELAY_PIN, HIGH);  // Turn OFF relay (reverse logic)
      Serial.println("No motion: Relay OFF");
    }
  }

  // Small delay for stability
  delay(100);
}

2. Soil Moisture Sensor

A soil moisture sensor measures the water content in the soil. It’s perfect for gardening and agricultural projects, allowing you to monitor or automate plant watering.

Project 2: Automatic Plant Watering System

Keep your plants healthy by automatically watering them when the soil is too dry. The soil moisture sensor sends data to the Arduino, which triggers a water pump when moisture levels drop below a set threshold.

Components Required

  • Arduino board
  • Soil moisture sensor
  • Water pump
  • Tubing or piping for water flow
  • 2-channel relay module
  • Separate power supply for the pump(3V to 6V)

Circuit Diagram

Program

// Pin definitions
const int soilMoisturePin = A0;  // Soil moisture sensor analog pin
const int ledPin = 8;            // LED pin
const int pumpPin = 9;           // Pump pin
const int threshold = 1000;      // Moisture threshold (adjust based on testing)

void setup() {
  // Initialize components
  pinMode(ledPin, OUTPUT);
  pinMode(pumpPin, OUTPUT);
  Serial.begin(9600);

  Serial.println("Soil Moisture Sensor Initialized");
}

void loop() {
  // Read soil moisture sensor value
  int soilValue = analogRead(soilMoisturePin);
  Serial.print("Soil Moisture Value: ");
  Serial.println(soilValue);

  if (soilValue > threshold) {    // Dry soil condition
    digitalWrite(ledPin, HIGH);   // Turn on LED
    digitalWrite(pumpPin, HIGH);  // Turn on pump
    Serial.println("Status: DRY");
  } else {                       // Sufficient moisture
    digitalWrite(ledPin, LOW);   // Turn off LED
    digitalWrite(pumpPin, LOW);  // Turn off pump
    Serial.println("Status: WET");
  }

  delay(500);  // Wait before the next reading
}

3. Color Sensor (e.g., TCS3200)

A color sensor can detect the color of an object by measuring reflected light across different color filters (usually Red, Green, and Blue). This sensor is often used in sorting systems and color-based recognition projects.

Project 3: RGB Color Detector

Point the sensor at an object, and the Arduino outputs the RGB values to identify the color. This is a great way to learn about color theory and how sensors interpret light.

Components Required

  • Arduino board
  • Color sensor module (e.g., TCS3200)
  • RGB LED
  • Jumper wires
  • Breadboard

Circuit Diagram

Program

#include <Wire.h>
#include "Adafruit_TCS34725.h"

// Pins for RGB LEDs
#define RED_LED_PIN 3
#define GREEN_LED_PIN 5
#define BLUE_LED_PIN 6

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

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

  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1)
      ;
  }

  // Initialize LED pins as output
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);

  // Turn off all LEDs initially
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(GREEN_LED_PIN, LOW);
  digitalWrite(BLUE_LED_PIN, LOW);
}

void loop() {
  uint16_t r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);

  // Normalize RGB values using clear channel (luminance)
  float red = r / (float)c * 255.0;
  float green = g / (float)c * 255.0;
  float blue = b / (float)c * 255.0;

  // Ensure values stay in bounds
  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  Serial.print("R:");
  Serial.print((int)red);
  Serial.print(" G:");
  Serial.print((int)green);
  Serial.print(" B:");
  Serial.println((int)blue);

  // Calculate differences between RGB values
  float diffRG = abs(red - green);
  float diffRB = abs(red - blue);
  float diffGB = abs(green - blue);

  // Turn off LEDs if differences are within the range of 30
  if (diffRG <= 50 && diffRB <= 50 && diffGB <= 50) {
    digitalWrite(RED_LED_PIN, LOW);
    digitalWrite(GREEN_LED_PIN, LOW);
    digitalWrite(BLUE_LED_PIN, LOW);
  } else {
    // Determine the dominant color and turn on the corresponding LED
    if (red > green && red > blue) {
      digitalWrite(RED_LED_PIN, HIGH);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, LOW);
    } else if (green > red && green > blue) {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, HIGH);
      digitalWrite(BLUE_LED_PIN, LOW);
    } else if (blue > red && blue > green) {
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, HIGH);
    } else {
      // If no dominant color, turn off all LEDs
      digitalWrite(RED_LED_PIN, LOW);
      digitalWrite(GREEN_LED_PIN, LOW);
      digitalWrite(BLUE_LED_PIN, LOW);
    }
  }

  delay(100);
}

Project 4: Visual Color Detection

Using the same color sensor setup with the Processing software, we will visualize the detected color on the screen. Just remove all the LEDs.

First, download the Processing software from here.

Install the software, then upload the program given below to your Arduino board.

Note: Make sure the USB cable is connected to the proper port on your laptop while running the software. Also, keep your serial monitor/plotter off.

Arduino Program

#include <Wire.h>
#include "Adafruit_TCS34725.h"

// Pins for RGB LED
#define redpin 3
#define greenpin 5
#define bluepin 6
#define commonAnode true

byte gammatable[256];
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

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

  if (!tcs.begin()) {
    Serial.println("No TCS34725 found ... check your connections");
    while (1)
      ;
  }

  // Gamma correction table
  for (int i = 0; i < 256; i++) {
    float x = i / 255.0;
    x = pow(x, 2.5);
    x *= 255.0;
    gammatable[i] = commonAnode ? 255 - x : x;
  }
}

void loop() {
  uint16_t r, g, b, c;
  tcs.getRawData(&r, &g, &b, &c);

  // Normalize RGB values using clear channel (luminance)
  float red = r / (float)c * 255.0;
  float green = g / (float)c * 255.0;
  float blue = b / (float)c * 255.0;

  // Ensure values stay in bounds
  red = constrain(red, 0, 255);
  green = constrain(green, 0, 255);
  blue = constrain(blue, 0, 255);

  Serial.print("R:\t");
  Serial.print((int)red);
  Serial.print("\tG:\t");
  Serial.print((int)green);
  Serial.print("\tB:\t");
  Serial.print((int)blue);
  Serial.print("\tC:\t");
  Serial.println(c);

  delay(100);
}

Next, paste this code inside this new software window and click on ‘Run’.

Processing Code

import processing.serial.*;

Serial myPort;  // Serial port for communication
float red = 0, green = 0, blue = 0, clear = 0;  // RGB and clear values from Arduino

void setup() {
  size(400, 400);  // Window size
  String portName = Serial.list()[0];  // Automatically select the first available port
  myPort = new Serial(this, portName, 9600);  // Open serial port
  myPort.clear();  // Clear old data in the buffer
  myPort.bufferUntil('\n');  // Wait for a full line of data
}

void draw() {
  background(255);  // White background

  // Detect color name and adjust displayed color
  String detectedColor = detectColor(red, green, blue, clear);

  if (detectedColor.equals("No Color Detected")) {
    // Draw a red "X" for No Color Detected
    fill(255, 0, 0);  // Red color
    stroke(255, 0, 0);
    strokeWeight(8);
    line(100, 100, 300, 300);  // Diagonal line 1
    line(100, 300, 300, 100);  // Diagonal line 2
    noStroke();
  } else {
    // Set fill color based on detected color
    if (detectedColor.equals("Black")) {
      fill(0);  // Black
    } else if (detectedColor.equals("White")) {
      fill(255);  // White
    } else {
      fill(red, green, blue);  // Use detected RGB values for other colors
    }

    noStroke();
    rect(50, 50, width - 100, height - 100);  // Draw rectangle
  }

  // Display detected color name and values
  fill(0);  // Black text
  textSize(20);
  textAlign(CENTER);
  text("Detected Color: " + detectedColor, width / 2, 30);
  text("R: " + int(red) + " G: " + int(green) + " B: " + int(blue) + " C: " + int(clear), width / 2, height - 20);
}

void serialEvent(Serial myPort) {
  String data = myPort.readStringUntil('\n');  // Read Serial data
  if (data != null) {
    data = trim(data);  // Remove whitespace
    String[] values = split(data, '\t');  // Split by tab characters
    if (values.length >= 8) {  // Ensure we have R, G, B, C values
      try {
        // Parse and update RGB and clear values
        red = float(values[1]);
        green = float(values[3]);
        blue = float(values[5]);
        clear = float(values[7]);
      } catch (Exception e) {
        println("Error parsing values: " + e.getMessage());
      }
    }
  }
}

String detectColor(float r, float g, float b, float c) {
  if (c < 400) return "Black";  // Low clear value indicates black
  if (c > 1600 && abs(r - g) < 50 && abs(g - b) < 50) return "White";  // High clear, similar RGB values
  if (c > 600 && c < 1200 && abs(r - g) < 30 && abs(g - b) < 30) return "No Color Detected";  // Mid-range clear, no distinct color
  if (r > g && r > b) return "Red";
  if (g > r && g > b) return "Green";
  if (b > r && b > g) return "Blue";
  return "Unknown";
}

4. IR Receiver

An Infrared (IR) receiver detects IR signals from a remote control. By decoding these signals, your Arduino can recognize specific button presses.

Project 5: Bulb and Motor Control Using Remote

In this project, you will control an LED bulb and DC motor using two buttons on your IR remote. This is a great project to learn about IR communication and how to decode remote control signals.

Components Required

  • Arduino UNO
  • IR receiver module
  • IR remote
  • 2 Channel Relay module
  • LED bulb
  • DC Motor
  • Separate power supply for the motor
  • Jumper wires
  • Breadboard

Circuit Diagram

Program

Note: Make sure you download the correct IRremote library version i.e., 2.5 or previous.

#include <IRremote.h>

#define IR_RECEIVE_PIN 5  // Pin for IR receiver

// Define relay pins
#define RELAY1_PIN 11
#define RELAY2_PIN 12

IRrecv irrecv(IR_RECEIVE_PIN);
decode_results results;

// Define IR remote button codes (replace with actual values from your remote)
#define BUTTON_1 0xFF30CF  // Example hex code for button 1
#define BUTTON_2 0xFF18E7  // Example hex code for button 2

// Relay states
bool relay1State = false;
bool relay2State = false;

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);

  // Initialize relay pins as outputs
  pinMode(RELAY1_PIN, OUTPUT);
  pinMode(RELAY2_PIN, OUTPUT);

  // Ensure relays are off initially
  digitalWrite(RELAY1_PIN, HIGH);
  digitalWrite(RELAY2_PIN, HIGH);

  // Initialize IR receiver
  Serial.println("Enabling IRin");
  irrecv.enableIRIn();

  Serial.println("Ready to receive IR signals");
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.print("Received code: ");
    Serial.println(results.value, HEX);

    // Check for button presses
    if (results.value == BUTTON_1) {
      digitalWrite(RELAY1_PIN, relay1State);
      Serial.print("Relay 1 state: ");
      Serial.println(relay1State ? "OFF" : "ON");
      relay1State = !relay1State;  // Toggle relay 1 state
    } else if (results.value == BUTTON_2) {
      digitalWrite(RELAY2_PIN, relay2State);
      Serial.print("Relay 2 state: ");
      Serial.println(relay2State ? "OFF" : "ON");
      relay2State = !relay2State;  // Toggle relay 2 state
      delay(2000);
      digitalWrite(RELAY2_PIN, LOW);
    }

    irrecv.resume();  // Receive the next value
  }
  delay(100);
}

5. Water Sensor

A water sensor (or rain sensor) can detect the presence of water by measuring the conductivity between two metal leads. It’s often used in rainfall detection or water leakage alarms.

Project 6: Rain Detection Alarm

Place the sensor outside, and it triggers a buzzer when it detects rain. This can serve as a simple alert system to protect your outdoor equipment or inform you when it starts to rain.

Components Required

  • Arduino board
  • Water sensor
  • Buzzer
  • LED
  • 220-ohm resistor
  • Jumper wires

Circuit Diagram

Program

const int waterSensorPin = A0;  // Water sensor output pin
const int ledPin = 8;           // LED pin
const int buzzerPin = 11;       // Buzzer pin
const int threshold = 300;      // Water detection threshold (adjust based on testing)

void setup() {
  pinMode(ledPin, OUTPUT);     // Set LED pin as output
  pinMode(buzzerPin, OUTPUT);  // Set Buzzer pin as output
  Serial.begin(9600);          // Initialize Serial Monitor
}

void loop() {
  int waterValue = analogRead(waterSensorPin);  // Read the water sensor value

  Serial.print("Water Sensor Value: ");
  Serial.println(waterValue);  // Print the sensor value for debugging

  if (waterValue > threshold) {     // If water is detected
    digitalWrite(ledPin, HIGH);     // Turn on LED
    digitalWrite(buzzerPin, HIGH);  // Turn on buzzer
    Serial.println("Water detected!");
  } else {
    digitalWrite(ledPin, LOW);     // Turn off LED
    digitalWrite(buzzerPin, LOW);  // Turn off buzzer
    Serial.println("No water detected.");
  }

  delay(500);  // Small delay for stability
}

6. HC-SR04 Ultrasonic Sensor

The HC-SR04 ultrasonic sensor measures distance by sending out ultrasonic pulses and timing how long they take to return. It’s widely used for obstacle avoidance and distance measurement.

Project 7: Distance measurement

Using this ultrasonic sensor we will measure the distance of an object from it and print the distance on a 0.91 inch OLED display.

Components Required

  • Arduino board
  • HC-SR04 ultrasonic sensor
  • 0.91 inch(128*32 px) OLED display
  • Jumper wires

Circuit Diagram

Program

#include <Wire.h>
#include <Adafruit_SSD1306.h>

// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// HC-SR04 pins
#define TRIG_PIN 8
#define ECHO_PIN 9

void setup() {
  // Initialize Serial Monitor
  Serial.begin(9600);
  Serial.println("Initializing...");

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 allocation failed");
    for (;;)
      ;
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("HC-SR04 + OLED");
  display.setCursor(0, 16);
  display.println("Distance in cm");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Initialize HC-SR04 pins
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

void loop() {
  long duration;
  float distance;

  // Send a 10us pulse to trigger pin
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Read echo pin and calculate duration
  duration = pulseIn(ECHO_PIN, HIGH);

  // Calculate distance in cm (speed of sound = 34300 cm/s)
  distance = duration * 0.034 / 2;

  // Display distance on Serial Monitor
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");

  //Display distance on OLED
  display.clearDisplay();
  //display.setCursor(0, 0);
  //display.setTextSize(1);
  //display.println("HC-SR04 Distance");
  display.setTextSize(4);
  display.setCursor(0, 0);
  display.print(distance);
  display.print(" cm");
  display.display();

  delay(1000);  // Wait for a short while before the next measurement
}

Project 8: Posture correction/Eye protection device

Mount the ultrasonic sensor behind your laptop. If you lean too far forward (reducing the measured distance), a buzzer reminder activates to keep your distance from the laptop screen.

Components Required

  • Arduino board
  • HC-SR04 ultrasonic sensor
  • Buzzer
  • Jumper wires

Circuit Diagram

Program

7. Sound Sensor

A sound sensor module typically includes a microphone and an amplifier circuit, allowing you to measure the intensity of sound waves. Perfect for projects reacting to claps, music, or ambient noise.

Project 9: Music Reactive LEDs

Let your LEDs dance to the rhythm of music! When the sound sensor detects variations in sound levels, the Arduino turns ON/OFF the LEDs.

Components Required

  • Arduino UNO
  • Sound sensor module
  • LED x 3
  • 220 ohm resistor x 3
  • Jumper wires

Circuit Diagram

Program

const int soundSensor = 2;
const int redLed = 3;
const int greenLed = 5;
const int blueLed = 6;

void setup() {

  Serial.begin(9600);

  pinMode(redLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(blueLed, OUTPUT);
}


void loop() {
  int soundValue = digitalRead(soundSensor);
  Serial.print("Sound Level:  ");
  Serial.println(soundValue);
  digitalWrite(redLed, soundValue);
  digitalWrite(greenLed, soundValue);
  digitalWrite(blueLed, soundValue);
  delay(10);
}

8. LDR Sensor (Light Dependent Resistor)

An LDR’s resistance changes based on the amount of light hitting it. In brighter conditions, its resistance decreases; in darker conditions, it increases. LDRs are key components in light-based automation.

Project 10: Automatic Street Light

Use an LDR to detect darkness and automatically turn on the LED bulb connected to a relay module. This project is commonly used for energy-saving lighting systems.

Components Required

  • Arduino board
  • LDR
  • 2-channel relay module
  • A.C bulb/ LED bulb
  • 10k ohm Resistor (for voltage divider)
  • Jumper wires

Circuit Diagram

Program

#define LDR_PIN A0    // Analog pin for LDR
#define RELAY_PIN 12  // Digital pin for relay

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Configure the relay pin as output
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // Ensure relay is off initially

  // Print a startup message
  Serial.println("LDR and Relay Control Initialized");
}

void loop() {
  // Read the LDR value
  int ldrValue = analogRead(LDR_PIN);

  // Print the LDR value to the Serial Monitor
  Serial.print("LDR Value: ");
  Serial.println(ldrValue);

  // Define a threshold for light level
  int threshold = 450;  // Adjust this value based on your environment

  // Control the relay based on LDR value
  if (ldrValue < threshold) {
    // If light level is low, turn ON the relay
    digitalWrite(RELAY_PIN, LOW);
    Serial.println("Relay ON (Low Light)");
  } else {
    // If light level is high, turn OFF the relay
    digitalWrite(RELAY_PIN, HIGH);
    Serial.println("Relay OFF (Bright Light)");
  }

  // Small delay for stability
  delay(500);
}

9. Joystick Module

A typical two-axis joystick module (often built with two potentiometers) can measure movement in the X and Y directions, as well as a push button press.

Project 11: Real-Time Ball Control on Screen

By connecting a joystick to an Arduino and using the Processing software, we will control a digital ball’s movement on a computer screen in real time. This teaches analog input reading and basic game development concepts.

Components Required

  • Arduino UNO
  • Joystick module
  • USB cable

Circuit Diagram

Arduino Program

void setup() {
  Serial.begin(9600);        // Initialize serial communication
  pinMode(2, INPUT_PULLUP);  // Joystick button (SW)
}

void loop() {
  int xValue = analogRead(A0);       // Read X-axis value(connect it to X on Joystick)
  int yValue = analogRead(A1);       // Read Y-axis value
  int buttonState = digitalRead(2);  // Read button state (pressed or not)

  // Send data to Processing in a format: X,Y,Button
  Serial.print(xValue);
  Serial.print(",");
  Serial.print(yValue);
  Serial.print(",");
  Serial.println(buttonState);

  delay(10);  // Small delay for stability
}

Processing Code

Note: Make sure the USB cable is connected to the proper port on your laptop while running the software. Also, keep your serial monitor/plotter off.

import processing.serial.*;  // Import the Serial library

Serial myPort;  // The serial port
float circleX, circleY;  // Circle position
float speed = 5;  // Speed factor for movement

void setup() {
  size(600, 600);  // Set window size
  circleX = width / 2;  // Start circle at the center
  circleY = height / 2;

  // Connect to Arduino
  myPort = new Serial(this, Serial.list()[0], 9600);  
  myPort.bufferUntil('\n');  // Read until newline
}

void draw() {
  background(0);  // Clear the screen
  fill(255, 0, 0);
  ellipse(circleX, circleY, 50, 50);  // Draw the circle
}

void serialEvent(Serial myPort) {
  String data = myPort.readStringUntil('\n');  // Read serial data
  data = trim(data);  // Remove extra whitespace
  if (data != null) {
    String[] values = split(data, ',');  // Split the data into X, Y, Button

    if (values.length == 3) {
      int xValue = int(values[0]);
      int yValue = int(values[1]);
      int buttonState = int(values[2]);

      if (buttonState == 0) {
        // Move the ball to the center when the button is pressed
        circleX = width / 2;
        circleY = height / 2;
        println("Button pressed: Ball moved to center");
      } else {
        // Map joystick values (0 to 1023) to movement speed
        float mappedX = map(xValue, 0, 1023, speed, -speed);
        float mappedY = map(yValue, 0, 1023, -speed, speed);

        // Update circle position
        circleX += mappedX;
        circleY += mappedY;

        // Keep circle within screen boundaries
        circleX = constrain(circleX, 25, width - 25);
        circleY = constrain(circleY, 25, height - 25);
      }
    }
  }
}

Project 12: Galaxy Fighter Game

Using the same setup and Arduino program, let’s create a simple 2D shooter. Move the spaceship using the joystick and fire lasers with the push button.

Processing code

import processing.serial.*;  // Import the Serial library

Serial myPort;  // Serial port for joystick
float playerX, playerY;  // Player position
float playerSize = 40;   // Size of the player's aircraft
boolean isGameOver = false; // Game state flag

ArrayList<Enemy> enemies;  // List of enemies
ArrayList<Bullet> bullets; // List of enemy bullets
ArrayList<PlayerBullet> playerBullets; // List of player bullets
int spawnTimer = 0;        // Timer for spawning enemies

void setup() {
  size(600, 600);  // Game screen size
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n');

  initializeGame();  // Initialize game variables
}

void draw() {
  if (isGameOver) {
    // Show "Game Over" screen
    background(0);
    fill(255, 0, 0);
    textAlign(CENTER, CENTER);
    textSize(50);
    text("Game Over", width / 2, height / 2);
    textSize(20);
    text("Press button to restart", width / 2, height / 2 + 40);
    return;
  }

  background(0);  // Black background

  // Draw player aircraft
  fill(0, 255, 0);
  noStroke();
  triangle(playerX, playerY, playerX - 20, playerY + 40, playerX + 20, playerY + 40);

  // Update and draw enemies
  for (int i = enemies.size() - 1; i >= 0; i--) {
    Enemy e = enemies.get(i);
    e.update();
    e.show();
    if (e.isOffScreen()) {
      enemies.remove(i);  // Remove enemies that leave the screen
    }
  }

  // Update and draw enemy bullets
  for (int i = bullets.size() - 1; i >= 0; i--) {
    Bullet b = bullets.get(i);
    b.update();
    b.show();
    if (b.isOffScreen()) {
      bullets.remove(i);  // Remove bullets that leave the screen
    } else if (b.hitsPlayer(playerX, playerY, playerSize)) {
      // Trigger Game Over if bullet hits the player
      isGameOver = true;
      break;  // Exit the loop
    }
  }

  // Update and draw player bullets
  for (int i = playerBullets.size() - 1; i >= 0; i--) {
    PlayerBullet pb = playerBullets.get(i);
    pb.update();
    pb.show();
    // Check if the bullet hits any enemy
    for (int j = enemies.size() - 1; j >= 0; j--) {
      if (pb.hitsEnemy(enemies.get(j))) {
        enemies.remove(j);  // Remove the enemy
        playerBullets.remove(i);  // Remove the player bullet
        break;
      }
    }
    if (pb.isOffScreen()) {
      playerBullets.remove(i);  // Remove player bullets that leave the screen
    }
  }

  // Spawn new enemies periodically
  spawnTimer++;
  if (spawnTimer > 60) {  // Spawn every 60 frames
    enemies.add(new Enemy());
    spawnTimer = 0;
  }
}

void serialEvent(Serial myPort) {
  String data = myPort.readStringUntil('\n');
  data = trim(data);
  if (data != null) {
    String[] values = split(data, ',');
    if (values.length == 3) {  // Ensure data includes X, Y, and button state
      // Update player position based on joystick input
      float xValue = map(float(values[0]), 0, 1023, 0, width);
      float yValue = map(float(values[1]), 0, 1023, height - 100, height);
      int buttonState = int(values[2]);  // Button state (0 = pressed, 1 = released)

      if (isGameOver && buttonState == 0) {
        // Restart the game if button is pressed during Game Over
        initializeGame();
        return;
      }

      if (!isGameOver) {
        playerX = constrain(xValue, 20, width - 20);  // Keep player on-screen
        playerY = constrain(yValue, height - 100, height - 20);

        // Shoot a bullet when the button is pressed
        if (buttonState == 0) {
          playerBullets.add(new PlayerBullet(playerX, playerY));
        }
      }
    }
  }
}

// Initialize or restart the game
void initializeGame() {
  // Reset player position
  playerX = width / 2;
  playerY = height - 60;

  // Clear all enemies and bullets
  enemies = new ArrayList<Enemy>();
  bullets = new ArrayList<Bullet>();
  playerBullets = new ArrayList<PlayerBullet>();

  // Reset game state
  spawnTimer = 0;
  isGameOver = false;
}

// Enemy Class
class Enemy {
  float x, y, size;
  float speed;  // Speed of the enemy

  Enemy() {
    x = random(20, width - 20);
    y = -40;
    size = 40;
    speed = 1;  // Slower vertical speed
  }

  void update() {
    y += speed;  // Move downward
    if (frameCount % 90 == 0) {  // Shoot bullets less frequently
      bullets.add(new Bullet(x, y + size / 2));
    }
  }

  void show() {
    fill(255, 0, 0);
    rectMode(CENTER);
    rect(x, y, size, size);
  }

  boolean isOffScreen() {
    return y > height;
  }
}

// Bullet Class (Enemy Bullets)
class Bullet {
  float x, y, size;

  Bullet(float startX, float startY) {
    x = startX;
    y = startY;
    size = 10;
  }

  void update() {
    y += 5;  // Move downward
  }

  void show() {
    fill(255, 255, 0);
    ellipse(x, y, size, size);
  }

  boolean isOffScreen() {
    return y > height;
  }

  boolean hitsPlayer(float px, float py, float pSize) {
    return dist(x, y, px, py) < (size + pSize) / 2;
  }
}

// PlayerBullet Class
class PlayerBullet {
  float x, y, size;

  PlayerBullet(float startX, float startY) {
    x = startX;
    y = startY;
    size = 8;
  }

  void update() {
    y -= 7;  // Move upward
  }

  void show() {
    fill(0, 0, 255);
    ellipse(x, y, size, size);
  }

  boolean isOffScreen() {
    return y < 0;
  }

  boolean hitsEnemy(Enemy e) {
    return dist(x, y, e.x, e.y) < (size + e.size) / 2;
  }
}

10. IR Obstacle Avoidance Sensor

IR obstacle avoidance sensors use infrared light to detect obstacles without physical contact. They’re common in robotics, especially for autonomous navigation.

Project 13: Burglar Alarm

Position the sensor near doors or windows. When an intruder approaches, the sensor detects an object within a certain range and triggers an alarm.

Components Required

  • Arduino board
  • IR obstacle avoidance sensor
  • Buzzer
  • LED
  • 220-ohm resistor
  • Jumper wires

Circuit Diagram

Program

// Pin definitions
const int irSensorPin = 2;  // IR sensor output pin
const int ledPin = 8;       // LED pin
const int buzzerPin = 11;   // Buzzer pin

void setup() {
  pinMode(irSensorPin, INPUT);  // IR sensor as input
  pinMode(ledPin, OUTPUT);      // LED as output
  pinMode(buzzerPin, OUTPUT);   // Buzzer as output

  digitalWrite(ledPin, LOW);     // Ensure LED is off initially
  digitalWrite(buzzerPin, LOW);  // Ensure buzzer is off initially
  Serial.begin(9600);            // Initialize serial communication
}

void loop() {
  int irValue = digitalRead(irSensorPin);  // Read the IR sensor value

  if (irValue == LOW) {             // Object detected
    digitalWrite(ledPin, HIGH);     // Turn on LED
    digitalWrite(buzzerPin, HIGH);  // Turn on buzzer
    Serial.println("Object detected!");
  } else {
    digitalWrite(ledPin, LOW);     // Turn off LED
    digitalWrite(buzzerPin, LOW);  // Turn off buzzer
    Serial.println("No object detected.");
  }

  delay(100);  // Small delay for stability
}

Project 14: White/Black Color Detection

This simple line detection project uses the IR sensor to differentiate between a white and black surface and print the detected color name on the 0.91-inch OLED display.

Components Required

  • Arduino board
  • IR obstacle avoidance sensor(with Analog pin)
  • 0.91 inch OLED display
  • Jumper wires

Circuit Diagram

Program

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Define the dimensions of the display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32

// Initialize the display with the I2C address (usually 0x3C)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Define the pin for the IR sensor
#define IR_SENSOR_PIN A0

void setup() {
  // Start the serial communication for debugging purposes (optional)
  Serial.begin(9600);

  // Initialize the display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  
  // Clear the buffer
  display.clearDisplay();

  // Set text size and color
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);

  // Set the IR sensor pin as input
  pinMode(IR_SENSOR_PIN, INPUT);
}

void loop() {
  // Read the value from the IR sensor
  int sensorValue = analogRead(IR_SENSOR_PIN);
  
  // Clear the display buffer
  display.clearDisplay();
 Serial.println(sensorValue);
  // Check the sensor value
  if(sensorValue <= 350) {
    // When a black line is detected
    display.clearDisplay();
    display.setCursor(20, 0);
    display.print("You are ");
    display.setCursor(25, 18);
    display.print("\"BLACK\"");
  } else if(sensorValue >= 700) {
    display.clearDisplay();
    // When a white line is detected
    display.setCursor(20, 0);
    display.print("You are ");
    display.setCursor(25, 18);
    display.print("\"WHITE\"");
  }
  else {
   display.clearDisplay();
       display.setCursor(20, 0);
    display.print("Waiting ");
  }
  
  // Show the message on the display
  display.display();

  // Short delay to avoid rapid switching
  delay(100);
}

11. MPU6050 Sensor

The MPU6050 is a 6-axis motion tracking device combining a 3-axis accelerometer and a 3-axis gyroscope. It’s used in drones, game controllers, and gesture-based projects.

Project 15: Simple Accelerometer + Gyroscope Readings

Learn to read the raw accelerometer and gyroscope data. Display the readings on the OLED display. This project helps you understand the fundamentals of motion sensing.

Components Required

  • Arduino board
  • MPU6050 module
  • 0.91 inch OLED display
  • Jumper wires

Circuit Diagram

Program

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>

// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// MPU6050 object
Adafruit_MPU6050 mpu;

void setup() {
  // Initialize Serial Monitor
  Serial.begin(9600);
  Serial.println("Initializing...");

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 allocation failed");
    for (;;)
      ;
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("MPU6050 + OLED");
  display.display();
  delay(2000);

  // Initialize MPU6050
  if (!mpu.begin()) {
    Serial.println("MPU6050 initialization failed!");
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("MPU6050 Error!");
    display.display();
    while (1)
      ;
  }
  Serial.println("MPU6050 ready");
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("MPU6050 Ready");
  display.display();
  delay(1000);
}

void loop() {
  // Get accelerometer and gyroscope data
  sensors_event_t accel, gyro, temp;
  mpu.getEvent(&accel, &gyro, &temp);

  // Display accelerometer and gyroscope data on Serial Monitor
  Serial.print("Accel X: ");
  Serial.print(accel.acceleration.x);
  Serial.print(" Y: ");
  Serial.print(accel.acceleration.y);
  Serial.print(" Z: ");
  Serial.println(accel.acceleration.z);

  Serial.print("Gyro X: ");
  Serial.print(gyro.gyro.x);
  Serial.print(" Y: ");
  Serial.print(gyro.gyro.y);
  Serial.print(" Z: ");
  Serial.println(gyro.gyro.z);

  // Display accelerometer and gyroscope data on OLED
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Accel: ");
  display.print("X=");
  display.print(accel.acceleration.x);
  display.print(" Y=");
  display.print(accel.acceleration.y);
  display.print(" Z=");
  display.println(accel.acceleration.z);

  display.setCursor(0, 16);
  display.print("Gyro: ");
  display.print("X=");
  display.print(gyro.gyro.x);
  display.print(" Y=");
  display.print(gyro.gyro.y);
  display.print(" Z=");
  display.println(gyro.gyro.z);

  display.display();

  delay(500);  // Delay for stability
}

Project 16: Aircraft simulation on your Laptop window

Use the sensor data to control a simple aircraft-like object on your processing software window.

Remove the OLED connections and upload the program given below.

Arduino Program

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

// Create MPU6050 object
Adafruit_MPU6050 mpu;

void setup() {
  Serial.begin(115200);

  // Initialize MPU6050
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Initialized!");

  // Set sensor ranges
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);  // Set accelerometer range to ±8G
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);       // Set gyro range to ±500 deg/s
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);    // Set filter bandwidth to 21 Hz

  delay(100);  // Allow settings to take effect
}

void loop() {
  // Create variables for accelerometer, gyroscope, and temperature data
  sensors_event_t accel, gyro, temp;

  // Get new sensor readings
  mpu.getEvent(&accel, &gyro, &temp);

  // Calculate pitch and roll from accelerometer data
  float pitch = atan2(accel.acceleration.y, sqrt(accel.acceleration.x * accel.acceleration.x + accel.acceleration.z * accel.acceleration.z)) * 180 / PI;
  float roll = atan2(-accel.acceleration.x, accel.acceleration.z) * 180 / PI;

  // Send pitch and roll data over Serial
  Serial.print(pitch);
  Serial.print(",");
  Serial.println(roll);

  delay(50);  // Send data every 50ms
}

Processing Code

import processing.serial.*;

Serial myPort;  // Serial port for communication
float pitch = 0; // Tilt along X-axis
float roll = 0;  // Tilt along Y-axis

void setup() {
  size(800, 800, P3D);  // 3D canvas
  myPort = new Serial(this, Serial.list()[0], 115200);  // Open serial port
  myPort.bufferUntil('\n');  // Wait for full data line
}

void draw() {
  background(135, 206, 235);  // Sky blue background
  lights();       // Enable lighting

  // Center the camera and apply rotations
  translate(width / 2, height / 2, -500);  // Center plane
  rotateX(radians(-pitch));               // Rotate for pitch
  rotateZ(radians(roll));                 // Rotate for roll

  // Draw plane body
  fill(200, 0, 0);  // Red for the body
  noStroke();
  pushMatrix();
  box(150, 30, 30);  // Main body
  popMatrix();

  // Draw wings
  fill(100, 100, 255);  // Blue for the wings
  pushMatrix();
  translate(0, 0, -60);
  box(200, 5, 20);  // Left wing
  popMatrix();

  pushMatrix();
  translate(0, 0, 60);
  box(200, 5, 20);  // Right wing
  popMatrix();

  // Draw tail
  fill(200, 0, 0);
  pushMatrix();
  translate(-60, -30, 0);
  box(20, 50, 10);  // Vertical tail fin
  popMatrix();

  pushMatrix();
  translate(-60, -15, 20);
  box(40, 5, 10);  // Horizontal tail fin right
  popMatrix();

  pushMatrix();
  translate(-60, -15, -20);
  box(40, 5, 10);  // Horizontal tail fin left
  popMatrix();
}

// Read pitch and roll data from Arduino
void serialEvent(Serial myPort) {
  String data = myPort.readStringUntil('\n');  // Read serial data
  data = trim(data);  // Remove whitespace
  if (data != null) {
    String[] values = split(data, ',');
    if (values.length == 2) {
      pitch = float(values[0]);  // Parse pitch
      roll = float(values[1]);   // Parse roll
    }
  }
}

12. BME280 Sensor

The BME280 is an environmental sensor capable of measuring temperature, humidity, and barometric pressure. It’s popular in weather stations and IoT projects for accurate climate data.

Project 17: Mini Weather Station

Monitor the temperature, humidity, and pressure in your room or outdoors. Display the data on an OLED screen.

Components Required

  • Arduino board
  • BME280 sensor module
  • 0.91 inch OLED display
  • Jumper wires

Circuit Diagram

Program

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32

// Create objects for BME280 and OLED
Adafruit_BME280 bme;  // BME280 object
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Timing for data refresh
unsigned long delayTime = 2000;

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

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // 0x3C is the default I2C address
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);

  // Initialize BME280 sensor
  if (!bme.begin(0x76)) {  // 0x76 is the default I2C address for BME280
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    for (;;)
      ;
  }

  // Initial display message
  display.setCursor(0, 0);
  display.println("BME280 Sensor");
  display.println("Initializing...");
  display.display();
  delay(2000);
}

void loop() {
  // Clear the display
  display.clearDisplay();

  // Get sensor data
  float temperature = bme.readTemperature();
  float humidity = bme.readHumidity();
  float pressure = bme.readPressure() / 100.0F;  // Convert to hPa

  // Print data to Serial Monitor
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println(" °C");

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.println(" %");

  Serial.print("Pressure: ");
  Serial.print(pressure);
  Serial.println(" hPa");
  Serial.println();

  // Display data on OLED
  // display.setCursor(0, 0);
  //display.println("BME280 Sensor Data");
  display.setCursor(0, 0);
  display.print("Temp: ");
  display.print(temperature);
  display.println(" C");

  display.setCursor(0, 10);
  display.print("Humidity: ");
  display.print(humidity);
  display.println(" %");

  display.setCursor(0, 20);
  display.print("Pressure: ");
  display.print(pressure);
  display.println(" hPa");

  display.display();

  // Wait for the next update
  delay(delayTime);
}

Conclusion

By exploring these 17 Arduino projects, you’ll gain a broad understanding of how different sensors work and how they can be applied in real-world scenarios. From simple motion detection to interactive games, each project challenges you to learn new skills in electronics, coding, and problem-solving.

Photo of author

Ankit Negi

I am an electrical engineer by profession who loves to tinker with electronic devices and gadgets and have been doing so for over six years now. During this period, I have made many projects and helped thousands of students through my blog and YouTube videos. I am active on Linkedin.

Leave a Comment