Buzón inteligente

Autores

  • Mohibul Alom
  • Cristofer Tamaral Martín
  • Adrián Martín Martín

Objetivo

Tenemos como objetivo desarrollar un proyecto de un sistema empotrado o embebido. Estos sistemas están orientados en cubrir una necesidad en concreto. En nuestro caso, hemos optado por integrar funciones nuevas a nuestro buzón que todos tenemos en nuestras casas. Además, tenemos como finalidad aportar seguridad de saber en todo momento el contenido introducido en nuestras casillas casi a diario.

Tareas

  • Tarea 1: ver el contenido del buzón desde cualquier sitio.
  • Tarea 2: detectar cuando se introducido nuevo contenido: cartas, revistas, etc.
  • Tarea 3: tomar una foto del contenido del buzón después de detectar dicho evento.
  • Tarea 4: enviar la foto tomada a nuestra red social, por ejemplo, Telegram.
  • Tarea 5: tener un mecanismo para extraer el contenido del buzón mediante un comando.

Materiales y costes

Placa Arduino Mega: 13.99 €

Módulo wifi: placa ESP32 Y módulo de cámara: OV2640: 11.99 €

Sensor: 1.80 €                                                                                                                                              

Motores: 6.99 €

Driver para el motor L298N: 6.90 €

Madera MDF, bisagra, cerrojo y clavos: 9.90 €

Rueda: 0 € (fabricada con restos de madera).

Total: 51.57 €

Diseño

Conexiones

Montaje

Para realizar la construcción primero se dibujó un boceto en el cual quedaban establecidas las medidas y como iban a ser cada una de las partes de nuestro buzón, quedando los lados con las siguientes medidas:

  • Laterales 25×50 cm.
  • Techo y suelo 30×20 cm.
  • Parte anterior y posterior 30×25 cm.
  • Rampa 32×20 cm.

Estas partes fueron cortadas y posteriormente se procedió a trabajar sobre cada una de ellas. En el techo se realizó una hendidura que actúa como hueco para introducir las cartas. En la cara frontal del buzón se realizó una segunda hendidura la cual actuará como salida de las cartas. En una de las partes laterales se colocaron unas bisagras y un cerrojo para que este lateral actuara como puerta para poder acceder al interior del buzón. En el otro lateral se colocó un motor el cual sujeta una “puerta” la cual se abre y se cierra imitando el mecanismo de un peaje para dejar salir las cartas o mantenerlas dentro. En la rampa se colocó otro motor conectado a una rueda fabricada con madera, esto serviría para impulsar las cartas hacia el exterior, a la rampa también se le colocaron unos bordes laterales para que las cartas si se movían hacia los lados no cayeran ni se quedaran enganchadas en el interior del buzón. La protoboard, la placa de Arduino y el resto de los componentes necesarios para el correcto funcionamiento del buzón fueron colocados en la parte interior del techo fijados con tornillos.

Código

 Código de la placa Arduino Mega:
