目录:

  • 1.系统实现目标
  • 2.硬件选型和软件准备
    • 2.1.硬件选型
    • 2.2.软件准备
  • 3.硬件的连接电路
  • 4.各个模块的驱动程序
    • 4.1.红外传感器的驱动程序
    • 4.2.DHT11温湿度传感器的驱动程序
    • 4.3.OLED显示模块
    • 4.4.舵机的驱动
    • 4.5.电机的驱动
  • 5.不同的工作模式
    • 5.1.选择模式
    • 5.2.手动模式
    • 5.3.自动模式
  • 6.总结

1.系统实现目标

本系统可以分为两个模式来进行运行,分别为手动模式和自动模式,同时,在上电进入系统后,还会有一个模式选择的界面产生。

  • 模式选择:在此界面中,可以通过按键K1来控制模式选择,两个模式分别为手动模式和自动模式;通过按键K2可以进入模式。
  • 手动模式:在手动模式中,可以通过K1来进行速度调整,分为低速、中速和高速,可以通过K3来控制是否为摇头状态。
  • 自动模式:在自动模式下,可以通过红外传感器来检测周围是否有人,通过温湿度传感器来测试周围环境温度和湿度,若达到条件就会触发风扇进行运转,风速也有低速模式、中速模式、高速模式。
    所有没写出的代码都太长,所以都在链接里面,可以自己下载,积分都设置为0了.

2.硬件选型和软件准备

2.1.硬件选型

1.最小系统板
这次项目使用的板子是stm32f103c8t6最小系统板,这个板子在tb上都能够买到,随便一个最小系统板都可以。

2.显示模块
显示模块是使用的0.96英寸的OLED屏幕,注意是使用的IIC通信协议的OLED屏幕,不是使用SPI总线协议的。买的时候要看清楚。

3.温度传感器
温湿度传感器使用的是DHT11温湿度传感器,用来采集环境的温湿度,最主要是用来采集温度。

4.红外模块
红外模块是用来检测风扇前是否有人的。

5.电机驱动模块
本次实验用的电机驱动模块是使用的大功率MOS管。

6.舵机
舵机这个元器件主要是用来实现风扇摆头这个功能。

7.电机
这次的电机是使用的空心杯这个电机,转速快,功率小。

以上的元件就是这次项目用到的主要元器件。

2.2.软件准备

当我们把所有的硬件都准备完活以后,就要开始编写软件代码,编写软件代码之前,需要进行软件环境的准备,如果没有软件环境,我把软件环境放在了以下连接中:
https://download.csdn.net/download/nbbskk/87239099

3.硬件的连接电路


硬件的连接电路如上
其中大功率MOS管需要注意,需要外接电源,不能使用单片机提供的5V引脚,因为如果这个mos管直接连接单片机中的5V引脚的话,就会造成程序的崩溃。

4.各个模块的驱动程序

4.1.红外传感器的驱动程序

红外传感器模块主要是用来检测前方是否有人存在,主要是用在自动模式下的。
.c文件

  #include "stm32f10x.h"                  // Device headervoid Infrared_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);//  GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}//PB10口来检测红外避障模块的功能,如果检测到障碍物返回1,未检测到障碍物返回2
uint16_t  Get_Sign(void)
{if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0){return 1;}else {return 2;}
}

.h文件

#ifndef  __INFRARED_H
#define __INFRARED_Hvoid Infrared_Init(void);
uint16_t  Get_Sign(void);#endif

4.2.DHT11温湿度传感器的驱动程序

DHT11温湿度传感器主要是用来检测环境温度的。
.c文件

#include "stm32f10x.h"                  // Device header
#include "dht11.h"
#include  "oled.h"
#include  "delay.h"extern uint8_t dat[5];void dht11_package_show(void)//DHT11显示模式打包
{//显示温度和湿度字符OLED_ShowChinese(10,0,9,16,1);OLED_ShowChinese(26,0,8,16,1);OLED_ShowString(42,0,":",16,1);OLED_ShowChinese(10,16,10,16,1);OLED_ShowChinese(26,16,8,16,1);OLED_ShowString(42,16,":",16,1);OLED_Refresh();if(DHT_Read()){//显示湿度OLED_ShowNum(52,16,dat[0],2,16,1);OLED_ShowString(70,16,"%",16,1);
//     OLED_ShowNum(50,0,dat[1],5,16,1);//显示温度OLED_ShowNum(52,0,dat[2],2,16,1);  OLED_DrawPoint(70,12,1);OLED_ShowNum(74,0,dat[3],1,16,1);OLED_Refresh();delay_ms(10);}
}

