简单的喷淋实验(2):(1)根据土壤湿度自动控制喷淋开关;(2)根据光照强度控制风扇以及灯的开关---嵌入式实训

目录

简单的喷淋实验(2):

(1)根据土壤湿度自动控制喷淋开关;

(2)根据光照强度控制风扇以及灯的开关---嵌入式实训

任务2:

具体过程:

所用的头文件:

data_global.h

mqtt.h

主程序:mian.c

运行结果:

运行过程视频:

上述程序存在问题:

初步破局:

继续探讨:


简单的喷淋实验(2):

(1)根据土壤湿度自动控制喷淋开关;

(2)根据光照强度控制风扇以及灯的开关---嵌入式实训

任务 2

在所给的 irrigate-1 文件夹中创建一个main.c 完成以下内容:

(1)根据土壤湿度自动控制喷淋开关

(2)根据光照强度控制风扇以及灯的开关

参考:

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include "mqtt.h"
#include "parse_config.h"

#define SUB_TOPIC  "1703161172612/AIOTSIM2APP"   //定阅的主题
#define PUB_TOPIC  "1703161172612/APP2AIOTSIM"  //发布主题

#define IRRIGATED_ON "{\"irrigated\":true}"
#define IRRIGATED_OFF "{\"irrigated\":false}"

#define FAN_ON		"{\"fan\":true}"
#define FAN_OFF		"{\"fan\":false}"

#define LAMP_ON		"{\"lamp\":true}"
#define LAMP_OFF		"{\"lamp\":false}"

#define ALARM_ON		"{\"alarm\":true}"
#define ALARM_OFF		"{\"alarm\":false}"

int main(int argc, const char *argv[])
{
	ENV msg_env={};
	//1.初始化mqtt协议
	if(mqtt_init()!=0)
	{
		printf("mqtt init err.\n");
		return -1;
	}
	//订阅别人发布的消息
	if(mqtt_subscribe(SUB_TOPIC) < 0)
	{
		printf("sub err.\n");
		return -1;
	}
	//循环获取温湿度
	//当大于阈值关闭灌溉,小于就打开
	while(1)
	{
		sleep(1);
		//获取值
		msg_env=get_virtual_env();

		if(msg_env.ill < 20000)
		{
			mqtt_publish(PUB_TOPIC,FAN_OFF);
			mqtt_publish(PUB_TOPIC,LAMP_ON);
		}else if(msg_env.ill > 50000)
		{
			mqtt_publish(PUB_TOPIC,FAN_ON);
			mqtt_publish(PUB_TOPIC,LAMP_OFF);
		}
		printf("ill:%f\n",msg_env.ill);


		if(msg_env.soil < 30)
		{
			mqtt_publish(PUB_TOPIC,IRRIGATED_ON);
		}else if(msg_env.soil > 50)
		{
			mqtt_publish(PUB_TOPIC,IRRIGATED_OFF);
		}
		printf("soilhum:%f\n",msg_env.soil);

		// if(msg_env.infrared == 1)
		// {
		// 	mqtt_publish(PUB_TOPIC,ALARM_ON);
		// }else {
		// 	mqtt_publish(PUB_TOPIC,ALARM_OFF);
		// }
		// printf("infrared:%d\n",msg_env.infrared);

	}
	exit_mqtt();
	return 0;
}

具体过程:

所用的头文件:
data_global.h
cpp 复制代码
#ifndef __DATA_GLOBAL__H__
#define __DATA_GLOBAL__H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <time.h>
#include <termios.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
struct env_info
{
	float soil;  //土壤湿度
	float light; //光照强度
	float temp;   //空气温度
	uint8_t gas;    //有害气体
};

extern struct env_info env_msg;

//设备编号
#define FAN  0x00
#define BEEP 0x10
#define LED  0x20
#define PUMP 0X30

#define DATA_ARRIVE SIGUSR1 //数据到达信号


//订阅、发布主题
#define ENV_PUB_TOPIC "FS_VRJJ/control"

//虚拟仿真硬件协议
#define LAMP_ON    "{\"lamp\":true}"
#define LAMP_OFF   "{\"lamp\":false}"

#define ALARM_ON   "{\"alarm\":true}"
#define ALARM_OFF  "{\"alarm\":false}"

#define SUNSHADE_FOR "{\"sunshade\":\"forward\"}"
#define SUNSHADE_REV	"{\"sunshade\":\"reverse\"}"
#define SUNSHADE_STOP	"{\"sunshade\":\"stop\"}"

#define VIR_FAN_ON	"{\"fan\":true}"
#define VIR_FAN_OFF "{\"fan\":false}"

