Table of Contents
- About The Project
- Repository Structure
- Hardware Setup
- 1. RFID Reader
- 2. Stepper Motor
- 3. Display - Crystalfontz 128x128 TFT LCD (BOOSTXL-EDUMKII Onboard)
- 4. Input Peripherals: Buttons & Joystick (BOOSTXL-EDUMKII Onboard)
- 5. Piezo Buzzer (BOOSTXL-EDUMKII Onboard)
- 6. VL53L0X - Distance Sensor
- 7. ESP32-S3 UART Communication
- Project wiring
- Software Setup
- User Guide
- Authors
Welcome to the Home Access Control System!
This project implements a smart door access control system that combines local hardware interaction with IoT remote management. Users can authenticate using unlock codes, while the administrator can access a dedicated secure menu using an RFID tag. Beyond the physical interface, an integrated Telegram bot handles remote interactions, enabling the administrator to oversee access permissions and allowing users to request or manage their own codes. The system also features a database that logs all access events for monitoring purposes.
.
├── 3D-Model/ # Hardware 3D printable components
│ ├── All components.3mf # All components in 1 file
│ ├── door.stl # Door model
│ ├── doorframe.3mf # Door frame model
│ ├── gear.stl # Gear mechanism model
│ ├── sensors_and_peripherals_supports.scad # OpenSCAD parametric supports
│ └── sensors_and_peripherals_supports.stl # Exported supports model
├── RepoImages/ # Documentation media and images
│ ├── HardwareSetup/ # Schematic diagram
│ ├── SoftwareSetup/ # Software Setup screenshots
│ │ ├── CCStudio/ # CCStudio IDE
│ │ ├── FSM/ # FSM diagram
│ │ └── VSCode+PlatformIO/ # VSCode and PlatformIO IDE
│ └── TelegramBot/ # Bot usage demonstrations (GIFs & Images)
├── ShortStaysAccessControlSystem/ # Firmware project (MSP432 Microcontroller)
│ ├── msp432p401r.cmd # Memory linker script
│ ├── src/ # Source code directory
│ │ ├── external_src/ # External hardware libraries
│ │ │ ├── LCD/ # Display graphics library
│ │ │ │ ├── Crystalfontz128x128_ST7735.c / .h # ST7735 controller primitives
│ │ │ │ └── HAL_MSP_EXP432P401R_Crystalfontz128x128_ST7735.c / .h # Display pin mapping
│ │ │ └── vl53l0x_msp432/ # Distance sensor submodule (Git)
│ │ │ ├── drivers/ # Sensor native API registers
│ │ │ │ ├── config.h # Timing configuration
│ │ │ │ ├── i2c.c / .h # I2C driver
│ │ │ │ ├── macro.h # Internal macros
│ │ │ │ └── vl53l0x.c / .h # Main ranging core
│ │ │ ├── main.c # Sensor standalone test
│ │ │ └── README.md # Submodule info
│ │ ├── buzzer.c / .h # Buzzer acoustic alerts
│ │ ├── comm_esp.c / .h # Serial communication with ESP32
│ │ ├── database.c / .h # Local access credentials memory
│ │ ├── display.c / .h # LCD high-level UI menus
│ │ ├── flash.c / .h # Flash memory storage driver
│ │ ├── fsm_helpers.c / .h # State machine utilities
│ │ ├── fsm.c / .h # Main application logic (FSM)
│ │ ├── irqHandlers.c / .h # Hardware interrupt routines
│ │ ├── joystick.c / .h # Analog joystick driver
│ │ ├── main.c # System entry point & loop
│ │ ├── motor.c / .h # Motor control driver
│ │ ├── push_button.c / .h # Buttons and debouncing
│ │ ├── sensors.c / .h # RFID and Distance sensor drivers
│ │ └── timers.c / .h # Periodic timer configurations
│ ├── startup_msp432p401r_ccs.c # Microcontroller vector table
│ ├── system_msp432p401r.c # System clock configuration
│ └── targetConfigs/ # IDE target configurations
│ ├── MSP432P401R.ccxml # Target configuration file
│ └── readme.txt # Target config info
├── TelegramBot/ # PlatformIO project (ESP32 Microcontroller)
│ ├── include/ # Global header files
│ │ ├── credential-template.h # Wi-Fi and Token template
│ │ └── README.md # Folder info
│ ├── lib/ # Custom local libraries
│ │ ├── DoorBotManager/ # Telegram connection & events logic
│ │ │ ├── DoorBotManager.cpp # Bot API implementation
│ │ │ └── DoorBotManager.h # Bot class definition
│ │ └── README.md # Lib folder info
│ ├── platformio.ini # Build and dependency settings
│ ├── src/ # Application source code
│ │ ├── idf_component.yml # ESP-IDF component packages
│ │ └── main.cpp # Main bot loop & Wi-Fi init
│ └── test/ # Unit testing folder
│ └── README.md # Test folder info
├── HomeAccessControlSystem-Presentation.pdf # Project presentation
└── README.md # Project documentation
To securely isolate local hardware operations from network tasks, the system architecture is divided between two interconnected microcontrollers:
Texas Instruments MSP432P401R: The core of the system, interfaced with the Educational BoosterPack MKII (BOOSTXL-EDUMKII). It handles several external and onboard sensors and actuators to manage physical access control and user interaction.
Espressif ESP32-S3: Operating as a dedicated network coprocessor, it connects to the MSP to handle all Wi-Fi connectivity, system time synchronization, and the Telegram Bot logic.
Below is the technical breakdown of each hardware module integrated into the system, including their designated communication protocols, pin mapping, and core logic.
Handles secure tag scanning and authentication, granting administrator-level access to the local configuration menu.
- Communication Protocol:
SPI - Hardware Connections:
SDA / CS: Pin[5.2]SCK: Pin[3.5]MOSI: Pin[3.6]MISO: Pin[3.7]RST: Pin[3.0]
ConfigureSPIpins (SCK, MOSI, MISO, CS, RST) asperipheralsSetCShigh (idle)
PullRSTlowfor1ms, thenhigh (hardreset)
SetSPImaster: 4MHz, mode0, MSBfirstKeepSPImoduledisabled (RFID_ready= false)ifnotRFID_ready:
RFID_Init()
EnableSPImoduleSetRSThigh, delay50msforbootupSoftresetMFRC522Verifyversion (0x37) ==0x91or0x92, ifinvalid: return false
ConfiguretheonboardtimerSetRxGainEnabletheantenna: setbit0andbit1ofTxControlReg (0x14)
RFID_ready= true return trueSetCShighDisableSPImoduleSetRSThigh (inactive)
Restorepinsasinputswithpull‑ups (sharedwiththeA_button)
Re‑initialisedisplayandbuttonsRFID_ready= falseREQArequest, ifresponselength<2bytes: return false
Anticollisioncommand-multiplecardscouldbepresentatthesametime. Ifresponselength<5bytes: return false
Checksumcheck, ifitfailsreturn false
returntheUIDUsed for standard admin access (in wait_RFID or block_RFID)
ifnotRFID_Enable() show"ERROR"andreturnfalsewhiletrue:
ifbuttonA_pressed: RFID_Disable(); return false // cancel (for wait_RFID only)ifRFID_ReadTag(uid, &len) succeeded:
ifthetagisvalidandcorrect:
show"VALID RFID"andplaythecorrectsoundreturntrueelse:
RFID_Disable()
show"WRONG RFID", playwrongsoundreturn false
else:
delay_ms(50) // no tag, keep polling after a short delayError checks and resilience: The RFID driver includes exhaustive checks for every SPI transaction (timeouts, protocol errors, collisions, CRC mismatches, and FIFO emptiness) and validates the UID checksum before accepting a read. If a critical error occurs (e.g., version mismatch after soft reset), it automatically re‑initialises the module; otherwise, it safely disables the SPI interface and restores pin functions, preventing hangs or bus conflicts.
Actuates the physical locking and unlocking mechanism of the door via precise rotational control.
- Communication Protocol:
ULN2003 driver - Hardware Connections:
IN1: Pin[2.5]IN2: Pin[6.6]IN3: Pin[6.7]IN4: Pin[2.3]
- Angle-based Control: Converts a given angle into the number of steps required by the 28BYJ-48 Stepper Motor.
- Safe locking/unlocking Mechanism: Saving in Flash memory a dedicated flag, ensures protection against two straight opening (or closing) cycles which can damage door mechanism. Pretty useful in case of power failure.
- Full-Step Drive: Supplying power to two coils simultaneously, the Motor gives the maximum available torque and holding force. This ensures reliability when opening/closing the door.
- External Power Supply: To avoid over-heating and self-reset procedure on the MSP-board due to over-current demanding, the Motor Driver is feed with an external 5V Power Source.
moveMotor(intangle): //This function converts the given angle into the number of steps required and manages motor movementcalculatenumberofstepsrequiredtoturnmotoronthegivenangleifthenumberofstepsisnegative:
MotorneedstoruncounterClockwiseelse:
MotorrunsclockwisecalculateindexfortheFor-cycle, dependinginwhichdirectionMotorshouldrunforeachstepMotorwillmake:
foreachpin:
iftheassociatedcoilshouldgohigh:
Setpinhighelse:
Setpinlowwaitbeforethenextstepbeforereturningfromthefunction, setallpinslowThe Crystalfontz CFAF128128B-0145T color 128x128-pixel TFT LCD renders the local Graphical User Interface (GUI), to display the keypad interface and the admin menu.
- Communication Protocol:
SPI - Hardware Connections:
LCD_SCLK: PinP1.5LCD_MOSI: PinP1.6LCD_CS: PinP5.0LCD_RST: PinP5.7LCD_BACKLIGHT: PinP3.7
- Numeric PIN Grid: Renders a 3x4 interactive keypad interface for standard user authentication.
- Administrator Menu: A scrollable, paginated menu allowing authorized admins to view the last access log and manually lock and unlock the door and clear the database.
- Dynamic Joystick Navigation: Translates raw X/Y analog inputs from the joystick to move a red selection rectangle (
Rectanglestruct) across the screen, supporting both grid-based navigation and vertical menu scrolling. - Interactive Selection & Feedback: Evaluates the position of the selection rectangle against a predefined array of coordinates (e.g.,
GRID_POINTS). When a user confirms a selection, the system executes a temporary visual flash (red-to-white fill) over the selected item to provide immediate confirmation feedback. - System Status Prompts: Delivers instant, color-coded visual alerts for real-time events (e.g.,
display_door_open(),display_wrong_pin(),display_block_access()).
// Initialize the graphics context, display orientation, and default fontsgraphicsInit():
initializeLCDhardwaresetcolors, fontandorientationUP// Routes joystick input to update the UI based on the active screen statemove_rectangle_on_display(x, y, grid_on):
ifgrid_on:
calculateboundsandshiftselectionboxacrossnumerickeypadelse:
handleverticalscrolling, pagination, andhighlightinginAdminMenu// Detects selected grid point and triggers visual feedbacknumber_selected():
foreachpointinGRID_POINTS:
ifthepointisinsidetheselectionrectangle:
triggervisualflashfeedbackreturnpoint_indexreturn-1// no number selectedCaptures analog and digital user inputs for menu navigation, selection, and system interaction.
- Communication Protocol:
GPIO(Digital Input with Interrupts) &ADC(Analog-to-Digital Converter) - Hardware Connections:
Button 1: PinP5.1Button 2: PinP3.5Joystick X-Axis: PinP6.0Joystick Y-Axis: PinP4.4
- Interrupt-Driven Architecture: Utilizes hardware interrupts for both the ADC (joystick) and GPIO (buttons) to capture inputs asynchronously. This prevents the system from blocking the main execution loop while waiting for user interaction.
- Pull-Up Configuration: Pushbuttons are configured with internal pull-up resistors, meaning they trigger on a high-to-low voltage transition (active-low) when pressed.
- Timer-Based Software Debouncing: To prevent mechanical switch bounce from registering as multiple rapid presses, the system temporarily disables the button interrupt and triggers a hardware timer. The input state is only validated after the timer expires.
ADC_interrupt():
ifconversion_finished:
joystick_X=read_ADC(X_channel)
joystick_Y=read_ADC(Y_channel)
setmove_rectangle_flag// trigger UI updaterestartjoystick_timerGPIO_button_interrupt():
ifbutton1_triggered:
initiate_debounce_sequence()
returninitiate_debounce_sequence():
disablebuttoninterrupts// ignore mechanical switch bouncestartdebounce_timer// wait for signal to stabilizedebounce_timer_interrupt():
stopdebounce_timerifbutton1isstillpressed:
setbutton1_pressed_flagresetUI_timeout_timerifbutton2isstillpressed:
setbutton2_pressed_flagresetUI_timeout_timerre-enablebuttoninterrupts// ready for next pressGenerates acoustic feedback for successful actions (correct PIN, valid RFID), wrong attempts, and system lockout. Comes with a configurable VOLUME
- Communication Protocol:
PWM(Pulse Width Modulation) - Hardware Connections:
Signal: PinP2.7(Timer_A0 capture/compare output 4)
StopTimer_A0DisablethetimerinterruptsandclearanypendinginterruptflagConfigureP2.7asperipheraloutput (primarymodulefunction)Timer_A_PWMConfig {
clockSource: SMCLKclockDivider: 16timerPeriod: calculatedasafunctionofthenotescompareRegister: 4outputMode: RESET_SETdutyCycle: calculatedasafunctionofthenotes
}Foreachnoteinthesong:
ifvolume!=0andfreq!=0:
timerPeriod= ((SMCLKfrequency) / (freq × 16)) & (0xFFFF) // clamped to 16‑bit]dutyCycle= (timerPeriod × volume) >> 10ConfigureandstartPWMwiththisperiod/dutydelayforthenote.durationdutyCycle=0 → stopPWMdelay_ms(1) // short silence between noteselse:
Stoptimer (nosound)All sequences are blocking (delay-based) and play to completion before returning control to the caller.
| Sound |
|---|
CorrectPin |
WrongPin |
LockOut |
CorrectRFID |
Detects user proximity to wake the system from low‑power mode, configured to trigger an interrupt when a target is closer than 300 mm (src/external_src/vl53l0x_msp432/drivers/config.h).
- Communication Protocol:
I²C - Hardware Connections:
SCL: PinP6.5SDA: PinP6.4XSHUT: PinP4.1(hardware reset / power enable)INTERRUPT: PinP4.6(active‑low)
ConfigureXSHUTasoutput, pulllow (sensorinreset)
InitialiseI²Cmaster (EUSCI_B1, speed: 400kHz, clksource: SMCLK)
Configureinterruptpinasinputwithpull‑up, edge‑triggered (fallingedge)ReleaseXSHUT (high) andwaitforsensorbootvl53l0x_init():
-I²Cslaveaddresssettodefaultaddress (0x29)
-loadSPADconfigurationfromNVM-Loaddefaulttuningsettings-Setsignalratelimit (0.25MCPS) andtimingbudget (33ms) foraveragelightconditions-RunVHVandphasecalibrationsCallvl53l0x_start_continuous(): armscontinuousback‑to‑backrangingClearanypendinginterruptonsensorEnableGPIOinterruptonP4.6ToF_ready= trueDisableGPIOinterruptonP4.6Callvl53l0x_stop_continuous() haltstherangingengineandclearsinterruptregisterPullXSHUTlow (sensorinhardwarestandby)
ToF_ready= false
ToF_flag=0DisablefurtherinterruptsonP4.6ClearinterruptflagonGPIOIfToF_ready: setToF_flag=1Systemin `STATE_AOD` withsensorenabledUserapproaches, sensorcrosses300mmthresholdandINTpinasserts
`ToF_flag` setso `check_for_inputs()` evaluatestheToFreadingvia `vl53l0x_read_range_interrupt()`
Ifrange ≤ low_threshold&&theerrorcodeisvalid:
disablethesensorandwakesystemto `STATE_INSERT_PIN`
else:
reactivatetheinterruptforToFandgotosleepThe VL53L0X driver implements automatic init retries (up to 2 attempts) if initialisation or continuous ranging start fails. Every I2C transaction includes NACK detection and timeout checks to prevent hanging or corrupted configuration in registers I/O operations.
An UART serial communication interface was configured to enable data exchange and command execution between the two microcontrollers.
Communication Protocol:
UARTHardware Connections:
- Texas Instruments MSP432P401R:
- TX: Pin
P3.3 - RX: Pin
P3.2
- TX: Pin
- Espressif ESP32-S3:
- TX: Pin
P17 - RX: Pin
P16
- TX: Pin
- Texas Instruments MSP432P401R:
Message Handling & Dispatching: Uses hardware interrupts (
EUSCIA2_IRQHandler) to asynchronously buffer incoming messages and routes them to specific handlers based on predefined prefixes (processUartMessage).PIN Management: Manages access by generating unique 4-digit PINs (
handleGenTempPin), verifying user inputs against stored credentials (handleVerifyPin), and processing early revocation requests (handleRevokePin).Time Synchronization: Requests network time (
requestRealTime) and parses the ESP32 payload to accurately configure the hardware Real-Time Clock (handleTimeSync).
- First, clone the repository with git
git clone <repository-url>cd<repository-folder>
git submodule init && git submodule update --remote- Then download CCStudio v12.8 and SimpleLink MSP432 SDK v3.40.01.02
⚠️ Important: The SimpleLink SDK must be placed in the parent directory of the repository (i.e., the folder that will contain the cloned repo). For example, if you pln to clone into~/my_project, the SDK should be extracted to~/(so the SDK folder sits alongsidemy_project, not inside it).
Now you can import the project in CCStudio:
- Launch CCStudio v12.8
- When prompted for a workspace, select the repository folder (the one you just cloned)
- Go to Project → Import Project (or File → Import → CCS Projects)
- Click Browse… and select the repository folder
- Under Discovered Projects, check the project you want to import
- Click Finish
The MSP432 program can be now uploaded to the board.
- Download and install Telegram on your device. We recommend using the Telegram Desktop application on your PC for a more comfortable setup experience.
Open this link @BotFather to launch the official bot creation tool in Telegram, then start the conversation by sending the command
/start. - Send the command
/newbotto create a new bot. - Follow @BotFather's instructions to configure your bot:
- First, choose a name for your bot (this is the display name users will see).
- Then, choose a unique username (it must end with
bot, e.g.,HomeAccess_bot).
- Once the bot is created, BotFather will send you a confirmation message containing your HTTP API Token. Copy and save this token securely, as you will need to insert it into the project file for the ESP firmware, as explained in the following section.
- To configure the bot's menu, send the command
/setcommandsto @BotFather. - Select your newly created bot from the provided list, then copy and paste the following text into the chat to set up your commands:
start - Initialize the bot and authenticate yourself
menu - Display the main control panel and available features
cancel - Abort the current operation or transaction
- Download and install Visual Studio Code.
- Install the PlatformIO IDE Extension from the VSCode extensions marketplace.
- Click the PlatformIO icon on the left sidebar. You will see the screen shown in the image below. Click the Pick a folder button. Navigate to the location where you cloned the
HomeAccessControlSystemrepository and select theTelegramBotfolder inside it to open the project.
Open the configuration file located at
TelegramBot/include/credential-template.hstarting from the root of the repository.Insert your Wi-Fi credentials and the Telegram Bot token you saved earlier by replacing the placeholder text inside the quotes "":
Copy and rename the file from
credential-template.htocredential.h. This ensures your sensitive credentials are not accidentally uploaded to GitHub if you push your changes, ascredential.his already included in theTelegramBotproject's.gitignorefile.Connect a microUSB cable to the UART port on your ESP32-S3 board. Go to the top right corner where the Build icon (the checkmark) is located, click the down arrow symbol next to it, and select Upload to compile the code and upload the firmware.
Note: The first time you perform this action, it will take some time. PlatformIO works in the background to automatically download all the necessary libraries and the updated Arduino core directly from the official Espressif repository.
This section explains how to interact with the system through its physical display and the Telegram bot.
Click here to watch:
The physical interface features an TFT LCD screen controlled by the onboard joystick and push buttons. The first image shows the numeric keypad, where users navigate to enter their 4-digit access PIN. The second image displays the Admin Menu, accessible exclusively with his PIN and RFID tag.
When logged as Admin, the system allows you to see and to navigate through an interactive “Log Database”, which stores in permanent memory (Flash) the last 10 autentication data remembering the moment of the access, the used PIN and if it has been recognised as the Admin one, as one of the Users or none.
Interactive Navigation: Using the on-board joystick, the Admin can browse the different Database pages containing all log data.
Quick Save: During initialization instructions, info stored in Flash memory are copied in a RAM instance to be modified and to be shown. When a new log event is added, the systems quickly upload these modifications in the permanent memory ensuring any data lost due to power faults.
Blocked User Access: The Home Access Control System checks when User access is denied multiple times, blocking it when a maximum number of tries is exceeded, until the Admin uses his RFID tag. To prevent an intruder from bypassing this check, a Boolean flag is stored in Flash memory with Database data so the system can remember, in case it’s turned off, that the Admin action is required to proceed with normal activities.
First of all, search for your bot in Telegram using the @username you assigned to it during the BotFather setup (refer to the previous Software setup section).
Now, you can initiate the conversation by pressing the Start button at the bottom of the chat or by typing the
/startcommand. You will receive a prompt asking you to authenticate as either an Admin or a User.If you choose to log in as an Admin, the bot will ask for an unlock code. Currently, this code is hardcoded as
9999.Once authenticated, the main command dashboard will appear. You can always bring up this dashboard again at any time by sending the
/menucommand (this applies to both Admin and Users).
Admin Features When logged in as an Admin, your dashboard will include the following functions:
Pin Duration: Set the validity time limit for the temporary pins granted to Users.
Remove User: Remove a specific User entirely from the system.
Revoke all PINS: Revoke all currently active unlock pins for all users in the system.
Beyond the dashboard, the main Admin's feature is receiving direct notifications to either approve or deny user pin requests.
User Features When logged in as a User, your dashboard adapts based on your current access status:
Request Temporary Pin: After the authentication, this is the only available action. Use it to send an access pin request to the Admin.
Temporary Pin Duration: Once the Admin grants you a pin, use this button to check how much validity time is left before it expires.
Revoke Temporary Pin: If you no longer need access, use this to manually revoke your own active pin early.
Pietro Baroni:
- MSP432 FSM structure
- Display API and menus
- Joystick ADC
- Push buttons
Michele Martini:
- Telegram bot
- ESP32 FSM
- UART Communication
Michele Casagrande:
- Flash I/O operations
- Database API
- Stepper motor integration
Alessandro Biasioli:
- RFID setup, logic and communication
- ToF Sensor bare-metal driver and logic
- Buzzer
- MCU sleep and AoD logic













