计算机设计大赛

目录

1.1需求分析

2.1概要设计

3.1软件界面设计:

4.1代码开源

  • 1.1需求分析

1.1  产品开发本说明:

     在如今每人都会扔出许多垃圾,在一些地方大部分垃圾能得到卫生填埋、焚烧等无害化处理,而更多的垃圾则是简单的掩埋,长期下去导致臭气蔓延,并且污染土壤和地下水。因为垃圾无害化处理的费用是非常高的,但若采用垃圾分类的方式管理垃圾,我们可以管理废物和回收物,减少占地、减少环境污染、变废为宝。有利于我国城镇化质量和生态文明建设的水平进一步提高。

1.2面向用户:

面向社区以及我们的各种景区的人平时产生生活垃圾和可回收垃圾的人群。

面向企业进行海量管理。

1.3主要性能和功能:

本产品具有垃圾识别、卡片识别、分类显示、安全控制、积分奖励,海量管理六大功能,性能较高,容错率高,可优化其能力。

1.4竞品分析:

产品名称

外观

优势

劣势

核心功能

脚踏式室外大号垃圾分类桶

能够一次性装入大量的垃圾,节省了时间对环境有防臭功能

体型太大,占用空间,是脚踏式的不够方便

垃圾分类

EKO感应垃圾桶

体型小、能够感应式的丢垃圾

不能够做到垃圾分类

智能感应

积分兑换-智能化的垃圾分类

能够达到垃圾自主分类的效果,智能控制,有积分奖励模式,海量管理

体型较小不能做到大型垃圾的处理

积分奖励

智能控制

垃圾分类

                         表1.4竞品分析情况

  • 2.1概要设计

    当前处于移动互联网的时代,本产品是基于Arduino的垃圾分类。实现对各个垃圾的分类和积分统计。

    

                           图2.1  总体设计流程图

  1. 本产品通过Arduino与各种传感器相结合和控制,实现了对垃圾桶是否装满和安全隐患防护的功能。
  2. MEGA2560板加入了超声波模块来对垃圾进行检测,从而判定是否溢出来定时进行垃圾的清理,一个火焰传感器对周围火焰进行检测报警,一个可燃气体传感器检测垃圾桶内部气体进行报警,蜂鸣器用于对火焰和可燃气体的检测进行报警,一个舵机模块加入舵机模块进行刷卡认证,并且把卡号发送给屏幕
  3. Esp8266板加入了一个温度传感器,一个压缩干,温度传感器的数值会通过该板同步上传到云平台,同理我们的mega2560板也会把数据通过串口发送到esp8266板进行数据上传,当检测到垃圾桶容量满了的时候可开关进行垃圾压缩。
  4. K210板通过摄像头对垃圾进行识别分类将垃圾投入垃圾桶,并且把收入的垃圾信息发送到屏幕。
  5. 串口屏实时显示用户刷卡后的ID,在投入垃圾后会语言播报垃圾种类,并且显示当前积分和用户排行榜
  • 详细设计

3.1软件界面设计:

                           图3.1-1实物作品软件设计界面

                          图3.1-2 APP前端积极奖励兑换界面

3.2技术创新:

  1. 本品使用了Arduino IDE软件编程,在mega2560开发板中加入esp8266wifi模块,将传感器所取的信息数据传入开发板,并通过云平台来实现信息的显示。如:为了解决垃圾的防火、防臭,火焰传感器可通过检测烟火焰将信息传给工作人员,超声波实时检测垃圾桶的余量并防止溢出,空气质量传感器通过mega2560开发板将数据传给wifi模块,来防止有害气体。温度传感器当温度过高时发给wifi设备让工作人员清楚的知道情况。
  2. 为了让广大市民提高垃圾分类的积极性,加入了积分奖励这一方面,通过mega2560让RFID板块,通过刷卡录入,将数据信息放在RFID模块库,当用户投入可回收垃圾时,k210发送串口从而达到用户的积极记录,并利用了串口屏将积分信息、垃圾满出度、实时时间正确的显示出来,更好的方便管理,在无人投放垃圾时进行垃圾宣传片播放。
  3. 设计了一个积极奖励兑换商城,通过扫描二维码打开微信小程序,可以看到里面的商品和兑换所需的积分数量,这样大大提高了市民的垃圾分类积极性,让垃圾分类观念更加普及。

                      图3.3制作作品利用的函数库

3.4组件结构:

超声波:检测是否满,以及实时监测垃圾桶的余量

可燃气体传感器:垃圾桶内环境气体是否异常

火焰传感器:通过传感器来判断,垃圾桶是否产生了火焰,来保护防火安全

温度传感器:检测垃圾桶内的温度,防止温度过高,造成异常

压缩杆:对满载垃圾进行压缩处理

舵机:对满载垃圾进行打包处理,方便卫生。

串口屏:实现时间实时显示,积分显示,垃圾种类显示,用户ID、排行榜显示

RFID模块:采集用户的数据信息,和积分与云平台同步。

喇叭:实现语音播报的情况

云台:实现自主分类垃圾

  • 测试报告

4.1产品测试报告:

产品名称:

基于云平台的智慧城域垃圾分类装置

产品型号:

1.0 版本

测试概述:

产品的安全性,稳定性

测试数量:

1 台

测试环境:

室外

测试时间:

2024 年5月3日

测试项目:

各传感器的信号采集,k210的稳定性,mega2560信息的输入度,积分奖励App平台,屏幕显示准确性,wifi模块稳定性。