.h文件

#ifndef  __DHT11_PACKAGE_H
#define __DHT11_PACKAGE_Hvoid dht11_package_show(void);#endif

4.3.OLED显示模块

OLED显示模块主要是用来显示和调试用的

OLED显示程序包括字库程序太大,放到以下连接中去下载。
https://download.csdn.net/download/nbbskk/87238933

4.4.舵机的驱动

舵机主要是用在切换风扇扫风和不扫风模式的
.c文件

#include "stm32f10x.h"                  // Device headervoid  SG90_Init(void)
{TIM_TimeBaseInitTypeDef    TIM_TimeBaseInitStructure;TIM_OCInitTypeDef     TIM_OCInitTypeDefStrucutre;GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6 ;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);TIM_InternalClockConfig(TIM3);//选择内部时钟//时基单元配置TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period=20000-1;              //ARR自动装载值TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;            //PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//输出比较器初始化TIM_OCInitTypeDefStrucutre.TIM_OCMode=TIM_OCMode_PWM1;TIM_OCInitTypeDefStrucutre.TIM_OCPolarity= TIM_OCPolarity_High;TIM_OCInitTypeDefStrucutre.TIM_OutputState= TIM_OutputState_Enable   ;TIM_OCInitTypeDefStrucutre.TIM_Pulse=0;                                                    //CCRTIM_OC1Init(TIM3, &TIM_OCInitTypeDefStrucutre);TIM_Cmd(TIM3,ENABLE);}void  setccr(uint16_t   crrnum)
{TIM_SetCompare1(TIM3,crrnum);//设置舵机的旋转,舵机旋转的crrnum最大为2500,最小为500
}

.h文件

#ifndef  __SG90_H
#define __SG90_Hvoid SG90_Init(void);
void  setccr(uint16_t   crrnum);#endif

4.5.电机的驱动

电机用来充当风扇

.c文件

#include "stm32f10x.h"                  // Device headervoid  key_PWM_Init(void)
{TIM_TimeBaseInitTypeDef    TIM_TimeBaseInitStructure;TIM_OCInitTypeDef     TIM_OCInitTypeDefStrucutre;GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 ;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//你GPIO_Init(GPIOB,&GPIO_InitStructure);TIM_InternalClockConfig(TIM3);//选择内部时钟//时基单元配置TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period=20000-1;              //ARR自动装载值TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;            //PSCTIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//输出比较器初始化TIM_OCInitTypeDefStrucutre.TIM_OCMode=TIM_OCMode_PWM1;TIM_OCInitTypeDefStrucutre.TIM_OCPolarity= TIM_OCPolarity_High;TIM_OCInitTypeDefStrucutre.TIM_OutputState= TIM_OutputState_Enable   ;TIM_OCInitTypeDefStrucutre.TIM_Pulse=0;                                                 //CCRTIM_OC3Init(TIM3, &TIM_OCInitTypeDefStrucutre);TIM_Cmd(TIM3,ENABLE);
}void  setccr3(uint16_t   crrnum3)
{TIM_SetCompare3(TIM3,crrnum3);//设置风扇的转速
}

.h文件

#ifndef    __KEY_PWM_H
#define   __KEY_PWM_Hvoid  key_PWM_Init(void);
void  setccr3(uint16_t   crrnum3);#endif

5.不同的工作模式

5.1.选择模式

当各个模块的驱动程序写好以后,就可以进行模式的选择了,通过对手动模式和自动模式的选择来进入到不同的模式当中。
模式选择功能的实现主要是通过按键和标志位来进行实现的,这个项目是通过四个按钮来进行控制的。
其中,当在模式选择界面的时候,需要两个按钮,分别接到GPIOA_2和GPIOA_3上,一端接低电平,另一端接IO口。
选择模式是通过以下的代码来实现的

show_words3();//显示选择界面option();//进行模式选择if(flago==0)//显示手动模式{OLED_ShowChinese(50,30,4,16,1);OLED_ShowChinese(66,30,5,16,1);OLED_Refresh();}else if(flago==1)//显示自动模式{OLED_ShowChinese(50,30,6,16,1);OLED_ShowChinese(66,30,5,16,1);OLED_Refresh();    }   action();//接收进入模式信息if(flago==0&&go==1)//进入手动模式{manual_mode_Init();//手动模式初始化while(1){//              manual_go();if(flag_go2==0) //进入循环后,未按下按键跳回选择界面{manual_go();//进入手动模式}else if(flag_go2==1)//跳出循环界面{OLED_Clear();flago=0;go=0;flag_go2=0;break;}}}else if(flago==1&&go==1)//进入自动模式{auto_mode_Init();//自动模式初始化while(1){//              auto_go();if(flag_go2==0){auto_go();}else if(flag_go2==1){OLED_Clear();flag_go2=0;flago=1;go=0;break;}}}

其中单片机上电以后就会进入模式选择界面,通过option函数来实现手动模式和自动模式的选择,此时液晶屏上会显示是手动模式还是自动模式。
option函数通过以下代码来实现的

//给PA2输入低电平进行模式的选择
void option(void)
{if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==0){delay_ms(30);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==0){delay_ms(30);u++;flago=u%2;}}
//  return flago;
}

option函数主要是通过连接到PA2口的按钮来实现的。

当选择到合适的模式的时候,那么就通过action函数来进入这个模式。
action函数是由以下程序来实现的

//给PA3输入低电平,进入此模式
void action(void)
{if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)==0){delay_ms(30);if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)==0){delay_ms(30);go=1;}}
//  return go;
}

主要是通过PA3口来控制进入。

5.2.手动模式

进入手动模式以后,主要就是通过按钮来实现风扇是否扫风、风扇转速控制主要是通过PA2口的按钮和PB11口的按钮来实现。

  • 当PA2口的按钮按下后,可以实现停止->低速->中速->高速->停止的切换,如此可以进行循环,这一步并没有加上减速的操作,是为了降低按钮的使用量。
  • 当PB11口的按钮按下以后,可以实现扫风和不扫风的切换。
  • 同时如果按下PA8口的按键的话,程序就会跳回选择模式的界面。

手动模式是由以下程序来实现的

uint16_t mo=0;
uint16_t deg=0;
uint8_t flags_it=0;
void manual_mode_Init(void)
{key_PWM_Init();add_init();delay_init();OLED_Init();key_it_Init();SG90_Init();setccr(1500);//显示风速两个字OLED_ShowChinese(20,0,12,16,1);OLED_ShowChinese(36,0,7,16,1);OLED_ShowString(51,0,":",16,1);OLED_Refresh();}void manual_go(void)
{uint16_t i=0;flags_it=Get_key_it_flag();//得到是否让风扇转动信号
//  mo=add_sub1 ();
//  OLED_ShowNum(40,0,flags_it,2,16,1);if(flags_it==1)//进入扫风的模式{//如果扫风,显示扫风模式四个字OLED_ShowChinese(22,25,11,16,1);OLED_ShowChinese(38,25,12,16,1);OLED_ShowChinese(54,25,0,16,1);OLED_ShowChinese(70,25,1,16,1);OLED_Refresh();//正向扫风for(i=500;i<2500;i+=100){mo=add_sub1 ();//控制风扇转速flags_it=Get_key_it_flag();if(flags_it==0){break;}mo=add_sub1 ();//控制风扇的转速deg=mo*830;setccr3(deg);//设置风扇转速setccr(i);delay_ms(100);mo=add_sub1 ();if(mo==0){//显示停止两个字OLED_ShowChinese(58,0,16,16,1);OLED_ShowChinese(74,0,17,16,1);OLED_Refresh();}else if(mo==4){//显示低速两个字OLED_ShowChinese(58,0,13,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}else if(mo==8){//显示中速两个字OLED_ShowChinese(58,0,14,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}else if(mo==12){//显示高速两个字OLED_ShowChinese(58,0,15,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}
//          OLED_ShowNum(0,0,mo,2,16,1);
//          OLED_ShowNum(20,0,i,2,16,1);
//          OLED_ShowNum(0,16,deg,6,16,1);
//          OLED_Refresh();}//反向扫风for(i=2500;i>500;i-=100){mo=add_sub1 ();flags_it=Get_key_it_flag();if(flags_it==0){break;}mo=add_sub1 ();deg=mo*830;setccr3(deg);setccr(i);delay_ms(100);mo=add_sub1 ();if(mo==0){OLED_ShowChinese(58,0,16,16,1);OLED_ShowChinese(74,0,17,16,1);OLED_Refresh();}else if(mo==4){OLED_ShowChinese(58,0,13,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}else if(mo==8){OLED_ShowChinese(58,0,14,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}else if(mo==12){OLED_ShowChinese(58,0,15,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}
//          OLED_ShowNum(0,0,mo,2,16,1);
//          OLED_ShowNum(20,0,i,2,16,1);
//          OLED_ShowNum(0,16,deg,6,16,1);
//          OLED_Refresh();}}else if(flags_it==0)//风扇不扫风{OLED_ShowString(22,25,"             ",16,1);OLED_Refresh();mo=add_sub1 ();deg=mo*830;setccr3(deg);if(mo==0){OLED_ShowChinese(58,0,16,16,1);OLED_ShowChinese(74,0,17,16,1);OLED_Refresh();}else if(mo==4){OLED_ShowChinese(58,0,13,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}else if(mo==8){OLED_ShowChinese(58,0,14,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}else if(mo==12){OLED_ShowChinese(58,0,15,16,1);OLED_ShowChinese(74,0,7,16,1);OLED_Refresh();}
//      OLED_ShowNum(0,32,mo,6,16,1);
//      OLED_ShowNum(0,48,deg,6,16,1);
//      OLED_Refresh();}}

5.3.自动模式

自动模式我设计的比较复杂。

  • 首先会检测左前是否有人,如果左前有人,就只会在左半边进行扫风;
  • 如果检测到左前没人,会检测右前是否有人,如果右前有人,只会在右半边进行扫风;
  • 如果左前和右前都有人,才会180度扫风;
  • 如果左前和右前都没人,那就不会扫风。
    同时,也会进行环境温度的检测
  • 如果环境温度>27度,那么就会进入低速模式;
  • 如果环境温度>29度,那么就会进入中速模式;
  • 如果环境温度>31度,那么就会进入高速模式;

同时,每隔10分钟就会检测一次周围是否有人,进行扫风模式的刷新。
同样,如果按下PA8口的按键,程序会跳回选择模式。
其中自动模式是由以下程序实现的

void auto_mode_Init(void)
{speed_control_Init();//显示速度两个字OLED_ShowChinese(10,32,7,16,1);OLED_ShowChinese(26,32,8,16,1);OLED_ShowString(42,32,":",16,1);OLED_Refresh();setccr(1500);}void auto_go(void)
{dht11_package_show();//温湿度的获取和显示if(dat[2]>=27&&dat[2]<29)//温度大于27度,进入低转速模式{low_speed();}if(dat[2]>=29&&dat[2]<31)//温度大于29度,进入中等转速模式{medium_speed();}if(dat[2]>=31)//温度大于31度,进入高转速模式{high_speed();}
}

其中low_speed()、medium_speed()、high_speed()就是我具体实现的自动转速实现的代码。
这些代码太大,放到以下连接中去下载。

https://download.csdn.net/download/nbbskk/87238938

6.总结

智能风扇系统的代码和设计思路就如上所示,如果想获得软件设计流程,可以参考我账号中的另一篇博客。
如果想要完整的源码,可以私信我。

注: 其中的汉字显示的代码都在oled.c、oled.h和oledfont.h中,如果想要显示自己想要的汉字,需要在字体生成软件中进行生成,字体生成软件我放在下面的连接中了。
https://download.csdn.net/download/nbbskk/87239085

其中的使用方法如下:

然后将生成的代码插入到oledfont.h中

格式和上面的代码保持一致即可

手把手教你写stm32f103智能风扇相关推荐

  1. 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫

    系列教程 手把手教你写电商爬虫-第一课 找个软柿子捏捏 如果没有看过第一课的朋友,请先移步第一课,第一课讲了一些基础性的东西,通过软柿子"切糕王子"这个电商网站好好的练了一次手,相 ...

  2. 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 1

    系列教程 手把手教你写电商爬虫-第一课 找个软柿子捏捏 如果没有看过第一课的朋友,请先移步第一课,第一课讲了一些基础性的东西,通过软柿子"切糕王子"这个电商网站好好的练了一次手,相 ...

  3. 手把手教你写一个生成对抗网络

    成对抗网络代码全解析, 详细代码解析(TensorFlow, numpy, matplotlib, scipy) 那么,什么是 GANs? 用 Ian Goodfellow 自己的话来说: " ...

  4. php注册程序,[PHP初级]手把手教你写注册程序 1

    [PHP初级]手把手教你写注册程序 1 实例内容 在此教程,我们将通过写一个用户注册程序,学习以下内容: 数据的传输与获取 信息的验证 pdo方式操作数据库 事务处理 前台显示文件:index.php ...

  5. python k线合成_手把手教你写一个Python版的K线合成函数

    手把手教你写一个Python版的K线合成函数 在编写.使用策略时,经常会使用一些不常用的K线周期数据.然而交易所.数据源又没有提供这些周期的数据.只能通过使用已有周期的数据进行合成.合成算法已经有一个 ...

  6. 手把手教你写Linux I2C设备驱动

    手把手教你写Linux I2C设备驱动 标签:Linux 设备 驱动 详解 i2c 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http:/ ...

  7. 手把手教你写DI_2_小白徒手撸构造函数注入

    在上一节:手把手教你写DI_1_DI框架有什么? 我们已经知道我们要撸哪些东西了 那么我们开始动工吧,这里呢,我们找小白同学来表演下 小白同学 :我们先定义一下我们的广告招聘纸有什么: 好,我们实现两 ...

  8. 手把手教你写DI_3_小白徒手支持 Singleton 和 Scoped 生命周期

    在上一节:手把手教你写DI_2_小白徒手撸构造函数注入 浑身绷带的小白同学:我们继续开展我们的工作,大家都知道 Singleton是什么,就是全局只有一个呗,我们就先从它开始,这个多简单,我们找个字典 ...

  9. 手把手教你写一个spring IOC容器

    本文分享自华为云社区<手把手教你写一个spring IOC容器>,原文作者:技术火炬手. spring框架的基础核心和起点毫无疑问就是IOC,IOC作为spring容器提供的核心技术,成功 ...

最新文章

  1. 【译】The Faults and Shortcomings of the EVM
  2. js怎么把函数字符串转成函数_字符串处理函数
  3. Realtime Ray Tracing RenderMan Point Cloud
  4. 史上最好记的神经网络结构速记表(上)
  5. Skipping JaCoCo execution due to missing execution data file
  6. 组态王与施耐德M241建立通讯
  7. 手绘三相电压电流波形的方法
  8. 教ai玩游戏_简单解释:DeepMind如何教AI玩视频游戏
  9. SpringBoot将图片/文件传至前端
  10. 07.尚硅谷网课7-实战练习
  11. Android自定义Lint检查-CustomLint
  12. 音视频开发: ffmpeg采集桌面屏幕、摄像头保存为视频
  13. 打地鼠java代码流程图_51单片机 普中51 打地鼠游戏 仿真 程序 流程图
  14. OpenGL实验2.3 三维模型的平移、缩放和旋转
  15. C语言:extern用法
  16. java中测代码段运行时间及内存的方法
  17. Vue 汉字转大写首字母(非汉字直接输出)
  18. 火车硬座车厢座位分布表
  19. 2017电影经典语句
  20. Microsoft Visual C++ 2005 SP1安装

热门文章

  1. c++ 删除数组中的重复项
  2. (HihoCoder - 1015)From hihoCoder
  3. JUnit4 使用详解
  4. 《了不起的盖茨比》读书笔记1-dream
  5. BPI-R3开发板 - uboot编译
  6. ETC1 支持 alpha
  7. pytorch中Tensor和ToTensor
  8. 计算机二级Python公共基础要点+真题题库考试系统下载
  9. JSBridge 原理
  10. 超简单 自定义VideoView 让视频拉伸至全屏