目录
1.1需求分析
2.1概要设计
3.1软件界面设计:
4.1代码开源
在如今每人都会扔出许多垃圾,在一些地方大部分垃圾能得到卫生填埋、焚烧等无害化处理,而更多的垃圾则是简单的掩埋,长期下去导致臭气蔓延,并且污染土壤和地下水。因为垃圾无害化处理的费用是非常高的,但若采用垃圾分类的方式管理垃圾,我们可以管理废物和回收物,减少占地、减少环境污染、变废为宝。有利于我国城镇化质量和生态文明建设的水平进一步提高。
面向社区以及我们的各种景区的人平时产生生活垃圾和可回收垃圾的人群。
面向企业进行海量管理。
本产品具有垃圾识别、卡片识别、分类显示、安全控制、积分奖励,海量管理六大功能,性能较高,容错率高,可优化其能力。
产品名称 | 外观 | 优势 | 劣势 | 核心功能 |
脚踏式室外大号垃圾分类桶 | 能够一次性装入大量的垃圾,节省了时间对环境有防臭功能 | 体型太大,占用空间,是脚踏式的不够方便 | 垃圾分类 | |
EKO感应垃圾桶 | 体型小、能够感应式的丢垃圾 | 不能够做到垃圾分类 | 智能感应 | |
积分兑换-智能化的垃圾分类 | 能够达到垃圾自主分类的效果,智能控制,有积分奖励模式,海量管理 | 体型较小不能做到大型垃圾的处理 | 积分奖励 智能控制 垃圾分类 |
表1.4竞品分析情况
当前处于移动互联网的时代,本产品是基于Arduino的垃圾分类。实现对各个垃圾的分类和积分统计。
图2.1 总体设计流程图
- 本产品通过Arduino与各种传感器相结合和控制,实现了对垃圾桶是否装满和安全隐患防护的功能。
- MEGA2560板加入了超声波模块来对垃圾进行检测,从而判定是否溢出来定时进行垃圾的清理,一个火焰传感器对周围火焰进行检测报警,一个可燃气体传感器检测垃圾桶内部气体进行报警,蜂鸣器用于对火焰和可燃气体的检测进行报警,一个舵机模块加入舵机模块进行刷卡认证,并且把卡号发送给屏幕
- Esp8266板加入了一个温度传感器,一个压缩干,温度传感器的数值会通过该板同步上传到云平台,同理我们的mega2560板也会把数据通过串口发送到esp8266板进行数据上传,当检测到垃圾桶容量满了的时候可开关进行垃圾压缩。
- K210板通过摄像头对垃圾进行识别分类将垃圾投入垃圾桶,并且把收入的垃圾信息发送到屏幕。
- 串口屏实时显示用户刷卡后的ID,在投入垃圾后会语言播报垃圾种类,并且显示当前积分和用户排行榜
3.1软件界面设计:
图3.1-1实物作品软件设计界面
图3.1-2 APP前端积极奖励兑换界面
- 本品使用了Arduino IDE软件编程,在mega2560开发板中加入esp8266wifi模块,将传感器所取的信息数据传入开发板,并通过云平台来实现信息的显示。如:为了解决垃圾的防火、防臭,火焰传感器可通过检测烟火焰将信息传给工作人员,超声波实时检测垃圾桶的余量并防止溢出,空气质量传感器通过mega2560开发板将数据传给wifi模块,来防止有害气体。温度传感器当温度过高时发给wifi设备让工作人员清楚的知道情况。
- 为了让广大市民提高垃圾分类的积极性,加入了积分奖励这一方面,通过mega2560让RFID板块,通过刷卡录入,将数据信息放在RFID模块库,当用户投入可回收垃圾时,k210发送串口从而达到用户的积极记录,并利用了串口屏将积分信息、垃圾满出度、实时时间正确的显示出来,更好的方便管理,在无人投放垃圾时进行垃圾宣传片播放。
- 设计了一个积极奖励兑换商城,通过扫描二维码打开微信小程序,可以看到里面的商品和兑换所需的积分数量,这样大大提高了市民的垃圾分类积极性,让垃圾分类观念更加普及。
图3.3制作作品利用的函数库
火焰传感器:通过传感器来判断,垃圾桶是否产生了火焰,来保护防火安全
压缩杆:对满载垃圾进行压缩处理
串口屏:实现时间实时显示,积分显示,垃圾种类显示,用户ID、排行榜显示
云台:实现自主分类垃圾
产品名称: | 基于云平台的智慧城域垃圾分类装置 | 产品型号: | 1.0 版本 |
测试概述: | 产品的安全性,稳定性 | 测试数量: | 1 台 |
测试环境: | 室外 | 测试时间: | 2024 年5月3日 |
测试项目: | 各传感器的信号采集,k210的稳定性,mega2560信息的输入度,积分奖励App平台,屏幕显示准确性,wifi模块稳定性。 | ||
测试条件: 在电源充足的情况下,刷卡投入垃圾,用户自己近距离丢垃圾的情况。 | |||
测试方法/过程:
| |||
测试结果: 产品能够通过wifi模块来上传各种信息,投入对应的可回收垃圾,k210能够反馈数据到串口屏幕,刷卡认证后舵机能准确转动给予响应,k210控制四个舵机能够准确识别投放垃圾,屏幕能够准确播报垃圾种类,显示积分,压缩干能正常运作并进行压缩 | |||
结论/建议: 产品整体性能较好,智能化的程度较高,建议改善空间大小,以便更多的投入垃圾,让垃圾分类进行的更好 |
测试项目 | 技术要求 | 测试结果 | 判定情况 | |
1 | K210摄像头 | 是否准确识别垃圾 | 是 | 良好 |
2 | 串口屏 | 是否准确显示积分,垃圾种类,语音播报 | 是 | 良好 |
3 | RFID模块 | 是否准确检测用户的id | 是 | 良好 |
4 | 蜂鸣器模块 | 是否准确报警提示 | 是 | 良好 |
5 | 超声波板 | 是否实时检测垃圾余量 | 是 | 良好 |
6 | Esp8266wifi模块 | 是否准确上传数据 | 是 | 良好 |
7 | 可燃气体传感器 | 是否测出气体的环境 | 是 | 良好 |
8 | 火焰传感器 | 是否检测火焰产生情况 | 是 | 良好 |
9 | Mega2560 | 是否准确控制传感器,RFID | 是 | 良好 |
10 | 温度传感器 | 是否能够对高温进行反馈 | 是 | 良好 |
11 | K210 | 是否准确控制舵机 | 是 | 良好 |
12 | L298N | 是否准确控制压缩干 | 是 | 良好 |
测试次数 测试名称 | 第一次 | 第二次 | 第三次 | 第四次 |
运行速度 | 快 | 中等 | 中等 | 较快 |
安全性 | 中等 | 好 | 好 | 较好 |
扩展性 | 好 | 较好 | 中等 | 好 |
部署方便性 | 好 | 好 | 较好 | 好 |
可用性 | 高 | 中等 | 较高 | 高 |
thingscloud物联网平台使用微信小程序扫描二维码即可:
在制作产品的过程,对材料购入、市场调查、代码编写、创新想法、程序加入等方面,进行了明确的分工。
任务一:压缩杆的控制,当垃圾容量到达一定值自动压缩垃圾
任务二:RFID实现锁定人物ID功能,发送串口给屏幕显示ID,屏幕实时显示ID,语音播报垃圾种类,实时显示积分
任务三:超声波模块检测垃圾桶满,温度传感器发现温度过高,有害气体传感器异常,火焰传感器发现有火,垃圾桶满载均会通过wifi模块发送信息到手机,超声波模块与串口屏实时显示垃圾桶的余量
基于图像识别的垃圾分类,以及对积分的具体应用,创建一个根据用户所扔的垃圾来了解用户的饮食情况从而来给出合理有效的饮食方案。
垃圾分类与旁边的超市进行联合起来,将积分用于兑换物品接着再创建网上兑换商城
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# 如果等待超时,返回错误代码 -1if time.ticks_diff(time.ticks_ms(), start_time) >= 3000:print("Error: no echo received!")return -1# 记录回响信号的时间戳t1 = time.ticks_us()while echo.value() == 1:passt2 = time.ticks_us()print(t2)# 计算距离(单位:厘米)duration = t2 - t1distance = duration * 0.017print(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)returndef lcd_show_except(e):import uioerr_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 1try: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= 0while(a<3):print("启动")write_str = ("page main") #跳到计数主屏幕uart_A.write(write_str)uart_A.write(s)print(write_str)a+=1while(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() - tplist=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)breakmax_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.5time.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)breakif 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) #舵机归位breakif plist.index(pmax)==3 or plist.index(pmax)== 5 or plist.index(pmax)== 9: #cigarette 其他垃圾if pmax >= 0.7: #0.5time.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)breakuart.deinit() # uart.deinit()和kpu.deinit(task)用于关闭UART和释放模型资源。del uartexcept Exception as e:raise efinally: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_5float 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 APclient.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();// 生成属性 JSONDynamicJsonDocument 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或0int 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博客