역자판기(RVM): DIY 스마트 재활용 시스템 키트
부품 및 소모품
| 부품 |
수량 |
| 아두이노 메가 2560 |
1 |
| NodeMCU ESP8266 브레이크아웃 보드 |
1 |
| 유도형 근접 센서, 15mm |
2 |
| 정전용량형 근접 센서, 12mm |
1 |
| SG90 마이크로 서보 모터 |
2 |
| 영숫자 LCD, 16x2 |
1 |
| 초음파 센서 HC-SR04 (일반) |
2 |
| GPS 모듈 (일반) |
1 |
| 피에조 부저 |
1 |
| 단일 회전 포텐셔미터, 100kΩ |
1 |
| 스위치 액추에이터, 스프링 리턴 푸시버튼 헤드 |
1 |
| 5mm LED: 빨강 |
2 |
| 점퍼 와이어 (일반) |
1 |
| 배터리, 12V |
1 |
| 9V 배터리 (일반) |
1 |
| 브레드보드 (일반) |
2 |
필수 도구 및 장비
- 납땜 인두 (일반)
- 디지털 멀티미터 (Mastech MS8217)
- 와이어 스트리퍼 & 커터 (18-10 AWG / 0.75-4mm²)
앱 및 온라인 서비스
- 아두이노 IDE
- Blynk
- ThingSpeak API
프로젝트 개요
동기
플라스틱 물병은 어디로 갈까요? 매립지, 바다, 강, 보도 위에 떠 있습니다. 해양 1제곱마일당 약 46,000개의 플라스틱 쓰레기가 떠다니는 것으로 추정됩니다. 이 플라스틱은 동물을 죽이고, 화학 물질을 유출시키며, 생태계를 교란시킵니다. 병 하나가 분해되는 데 최대 1,000년이 걸리며, 그 과정에서 발암 물질과 생식 장애를 유발할 수 있는 독성 물질이 누출됩니다. 플라스틱 소각 시 일산화탄소, 염소, 염산, 퓨란, 아질산염 등 유독 가스가 발생합니다. 안타깝게도 재활용 주장만으로는 한계가 있습니다. 연간 사용되는 350억 개의 병 중 단 12%만 재활용되며, 재활용 통에 넣은 것의 절반만 실제로 재활용됩니다.
아이디어
플라스틱 및 금속 폐기물을 처리하는 스마트 머신은 페트병과 캔을 받아 재활용하고, 사용자에게 지갑에 포인트를 지급합니다. 역자판기는 근접 센서로 병 종류를 구분하고, 사용자가 웹사이트에 코드를 입력하면 포인트가 적립됩니다. 이 발명은 플라스틱 및 금속 폐기물(병)의 환경 관리 및 재활용과 관련됩니다. 환경에 버려지는 플라스틱 쓰레기와 재활용에 대한 낮은 참여는 모든 생물에게 지속적인 문제입니다.

작동 원리
역자판기는 사용한 음료 용기를 받아들이고 사용자에게 돈을 돌려주는 장치로(일반 자판기의 역순환), 의무 재활용법이나 용기 보증금 제도가 있는 지역에서 인기가 있습니다.
기본 동작: 사용자가 빈 병/캔을 투입구에 넣으면 수평 이송 시스템이 한 번에 하나씩 용기를 받아들입니다. 병/캔은 정전용량 및 유도 근접 센서로 자동 스캔됩니다. 유도 센서 값이 1이면 금속, 유도 센서 0이고 정전용량 센서 1이면 플라스틱으로 판별합니다.
보상 시스템: 기존 RVM은 동전이나 쿠폰을 지급하지만, 종이 사용 감소를 위해 본 시스템에서는 플라스틱 감지 시 LCD에 암호화된 코드가 표시됩니다. 사용자는 기계의 QR 코드를 스캔해 웹사이트로 이동한 후 LCD의 코드를 입력해 포인트를 교환합니다.

웹사이트 계정이 필수이며, 로그인 후 코드 입력으로 포인트를 교환합니다.
추가 기능: 기계가 가득 차면 초음파 센서와 NodeMCU로 수위를 모니터링하고, GPS로 정확한 위치를 수거 업체에 알립니다.

