System Overview
This design develops an intelligent vision protection system based on the STM32 microcontroller, effectively preventing myopia and poor posture through functions such as ultrasonic distance measurement, ambient light detection, and timed reminders. The system adopts a modular design, including modules for sensor data acquisition, threshold judgment, alarm prompts, and user interaction, characterized by strong practicality and low cost.
Hardware Design
Core Controller Selection
The system uses the STM32F103C8T6 as the main controller, which is a 32-bit microcontroller based on the ARM Cortex-M3 core, featuring rich peripheral interfaces and high processing capability, making it very suitable for embedded application scenarios. If you need the circuit schematic for this design, you can follow my public account
and contact me via private message to obtain it.
This chip has the following advantages:
- 72MHz main frequency, meeting real-time requirements
- Rich peripheral interfaces (ADC, PWM, USART, etc.)
- Low power design, suitable for battery power supply
- Low cost, with abundant development resources
Sensor Module
1. Ultrasonic Distance Measurement Module (HC-SR04)
Used to detect the distance between the user’s face and the desktop to prevent reading too closely. The HC-SR04 ultrasonic sensor has the following characteristics:
- Measurement range: 2cm-400cm
- Accuracy: 3mm
- Operating voltage: 5V DC
- Operating current: 15mA
This module triggers distance measurement through the Trig pin, and the Echo pin receives the echo, with measurement time proportional to distance.
2. Light Sensor Module
Used to detect ambient light intensity to prevent eye strain in overly dark or bright environments. It uses a light-dependent resistor combined with the STM32’s internal ADC:
- Light-dependent resistor GL5516
- Measurement range: 10-20K Lux
- ADC resolution: 12 bits (0-4095)
- Connected to the STM32’s ADC pin via a voltage divider circuit
Display and Interaction Module
1. OLED Display
Using a 0.96-inch OLED12864 display (IIC interface) to display in real-time:
- Current measured distance
- Ambient light intensity
- Set threshold
- Remaining time
2. Key Input
Utilizing four independent keys to implement function settings:
- Distance threshold adjustment
- Light intensity threshold adjustment
- Timer setting
- Mode switching
Alarm Module
1. Buzzer Alarm
Triggered when poor eye usage is detected:
- Active buzzer (5V)
- NPN transistor drive
- Supports different alarm modes (distance/light intensity/timer)
2. LED Indicator
RGB LED for status indication:
- Green: Normal
- Yellow: Warning
- Red: Alarm
Power Module
The system uses USB 5V power supply, with the AMS1117-3.3V voltage regulator chip providing power to the STM32 and other 3.3V devices.
Software Design
Main Program Flowchart
The system software adopts a modular design, with the main program flow as follows:
- System initialization (clock, peripherals, variables)
- Sensor data acquisition (distance, light intensity)
- Threshold comparison and state judgment
- Control alarm and display based on state
- Process user input
- Return to step 2 for loop execution
Core Code Implementation
Below is the code implementation of the system’s main function and key functional modules, including detailed comments:
#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "hcsr04.h"
#include "key.h"
#include "timer.h"
#include "led.h"
#include "adc.h"
// Global variable definition
uint16_t current_distance = 0; // Current measured distance (cm)
uint16_t current_light = 0; // Current light intensity (0-100)
uint16_t distance_threshold = 30; // Distance threshold (cm)
uint16_t light_threshold = 40; // Light intensity threshold (0-100)
uint16_t timer_count = 0; // Timer counter (minutes)
uint16_t timer_set = 45; // Timer setting (minutes)
int main(void) {
// 1. System initialization
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Set interrupt priority group
Delay_Init(); // Delay function initialization
OLED_Init(); // OLED initialization
HCSR04_Init(); // Ultrasonic module initialization
KEY_Init(); // Key initialization
TIM3_Init(4999, 7199); // Timer initialization (10ms interrupt)
LED_Init(); // LED initialization
ADC1_Init(); // ADC initialization
// 2. Display initial information
OLED_ShowString(0, 0, "Distance: cm");
OLED_ShowString(0, 2, "Light: %");
OLED_ShowString(0, 4, "Timer: / min");
OLED_ShowString(0, 6, "STM32 Vision Guard");
// 3. Main loop
while(1) {
// 3.1 Get sensor data
current_distance = HCSR04_GetDistance(); // Get distance (cm)
current_light = 100 - (ADC_GetValue()/40); // Get light intensity (0-100%)
// 3.2 Update display
OLED_ShowNum(72, 0, current_distance, 3); // Display distance
OLED_ShowNum(48, 2, current_light, 3); // Display light intensity
OLED_ShowNum(48, 4, timer_count, 2); // Display current timer
OLED_ShowNum(72, 4, timer_set, 2); // Display set time
// 3.3 State judgment and alarm
if(current_distance < distance_threshold) {
LED_SetColor(LED_RED); // Set LED to red
BEEP_On(); // Turn on buzzer
OLED_ShowString(90, 0, "!"); // Display warning sign
} else if(current_light < light_threshold) {
LED_SetColor(LED_YELLOW); // Set LED to yellow
BEEP_On(); // Turn on buzzer
OLED_ShowString(90, 2, "!"); // Display warning sign
} else {
LED_SetColor(LED_GREEN); // Set LED to green
BEEP_Off(); // Turn off buzzer
OLED_ShowString(90, 0, " "); // Clear warning sign
OLED_ShowString(90, 2, " "); // Clear warning sign
}
// 3.4 Process key input
KEY_Process(); // Key processing function
Delay_Ms(100); // Delay 100ms
}
}
// Timer interrupt service function (triggered every 10ms)
void TIM3_IRQHandler(void) {
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
static uint16_t count = 0;
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // Clear interrupt flag
count++;
if(count >= 6000) { // 6000*10ms = 60s = 1 minute
count = 0;
timer_count++;
if(timer_count >= timer_set) {
BEEP_On(); // Timer time reached, turn on buzzer
LED_SetColor(LED_RED); // Set LED to red
}
}
}
}
Key Functional Modules
1. Ultrasonic Distance Measurement Module
// HC-SR04 initialization
void HCSR04_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_TRIG_RCC | HCSR04_ECHO_RCC, ENABLE);
// Trig pin configuration (output)
GPIO_InitStructure.GPIO_Pin = HCSR04_TRIG_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HCSR04_TRIG_PORT, &GPIO_InitStructure);
// Echo pin configuration (input)
GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(HCSR04_ECHO_PORT, &GPIO_InitStructure);
HCSR04_TRIG_OFF(); // Initial state Trig low
}
// Get distance (cm)
uint16_t HCSR04_GetDistance(void) {
uint32_t time = 0;
HCSR04_TRIG_ON(); // Send 10us high pulse
Delay_Us(10);
HCSR04_TRIG_OFF();
while(GPIO_ReadInputDataBit(HCSR04_ECHO_PORT, HCSR04_ECHO_PIN) == RESET); // Wait for Echo to go high
while(GPIO_ReadInputDataBit(HCSR04_ECHO_PORT, HCSR04_ECHO_PIN) != RESET) { // Measure high level time
time++;
Delay_Us(1);
if(time > 23529) break; // Timeout (400cm)
}
return time / 58; // Calculate distance (cm)
}
2. Light Sensor Module
// ADC initialization
void ADC1_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
// Configure ADC pin (PA1)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// ADC configuration
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
// Get ADC value (0-4095)
uint16_t ADC_GetValue(void) {
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
return ADC_GetConversionValue(ADC1);
}
3. Key Processing Module
// Key initialization
void KEY_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(KEY1_RCC | KEY2_RCC | KEY3_RCC | KEY4_RCC, ENABLE);
GPIO_InitStructure.GPIO_Pin = KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEY1_PORT, &GPIO_InitStructure);
}
// Key processing function
void KEY_Process(void) {
static uint8_t key_up = 1;
if(key_up && (KEY1_PRES || KEY2_PRES || KEY3_PRES || KEY4_PRES)) {
Delay_Ms(10); // Debounce
key_up = 0;
if(KEY1_PRES) { // Increase distance threshold
distance_threshold += 5;
if(distance_threshold > 60) distance_threshold = 60;
} else if(KEY2_PRES) { // Decrease distance threshold
distance_threshold -= 5;
if(distance_threshold < 20) distance_threshold = 20;
} else if(KEY3_PRES) { // Increase light intensity threshold
light_threshold += 5;
if(light_threshold > 80) light_threshold = 80;
} else if(KEY4_PRES) { // Decrease light intensity threshold
light_threshold -= 5;
if(light_threshold < 20) light_threshold = 20;
}
} else if(KEY1_PRES==0 && KEY2_PRES==0 && KEY3_PRES==0 && KEY4_PRES==0) {
key_up = 1;
}
}
System Schematic
The system hardware connection schematic is as follows:
+-------------------+ +-------------------+ +-------------------+
| STM32F103C8T6 | | HC-SR04 | | OLED12864 |
| | | | | |
| PA0 <--------- |<-----| Trig | | |
| PA1 <--------- |<-----| Echo | | |
| | | | | |
| PA2 <--------- |<-----| VCC (5V) | | |
| PA3 <--------- |<-----| GND | | |
| | | | | |
| PB6 <--------- |<-----| SCL | | |
| PB7 <--------- |<-----| SDA | | |
| | | | | |
| PB8 <--------- |<-----| + | | |
| PB9 <--------- |<-----| - | | |
| | | | | |
| PC13 <--------- |<-----| Buzzer | | |
| | | | | |
| PA4 <--------- |<-----| Light Sensor | | |
| | | | | |
| PB0 <--------- |<-----| KEY1 | | |
| PB1 <--------- |<-----| KEY2 | | |
| PB10 <--------- |<-----| KEY3 | | |
| PB11 <--------- |<-----| KEY4 | | |
+-------------------+ +-------------------+ +-------------------+
Function Testing and Optimization
Testing Plan
-
Distance Detection Test:
- Test the accuracy of the ultrasonic module at different distances (20cm-50cm)
- Verify the alarm threshold setting function
-
Light Intensity Detection Test:
- Test the response of the light sensor using an adjustable light source
- Verify the accuracy of the alarm under different lighting conditions
-
Timing Function Test:
- Test the accuracy of the timed alarm
- Verify the timer setting function
-
Comprehensive Test:
- Simulate actual usage scenarios for long-term stability testing
- Test the interaction of multiple modules working simultaneously
Optimization Suggestions
-
Algorithm Optimization:
- Add sensor data filtering algorithms to improve stability
- Implement dynamic threshold adjustment to adapt to different user needs
-
Function Expansion:
- Add a Bluetooth module for mobile app control
- Add data logging functionality to track eye usage habits
- Support multi-user mode to store personalized settings
-
User Experience Optimization:
- Add voice prompt functionality
- Optimize alarm methods (vibration, light, etc.)
- Improve user interface to include more status displays
Conclusion
This article provides a detailed introduction to a vision protection system design based on the STM32 microcontroller, including hardware selection, circuit design, software implementation, and functional testing. The system achieves intelligent alarms through ultrasonic distance measurement and ambient light detection, characterized by strong practicality and low cost, especially suitable for students and office workers. The complete source code and detailed comments provided can serve as a reference for related project development and can also be further developed based on this foundation!