Multiplayer Gameshow Buzzer - Teil 2 - Spielererweiterung und Updates

Dans les commentaires du premier blogpost Multiplayer Game Show Buzzer, les gens ont demandé comment étendre la configuration de 4 à 8 joueurs. Cette question et quelques autres idées de petites mises à jour m'ont conduit à écrire une deuxième partie. J'utilise une gestion dynamique de la mémoire, de sorte que le nombre de joueurs peut être choisi librement entre 1 et (y compris) 12. Je montre également qu'il n'est pas nécessaire d'initialiser les broches d'entrée dans la routine setup() et j'ajoute quelques astuces qui font transpirer le joueur un peu plus. C'est parti.

Ce qu'il nous faut

Numéro

Composant

1

Nano v3 atmega328 ou alors Boîte de microcontrôleur avec ATMEGA328P

Jusqu'à 12

Bouton

1

RGB WS2812B Bague LED avec 12 LED

1

Module de buzzer passif KY-006

plusieurs

câble de connexion

2

Breadboard ou alors MB 102 Breadboard Kit


Schéma

schéma

Schéma du circuit à cliquer

Microcontrôleur

RGB Bague LED

D2

IN

+ 5V

VCC

GND

GND


Buzzer

D3

(S)ignal

GND

-


Bouton 1-12

D4 - D12

A0 - A2

Pin 1 chacun

GND

Pin 2 chacun


Le lecteur attentif remarquera maintenant que nous n'utilisons pas D13. Cette broche ne doit pas être utilisée comme broche d'entrée sur le Nano V3.0 avec Atmega328, car la résistance de la LED intégrée s'y trouve. Pour les versions plus grandes de l'ATmega328, cela devrait marcher. Mais comme j'aime les défis, on va s'en tenir à la petite version et la quille numéro 13 va rester sur le carreau. Puisque nous disposons d'un ensemble de 12 LED sur l'anneau de LED RVB, mais que les broches numériques officielles sont à plat, nous allons utiliser les broches analogiques comme entrées numériques.

La structure est par ailleurs la même que dans la partie 1. Nous ne faisons qu'étendre les boutons 5 à 12.

Exposition

Mon nouvel objectif est d'étendre les boutons de manière dynamique. Bien sûr, cela est limité car les broches doivent être initialisées comme sorties ou entrées dans le code source. Cette tâche ne peut être confiée à l'utilisateur. Nous nous limitons donc à un maximum de 12 joueurs. En allumant le microcontrôleur, je veux d'abord déterminer combien de joueurs vont participer. Le premier bouton est obligatoire. Nous en avons besoin pour le mode de configuration du joueur. Au début, vous appuyez sur ce bouton aussi souvent qu'il y a des joueurs. Pour chaque joueur, une autre LED s'allume sur l'anneau. Lorsque le dernier lecteur est sélectionné, appuyez sur le bouton et maintenez-le enfoncé pour terminer la configuration du lecteur. Si vous voulez utiliser les 12 boutons, appuyez sur la touche et maintenez-la enfoncée jusqu'à ce que tous les voyants s'allument. L'installation est alors automatiquement terminée et vous pouvez commencer.

Dans la première version, la LED du lecteur s'allumait pendant quelques secondes après l'appui sur un bouton. Je pensais que cela pouvait être utilisé pour limiter le temps de réponse d'un joueur après qu'il ait buzzé. Pour mettre un peu plus de "pression" sur le joueur, j'ai maintenant ajouté un bip qui se fait entendre toutes les secondes. Lorsque le temps de réponse est écoulé, vous entendez un long bip.

Le code source

Dans le sketch, j'ai étendu le nombre maximum de boutons à 12 et défini la broche 4 du microcontrôleur comme DEFAULTBUTTONPIN. J'ai étendu le tableau uint32_t color[MAX_BUTTONS], qui contient les valeurs des couleurs, à 12. À ce stade, il est difficile de créer la mémoire de manière dynamique. Les valeurs des couleurs pourraient être générées de manière aléatoire, puis étendues de manière dynamique, comme je le montrerai dans un instant avec les autres tableaux. Je l'ai enregistré et j'ai corrigé les couleurs.

