DIY 智能回收系统:反向自动售货机 (RVM) 完整构建指南
组件与材料
| 组件 | 数量 | 备注 |
|---|---|---|
| Arduino Mega 2560 | 1 | 主控制器,负责传感器读取与舵机控制 |
| NodeMCU ESP8266 开发板 | 1 | WiFi 连接,上传满溢数据至云端 |
| 感应式接近传感器, 15mm (感应金属) | 2 | 检测金属罐 |
| 电容式接近传感器, 12mm (感应非金属) | 1 | 检测塑料瓶 |
| SG90 微型舵机 | 2 | 分别控制塑料/金属分类落料口 |
| 16x2 字符型 LCD | 1 | 显示加密兑换码 |
| 超声波测距模块 HC-SR04 | 2 | 监测垃圾桶填满高度 |
| GPS 模块 (通用) | 1 | 获取设备地理位置 |
| 无源蜂鸣器 | 1 | 投递成功提示音 |
| 单圈电位器 100kΩ | 1 | LCD 对比度调节 |
| 轻触开关 | 1 | 复位/功能键 |
| 5mm 红色 LED | 2 | 状态指示 |
| 杜邦线 (通用) | 1 | |
| 12V 电池 | 1 | 主供电 |
| 9V 电池 | 1 | 备用/辅助供电 |
| 面包板 (通用) | 2 |
所需工具
- 电烙铁
- 数字万用表
- 剥线钳
应用与在线服务
- Arduino IDE
- Blynk 物联网平台
- ThingSpeak 数据可视化
项目背景与动机
环境危机
塑料瓶最终流向何方?垃圾填埋场、海洋、河流和人行道。据估算,每平方英里海洋漂浮着约 46,000 件塑料垃圾。这些塑料杀害动物、渗漏化学物质、破坏生态系统。单个瓶子分解需长达一千年,过程中释放致癌及生殖毒性物质。焚烧塑料会产生一氧化碳、氯气、盐酸、呋喃和亚硝酸盐等剧毒排放。尽管提倡回收,但全球每年 350 亿瓶中仅 12% 被回收,投入回收箱的仅有一半真正被处理。
解决方案构想
本项目设计一款智能回收机:用户投入塑料瓶或金属罐,机器自动识别材质并给予积分奖励。积分通过手机扫描机身二维码,在网页输入 LCD 上显示的加密码兑换。系统采用电容/感应式接近传感器区分材质,超声波监测满溢并通过 NodeMCU + GPS 上报位置至 Blynk/ThingSpeak,实现无人值守智能回收闭环。
工作原理
核心流程
- 投递:用户将空瓶/罐放入入口,水平进料系统逐个接收。
- 识别:
- 感应式传感器输出 1 → 金属罐
- 感应式输出 0 且电容式输出 1 → 塑料瓶
- 分拣:对应舵机旋转打开分类落料口,蜂鸣器响一声,LED 闪烁确认。
- 奖励:LCD 显示一次性加密码,用户扫码进入网页录入兑换积分(需注册账号)。
- 满溢报警:超声波检测垃圾桶高度 ≤ 5cm 时,NodeMCU 通过 Blynk 推送通知并上传 GPS 坐标至 ThingSpeak,通知回收人员收运。
系统架构图