코드
폐기물 분류 (C/C++)
#include <LiquidCrystal.h>
#include <Servo.h>
LiquidCrystal lcd(1,2,4,5,6,7);
const int knapp = 3;
int ButtonState = 0;
int oldButtonState = 0;
const int ledPin1 = 10;
const int ledPin2 = 11;
const int buzz1 = 12;
const int buzz2 = 13;
const int plasticsensor = A0;
int metalsensor = A1;
int metalsensor_M = A2;
Servo myservo;
Servo myservo_M;
int pos = 90;
int pos_M = 360;
void setup() {
pinMode(knapp, INPUT);
digitalWrite(knapp, LOW);
lcd.begin(16,2);
lcd.clear();
myservo.attach(9);
myservo_M.attach(8);
pinMode(plasticsensor, INPUT_PULLUP);
pinMode(metalsensor, INPUT_PULLUP);
pinMode(metalsensor_M, INPUT_PULLUP);
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(buzz1, OUTPUT);
pinMode(buzz2, 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 sensor_read = digitalRead(plasticsensor);
Serial.println("plastic sensor");
Serial.println(sensor_read);
int sensor_read_m = digitalRead(metalsensor);
Serial.println("metal sensor1");
Serial.println(sensor_read_m);
int sensor_read_mm = digitalRead(metalsensor_M);
Serial.println(sensor_read_mm);
// 플라스틱 감지 시 서보 동작
if ((sensor_read == 1) && (sensor_read_m != 1)) {
for (pos = 90; pos <= 240; pos += 1) {
myservo.write(pos);
digitalWrite(ledPin1, HIGH);
digitalWrite(buzz1, HIGH);
}
for (pos = 240; pos >= 90; pos -= 1) {
myservo.write(pos);
}
} else {
myservo.write(pos);
digitalWrite(ledPin1, LOW);
digitalWrite(buzz1, LOW);
}
// 금속 감지 시 서보 동작
if ((sensor_read_mm == 1) && (sensor_read == 0)) {
for (pos_M = 360; pos_M >= 50; pos_M -= 1) {
myservo_M.write(pos_M);
digitalWrite(ledPin2, HIGH);
digitalWrite(buzz2, HIGH);
}
for (pos_M = 50; pos_M <= 360; pos_M += 1) {
myservo_M.write(pos_M);
}
} else {
myservo_M.write(pos_M);
digitalWrite(ledPin2, LOW);
digitalWrite(buzz2, LOW);
}
}
쓰레기통 수위 모니터링 (C/C++ - NodeMCU용)
#include "ThingSpeak.h"
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#define BLYNK_PRINT Serial
#define TRIGGER2 5
#define ECHO2 4
WiFiClient client;
static const int RXPin = 4, TXPin = 5;
static const uint32_t GPSBaud = 9600;
unsigned long myChannelField = 1067056;
const int ChannelField = 1;
const char * myWriteAPIKey = "FMV95MD2A1J7Y8SP";
TinyGPSPlus gps;
WidgetMap myMap(V0);
SoftwareSerial ss(RXPin, TXPin);
BlynkTimer timer;
char auth[] = "YVvgHBx9fIM1-yR_2XrGXXkKdIuEmrYL";
char ssid[] = "diksha";
char pass[] = "diksha19";
unsigned int move_index = 1;
void setup() {
Serial.begin(115200);
ss.begin(GPSBaud);
Blynk.begin(auth, ssid, pass);
pinMode(TRIGGER2, OUTPUT);
pinMode(ECHO2, INPUT);
pinMode(BUILTIN_LED, OUTPUT);
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client);
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
while (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass);
Serial.print(".");
delay(100);
}
Serial.println("\nConnected.");
}
while (ss.available() > 0) {
if (gps.encode(ss.read())) {
Serial.println("GPS Connected");
if (gps.location.isValid()) {
float latitude = gps.location.lat();
float longitude = gps.location.lng();
Serial.print("LAT: "); Serial.println(latitude, 6);
Serial.print("LONG: "); Serial.println(longitude, 6);
ThingSpeak.setField(3, latitude);
ThingSpeak.setField(4, longitude);
ThingSpeak.writeFields(myChannelField, myWriteAPIKey);
Blynk.virtualWrite(V1, String(latitude, 6));
Blynk.virtualWrite(V2, String(longitude, 6));
myMap.location(move_index, latitude, longitude, "GPS_Location");
}
}
}
long duration2, distance2;
digitalWrite(TRIGGER2, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER2, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER2, LOW);
duration2 = pulseIn(ECHO2, HIGH);
distance2 = (duration2 / 2) / 29.1;
if (distance2 <= 5) {
Blynk.notify("Please!! empty the dustbin");
}
Serial.println("2 ultrasonic Centimeter:");
Serial.println(distance2);
Blynk.virtualWrite(V6, distance2);
ThingSpeak.writeField(myChannelField, ChannelField, distance2, myWriteAPIKey);
delay(100);
Blynk.run();
timer.run();
}
회로도
