Electronic 6 Août 2024

How to make a custom home voice personal assistant based on an esp32

Introduction

This personal project is based on a simple observation: nowadays there are a significant number of voice assistants coupled with numerous tools promising hyper connectivity and boosted productivity. We therefore end up getting lost in all these opaque layers processing our personal data as well as in subscriptions that are often prohibitively expensive compared to the simplicity of the tasks that we want our electronic companion to carry out.

Today I decided to show you in the smallest details how I managed to design Cristal a voice assistant which can respond to all your wishes as long as you are ready to fiddle a minimum between the hardware and the software.

Cristal Home Assistant|inline
Cristal Home Assistant

The necessary equipment

|inline

  • An ESP32 will be the microcontroller of our project! We will take full advantage of its WiFi capacity but also of its integrated ADCs.

    |inline

  • An OLED screen (128x64) using the SH1106 chip, it will be the main means of feedback with the user.

    |inline

  • A MicroSD Card Module as well as a microSD card with the smallest capacity you have, in fact it will be useful to us only to temporarily store the audio file recorded by the microphone as well as the secret identifiers specific to your assistant, so it only takes a few kilobytes , but if you have personal upgrades requiring storage then judge the card’s capacity accordingly. ⚠️ IMPORTANT NOTE : the card must be formatted in FAT32 format

©Osoyoo|inline
©Osoyoo

  • An Ultrasonic Sensor, HC-SR04 is the safe bet.

    |inline

  • A microphone using the i2s protocol, personally I use the MAX9814 which is widespread in the field of microelectronics in particular because it carries a high quality amplifier with automatic gain control (AGC) and low noise microphone polarization.

    |inline

  • LED’s of the color you want. (the best is that it matches the color of your case)

    |inline

  • A push button.

A small server

Unfortunately, although the esp32 is a true marvel due to the extent of its capabilities, certain actions are either not possible, or possible but within a period of time which makes use uncomfortable and not smooth.

This is the case for voice recognition for example, which is therefore central to our project, which is why it is necessary to first record the audio file before transmitting it to a more powerful device so that the latter achieves recognition. But be careful by “more powerful” I don’t mean a server with 32GB of ram and a premium CPU, no it’s quite the opposite! You can either rent the smallest server configuration from a host, or use a Raspberry Pi at home.

|inline

In my case for example, I rent a server thanks to DigitalOcean, I selected the lowest possible configuration with only 1GB of Ram and an inefficient Intel processor. But it is more than sufficient as you can see in the graphs below, in terms of the memory or processor usage percentages with actions initiated by my custom assistant.

Screenshot of data measured on the server I used for this project
Screenshot of data measured on the server I used for this project

If you would like to see in more detail how to set up your Linux server for the voice assistant, click here.

3D models for those who want/can print them…

You can print the four parts of the project, here are the 3d files, feel free to modify them as you wish! (namely I printed it with my Ender-3 V3 SE)

|inline

Wiring

Make the connections follow this:

Micro SD Card Module :

  • 3.3 V
  • MISO : GPIO 19
  • CLK : GPIO 18
  • MOSI : GPIO 23
  • CS : GPIO 5
  • GND

Ultrasonic sensor :

  • VCC : 5V
  • Trig : GPIO 15
  • Echo : GPIO 2
  • GND

OLED Display :

  • VDD : 5V
  • GND
  • SCK : GPIO 22
  • SDA : GPIO 27

Blue LED’S :

  • GPIO 12
  • GND

Push Button :

  • 3.3 V
  • GPIO 4
  • GND

Microphone MAX9814 :

  • VDD : 3.3 V
  • OUT : GPIO 35 (ADC1_CHANNEL_7)
  • GND

Functionalities :

  • If you want to see how to display live weather on screen via I2C, click here.

  • If you want to see how to display live date and time based on GPS coordinates (to get timezone) on an I2C screen, click here.

  • If you want to see how to display daily news on screen via I2C, click here.

  • If you want to see how to record sound on microSD card via MAX9814 microphone, click here.

  • If you want to see how to keep your API identifiers secret for this ultra-connected project, click here.