测试条件:

在电源充足的情况下,刷卡投入垃圾,用户自己近距离丢垃圾的情况。

测试方法/过程:

  1. 认证测试:用户进行刷卡认证,屏幕显示用户id并根据垃圾给定积分
  2. 安全测试:放入烟头或高温物来检测火焰和温度传感器的数据传递,并判断反应度和安全性
  3. 进行不断的测试和记录,多次进行优化调整。

   

测试结果:

   产品能够通过wifi模块来上传各种信息,投入对应的可回收垃圾,k210能够反馈数据到串口屏幕,刷卡认证后舵机能准确转动给予响应,k210控制四个舵机能够准确识别投放垃圾,屏幕能够准确播报垃圾种类,显示积分,压缩干能正常运作并进行压缩

结论/建议:

   产品整体性能较好,智能化的程度较高,建议改善空间大小,以便更多的投入垃圾,让垃圾分类进行的更好

4.2硬件与效果测试报告:

测试项目

技术要求

测试结果

判定情况

1

K210摄像头

是否准确识别垃圾

良好

2

串口屏

是否准确显示积分,垃圾种类,语音播报

良好

3

RFID模块

是否准确检测用户的id

良好

4

蜂鸣器模块

是否准确报警提示

良好

5

超声波板

是否实时检测垃圾余量

良好

6

Esp8266wifi模块

是否准确上传数据

良好

7

可燃气体传感器

是否测出气体的环境

良好

8

火焰传感器

是否检测火焰产生情况

良好

9

Mega2560

是否准确控制传感器,RFID

良好

10

温度传感器

是否能够对高温进行反馈

良好

11

K210

是否准确控制舵机

良好

12

L298N

是否准确控制压缩干

良好

4.3技术指标:

       测试次数

测试名称

第一次

第二次

第三次

第四次

运行速度

中等

中等

较快

安全性

中等

较好

扩展性

较好

中等

部署方便性

较好

可用性

中等

较高

  • 安装及使用

5.1安装环境要求:

thingscloud物联网平台使用微信小程序扫描二维码即可:

         

5.2RFID模块安装:

  • 项目总结

6.1项目协调:

在制作产品的过程,对材料购入、市场调查、代码编写、创新想法、程序加入等方面,进行了明确的分工。

6.2任务分解:

任务一:压缩杆的控制,当垃圾容量到达一定值自动压缩垃圾

任务二:RFID实现锁定人物ID功能,发送串口给屏幕显示ID,屏幕实时显示ID,语音播报垃圾种类,实时显示积分

任务三:超声波模块检测垃圾桶满,温度传感器发现温度过高,有害气体传感器异常,火焰传感器发现有火,垃圾桶满载均会通过wifi模块发送信息到手机,超声波模块与串口屏实时显示垃圾桶的余量

6.3后续升级:

基于图像识别的垃圾分类,以及对积分的具体应用,创建一个根据用户所扔的垃圾来了解用户的饮食情况从而来给出合理有效的饮食方案。

6.4商业推广: 

垃圾分类与旁边的超市进行联合起来,将积分用于兑换物品接着再创建网上兑换商城

4.1代码开源

注:此作品由工训赛改进而来 原作品链接(开源)2023工训大赛智能垃圾分类项目(可循环播放视频,显示垃圾分类信息,拍照识别,垃圾分类,满载报警,压缩)_工程训练大赛垃圾分类项目-CSDN博客

k210总代码:     使用亚博K210开发板

#2023 10 15 派大星改
# object classifier boot.py
# generated by maixhub.com
from fpioa_manager import *
from modules import ultrasonic
from fpioa_manager import fm
from Maix import GPIO
import math
import struct
import sensor, image, lcd, time
import KPU as kpu
import gc, sys
from Maix import GPIO
from machine import UART
from machine import Timer,PWM
#
#
i= 8
# 定义超声波传感器的触发引脚和回响引脚
trig_pin = 0
echo_pin = 1
 
#控制串口通信
board_info_tx=15
board_info_rx=17
# 将GPIO口初始化为输入/输出模式
fm.register(trig_pin, fm.fpioa.GPIO0)
fm.register(echo_pin, fm.fpioa.GPIO1)
trig = GPIO(GPIO.GPIO0, GPIO.OUT)
echo = GPIO(GPIO.GPIO1, GPIO.IN)
tim = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM)               #控制2个云台舵机
S1 = PWM(tim, freq=50, duty=0, pin=21)
tim = Timer(Timer.TIMER1, Timer.CHANNEL0, mode=Timer.MODE_PWM)
S2 = PWM(tim, freq=50, duty=0, pin=23)
 
value = 0xFF
s = struct.pack('B', value)
list_of_values = [255]*3
s = struct.pack('3B', *list_of_values)                                       #串口通信结束符
 
fm.register(board_info_tx,fm.fpioa.UART1_TX,force=True)
fm.register(board_info_rx,fm.fpioa.UART1_RX,force=True)
uart_A = UART(UART.UART1, 115200, 8, None, 1, timeout=1000, read_buf_len=4096)
#uart_A = UART(UART.UART1, 115200,read_buf_len=4096)
 
 
def Servo_1(servo,angle):
    S1.duty((angle+90)/180*10+2.5)              #竖直舵机
def Servo_2(servo,angle):
    S2.duty((angle+90)/270*10+2.5)              #水平舵机