1 
2   //Boton
3   const int buttonPIN = 30;
4 
5 
6   //Tapa
7   int IN1 = 5;      // IN1 de L298N a pin digital 5
8   int IN2 = 6;      // IN2 de L298N a pin digital 6
9   int ENA = 7;      // ENA de L298N a pin digital 7
10  int VELOCIDAD = 200;      // variable para almacenar valor de velocidad
11
12  //rampa
13  int IN3 = 8;      // IN1 de L298N a pin digital 8
14  int IN4 = 9;      // IN2 de L298N a pin digital 9
15  int ENB = 10;      // ENA de L298N a pin digital 10
16  int VELOCIDAD_RAMPA = 200;      // variable para almacenar valor de velocidad
17
18
19  //***********************************************************
20
21  int op = 100;
22  int opB = 0;
23
24  //pin para el sensor de infrarrojo debe ser PWM (pines con simbolo "~")
25  const int sensorPIN = 4;
26
27  void setup() {
28    pinMode(sensorPIN, INPUT);
29    Serial.begin(115200); // opens serial port, sets data rate to 9600 bps
30
31    pinMode(buttonPIN, INPUT); //pin
32
33    pinMode(12, OUTPUT); //pin led
34    pinMode(13, OUTPUT); //pin led
35
36    pinMode(IN1, OUTPUT);   // pin 5 como salida
37    pinMode(IN2, OUTPUT);   // pin 6 como salida
38    pinMode(ENA, OUTPUT);   // pin 7 como salida
39
40    pinMode(IN3, OUTPUT);   // pin 8 como salida
41    pinMode(IN4, OUTPUT);   // pin 9 como salida
42    pinMode(ENA, OUTPUT);   // pin 10 como salida
43
44  }
45
46  void loop() {
47
48    int button = digitalRead(buttonPIN);
49    int sensor = digitalRead(sensorPIN);
50
51    if (sensor != HIGH) {
52      Serial.write(op);
53      digitalWrite(12, HIGH);
54      delay(500);
55    } else {
56      digitalWrite(12, LOW);
57    }
58
59
60    if (button == HIGH) {
61      Serial.println(button);
62      expulsarcarta();
63      digitalWrite(13, HIGH);
64    } else {
65      digitalWrite(13, LOW);
66    }
67  }
68
69
70  void expulsarcarta() {
71    //subimos tapa arriba
72    analogWrite(ENA, VELOCIDAD);
73    digitalWrite(IN1, HIGH);
74    digitalWrite(IN2, LOW);
75    delay(1000);
76
77    //paramos el motor de la tapa
78    digitalWrite(ENA, LOW);
79
80    //Iniciamos el motor de la rampa hacia adelante
81    analogWrite(ENB, VELOCIDAD_RAMPA);
82    digitalWrite(IN3, LOW);
83    digitalWrite(IN4, HIGH);
84    delay(5000);
85
86    //paramos el motor de la rampa
87    digitalWrite(ENB, LOW);
88
89    //bajamos la tapa hacia abajo
90    analogWrite(ENA, VELOCIDAD);
91    digitalWrite(IN1, LOW);
92    digitalWrite(IN2, HIGH);
93    delay(1000);
94
95    //paramos el motor de la tapa
96    digitalWrite(ENA, LOW);
97
98  }

Código de la placa ESP32CAM:
1   #include <Arduino.h>
2   #include <WiFi.h>
3   #include <WiFiClientSecure.h>
4   #include "soc/soc.h"
5   #include "soc/rtc_cntl_reg.h"
6   #include "esp_camera.h"
7   #include <UniversalTelegramBot.h>
8   #include <ArduinoJson.h>
9  
10  const char* ssid = "MiFibra-F929-24G";
11  const char* password = "FcoVnHm9";
12 
13  // Initialize Telegram BOT
14  String BOTtoken = "1539204514:AAE1ezuvj1cLQ8W3PbbLAR3LvGc9Ciwv00U";  // your Bot Token (Get from Botfather)
15 
16  // Use @myidbot to find out the chat ID of an individual or a group
17  // Also note that you need to click "start" on a bot before it can
18  // message you
19  String CHAT_ID = "1529030408";
20 
21  bool sendPhoto = false;
22 
23  WiFiClientSecure clientTCP;
24  UniversalTelegramBot bot(BOTtoken, clientTCP);
25 
26  #define FLASH_LED_PIN 4
27  bool flashState = LOW;
28 
29  //Checks for new messages every 1 second.
30  int botRequestDelay = 1000;
31  unsigned long lastTimeBotRan;
32 
33  //CAMERA_MODEL_AI_THINKER
34  #define PWDN_GPIO_NUM     32
35  #define RESET_GPIO_NUM    -1
36  #define XCLK_GPIO_NUM      0
37  #define SIOD_GPIO_NUM     26
38  #define SIOC_GPIO_NUM     27
39 
40  #define Y9_GPIO_NUM       35
41  #define Y8_GPIO_NUM       34
42  #define Y7_GPIO_NUM       39
43  #define Y6_GPIO_NUM       36
44  #define Y5_GPIO_NUM       21
45  #define Y4_GPIO_NUM       19
46  #define Y3_GPIO_NUM       18
47  #define Y2_GPIO_NUM        5
48  #define VSYNC_GPIO_NUM    25
49  #define HREF_GPIO_NUM     23
50  #define PCLK_GPIO_NUM     22
51 
52 
53  void configInitCamera() {
54    camera_config_t config;
55    config.ledc_channel = LEDC_CHANNEL_0;
56    config.ledc_timer = LEDC_TIMER_0;
57    config.pin_d0 = Y2_GPIO_NUM;
58    config.pin_d1 = Y3_GPIO_NUM;
59    config.pin_d2 = Y4_GPIO_NUM;
60    config.pin_d3 = Y5_GPIO_NUM;
61    config.pin_d4 = Y6_GPIO_NUM;
62    config.pin_d5 = Y7_GPIO_NUM;
63    config.pin_d6 = Y8_GPIO_NUM;
64    config.pin_d7 = Y9_GPIO_NUM;
65    config.pin_xclk = XCLK_GPIO_NUM;
66    config.pin_pclk = PCLK_GPIO_NUM;
67    config.pin_vsync = VSYNC_GPIO_NUM;
68    config.pin_href = HREF_GPIO_NUM;
69    config.pin_sscb_sda = SIOD_GPIO_NUM;
70    config.pin_sscb_scl = SIOC_GPIO_NUM;
71    config.pin_pwdn = PWDN_GPIO_NUM;
72    config.pin_reset = RESET_GPIO_NUM;
73    config.xclk_freq_hz = 20000000;
74    config.pixel_format = PIXFORMAT_JPEG;
75 
76    //init with high specs to pre-allocate larger buffers
77    if (psramFound()) {
78      config.frame_size = FRAMESIZE_UXGA;
79      config.jpeg_quality = 10;  //0-63 lower number means higher quality
80      config.fb_count = 2;
81    } else {
82      config.frame_size = FRAMESIZE_SVGA;
83      config.jpeg_quality = 12;  //0-63 lower number means higher quality
84      config.fb_count = 1;
85    }
86 
87    // camera init
88    esp_err_t err = esp_camera_init(&config);
89    if (err != ESP_OK) {
90      Serial.printf("Camera init failed with error 0x%x", err);
91      delay(1000);
92      ESP.restart();
93    }
94 
95    // Drop down frame size for higher initial frame rate
96    sensor_t * s = esp_camera_sensor_get();
97    s->set_framesize(s, FRAMESIZE_CIF);  // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
98  }
99 
100 void handleNewMessages(int numNewMessages) {
101   Serial.print("Handle New Messages: ");
102   Serial.println(numNewMessages);
103
104   for (int i = 0; i < numNewMessages; i++) {
105     String chat_id = String(bot.messages[i].chat_id);
106     if (chat_id != CHAT_ID) {
107       bot.sendMessage(chat_id, "Unauthorized user", "");
108       continue;
109     }
110
111     // Print the received message
112     String text = bot.messages[i].text;
113     Serial.println(text);
114
115     String from_name = bot.messages[i].from_name;
116     if (text == "/start") {
117       String welcome = "Welcome , " + from_name + "\n";
118       welcome += "Use the following commands to interact with the ESP32-CAM \n";
119       welcome += "/photo : takes a new photo\n";
120       welcome += "/flash : toggles flash LED \n";
121       bot.sendMessage(CHAT_ID, welcome, "");
122     }
123     if (text == "/flash") {
124       flashState = !flashState;
125       digitalWrite(FLASH_LED_PIN, flashState);
126       Serial.println("Change flash LED state");
127     }
128     if (text == "/photo") {
129       sendPhoto = true;
130       Serial.println("New photo request");
131     }
132   }
133 }
134
135 String sendPhotoTelegram() {
136   const char* myDomain = "api.telegram.org";
137   String getAll = "";
138   String getBody = "";
139
140   camera_fb_t * fb = NULL;
141   fb = esp_camera_fb_get();
142   if (!fb) {
143     Serial.println("Camera capture failed");
144     delay(1000);
145     ESP.restart();
146     return "Camera capture failed";
147   }
148
149   Serial.println("Connect to " + String(myDomain));
150
151
152   if (clientTCP.connect(myDomain, 443)) {
153     Serial.println("Connection successful");
154
155     String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
156     String tail = "\r\n--RandomNerdTutorials--\r\n";
157
158     uint16_t imageLen = fb->len;
159     uint16_t extraLen = head.length() + tail.length();
160     uint16_t totalLen = imageLen + extraLen;
161
162     clientTCP.println("POST /bot" + BOTtoken + "/sendPhoto HTTP/1.1");
163     clientTCP.println("Host: " + String(myDomain));
164     clientTCP.println("Content-Length: " + String(totalLen));
165     clientTCP.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
166     clientTCP.println();
167     clientTCP.print(head);
168
169     uint8_t *fbBuf = fb->buf;
170     size_t fbLen = fb->len;
171     for (size_t n = 0; n < fbLen; n = n + 1024) {
172       if (n + 1024 < fbLen) {
173         clientTCP.write(fbBuf, 1024);
174         fbBuf += 1024;
175       }
176       else if (fbLen % 1024 > 0) {
177         size_t remainder = fbLen % 1024;
178         clientTCP.write(fbBuf, remainder);
179       }
180     }
181
182     clientTCP.print(tail);
183
184     esp_camera_fb_return(fb);
185
186     int waitTime = 10000;   // timeout 10 seconds
187     long startTimer = millis();
188     boolean state = false;
189
190     while ((startTimer + waitTime) > millis())
191     {
192       Serial.print(".");
193       delay(100);
194       while (clientTCP.available())
195       {
196         char c = clientTCP.read();
197         if (c == '\n')
198         {
199           if (getAll.length() == 0) state = true;
200           getAll = "";
201         }
202         else if (c != '\r')
203           getAll += String(c);
204         if (state == true) getBody += String(c);
205         startTimer = millis();
206       }
207       if (getBody.length() > 0) break;
208     }
209     clientTCP.stop();
210     Serial.println(getBody);
211   }
212   else {
213     getBody = "Connected to api.telegram.org failed.";
214     Serial.println("Connected to api.telegram.org failed.");
215   }
216   return getBody;
217 }
218
219 void setup() {
220   WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
221   // Init Serial Monitor
222   Serial.begin(115200);
223
224   // Set LED Flash as output
225   pinMode(FLASH_LED_PIN, OUTPUT);
226   digitalWrite(FLASH_LED_PIN, flashState);
227
228   // Config and init the camera
229   configInitCamera();
230
231   // Connect to Wi-Fi
232   WiFi.mode(WIFI_STA);
233   Serial.println();
234   Serial.print("Connecting to ");
235   Serial.println(ssid);
236   WiFi.begin(ssid, password);
237   while (WiFi.status() != WL_CONNECTED) {
238     Serial.print(".");
239     delay(500);
240   }
241   Serial.println();
242   Serial.print("ESP32-CAM IP Address: ");
243   Serial.println(WiFi.localIP());
244 }
245
246 void loop() {
247
248   int men = 0;
249
250   if (Serial.available()) {
251     men = Serial.read();
252     if (men == 100) {
253       bot.sendMessage(CHAT_ID, "DETECTADO PRESENCIA", "");
254       digitalWrite(FLASH_LED_PIN, HIGH);
255       sendPhotoTelegram();
256       digitalWrite(FLASH_LED_PIN, LOW);
257     }
258   }
259
260
261   if (sendPhoto) {
262     Serial.println("Preparing photo");
263     digitalWrite(FLASH_LED_PIN, HIGH);
264     sendPhotoTelegram();
265     digitalWrite(FLASH_LED_PIN, LOW);
266     sendPhoto = false;
267   }
268   if (millis() > lastTimeBotRan + botRequestDelay)  {
269     int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
270     while (numNewMessages) {
271       Serial.println("got response");
272       handleNewMessages(numNewMessages);
273       numNewMessages = bot.getUpdates(bot.last_message_received + 1);
274     }
275     lastTimeBotRan = millis();
276   }
277 }

Dificultades y soluciones

Una de las dificultades que se nos presenta es la falta de ruedas para realizar el mecanismo de la rampa. Esto se solucionó cortando una madera con el diámetro requerido de madera la cual se recubrió con una cinta de impresora para que no resbalaran las cartas por ella.

Otra complicación que surgió tras la construcción del buzón fue que el motor que permitía que las cartas salieran no era capaz de levantar esta pieza que cerraba el buzón por lo que hubo que sustituirla por otro material más ligero.

Además, hemos tenido muchos problemas al intentar enviar una señal desde telegram a la placa de Arduino para que una vez llegada la señal activara el proceso de extracción de las cartas.

La solución que encontramos a este contratiempo fue poner un botón que sustituyera la señal enviada por telegram.

Conclusiones

Nos hacía bastante ilusión hacer un proyecto de este tipo entre nuestro grupo de compañeros, era nuestra primera vez con este tipo de materiales. Es una asignatura que nos despierta gran interés al ser muy visual e interactuar físicamente con los componentes.

Durante la realización del proyecto hemos tenido bastantes problemas con la logística al tener un integrante del grupo sin poder desplazarse por problemas de salud, también con la entrega de los componentes por parte de amazon y con la comunicación de diferentes módulos, hemos usado módulos bastante complejos y hemos tenido ideas muy ambiciosas como usar el buzón mediante una red social como telegram.

Esto nos ha llevado bastante tiempo y nos ha dado bastantes problemas. A pesar de ello hemos intentado hacerlo lo mejor posible dentro de nuestros conocimientos.

Video del proyecto

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *