WikiElectronique

Wiki sur l'électronique et l'informatique

Outils pour utilisateurs

Outils du site


esp_idf

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
esp_idf [2024/06/15 19:01] – [Plusieurs valeurs en même temps] jpesp_idf [2024/06/26 00:01] (Version actuelle) – [ADC] jp
Ligne 6: Ligne 6:
 Aller dans le menu "Extension"\\ Aller dans le menu "Extension"\\
 Installer l'extension "ESP-IDF"\\ Installer l'extension "ESP-IDF"\\
 +Vérifier que vous avez bien la dernière version d'ESP-IDF 
 +
  
 ===== Créer un 1er projet ===== ===== Créer un 1er projet =====
Ligne 55: Ligne 57:
 </code> </code>
  
-delay() est bien souvent une fonction bloquante qui va demander à votre micro de tourner en boucle et ne fera rien d'autre jusqu'à que ça boucle soit terminée. (Cette méthode c'est le mal !)+delay() est bien souvent une fonction bloquante qui va demander à votre micro de tourner en boucle et ne fera rien d'autre jusqu'à que sa boucle soit terminée. (Cette méthode c'est le mal !)
  
-Arduino propose aussi une méthode millis() qui renvoie le nombre de millisecondes écoulé depuis le démarrage du micro. +Arduino propose aussi une méthode millis() qui renvoie le nombre de millisecondes écoulées depuis le démarrage du micro. 
 Il s'agit d'un compteur qui est incrémenté par un timer.\\ Il s'agit d'un compteur qui est incrémenté par un timer.\\
-Il est possible de comparer "l'heure" du début de notre tache (previousTime) à la valeur de millis() (currentTime) et si la différence est supérieur à X ms, alors X ms se sont écoulés+Il est possible de comparer "l'heure" du début de notre tache (previousTime) à la valeur de millis() (currentTime) et si la différence est supérieur à X ms, alors X ms se sont écoulées
 Le code n'est plus bloquant mais cela implique de créer un nombre important de variables et transformer votre code en usine à gaz si vous avez plusieurs taches à exécuter.  Le code n'est plus bloquant mais cela implique de créer un nombre important de variables et transformer votre code en usine à gaz si vous avez plusieurs taches à exécuter. 
    
Ligne 126: Ligne 128:
  
 Résultat: Un entier 12 Résultat: Un entier 12
 +
 +==== Un nombre entier sur 3 digits ====
 +
 +<code c>
 +  int8_t val = 12;
 +  printf("Un entier %03d\r\n",val);
 +</code>
 +
 +Résultat: Un entier 012
 +
  
 ==== Un nombre entier négatif ==== ==== Un nombre entier négatif ====
Ligne 171: Ligne 183:
  
 ===== String ===== ===== String =====
 +
 +==== Concaténation ====
  
 On a souvent besoin de manipuler des chaînes de caractères.  On a souvent besoin de manipuler des chaînes de caractères. 
Ligne 187: Ligne 201:
     printf("Trame: %s dont la taille est %d\r\n",trame,pt);     printf("Trame: %s dont la taille est %d\r\n",trame,pt);
 } }
-<code>+</code>
  
 Résultat : Trame: ESP32-C6,VALI:12,VALF:3.14; dont la taille est 27 Résultat : Trame: ESP32-C6,VALI:12,VALF:3.14; dont la taille est 27
