stm32室内环境监测系统程序(项目分享DIYSTM32植物监测系统)
stm32室内环境监测系统程序(项目分享DIYSTM32植物监测系统)3)DHT22温度传感器2)Sigfox TD1208R项目需要的知识储备系统的硬件组成部分1)主控:STM32 L432开发板
疫情让很多人成为园艺大师,在家种上了蔬菜。如何科学规范的种植呢?今天分享的就是一套近乎0基础就可以实现的植物监测系统。
系统功能
监控包括:
- 空气/土壤水分
- 空气/土壤温度
- 亮度(包括RGB 光线)
附加的功能:
还可以发送本地化信息,从而提供天气预报。为监控系统创建了一个Twitter帐户。使用 Sigfox 发送的每条消息也作为推文发送。
项目需要的知识储备
- 微控制器编程
- 如何阅读数据表并提取最重要的数据
- I2C、SPI、UART、CRC 协议
- 如何使用 Sigfox 发送数据(Sigfox 无线技术是低功耗广域网 (LPWAN) 技术):
- 1)AT 命令
- 2)每天可以发送多少条消息?
- 3)如何构建消息?(JSON 语言)
系统的硬件组成部分
1)主控:STM32 L432开发板
2)Sigfox TD1208R
3)DHT22温度传感器
4)Seeed Studio Grove 湿度传感器
5)Adafruit TSL2561 照度传感器
6)Adafruit TCS34725 RGB 颜色传感器
7)Seeed Studio Grove DS18B20 温度传感器
8)Adafruit 单色 0.96" 128x64 OLED 图形显示器
9)USB Micro-B 连接器分线板
系统设计步骤
1. 对项目使用的所有引脚进行映射
2. 对微控制器 STM32 NUCLEO-L432KC 进行编程
- 从传感器获取数据
- 使用 Sigfox 转换发送数据
- 在 OLED 屏幕上显示数据
- 配置 Sigfox 模块不发送消息时微控制器的睡眠模式
3. 配置仪表板,将显示所有检索到的数据
- 创建图表
- 将数据保存在数据库中
- 使用此数据显示天气预报
- 配置 Twitter 和邮件
- CSV 报告(每周、每月和每半年)
- 如果有多个Sigfox模块,创建一个下拉列表以允许最终用户过滤数据以显示
使用哪些引脚?
项目有 5 个传感器可供使用,它们的连接通信方式不同。阅读 NUCLEO L432KC 的数据表可以对要使用的引脚进行分类。
下图为项目定义的映射:
点击可放大
嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!
无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。
点击这里找小助理0元领取嵌入式物联网学习资料(头条)
软件代码编写
要使用的头文件:
#include "mbed.h"
#include "DS18B20.h"
#include "DHT.h"
#include "TSL2561.h"
#include "Adafruit_SSD1306.h"
#include "WakeUp.h"
在mapping.h 文件中,根据需要注释/取消注释以下行:
// Uncomment line to enable the focused object/sensor :
#define OLED_ACTIF
#define SIGFOX_ACTIF
#define I2C_ACTIF
#define DEBUG_UART_ACTIF
#define DHT_ACTIF
#define GROVE_MOIST_ACTIF
#define ONEWIRE_TEMP_ACTIF
#define LUX_ACTIF
#define RGB_ACTIF
#define BATTERIE_ACTIF
对于高级用户,可以在此文件中修改其他参数,例如:
- 传感器校准
- 引脚分配
- 测量精度
- 计时
main初始化:
/*********************************
Initialisation
*********************************/
#ifdef BATTERIE_ACTIF
float BATTERIE_MIN = 33;
float BATTERIE_MAX = 42;
#endif
#ifdef OLED_ACTIF
// Initialisation de l'écran
OLED.fillRect(0 0 LARGEUR_OLED HAUTEUR_OLED BLACK);
OLED.setTextCursor(0 10); OLED.printf("===================");
OLED.setTextCursor(0 20); OLED.printf(" PlantSigfox ");
OLED.setTextCursor(0 30); OLED.printf(" Projet ei2i-4 ");
OLED.setTextCursor(0 40); OLED.printf("Jeanne Anais Thomas");
OLED.setTextCursor(0 50); OLED.printf("===================");
OLED.display();
#endif
#ifdef DEBUG_UART_ACTIF
// Initialisation des communications UART
pc.format(8 SerialBase::None 1);
pc.baud(9600);
#endif
#ifdef SIGFOX_ACTIF
Sigfox.format(8 SerialBase::None 1);
Sigfox.baud(9600);
#endif
#ifdef ONEWIRE_TEMP_ACTIF
// Initialisation du capteur de température
while (!Temperature.initialize()); // on attend que le capteur soit initialisé avant de pouvoir effectuer des mesures
#endif
#ifdef RGB_ACTIF
// Initialisation du TCS34725
rgb.init_RGB();
#endif
// Attente de 5 secondes avant le démarrage du programme
wait(5);
主循环分为 3 个部分:
1 - 获取方法和数据处理:
为了使测量点更可靠,每个点对应于一段时间内的测量平均值(在 Mapping.h 中定义)。
/*********************************
Mesure des ADC
*********************************/
// On effectue une moyenne sur une quantité de relevés ( pour avoir une mesure fiable )
#if defined(GROVE_MOIST_ACTIF) || defined(BATTERIE_ACTIF)
Niveau_Batterie = 0;
HumidSol = 0;
for (i=0; i < NB_MESURES; i )
{
#ifdef BATTERIE_ACTIF
// Batterie
VBAT = 100 * Batterie; // Lecture de l'entrée ADC
Niveau_Batterie = ((VBAT - BATTERIE_MIN) / (BATTERIE_MAX - BATTERIE_MIN)) * 100 ;
#endif
#ifdef GROVE_MOIST_ACTIF
// Humidité du Sol (Grove)
HumidSol = ((Capteur_Moisture - GROVE_MOIST_MIN) / (GROVE_MOIST_MAX - GROVE_MOIST_MIN)) * 100;
#endif
wait(TEMPS_MESURE);
}
#endif
// Moyennage du résultat
#ifdef GROVE_MOIST_ACTIF
HumidSol /= NB_MESURES;
#endif
#ifdef BATTERIE_ACTIF
Niveau_Batterie /= NB_MESURES;
// Limitation de la batterie
if (Niveau_Batterie >100) Niveau_Batterie = 100;
// Si la batterie est déconnectée on doit le faire remarquer (code : 101)
if (Niveau_Batterie < 0) Niveau_Batterie = 101;
#endif
/*********************************
Température du sol (OneWIRE)
*********************************/
#ifdef ONEWIRE_TEMP_ACTIF
Temperature.setResolution(twelveBit); // Le choix de la résolution se fait avant le relevé des données
TempSol = Temperature.readTemperature(); // relevé de données
#endif
/*********************************
Température/Humidité Air (Grove)
*********************************/
#ifdef DHT_ACTIF
int err;
wait(1); // wait 1 second for device stable status
do
{
err = sensor.readData();
wait(1);
}
while (err != 0);
if (err == 0)
{
TempAir = sensor.ReadTemperature(CELCIUS);
HumidAir = sensor.ReadHumidity();
}
#endif
/*********************************
Luminosité / RGB(Adafruit)
*********************************/
#ifdef LUX_ACTIF
Lumiere = COEF_LUX * lum.lux();
#endif
#ifdef RGB_ACTIF
rgb.GET_RGB(&Clear &Red &Green &Blue);
#ifdef RGB_1_OCTET
// On réduit la précision des données brutes en divisant par 256 pour n'avoir qu'un octet seulement
Clear /= 256;
Red /= 256;
Green /= 256;
Blue /= 256;
#endif
#endif
2 - 显示和发送数据:
数据显示在 OLED 屏幕上,并通过 Sigfox 模块作为帧发送到云端。
/*********************************
Affichage OLED
*********************************/
#ifdef OLED_ACTIF
// OLED Reset
OLED.fillRect(0 0 LARGEUR_OLED HAUTEUR_OLED BLACK);
line = 0;
// Sol :
#if defined(GROVE_MOIST_ACTIF) && defined(ONEWIRE_TEMP_ACTIF)
OLED.setTextCursor(0 line);
OLED.printf("Sol = %d \tC // %d \t/\t" (int)TempSol (int)HumidSol);
line =10;
#endif
// Air :
#ifdef DHT_ACTIF
OLED.setTextCursor(0 line);
OLED.printf("Air = %d \tC // %d \t/\t" (int)TempAir (int)HumidAir);
line =10;
#endif
// Intensité lumineuse
#if defined(LUX_ACTIF) && defined(I2C_ACTIF)
OLED.setTextCursor(0 line);
OLED.printf("Light = %d" (int)Lumiere);
OLED.setTextCursor(110 line);
OLED.printf("Lux");
line =10;
#endif
// Couleurs RGB
#if defined(RGB_ACTIF) && defined(I2C_ACTIF)
OLED.setTextCursor(0 line);
OLED.printf("RGB = %d/%d/%d" Red Green Blue);
line =10;
OLED.setTextCursor(0 line);
OLED.printf("Clear = %d" Clear);
line =10;
#endif
// Batterie
#ifdef BATTERIE_ACTIF
OLED.setTextCursor(0 line);
if (((int)Niveau_Batterie >= 0) && ((int)Niveau_Batterie <= 100))
{
OLED.printf("Batterie : %d" (int)Niveau_Batterie);
OLED.setTextCursor(110 line);
OLED.printf("\t/\t");
}
else
{
OLED.printf("Prise Secteur");
}
#endif
// Display
OLED.display();
#endif
/****************************************************************************
Envoi des données via le module Sigfox (dépend du format des données)
*****************************************************************************/
#ifdef SIGFOX_ACTIF
#if defined(RGB_2_OCTET) && !defined(RGB_1_OCTET)
// trame 1 : [T°Air Hum Air T°Sol Hum Sol Lumiere Batterie]
Sigfox.printf("AT$SS=x x x x x x \r\n" (int)TempAir (int)HumidAir (int)TempSol (int)HumidSol (int)Lumiere (int)Niveau_Batterie);
// trame 2 : [Clear Red Green Blue]
Sigfox.printf("AT$SS=x x x x \r\n" Clear Red Green Blue);
#endif
#if defined(RGB_1_OCTET) && !defined(RGB_2_OCTET)
// trame : [T°Air Hum Air T°Sol Hum Sol Lumiere Batterie Clear Red Green Blue]
Sigfox.printf("AT$SS=x x x x x x x x x x \r\n" (int)TempAir (int)HumidAir (int)TempSol (int)HumidSol (int)Lumiere (int)Niveau_Batterie Clear Red Green Blue);
#endif
#endif
// Envoi des données sur le debug UART (optionnel)
#ifdef DEBUG_UART_ACTIF
#if defined(RGB_2_OCTET) && !defined(RGB_1_OCTET)
// trame 1 : [T°Air Hum Air T°Sol Hum Sol Lumiere Batterie]
pc.printf("AT$SS=x x x x x x \r\n" (int)TempAir (int)HumidAir (int)TempSol (int)HumidSol (int)Lumiere (int)Niveau_Batterie);
// trame 2 : [Clear Red Green Blue]
pc.printf("AT$SS=x x x x \r\n" Clear Red Green Blue);
#endif
#if defined(RGB_1_OCTET) && !defined(RGB_2_OCTET)
// trame : [T°Air Hum Air T°Sol Hum Sol Lumiere Batterie Clear Red Green Blue]
pc.printf("AT$SS=x x x x x x x x x x \r\n" (int)TempAir (int)HumidAir (int)TempSol (int)HumidSol (int)Lumiere (int)Niveau_Batterie Clear Red Green Blue);
#endif
#endif
3 - 待机:
微控制器进入待机模式以限制其空闲时间的消耗:
/*********************************
Mise en veille de l'appareil
*********************************/
#if defined(OLED_ACTIF) && defined(OLED_VEILLE)
// Test : éteindre l'écran au bout d'un temps donné
wait (DUREE_AFFICHAGE);
OLED.fillRect(0 0 LARGEUR_OLED HAUTEUR_OLED BLACK);
OLED.display();
WakeUp::set_ms((TEMPS_RELEVE-DUREE_AFFICHAGE)* 1000);
deepsleep();
#else
WakeUp::set_ms(TEMPS_RELEVE * 1000);
deepsleep();
#endif
注意:整个代码依赖于 Mapping.h 文件中的配置
PCB焊接
硬件组件接线整体示意图:
太阳能电池的制作:
外壳及封装:
此项目来自hackster.io,制作者是Team PlantSigfox EI2I4: Thomas Broussard Jeanne Baumier Anaïs Auberval
END
转载自:达尔闻说
文章来源于项目分享| DIY STM32植物监测系统,园艺大师指日可待
原文链接:https://mp.weixin.qq.com/s/5D1ZhbEw27goCkPp4u0ALQ