#define IRRIGATED_OFF "{\"irrigated\":false}"
#define IRRIGATED_ON "{\"irrigated\":true}"
#endif
mqtt.h
cpp 复制代码
#ifndef __MQTT_SMART_H_
#define __MQTT_SMART_H_


typedef struct env
{
	float soil;//土壤湿度
	float ill;//光照
	int smog;//烟雾
	int infrared;//人体红外
}ENV;
int mqtt_init();
void exit_mqtt();
int mqtt_subscribe(const char*topic);
int mqtt_publish(const char *topic, char *msg);
ENV get_virtual_env();

#endif
主程序:mian.c
cpp 复制代码
#include<stdio.h>
#include"mqtt.h"
#include<unistd.h>
#include"data_global.h"
 
#define subscribe "1703503856299/AIOTSIM2APP"
#define publish "1703503856299/APP2AIOTSIM"
int main(int argc, char *argv[]){
    //1-连接服务器
    mqtt_init();
 
    //2-订阅元宇宙平台主题,获得数据串
        //通过目标节点的发布主题,才能的得到发布的内容
    mqtt_subscribe(subscribe);

 
    //4.循环获取数据,下发控制指令
    while (1){
        sleep(1);
        ENV env= get_virtual_env();
        if (env.soil>60){
            mqtt_publish(publish, IRRIGATED_OFF);
            printf("关闭喷淋。。。。\n");
        }
        else if (env.soil<30){
            mqtt_publish(publish, IRRIGATED_ON);
            printf("打开喷淋\n");
        }

        printf("当前土壤湿度:%.2f\n", env.soil);

        if (env.ill>27000)
        {
            mqtt_publish(publish, VIR_FAN_ON);
            mqtt_publish(publish,  LAMP_OFF);
            printf("打开风扇,关闭灯。。。。\n");
        }
        else if (env.ill<25000)
        {
            mqtt_publish(publish,  VIR_FAN_OFF);
            mqtt_publish(publish,  LAMP_ON);
            printf("关闭风扇,打开灯。。。。。。\n");
        }
        
        sleep(1);
        printf("当前光照强度:%.2f\n", env.ill);
        printf("++++++++++++++++++++++++++++\n");
    }
    exit_mqtt();
    return 0;
}
运行结果:

元宇宙未运行时:

元宇宙运行后:

运行过程视频:

嵌入式实训2023-12-25 20-19-53


上述程序存在问题:

初步破局:

在元宇宙实验平台还没开始运行时,各种数据都是0,就会导致程序通过if、else if判断语句来控制各种机器运作,这是不正确的。为了避免这种情况,可以添加一些额外的判断来解决这个问题。

首先,我们可以在while循环之前添加一个延时等待,让实验平台有足够的时间来获取和发送数据。例如,我们可以使用sleep函数来等待5秒钟:

cpp 复制代码
sleep(5); // 等待5秒钟,让实验平台有足够的时间来获取和发送数据

然后,我们可以在if、else if判断语句之前添加一个判断,检查所需的数据是否已经被正确地获取。例如,我们可以检查土壤湿度是否为0来确定是否成功获取了土壤湿度数据:

cpp 复制代码
ENV env= get_virtual_env();
if (env.soil == 0) {
    printf("未成功获取到土壤湿度数据,等待下一次获取...\n");
    sleep(1);
    continue; // 跳过本次循环,等待下一次循环
}

// 在此之后添加if、else if判断语句进行控制

同样,我们可以添加类似的判断来检查光照强度等数据是否已经被正确获取。这样做可以避免在数据未准备好时误操作机器,保证程序的正确性。

完整代码:

cpp 复制代码
#include<stdio.h>
#include"mqtt.h"
#include<unistd.h>
#include"data_global.h"
 
#define subscribe "1703503856299/AIOTSIM2APP"
#define publish "1703503856299/APP2AIOTSIM"
int main(int argc, char *argv[]){
    //1-连接服务器
    mqtt_init();
 
    //2-订阅元宇宙平台主题,获得数据串
        //通过目标节点的发布主题,才能的得到发布的内容
    mqtt_subscribe(subscribe);

    //3.等待数据准备就绪
    printf("等待数据准备就绪...\n");
    sleep(5); // 等待5秒钟,让实验平台有足够的时间来获取和发送数据

    //4.循环获取数据,下发控制指令
    while (1){
        ENV env= get_virtual_env();
        if (env.soil == 0) {
            printf("未成功获取到土壤湿度数据,等待下一次获取...\n");
            sleep(1);
            continue; // 跳过本次循环,等待下一次循环
        }

        if (env.soil>60){
            mqtt_publish(publish, IRRIGATED_OFF);
            printf("关闭喷淋。。。。\n");
        }
        else if (env.soil<30){
            mqtt_publish(publish, IRRIGATED_ON);
            printf("打开喷淋\n");
        }

        printf("当前土壤湿度:%.2f\n", env.soil);

        if (env.ill == 0) {
            printf("未成功获取到光照强度数据,等待下一次获取...\n");
            sleep(1);
            continue; // 跳过本次循环,等待下一次循环
        }

        if (env.ill>27000)
        {
            mqtt_publish(publish, VIR_FAN_ON);
            mqtt_publish(publish,  LAMP_OFF);
            printf("打开风扇,关闭灯。。。。\n");
        }
        else if (env.ill<25000)
        {
            mqtt_publish(publish,  VIR_FAN_OFF);
            mqtt_publish(publish,  LAMP_ON);
            printf("关闭风扇,打开灯。。。。。。\n");
        }
        
        printf("当前光照强度:%.2f\n", env.ill);
        printf("++++++++++++++++++++++++++++\n");
        sleep(1);
    }

    exit_mqtt();
    return 0;
}