Draw eyes expressions on an OLED screen

Here is a class for creating facial expressions on a 128x64 screen using geometry from the u8g2lib library.

class Eyes {
private :
  int x1, x2, y, width, height;
public :
  int step;
  void initialize(){
    x1 = 8;
    x2 = 70;
    y = 24;
    height = 14;
    width = 50;
    step = 0;
  }

  void det_eyes_in(){
    for (int brightness = 0; brightness < 256; brightness+=15){
      u8g2.clearBuffer();
      u8g2.setContrast(brightness);
      u8g2.drawRBox(x1, y, width, height, 7);
      u8g2.drawRBox(x2, y, width, height, 7);
      u8g2.sendBuffer();
    }
    step = 1;
  }

  void det_eyes_out(){
    for (int brightness = 255; brightness >= 0; brightness-=15){
      u8g2.clearBuffer();
      u8g2.setContrast(brightness);
      u8g2.drawRBox(x1, y, width, height, 7);
      u8g2.drawRBox(x2, y, width, height, 7);
      u8g2.sendBuffer();
    }
    step = 0;
  }

  void clign_in(){
    if (step == 2){ 
      for (int i = 0; i < 12; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        y += 1;
        height -= 2;
      };
      step = 1;
    }
  } 

  void clign_out(){
    if (step == 1){
      for (int i = 0; i < 12; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        y -= 1;
        height += 2;
      };
      step = 2;
    }
  }

  void round_in(){
    if (step == 2){
      for (int i = 0; i < 16; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        y += 1;
        height -= 1;
        x1 += 1;
        x2 += 1;
        width -= 2;
      };
      step = 3;
    }
  }

  void round_out(){
    if (step == 3){
      for (int i = 0; i < 16; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        y -= 1;
        height += 1;
        x1 -= 1;
        x2 -= 1;
        width += 2;
      };
      step = 2;
      digitalWrite(BLUE_LED, LOW);
    }
  }

  void look_right(){
    if (step == 3){
      for (int i = 0; i < 14; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 += 4;
        x2 += 1;
      }
      delay(1000);
      for (int i = 0; i < 14; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 -= 4;
        x2 -= 1;
      }
    }
  }

  void look_left(){
    if (step == 3){
      for (int i = 0; i < 14; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 -= 1;
        x2 -= 4;
      }
      delay(1000);
      for (int i = 0; i < 14; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 += 1;
        x2 += 4;
      }
    }
  }

  void look_up(){
    if (step == 3){ 
      for (int i = 0; i < 20; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 += 1;
        x2 -= 1;
        y -= 1;
      }
      delay(1000);
      for (int i = 0; i < 20; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 -= 1;
        x2 += 1;
        y += 1;
      }
    }
  }

  void look_down(){
    if (step == 3){
      for (int i = 0; i < 20; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 += 1;
        x2 -= 1;
        y += 1;
      }
      delay(1000);
      for (int i = 0; i < 20; i++){
        u8g2.clearBuffer();
        u8g2.drawRBox(x1, y, width, height, 7);
        u8g2.drawRBox(x2, y, width, height, 7);
        u8g2.sendBuffer();
        x1 -= 1;
        x2 += 1;
        y -= 1;
      }
    }
  }
};

View and manage a timer on an OLED screen

Here is a class for creating a timer on a 128x64 screen using the u8g2lib library. To initiate a timer, simply call Timer(<number_of_seconds>), for example Timer(600) initiates a timer of 600 seconds/10 minutes.

