LoM project - Smart Recycle Bin

Da raspibo.
Versione del 18 lug 2019 alle 10:11 di Laura (discussione | contributi) (Creata pagina con '== Software == Per l’esecuzione del codice si è deciso di creare un ambiente virtuale python all'interno dell'utente <code>pi</code> del Raspberry. Questo permette di evit...')
(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)
Jump to navigation Jump to search

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.