The best companion of my old mother.
Project for a funny talking robot to create some animation in senior people life ...
Components and supplies
1
Arduino® Nano ESP32
1
DFPlayer - A Mini MP3 Player
1
Mini Photocell
1
LED (generic)
1
3.3V-5V 4 Channels Logic Level Converter
1
Presence sensor LD2410
1
Grove - Barometer Sensor (BMP280)
1
10kOhm potentiometer
1
5 watt speaker 4 ohm
1
Battery charger with 2 x 16340 LIPO
1
Adafruit Microphone Breakout MAX4466
1
10k Resistor
Apps and platforms
1
Arduino IDE
Project description
Code
Companion code
required updates with your own details are listed
1/* ---------------------------- 2 Robot companion for senior people 3 Astropifou - Alain Destruel 4 03/2025 5 6 - messages to be recorded in your own language with robot voice are explained with the Speakaloud function 7 - messages to be recorded in your own language with human voice are explained with the Speaktogoogle function 8 - birthdays and saint days of your family must be updated 9 - internet details must be updated 10 - callmebot API key must be updated 11 - update your email adress 12 - I have created an email adress for the robot (sender.email) you can do the same or use an existing email adress. 13 - You must create a password for your email (receiver email) in your google account to accept emails from an application (https://fr.vittascience.com/learn/tutorial.php?id=1030/envoyer-un-mail-a-partir-d-une-carte-esp32) 14 15----------------------------------*/ 16 17#include <SPI.h> 18#include <WiFi.h> 19#include <ESP_Mail_Client.h> 20#include <time.h> 21#include <LittleFS.h> 22#include <Timer.h> 23#include <DFRobotDFPlayerMini.h> 24#include <Adafruit_BME280.h> 25#include <HTTPClient.h> 26#include <UrlEncode.h> 27 28uint8_t PresencePin = 13; // Digital pin for presence sensor LD2410 29uint8_t LightPin = 34; // Photocell input pin 30uint8_t LedPin = 25; // Led Pin 31uint8_t SoundPin = 35; // Micro Pin 32uint8_t PotarPin = 32; // Potar Pin 33 34SMTPSession smtp; // Declare the global used SMTPSession object for SMTP transport 35Session_Config config; // Declare the global used Session_Config for user defined session credentials 36time_t maintenant; // time info 37struct tm * timeinfo; 38 39Timer timerin, timerout, timersensors; // timers 40Adafruit_BME280 bme; // °C 41 42DFRobotDFPlayerMini myDFPlayer; // MP3 player 43#define mySoftwareSerial Serial1 // Hardware Serial port 1 for MP3 44 45// booleans 46bool isin = true; 47bool Goodmorning, Goodnight, Comeback, Lunch, Lampadaire, Teatime, Beautifulday, Wakeupalert = false; 48bool Loto, Lotoresult, Dinertime, Market = false; 49String goodday=""; // good actions of the day to be sent to Senior 50 51float meanwakeuptime = 8; // hour 52float meansleeptime = 21.5; // hour 53float meanpromenadetime = 60; // mn 54float meanlunchtime = 60; // mn 55float gotosleeptime =21; //hour 56float promenade =0; // last promenade duration 57const int sensordelay = 60; // mn delay between 2 sensor alerts 58uint64_t sleeptime = 0; // sec 59float yesterdaypressure = 1000; 60float pressure = 0; // pressure for meteo 61 62void setup() { 63 Serial.begin(115200); 64 65 mySoftwareSerial.begin(9600, SERIAL_8N1, 26, 27); // Speed, type, RX, TX for MDPlayer 66 myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms 67 68 pinMode(PresencePin, INPUT); 69 pinMode(LightPin, INPUT); 70 pinMode(LedPin, OUTPUT); 71 pinMode(SoundPin, INPUT); 72 pinMode(PotarPin, INPUT); 73 74 timerin.start(); 75 76 Initfilesystem (); 77 initplayer(); // MP3 78 Speakaloud(5,1); // I am nono ... 79 delay(10000); 80 81 Initwifi(); // init Wifi 82 Inittime(); // init time from NTP 83 84 if (Checksensors()) { // init and chek of sensors and filesystem 85 Speakaloud(5,4); // Ready ... 86 } else { 87 Speakaloud(5,9); // Problem 88 } 89 90 randomSeed(analogRead(32)); 91 92} 93// -------------------------------------------------- 94// ----------- LOOP ------------------------------ 95void loop() { 96 time(&maintenant); 97 timeinfo = localtime(&maintenant); 98 99 Clock(); // hour bell 100 101 Executetimers (); // timers update 102 103// ------------- Alert wake too too late 104 if ((timeinfo->tm_hour >= 10) && (timeinfo->tm_hour <= 13) && !isin && !Wakeupalert && !Goodmorning) { 105 Sendwhatsapp ("Arlette n'est pas encore levée"); // text added whatsapp alert (sorry for french) 106 Wakeupalert = true; 107 Appendlog("Arlette n'est pas encore levée"); // text added in the daily email (sorry for french) 108 } 109 110if ((timeinfo->tm_hour >=8) && (timeinfo->tm_hour <=21)) { Executeaction(); } 111 112 113//Deepsleep timer configuration 114 if ((timeinfo->tm_hour >=21) && (timeinfo->tm_min >= 15)) { // night no action 115 Midnightinit (); 116 sleeptime = 10*3600; 117 digitalWrite(LedPin,LOW); 118 esp_sleep_enable_timer_wakeup(sleeptime * 1000000); // ùs to s conversion 119 Appendlog(" -- ESP32 wake up in " + String(sleeptime) + " sec"); 120 delay(10000); 121 esp_light_sleep_start(); // stop any process during sleep 122 } 123 124 delay(300000) ; // loop every 5 mn 125} 126 127// -------------------------------------------------- 128// ----------- Main function --------------------- 129void Executeaction() { 130 float wakeuptime; 131 132 Appendlog("--- Execute Actions"); 133 if (random(1,20) >= 19) { 134 Speakaloud(2,22); // waking up 135 Speakaloud(2,23); // all right 136 } 137 138 Sensoralerts(); // get sensors data 139 140// ---------- GOOD MORNING 141 if ((timeinfo->tm_hour >= 8) && (timeinfo->tm_hour <= 10) && isin && !Goodmorning) { // action Goodmorning when someone detected 142 Goodmorning = true; 143 144 Birthday (); 145 Fete (); 146 147 Speakaloud(2,22); // waking up 148 Speakaloud(2,23); // all right 149 Speakaloud(2,1); // Goodmorning 150 wakeuptime = timeinfo->tm_hour + timeinfo->tm_min / 60; 151 if (wakeuptime < meanwakeuptime - 0.4) { 152 Speakaloud(2,3); // early wake up 153 Happy("Tu t'es levée de bonne heure"); 154 } 155 if (wakeuptime > meanwakeuptime + 0.4) { 156 Speakaloud(2,2); // late wake up 157 Speakaloud(1,2); // not happy 158 } 159 Speaktogoogle(5); // Good morning google 160 Speaktogoogle(1); // Good meteo 161 Speaktogoogle(8); // Good rain 162 Speaktogoogle(9); // today program 163 Speaktogoogle(2); // Good news 164 165 meanwakeuptime = (5*meanwakeuptime + wakeuptime)/6; 166 167 float sleeptime = wakeuptime + 24 - gotosleeptime; 168 Appendlog("Goodmorning "+ String(sleeptime) + " h of sleep - mean : "+ String(meanwakeuptime)); 169 170 if (Light() == 2 ) {Speakaloud(2,5); } // low luminosity 171 if (Light() == 4 ) {Speakaloud(2,4); } // high luminosity 172 173 pressure = bme.readPressure() / 100.0; 174 Appendlog(" - Pressure = " + String(pressure) + " hPa - Yesterday : " + String(yesterdaypressure)); 175 176 if (pressure > yesterdaypressure*1.03) { 177 Speakaloud(2,17); 178 Appendlog("High pressure");} 179 if (pressure < yesterdaypressure*0.97) { 180 Speakaloud(2,18); 181 Appendlog("Low pressure");} 182 yesterdaypressure = pressure; 183 } 184 185// ---------- GOOD NIGHT 186 if ((timeinfo->tm_hour >= 21) && !isin && (timerout.read()/60000 > 15) && !Goodnight) { // action Goodnight when someone not detected since 10mn and light off and sound off 187 Goodnight = true; 188 gotosleeptime = timeinfo->tm_hour + timeinfo->tm_min / 60; 189 meansleeptime = (5*meansleeptime + gotosleeptime)/6; 190 Appendlog("Go to Sleep : "+ String(gotosleeptime) + " h -- mean : " + String(meansleeptime)); 191 } 192// what a beautiful day 193 if ((timeinfo->tm_hour >= 10) && (timeinfo->tm_min >= 10) && (timeinfo->tm_min <= 20) && 194 isin && (Light() >= 3) && !Beautifulday) { 195 Speakaloud(2,24); 196 Beautifulday = true; 197 Happy("Une belle journée !"); 198 Appendlog("Beautiful day");} 199 200 // ---------- Promenade 201 if ( ( ((timeinfo->tm_hour >= 10) && (timeinfo->tm_hour <= 12))|| 202 ((timeinfo->tm_hour >= 13) && (timeinfo->tm_hour <= 18))) 203 && isin && Comeback && promenade >= 30 ) { // comeback from promenade 204 Speakaloud(2,19); // back from promenade 205 if (promenade < meanpromenadetime - 0.4) { // sound in dir 04 206 Speakaloud(2,20); // short promenade 207 Speakaloud(1,2); // not happy 208 } 209 if (promenade > meanpromenadetime + 0.4) { 210 Happy("Tu as fait une longue promenade de " + String(promenade) + " minutes"); 211 Speakaloud(2,21); // long promenade 212 } 213 Comeback = false; 214 meanpromenadetime = (5*meanpromenadetime + promenade)/6; 215 Appendlog("Back from promenade of "+ String(promenade) + "mn - Mean : " + String(meanpromenadetime) ); 216 } 217 218// ---------- Lunch come back 219 if ((timeinfo->tm_hour >= 12) && (timeinfo->tm_hour <= 14) 220 && isin && Comeback && promenade > 15) { // comeback from lunch 221 222 if (promenade < meanlunchtime - 0.4) { // sound in dir 05 223 Speakaloud(1,2); // not happy 224 } 225 if (promenade > meanlunchtime + 0.4) { Happy("Tu as passé beaucoup de temps au déjeuner : " + String(promenade) + " minutes"); } 226 Comeback = false; 227 meanlunchtime = (5*meanlunchtime + promenade)/6; 228 Appendlog("Back from lunch time of "+ String(promenade) + "mn -- mean : " + String(meanlunchtime)); 229 } 230 231// ---------- prepare to Lunch 232 if ((timeinfo->tm_hour >= 11) && (timeinfo->tm_hour <= 12) && isin && !Lunch) { // prepare to lunch dir 06 233 Speakaloud (2,11) ; 234 Lunch = true; 235 Appendlog("Prepare to lunch"); 236 } 237 238// ---------- LOTO 239 if (((timeinfo->tm_wday == 1) || (timeinfo->tm_wday == 3) || (timeinfo->tm_wday == 6)) && 240 (timeinfo->tm_hour >= 19) && (timeinfo->tm_min >=30) && (timeinfo->tm_hour <=20) && isin && !Lotoresult) { // Loto 20h Mon, Wed, Sat 241 Happy("c'est le loto"); 242 Speakaloud (2,12) ; // LOTO soon 243 Lotoresult = true; 244 Appendlog("Loto result soon"); 245 } 246 if (((timeinfo->tm_wday == 1) || (timeinfo->tm_wday == 3) || (timeinfo->tm_wday == 6)) && 247 (timeinfo->tm_hour >= 20) && (timeinfo->tm_min >=20) && isin && !Loto) { // Loto 20h Mon, Wed, Sat 248 Happy("alors tu as gagné au loto ?"); 249 Speaktogoogle(4); // LOTO result 250 Loto = true; 251 Appendlog("Loto result"); 252 } 253 254// ---------- too dark 255 if ((timeinfo->tm_hour >= 17) && (timeinfo->tm_hour <=20) && isin && !Lampadaire && (Light() <= 2)) { // light on the evening 256 Speakaloud(1,2); // not happy 257 Speakaloud (2,13) ; // lampadaire light 258 Speaktogoogle(7); // light on 259 Speaktogoogle(6); // music 260 Lampadaire = true; 261 Appendlog("Too dark"); 262 } 263 264// ------------ Tea time 265 if ((timeinfo->tm_hour >= 17) && (timeinfo->tm_hour <=18) && isin && !Teatime) { // tea time 266 Happy("c'est l'heure du thé"); 267 Speakaloud (2,14) ; // tea time 268 Teatime = true; 269 Appendlog("Tea time"); 270 } 271 272// ------------ Diner time 273 if ((timeinfo->tm_hour >= 19) && (timeinfo->tm_hour <=20) && isin && !Dinertime) { // Diner time 274 Happy("c'est l'heure du diner"); 275 Speakaloud (2,15) ; // Diner time 276 Dinertime = true; 277 Appendlog("Diner time"); 278 } 279 280// ---------- Market day 281 if ( ((timeinfo->tm_wday == 2) || (timeinfo->tm_wday == 6)) && 282 (timeinfo->tm_hour >= 9) && (timeinfo->tm_hour <=12) && isin && !Market) { // Market day 283 Happy("c'est le jour du marché ?"); 284 Speakaloud (2,16) ; // Market 285 Market = true; 286 Appendlog("Market day"); 287 } 288 289// ---------- Evening action 290 if ( (timeinfo->tm_hour >= 17) && (timeinfo->tm_hour <= 19) && (timeinfo->tm_min <= 6) && isin) { // Evening actions 291 if (random(1,10) >= 5) { 292 Happy("un peu d'action le soir"); 293 Speakaloud(4, random(1, 2)); 294 delay(4000); 295 Appendlog("Evening action"); 296 } 297 } 298 299 // ---------- Random action 300 if ( (((timeinfo->tm_hour >= 9) && (timeinfo->tm_hour <= 12)) || 301 ((timeinfo->tm_hour >= 14) && (timeinfo->tm_hour <= 19))) && (timeinfo->tm_min <= 6) && isin && (Sound()<=2) ) { // Random actions 302 if (random(1,10) >= 8) { 303 Speakaloud(3, random(1, 17)); 304 delay(4000); 305 Appendlog("Random action"); 306 } 307 } 308 309} 310 311// -------------------- secondary functions ------------------- 312// --------------------------------------------------------------- 313void Executetimers () { 314// Appendlog("Execute timers start : isin " + String(isin) + " -- Comeback :" + String(Comeback)+ " -- promenade :" + String(promenade)); 315 316 if (Presencevalue() == HIGH || Sound() >=2) { 317 if (!isin) { 318 timerin.start(); 319 Appendlog("Start timer In"); 320 promenade = timerout.read()/60000; 321 timerout.stop(); 322 Comeback=true; 323 Appendlog("Execute timers : Come back from promenade : " + String(promenade)); 324 isin = true; 325 } 326 } else { 327 if (isin) { 328 timerout.start(); 329 Appendlog("Start timer Out"); 330 Comeback = false; 331 Appendlog("Execute timers : promenade starts -- time in :"+ String(timerin.read()/60000)); 332 timerin.stop(); 333 isin =false; 334 } 335 } 336 Appendlog("Execute timers end : isin " + String(isin) + " -- Comeback " + String(Comeback)+ " -- promenade " + String(promenade) + " In since : " + String(timerin.read()/60000) + " --- Out since : " + String(timerout.read()/60000) ); 337} 338 339bool Checksensors() { 340 Appendlog(" ---- Checksensors : "); 341 342 unsigned BMEstatus; 343 344 if ((Light() >=1) && (Light() <=4)) { 345 Speakaloud(5,5); // light ok 346 } else { 347 Speakaloud(5,12); // I am blind 348 Appendlog("Blind"); 349 return false; 350 } 351 if ((Sound()>=1) && (Sound() <=4)) { // sound ok 352 Speakaloud(5,6); 353 } else { 354 Speakaloud(5,13); // I can't listen 355 Appendlog("no sound"); 356 return false; 357 } 358 if (Presencevalue() == HIGH) { // Presence ok 359 Speakaloud(5,7); 360 } else { 361 Speakaloud(5,14); // I can't detect presence 362 Appendlog("No Presence"); 363 return false; 364 } 365 BMEstatus = bme.begin(0x76); 366 delay(4000); 367 368 if (BMEstatus) { // Temperature ok 369 Speakaloud(5,8); 370 } else { 371 Appendlog(F("no valid BME280 sensor")); 372 Speakaloud(5,15); // Pb temperature 373 return false; 374 } 375 delay(5000); 376 return true; 377} 378 379void Sensoralerts (){ 380 Appendlog("--- Sensors alerts"); 381 float temperature = bme.readTemperature()-3; // ajust sensor 382 float humidity = bme.readHumidity(); 383 384 Appendlog("Sensorsalerts Presence :" + String(Presencevalue()) + " -- Sound :"+ String(Sound()) + " -- Light : " + String(Light()) + " -- Temperature: " + String(temperature)+" -- Humidity: " + String(humidity) + "%"); 385 386 if ((timersensors.state() == STOPPED) || (timersensors.read()/60000 > sensordelay)) { 387 if (Sound() == 4) { // too noisy 388 Speakaloud (2,10) ; 389 Speakaloud(1,2); // not happy 390 timersensors.stop(); 391 timersensors.start(); 392 } 393 if (temperature > 25) { // too hot 394 Speakaloud (2,6) ; 395 Speakaloud(1,2); // not happy 396 timersensors.stop(); 397 timersensors.start(); 398 } 399 if (temperature < 20) { // too cold 400 Speakaloud (2,7) ; 401 Speakaloud(1,2); // not happy 402 timersensors.stop(); 403 timersensors.start(); 404 } 405 if (humidity > 42) { // too wet 406 Speakaloud (2,8) ; 407 Speakaloud(1,2); // not happy 408 timersensors.stop(); 409 timersensors.start(); 410 } 411 if (humidity < 34) { // too dry 412 Speakaloud (2,9) ; 413 Speakaloud(1,2); // not happy 414 timersensors.stop(); 415 timersensors.start(); 416 } 417 } 418} 419 420void Midnightinit() { 421 Appendlog("--- Midnight Init"); 422 Appendlog("--- Goodmorning: "+String(Goodmorning)+ " Goodnight: "+String(Goodnight) + " Comeback: "+String(Comeback)+" Lunch: "+String(Lunch)+ " Lampadaire: "+String(Lampadaire)); 423 Appendlog("--- Teatime: "+String(Teatime)+" Loto: "+String(Loto)+ " Lotoresult: "+String(Lotoresult) + " Dinertime: "+String(Dinertime)+" Market: "+String(Market)+ " Beautifulday: "+String(Beautifulday)+" isin: "+String(isin)); 424 425 Goodmorning = false; 426 Goodnight = false; 427 Comeback = false; 428 Lunch = false; 429 Lampadaire = false; 430 Teatime = false; 431 Loto = false; 432 Lotoresult = false; 433 Dinertime = false; 434 Market = false; 435 Beautifulday = false; 436 Wakeupalert = false; 437 isin = false; 438 439 timerin.stop(); 440 timerout.stop(); 441 timersensors.stop(); 442 promenade = 0; 443 444 Appendlog("--- Midnightinit reset"); 445 446 Send_log(); // send log file and clear logs 447 Deletelog (); 448} 449 450String Str_Smarttime() { 451/* struct tm { 452 int tm_sec; /* seconde de minute 0 à 59 453 int tm_min; /* minutes 0 à 59 454 int tm_hour; /* heure 0 à 23 455 int tm_mday; /* jour du mois 1 à 31 456 int tm_mon; /* mois 0 à 11 457 int tm_year; /* années depuis 1900 458 int tm_wday; /* jours depuis dimanche 0 à 6 459 int tm_yday; /* jours depuis le 1er janvier , 0 à 365 460 int tm_isdst; /* drapeau Daylight (heure d'hiver) 461} */ 462 463 String Smarttime; 464 static String day[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 465 466 time(&maintenant); 467 timeinfo = localtime(&maintenant); 468 String Smartime = day[timeinfo->tm_wday] + " "; 469 470 if (timeinfo->tm_mday < 10) { 471 Smartime = Smartime + "0" + timeinfo->tm_mday + "-"; 472 } else { 473 Smartime = Smartime + timeinfo->tm_mday + "-"; // timeinfo->tm_mday: jour du mois (1 - 31) 474 } 475 if ((timeinfo->tm_mon + 1) < 10) { 476 Smartime = Smartime +"0"+ (timeinfo->tm_mon + 1)+ "-"; 477 } else { 478 Smartime = Smartime + (timeinfo->tm_mon + 1)+ "-"; // timeinfo->tm_mon: mois (0 - 11, 0 correspond à janvier) 479 } 480 Smartime = Smartime + (timeinfo->tm_year + 1900); // timeinfo->tm_year: tm_year nombre d'années écoulées depuis 1900 481 482 Smartime = Smartime +" Heure: "; 483 if ((timeinfo->tm_hour ) < 10) { 484 Smartime = Smartime +"0"+ timeinfo->tm_hour + ":"; 485 } else { 486 Smartime = Smartime + timeinfo->tm_hour + ":"; // heure entre 0 et 23 487 } 488 if (timeinfo->tm_min < 10) { 489 Smartime = Smartime +"0"+ timeinfo->tm_min +":"; 490 } else { 491 Smartime = Smartime + timeinfo->tm_min +":"; // timeinfo->tm_min: minutes (0 - 59) 492 } 493 if (timeinfo->tm_sec < 10) { 494 Smartime = Smartime + "0"+ timeinfo->tm_sec; 495 } else { 496 Smartime = Smartime + timeinfo->tm_sec; // timeinfo->tm_sec: secondes (0 - 60) 497 } 498 Smartime = Smartime + " "; 499 return Smartime; 500} 501 502// Callback function to get the Email sending status 503 504void smtpCallback(SMTP_Status status) { 505 Appendlog(" ---- smtpCallback " + String(status.info())); 506} 507 508 void Inittime() { 509 uint8_t co = 1; 510 511 if (WiFi.status() != WL_CONNECTED) {Initwifi();} 512 513 // serveur NTP from lib Time 514// configTime(3600, 0, "fr.pool.ntp.org"); 515 configTzTime("CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", "fr.pool.ntp.org"); 516 Appendlog("Wait for time from NTP"); 517 518 while (time(nullptr) <= 100000) { 519 co = co+1; 520 if (co == 50) { 521 Speakaloud(5, 17); //can't find date and time 522 co=0; 523 } 524 Serial.print("."); 525 delay(1000); 526 } 527 time(&maintenant); 528 timeinfo = localtime(&maintenant); 529 530 Speakaloud(5,3); // NTP ... 531} 532 533void Initfilesystem () { 534 ESP_MAIL_DEFAULT_FLASH_FS.begin(); // Init filesystem 535 if (!LittleFS.begin(1)) { 536 Appendlog("LittleFS mount failed!"); 537 Speakaloud(5,11); // pb filesystem 538 } 539 Deletelog (); 540} 541 542// Wifi init testing several SSID 543// update the SSID and Pass with your own details 544void Initwifi() { 545 String pass [] = {"pass1", "pass2"}; 546 String SSID [] = {"SSID1", "SSID2"}; 547 548 while (WiFi.status() != WL_CONNECTED) 549 { 550 for (int nss=0; nss<=1; nss++) 551 { 552 if (WiFi.status() != WL_CONNECTED) 553 { 554 Appendlog("Tentative connection to : " + SSID[nss] + " " + pass[nss]); 555 for (int co=0; co<=20; co++) 556 { 557 WiFi.begin(SSID[nss], pass[nss]); 558 if (WiFi.status() != WL_CONNECTED) 559 { 560 Serial.print("."); 561 delay(2000); 562 } 563 } 564 if (WiFi.status() != WL_CONNECTED) {Speakaloud(5, 16); } //can't find wifi 565 } 566 } 567 } 568 PrintWifiData(); 569 Speakaloud(5,2); // Wifi ... 570} 571// I use callmebot API 572// you must ask for a callmebot API key (for free) 573// update the key with your own key 574 575void Sendwhatsapp (String message){ 576 String url = "YOUR OWN KEY" + urlEncode(message); 577 HTTPClient http; 578 579 if (WiFi.status() != WL_CONNECTED) {Initwifi();} 580 581 delay(10000); 582 http.begin(url); 583 584 http.addHeader("Content-Type", "application/x-www-form-urlencoded"); // Specify content-type header 585 586 int httpResponseCode = http.POST(url); // Send HTTP POST request 587 if (httpResponseCode == 200){ 588 Appendlog("Whatsapp sent"); 589 } 590 else{ 591 Appendlog("Error Whatsapp HTTP response code: " + httpResponseCode); 592 } 593 // Free resources 594 http.end(); 595} 596 597/* 598You must : 599 update your email adress 600 I have created an email adress for the robot (sender.email) you can do the same or use an existing email adress 601 You must create a password for your email (receiver email) in your google account to accept emails from an application (https://fr.vittascience.com/learn/tutorial.php?id=1030/envoyer-un-mail-a-partir-d-une-carte-esp32) 602*/ 603void Send_log() { 604 Appendlog(" ------Send log"); 605 if (WiFi.status() != WL_CONNECTED) {Initwifi();} 606 delay(2000); 607 608// Set the session config 609 config.server.host_name = "smtp.gmail.com"; // for outlook.com 610 config.server.port = 587; // for TLS with STARTTLS or 25 (Plain/TLS with STARTTLS) or 465 (SSL) 611 config.login.email = "EMAIL ADRESS OF YOUR ROBOT"; // set to empty for no SMTP Authentication 612 config.login.password = "YOUR GOOGLE APPLICATION PASSWORD"; // set to empty for no SMTP Authentication 613 config.login.user_domain = ""; 614 615 // Declare the SMTP_Message class variable to handle to message being transport 616 SMTP_Message message; 617 618 // Set the message headers 619 message.sender.name = "Nono"; 620 message.sender.email = "EMAIL ADRESS OF YOUR ROBOT"; 621 message.subject = "La journée d'Arlette"; 622 message.addRecipient("YOU OWN EMAIL", "YOUR OWN EMAIL"); 623 // message.addCc("CC ADRESS IF NEEDED"); 624 625 // Set the message content 626 message.text.content = goodday; 627 628 // Declare the attachment data 629 SMTP_Attachment att; 630 631//Add file text attachment to the message 632 message.resetAttachItem(att); 633 att.descr.filename = "log.txt"; 634 att.descr.mime = "text/plain"; 635 att.file.path = "/log.txt"; 636 att.file.storage_type = esp_mail_file_storage_type_flash; 637 att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64; 638 message.addAttachment(att); 639 640 // Set the callback function to get the sending results 641 smtp.callback(smtpCallback); 642 643 // Connect to the server 644 smtp.connect(&config); 645 646 // Start sending Email and close the session 647 time(&maintenant); 648 if (!MailClient.sendMail(&smtp, &message)) 649 Appendlog("Error sending Email, " + smtp.errorReason()); 650} 651 652// Append in a file, il file does not exist it is created 653void Appendfile(const char * path, const char * message) { 654 File file = LittleFS.open(path, "a"); 655 if (!file) { 656 Appendlog("file open failed!"); 657 return; 658 } 659 if (file.println(message)) { 660// Appendlog("file append success"); 661 } else { 662 Appendlog("file append failed!"); 663 } 664} 665 666// Delete FS file 667void Deletefile(const char * path) { 668 Appendlog("Delete file : "+ String(path) ); 669 if (LittleFS.remove(path)) { 670 Appendlog(" Delete success"); 671 } else { 672 Appendlog(" : file delete failed!"); 673 } 674} 675 676void Readfile(const char * path) { 677 File file = LittleFS.open(path, "r"); 678 if (!file || file.isDirectory()) { 679 Appendlog("...read failed!"); 680 return; 681 } 682 while (file.available()) { 683 Serial.write(file.read()); 684 } 685} 686 687void Appendlog (String message) { 688 String m = Str_Smarttime() + message; 689 Serial.println(m); 690 Appendfile ( "/log.txt",m.c_str()); 691} 692 693void Deletelog () { 694 Deletefile ("/log.txt"); 695 goodday = ""; 696} 697 698void initplayer() { 699 Appendlog("Initializing DFPlayer ... (May take 3~5 seconds)"); 700 701 myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms 702 while (!myDFPlayer.begin(mySoftwareSerial)) { 703 Appendlog("DFPlayer Unable to begin"); 704 delay(500); 705 } 706 Appendlog("DFPlayer Mini online."); 707 myDFPlayer.volume(Potarvolume ()); 708} 709 710/* Sounds 711 I use Voicemod V3 to transform voice in "Robot like" voice 712 bips and funny sounds for free can be ealisy found in the internet 713 714 DIR 01 : goodies 715 01: happy sound 716 02: not happy sound 717 03 to 14: bips 718 719 Dir 02 : Good morning 720 01 : Good morning 721 02 : late wake up 722 03 : early wake up 723 04 : higj luminosity 724 05 : low luminosity 725 06 : too hot 726 07 : too cold 727 08 : too wet 728 09 : too dry 729 10 : too noisy 730 11 : prepare to lunch 731 12 : loto 732 13 : dark lampadaire 733 14 : tea time 734 15 : diner time 735 16 : Market day 736 17 : high pressure - good weather 737 18 : low pressure - bad weather 738 19 : promenade back 739 20 : short promenade 740 21 : long promenade 741 22 : everything all right ? 742 23 : waking up 743 24 : what a beautiful day 744 25 : birthday 745 26 : fete 746 Dir 03 : Random actions 747 Dir 04 : Evening actions 748 01 : call Monique 749 02 : apero 750 Dir 05 : 751 01 : nono 752 02 : wifi OK 753 03 : date and time OK 754 04 : ready 755 05 : light OK 756 06 : sound OK 757 07 : presence OK 758 08 : BME OK 759 09 : Problem ! 760 10 : --- free 761 11 : pb filesystem 762 12 : blind 763 13 : no sound 764 14 : no presence detect 765 15 : no BME 766 16 : no WIfi 767 17 : no date 768 Dir 6 Morning actions 769 01 : coffee with friend 770 Dir 10 : OK Google 771 01 : meteo 772 02 : news 773 03 : Good night 774 04 : loto 775 05 : good morning 776 06 : slow music 777 07 : lampadaire on 778 08 : rain 779 09 : today program 780 781*/ 782// voice messages with a robot like voice 783void Speakaloud (int folderNumber, int fileNumber) { 784 Appendlog("Speakaloud folder " + String(folderNumber) + " -- file " + String(fileNumber)); 785 786 myDFPlayer.volume(Potarvolume ()); 787 myDFPlayer.playFolder(1, random(3, 14)); // bip random 788 delay(4000); 789 myDFPlayer.playFolder(folderNumber, fileNumber); 790 delay(10000); 791} 792 793// voice messages ith human voice for google assistant 794void Speaktogoogle (int fileNumber) { 795 Appendlog("Speaktogoogle file : "+ String(fileNumber) ); 796 797 myDFPlayer.volume(12); 798 myDFPlayer.playFolder(10, fileNumber); 799 delay(20000); 800} 801 802int Light () { 803 int val = map(analogRead(LightPin), 0, 3000, 1, 10); 804 805 if (val == 1) { // night 806 if ((isin) && (timeinfo->tm_hour >= 9) && (timeinfo->tm_hour <= 21)) { 807 Appendlog ("Led light on"); 808 digitalWrite(LedPin,HIGH); } // led light on 809 return 1; 810 } 811 if (val <= 4) { // sombre 812 digitalWrite(LedPin,LOW); // led light off 813 return 2; 814 } 815 if (val <= 6) { // normal 816 digitalWrite(LedPin,LOW); // led light off 817 return 3; 818 } 819 if (val > 6) { // tres clair 820 digitalWrite(LedPin,LOW); // led light off 821 return 4;} 822} 823 824// -------------- Blink 825void Blink(uint8_t n) { 826 for(int i = 0; i <= n-1; i += 1) 827 { 828 Appendlog ("Blink"); 829 digitalWrite(LedPin,HIGH); 830 delay(200); 831 digitalWrite(LedPin,LOW); 832 } 833} 834 835/* 1 : no sound 836 4 : too high */ 837int Sound() { 838 int volume = 0; 839 for(int i = 0; i < 200; i += 1) // max volume over a few sec 840 { 841 if (analogRead(SoundPin)> volume) {volume = analogRead(SoundPin);} 842 delay(10); 843 } 844 return map(volume, 1800, 4000, 1,4 ); 845} 846 847int Potarvolume () { // sound volume between 1-30 848 return (map(analogRead(PotarPin), 0, 4095, 1, 30)); 849} 850 851void Clock() { 852 if ((timeinfo->tm_hour >= 9) && (timeinfo->tm_hour <=20 ) && (timeinfo->tm_min <= 10 ) && isin) { 853 myDFPlayer.playFolder(1, random(3, 11)); // bip random 854 delay(5000); 855 Appendlog(" ----------Clock"); 856 } 857} 858 859int Presencevalue() { 860 return digitalRead(PresencePin); 861} 862 863void Happy(String message){ 864 Speakaloud(1,1); // happy 865 Blink(3); 866 Appendlog ("Happy : " + message); 867 goodday = goodday + Str_Smarttime() + message + "\n"; 868} 869 870void PrintWifiData() { 871// print your gateway address: 872 IPAddress gateway = WiFi.gatewayIP(); 873 Serial.print("Gateway: "); 874 Serial.println(gateway); 875// print your subnet mask: 876 IPAddress subnet = WiFi.subnetMask(); 877 Serial.print("NetMask: "); 878 Serial.println(subnet); 879 880 Appendlog("Connected to SSID : " + String(WiFi.SSID()) + " signal strength (RSSI):" + String(WiFi.RSSI())); 881} 882 883// birthdays of your family (examples) 884void Birthday () { 885 int days [] = { 21, 6, 3, 29, 9, 13, 9, 12, 17, 8, 21, 2}; 886 int months [] = { 3, 12, 7, 1, 3, 6, 8, 10, 3, 10, 9, 8}; 887// Alain, Del, Geo, PL, Bri, Arl, Jacq, Pauline, Gael, Sacha, Arthur, Leon 888// for ex alain birthday is march 21. 889 890 for(int i = 0; i <= 11; i += 1) 891 { 892 if ((timeinfo->tm_wday == days[i]) && (timeinfo->tm_mon == months[i])) {Speakaloud(2,25);} 893 } 894} 895 896// saint days of your family (examples) 897void Fete () { 898 int days [] = {9, 26, 8, 29, 23, 17, 8, 26, 17, 22, 15, 10}; 899 int months [] = {9, 11, 11, 6, 7, 7, 2, 1, 12, 4, 11, 11}; 900 901 for(int i = 0; i <= 11; i += 1) 902 { 903 if ((timeinfo->tm_wday == days[i]) && (timeinfo->tm_mon == months[i])) {Speakaloud(2,26);} 904 } 905}
Downloadable files
example of vintage robot
https://www.thingiverse.com/thing:2759322
example of robot voice (DIR = 5, file = 001)
001.mp3
example of funny bip (DIR = 1, file = 001)
001.mp3
Comments
Only logged in users can leave comments