LoM project - Smart Recycle Bin

Da raspibo.
Versione del 18 lug 2019 alle 14:20 di Laura (discussione | contributi) (→‎Conclusioni e sviluppi futuri)
(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)
Jump to navigation Jump to search

Introduzione

Smart Recycle Bin consiste in una scatola progettata per il riconoscimento e la differenziazione dei rifiuti: carta, vetro, plastica e indifferenziato.

Scopo del progetto: l’utente ripone nello Smart Recycle Bin un oggetto da cestinare, di questo viene riconosciuto il materiale ed è cestinato nel bidone corrispondente.

Smart.jpeg

Tutto il lavoro è stato sviluppato attraverso Raspberry Pi 3 B+ e Arduino Uno, con la scrittura del codice in Python nel primo caso e in C++ nel secondo.

Un video dimostrativo si trova al seguente link: YouTube - Smart Recycle Bin

Materiali e componenti utilizzati

Componenti elettronici

  • 2 servo motori MG 996R
  • Motore passo passo bipolare Nema 17 con shield L293D
  • Raspberry Pi Camera
  • Breadboard
  • Bottone e led
  • Alimentatori vari

Altri materiali

  • Scatola di cartone
  • Assi di legno
  • Viti, chiodi e simili
  • Cinghia di gomma
  • Quattro ruote

Fasi di lavoro

Per la costruzione della pattumiera si è utilizzata una scatola di cartone.

L'identificazione del materiale del rifiuto avviene mediante una fotografia scattata dalla pi camera; questa è fissata ad un supporto in cartone la cui posizione consente un'inquadratura ottimale.

In questa stessa struttura è stato inserito il Raspberry e molti dei componenti elettronici utilizzati nel progetto.

Strumenti pilotati tramite Raspberry Pi

Per comunicare al sistema la presenza del rifiuto nella scatola, l'utente deve premere il bottone. Quest'azione innesca l'attivazione dell'intero sistema.

Per il riconoscimento del materiale dell'oggetto è stata utilizzata una Pi Camera, la quale scatta una foto. Questa a sua volta, è elaborata dalle API di Clarifai che restituiscono una risposta dalla quale estrapolare il materiale.

Sul fondo della scatola è stata aperta una porticina dalla quale verrà espulso l’oggetto da cestinare. Lo strumento che permette di aprire e chiudere la porta è un oggetto molto simile ad una carrucola, costruito con un pezzo di legno e del filo, ed azionato mediante un servo motore. Inoltre è stata realizzata una serratura, pilotata da un altro servo motore, che permette di tenere bloccata la porta quando questa è chiusa.

Infine, alla scatola sono state fissate delle ruote che consentono il suo movimento lungo la struttura in legno su cui poggia. La scatola, dotata di ruote, viene spostata da una cinghia di gomma fissata al suo fondo e connessa direttamente con il motore passo passo.

Smart-scatola.jpg

Strumenti pilotati tramite Arduino

La gestione del movimento della scatola è ottenuta con il motore passo passo. Per regolare il flusso di corrente necessario per azionare il motore stesso, è stato utilizzato uno shield L293D.

Foto-passopasso.jpg

Assemblaggio del circuito

Realizzata la struttura si passa all’assemblaggio del circuito e delle componenti elettroniche, come mostrato nello schema di seguito.

Circuito.png

Comunicazione tra Rspberry Pi e Arduino

Progettate le singole parti è ora di assemblarle e farle comunicare! Il modo più semplice per fare ciò è utilizzare un connettore USB e collegare direttamente tra loro le due schede configurando la comunicazione seriale.

Software

Per l’esecuzione del codice si è deciso di creare un ambiente virtuale python all'interno dell'utente pi del Raspberry. Questo permette di evitare conflitti nell'utilizzo delle librerie necessarie per il progetto. La creazione dell’ambiente è stata eseguita da terminale utilizzando virtualenv con il seguente comando:

virtualenv –p python riciclo

Per attivare e disattivare l'ambiente i comandi sono rispettivamente:

. /riciclo/bin/activate 
deactivate

Attivato l'ambiente si eseguono i seguenti comandi per aggiornare l'ambiente e per installare le librerie necessarie:

sudo apt-get update
pip freeze 
# installazione delle API di Clarifai e verifica del loro funzionamento
pip install clarifai 
python –c ‘from clarifai.rest import clarifaiApp’
# installazione del software di PiCamera
pip install picamera
# installazione della libreria per i pin I/O di Raspberry
pip install RPi.GPIO
# installazione della libreria per la comunicazione seriale Raspberry - Arduino
pip install pyserial

