4. Générateur de nombres aléatoires & sortie PWM


Parmi les fonctions de base, il en existe une qui nous semble rarement utile: le générateur de nombres aléatoires. En effet, en modélisme ferroviaire, nous sommes plutôt préparés à gérer des évènements discrets, des automates à états, des messages de commandes prévisibles, etc... Or, on lui trouve un intérêt dans un cas bien particulier. Mais nous le verrons plus bas avec un exemple...


Qu'est-ce qu'un générateur de nombres aléatoires?

Comme son nom l'indique, c'est une fonction qui, à chaque appel, fournit un nombre aléatoirement déterminé dans un intervalle donné. Or, un ordinateur ou un processeur n'a aucune notion de hasard ou d'évènement aléatoire. Pour combler ce manque, il existe des tables hard-coded (codées "en dur" signifiant: indéformables, non modifiables...) au niveau du système. Celles-ci représentent des listes pré-définies de nombres simulant une suite de tirages pseudo aléatoires. Dans la plupart des situations et en particulier pour réaliser des animations, c'est bien suffisant...

La fonction fournie par l'environnement de l'Arduino est random(). On appelle cette fonction avec un paramètre qui correspond à l'ensemble des nombres parmi lesquels on désire en tirer un aléatoirement. Par exemple, si nous désirons obtenir un nombre aléatoire entre 0 et 9, il suffit d'appeler la fonction ainsi: random( 10 ).

En effectuant plusieurs tirages successifs avec le même paramètre, la suite des nombres obtenus doit normalement ressembler à une suite de nombres comme si nous avions pu "tirer au hasard des numéros d'un chapeau". Mais comme vous pourrez le constater avec un simple exemple, cette suite de tirages est prévisible.

long number = 0;

void setup()
{
  Serial.begin( 9600 );
  Serial.println( "Start" );
}

void loop()
{
  number = random( 10 );
  Serial.println( number );
  delay( 500 );
};


Les valeurs obtenues sont: 7, 9, 3, 8, 0, 2, 4, 8... En exécutant plusieurs fois de suite ce programme, la liste des valeurs reste la même... Et il ne serait pas étonnant que vous obteniez les mêmes résultats avec votre propre Arduino Uno...

Profitons de cet exemple pour insérer de nouvelles fonctions contenues dans la classe Serial (pour simplifier, voyez une classe comme un "ensemble" de fonctions régies par une mécanique interne qui leur est propre). Cette classe permet entre-autre d'afficher des messages à l'écran de l'ordinateur (dans le moniteur série de l'environnement de développement). Cela peut être utile lorsque qu'une erreur s'est glissée dans le programme et qu'il est nécessaire de comprendre pourquoi il ne fonctionne pas...

On commence par initialiser la classe en appelant la méthode Serial.begin() avec comme paramètre la vitesse de transfert en bauds. Ignorez pour l'instant la signification de cette valeur et utilisez 9600. Ensuite, la méthode Serial.println() affichera le message contenu en paramètre. Il peut s'agir de texte comme par exemple Serial.println( "Start" ) ou le contenu d'une variable Serial.println( number ). Dans notre exemple de code, nous obtiendrons l'affichage suivant:

Start
7
9
3
8
0
2
4
8

A chaque fois que le bouton reset de l'Arduino est pressé, l'affichage reprend à l'identique puisque la liste des tirages aléatoires... n'est pas aléatoire ;-). Mais assez de théorie pour l'instant, passons à la pratique!


Exemple du "feu de camp":

Là encore, nous ajoutons une nouvelle led sur la prochaine sortie PWM disponible. Il s'agit d'un montage à trois leds, mais cet exemple peut être étendu jusqu'à utiliser toutes les sorties PWM de la carte. Les couleurs sont aussi interchangeables suivant les goûts de chacun.


Comme dans les exemples précédents, le programmeur peut laisser libre cours à son imagination. Il n'y a pas une suite unique d'instructions pour réaliser ce genre d'effet. Bien au contraire, on mélangera les appels aux valeurs aléatoires et aux pauses afin d'obtenir une suite d'évènements la plus aléatoire possible. C'est souvent à ce moment-là qu'on rencontre le plus de difficulté pour représenter un effet réalistement. Mais cela s'acquiert par la pratique... Il faut tester différentes options ou combinaisons et bien observer les résultats. L'Arduino est très pratique pour cela, alors profitons-en...

Voici un exemple de code très simple:

int led1 = 3;
int led2 = 5;
int led3 = 6;

long number = 0;
long t = 0;

void setup()
{
  pinMode( led1, OUTPUT );
  pinMode( led2, OUTPUT );
  pinMode( led3, OUTPUT );
}

void loop()
{
  number = 100 + random( 100 );
  analogWrite( led1, number );
  t = random( 20 );
  delay( t );

  number = random( 256 );
  analogWrite( led2, number );
  t = random( 20 );
  delay( t );

  number = 150 + random( 100 );
  analogWrite( led3, number );
  t = random( 20 );
  delay( t );
}

Quelques mots d'explications:
  • on commence par définir les 3 ports à utiliser: led1, led2 et led3
  • comme nous l'avons vu précédemment, on initialise les trois ports en mode "sortie" avec la fonction pinMode()
  • ensuite, on combine les appels à random() et à delay() de façon à créer des durées et des intensités les plus aléatoires possible
  • pour finir, il ne faut pas oublier de changer l'état des sorties en appelant analogWrite().
Une remarque importante encore: à première vue, on peut penser en examinant le code que chaque led est allumée pendant une durée correspondant à l'instruction delay() qui suit l'appel à analogWrite(). Pas tout à fait... Ne vous inquiétez pas, c'est une confusion que l'on rencontre fréquemment chez les débutants en programmation... Souvenez-vous que delay() signifie uniquement "pause" et non pas "durée d'exécution de l'instruction qui la précède". En d'autres termes: delay() n'est pas la durée de analogWrite()! En fait, l'état d'une sortie persiste jusqu'à ce que son état change par un autre appel à analogWrite(). Donc ici, la led1 restera allumée à l'intensité choisie pendant une durée équivalente à la somme des trois delay() consécutifs... Prenez le temps d'examiner et de comprendre ce point... Je vous laisse étudier le reste de cet exemple et vous encourage à le modifier à votre guise.

En conclusion, nous avons montré une utilisation possible de ce générateur de nombres aléatoires en le combinant aux sorties PWM. A partir de là, il est facile de créer d'autres effets similaires comme:
  • un poste de soudure à l'arc en utilisant des leds de couleurs blanche et bleue et en modifiant l'effet par la génération de clignotements plus rapides et intenses
  • un poste de soudure à l'acétylène en utilisant des leds jaunes et en créant des effets relativement constant sans trop de clignotements
  • un écran de télévision dans un appartement en utilisant des leds de couleurs différentes
  • un tube néon ou une ampoule qui clignote au dessus d'une porte
  • le démarrage de l'éclairage urbain en simulant la variation d'intensité des ampoules au sodium
  • etc...

Le reste est juste un mélange d'imagination et d'observation... En attendant, voici l'effet obtenu avec notre exemple. Bons tests!




Aucun commentaire:

Publier un commentaire