核心代码
1. 垃圾分拣主程序 (Arduino Mega)
#include
#include
LiquidCrystal lcd(1, 2, 4, 5, 6, 7);
const int btnPin = 3;
int btnState = 0, lastBtnState = 0;
const int ledPlastic = 10, ledMetal = 11;
const int buzzPlastic = 12, buzzMetal = 13;
const int plasticSensor = A0;
const int metalSensor1 = A1, metalSensor2 = A2;
Servo servoPlastic, servoMetal;
int posP = 90, posM = 360; // 舵机初始角度
void setup() {
pinMode(btnPin, INPUT); digitalWrite(btnPin, LOW);
lcd.begin(16, 2); lcd.clear();
servoPlastic.attach(9); servoMetal.attach(8);
pinMode(plasticSensor, INPUT_PULLUP);
pinMode(metalSensor1, INPUT_PULLUP);
pinMode(metalSensor2, INPUT_PULLUP);
pinMode(ledPlastic, OUTPUT); pinMode(ledMetal, OUTPUT);
pinMode(buzzPlastic, OUTPUT); pinMode(buzzMetal, OUTPUT);
Serial.begin(9600);
}
void loop() {
// 引导用户投放
lcd.setCursor(0,0); lcd.print("INSERT METAL ON");
lcd.setCursor(0,1); lcd.print(" RIGHT SIDE ");
delay(6000); lcd.clear();
int valPlastic = digitalRead(plasticSensor);
int valMetal1 = digitalRead(metalSensor1);
int valMetal2 = digitalRead(metalSensor2);
Serial.println("Plastic: " + String(valPlastic));
Serial.println("Metal1: " + String(valMetal1));
Serial.println("Metal2: " + String(valMetal2));
// 塑料瓶检测到且无金属 → 触发塑料舵机
if (valPlastic == 1 && valMetal1 != 1) {
for (posP = 90; posP <= 240; posP++) {
servoPlastic.write(posP); delay(5);
digitalWrite(ledPlastic, HIGH); digitalWrite(buzzPlastic, HIGH);
}
for (posP = 240; posP >= 90; posP--) { servoPlastic.write(posP); delay(5); }
} else {
servoPlastic.write(posP);
digitalWrite(ledPlastic, LOW); digitalWrite(buzzPlastic, LOW);
}
// 金属罐检测到且无塑料 → 触发金属舵机
if (valMetal2 == 1 && valPlastic == 0) {
for (posM = 360; posM >= 50; posM--) {
servoMetal.write(posM); delay(5);
digitalWrite(ledMetal, HIGH); digitalWrite(buzzMetal, HIGH);
}
for (posM = 50; posM <= 360; posM++) { servoMetal.write(posM); delay(5); }
} else {
servoMetal.write(posM);
digitalWrite(ledMetal, LOW); digitalWrite(buzzMetal, LOW);
}
}
2. 垃圾桶满溢监测与上报 (NodeMCU ESP8266)
#include
#include
#include
#include
#include
#define BLYNK_PRINT Serial
#define TRIG_PIN 5
#define ECHO_PIN 4
WiFiClient client;
static const int RXPin = 4, TXPin = 5; // GPS 模块串口
static const uint32_t GPSBaud = 9600;
unsigned long channelID = 1067056;
const int fieldNum = 1;
const char *writeAPIKey = "FMV95MD2A1J7Y8SP";
TinyGPSPlus gps;
WidgetMap myMap(V0);
SoftwareSerial ss(RXPin, TXPin);
BlynkTimer timer;
char auth[] = "YVvgHBx9fIM1-yR_2XrGXXkKdIuEmrYL";
char ssid[] = "your_wifi_ssid";
char pass[] = "your_wifi_pass";
unsigned int moveIndex = 1;
void setup() {
Serial.begin(115200);
ss.begin(GPSBaud);
Blynk.begin(auth, ssid, pass);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(BUILTIN_LED, OUTPUT);
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client);
}
void loop() {
// WiFi 重连
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Connecting to "); Serial.println(ssid);
while (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass); delay(100); Serial.print(".");
}
Serial.println("\nConnected.");
}
// GPS 解析
while (ss.available() > 0) {
if (gps.encode(ss.read())) {
if (gps.location.isValid()) {
float lat = gps.location.lat();
float lng = gps.location.lng();
Serial.print("LAT: "); Serial.println(lat, 6);
Serial.print("LONG: "); Serial.println(lng, 6);
ThingSpeak.setField(3, lat);
ThingSpeak.setField(4, lng);
ThingSpeak.writeFields(channelID, writeAPIKey);
Blynk.virtualWrite(V1, String(lat, 6));
Blynk.virtualWrite(V2, String(lng, 6));
myMap.location(moveIndex, lat, lng, "RVM_Location");
}
}
}
// 超声波测距
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
int distance = (duration / 2) / 29.1; // cm
if (distance <= 5) { // 阈值 5cm 触发报警
Blynk.notify("请清空垃圾桶!");
}
Serial.print("Distance: "); Serial.println(distance);
Blynk.virtualWrite(V6, distance);
ThingSpeak.writeField(channelID, fieldNum, distance, writeAPIKey);
Blynk.run();
timer.run();
delay(100);
}
原理图

扩展建议
- 增加太阳能供电模块,实现野外部署零布线
- 接入微信/支付宝小程序,替代网页兑换,提升用户体验
- 加入压力传感器或重量模块,统计回收重量,生成环保报告
- 使用 LoRa 替代 WiFi,适应无网络覆盖区域
制造工艺
- 缝纫机演进:从19世纪创新到现代自动化制造
- 树莓派蓝牙近感智能门锁:手机离开自动上锁
- 树莓派 + MCP9808 + InfluxDB + Grafana:家庭温度监测系统
- 薯条自动售货机幕后揭秘:全自动炸薯条如何 2 分钟出炉
- 鲜奶自动售货机:便捷、实惠、环保的新选择
- 薯条自动贩卖机:几分钟热辣现做,如何实现?
- 面条自动贩卖机大揭秘:杯面vs拉面机,如何选?
- 创新茶咖汤自动售货机:多功能热饮新体验
- 预制餐自动售货机:随时享用新鲜健康餐食
- 软饮料自动售货机完全指南:原理、优势与常见问题
- 冰棒自动售货机:解锁商业利润新增长点
- Banner DBQ5 接近传感器测试仪便携演示盒:DC 传感器快速精准测试