Di seguito si riporta il codice python con il codice implementato.

from picamera import PiCamera
from clarifai.rest import ClarifaiApp
import RPi.GPIO as GPIO
import json
import time
import datetime
from serial import Serial
 
# setup comunicazione seriale con arduino
arduino = Serial('/dev/ttyACM0', 9600)
time.sleep(2)
 
# PIN utilizzati su Raspberry
button = 12
led = 11
pulley_servo = 16
lock_servo = 18
 
# setup GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(lock_servo, GPIO.OUT)
GPIO.setup(pulley_servo, GPIO.OUT)
GPIO.setup(button, GPIO.IN, pull_up_down = GPIO.PUD_UP) 
GPIO.setup(led, GPIO.OUT)
 
# setup camera
camera = PiCamera()
 
# setup led
GPIO.output(led, GPIO.LOW)
led_status = False
 
# setup serratura e carrucola
lock = GPIO.PWM(lock_servo, 50)
pully = GPIO.PWM(pulley_servo, 50)
lock.start(0)
pully.start(0)

# apertura file di log
f = open("recycle_bin_log.txt" ,"a+")

# funzione per la comunicazione con Arduino per avviare lo stepper   
def start_stepper(input):
    arduino.write(input)
    c = True
    while c:
        r = arduino.readline()
        if r == 'ok\n':
            f.write("Stepper end movement with response: " + r)
        c = False
 
# funzione per il riconoscimento del materiale
def material_recognition(): 
    # setup clarifai
    app = ClarifaiApp(api_key='**************************************')
    model = app.public_models.general_model
    # richiesta alle API
    response = model.predict_by_filename('/home/pi/riciclo/codici/image-recognition.jpg')
    array = response["outputs"][0]["data"]["concepts"]
 
    object_material = ['unknow', 0]
    materials_list = ('plastic', 'glass', 'paper')
 
    # lettura della risposta e selezione del materiale 
    for el in array:
        keyword = el['name']
        value = el['value']
        for material in materials_list:
            if (keyword == material) and (int(object_material[1]) < value):
                object_material = (material, value)
 
    # il materiale è...
    f.write("Material: " + object_material[0] + "\n") 
    return object_material[0]

# funzione per l'attivazione dei servomotori
def start_servo():
    # si srotola la carruola
    pully.ChangeDutyCycle(2) 
    time.sleep(0.5)
    # si apre la porta
    lock.ChangeDutyCycle(2)
    time.sleep(4)
    # si arrotola la carrucola
    pully.ChangeDutyCycle(5) 
    time.sleep(0.5)
    # si chiude la porta
    lock.ChangeDutyCycle(5)
    time.sleep(0.5)
    # si allenta la carrucola
    pully.ChangeDutyCycle(3)

# avvio del sistema
try:
    f.write("System started - {:%Y-%m-%d %H:%M:%S} \n".format(datetime.datetime.now()))
    while True:
        # attesa dell'evento: "l'utente preme il bottone"
        channel = GPIO.wait_for_edge(button, GPIO.FALLING)
        if channel == button:
            # se il led è spento (quindi il sistema non è attivo)... 
            if led_status == False:
                #  accendiamo il led e attiviamo il sistema
                led_status = not led_status
                GPIO.output(led, led_status)
                f.write("led on - system activation\n")

                # attvazione della PiCamera e scatto della foto
                camera.rotation = 180
                camera.start_preview()
                time.sleep(0.5)
                camera.capture('/home/pi/riciclo/codici/image-recognition.jpg') 
                camera.stop_preview()

                # riconoscimento materiale
                object_material = material_recognition()

                # attivazione del movimento della scatola   
                if obj_mat == 'glass':
                    start_servo()
                elif obj_mat == 'unknow':
                    start_stepper('1')
                    start_servo()
                    start_stepper('2')
                elif obj_mat == 'plastic':
                    start_stepper('3')
                    start_servo()
                    start_stepper('4')
                else:
                    start_stepper('5')
                    start_servo()
                    start_stepper('6')

                # disattivazione del sistema e spegnimento del led
                led_status = not led_status
                GPIO.output(led, led_status)
                f.write("led off - system deactivation\n")

except KeyboardInterrupt:
    print("Cleaning up")
    GPIO.output(led, GPIO.LOW)
    lock.stop()
    pully.stop()
    GPIO.cleanup()
    f.write("System stopped - {:%Y-%m-%d %H:%M:%S} \n".format(datetime.datetime.now()))
    f.close()

Nelle righe che seguono, invece, riportiamo il codice C++ implementato per il funzionamento del motore passo passo tramite Arduino.

#include <AFMotor.h>