#超声波
def measure_distance():
    trig.value(0) # 发送触发信号
    time.sleep_ms(2)
    trig.value(1)
    time.sleep_us(10)
    trig.value(0)
    start_time = time.ticks_ms()
    while echo.value() == 0 and time.ticks_diff(time.ticks_ms(), start_time) < 3000:
        pass
 
    # 如果等待超时,返回错误代码 -1
    if time.ticks_diff(time.ticks_ms(), start_time) >= 3000:
        print("Error: no echo received!")
        return -1
 
    # 记录回响信号的时间戳
    t1 = time.ticks_us()
    while echo.value() == 1:
        pass
    t2 = time.ticks_us()
 
    print(t2)
    # 计算距离(单位:厘米)
    duration = t2 - t1
    distance = duration * 0.017
    print(distance)
    if distance < 15:                                 #距离判断
       write_str = ("t20.bco=63488")
       uart_A.write(write_str)
       print("满载")
       uart_A.write(s)
    else:
       write_str = ("t20.bco=34784")
       uart_A.write(write_str)
       print("未满载")
       uart_A.write(s)
    return
 
 
 
 
 
 
def lcd_show_except(e):
    import uio
    err_str = uio.StringIO()
    sys.print_exception(e, err_str)
    err_str = err_str.getvalue()
    img = image.Image(size=(224,224))
    img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
    lcd.display(img)
 #开机启动
 ########################################################################################################################
def main(labels = None, model_addr="/sd/m.kmodel", sensor_window=(224, 224), lcd_rotation=0, sensor_hmirror=False, sensor_vflip=False):
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing(sensor_window)
    sensor.set_hmirror(sensor_hmirror)
    sensor.set_vflip(sensor_vflip)
    sensor.run(1)
 
    lcd.init(type=1,invert=1)        #小LCD屏幕
    lcd.rotation(lcd_rotation)
    lcd.clear(lcd.WHITE)
    if not labels:
        with open('labels.txt','r') as f:
            exec(f.read())
    if not labels:
        print("no labels.txt")
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "no labels.txt", color=(255, 0, 0), scale=2)
        lcd.display(img)
        return 1
    try:
        img = image.Image("startup.jpg")
        lcd.display(img)
    except Exception:
        img = image.Image(size=(320, 240))
        img.draw_string(90, 110, "loading model...", color=(255, 255, 255), scale=2)
        lcd.display(img)
    task = kpu.load(model_addr)
    try:
####################################循环######################################################################################
        a= 0
        while(a<3):
            print("启动")
            write_str = ("page main")           #跳到计数主屏幕
            uart_A.write(write_str)
            uart_A.write(s)
            print(write_str)
            a+=1
 
 
        while(True):
            Servo_1(S1, i)
            Servo_2(S2, 0)
            time.sleep_ms(500)
            measure_distance()                 #满载检查
            print("满载jianche ")
            write_str = ("n5.val=0")           #初始化串口屏幕
            uart_A.write(write_str)
            uart_A.write(s)
            print(write_str)
            while(True):
 
                img = sensor.snapshot()
                t = time.ticks_ms()
                fmap = kpu.forward(task, img)
                t = time.ticks_ms() - t
                plist=fmap[:]
                pmax=max(plist)                      #判断最大置信度
                if pmax < 0.4:                       #检测空物品
                    empty_str = "Not subject"
                    img.draw_string(0, 0, empty_str, scale=2)
                    lcd.display(img)
                    Servo_1(S1, i)
                    Servo_2(S2, 0)
                    break
                max_index=plist.index(pmax)
                img.draw_string(0,0, "%.2f : %s" %(pmax, labels[max_index].strip()), scale=2)
                img.draw_string(0, 200, "t:%dms" %(t), scale=2)
                lcd.display(img)
 
 
                if plist.index(pmax)==0 or plist.index(pmax)==6:  #fruit "vegetable"    厨余垃圾
                    if pmax >= 0.5:
 
                            time.sleep_ms(50)      #等待垃圾掉落待静止的时间
                            Servo_2(S2,90)
                            time.sleep_ms(1000)
                            Servo_1(S1,-20)
                            time.sleep_ms(1500)
                            #write_str = ()
                            Servo_1(S1,i)
                            time.sleep_ms(400)
                            Servo_2(S2,0)
                            time.sleep_ms(1000)
                            uart_A.write("t7.txt=\"厨余垃圾\"")
                            print("厨余垃圾ok")
                            uart_A.write(s)
 
                            time.sleep_ms(450)   #舵机归位
                            Servo_1(S1,i)
                            time.sleep_ms(450)
                            break
                            #time.sleep_ms(500)      #等待垃圾掉落待静止的时间
 
                if plist.index(pmax)== 1 or plist.index(pmax)==2 or plist.index(pmax)== 7:  #capsule      有害垃圾
                    if pmax >= 0.6:    #0.5
 
                            time.sleep_ms(50)      #时隔几秒后继续检测垃圾
                            #Servo_2(S2,90)
                            #time.sleep_ms(500)
                            Servo_1(S1,-30)
                            time.sleep_ms(1500)
                            #write_str = ()
                            uart_A.write("t7.txt=\"有害垃圾\"")
                            print("有害垃圾ok")
                            uart_A.write(s)
 
                            time.sleep_ms(450)   #舵机归位
                            Servo_1(S1,i)
                            Servo_2(S2,0)
                            time.sleep_ms(450)
                            break
 
 
 
                if plist.index(pmax)==4 or plist.index(pmax)==8:  #bottle        可回收垃圾
                    if pmax >= 0.5:
 
                            time.sleep_ms(50)      #等待垃圾掉落待静止的时间
                            Servo_2(S2,180)
                            time.sleep_ms(1000)
                            Servo_1(S1,-20)
                            time.sleep_ms(1500)
                            #write_str = ()
                            Servo_1(S1,i)
                            time.sleep_ms(400)
                            Servo_2(S2,0)
                            time.sleep_ms(1000)
                            uart_A.write("t7.txt=\"可回收垃圾\"")
                            print("可回收垃圾ok")
                            uart_A.write(s)
                            time.sleep_ms(1200)   #舵机归位
                            break
 
 
 
                if plist.index(pmax)==3 or plist.index(pmax)== 5 or plist.index(pmax)== 9:  #cigarette      其他垃圾
                    if pmax >= 0.7:  #0.5
 
                            time.sleep_ms(50)      #等待垃圾掉落待静止的时间
                            Servo_2(S2,-90)
                            time.sleep_ms(1000)
                            Servo_1(S1,-20)
                            time.sleep_ms(1500)
                            #write_str = ()
                            Servo_1(S1,i)
                            time.sleep_ms(400)
                            Servo_2(S2,0)
                            time.sleep_ms(1000)
 
                            uart_A.write("t7.txt=\"其他垃圾\"")
                            print("其他垃圾ok")
                            uart_A.write(s)
                            time.sleep_ms(450)   #舵机归位
                            Servo_1(S1,i)
                            Servo_2(S2,0)
                            time.sleep_ms(500)
                            break
        uart.deinit()                   # uart.deinit()和kpu.deinit(task)用于关闭UART和释放模型资源。
        del uart
    except Exception as e:
        raise e
    finally:
        if not task is None:
            kpu.deinit(task)
 
