Click the blue text above to follow us
🤞Hello everyone, this is the 5132 microcontroller graduation project sharing. Today, I will share with you the “Smart Desk Lamp based on STM32”!
01
Physical Display

02
Function Introduction
2.1 Hardware List
-
STM32F103C8T6 Minimum Core Control Board
-
ASP20 Voice Recognition Module
-
ESP8266 Wireless Module
-
Human Pyroelectric Sensor
-
Photoresistor
-
High-Power LED Lamp
-
Backup Battery
-
0.96 Inch OLED Display
-
Buzzer
-
DHT11 Temperature and Humidity Sensor
-
4 Buttons
-
Power Interface and Switch
2.2 Function Description
-
STM32F103C8T6 Core Board: Acts as the system control center, coordinating the operation of various modules and executing control logic.
-
ASP20 Voice Recognition Module: Receives and recognizes voice commands, enabling voice control functions such as “turn on the light” and “turn off the light”.
-
ESP8266 Wireless Module: Connects to a remote cloud platform, supporting mobile app remote monitoring and control of device status.
-
Human Pyroelectric Sensor: Detects the presence of a person in the environment, automatically turning off the light when no one is present and triggering the light to turn on when someone is detected.
-
Photoresistor: Collects ambient light intensity, adjusting the brightness of the LED lamp based on light intensity in automatic mode.
-
High-Power LED Lamp: Simulates a desk lamp, providing illumination, and can control brightness and switch through various modes.
-
Backup Battery: Provides continuous power to the microcontroller after a power outage, ensuring the accuracy of the real-time clock.
-
0.96 Inch OLED Display: Displays real-time information such as time, temperature, humidity, light intensity, and system operating mode.
-
Buzzer: Emits an alarm sound when temperature or humidity exceeds the set threshold.
-
DHT11 Temperature and Humidity Sensor: Collects environmental temperature and humidity data for threshold judgment and alarm in automatic mode.
-
4 Buttons: Used for mode switching (remote/automatic/manual/voice), gear adjustment, threshold setting, and timing function operations.
-
Power Interface and Switch: Provides power input to the system, controlling the overall power on/off.
2.3 Control Modes
(1) Remote Mode: After system reset, it enters this mode, connecting to the remote cloud platform via ESP8266. The mobile app can control the light switch, mode switching (manual mode, remote mode, etc.), and view data such as light intensity, temperature, and humidity in real-time.
(2) Automatic Mode: In the presence of a person, it controls the brightness and switch of the light based on light intensity and human detection. The stronger the light intensity, the dimmer the light; when a person is detected, the light turns on, and when no one is present, the light turns off. Additionally, when temperature and humidity exceed the set threshold, the buzzer will sound an alarm.
(3) Manual Mode: Controls the light’s gear through the second button, with the first gear being off, and the second, third, and fourth gears being different brightness levels.
(4) Timing Mode: Sets the light-on time, and when the set time is reached, the light automatically turns on. The second button is used to switch between hours, minutes, and seconds for setting.
(5) Voice Mode: The system is awakened by the voice command “Xiao Zhi, I am here”, and then the light can be controlled by voice commands such as “turn on the light” and “turn off the light”.
(6) Threshold Setting Mode: Thresholds for temperature, humidity, etc., can be set using buttons for judgment in automatic mode.
03
Software Design Flowchart

04
Schematic Display