J'ai modifié les tableaux pour les broches d'entrée et les états des boutons comme suit :

 int *Bouton_pins = ZÉRO;
 int *Button_Pins_Temp = ZÉRO;
 booléen *Vieux = ZÉRO;
 booléen *oldstate_temp = ZÉRO;
 booléen *Newstate = ZÉRO;
 booléen *Newstate_temp = ZÉRO;

Peut-être la question se pose-t-elle maintenant : que fait-il ?

Les pointeurs sont un livre fermé pour beaucoup de gens. Un tableau peut être programmé en notation de tableau. Cela ressemble à quelque chose comme ça :

 int Bouton_pins[1] = 0;

Comme vous pouvez déjà le constater, le nombre d'éléments est déterminé lors de la déclaration. Cependant, nous ne savons pas, lors de la programmation, combien de boutons seront utilisés ultérieurement et un tableau ne peut pas être étendu lors de l'exécution. Nous ne pouvons définir que le nombre maximum. Bien entendu, nous pouvons également créer un tableau de 12 champs. Mais nous voulons le rendre un peu plus excitant, économiser de la mémoire et travailler de manière dynamique. Nous utilisons donc la notation par pointeur. La définition avec NULL (qui ne correspond pas à 0, mais à un pointeur NULL) doit être faite de manière à ce que le pointeur ne pointe pas vers rien et qu'un état non défini se produise. Vous pouvez l'imaginer comme une prise aveugle dans le monde réel. Un tuyau vide est posé, mais pas encore utilisé et sécurisé par un bouchon aveugle pour le moment. En plus de malloc(), il y a aussi calloc(), où toutes les valeurs sont définies avec 0, et realloc(), dont nous aurons besoin plus tard pour agrandir le tableau.

J'ai ensuite ajouté une autre tonalité C6 au tableau des tonalités. Dans la section que j'ai appelée GAME CONFIGURATION, le temps de réponse (maintenant 5 secondes / 5000 ms), l'intervalle entre les bips du temps de réponse (maintenant 1 seconde / 1000 ms) et le maintien de la touche pendant la configuration (maintenant 2 secondes / 2000 ms) peuvent être modifiés.

Dans le setup(), les tableaux sont ensuite dotés d'un espace de stockage et connectés aux pointeurs que j'ai déclarés auparavant :

   Bouton_pins = (Int *)malloc(Joueur_count*(taille de(int)));
   Vieux = (booléen*)malloc(Joueur_count*(taille de(booléen)));
   Newstate = (booléen*)malloc(Joueur_count*(taille de(booléen)));
   Bouton_pins[0] = DefaultButtonPinPin;

La fonction malloc() réserve la mémoire de la taille spécifiée et renvoie un pointeur vers cet emplacement mémoire. Avec l'affectation à BUTTON_PINS, notre tableau est lié à cet emplacement mémoire. La variable player_count contient la valeur 1 au démarrage du programme. La fonction sizeof(int) renvoie la taille d'un entier, on réserve donc 1 x 2 octets. Si nous avions laissé player_count commencer par 0 comme d'habitude, aucune mémoire ne pourrait être réservée, car 0 x quelque chose reste 0. Nous pouvons alors utiliser ce compteur plusieurs fois, mais nous devons faire attention plus tard lorsque nous utilisons la variable comme index pour le tableau, car là nous commençons à compter avec 0.

Le tableau BUTTON_PINS est en fait la liste qui contient la broche d'entrée de chaque joueur. De cette façon, je peux attribuer les quilles à tous les joueurs de 0 à 11 et itérer sur cette liste plus tard. Le joueur 0 contient le DEFAULTBUTTONPIN 4.

Après l'animation de démarrage, que je n'ai pas modifiée, la LED du premier joueur s'allume :

   déshabiller.Setpixelcolor(Joueur_count - 1, Couleur[Joueur_count - 1]);
   déshabiller.spectacle();

Cette fois-ci, je me suis abstenu de régler le décalage de manière à ce que la LED supérieure soit attribuée au premier joueur. Cela prendrait un peu plus de temps.

Dans la boucle(), il faut maintenant faire la distinction entre la configuration du joueur et le mode de jeu normal. Ceci est fait par la variable setupMode. Lorsque le programme démarre, nous sommes dans la configuration du lecteur, la première LED est allumée et le premier bouton est déjà initialisé comme entrée. Si le bouton est pressé, les tableaux sont agrandis avec realloc().