if __name__ == "__main__":
  try :
      #labels = ["bottle", "brick", "capsule", "pill", "stone", "vegetable"]
      #labels = ["chuyu", "dainci", "jiaolang", "shitou", "shuiping", "taoci", "yaobaozhung", "yilaguan"]
      labels = ["chuyu", "dainci", "jiaolang", "shitou", "shuiping", "taoci", "xiaotudou", "yaobaozhung", "yilaguan", "zhuangtou"]
      main(labels=labels, model_addr="/sd/m.kmodel")
  except Exception as e:
      sys.print_exception(e)
      lcd_show_except(e)
  finally:
      gc.collect()
 

ESP8266代码:

 

#include <ThingsCloudWiFiManager.h>
#include <ThingsCloudMQTT.h>
// 安装第三方依赖
// DHT_sensor_library
// Adafruit_Unified_Sensor
#include "DHT.h"

//邮件代码
#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>
/* qq 邮箱的 smtp 地址和端口号 */
#define SMTP_HOST "smtp.qq.com"
#define SMTP_PORT 465
/* 
你的邮箱和授权码 授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码。 
如何获取授权码 https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256
*/
#define AUTHOR_EMAIL "xx@qq.com"
#define AUTHOR_PASSWORD "xxxx"
/* 接收人邮箱地址 email*/
#define RECIPIENT_EMAIL "xx@qq.com"
String customMessage = ""; // 定义一个自定义的消息字符串变量,发送邮件的内容
SMTPSession smtp;

//======================================================
// 设置 ssid / password,连接到你的 WiFi AP
const char *ssid = "xxxx";
const char *password = "88888888";
// 在 ThingsCloud 控制台的设备详情页中,复制以下设备连接信息
// https://console.thingscloud.xyz
#define THINGSCLOUD_MQTT_HOST "xxxx"
#define THINGSCLOUD_DEVICE_ACCESS_TOKEN "xxxx"
#define THINGSCLOUD_PROJECT_KEY "xxx"
//======================================================

ThingsCloudMQTT client(
  THINGSCLOUD_MQTT_HOST,
  THINGSCLOUD_DEVICE_ACCESS_TOKEN,
  THINGSCLOUD_PROJECT_KEY);

// 设置压缩杆的输入引脚  
#define RELAY_PIN1 4
#define RELAY_PIN2 5
// 上报数据的间隔时间计时器
unsigned long timer1 = millis();
// 设置定时上报数据的时间间隔,单位是 ms。免费版项目请务必大于30秒,否则设备可能会被限连。
const int report_interval = 1000 * 3 * 5;

// 设置DHT11的数据引脚
#define DHTPIN 14
// 设置使用的DHT类型use pins 3, 4, 5, 12, 13 or 14 --
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);


  float h ;//= dht.readHumidity();//湿度
  float t ;//= dht.readTemperature();//温度
  float p = random(1, 50);//pm2_5
  float ke  = 0;//可回收
  float cu  = 0;//厨余
  float qi  = 0;//其他
  float you = 0;//有害
  int jifen =random(0,100);//用户积分
  bool c=false ;//火焰报警状态
  bool d=false ;//满载报警状态
  int uid ;
void setup()
{
  dht.begin();
  Serial.begin(115200);
  pinMode(RELAY_PIN1, OUTPUT);
  pinMode(RELAY_PIN2, OUTPUT);
  // 初始断开继电器,输出低电平
  digitalWrite(RELAY_PIN1, LOW);
  digitalWrite(RELAY_PIN2, LOW);
  // 允许 SDK 的日志输出
  client.enableDebuggingMessages();

  // 连接 WiFi AP
  client.setWifiCredentials(ssid, password);


}