// 'sablier', 64x64px
const unsigned char epd_bitmap_sablier_top [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 
	0x00, 0xc0, 0x1f, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xf8, 0x03, 0x00, 
	0x00, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x00, 
	0x00, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xfc, 0x01, 0x00, 
	0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xfe, 0x00, 0x00, 
	0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x7f, 0x00, 0x00, 
	0x00, 0x00, 0xfc, 0x01, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00, 0x00, 
	0x00, 0x00, 0xf8, 0x07, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0xf0, 0x0f, 0x00, 0x00, 
	0x00, 0x00, 0xe0, 0x1f, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 
	0x00, 0x00, 0x80, 0x7f, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 
	0x00, 0x00, 0xc0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 
	0x00, 0x00, 0xf0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0x00, 
	0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 
	0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 
	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 
	0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// 'sablier', 64x64px
const unsigned char epd_bitmap_sablier_right [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 
	0xc0, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x07, 
	0xe0, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0x07, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0x07, 
	0xe0, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x01, 0x80, 0xff, 0xc1, 0x07, 
	0xe0, 0xff, 0xff, 0x03, 0xc0, 0x7f, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x1f, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0x0f, 0xf0, 0x0f, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0x1f, 0xf8, 0x07, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0x7f, 0xfe, 0x03, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0x7f, 0xfe, 0x03, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0x1f, 0xf8, 0x07, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0x0f, 0xf0, 0x0f, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0x07, 0xe0, 0x1f, 0xc0, 0x07, 0xe0, 0xff, 0xff, 0x03, 0xc0, 0x7f, 0xc0, 0x07, 
	0xe0, 0xff, 0xff, 0x01, 0x80, 0xff, 0xc1, 0x07, 0xe0, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x07, 
	0xe0, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0x07, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0x07, 
	0xe0, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x03, 
	0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// 'sablier', 64x64px
const unsigned char epd_bitmap_sablier_bottom [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 
	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 
	0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 
	0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 
	0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0x00, 
	0x00, 0x00, 0xf0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 
	0x00, 0x00, 0xc0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x80, 0x3f, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xf8, 0x03, 0x00, 0x00, 
	0x00, 0x00, 0xe0, 0x0f, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xc0, 0x0f, 0x00, 0x00, 
	0x00, 0x00, 0xf8, 0x01, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3f, 0x00, 0x00, 
	0x00, 0x00, 0xfc, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 
	0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x00, 0x00, 
	0x00, 0x00, 0x1f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x00, 
	0x00, 0x80, 0x1f, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xf0, 0x01, 0x00, 
	0x00, 0x80, 0x0f, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x00, 
	0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 
	0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 
	0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// 'sablier', 64x64px
const unsigned char epd_bitmap_sablier_left [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 
	0xc0, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x07, 
	0xe0, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0x07, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0x07, 
	0xe0, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x07, 0xe0, 0x83, 0xff, 0x01, 0x80, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0xfe, 0x03, 0xc0, 0xff, 0xff, 0x07, 0xe0, 0x03, 0xf8, 0x07, 0xe0, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0xf0, 0x0f, 0xf0, 0xff, 0xff, 0x07, 0xe0, 0x03, 0xe0, 0x1f, 0xf8, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0xc0, 0x7f, 0xfe, 0xff, 0xff, 0x07, 0xe0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x03, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x03, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x03, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0x03, 0xc0, 0x7f, 0xfe, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0xe0, 0x1f, 0xf8, 0xff, 0xff, 0x07, 0xe0, 0x03, 0xf0, 0x0f, 0xf0, 0xff, 0xff, 0x07, 
	0xe0, 0x03, 0xf8, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x03, 0xfe, 0x03, 0xc0, 0xff, 0xff, 0x07, 
	0xe0, 0x83, 0xff, 0x01, 0x80, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x07, 
	0xe0, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0x07, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0x07, 
	0xe0, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x03, 
	0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

class Timer {
  private :
    int requ_time, minutes, secondes;
    bool already_act;

    void set_normal_time(void){
      if (requ_time >= 60){
        minutes = requ_time / 60;
        secondes = requ_time - (minutes*60);
      }
      else{
        minutes = 0;
        secondes = requ_time;
      }
    }

    void start_timer(void){
      if (!already_act){
        already_act = true;
        char buffer_time_curr[5];
        while (requ_time > 0){
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_helvB18_te);
          u8g2.setFontDirection(2);
          u8g2.enableUTF8Print();
          u8g2.drawUTF8(65,40,"Timer");

          u8g2.setFont(u8g2_font_logisoso24_tr);

          snprintf(buffer_time_curr, sizeof(buffer_time_curr), "%i:%02i", minutes, secondes);
          u8g2.drawUTF8(65,5,buffer_time_curr);

          u8g2.setBitmapMode(1);
          if (requ_time % 4 == 0){
            u8g2.drawXBM(66, 2, 64, 64, epd_bitmap_sablier_top);
          }
          else if (requ_time % 4 == 1){
            u8g2.drawXBM(66, 2, 64, 64, epd_bitmap_sablier_left);
          }
          else if (requ_time % 4 == 2){
            u8g2.drawXBM(66, 2, 64, 64, epd_bitmap_sablier_bottom);
          }
          else {
            u8g2.drawXBM(70, 2, 64, 64, epd_bitmap_sablier_right);
          }

          requ_time--;
          u8g2.sendBuffer();
          set_normal_time();
          delay(1000);
        }       
      }
    }
  public :
    Timer(int inp_t){
      requ_time = inp_t;
      already_act = false;
      set_normal_time();
      start_timer();
    }
};

Display a “Hello” message on an OLED screen with an animated smiley!

// smiley 32x32px
const unsigned char epd_bitmap_smiley [] PROGMEM = {
	0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x80, 0x3f, 0xfc, 0x01, 0xc0, 0x03, 0xc0, 0x03, 
	0xe0, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x0e, 0x38, 0x00, 0x00, 0x1c, 0x1c, 0xe0, 0x07, 0x38, 
	0x0c, 0xf8, 0x1f, 0x30, 0x0e, 0xfe, 0x7f, 0x70, 0x06, 0x0f, 0xf0, 0x60, 0x87, 0x07, 0xe0, 0xe1, 
	0x87, 0x03, 0xc0, 0xe1, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 
	0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x0c, 0x10, 0xc0, 0x07, 0x1e, 0x78, 0xe0, 
	0x07, 0x3e, 0x7c, 0xe0, 0x06, 0x1e, 0x78, 0x60, 0x0e, 0x0c, 0x30, 0x70, 0x0c, 0x00, 0x00, 0x30, 
	0x1c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00, 0x07, 
	0xc0, 0x03, 0xc0, 0x03, 0x80, 0x1f, 0xf8, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xf8, 0x1f, 0x00
};

// 'sourire', 32x32px
const unsigned char epd_bitmap_sourire [] PROGMEM = {
	0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x80, 0x1f, 0xf8, 0x01, 0xc0, 0x03, 0xc0, 0x03, 
	0xe0, 0x00, 0x00, 0x07, 0x70, 0xf0, 0x0f, 0x0e, 0x38, 0xfc, 0x3f, 0x1c, 0x1c, 0x1e, 0x78, 0x38, 
	0x0c, 0x07, 0xe0, 0x30, 0x8e, 0x03, 0xc0, 0x71, 0xc6, 0x01, 0x80, 0x63, 0xc7, 0x00, 0x00, 0xe3, 
	0xe7, 0x00, 0x00, 0xe7, 0x63, 0x00, 0x00, 0xc6, 0x63, 0x00, 0x00, 0xc6, 0xe3, 0xff, 0xff, 0xc7, 
	0xe3, 0xff, 0xff, 0xc7, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 
	0x67, 0x18, 0x18, 0xe6, 0xe6, 0x1f, 0xf8, 0x67, 0xce, 0x0f, 0xf0, 0x73, 0x0c, 0x00, 0x00, 0x30, 
	0x1c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00, 0x07, 
	0xc0, 0x03, 0xc0, 0x03, 0x80, 0x1f, 0xf8, 0x01, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xf8, 0x1f, 0x00
};

void bonjour_func(){
  for (int i=0;i<25;i++){
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_helvB18_te);
    u8g2.setFontDirection(2);
    u8g2.enableUTF8Print();

    u8g2.setFont(u8g2_font_lubB14_tr);
    u8g2.drawUTF8(110,45,"Bonjour !");

    u8g2.setBitmapMode(1);
    
    if (i % 2 == 0){
      u8g2.drawXBM(50, 2, 32, 32, epd_bitmap_smiley);
    }
    else {
      u8g2.drawXBM(50, 2, 32, 32, epd_bitmap_sourire);
    }
    u8g2.sendBuffer();
    delay(300);
  }
}

Measuring a distance with an HC-SR04 ultrasonic sensor

float get_distance_ultrasonic(){
  // Clears the trigPin
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(ECHO_PIN, HIGH);
  
  // Calculate the distance
  float distanceCm = duration * SOUND_SPEED/2;
  return distanceCm;
}

Perform Pulse Width Modulation on the LEDs

Pulse Width Modulation is a technique used to control the brightness of an LED by adjusting the duty cycle of a square wave signal.

#include <Arduino.h>
#include <stdio.h>
#include <pwm.h>

#define BLUE_LED 12

void vari_blue(void *pvParameters){
    pinMode(BLUE_LED, OUTPUT);
    for(int pwm_loop = 0; pwm_loop < 2; pwm_loop++){
        for (int fadeValue =15; fadeValue <= 255; fadeValue ++){
            analogWrite(BLUE_LED, fadeValue);
            vTaskDelay(1 / portTICK_PERIOD_MS);
        }

        // Variation du max au min par décrément
        for (int fadeValue =255; fadeValue >= 15; fadeValue --){
            analogWrite(BLUE_LED, fadeValue);
            vTaskDelay(1 / portTICK_PERIOD_MS);
        }
    }
    analogWrite(BLUE_LED, 255);
}

void fade_in_blue(void *pvParameters){
    pinMode(BLUE_LED, OUTPUT);
    for (int fadeValue =0; fadeValue <= 255; fadeValue ++){
        analogWrite(BLUE_LED, fadeValue);
        vTaskDelay(5 / portTICK_PERIOD_MS);
    }
}

void fade_out_blue(void *pvParameters){
    pinMode(BLUE_LED, OUTPUT);
    for (int fadeValue =255; fadeValue >= 0; fadeValue --){
        analogWrite(BLUE_LED, fadeValue);
        vTaskDelay(2 / portTICK_PERIOD_MS);
    }
}

Setup & Loop

In Arduino programming, the setup() and loop() functions are fundamental to every sketch (a program written for Arduino). They define the basic structure and flow of your Arduino code. The setup() function is used to initialize variables, pin modes, start using libraries, and set up any other required state or configurations for your Arduino program. It is executed only once when the Arduino board is powered on or reset. The loop() function is where the main logic of the Arduino program is executed. It runs continuously in a loop after the setup() function has completed.

So that you have a clear idea, here is what the setup function of the program looks like inside the “Cristal” wizard :

#include <Arduino.h>
#include <U8g2lib.h>
#include <stdio.h>
#include <Wire.h>
#include <pwm.h>
#include <open-meteo.h>
#include <WiFi.h>
#include <wavserv.h>
#include <rec-sound.h>
#include <date-heure.h> 
#include <gasdk.h>
#include <open-news-api.h>
#include <get_secret_values.h>

#define I2C_SDA 27
#define I2C_SCL 22
#define BLUE_LED 12
#define BTN_PIN 4
#define TRIG_PIN 15
#define ECHO_PIN 2
#define SOUND_SPEED 0.034
#define MAX_TITLES 5
#define DISPLAY_TIME 6000  // Temps d'affichage de chaque titre en millisecondes

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, /* reset=*/ U8X8_PIN_NONE);

// Variables :
char input_refl;
char input;

long duration;
float distanceCm;

int count_inactivity = 0;
bool actived = false;
int passive_counter = 0;

String API_key;
String Device_Id;
String Model_Id;

String* titles_news = nullptr;

Eyes e1;

void setup(void) {
  pinMode(35,INPUT);
  Serial.begin(9600);
  Wire.begin(I2C_SDA, I2C_SCL);
  u8g2.begin();
  e1.initialize();

  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  pinMode(BLUE_LED, OUTPUT);

  pinMode(BTN_PIN, INPUT);

  const char* ssid = get_secret(0);
  const char* password = get_secret(1);
  API_key = get_secret(2);
  Model_Id = get_secret(3);
  Device_Id = get_secret(4);

  // Utilisation des valeurs
  Serial.println("SSID: " + String(ssid));
  Serial.println("Password: " + String(password));

  Serial.println("Connexion au réseau WiFi...");
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connexion en cours...");
  }

  Serial.println("Connecté au réseau WiFi !");

}