// Number of steps per output rotation
const int stepsPerRevolution = 200;

//input ricevuto da raspberry che indica quali comandi eseguire
int attuale;   
int precedente = 0;

// connessione del motore alla prota #1 (M1 and M2)
AF_Stepper motor(stepsPerRevolution, 1);

/*
 * comando: 1 -> vai da 1 a 0 (vai su indifferenziato)
 *          2 -> vai da 0 a 1 (torna da indifferenziato a posizione base) 
 *          3 -> vai da 1 a 2 (vai su plastica)
 *          4 -> vai da 2 a 1 (torna da plastica a posizione base) 
 *          5 -> vai da 1 a 3 (vai su carta)
 *          6 -> vai da 3 a 1 (torna da carta a posizione base) 
*/
void spostaMotore(int comando){

  //vai in posizione 0 (indifferenziato)
  if(comando == 1){
    motor.step(1280, FORWARD, SINGLE);
  }
  //torna in posizione 1 da posizione 0
  else if(comando == 2){
    motor.step(1280, BACKWARD, SINGLE); 
  }
  //vai in posizione 2 (plastica)
  else if(comando == 3){
    motor.step(1280, BACKWARD, SINGLE);
  }
  //torna in posizione 1 da posizione 2
  else if(comando == 4){
    motor.step(1280, FORWARD, SINGLE); 
  }
  //vai in posizione 3 (carta)
  else if(comando == 5){
    motor.step(1280*2, BACKWARD, SINGLE);
  }
  //torna in posizione 1 da posizione 3
  else if(comando == 6){
    motor.step(1280*2, FORWARD, SINGLE); 
  }
  
  Serial.print("ok\n");
  motor.release();
  
}

void setup() {
  Serial.begin(9600);
  motor.setSpeed(60); //velocita (in rpm (revolution per minute))
}

void loop() {
  if(Serial.available()){
    attuale = Serial.read() - '0';
  }
  if(precedente != attuale){
    precedente = attuale;
    spostaMotore(attuale);
  }  
}

Per permettere all'utente di utilizzare lo Smart Recycle Bin senza un dispositivo dal quale farlo partire (display), è necessario abilitare l'avvio automatico dello script python all’accensione del sistema operativo. Per fare ciò si implementa uno script bash che attivi l’ambiente virtuale e che avvii successivamente il codice python. Lo script bash è il seguente:

#!/bin/bash
sleep 120
source /home/pi/riciclo/bin/activate
python /home/pi/riciclo/codici/recycle.py

Successivamente occorre aggiungere le righe seguenti al file crontab in modo che esegua lo script bash ad ogni riavvio del sistema.

PATH=/home/pi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/home/pi/.local/bin
@reboot /bin/bash /home/pi/riciclo/codici/avvio.sh > /home/pi/riciclo/codici/logsAvvio/cronlog 2>&1

N.B. Affinchè il software funzioni correttamente è necessario mantenere il Raspberry connesso ad internet.

Conclusioni e sviluppi futuri

In una fase successiva molti sono gli sviluppi che potrebbero essere realizzati.

Di seguito relazioniamo alcune idee:

  • Per esigenze di spazio, lo smart recycle bin può essere costruito in taglie e forme differenti.
  • Riconoscimento del materiale mediante codice a barre: avvicinare il codice a barre dei prodotti a un lettore e gettare i rifiuti all’interno della pattumiera, a smistare i prodotti in base al materiale ci penserà il prodotto inventato.
  • La pattumiera può essere dotata di un compattatore per la riduzione del volume dei rifiuti e appositi sensori che riconoscano i materiali per smaltirli in maniera più veloce
  • Si potrebbe pensare di implementare nuove funzionalità capaci di smaltire l’umido
  • Nel caso in cui l'oggetto non venga riconosciuto mediante le modalità esposte precedentemente, si potrebbe pensare di mettere un display su cui appare un invito rivolto all'utente a premere un tasto, collocato sulla struttura, corrispondente al materiale che sta gettando
  • Sensori di peso posti sotto ai cestini e collegati ad un display su cui appare un messaggio che permette di capire quando uno di questi è pieno
  • Se la struttura su cui si muove la pattumiera è orizzontale, similmente alla nostra, si potrebbe migliorare il movimento del motore passo passo aggiungendo un sensore alla pattumiera, il quale permette di rilevare dei segnali posti sui binari. Questi ultimi indicherebbero al motore passo passo la posizione sulla quale dovrà fermarsi.

Presto decidere se l'oggetto va nella plastica o nel vetro non sarà più uno stress: con la pattumiera intelligente.

Il pianeta ve ne sarà grato!