void pubSensors()//推送云端
{
  h = dht.readHumidity();//湿度
  t = dht.readTemperature();//温度
  // 检查是否读取到传感器数据
  if (isnan(h) || isnan(t)||isnan(p)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // 串口打印数据日志
  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F(" pm2_5: "));
  Serial.print(p);
  Serial.print( F("μg/m³" ));
  Serial.println();

  // 生成属性 JSON
  DynamicJsonDocument obj(512);
  obj["temperature"] = t;
  obj["humidity"] = h;
  obj["pm2_5"] = p;
  obj["ke"] = ke;
  obj["cu"] = cu;
  obj["qi"] = qi;
  obj["you"] = you;
  obj["jifen"] = jifen;
  obj["huo"] = c;
  obj["manzai"] = d;
  obj["uid"] = uid;
 
  char attributes[512];
  serializeJson(obj, attributes);
  // 调用属性上报方法
  client.reportAttributes(attributes);
}
void handleAttributes(const JsonObject &obj) {
  if (obj.containsKey("relay")) {
    // 接收到下发的 relay 属性
    if (obj["relay"] == true) {
      // 闭合继电器,输出低电平
      // digitalWrite(RELAY_PIN, LOW);
      //yasuo();
      digitalWrite(RELAY_PIN1, LOW);//压缩杆
      digitalWrite(RELAY_PIN2, HIGH);
      Serial.println("relay switch to ON");
    } else {
      // 断开继电器,输出高电平
      // digitalWrite(RELAY_PIN, HIGH);
        // 将电机设置为停止
      digitalWrite(RELAY_PIN1, HIGH);//压缩杆
      digitalWrite(RELAY_PIN2, LOW);      
      Serial.println("relay switch to OFF");
    }
  }
}
void onMQTTConnect() {

  // 订阅获取属性的回复消息
  client.onAttributesGetResponse([](const String &topic, const JsonObject &obj) {
    if (obj["result"] == 1) {
      handleAttributes(obj["attributes"]);
    }
  });

  // 订阅云平台下发属性的消息
  client.onAttributesPush([](const JsonObject &obj) {
    handleAttributes(obj);
  });

  // 读取设备在云平台上的属性,用于初始化继电器状态。
  // 云平台回复的属性会进入上边 client.onAttributesGetResponse 接收的消息。
  client.getAttributes();


  client.executeDelayed(1000 * 5, []()
  {
    pubSensors();
  });
}









// 读取并发布传感器数据到 ThingsCloud


// // 必须实现这个回调函数,当 MQTT 连接成功后执行该函数。
// void onMQTTConnect()
// {
//   // 延迟 5 秒上报首次传感器数据
//   client.executeDelayed(1000 * 5, []()
//   {
//     pubSensors();
//   });
// }





void receive(){//处理串口消息

    
      // 等待串口接收到数据
  if (Serial.available()) {
    // 读取串口接收到的数据
    String data = Serial.readStringUntil('\n');

    // 查找包含关键字的数据段
    int startIndex = data.indexOf("a=");
    int endIndex = data.indexOf("d=") + 4;

    // 提取关键字段
    String targetData = data.substring(startIndex, endIndex);

    // 解析数据并存储到变量中
    int index;
    String temp;

    index = targetData.indexOf("a=");
    temp = targetData.substring(index + 2, targetData.indexOf(',', index));
    ke = temp.toInt();//超声波
    
    index = targetData.indexOf("b=");
    temp = targetData.substring(index + 2, targetData.indexOf(',', index));
    int jifen1 = temp.toInt();//积分

    index = targetData.indexOf("c=");
    temp = targetData.substring(index + 2,targetData.indexOf(',', index));
    c = temp.toInt()==1;//火焰

    index = targetData.indexOf("d=");
    temp = targetData.substring(index + 2,targetData.indexOf(',', index));
    uid = temp.toInt();
    
    d=ke>85;//满载状态
    }
    // index = targetData.indexOf("e=");
    // temp = targetData.substring(index + 2,targetData.indexOf(',', index));
    // you = temp.toInt();
    // 输出解析后的变量值
    Serial.print("a=");
    Serial.print(ke);
    Serial.print(", b=");
    Serial.print(jifen);
    Serial.print(", c=");
    Serial.print(c);
    Serial.print(", d=");
    Serial.println(uid); 
   
}