Ligne 193: Ligne 207:
 Il est évidement possible d'écrire ceci en un seul sprintf(). Il est évidement possible d'écrire ceci en un seul sprintf().
  
 +===== ESP-NOW =====
 +
 +L'ESP-NOW est une méthode simple de transmission de données par radio en 2.4Ghz entre plusieurs ESP. 
 +
 +Avantages :\\
 +  * Simple à mettre en œuvre
 +  * Pas de temps d'appairage et peu de latence lors des transmissions
 +  * Pas de réseau (Pas de réseau ESP-NOW à créer, pas de réseau Wifi à rejoindre, pas de gateway, c'est du vrai point à point)
 +  * Possibilité de crypter les trames
 +  * Pas besoin de déclarer l'adresse de l’émetteur sur l'ESP récepteur. (Ca peut se faire en live au moment de la réception de la trame)
 +  * Portée plus importante que du Wifi classique
 +  * Consommation réduite
 +
 +Inconvénients : \\
 +  * Limité à 20 devices (On a néanmoins la possibilité de broadcaster une trame à tout le monde et donc d'avoir plus de 20 devices max)
 +  * Pas de gestion des collisions
 +
 +Exemple de code pour un récepteur:\\
 +<code c>
 +#include <stdlib.h>
 +#include <string.h>
 +#include "freertos/FreeRTOS.h"
 +#include "freertos/task.h"
 +#include "freertos/queue.h"
 +#include "nvs_flash.h"
 +#include "esp_event.h"
 +#include "esp_netif.h"
 +#include "esp_wifi.h"
 +#include "esp_log.h"
 +#include "esp_system.h"
 +#include "esp_now.h"
 +
 +void onReceiveData(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int len) {
 +    printf("** Data Received **\n");
 +    printf("Source: %02x:%02x:%02x:%02x:%02x:%02x\n", esp_now_info->src_addr[0], esp_now_info->src_addr[1], esp_now_info->src_addr[2], esp_now_info->src_addr[3], esp_now_info->src_addr[4], esp_now_info->src_addr[5]);
 +    printf("Destination: %02x:%02x:%02x:%02x:%02x:%02x\n", esp_now_info->des_addr[0], esp_now_info->des_addr[1], esp_now_info->des_addr[2], esp_now_info->des_addr[3], esp_now_info->des_addr[4], esp_now_info->des_addr[5]);
 +    printf("Length: %d byte(s)\n", len);
 +    printf("Data: %d\n\n", data[0]);
 +}
 +
 +static void init_espnow(void)
 +{
 +    if (esp_now_init() != ESP_OK) {
 +        printf("Error initializing ESP-NOW\n");
 +        return;
 +    }
 +    else
 +        printf("ESP-NOW ready !\n");
 +
 +    esp_now_register_recv_cb(onReceiveData);
 +}
 +
 +static void init_wifi(void)
 +{
 +    const wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
 +    esp_err_t ret = nvs_flash_init();
 +    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
 +        ESP_ERROR_CHECK( nvs_flash_erase() );
 +        ret = nvs_flash_init();
 +    }
 +    ESP_ERROR_CHECK( ret );
 +    ESP_ERROR_CHECK( esp_netif_init());
 +    ESP_ERROR_CHECK( esp_event_loop_create_default() );
 +    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
 +    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
 +    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
 +    ESP_ERROR_CHECK( esp_wifi_start() );
 +}
 +
 +void app_main(void)
 +{    
 +    init_wifi();
 +    init_espnow();
 +
 +    while (1) {
 +        vTaskDelay(100/ portTICK_PERIOD_MS);
 +    }
 +}
 +</code>
 +
 +<code>
 +** Data Received **
 +Source: 40:4c:ca:5c:c9:6c
 +Destination: 40:4c:ca:5b:e9:50
 +Length: 4 byte(s)
 +Data: 65
 +</code>
 +
 +
 +Exemple de code pour un émetteur:
 +<code c>
 +#include <stdlib.h>
 +#include <string.h>
 +#include "freertos/FreeRTOS.h"
 +#include "freertos/task.h"
 +#include "freertos/queue.h"
 +#include "nvs_flash.h"
 +#include "esp_event.h"
 +#include "esp_netif.h"
 +#include "esp_wifi.h"
 +#include "esp_log.h"
 +#include "esp_system.h"
 +#include "esp_now.h"
 +
 +uint8_t broadcastAddress[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; //A remplacer par l'adresse mac du destinataire
 +esp_now_peer_info_t peerInfo;
 +int x = 65;
 +
 +void onReceiveData(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int len) {
 +    printf("** Data Received **\n");
 +    printf("Source: %02x:%02x:%02x:%02x:%02x:%02x\n", esp_now_info->src_addr[0], esp_now_info->src_addr[1], esp_now_info->src_addr[2], esp_now_info->src_addr[3], esp_now_info->src_addr[4], esp_now_info->src_addr[5]);
 +    printf("Destination: %02x:%02x:%02x:%02x:%02x:%02x\n", esp_now_info->des_addr[0], esp_now_info->des_addr[1], esp_now_info->des_addr[2], esp_now_info->des_addr[3], esp_now_info->des_addr[4], esp_now_info->des_addr[5]);
 +    printf("Length: %d byte(s)\n", len);
 +    printf("Data: %d\n\n", data[0]);
 +}
 +
 +static void init_espnow(void)
 +{
 +    if (esp_now_init() != ESP_OK) {
 +        printf("Error initializing ESP-NOW\n");
 +        return;
 +    }
 +    else
 +    {
 +        printf("ESP-NOW ready !\n");
 +        SetColorWhite();
 +    }
 +    memcpy(peerInfo.peer_addr, broadcastAddress, 6);
 +    peerInfo.channel = 0;  
 +    peerInfo.encrypt = false;
 +    if (esp_now_add_peer(&peerInfo) != ESP_OK){
 +        printf("Failed to add peer\n");
 +        return;
 +    }
 +    esp_now_register_recv_cb(onReceiveData);
 +}
 +
 +static void init_wifi(void)
 +{
 +    const wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
 +    esp_err_t ret = nvs_flash_init();
 +    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
 +        ESP_ERROR_CHECK( nvs_flash_erase() );
 +        ret = nvs_flash_init();
 +    }
 +    ESP_ERROR_CHECK( ret );
 +    ESP_ERROR_CHECK( esp_netif_init());
 +    ESP_ERROR_CHECK( esp_event_loop_create_default() );
 +    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
 +    ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
 +    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
 +    ESP_ERROR_CHECK( esp_wifi_start() );
 +}
 +
 +void app_main(void)
 +{    
 +    init_wifi();
 +    init_espnow();
 +
 +    while (1) {
 +
 +        esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &x, sizeof(int));
 +        if (result == ESP_OK) {
 +            printf("Data sent successfully\n");
 +        }
 +        else {
 +            printf("Error sending the data\n");
 +        }
 +         vTaskDelay(10000 / portTICK_PERIOD_MS);
 +    }
 +}
 +</code>
 +
 +On peut évidement combiner les codes pour faire un émetteur/récepteur.
 +
 +===== LOG =====
 +
 +Espressif a développé un système de log via la liaison série assez puissant.
 +Au lieu d'utiliser un simple printf(), on va utiliser ESP_LOGx
 +
 +Texte informatif en vert\\
 +<code c>
 +ESP_LOGI(TAG,"Trame: %s, len: %d", tx_buffer,len);
 +</code>
 +
 +Texte d'erreur en rouge\\
 +<code c>
 +ESP_LOGE(TAG,"%s", "Error initializing ESP-NOW");
 +</code>
 +
 +Texte d'alerte en orange\\
 +<code c>
 +ESP_LOGW(TAG,"%s", "Warning");
 +</code>
 +
 +TAG va permettre de mettre un prefix devant la ligne afin d'identifier le context. Il se déclare comme ceci :\\
 +<code c>
 +static const char *TAG = "log";
 +</code>
 +
 +<code c>
 +#include <stdlib.h>
 +#include <string.h>
 +#include "esp_log.h"
 +
 +static const char *TAG = "log";
 +
 +void app_main(void)
 +{
 +  uint8_t broadcastAddress[] = {0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF};
 +  uint8_t len =6;
 +  
 +  ESP_LOGI(TAG,"Adresss: %s, len: %d", broadcastAddress,len);
 +  
 +  ESP_LOGE(TAG,"%s", "Error");
 +}
 +</code>
 +
 +L'avantage de cette solution est que vous pouvez facilement choisir dans votre code le niveau d'information que vous souhaitez affricher. Par défaut vous allez tout voir mais si dans votre code vous tapez : 
 +
 +<code c>
 +esp_log_level_set("*", ESP_LOG_ERROR);
 +</code>
 +Uniquement les log d'erreur seront affichés
 +
 +<code c>
 +esp_log_level_set("wifi", ESP_LOG_WARN);
 +</code>
 +Uniquement les log d'alerte avec le tag wifi seront affichés. 
 +
 +<code c>
 +esp_log_level_set("*", ESP_LOG_NONE);
 +</code>
 +Aucun log n'est affiché
 +
 +Ce qui permet de mettre beaucoup de log mais de n'afficher que ce qui nous interesse sans polluer la liaison série en fonctionnement normal
 +
 +===== ADC =====
 +
 +La mise en oeuvre de l'ADC de l'ESP32 n'est pas forcement simple. \\
 +Il faut savoir que l'ESP32 dispose d'une référence interne de 1.1V mais qui peut varier de 1V à 1.2V ...\\
 +C'est pour cette raison, qu'il est necessaire de réaliser une calibration de cette référence lors de l'initialisation de l'ADC.
 +
 +Voici les étapes d'initialisation de l'ADC : 
 +__Etape 1:__ \\
 +Configuration de l'ADC1 pour une lecture ponctuelle. 
 +Cette méthode retourne un handle vers l'ADC1
 +<code c>
 +    adc_oneshot_unit_init_cfg_t init_config1 = {
 +        .unit_id = ADC_UNIT_1,
 +    };
 +    ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
 +</code>
 +
 +__Etape 2:__ \\
 +Configuration de l'ADC pour retourner une valeur sur 12bits et d’atténuer le signal d'entrée de 12db.
 +Ce qui veut dire que l'attenuation sera de 20.log(x) = -12 => x = 0.251. 
 +La tension appliquée sur l'entrée sera multipliée par 0.251 avant d'entrée sur l'ADC. 
 +Donc 3.3V donnera 0.828V sur l'entrée de l'ADC dont la pleine échelle est 1.1V.
 +
 +On configure également l'entrée GPIO 5 comme entrée de l'ADC.
 +<code c>
 +    adc_oneshot_chan_cfg_t config = {
 +        .bitwidth = ADC_BITWIDTH_DEFAULT,
 +        .atten = ADC_ATTEN_DB_12,
 +    };
 +    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_5, &config));
 +</code>
 +
 +__Etape 3:__ 
 +
 +Une fois la configuration terminée, on lance la calibration de l'ADC.
 +<code c>
 +    adc_cali_curve_fitting_config_t cali_config = {
 +    .unit_id = ADC_UNIT_1,
 +    .chan = ADC_CHANNEL_5,
 +    .atten = ADC_ATTEN_DB_12,
 +    .bitwidth = ADC_BITWIDTH_DEFAULT,
 +    };
 +    esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_chan0_handle);
 +</code>
 +
 +__Etape 4:__ 
 +Une fois la configuration réalisée, il ne reste plus qu'à lire la valeur mesurée par l'ADC.\\
 +La mesure se fait en 2 étapes. La première consiste à récupérer la valeur brute de l'ADC et la 2ème consiste à convertir cette tension par rapport à l'atténuation, la tension de référence et sa calibration.
 +
 +<code c>
 +ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_5, &adc_raw));
 +ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, ADC_CHANNEL_5, adc_raw);
 +        
 +ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw, &voltage));
 +ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, ADC_CHANNEL_5, voltage);
 +</code>
 +
 +Exemple complet: 
 +<code c>
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include "freertos/FreeRTOS.h"
 +#include "freertos/task.h"
 +#include "soc/soc_caps.h"
 +#include "esp_log.h"
 +#include "esp_adc/adc_oneshot.h"
 +#include "esp_adc/adc_cali.h"
 +#include "esp_adc/adc_cali_scheme.h"
 +
 +const static char *TAG = "ADC";
 +
 +adc_oneshot_unit_handle_t adc1_handle;
 + adc_cali_handle_t adc1_cali_chan0_handle = NULL;
 +
 +static int adc_raw;
 +static int voltage;
 +
 +static void init_adc()
 +{
 +    //-------------ADC1 Init---------------//
 +    adc_oneshot_unit_init_cfg_t init_config1 = {
 +        .unit_id = ADC_UNIT_1,
 +    };
 +    ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
 +
 +    //-------------ADC1 Config---------------//
 +    adc_oneshot_chan_cfg_t config = {
 +        .bitwidth = ADC_BITWIDTH_DEFAULT,
 +        .atten = ADC_ATTEN_DB_12,
 +    };
 +    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_5, &config));
 +
 +    //-------------ADC1 Calibration Init---------------//
 +    adc_cali_curve_fitting_config_t cali_config = {
 +    .unit_id = ADC_UNIT_1,
 +    .chan = ADC_CHANNEL_5,
 +    .atten = ADC_ATTEN_DB_12,
 +    .bitwidth = ADC_BITWIDTH_DEFAULT,
 +    };
 +    esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_chan0_handle);
 +
 +    if (ret == ESP_OK) {
 +        ESP_LOGI(TAG, "Calibration Success");
 +    } else if (ret == ESP_ERR_NOT_SUPPORTED) {
 +        ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
 +    } else {
 +        ESP_LOGE(TAG, "Invalid arg or no memory");
 +    }
 +}
 +
 +void app_main(void)
 +{
 +    init_adc();
 +
 +
 +    while (1) {
 +        ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_5, &adc_raw));
 +        ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, ADC_CHANNEL_5, adc_raw);
 +        
 +        ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan0_handle, adc_raw, &voltage));
 +        ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, ADC_CHANNEL_5, voltage);
 +        
 +        vTaskDelay(1000/ portTICK_PERIOD_MS);
 +    }
 +}
 +</code>
 +
 +{{:esp32_c6_adc.png?400|}}
  
esp_idf.1718470895.txt.gz · Dernière modification : 2024/06/15 19:01 de jp

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki