Générer des salves d'impulsions

Disons qu’il y a de mauvais exemples. Mais des éléments globaux vous en aurez toujours besoin. On est aussi en C++, pas en Java, tout n’a pas besoin d’être un objet.

je pense que vous faites des objets non globaux sans le savoir.

Par exemple si vous écrivez

void afficherX(int x) {
  String message = "le nombre vaut ";
  message += x;
  Serial.println(message);
}

L'objet message est local à la fonction. Il est crée lorsque l'on rentre dans la fonction et libéré automatiquement quand on en sort.

Sinon les instances classiques (Serial, vos boutons, LCD, ...) sont globales parce qu'on veut qu'elles durent tout le temps du programme et on veut souvent y avoir accès partout dans le code.

En C++ quand le programme se termine, tous les objets sont libérés (leur destructeur est appelé) avant de vraiment finir, y compris les globaux, mais sur un micro-contrôleur, le programme tourne généralement en boucle infinie et ne se termine pas vraiment sauf si on coupe l'alim, donc les destructeurs des objets globaux ne sont presque jamais appelés automatiquement.

Je n'ai jamais vu créer un objet global sauf dans Arduino et tu as la réponse dans ta question, c'est pour la facilité. Un objet n'est pas une variable tout comme une classe n'est pas une structure. Les tutos font généralement un rapprochement entre C et C++ en mettant en parallèle structure/variable et class/objet mais c'est oublier de préciser en C++ le lien entre variable et entité et le lien entre données et traitement tout en ignorant encapsulation et abstraction.

C'est une question d'allocation, mais je crois qu'il y a peu ou pas de différence entre C et C++ hormis les mots clés

Je ne dis pas que l'on n'a jamais besoin d'une variable globale même si cela demeure rare mais je ne connais aucune raison de créer une liste de variables globales, d'avoir un objet global ou de mettre les variables d'une class en public hormis se faciliter la vie

Ça je l'avais compris.
C'est vrai pour Serial, mais aussi l'objet Wire de la classe twowire pour l'I2C.
D'ailleurs, on voit des bibliothèques dans lesquelles l'auteur doit trouver ridicule ce nom de Wire et créé son propre objet, avec un nom plus logique et plus proche du terme i2c.

Je m'explique différemment.
C'est de la curiosité.
Je ne cherche pas à savoir si on gagne quelque chose ou pas.
Je n'ai jamais vu d'exemple où un objet instancié dans une fonction était passé en paramètre dans une autre.
En général, j'ouvre mes fichiers des bibliothèques, même si je ne comprends pas tout.

Le Viking et toi, vous me confirmez qu'un objet peut se manipuler comme une variable ?
Cela m'a toujours paru cohérent, mais ma curiosité n'est pas assez forte pour me forcer à franchir le pas. :grinning_face:

Vous avez souvent l’instance qui représente l’application (suivant les langages et environnement)

Je ne sais pas ce que vous voulez dire par la , En C++, toute variable est une instance d’un type, qu’il soit fondamental ou défini par l’utilisateur.

C’est parfois une motivation :slight_smile:

En C++, seule la visibilité par défaut change : dans une struct les membres sont publics par défaut, dans une class ils sont privés. Pour le reste, elles ont exactement les mêmes capacités (constructeurs, héritage, méthodes virtuelles, surcharge…).

J'aurais dit le contraire pour les cours sur la programmation. Exemple OpenClassroom qui est pour beaucoup une référece.

Bonsoir,
j'ai repris un peu le code RMT de al1fch pour le faire fonctionner (le RMT) :

#include <driver/rmt.h>

#define RMT_TX_CHANNEL RMT_CHANNEL_0  // Canal RMT à utiliser
#define RMT_TX_GPIO_NUM 17            // GPIO à utiliser pour la sortie

// Création des impulsions
const int pulse_count = 10;  // 10 impulsions
rmt_item32_t items[pulse_count];

void setup() {
  // Configuration du canal RMT
  rmt_config_t config;
  config.rmt_mode = RMT_MODE_TX;
  config.channel = RMT_TX_CHANNEL;
  config.gpio_num = (gpio_num_t)RMT_TX_GPIO_NUM;
  config.mem_block_num = 1;
  config.tx_config.loop_en = false;
  config.tx_config.carrier_en = false;
  config.tx_config.idle_output_en = true;
  config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
  config.clk_div = 80;  // Diviseur d'horloge (80 MHz / 80 = 1 MHz → 1 tick = 1 µs)

  rmt_config(&config);
  rmt_driver_install(config.channel, 0, 0);

  // Durées en µs 
  const uint32_t high_duration = 25; // 25 us
  const uint32_t low_duration = 50;  // le double pour l'état bas dans cet exemple

  // Remplir le tableau d'items
  for (int i = 0; i < pulse_count; i++) {
    items[i].duration0 = high_duration;
    items[i].level0 = 1;
    items[i].duration1 = low_duration;
    items[i].level1 = 0;
  }

}