void sendqqmsger()//发送报警邮件
  {
    
    /* smtp开启debug,debug信息输出到串口 */
  smtp.debug(1);
  /* 注册回调函数,获取邮件发送状态 */
  //smtp.callback(getSmtpStatusCallback);
  ESP_Mail_Session session;
  /* 设置smtp 相关参数, host, port等 */
  session.server.host_name = SMTP_HOST;
  session.server.port = SMTP_PORT;
  session.login.email = AUTHOR_EMAIL;
  session.login.password = AUTHOR_PASSWORD;
  session.login.user_domain = "";
  /* 定义smtp message消息类 */
  SMTP_Message message;
  /* 定义邮件消息类的名称,发件人,标题和添加收件人 */
  message.sender.name = "Esp8266er";
  message.sender.email = AUTHOR_EMAIL;
  message.subject = "垃圾桶告警邮件";
  message.addRecipient("Sara", RECIPIENT_EMAIL);
  /* 设置message html 格式和内容*/
  
  String htmlMsg = "<div style=\"color:#2f4468;\"><h1>" + customMessage + "</h1><p>Sent from Esp8266er</p></div>";

  //String htmlMsg = "<div style=\"color:#2f4468;\"><h1> //%s Hello World!</h1><p>Sent from Esp8266er</p></div>";
  message.html.content = htmlMsg.c_str();
  message.html.content = htmlMsg.c_str();
  message.text.charSet = "us-ascii";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
  /* 连接smtp服务器 */
  if (!smtp.connect(&session))
    return;
  /* 调用发送邮件函数,失败的话,获取失败信息 */
  if (!MailClient.sendMail(&smtp, &message))
    Serial.println("发送邮件失败,失败原因是 , " + smtp.errorReason());
}

  
void loop()
{
  client.loop();
    // 按间隔时间上报传感器数据



  if (millis() - timer1 > report_interval)
  {
    timer1 = millis();
    receive();//处理串口消息
        if(ke>80)customMessage="垃圾桶已满,请及时清理垃圾桶。";
        if(c==1) customMessage+="垃圾桶起火啦,请及时处理";
         //sendqqmsger();
      
  
   pubSensors();   //上报数据//推送云端
  }

}

MEGA2560

#include <SPI.h>
#include <MFRC522.h>
#include<SoftwareSerial.h>
#include<Servo.h>
#define RST_PIN 5
#define SS_PIN 53
#include <TimerOne.h>
MFRC522 mfrc522(SS_PIN, RST_PIN);

int CardNumber1[] = {3, 145, 101, 37};
int CardNumber2[] = {51, 16, 138, 171};
int CardNumber3[] = {19, 39, 127, 245};
int CardNumber4[] = {202, 128, 154, 89};
Servo myservo;
int servoPin = 8;



int analogPin = A1;  // 模拟输入引脚连接到A1
int digitalPin = 3;  // 数字输出引脚连接到数字引脚3
int flameAnalogPin = A0; // 火焰传感器的模拟输出连接到模拟引脚A0
int flameDigitalPin = 2; // 火焰传感器的数字输出连接到数字引脚D2
const int trigPin = 9; // 连接到超声波传感器的发送引脚
const int echoPin = 10; // 连接到超声波传感器的接收引脚
const int buzzerPin = 13;//蜂鸣器
int flameAnalogValue;// 读取火焰传感器的模拟值
float percentage;//超声波转百分比
int percentage_int;
long duration;
int distance;





//以下是发送给esp8266串口的变量
  int a;//超声波测距可回收    数值
  int b;//有害气体            数值
  int c;//火焰传感器          1或0
  int d;//FIRD               数值
  int e;//投入可回收个数
  int analogValue;//有害气体浓度
  
unsigned long previousMillis = 0;
const long interval = 30000;  // 30秒
void setup()
{
  Timer1.initialize(30000000);  // 设置 Timer2 的周期为 30秒
  Timer1.attachInterrupt(timer2ISR);  // 绑定中断处理函数
  SPI.begin();
  mfrc522.PCD_Init();
  myservo.attach(servoPin);
  myservo.write(0);
  Serial.println(F("Scan PICC to see UID, type, and data blocks..."));


  pinMode(analogPin, INPUT);    // 将A1设置为输入模式
  pinMode(digitalPin, INPUT);   // 将数字引脚3设置为输入模式
  pinMode(flameDigitalPin, INPUT); // 将数字引脚设置为输入模式
  pinMode(buzzerPin, OUTPUT);
  pinMode(trigPin, OUTPUT);//超声波发引脚
  pinMode(echoPin, INPUT);//超声波收引脚
  digitalWrite(buzzerPin,HIGH);//蜂鸣器
  
  Serial.begin(115200);    //电脑串口
  Serial1.begin(115200);  //esp8266发送数据
  //Serial2.begin(115200);  //给屏幕发送数据   这里先不打开 用的时候打开在关闭





}
void timer2ISR() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // 每隔30秒执行一次的任务
    previousMillis = currentMillis;
    // 执行你的任务代码
    send();
  }
}
void  qiti(){   //有害气体读取报警
  analogValue = analogRead(analogPin) ;   // 读取模拟输入引脚A1的数值
  Serial.print("烟雾:");
  Serial.println(analogValue);
  b=analogValue ;
  if (analogValue > 200) {   // 如果烟雾传感器数值超过50,触发蜂鸣器警报
    digitalWrite(buzzerPin, LOW);
  }
  //else
  // { 
  //   digitalWrite(buzzerPin,HIGH);
  // }

}
void  flame(){//火焰报警
  flameAnalogValue= analogRead(A0); //读取火焰传感器的模拟值
  Serial.print("火焰:");
  Serial.println(flameAnalogValue);
  if (flameAnalogValue <900) //当模拟值大于1时蜂鸣器鸣响,阈值根据实际测试进行修改
  { 
    c=1;
    digitalWrite(buzzerPin, LOW);//
  }
  else
  { 
    c=0;
   
  }

}


void chaoshenbo(){         //超声波测距  可回收
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // 接收超声波回波
  duration = pulseIn(echoPin, HIGH);

  // 将回波时间转换为距
  distance = duration * 0.034 / 2;
  percentage= ((30 - distance) / 30.0) * 100; // 修正了百分比计算公式
  Serial.println(percentage);
  a = int(percentage); // 将百分比转换为整数部分

//   // 输出距离到串口监视器
  Serial.print("Distance: ");
  Serial.println(distance);



}

void send(){//串口发送
  String data = "a=";
  data += String(a);
  data += ",b=";
  data += String(b);
  data += ",c=";
  data += String(c);
  data += ",d=";
  data += String(d);
  // data += ",e=";
  // data += String(e);
  // data += ",";
  // 发送数据
  Serial.println(data);
  Serial1.println(data);


}
void uid(){
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
// 读卡
  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  // 获取卡片号码
  byte* uid = mfrc522.uid.uidByte;
  int detectedCardNumber[] = {uid[0], uid[1], uid[2], uid[3]};
  myservo.write(90);              // 舵机角度写入
                        // 等待转动到指定角度
  Serial2.begin(115200);  //给屏幕发送数据
  // 检查是否为目标卡片
  {
    if (detectedCardNumber[0] == CardNumber1[0] &&
        detectedCardNumber[1] == CardNumber1[1] &&
        detectedCardNumber[2] == CardNumber1[2] &&
        detectedCardNumber[3] == CardNumber1[3]) {
      Serial.println("编号一");
      Serial2.print("n7.val=1\xff\xff\xff");
      d=1;
    
    }

    // 检查是否为目标卡片
    if (detectedCardNumber[0] == CardNumber2[0] &&
        detectedCardNumber[1] == CardNumber2[1] &&
        detectedCardNumber[2] == CardNumber2[2] &&
        detectedCardNumber[3] == CardNumber2[3]) {
      Serial.println("编号二");
      Serial2.print("n7.val=2\xff\xff\xff");
      //Serial2.print("main.t7.txt=\"厨余垃圾\"\xff\xff\xff");
      d=2;
    }
    // 检查是否为目标卡片
    if (detectedCardNumber[0] == CardNumber3[0] &&
        detectedCardNumber[1] == CardNumber3[1] &&
        detectedCardNumber[2] == CardNumber3[2] &&
        detectedCardNumber[3] == CardNumber3[3]) {
      Serial.println("编号三");
      Serial2.print("n7.val=3\xff\xff\xff");
      d=3;
    }
    // 检查是否为目标卡片
    if (detectedCardNumber[0] == CardNumber4[0] &&
        detectedCardNumber[1] == CardNumber4[1] &&
        detectedCardNumber[2] == CardNumber4[2] &&
        detectedCardNumber[3] == CardNumber4[3]) {
      Serial.println("编号四");
      Serial2.print("main.n7.val=4\xff\xff\xff");
      d=4;
    }
      
      
      Serial.flush();
      Serial2.end();
    
  }
}

void loop() {

  chaoshenbo();//超声波测距  可回收
  uid();       //注册用户
  delay(1500); // 停止30秒后再上报
  myservo.write(0);
  digitalWrite(buzzerPin,HIGH);
  qiti();   //有害气体读取报警
  flame();//火焰报警
  //send();//发送esp8266数据
}

”屏幕是以下链接的(开源)2023工训大赛智能垃圾分类项目(可循环播放视频,显示垃圾分类信息,拍照识别,垃圾分类,满载报警,压缩)_工程训练大赛垃圾分类项目-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/647633.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3D牙科网格分割使用基于语义的特征学习与图变换器

文章目录 3D Dental Mesh Segmentation Using Semantics-Based Feature Learning with Graph-Transformer摘要方法实验结果 3D Dental Mesh Segmentation Using Semantics-Based Feature Learning with Graph-Transformer 摘要 本文提出了一种新颖的基于语义的牙科网格分割方…

计算机毕业设计 | SSM汽车租赁系统(附源码)

1&#xff0c; 概述 1.1 课题背景 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。用户生活水平的不断提高&#xff0c;日常生活中用户对汽车租赁系统方面的要求也在不断提高&#xff0c;需要汽车租赁系统查询的人数更是不断增加&#xff0c;使得汽车租赁系统的…

rockylinux 利用nexus 搭建私服yum仓库

简单说下为啥弄这个私服&#xff0c;因为自己要学习一些东西&#xff0c;比如新版的k8s等&#xff0c;其中会涉及到一些yum的安装&#xff0c;为了防止因网络问题导致yum安装失败&#xff0c;和重复下载&#xff0c;所以弄个私服&#xff0c;当然也有为了意外保障的想法&#x…

树形DP-AcWing 285. 没有上司的舞会-XMUOJ提瓦特庆典策划

题目 思路 话不多说&#xff0c;直接上代码 代码 /* AcWing 285. 没有上司的舞会-XMUOJ提瓦特庆典策划 --JinlongW-2024/05/26 */ #include <bits/stdc.h> using namespace std; const int N7000; int st[N];//标记是否有父亲结点 int happy[N]; int dp[N][2]; vect…

【AHK V2】设计模式之命令模式

目录 情景剧场什么是命令模式优缺点优点缺点 使用命令模式的步骤命令模式代码示例合理使用AI工具自动生成代码 情景剧场 我们来设想一个场景&#xff1a; 你进入一家餐馆&#xff0c;餐馆只有老板一个人&#xff08;老板即厨师&#xff09;。 “老板&#xff0c;一份小炒肉&am…

HCIP的学习(22)

BGP优化 [r1-bgp]peer 12.0.0.2 default-route-advertise ---BGP下放缺省路由&#xff0c;无论本地的路由表中是否存在缺省路由&#xff0c;都会向对等体下发一条下一跳为本地的缺省路由&#xff0c;从而减少网络中路由数量&#xff0c;节省对等体的设备资源 BGP协议优先级 缺…

