We do not engage in one-time transactions; we aim to be long-term partners in technical growth!
01
—
Physical Video Demonstration
See the end of the article for data sharing
02
—
Project Overview
Title: Microcontroller-Based Library Seat Monitoring System
Main Control: STM32
Display: OLED Display
DS1302 Clock Module
Infrared Photoelectric
Infrared Temperature Measurement Module
Bluetooth Module
Red LED + Yellow LED
Sound and Light Alarm: LED + Buzzer
Functionality:
1. The photoelectric sensor detects whether an item is present in the seat, while the infrared temperature sensor identifies whether it is a human or another object.
2. If an object occupies the seat, the buzzer will sound an alarm to indicate that the seat should not be occupied.
3. If a person is present, the system operates normally. If a person uses the seat for an extended period, the yellow light will illuminate for one minute to remind them to take a break. If a person leaves the seat for an extended period, the red light will illuminate, prompting staff to clean the seat.
4. The display shows the current seat number and data information.

03
—
Schematic Design

04
—
PCB Hardware Design


05
—
Program Design
#include "stm32f10x.h" // Include device header file
#include "delay.h" // Include delay library
#include "lcd.h" // Include LCD display library
#include "ds1302.h" // Include DS1302 clock library
#include "IOput.h" // Include input output library
#include "usart.h" // Include USART library
// Define global variables
u8 show_flag, BEEP_flag, on_flag, count;
u8 flag_lightel = 0,flag_wd = 0;
float MAX_WD=37.5,wd;
u8 flag_peo = 0;
u8 flag_real_peo = 0;
u8 flag_wuti = 0;
u8 timeM = 0;
u8 timeS = 0;
// Buzzer control function
void beep1(){
BEEP = 0; // Turn on the buzzer
// Delay for 8 seconds, simulating the buzzer sounding for 8 seconds
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
BEEP = 1; // Turn off the buzzer
// Delay for 8 seconds, simulating the buzzer stopping for 8 seconds
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
Delay_1ms(1000);
}
// Display time function
void showtime(void){
OLED_ShowCH(0,0,"Number:");
OLED_ShowNum(40,0,12,2,16);
if(flag_peo&&!flag_lightel )
{
OLED_ShowCH(64,0,"Occupied");
flag_real_peo = 1;
BEEP = 1;
}
else if(!flag_lightel)
{
OLED_ShowCH(64,0,"Object");
flag_real_peo = 0;
flag_wuti = 1;
BEEP = 0;
}
else
{
OLED_ShowCH(64,0,"Vacant");
flag_real_peo = 0;
flag_wuti = 0;
BEEP = 1;
}
OLED_ShowCH(0, 2, "Status:"); // Display alarm indicator
ds1032_read_realTime(); // Read current time
// Display year, month, date, hour, minute, and second
OLED_ShowNum(0, 4, TimeData.year, 4, 16);
OLED_ShowString(35, 4, "/", 16);
OLED_ShowNum(43, 4, TimeData.month, 2, 16);
OLED_ShowString(60, 4, "/", 16);
OLED_ShowNum(70, 4, TimeData.day, 2, 16);
OLED_ShowNum(0, 6, TimeData.hour, 2, 16);
OLED_ShowString(20, 6, ":", 16);
OLED_ShowNum(30, 6, TimeData.minute, 2, 16);
OLED_ShowString(50, 6, ":", 16);
OLED_ShowNum(60, 6, TimeData.second, 2, 16);
}
// Function to display and modify time
void show_change_time(void){
OLED_ShowString(0, 4, "20", 16);
OLED_ShowNum(16, 4, lssj.year, 2, 16);
OLED_ShowString(35, 4, "/", 16);
OLED_ShowNum(43, 4, lssj.month, 2, 16);
OLED_ShowString(60, 4, "/", 16);
OLED_ShowNum(70, 4, lssj.day, 2, 16);
OLED_ShowNum(0, 6, lssj.hour, 2, 16);
OLED_ShowString(20, 6, ":", 16);
OLED_ShowNum(30, 6, lssj.minute, 2, 16);
OLED_ShowString(50, 6, ":", 16);
OLED_ShowNum(60, 6, lssj.second, 2, 16);
Delay_50ms(2); // Delay
}
// Timer function to check if the set alarm time is reached
void DINGSHI(u8 minute_flag,u8 flag_led){
if(TimeData.minute == minute_flag && TimeData.second < 30)
{
BEEP_flag = 1;
}
if(BEEP_flag == 1)
{
if(flag_led)
{
OLED_ShowCH(40,2,"Time to rest");
YELLOW = 1;
}
else
{
RED = 1;
OLED_ShowCH(40,2,"Time to clean");
}
if(TimeData.second > 30)
{
RED = 0;
YELLOW = 0;
on_flag = 0;
BEEP_flag = 0;
}
}}
void check_people(void){
u8 WENDU_H,WENDU_L;
// OLED_ShowCH(0,0," Infrared Thermometer ");
// OLED_ShowCH(0,2,"Temperature Threshold:");
// OLED_ShowCH(0,4,"Current Temperature:");
// OLED_Showdecimal(72,2,MAX_WD,2,1,16);
if(USART_RX_STA&0X8000)// Data received once
{
WENDU_H=USART_RX_BUF[2];
WENDU_L=USART_RX_BUF[3]/10;
WENDU_H=WENDU_H&0X00FF;
if(WENDU_H>=55)
{
WENDU_H=0;
WENDU_L=0;
wd = (float)WENDU_H+(float)WENDU_L;
UsartPrintf(USART1,"Number:%d\r\n",12);
if(flag_real_peo)
{
UsartPrintf(USART1,"Occupied\r\n");
}
else if(flag_wuti)
{
UsartPrintf(USART1,"Object present\r\n");
}
else
{
UsartPrintf(USART1,"Vacant\r\n");
}
UsartPrintf(USART1,"\r\n\r\n");
OLED_ShowNum(104,0,wd,2,16);
if(wd>1 &&& wd < 39.5)
{
flag_peo = 1;
}
else
{
flag_peo = 0;
}
USART_RX_STA=0;// Start next reception
}
else
{
wd = (float)WENDU_H+(float)WENDU_L;
UsartPrintf(USART1,"Number:%d\r\n",12);
if(flag_real_peo)
{
UsartPrintf(USART1,"Occupied\r\n");
}
else if(flag_wuti)
{
UsartPrintf(USART1,"Object present\r\n");
}
else
{
UsartPrintf(USART1,"Vacant\r\n");
}
UsartPrintf(USART1,"\r\n\r\n");
OLED_ShowNum(104,0,wd,2,16);
if(wd>1 &&& wd < 39.5)
{
flag_peo = 1;
}
else
{
flag_peo = 0;
}
USART_RX_STA=0;// Start next reception
}
}
delay_ms(200); // Send temperature measurement command 0XFA 0XCA 0XC4
USART2_SendData(0XFA);
USART2_SendData(0XCA);
USART2_SendData(0XC4);
}
// Main function
int main(void){
delay_init(); // Initialize delay
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Configure priority group
OLED_Init(); // Initialize OLED
delay_ms(1);
OLED_Clear(); // Clear screen
ds1302_gpio_init(); // Initialize DS1302
input_init(); // Initialize input
output_init(); // Initialize output
Usart1_Init(9600);
Usart2_Init(9600);
// Send temperature mode command 0XFA 0XC5 0XBF
USART_SendData(USART2,0XFA);
USART_SendData(USART2,0XC5);
USART_SendData(USART2,0XBF);
delay_ms(50);
while(1)
{
check_people();
flag_lightel= GD;
key_scan();
if(key1_flag == 1)
{
key1_flag = 0;
show_flag++;
if(show_flag == 7)
{
show_flag = 0;
lssj.month = (lssj.month) / 10 * 16 + (lssj.month) % 10;
lssj.day = (lssj.day) / 10 * 16 + (lssj.day) % 10;
lssj.hour = (lssj.hour) / 10 * 16 + (lssj.hour) % 10;
lssj.minute = (lssj.minute) / 10 * 16 + (lssj.minute) % 10;
lssj.second = (lssj.second) / 10 * 16 + (lssj.second) % 10;
lssj.year = lssj.year;
ds1032_init(); // Initialize DS1032
}
}
if(show_flag == 0)
{
showtime(); // Display time
lssj.year = TimeData.year - 2000;
lssj.month = TimeData.month;
lssj.day = TimeData.day;
lssj.hour = TimeData.hour;
lssj.minute = TimeData.minute;
lssj.second = TimeData.second;
lssj.week = TimeData.week;
if(flag_real_peo == 1)
{
OLED_ShowCH(40,2,"Position occupied");
// flag_real_peo = 0;
on_flag++;
if(on_flag == 1)
{
timeM = TimeData.minute;
timeS = TimeData.second;
}
}
else
{
on_flag = 0;
}
if(on_flag)
{
DINGSHI(timeM+1,1);// Yellow light reminder for occupied
}
else
{
DINGSHI(timeM+1,0);// Red light reminder for vacant
OLED_ShowCH(40,2,"Position vacant");
}
// count++; // Increase count
// if(count >= 100)
// {// // Print time and alarm status via serial port
// UsartPrintf(USART1, "Time:\r\n%d year", TimeData.year);
// UsartPrintf(USART1, "%d month", TimeData.month);
// UsartPrintf(USART1, "%d day\r\n", TimeData.day);
// UsartPrintf(USART1, " %d", TimeData.hour);
// UsartPrintf(USART1, ":%d", TimeData.minute);
// UsartPrintf(USART1, ":%d\r\n", TimeData.second);
// if(on_flag == 1)
// {// UsartPrintf(USART1, "Alarm: On\r\n");
// }
// else
// {// UsartPrintf(USART1, "Alarm: Off\r\n");
// }
// count = 0; // Reset count
// }
}
// The following are functions to adjust year, month, day, hour, minute, and second
if(show_flag == 1)
{
show_change_time();
if(key2_flag == 1)
{
key2_flag = 0;
lssj.year++;
}
if(key3_flag == 1)
{
key3_flag = 0;
lssj.year--;
}
if(lssj.year > 100)
lssj.year = 0;
OLED_ShowChar(24, 4, '_', 16);
Delay_50ms(2);
}
if(show_flag == 2)
{
show_change_time();
if(key2_flag == 1)
{
key2_flag = 0;
lssj.month++;
}
if(key3_flag == 1)
{
key3_flag = 0;
lssj.month--;
}
if(lssj.month > 12)
lssj.month = 1;
if(lssj.month < 1)
lssj.month = 12;
OLED_ShowChar(51, 4, '_', 16);
Delay_50ms(2);
}
if(show_flag == 3)
{
show_change_time();
if(key2_flag == 1)
{
key2_flag = 0;
lssj.day++;
}
if(key3_flag == 1)
{
key3_flag = 0;
lssj.day--;
}
if(lssj.day > 31)
lssj.day = 1;
if(lssj.day < 1)
lssj.day = 31;
OLED_ShowChar(78, 4, '_', 16);
Delay_50ms(2);
}
if(show_flag == 4)
{
show_change_time();
if(key2_flag == 1)
{
key2_flag = 0;
lssj.hour++;
if(lssj.hour > 23)
lssj.hour = 0;
}
if(key3_flag == 1)
{
key3_flag = 0;
lssj.hour--;
if(lssj.hour > 200)
lssj.hour = 23;
}
OLED_ShowChar(8, 6, '_', 16);
Delay_50ms(2);
}
if(show_flag == 5)
{
show_change_time();
if(key2_flag == 1)
{
key2_flag = 0;
lssj.minute++;
if(lssj.minute > 59)
lssj.minute = 0;
}
if(key3_flag == 1)
{
key3_flag = 0;
lssj.minute--;
if(lssj.minute > 200)
lssj.minute = 59;
}
OLED_ShowChar(38, 6, '_', 16);
Delay_50ms(2);
}
if(show_flag == 6)
{
show_change_time();
if(key2_flag == 1)
{
key2_flag = 0;
lssj.second++;
if(lssj.second > 59)
lssj.second = 0;
}
if(key3_flag == 1)
{
key3_flag = 0;
lssj.second--;
if(lssj.second > 200)
lssj.second = 59;
}
OLED_ShowChar(68, 6, '_', 16);
Delay_50ms(2);
}
}
}