Introduction to Robotics - Homework Repository Welcome to my repository for the "Introduction to Robotics" course at the University of Bucharest (2025-2026), I am Bogdan and this repository documents my progress, code, and project showcases for the homework assignments. Each assignment is organized into its own section below.
This project involves controlling the color of an RGB LED using three potentiometers. Each potentiometer adjusts the intensity of one of the three primary colors (Red, Green, and Blue), allowing for a full spectrum of mixed colors. The entire system is managed by an Arduino, which reads the analog input from the potentiometers and sends a corresponding PWM signal to the LED.
The goal of this assignment is to create a circuit and a program that allows a user to dynamically change the color of an RGB LED. This is achieved by:
Reading the analog values from three separate potentiometers using an Arduino.
Mapping these input values to the appropriate PWM (Pulse-Width Modulation) output range for the LED.
Controlling the Red, Green, and Blue channels of the LED independently, based on the potentiometer inputs.
Writing clean, well-documented, and efficient code that avoids "magic numbers" and follows best practices.
1x RGB LED
3x Potentiometers
An Arduino Uno board
3 Resistors and connecting wires
Values coming from the potentiometers must be mapped to the values that will pe given as input for the RGB LED.
A short video demonstrating the functionality of the LED controller can be viewed: (here)
**All the calculations were made considering the RGB LED's specs from the official (datasheet) **
The main goal is to design and build a traffic lights system for a pedestrian crosswalk using an Arduino Uno.
The system must follow a specific sequence of states:
-
State 1 (Idle):
- Cars: Green
- Pedestrians: Red
- Buzzer: Off
- Duration: Indefinite. The system waits for a button press to transition.
-
State 2 (Transition):
- Begins 8 seconds after a valid button press in State 1.
- Cars: Yellow
- Pedestrians: Red
- Buzzer: Off
- Duration: 3 seconds.
-
State 3 (Pedestrians Go):
- Cars: Red
- Pedestrians: Green
- Buzzer: Beeping at a slow interval.
- Duration: 8 seconds.
-
State 4 (Warning - Blink):
- Cars: Red
- Pedestrians: Blinking Green
- Buzzer: Beeping faster than in State 3.
- Duration: 4 seconds.
- The system automatically returns to State 1 after this state.
- Button Input: The button press must be handled using an interrupt. (Mandatory for CTI students). The button must only have an effect if pressed during State 1.
- 7-Segment Display: Must show a countdown of the time remaining for States 2, 3, and 4. In State 1, it can be off or display a symbol.
- Non-Blocking Code: The project must use
millis()for all timing and delays. Usingdelay()is not allowed. - Code Quality: Code must be clean, well-commented, easy to read, and use clear variable names and modular functions.
- 1 x Arduino Uno
- 5 x LEDs (3 for cars: Red, Yellow, Green; 2 for pedestrians: Red, Green)
- 1 x Push Button
- 1 x Buzzer
- 1 x 7-Segment Display
- Resistors (for LEDs and display, all LEDs use 220Ω resistors and the 7 segment display uses 4x 330Ω and 4x470Ω due to unavailability of more 330Ω resistors)
- Jumper wires
- 2 x Breadboard
- 1 x Piece of duct tape because the buzzer was way too loud
A short video demonstrating the full functionality of the traffic light system, including all states and the button interrupt can be seen here
This project involves designing and building a simple home alarm system controlled via a Serial Monitor menu. The system features two primary states (Armed/Disarmed) and is managed entirely through serial commands. When armed, it detects intrusions based on changes in distance (via an ultrasonic sensor). The system also features an automatic "night mode" arming capability using a photoresistor (LDR) to detect darkness.
The goal is to create a state-based, interactive security system using an Arduino Uno and various sensors.
- System States: The system must always be in one of two states: Armed or Disarmed.
- Serial Menu: All interaction must be handled through a clear and user-friendly menu in the Serial Monitor. The menu options must change depending on the system's state.
- If Disarmed:
Arm System: Manually arms the system (after a 3-second countdown).Alarm (Test): (Optional) Manually triggers the alarm for testing.Settings: Enters a sub-menu to configure system parameters.
- If Armed:
Disarm System: Prompts the user for a password to disarm the system.
- If Disarmed:
- Arming Logic:
- Manual: Via the "Arm System" menu option.
- Automatic: The system automatically arms itself when the LDR (photoresistor) detects darkness (light level falls below a set threshold).
- Sensor Behavior:
- Ultrasonic (HC-SR04): When the system is armed, it must record a "baseline" environment distance. It triggers an intrusion alert only when it detects a change from this baseline (e.g.,
abs(currentDistance - baselineDistance) > tolerance). - Photoresistor (LDR): Continuously measures ambient light. Its only job is to trigger the automatic arming in "night mode".
- Ultrasonic (HC-SR04): When the system is armed, it must record a "baseline" environment distance. It triggers an intrusion alert only when it detects a change from this baseline (e.g.,
- Alarm Sequence:
- When an intrusion is detected (while armed), the system waits for a 3-second delay.
- After 3 seconds, the Buzzer activates.
- The Red LED flashes repeatedly.
- The Serial Monitor displays "Intrusion detected! Enter password:".
- Entering the correct password stops the alarm and disarms the system.
- Upon disarming, the Green LED turns on, and the buzzer/red LED stop.
- Settings Sub-Menu: The
Settingsoption must allow the user to:- Set Ultrasonic Sensitivity (the "tolerance range" for movement).
- Set LDR Light Threshold (the brightness level for automatic arming).
- Set/Change Buzzer Tone or Pattern.
- Change Password (must require the current password first).
- User Feedback: The system must provide clear feedback for all actions (e.g., "System armed.", "Password incorrect!", "Threshold updated.").
- Non-Blocking Code: All delays and timeouts (e.g., the 3-second arming countdown, the 3-second alarm delay, LED flashing) must be implemented using
millis(). The use ofdelay()is not allowed in the main logic. - Modular Code: The code must be well-structured and modular, using separate functions for distinct tasks (e.g.,
checkSensors(),showMenu(),updateAlarm(),handlePassword()). - Robust Menu: The menu navigation must be robust. Invalid inputs should not crash the program and should prompt the user to try again.
- 1 x Arduino Uno
- 1 x Ultrasonic sensor (HC-SR04)
- 1 x Photoresistor (LDR)
- 1 x Buzzer
- 1 x Red LED
- 1 x Green LED
- 1 x Push Button (For Mute/Silence function)
- Resistors (220Ω for LEDs, 10kΩ for LDR, I had no 10k resistor at the moment, I used a 2k one)
- Jumper wires and a Breadboard
IMPORTANT MENTION: I am well aware that I have used the green(ish) jumper wire to power the ground pin of the mute button, I had no choice because if I wanted easy acces to that button, a normal long wire would have been in the user finger's way, I thought of ergonomics
Video demo can be seen here
This project is a "Simon Says" memory game built on a 4-digit 7-segment display. The game generates and displays a 4-character sequence, which the player must then reproduce using a joystick. The difficulty increases as the game progresses, with the sequence display time decreasing after each correct round.
The primary goal is to build a fully functional, non-blocking memory game using an Arduino, a 7-segment display, a 74HC595 shift register, and a joystick.
- Game Logic: The system displays a 4-character sequence for a set time. The player must then input the same sequence.
- Difficulty: After each correct round, the time the sequence is displayed decreases, increasing the difficulty.
- Menu System: A startup menu must be navigable with the joystick, offering three options:
PLAy: Starts a new game.SCOR: Displays the highest score achieved (resets on power loss).StOP: Cancels a running game (if paused) and returns to the idle menu.
- Pause State: An external "Pause/Menu" button, when pressed during the game, must display "PAUS" and return to the main menu. From here, the user can see the score, stop the game, or start a new one.
- Display Text: The system must be able to display specific text states, including
PLAy,PAUS,StOP,Err, andSCOR.
- Joystick Left/Right: Moves the active cursor across the 4 digits (0-3).
- Joystick Up/Down: Cycles through the available characters for the currently selected digit.
- Joystick SW (Short Press): Toggles between "Cursor Move" mode and "Digit Edit" mode.
- Joystick SW (Long Press): Submits the 4-character answer for verification.
- Pause Button (External): Pauses the game and returns to the main menu.
- Non-Blocking Code: All timing (sequence display, blinking, multiplexing, buzzer) must be implemented using
millis(). The use ofdelay()is strictly forbidden. - Display Driver: The 8 segments of the display must be controlled via a 74HC595 shift register.
- Multiplexing: All 4 digits must be controlled using non-blocking multiplexing to avoid "ghosting" and maintain a stable image.
- Buzzer Feedback: The buzzer must provide non-blocking audio feedback for cursor movement (tick), digit selection (click), correct answers (success jingle), and incorrect answers (error tone).
- 1 x Arduino Uno
- 1 x 4-Digit 7-Segment Display (Common Cathode)
- 1 x 74HC595 Shift Register
- 1 x Joystick Module (with X, Y, and SW outputs)
- 1 x Active Buzzer
- 1 x Push Button (for Pause/Menu)
- 8 x 220Ω Resistors (for segment current limiting)
- Jumper wires and a Breadboard
A video demonstration of the fully functional game can be viewed here.
This section details the hardware connections and design choices as required. IMPORTANT MENTION: THIS SCHEMA IS NOT MINE, IT HAS BEEN USED IN THE LAB STUDENTS PDF
| Component | Pin | Arduino Pin |
|---|---|---|
| 74HC595 (Register) | DATA (DS) | D12 |
| CLOCK (SHCP) | D10 |
|
| LATCH (STCP) | D11 |
|
| 7-Seg Display | Digit 1 Control | D4 |
| Digit 2 Control | D5 |
|
| Digit 3 Control | D6 |
|
| Digit 4 Control | D7 |
|
| Joystick | X-Axis | A0 |
| Y-Axis | A1 |
|
| Switch (SW) | D2 |
|
| Controls | Pause Button | D3 |
| Buzzer (+) | D9 |
The 4-digit 7-segment display used in this project is Common Cathode (CC).
- The 8 segment pins (A-G, DP) are connected to the 74HC595 outputs (via resistors).
- The 4 common cathode "digit select" pins are connected to Arduino pins
D4-D7. - A digit is activated by setting its corresponding control pin to
LOW.
To meet the requirements, a character set of 16 characters was implemented. The FONT_MAP array in the code contains the bitmasks (0b(DP)GFEDCBA) for each character. LSBFIRST bit order is used when sending data with shiftOut().
- Character Set Used:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, P, L, S, E, - - Special Characters:
PLAyis rendered usingP,L,A, and4.StOPis rendered usingS,7(for 't'),0(for 'O'), andP.SCORis rendered usingS,C,0(for 'O'), andr(not implemented, used '0').Erris rendered usingE,r,r(not implemented, usedErr).
As per the requirements, two distinct blinking patterns are used to indicate the system state:
- Slow Blink (1 Hz / 500ms): Used in the Menu and in "Cursor Move" mode to indicate the currently active digit (cursor position).
- Fast Blink (4 Hz / 125ms): Used in "Digit Edit" mode to indicate that the selected digit is "unlocked" and its value can be changed with Up/Down controls.
This project is a recreation of the famous "Chrome Dino" game, adapted for a 16x2 LCD display using an Arduino. The project focuses heavily on Clean Architecture principles, separating the game logic (Model), the rendering logic (View), and the user input (Controller). The game is an endless runner where the player must jump over cactuses and collect birds to achieve the highest score.
The main goal was to build a game on the LCD that runs smoothly using millis() for timing and adheres to strict software architecture rules.
- Game Type: Option C - Endless Runner.
- Architecture: strict Separation of Concerns (SoC). The Game Logic must not know about the LCD, and the Renderer must not know about the game rules.
- Gameplay:
- Gravity & Jumping: The player (Dino) runs on the bottom row and can jump to the top row to avoid obstacles.
- Obstacles: Cacti appear on the ground (Game Over if touched).
- Collectibles: Birds appear in the air (Bonus points if collected).
- Speed: The game progressively gets faster as the score increases.
- Menu System:
- Start Game.
- High Score (saved in EEPROM, retains top 3 scores even after power loss).
- Pause Mode (Bonus).
- Visuals: Use of Custom Characters (Glyphs) for the Dino, Cactus, and Bird.
- Timing: Use
millis()exclusively. Nodelay()allowed. - Rendering Optimization: Implement Differential Rendering (draw only changed pixels) to prevent LCD "ghosting" and flickering.
- Input Buffering: Implement an input buffer to capture jump commands even between frame updates for responsive controls.
- 1 x Arduino Uno
- 1 x LCD Display (16x2) with Header Pins
- 1 x Joystick Module
- 1 x Active/Passive Buzzer
- 1 x Potentiometer (for LCD Contrast)
- 1 x Breadboard & Jumper Wires
A video demonstration of the Dino game, showing the clean architecture in action, the menu system, and the ghosting-free rendering can be viewed here.
| Component | Pin Function | Arduino Pin |
|---|---|---|
| LCD 16x2 | RS | D7 |
| Enable (EN) | D6 |
|
| D4 | D5 |
|
| D5 | D4 |
|
| D6 | D3 |
|
| D7 | D2 |
|
| Joystick | VRx (Vertical/Jump) | A1 |
| VRy (Horizontal) | A0 |
|
| SW (Select/Pause) | D9 |
|
| Audio | Buzzer (+) | D8 |
This project uses a modular approach to ensure the code is maintainable and scalable.
IGameRenderer(Interface): An abstract class defining the contract for drawing. This allows swapping the LCD for a Serial monitor or another display without changing the game logic.GameModel(The Logic): Handles the "World". It manages the grid mapchar grid[2][16], collision detection, score calculation, and physics (gravity). It has zero dependencies on the Arduino LCD library.LCDRenderer(The View): ImplementsIGameRenderer. It handles the hardware specifics of the LiquidCrystal library.- Optimization: It uses a
lastGrid[2][16]buffer to compare the current frame with the previous one. It only sendslcd.write()commands for characters that have changed, eliminating the flicker effect common in LCD games.
- Optimization: It uses a
GameController(The Glue): Reads the Joystick inputs and bridges the Model and the Renderer. It handles the "Game Loop", Input Buffering (to fix input lag), and state transitions (Menu -> Game -> Pause -> GameOver).
The system moves between 4 main states managed by an enum:
STATE_MENU: Shows "Start" and "High Scores".STATE_PLAYING: The active game loop. Handles physics and scrolling.STATE_PAUSED: Freezes the game loop but keeps the render active.STATE_GAMEOVER: Displays final score and saves it to EEPROM if it's in the top 3.STATE_HIGHSCORES: Reads and displays the top 3 runs from memory.
The HD44780 LCD controller allows for up to 8 custom characters. I utilized 4 slots:
ID 0: Dino RunID 1: Cactus (Obstacle)ID 2: Bird (Collectible)ID 3: Dino Jump (Visual variation when in the air)