Linux系统进程管理

系统进程管理 一、进程概述 1.1 什么是进程&#xff1f;进程管理需要做什么&#xff1f; 进程是已启动的运行实例&#xff0c;进程有以下组成部分&#xff1a; ​ 已分配内存的地址空间 ​ 进程ID ​ 程序的代码 ​ 进程状态 进程管理包括进程调度、中断处理、信号、进程…

从感知机到神经网络

感知机 一、感知机是什么二、用感知机搭建简单逻辑电路2.1 与门2.2 与非门2.3 或门 三、感知机的局限性3.1 异或门3.2 线性和非线性 四、多层感知机4.1 已有门电路的组合4.2 Python异或门的实现 五、感知机模型5.1 感知机模型5.2 感知机损失函数5.3 感知机学习算法 六、感知机原…

贪心-AcWing 1522. 排成最小的数字-XMUOJ石板序列

题目 思路 getline() 是 C 标准库中的一个函数&#xff0c;用于从输入流中读取一行文本&#xff0c;并将其存储为字符串。它可以从标准输入、文件流、字符串流等不同类型的输入流中读取数据。C中istringstream、ostringstream、stringstream详细介绍和使用_c istringstream-CS…

【网络技术】【Kali Linux】Wireshark嗅探(十五)SSDP(简单服务发现协议)报文捕获及分析

往期 Kali Linux 上的 Wireshark 嗅探实验见博客&#xff1a; 【网络技术】【Kali Linux】Wireshark嗅探&#xff08;一&#xff09;ping 和 ICMP 【网络技术】【Kali Linux】Wireshark嗅探&#xff08;二&#xff09;TCP 协议 【网络技术】【Kali Linux】Wireshark嗅探&…

SpringMVC:创建一个简单的SpringMVC框架S

目录 一、框架介绍 两个重要的xml文件 SpringMVC执行流程 二、Vscode搭建SpringMVC框架 1、maven创建webapp原型项目 2、pom.xml下添加springmvc的相关依赖 3、在web.xml配置 4、springmvc.xml的配置 5、编写Controller控制器类 6、 编写JSP界面 7、项目结构图 一…

C++开发面试常问总结

一些面试总结 TCP粘包了解吗&#xff1f;解决办法&#xff1f;讲一下乐观锁悲观锁git中 git pull和git fetch的区别1.虚函数实现机制&#xff1a;2.进程和线程的区别&#xff1a;3.TCP三次握手、四次挥手&#xff1a;4.HTTP状态码&#xff0c;报头&#xff1a;5.智能指针&#…

Jeecg | 完成配置后,如何启动整个项目?

前端启动步骤&#xff1a; 1. 以管理员身份打开控制台&#xff0c;切换到前端项目目录。 2. 输入 pnpm install 3. 输入 pnpm dev 4. 等待前端成功运行。 可以看到此时前端已经成功启动。 后端启动步骤&#xff1a; 1. 启动 mysql 服务器。 管理员身份打开控制台&#…

录屏技巧:win11怎么录屏?这5个电脑录屏方法快速了解下

无论您是想进行工作演示还是游戏直播&#xff0c;电脑录屏都有很大帮助。录制 Win 11 屏幕在很多方面都非常有效&#xff0c;因为它能让事情变得更简单。但 Win11怎么录屏呢&#xff1f;如果您仍有困惑&#xff0c;请查看本篇文章中列出的5个方法。在本文中&#xff0c;我们列出…

解决 Failed to parse remote port from server output【Remote-SSH】【VSCode】

描述 一早起来&#xff0c;发现remote-ssh无法进入服务器容器&#xff0c;本地使用git bash进行ssh可正常连接服务器&#xff0c;基本确定是vscode工具本身的问题。重装本地用户的.vscode相关目录清空&#xff0c;vscode重装均无果&#xff0c;不建议尝试。弹窗信息为Could no…

机器重启oracle数据库自动启动异常

业务连接报ora-01033&#xff1a; 检查服务器&#xff0c;发现有重启记录&#xff0c;oracle进程存在&#xff0c;数据库状态处于mount状态&#xff0c;检查日志&#xff0c;发现在数据库启动时没有正常open&#xff1a; 连入数据库&#xff1a;Select * from v$backup 发现数…

visual studio code生成代码模板

编写需要生成代码片段的代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wid…

Vue3图片浏览组件v-viewer,支持旋转、缩放、翻转等操作

文章目录 1. v-viewer组件简介2. 在vue项目使用2.1 指令形式调用2.2 组件形式调用2.3 api形式调用 Viewer的配置项 & 方法bug 1. v-viewer组件简介 一款基于 viewer.js 封装的Vue版插件&#xff0c;可用于图像查看&#xff0c;以及图片的旋转、缩放等功能预览 官网&#…

CVE-2020-7982 OpenWrt 远程命令执行漏洞学习(更新中)

OpenWrt是一款应用于嵌入式设备如路由器等的Linux操作系统。类似于kali等linux系统中的apt-get等&#xff0c;该系统中下载应用使用的是opgk工具&#xff0c;其通过非加密的HTTP连接来下载应用。但是其下载的应用使用了SHA256sum哈希值来进行检验&#xff0c;所以将下载到的数据…

python探索转义字符的奥秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、转义字符的定义与功能 案例解析&#xff1a;换行符与双引号 二、转义字符的应用场景 …