05
Partial Program Display
Control modes and logic of the main program:
#include "sys.h" // Header file
#include "delay.h"
#include "usart.h"
#include "timer.h"
#include "usart3.h"
#include "gizwits_product.h"
#include "Key.h"
#include "Buzzer.h"
#include "OLED.h"
#include "AD.h"
#include "MyRTC.h"
#include "PWM.h"
#include "renti.h"
#include "Serial2.h"
#include "dht11.h"
uint8_t KeyNum; // Store key value
u8 bufe[10]; // Store sensor collected data
uint16_t AD0, AD1, AD2; // Store 5 ADC values
uint32_t GuangYu1 = 10, GuangYu2 = 30, GuangYu3 = 50, GuangYu4 = 70; // Light intensity threshold upper limits
u8 state, state2, state2_1, state2_2, state3, state4, S_YuZhi; // Key state flags
u8 t = 0; // Sensor reading time interval
u8 flag; // Remote control flag
u8 flag2 = 0, flag1, flag3;
uint16_t RTC_Time[] = {0, 0, 0};
uint16_t RTC_Time1[] = {18, 0, 0}; // Timing time --- on
uint16_t RTC_Time2[] = {22, 0, 0}; // Timing time --- off
u8 T_state, T_state1, qingping = 1, state_dingshi_yu_guan, state_dingshi_yu_kai, state_dingshi_yu_switch, state3_1;
u8 TempYu = 30;
u8 HumiYu = 40;
extern void TimeSet(void);
extern void TimeRead(void);
extern void DingShiMoShi(void);
extern void YuZhiSet(void);
extern void ChuangGan(void);
extern void YuZhiSet(void);
void MY_Gizwits_Init(void) // Gizwits initialization function
{
TIM3_Int_Init(9, 7199); // 1MS system timer
usart3_init(9600);// WIFI initialization
memset((uint8_t *)&currentDataPoint, 0, sizeof(dataPoint_t)); // Device status structure initialization
gizwitsInit();// Circular buffer initialization
gizwitsSetMode(2); // Set mode
userInit();
}
void shoudong() // state2,state2_1,state2_2
{
if (KeyNum == 2) // Button PB0 controls window switch
{
delay_ms(20);
if (KeyNum == 2)
{
state2++;
if (state2 > 3)
{
state2 = 0;
}
}
}
switch (state2)
{
case 0:
PWM_SetCompare1(0);
OLED_ShowChinese(4, 4, 76);
break;
case 1:
PWM_SetCompare1(33);
OLED_ShowChinese(4, 4, 77);
break;
case 2:
PWM_SetCompare1(66);
OLED_ShowChinese(4, 4, 78);
break;
case 3:
PWM_SetCompare1(100);
OLED_ShowChinese(4, 4, 79);
break;
default:
break;
}}
void zhidong(){
if ((bufe[2] > TempYu) || (bufe[3] > HumiYu))
{
Buzzer_Turn();
}
else
{
Buzzer_OFF();
}
if (flag == 1) {
switch (state4)
{
case 1:
PWM_SetCompare1(0);
OLED_ShowChinese(4, 4, 76);
break;
case 2:
PWM_SetCompare1(33);
OLED_ShowChinese(4, 4, 77);
break;
case 3:
PWM_SetCompare1(66);
OLED_ShowChinese(4, 4, 78);
break;
case 4:
PWM_SetCompare1(100);
OLED_ShowChinese(4, 4, 79);
break;
default:
break;
} }
else {
PWM_SetCompare1(0);
}}
void YuYingMode() // First say Xiao Zhi wake up, then say open window and close window
{
if (Serial2_RxFlag == 1) // Serial port received data packet flag, if a data packet is received, it will be set to 1
{
if (strcmp(Serial2_RxPacket, "LED_ON") == 0)
{
PWM_SetCompare1(100);
}
else if (strcmp(Serial2_RxPacket, "LED_OFF") == 0)
{
PWM_SetCompare1(0);
}
if (strcmp(Serial2_RxPacket, "TOUYING_ON") == 0)
{
PWM_SetCompare1(0);
}
if (strcmp(Serial2_RxPacket, "JIANGKE_ON") == 0)
{
PWM_SetCompare1(50);
}
if (strcmp(Serial2_RxPacket, "ZIXI_ON") == 0)
{
PWM_SetCompare1(80);
}
Serial2_RxFlag = 0; // Clear the flag, if not cleared, the next data packet cannot be received
}}
int main(void){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Set NVIC interrupt group 2: 2 bits for preemption priority, 2 bits for response priority
uart_init(9600); // Serial port initialization to 9600
delay_init(); // Delay function initialization
Buzzer_Init(); // Below is peripheral initialization
OLED_Init();
Key_Init();
AD_Init();
DHT11_Init();
PWM_Init(); // PWM initialization
MyRTC_Init();
RenTiSensor_Init();
MY_Gizwits_Init(); // Gizwits initialization
Serial2_Init(); // Serial port 2 initialization (voice recognition module)
while (1) {
userHandle(); // Data upload
gizwitsHandle((dataPoint_t *)&currentDataPoint); // Background processing, must be placed in while
if (t % 10 == 0) {
DHT11_Read_Data(&bufe[2], &bufe[3]); // Read temperature and humidity and display on OLED
AD1 = AD_GetValue(ADC_Channel_1); // Light sensor
if (AD1 > 4000)AD1 = 4000;
bufe[1] = (u8)(100 - AD1 / 40);
if (bufe[1] < GuangYu1) state4 = 4;
else if (bufe[1] < GuangYu2) state4 = 3;
else if (bufe[1] < GuangYu3) state4 = 2;
else if (bufe[1] < GuangYu4) state4 = 1;
}
t++;
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4) == 1) {
flag = 1;
}
else {
flag = 0;
}
KeyNum = Key_GetNum();
if (KeyNum == 1) {
qingping = 0;
delay_ms(20);
if (KeyNum == 1) {
state++;
if (state > 5) {
state = 0;
}
}
}
if (state == 0) // Remote mode {
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
TimeRead();
ChuangGan();
OLED_ShowChinese(1, 7, 49);
OLED_ShowChinese(1, 8, 50);
}
if (state == 1) // Automatic mode {
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
OLED_ShowChinese(1, 7, 51);
OLED_ShowChinese(1, 8, 52);
TimeRead();
zhidong();
ChuangGan();
}
if (state == 2) // Manual mode {
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
OLED_ShowChinese(1, 7, 18);
OLED_ShowChinese(1, 8, 52);
TimeRead();
ChuangGan();
shoudong();
}
if (state == 3) // Timing mode {
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
OLED_ShowChinese(1, 7, 84);
OLED_ShowChinese(1, 8, 85);
TimeRead();
DingShiMoShi();
}
if (state == 4) // Voice mode {
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
OLED_ShowChinese(1, 7, 57);
OLED_ShowChinese(1, 8, 58);
TimeRead();
ChuangGan();
YuYingMode();
}
if (state == 5) // Threshold mode {
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
OLED_ShowChinese(1, 7, 86);
OLED_ShowChinese(1, 8, 87);
TimeRead();
YuZhiSet();
}
}}
void TimeSet() // Set time
{
if (KeyNum == 2) // PB10 {
delay_ms(20);
if (KeyNum == 2) {
T_state++;
if (T_state > 2) {
T_state = 0;
}
}
}
if (T_state == 0) // Time display mode {
MyRTC_ReadTime();
OLED_ShowNum(1, 5, MyRTC_Time[3], 2); // Hour
OLED_ShowString(1, 7, ":");
OLED_ShowNum(1, 8, MyRTC_Time[4], 2); // Minute
OLED_ShowString(1, 10, ":");
OLED_ShowNum(1, 11, MyRTC_Time[5], 2); // Second
RTC_Time[0] = MyRTC_Time[3];
RTC_Time[1] = MyRTC_Time[4];
RTC_Time[2] = MyRTC_Time[5];
}
if (T_state == 1) // Modify time {
if (KeyNum == 5) {
delay_ms(20);
if (KeyNum == 5) {
T_state1++;
if (T_state1 > 2) {
T_state1 = 0;
}
}
}
if (T_state1 == 0) // Modify hour {
if (KeyNum == 4)RTC_Time[0]++;
if (KeyNum == 3)RTC_Time[0]--;
if (RTC_Time[0] > 23 & RTC_Time[0] < 100)RTC_Time[0] = 0;
if (RTC_Time[0] > 100)RTC_Time[0] = 23;
OLED_ShowNum(1, 5, RTC_Time[0], 2); // Hour
}
if (T_state1 == 1) // Modify minute {
if (KeyNum == 4)RTC_Time[1]++;
if (KeyNum == 3)RTC_Time[1]--;
if (RTC_Time[1] > 59 & RTC_Time[1] < 100)RTC_Time[1] = 0;
if (RTC_Time[1] > 100)RTC_Time[1] = 59;
OLED_ShowNum(1, 8, RTC_Time[1], 2); // Minute
}
if (T_state1 == 2) // Modify second {
if (KeyNum == 4)RTC_Time[2]++;
if (KeyNum == 3)RTC_Time[2]--;
if (RTC_Time[2] > 59)RTC_Time[2] = 0;
if (RTC_Time[2] > 59 & RTC_Time[2] < 100)RTC_Time[2] = 0;
if (RTC_Time[2] > 100)RTC_Time[2] = 59;
OLED_ShowNum(1, 11, RTC_Time[2], 2); // Second
}
}
if (T_state == 2) {
MyRTC_Time[3] = RTC_Time[0];
MyRTC_Time[4] = RTC_Time[1];
MyRTC_Time[5] = RTC_Time[2];
MyRTC_SetTime();
T_state = 0;
}}
void TimeRead(){
MyRTC_ReadTime();
OLED_ShowNum(1, 5, MyRTC_Time[3], 2); // Hour
OLED_ShowString(1, 7, ":");
OLED_ShowNum(1, 8, MyRTC_Time[4], 2); // Minute
OLED_ShowString(1, 10, ":");
OLED_ShowNum(1, 11, MyRTC_Time[5], 2); // Second
}
void DingShiMoShi(){
TimeRead(); //............................... Timing mode ..................................../
if ((MyRTC_Time[3] == RTC_Time1[0]) && (MyRTC_Time[4] == RTC_Time1[1]) && (MyRTC_Time[5] == RTC_Time1[2]))
{
PWM_SetCompare1(100);// Peripheral operation
}
if ((MyRTC_Time[3] == RTC_Time2[0]) && (MyRTC_Time[4] == RTC_Time2[1]) && (MyRTC_Time[5] == RTC_Time2[2]))
{
PWM_SetCompare1(0);// Peripheral operation
}//............................... Modify timing time ..................................../
OLED_ShowChinese(3, 1, 31);
OLED_ShowString(3, 3, ":");
OLED_ShowNum(3, 5, RTC_Time1[0], 2);
OLED_ShowString(3, 7, ":");
OLED_ShowNum(3, 8, RTC_Time1[1], 2);
OLED_ShowString(3, 10, ":");
OLED_ShowNum(3, 11, RTC_Time1[2], 2);
OLED_ShowChinese(4, 1, 32);
OLED_ShowString(4, 3, ":");
OLED_ShowNum(4, 5, RTC_Time2[0], 2);
OLED_ShowString(4, 7, ":");
OLED_ShowNum(4, 8, RTC_Time2[1], 2);
OLED_ShowString(4, 10, ":");
OLED_ShowNum(4, 11, RTC_Time2[2], 2);
if (KeyNum == 2) {
delay_ms(20);
if (KeyNum == 2) {
state_dingshi_yu_kai++;
if (state_dingshi_yu_kai > 5) {
state_dingshi_yu_kai = 0;
}
}
}
if (state_dingshi_yu_kai == 0) // Hour {
if (KeyNum == 3) RTC_Time1[0]++;
if (KeyNum == 4) RTC_Time1[0]--;
}
if (state_dingshi_yu_kai == 1)// Minute {
if (KeyNum == 3) RTC_Time1[1]++;
if (KeyNum == 4) RTC_Time1[1]--;
}
if (state_dingshi_yu_kai == 2)// Second {
if (KeyNum == 3) RTC_Time1[2]++;
if (KeyNum == 4) RTC_Time1[2]--;
}
if (state_dingshi_yu_kai == 3) // Hour {
if (KeyNum == 3) RTC_Time2[0]++;
if (KeyNum == 4) RTC_Time2[0]--;
}
if (state_dingshi_yu_kai == 4)// Minute {
if (KeyNum == 3) RTC_Time2[1]++;
if (KeyNum == 4) RTC_Time2[1]--;
}
if (state_dingshi_yu_kai == 5)// Second {
if (KeyNum == 3) RTC_Time2[2]++;
if (KeyNum == 4) RTC_Time2[2]--;
}}
// Set threshold function
void YuZhiSet(){
OLED_ShowString(2, 1, "T:");
OLED_ShowNum(2, 3, TempYu, 2);
OLED_ShowString(3, 1, "S:");
OLED_ShowNum(3, 3, HumiYu, 2);
if (KeyNum == 2) {
delay_ms(20);
if (KeyNum == 2) {
S_YuZhi++;
if (S_YuZhi > 1) {
S_YuZhi = 0;
}
}
}
switch (S_YuZhi) {
case 0:
if (KeyNum == 3) TempYu++;
if (KeyNum == 4) TempYu--;
break;
case 1:
if (KeyNum == 3) HumiYu++;
if (KeyNum == 4) HumiYu--;
break;
}}
void ChuangGan(){
if (qingping == 0) {
OLED_Clear();
qingping = 1;
}
OLED_ShowChinese(2, 1, 53);
OLED_ShowChinese(2, 2, 54);
OLED_ShowString(2, 5, ":");
OLED_ShowNum(2, 6, bufe[1], 2);
OLED_ShowString(2, 8, "%");
OLED_ShowChinese(4, 1, 74);
OLED_ShowChinese(4, 2, 75);
OLED_ShowString(4, 5, ":");
OLED_ShowChinese(4, 5, 74);
OLED_ShowChinese(3, 1, 82);
OLED_ShowChinese(3, 2, 83);
OLED_ShowString(3, 5, ":");
if (flag == 1) {
OLED_ShowChinese(3, 4, 80); // Someone present
OLED_ShowChinese(3, 5, 82); // Someone present
}
else {
OLED_ShowChinese(3, 4, 81);// No one present
OLED_ShowChinese(3, 5, 82);
}
OLED_ShowString(2, 12, "T:");
OLED_ShowNum(2, 14, bufe[2], 2);
OLED_ShowString(3, 12, "S:");
OLED_ShowNum(3, 14, bufe[3], 2);
}
PhysicalPurchase TB: 5132 Microcontroller Design
Physical Customization VX:lwfw123456789