Constantino Rivera Palacios
Published © GPL3+

Intelligent Trash Containers (ITC)

The Intelligent Trash Container (ITC) provides real time information to create a time and energy efficient waste system.

BeginnerFull instructions provided5 hours248

Things used in this project

Hardware components

AVR IoT Mini Cellular Board
Microchip AVR IoT Mini Cellular Board
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE
IO Adafruit
Fusion 360
Autodesk Fusion 360

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

Container STL files

Schematics

ITC Schematics

Code

ITC code

C/C++
// Intelligent Trash Containers (ITC)
// Author: Constantino Rivera Palacios 

// Hacksterio IoT The Future of Resilience Contest

// Libraries
#include <Arduino.h>
#include <mcp9808.h>
#include <Servo.h>
#include <mqtt_client.h>
#include <lte.h>


// Definitions
#define Trigger PIN_PD0
#define Echo PIN_PB5
#define SW0 PIN_PD2
#define SW1 PIN_PF6

#define MQTT_THING_NAME "ITC"
#define IO_USERNAME  "constanripa"
#define IO_KEY       // Here goes the key
#define MQTT_USE_TLS       false
#define MQTT_KEEPALIVE     60
#define MQTT_USE_ECC       false
#define AIO_SERVER   "io.adafruit.com"
#define AIO_SERVERPORT 1883
#define MQTT_PUB_TOPIC1 "constanripa/feeds/log"
#define MQTT_PUB_TOPIC2 "constanripa/feeds/full"            // 0
#define MQTT_PUB_TOPIC3 "constanripa/feeds/temperature"     // 1
#define MQTT_PUB_TOPIC4 "constanripa/feeds/trash"           // 2

Servo servo;

// Variables
long cm, duration;
volatile char new_trash = false;
unsigned long int last_time_tem, last_time_pressed; 
//unsigned long int period_ms_tem = 3600000;  // Periodic measurements: 1 h for temperature
unsigned long int period_ms_tem = 60000;
unsigned long int reset = 5000;               // Reset at 5 s of Sw0 pressed
char full = false;


void sw0_pressed(){
  new_trash = true;                           // Someone wants to use the container
  Serial3.println("Someone is introducing trash");
}

void publishing_log(String string){

      // Attempt to connect to the broker
  if(MqttClient.begin(MQTT_THING_NAME,
                         AIO_SERVER,
                         AIO_SERVERPORT,
                         MQTT_USE_TLS,
                         MQTT_KEEPALIVE,
                         MQTT_USE_ECC,
                         IO_USERNAME,
                         IO_KEY)){
                          
        Serial3.println("MQTT connection established");
        bool publishedSuccessfully = MqttClient.publish(MQTT_PUB_TOPIC1, string.c_str());
        if (publishedSuccessfully) {
            Serial3.print("Published message: ");
            Serial3.println(string);                      
        } else {
            Serial3.println("Failed to publish");
        }
        Serial3.println("Closing MQTT connection");

        }else{
        Serial3.println("Connection to MQTT failed");
        }

        MqttClient.end();
}


void publishing_data(char opt, String num){
  bool publishedSuccessfully;

      // Attempt to connect to the broker
  if(MqttClient.begin(MQTT_THING_NAME,
                         AIO_SERVER,
                         AIO_SERVERPORT,
                         MQTT_USE_TLS,
                         MQTT_KEEPALIVE,
                         MQTT_USE_ECC,
                         IO_USERNAME,
                         IO_KEY)){
                          
        Serial3.println("MQTT connection established");
        switch(opt){
          case 0:
            publishedSuccessfully = MqttClient.publish(MQTT_PUB_TOPIC2, num.c_str());
          break;
          case 1:
            publishedSuccessfully = MqttClient.publish(MQTT_PUB_TOPIC3, num.c_str());
          break;
          case 2:
            publishedSuccessfully = MqttClient.publish(MQTT_PUB_TOPIC4, num.c_str());
          break;
          default:
          Serial3.println("ERROR");          
        }

        if (publishedSuccessfully) {
            Serial3.print("Published message: ");
            Serial3.println(num);                      
        } else {
            Serial3.println("Failed to publish");
        }
        Serial3.println("Closing MQTT connection");
        delay(2000);
        
   }else{
        Serial3.println("Connection to MQTT failed");
        }

        MqttClient.end();
}

// Setup code
void setup() {
  
  Serial3.begin(115200);
  Serial3.println(F("Powered on AVR IoT Cellular Mini"));
  
  pinMode(Trigger, PIN_DIR_OUTPUT);
  pinMode(Echo, PIN_DIR_INPUT);
  pinConfigure(SW0, PIN_DIR_INPUT | PIN_PULLUP_ON);

  servo.attach(PIN_PE1);
  servo.write(0);
  
      // Establish LTE connection
  if (!Lte.begin()) {
        Serial3.println("Failed to connect to operator");

        // Halt here
        while (1) {}
  }
  Serial3.println("Connected to operator");

 // LteClient client;

  if (Mcp9808.begin(0x18)){
    Serial3.println("Could not initialize the Temperature sensor");
  }
    Serial3.println("MCP9808 initialized!"); 

  attachInterrupt(digitalPinToInterrupt(SW0), sw0_pressed, FALLING);
  
  last_time_tem = millis();  
}

// Loop code
void loop() {

  if( (millis() - last_time_tem) > period_ms_tem){ 
    // Temperature
    int TempC = (int)Mcp9808.readTempC();
    int Temp = ((TempC - 32) * 5 / 9);      // Conversion to ºC
    Serial3.println("Temperature: ");
    Serial3.print(TempC);
    Serial3.println(" ºF");
    Serial3.print(Temp);
    Serial3.println(" ºC");
    publishing_data(1, (String) Temp);
    last_time_tem = millis();
   
  }

  if(new_trash && !full ){     // Only opens if button pressed and it's not full
    float volume = 0;
    servo.write(90);
    publishing_log("Someone is dumping trash");
    delay(8000);                   // 10 s delay to let users throw the trash
    digitalWrite(Trigger, LOW);
    delayMicroseconds(5);
    digitalWrite(Trigger, HIGH);
    delayMicroseconds(10);
    digitalWrite(Trigger, LOW);
  
    pinMode(Echo, INPUT);
    duration = pulseIn(Echo, HIGH);
    cm = (duration/2) / 29.1;     
    Serial3.print("Distance = ");
    Serial3.print(cm);
    Serial3.println(" cm");
    volume = (float) (((15 - cm) * 100)/ 13);  // 15 cm but 12 are in range of measurement
    if( cm > 0 && cm < 6){
    full = true;
    Serial3.println("Container is full!");
    publishing_log("Container is full. Please empty");
    publishing_data(0, "1");
    detachInterrupt(digitalPinToInterrupt(SW0));                                       // Button no longer responds to users as it is full
    }
    publishing_data(2, (String) volume);
    servo.write(0); 
    digitalWrite(PIN_PE1, LOW);
    
    new_trash = false;
  }

  if(!digitalRead(SW0)){
    last_time_pressed = millis();
  
    while(!digitalRead(SW0)){}
  
    if( (millis() - last_time_pressed ) > reset){
      full = false;
      Serial3.println("Container has been emptied");
      publishing_log("Container has been emptied");
      publishing_data(0, "0");      // Off indicator
      publishing_data(2, "0");      // Reset trash levels
      attachInterrupt(digitalPinToInterrupt(SW0), sw0_pressed, FALLING);
    }
  }
  
}

Credits

Constantino Rivera Palacios

Constantino Rivera Palacios

1 project • 1 follower

Comments