Prezentarea pe scurt a proiectului:
Acest DeskBin are drept functionalitate principala deschiderea automata. Acest lucru se realizeaza in felul urmator:
A doua functionalitate consta in raportarea nivelului de umplere. Aceste date sunt preluate de cel de-al doilea senzor ultra-sonic pozitionat in capacul cosului, fiind legat la un led RGB. Astfel, daca DeskBin-ul nu e plin, led-ul RGB va sta aprins pe verde, respectiv daca este plin, va sta aprins pe rosu, dezactivand senzorul de deschidere pana va fi golit.
A treia functionalitate este cea a ecranului LCD. In functie de nivelul de umplere, va afisa emoji-uri cu diferite stari:
| Componenta | Cantitate |
|---|---|
| Arduino UNO R3 | 1 |
| Servo-motor SG90 | 1 |
| Senzor ultra-sonic HC-SR04 | 2 |
| Display LCD 2004A IIC | 1 |
| Adaptor display PCF8574 | 1 |
| Led RGB | 1 |
| Fire T-T, M-T |
Inainte de toate, am definit:
In functia setup() realizez urmatoarele:
In functia loop() se urmeaza acest curs de executie:
In cazul senzorului ultrasonic pentru deschidere, daca distanta este intre 5 si 20 cm (parametru calculat in functie de timp), se va apela
my_servo.write() pe servomotor.
Iar in cazul senzorului ultrasonic pentru nivelul de umplere, culoarea va fi setata prin digitalWrite(pin, level). Totodata, datorita structurii if din loop, se permite deschiderea automata a cosului doar dca inca este spatiu.
Functia set_emoji() este apelata ultima in loop, deoarece ea depinde tot ce a fost executat pana atunci. Practic se reevaluzeaza conditiile de umplere si deschidere pentru a afisa pe LCD un emoji definit anterior. Altfel, default va exista un emoji smiley :)
Mai jos atasez codul:
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define SERVO 12
#define ECHO_PIN_DIST 5
#define TRIGGER_PIN_DIST 6
#define ECHO_PIN_FULL 10
#define TRIGGER_PIN_FULL 8
#define RED_PIN 2
#define BLUE_PIN 3
#define GREEN_PIN 4
#define FULL 15
#define MIN_DIST 5
#define MAX_DIST 20
// servo
Servo my_servo;
// display
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
byte eyeLeftUp[] = {
0x0F,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10
};
byte eyeLeftDown[] = {
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x0F
};
byte eyeRightUp[] = {
0x1E,
0x01,
0x01,
0x01,
0x01,
0x01,
0x01,
0x01
};
byte eyeRightDown[] = {
0x01,
0x01,
0x01,
0x01,
0x01,
0x01,
0x01,
0x1E
};
byte eyeVerticalLeft[] = {
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10
};
byte eyeVerticalRight[] = {
0x01,
0x01,
0x01,
0x01,
0x01,
0x01,
0x01,
0x01
};
byte eyeHorizontalUp[] = {
0x1F,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
byte eyeHorizontalDown[] = {
0x00,
0x00,
0x1F,
0x1F,
0x1F,
0x1F,
0x1F,
0x1F
};
byte smileyMouth[] = {
0x00,
0x00,
0x00,
0x00,
0x00,
0x10,
0x11,
0x0E
};
byte eatingMouth[] = {
0x00,
0x00,
0x0E,
0x11,
0x11,
0x11,
0x11,
0x0E
};
byte sleepyEye[] = {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x1F,
0x1F
};
byte satiatedMouth[] = {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
// Reset trigger to LOW
void reset_trigger(int trigger_pin)
{
digitalWrite(trigger_pin, LOW);
delayMicroseconds(5000);
digitalWrite(trigger_pin, HIGH);
delayMicroseconds(5000);
digitalWrite(trigger_pin, LOW);
}
void createSatiatedMouth() {
lcd.createChar(12, satiatedMouth);
}
void printSatiatedMouth() {
lcd.setCursor(9, 3);
lcd.write(12);
}
void createSmileyMouth() {
lcd.createChar(9, smileyMouth);
}
void printSmileyMouth() {
lcd.setCursor(9, 3);
lcd.write(9);
}
void createOpenMouth() {
lcd.createChar(10, eatingMouth);
}
void printOpenMouth() {
lcd.setCursor(9, 3);
lcd.write(10);
}
void createSleepyEye() {
lcd.createChar(11, sleepyEye);
}
void printSleepyEye(int val) {
int i = val;
lcd.setCursor(i + 3, 2);
lcd.write(11);
lcd.setCursor(i + 4, 2);
lcd.write(11);
}
void printSleepyEyes() {
printSleepyEye(0);
printSleepyEye(12);
}
// construct every component of emoji
void createNormalEye() {
lcd.createChar(1, eyeLeftUp);
lcd.createChar(2, eyeLeftDown);
lcd.createChar(3, eyeRightUp);
lcd.createChar(4, eyeRightDown);
lcd.createChar(5, eyeVerticalLeft);
lcd.createChar(6, eyeVerticalRight);
lcd.createChar(7, eyeHorizontalUp);
lcd.createChar(8, eyeHorizontalDown);
}
void printNormalEye(int val) {
int i = val;
lcd.setCursor(i + 2, 0);
lcd.write(1);
lcd.setCursor(i + 2, 2);
lcd.write(2);
lcd.setCursor(i + 5, 0);
lcd.write(3);
lcd.setCursor(i + 5, 2);
lcd.write(4);
lcd.setCursor(i + 2, 1);
lcd.write(5);
lcd.setCursor(i + 5, 1);
lcd.write(6);
lcd.setCursor(i + 3, 0);
lcd.write(7);
lcd.setCursor(i + 4, 0);
lcd.write(7);
lcd.setCursor(i + 3, 2);
lcd.write(8);
lcd.setCursor(i + 4, 2);
lcd.write(8);
}
void printNormalEyes() {
printNormalEye(0);
printNormalEye(12);
}
/* print emojies functions */
void printEatingEmoji() {
printNormalEyes();
printOpenMouth();
}
void printSleepingEmoji() {
printSleepyEyes();
printOpenMouth();
}
void printSmileyEmoji() {
printNormalEyes();
printSmileyMouth();
}
void printSatiatedEmoji() {
printNormalEyes();
printSatiatedMouth();
}
void setup()
{
// initialize the lcd
lcd.init();
lcd.backlight();
lcd.clear();
// init face components
createNormalEye();
createSleepyEye();
createSmileyMouth();
createOpenMouth();
createSatiatedMouth();
// init servo
my_servo.attach(SERVO);
// init open ultrasonic sensor
pinMode(TRIGGER_PIN_DIST, OUTPUT);
pinMode(ECHO_PIN_DIST, INPUT);
// init full ultrasonic
pinMode(TRIGGER_PIN_FULL, OUTPUT);
pinMode(ECHO_PIN_FULL, INPUT);
// init rgb led
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
delay(100);
Serial.begin(9600);
}
float get_distance(int echo_pin)
{
float dist;
// set pin
pinMode(echo_pin, INPUT);
// get distance to hand
long duration = pulseIn(echo_pin, HIGH);
// distance in cm (converted from time)
dist = duration / 58.82;
return dist;
}
void open_trash_by_hand(float dist)
{
int pos;
if (dist <= MAX_DIST && dist >= MIN_DIST) {
pos = 90;
my_servo.write(pos);
delay(50);
}
else {
pos = 0;
my_servo.write(pos);
}
}
// check if deskbin is full
void check_content(float dist_full) {
if (dist_full <= FULL) {
// turn red led on
digitalWrite(RED_PIN, HIGH);
digitalWrite(GREEN_PIN, LOW);
}
else {
// turn green led on
digitalWrite(RED_PIN, LOW);
digitalWrite(GREEN_PIN, HIGH);
delay(1000);
}
}
void set_emoji(int dist_hand, int dist_full) {
if (dist_full <= FULL) {
printSatiatedEmoji();
delay(100);
} else if (dist_hand <= MAX_DIST && dist_hand >= MIN_DIST) {
printEatingEmoji();
delay(500);
} else {
printSmileyEmoji();
}
}
void loop()
{
/* full ultrasonic */
// reset
reset_trigger(TRIGGER_PIN_FULL);
// get dist(sensor, garbage)
float dist_full = get_distance(ECHO_PIN_FULL);
// activate led depending on status
check_content(dist_full);
float dist_hand;
if (dist_full <= FULL) {
// is full
} else {
/* open sensor*/
// reset
reset_trigger(TRIGGER_PIN_DIST);
// get dist(sensor, hand)
dist_hand = get_distance(ECHO_PIN_DIST);
// activate servo if dist_hand in range(MIN_DIST, MAX_DIST)
open_trash_by_hand(dist_hand);
}
/* set emoji */
set_emoji(dist_hand, dist_full);
}
Cand exista spatiu si este in asteptare, apare smiley_emoji, iar ledul este verde
Cand este deschis, apare eating_emoji
Cand nu mai exista spatiu, apare satiated_emoji, iar ledul devine rosu
Iar aici, alte detalii
Realizarea acestui proiect a fost o experienta frumoasa si utila. A fost primul meu proiect cu micro-controller si pot spune ca este un sentiment rewarding in final.
Principala dificultate pe care am intampinat-o a fost gasirea pe internet a modului de legare pentru un LCD 2.8 inch ILI9341, fara pin CS. Drept urmare, am gasit alternativa LCD 2004A IIC, care s-a pretat foarte bine genului de aplicatie al proiectului.