void loop() {
  delay(100); //
  rmt_write_items(RMT_TX_CHANNEL, items, pulse_count, true); // envoie la télécommande
}

pour qui cela intéresse

1 Like

Non un objet ne peut pas être manipulé comme une variable si la classe est correctement codée, c'est à dire en respectant le principe d'encapsulation

C'est le cas de Qt mais je n'utilise jamais un objet déclaré global pour le faire.
Pour ce qui est structure je répondais @68tjs au sujet des tutos qui expliquent le C++ en prenant le C comme référence, je ne parlais pas de class et structure en C++.

Oui - Je ne suis pas du tout un pro de Qt mais il me semble que de nombreux services et ressources comme le presse-papiers, les paramètres, le pool de threads ou les polices sont accessibles globalement . Vous avez aussi l’écran, le clavier, la souris et les périphériques d’entrée-sortie qui sont également accessibles globalement via des classes qui centralisent leur gestion et fournissent des accès unifiés aux événements et aux ressources associées.

La majorité des environnements OO utilisent des objets globaux qui représentent l’application ou le système, souvent pour structurer l’environnement d’exécution ou centraliser la gestion des ressources.

En Objective-C vous avez UIApplication sur iOS, en Swift @main struct App et UIApplication.shared, en Java la classe Application sous Android ou des singletons système comme Runtime.getRuntime(), en C# avec Application sous Windows Forms ou App sous WPF, en Python via certains frameworks comme Flask ou Django avec des instances globales d’application, ou en Delphi avec l’objet Application global…

➜ Ces objets servent de point d’entrée ou de gestionnaire centralisé pour l’environnement d’exécution et on obtient ces instances globales en les créant dans main() car elles sont rendues disponibles via des getters statiques / à travers l’objet Application.

Donc une ou des instances globales qui représentent le système sont acceptables et acceptées dans l’industrie comme une pratique courante.

Appliquez cela à la programmation embarquée, notamment sur Arduino : l’utilisation d’instances globales n’est pas forcément une mauvaise pratique ni un archaïsme, cela peut être un choix réfléchi et adapté au contexte.

Contrairement aux environnements généralistes où la modularité et la réutilisabilité imposent de limiter les variables globales, un microcontrôleur exécute une tâche dédiée, dans un cadre strict de ressources mémoire et de puissance de calcul.

Déclarer les instances en global permet d’allouer leur mémoire à la compilation, dans une zone bien définie (la zone data ou bss selon qu’elles sont initialisées ou non). Cela garantit qu’au démarrage, la mémoire occupée par ces objets est connue et réservée, évitant ainsi toute fragmentation dynamique et limitant les risques d’épuisement du tas ou de débordement de pile.

Il faut aussi se souvenir que l'allocation dynamique est souvent coûteuse et risquée dans ces environnements (pas de try catch sur un petit arduino), et permet une initialisation dès le démarrage, avec une empreinte fixe et maîtrisée, reportée à la compilation, ce qui facilite le dimensionnement mémoire.

C’est pour moi la même logique qu’un QApplication ou QGuiApplication sous Qt qui, de manière globale et centralisée, représente l’état de l’application. Ici, si vous pilotez des volets, l’état de chaque volet est central dans le système. Les instancier globalement permet à toutes les parties du programme d’y accéder sans surcharge inutile, et de maintenir un modèle mémoire parfaitement prévisible, ce qui est aussi fondamental en embarqué.

J'ai delete car la faim étant mauvaise conseillère j'avais fait des raccourcis qui pouvaient être confus ou mal interprétés
Je ne suis pas un expert mais je connais suffisamment Qt pour dire que la class QApplication n'a pas d'objet global, il faut le créer
QApplication app(argc, argv);
et je n'ai trouvé aucune instance globale dans QApplication.
Dire accessibles globalement via des classes c'est justement dire je n'ai pas d'instance globale je suis le principe d'encapsulation. Perso je n'utilise pas car je personnalise mes widgets avec CSS mais je sais que c'est bien pratique sur les grosses appli notamment multilingues

Oui mais de mémoire (c'est veux et peut être plus d'actualité) certaines données internes à Qt sont en singleton ou en variables statiques cachées, mais en tant qu’utilisateur de l’API, on ne manipule pratiquement jamais d’objet global en effet mais ils sont (étaient) là.

Par contre cela a l'inconvénient (limité sur gros ordinateur) de la dynamicité, que l'on cherche à éviter sur les petits µC comme je le disais auparavant.