整体介绍
1. 主控
采用搭载STM32L4R5ZI低功耗芯片的ST官方NUCLEO-L4R5ZI开发板,使用stm32cubeMX配置,HAL库开发。

2. 传感器部分
使用DHT11采集环境温湿度,BH1750采集光照强度,采用电容式土壤湿度传感器,JW01 CO2,HCHO,TVOC三合一传感器。
3. 按键开关
使用了一个RGB灯来代表植物生长灯,设有红、蓝、绿、白四种颜色;配备6个按键,分别控制RGB灯、板载LED2、4路继电器。
4. NB-IOT
采用安信可EC-01F-kit开发板,通过串口与单片机通讯。

5. 阿里云物联网平台
将采集到的数据通过NB-IOT模组通过MQTT协议发送到阿里云物联网平台,并利用IOT-Studio简单绘制用户端页面。


配置
1. 时钟,定时器配置
首先配置RCC,SYS。其次配置定时器TIM1实现微秒级延时,用来读取DHT11温湿度数据,具体可以参考DHT11数据手册。

2. 引脚配置
| GPIO |
引脚 |
对应功能 |
| 推挽输出 |
PB7,PF15 |
主灯和DHT11温湿度传感器 |
| LPUART |
PG7(TX),PG8(RX) |
与上位机通信串口,通过板载usb连接 |
| USART2 |
PD5(TX),PD6(RX) |
JW01二氧化碳传感器 |
| I2C1 |
PB8(SCL),PB9(SDA) |
BH1750光照强度传感器 |
| TIM2 |
PA0,PA1,PA2 |
RGB植物生长灯 |
| 推挽输出 |
PG10,PG11,PG13,PG15 |
四路继电器开关 |
| 上拉输入(EXTI) |
PA4,PB0,PC1,PD3,PD12,PG2 |
按键中断,分别控制主灯,RGB,四个继电器 |
| ADC1_IN1 |
PC0 |
土壤湿度传感器 |
继电器可连接水泵,风扇等,实现控制开关。
示例代码
1. DHT11温湿度传感器
DHT11.C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| #include "dht11.h"
extern TIM_HandleTypeDef htim1;
static void DATA_OUTPUT(u8 flg); static u8 DATA_INPUT(void); static u8 DH11_Read_Byte(void);
u8 DH11_Read(void);
static void Test(void);
DH11_DATA DH11_data;
void Delay_us(uint16_t us) { uint16_t differ = 0xffff-us-5; __HAL_TIM_SET_COUNTER(&htim1,differ); HAL_TIM_Base_Start(&htim1); while(differ < 0xffff-5){ differ = __HAL_TIM_GET_COUNTER(&htim1); } HAL_TIM_Base_Stop(&htim1); }
void DATA_OUTPUT(u8 flg) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = DATA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DATA_GPIO_Port, &GPIO_InitStruct);
if(flg==0) { DATA_RESET(); } else { DATA_SET(); } }
u8 DATA_INPUT(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; u8 flg=0; GPIO_InitStruct.Pin = DATA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(DATA_GPIO_Port, &GPIO_InitStruct);
if(DATA_READ()==GPIO_PIN_RESET) { flg=0; } else { flg=1; }
return flg; }
u8 DH11_Read_Byte(void) { u8 ReadDat=0; u8 temp=0; u8 retry=0; u8 i=0; for(i=0;i<8;i++) { while(DATA_READ()==0&&retry<100) { Delay_us(1); retry++; } retry=0; Delay_us(40); if(DATA_READ()==1) { temp=1; } else { temp=0; } while(DATA_READ()==1&&retry<100) { Delay_us(1); retry++; } retry=0; ReadDat<<=1; ReadDat|=temp; } return ReadDat; }
u8 DH11_Read(void) { u8 retry=0; u8 i=0; DATA_OUTPUT(0); HAL_Delay(18); DATA_SET(); Delay_us(20); DATA_INPUT(); Delay_us(20); if(DATA_READ()==0) { while(DATA_READ()==0&&retry<100) { Delay_us(1); retry=0; } retry=0; while(DATA_READ()==1&&retry<100) { Delay_us(1); retry++; } retry=0; for(i=0;i<5;i++) { DH11_data.Data[i]=DH11_Read_Byte(); } Delay_us(50); } u32 sum=DH11_data.Data[0]+DH11_data.Data[1]+DH11_data.Data[2]+DH11_data.Data[3]; if((sum)==DH11_data.Data[4]) { DH11_data.humidity=DH11_data.Data[0]; DH11_data.temp=DH11_data.Data[2]; return 1; } else { return 0; } }
void Test(void) { if(DH11_Read()) { DH11_data.index++; if(DH11_data.index>=128) { DH11_data.index=0; } } }
void DH11_Task(void) { Test(); }
|
DHT11.H
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #ifndef _DH11_H_ #define _DH11_H_
#include"main.h"
#define u8 unsigned char #define u16 unsigned short #define u32 unsigned int
#define DATA_SET() HAL_GPIO_WritePin(DATA_GPIO_Port, DATA_Pin, GPIO_PIN_SET) #define DATA_RESET() HAL_GPIO_WritePin(DATA_GPIO_Port, DATA_Pin, GPIO_PIN_RESET)
#define DATA_READ() HAL_GPIO_ReadPin(DATA_GPIO_Port,DATA_Pin)
typedef struct { u8 Data[5]; u8 index; u8 temp; u8 humidity; }DH11_DATA;
extern DH11_DATA DH11_data;
void DH11_Task(void);
#define DATA_Pin GPIO_PIN_15 #define DATA_GPIO_Port GPIOF
#endif
|
实现
1 2 3 4 5 6 7 8
| int main(void) { HAL_TIM_Base_Start(&htim1); while(1) { DH11_Task(); } }
|
2. BH1750光照强度传感器
BH1750.C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include "bh1750.h" #include "i2c.h"
#define bh1750_i2c hi2c1
static uint8_t BH1750_Send_Cmd(BH1750_MODE cmd); static uint8_t BH1750_Read_Dat(uint8_t* dat); static uint16_t BH1750_Dat_To_Lux(uint8_t* dat);
static uint8_t BH1750_Send_Cmd(BH1750_MODE cmd) { return HAL_I2C_Master_Transmit(&bh1750_i2c, BH1750_ADDR_WRITE, (uint8_t*)&cmd, 1, 0xFFFF); }
static uint8_t BH1750_Read_Dat(uint8_t* dat) { return HAL_I2C_Master_Receive(&bh1750_i2c, BH1750_ADDR_READ, dat, 2, 0XFFFF); }
static uint16_t BH1750_Dat_To_Lux(uint8_t* dat) { uint16_t lux = 0; lux = dat[0]; lux <<= 8; lux |= dat[1]; lux = (int)(lux / 1.2); return lux; }
uint16_t Get_BH1750_Value(void) { uint8_t dat[2] = {0}; uint16_t lux;
if(HAL_OK != BH1750_Send_Cmd(ONCE_H_MODE)) { return 0; } HAL_Delay(120); if(HAL_OK != BH1750_Read_Dat(dat)) { return 0; } lux = BH1750_Dat_To_Lux(dat); return lux; }
|
BH1750.H
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #ifndef __BH1750_H_ #define __BH1750_H_
#include "stdint.h"
uint16_t Get_BH1750_Value(void);
#define BH1750_ADDR_WRITE 0x46 #define BH1750_ADDR_READ 0x47
typedef enum { POWER_OFF_CMD = 0x00, POWER_ON_CMD = 0x01, RESET_REGISTER = 0x07, CONT_H_MODE = 0x10, CONT_H_MODE2 = 0x11, CONT_L_MODE = 0x13, ONCE_H_MODE = 0x20, ONCE_H_MODE2 = 0x21, ONCE_L_MODE = 0x23 } BH1750_MODE;
#endif
|
实现
1 2
| int lux; lux = Get_BH1750_Value();
|
3. JW01二氧化碳传感器
采用串口中断与DMA接收数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { uint8_t sum = 0; if(huart -> Instance == USART3) { if(rx_buf[0] == 44){ tvoc = (rx_buf[2]*256+rx_buf[3]) * 0.001; ch2o = (rx_buf[4]*256+rx_buf[5]) * 0.001; co2 = (rx_buf[6]*256+rx_buf[7]); HAL_UART_Receive_DMA((UART_HandleTypeDef *)&huart3, (uint8_t *)rx_buf, 9); } else { HAL_UART_DMAStop((UART_HandleTypeDef *)&huart3); HAL_Delay(10); HAL_UART_Receive_DMA((UART_HandleTypeDef *)&huart3, (uint8_t *)rx_buf, 9); } } }
|