Remarque : malloc(), calloc() et realloc() ne doivent être utilisés que de manière limitée sur ces microcontrôleurs, car la mémoire du programme est fragmentée et finit par s'épuiser. Comme nous nous limitons à 12 joueurs, cela ne devrait pas poser de problème.

Avec l'extension du tableau de broches, la broche respective est également initialisée comme une entrée. Ceci peut être fait non seulement dans setup(), mais aussi à tout moment plus tard dans le programme. Maintenant, c'est un peu plus délicat si vous utilisez le petit Nano V3 ATmega328, car la broche 13 ne doit pas être initialisée comme une entrée et utilisée avec des boutons. Avec l'astuce suivante et une autre variable, nous pouvons entrer les broches dans le tableau des broches au fur et à mesure de nos besoins :

 // broche 13 surpring
 SI (Joueur_count < 10) {
     code PIN = DefaultButtonPinPin + (Joueur_count - 1);
 }
 Autre {
     code PIN = DefaultButtonPinPin + (Joueur_count);
 }

Le joueur n°9 a la broche D12. Entre-temps, il reste avec l'ordre calculé à l'aide du DEFAULTBUTTONPIN et du numéro du joueur. La broche 4 est déjà présente dans le tableau à la position 0. Les broches 5 à 12 sont saisies ici l'une après l'autre. Continuez ensuite avec la broche 14 (A0). Lorsque le nombre maximum de joueurs est saisi, le tableau ressemble à ceci :

domaine

0

1

2

3

4

5

6

7

8

9

10

11

Code PIN

4

5

6

7

8

9

10

11

12

14

15

16

Si nous itérons maintenant sur le numéro de champ, nous obtenons toujours la broche d'entrée correspondante, dont nous avons besoin pour digitalRead() dans la boucle principale. Les tableaux oldState et newState sont également étendus. Si vous utilisez un autre microcontrôleur, vous pouvez commenter ou adapter ce petit algorithme.

Lorsque le nombre maximum de joueurs est atteint, la configuration des joueurs est terminée, les LED sont éteintes et le jeu télévisé peut commencer.

Si vous voulez que le nombre de joueurs reste faible, le bouton doit rester enfoncé et la configuration des joueurs doit être terminée après le temps présélectionné. Pour ce faire, nous utilisons buttonpress_time = millis() ; pour prendre le temps de départ lorsque le bouton est pressé. La requête à ce sujet suit plus bas :

   // tenir la main pour finir la configuration du joueur
   SI (installer && (Newstate[Button_Count] == Faible) && (Vieux[Button_Count] == Faible)) {
     SI (millis() - Boutonpress_time >= BoutonLongress_Time) {
       installer = faux;
       pour (int je = 0; je < Pixel_count; je++) {
         déshabiller.Setpixelcolor(je, déshabiller.Couleur(  0,   0,   0));
         déshabiller.spectacle();
      }
    }
  }

À ce stade, on vérifie si la broche d'entrée était LOW, est LOW et si le programme est toujours en setupMode. Si c'est le cas, on vérifie si le temps de maintien de la touche est atteint. Si oui, la configuration du lecteur se termine également ici.

Vous pouvez télécharger le code source complet ici.

Conclusion

Une véritable évolution (c'est-à-dire une flexibilité dans le nombre de joueurs) n'est possible que dans une mesure limitée. Le tableau des couleurs pourrait toujours être rempli automatiquement. Sinon, cela dépend du microcontrôleur utilisé et du nombre de broches d'entrée disponibles. Avec quelques ajustements, vous pouvez augmenter ce nombre autant que vous le souhaitez. Cependant, avec 12 joueurs, vous êtes déjà sur la bonne voie. Vous devrez alors également remplacer l'anneau RVB pour que davantage de LED soient disponibles.

Amusez-vous bien à bricoler

Andreas Wolter

pour le blog AZ-Delivery.

Pour arduinoProjets pour les débutants

Laisser un commentaire

Tous les commentaires sont modérés avant d'être publiés

Messages de blogs recommandés

  1. Installez maintenant ESP32 via l'administrateur de la carte
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA-Over the Air-ESP Programmation par WiFi