And here is the loop() function of course I display it for information purposes only, you can do what you want on your side. But this is what it might look like as a user menu. If there are things you don’t see implemented, look at the subsections in the Features section above.

void loop(void) {

  count_inactivity++;
  float dist = get_distance_ultrasonic();
  
  if (dist < 15.0)
  {
    count_inactivity--;

    e1.det_eyes_in();
    actived = true;

    while (digitalRead(BTN_PIN) == LOW) {
      float dist = get_distance_ultrasonic();

      if ((dist > 15.0)&&(passive_counter >= 20)){
        passive_counter = 0;
        break;
      }
      else if (dist > 15.0){passive_counter++;}
      delay(300);
    }

    if (digitalRead(BTN_PIN) == HIGH)
    {
      if (e1.step == 1)
      {
        xTaskCreate([](void *parameter)
        {
          e1.clign_out();
          vTaskDelete(NULL); 
        }, "task1", 2048, NULL, 5, NULL);
        xTaskCreate([](void *parameter)
        {
          vari_blue(parameter);
          vTaskDelete(NULL); 
        }, "task2", 2048, NULL, 5, NULL);
      }
      delay(500);
      record_mic();
      delay(500);
      String word = recowav();
      Serial.println(word);
      if (word == String("météo"))
        {
          Meteo_aff m1;
          m1.temp =  get_temp();
          m1.dn_cond = get_day_night();
          m1.wmo_code = get_WMO();
          m1.setLocation("Guilers");
          m1.print_4user();
          delay(10000);
        }
      else if (word == String("minuteur"))
        {
          Timer(600);
        }
      else if (word == String("bonjour"))
        {
          bonjour_func();
        }
      else if ((word == String("date"))||(word == String("heure")||(word == String("jour"))))
        {
          print_datetime();
        }
      else if (word == String("allume bureau"))
        {
          String input_phrase = String("Turn on Bureau Romain");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("éteins bureau"))
        {
          String input_phrase = String("Turn off Bureau Romain");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("ouvre le volet"))
        {
          String input_phrase = String("set velux romain at 100%");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("entrouvre le volet"))
        {
          String input_phrase = String("set velux romain at 50%");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("ferme le volet"))
        {
          String input_phrase = String("set velux romain at 0%");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("TF1"))
        {
          String input_phrase = String("tf1");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("France 2"))
        {
          String input_phrase = String("france 2");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("M6"))
        {
          String input_phrase = String("m6");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("France 3"))
        {
          String input_phrase = String("france 3");
          exec_com_assistant(API_key,Device_Id,Model_Id,input_phrase);
        }
      else if (word == String("info")||word == String("infos"))
        {
          display_titles();
        }
    }

    if (e1.step == 2)
    {
      delay(1000);
      xTaskCreate([](void *parameter)
      {
        e1.clign_in();
        vTaskDelete(NULL); 
      }, "task1", 2048, NULL, 5, NULL);
      xTaskCreate([](void *parameter)
      {
        fade_out_blue(parameter);
        vTaskDelete(NULL); 
      }, "task2", 2048, NULL, 5, NULL);
    }

    delay(2000);

  }

  if (count_inactivity >= 20){
    if (actived){
      e1.det_eyes_out();
      actived = false;
    }
    count_inactivity = 0;
  }

  delay(300);
}

Conclusion

To better understand the project, do not hesitate to explore the GitHub repository.