继续探讨:

还是有点问题,如果等待5秒后,实验平台运行了,但是土壤湿度和光照强度又恰好是0呢?这样是没有错误的呀

上述提出了一个很好的问题。确实,在等待5秒后,如果土壤湿度和光照强度仍然是0,那么程序就会继续执行,而不会等待数据准备就绪。为了解决这个问题,可以使用一个循环来判断数据是否已经准备就绪,并设置一个最大等待时间。

下面是修改后的代码示例:

cpp 复制代码
#include<stdio.h>
#include"mqtt.h"
#include<unistd.h>
#include"data_global.h"
 
#define subscribe "1703503856299/AIOTSIM2APP"
#define publish "1703503856299/APP2AIOTSIM"
int main(int argc, char *argv[]){
    //1.连接服务器
    mqtt_init();
 
    //2.订阅元宇宙平台主题,获得数据串
    //通过目标节点的发布主题,才能的得到发布的内容
    mqtt_subscribe(subscribe);

    //3.等待数据准备就绪
    printf("等待数据准备就绪...\n");
    int max_wait_time = 10; // 最大等待时间为10秒
    int wait_time = 0; // 已等待的时间
    ENV env;
    while (1){
        env= get_virtual_env();
        if (env.soil != 0 && env.ill != 0) {
            break; // 数据已准备就绪,跳出循环
        }

        sleep(1);
        wait_time++;
        if(wait_time >= max_wait_time){
            printf("超过最大等待时间,未成功获取到数据!\n");
            exit_mqtt();
            return 0;
        }
    }

    //4.循环获取数据,下发控制指令
    while (1){
        if (env.soil>60){
            mqtt_publish(publish, IRRIGATED_OFF);
            printf("关闭喷淋。。。。\n");
        }
        else if (env.soil<30){
            mqtt_publish(publish, IRRIGATED_ON);
            printf("打开喷淋\n");
        }

        printf("当前土壤湿度:%.2f\n", env.soil);

        if (env.ill>27000)
        {
            mqtt_publish(publish, VIR_FAN_ON);
            mqtt_publish(publish,  LAMP_OFF);
            printf("打开风扇,关闭灯。。。。\n");
        }
        else if (env.ill<25000)
        {
            mqtt_publish(publish,  VIR_FAN_OFF);
            mqtt_publish(publish,  LAMP_ON);
            printf("关闭风扇,打开灯。。。。。。\n");
        }
        
        printf("当前光照强度:%.2f\n", env.ill);
        printf("++++++++++++++++++++++++++++\n");
        sleep(1);
    }

    exit_mqtt();
    return 0;
}
相关推荐
小菜鸟学代码··4 分钟前
STM32文件详解
stm32·单片机·嵌入式硬件
88号技师34 分钟前
2024年12月一区SCI-加权平均优化算法Weighted average algorithm-附Matlab免费代码
人工智能·算法·matlab·优化算法
IT猿手35 分钟前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab
88号技师35 分钟前
几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
开发语言·人工智能·算法·matlab·优化算法
一只小bit39 分钟前
数据结构之栈,队列,树
c语言·开发语言·数据结构·c++
马浩同学1 小时前
【GD32】从零开始学GD32单片机 | DAC数模转换器 + 三角波输出例程
c语言·单片机·嵌入式硬件·mcu
我要学编程(ಥ_ಥ)1 小时前
一文详解“二叉树中的深搜“在算法中的应用
java·数据结构·算法·leetcode·深度优先
埃菲尔铁塔_CV算法1 小时前
FTT变换Matlab代码解释及应用场景
算法
沐泽Mu2 小时前
嵌入式学习-QT-Day05
开发语言·c++·qt·学习
许野平2 小时前
Rust: enum 和 i32 的区别和互换
python·算法·rust·enum·i32