Sortir un nombre sous forme binaire de 8 bits via les sorties digitale arduino

Bonsoir,

J’ai réalisé un ALU 8 bits Adder qui est capable d’additioner des termes < 255 en décimal (ou 11111111 en binaire). J’aimerais via mon arduino, entrer via le moniteur série un nombre décimal, que mon arduino convertisse le nombre en binaire ;

J’entre 42 sur le moniteur série, le programme stocke ce nombre sous sa forme binaire (00101010). Pour le premier terme de l’addition, les sorties 5 à 13 (une sortie pour chaque bit) seront défini en état haut quand il y a un 1, et en état bas quand il y a un 0 dans le nombre sous sa forme binaire stocke.

J’ai déjà un code un peu tiré par les cheveux qui me permet de générer des nombres sous forme binaire aléatoirement, mais qui n’est pas intéressant et génère à 95% des nombres > 100.

byte rnd_8bits[8];

void setup() {
  for (int pin = 5; pin < 14; pin++) {
    pinMode(pin, OUTPUT);
  }
}

void loop() {
  for (int i = 0; i < 8; i++) {
    rnd_8bits[i] = random(0, 2);
  }

  digitalWrite(5, rnd_8bits[0]);
  digitalWrite(6, rnd_8bits[1]);
  digitalWrite(7, rnd_8bits[2]);
  digitalWrite(8, rnd_8bits[3]);
  digitalWrite(9, rnd_8bits[4]);
  digitalWrite(10, rnd_8bits[5]);
  digitalWrite(11, rnd_8bits[6]);
  digitalWrite(12, rnd_8bits[7]);

  for (int i = 0; i < 8; i++) {
    rnd_8bits[i] = 0;
  }

  delay(500);
}

Pour le deuxième terme de l’addition je vais réaliser le projet final avec un atmega1284p pour avoir plus de broche (ou utiliser plusieurs shiftregister sur atmega328P)

Merci de m’éclairer sur la fonction à réaliser ou si ça existe déjà je suis preneur :slight_smile: ! Bonne soirée.

t’as de la chance, ton “nombre” est déjà stocké en binaire dans ton arduino (ainsi que dans tout ordinateur non-quantique), pour extraire chaque bit d’un nombre il suffit, par exemple, d’utiliser les décalages et un “masque” :

unsigned char nombreAConvertir = 12; // ou la valeur que tu veux, tu peux t'en faire une fonction aussi, ce sera plus simple
bool bitsSepares[8]; // les bits seront representés sous forme de booléens true = 1 et false = 0

for(int i=0; i<8; i++)
{
    bitsSepares[i] = ( ((nombreAConvertir >> i) & 1) != 0 );  // décalage du nombre à convertir du bit en cours d'extraction puis on prend le premier bit. La comparaison avec 0 c'est pour éviter un warning à la compilation puisqu'on récupère un booleen directement.
}

Et voilà, t’as “sorti” bit à bit, les bits de ton nombre… Après, au lieu d’utiliser un tableau, tu peux te contenter d’écrire directement dans tes sorties :

for(int i=0; i<8; i++)
{
    digitalWrite( i + 5,  ((nombreAConvertir >> i) & 1) ? HIGH : LOW); // i+5 car dans ton brochage tu commences par la sortie 5 et qu'elles se suivent
}

Si tu veux plus de détails, t’auras plus d’infos et explications détaillées en lisant ce tuto

Salut;

J’aimerais via mon arduino, entrer via le moniteur série un nombre décimal, que mon arduino convertisse le nombre en binaire ;

Pour envoyer un nombre entier du moniteur vers l’Arduino Il te suffi de te renseigner sur la classe Serial et ces fonctions qui traite la transmission de données série.
Voici un lien qui t’aidera a trouver les outils dont tu as besoins.
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.ReferenceEtendue

J’entre 42 sur le moniteur série, le programme stocke ce nombre sous sa forme binaire (00101010). Pour le premier terme de l’addition, les sorties 5 à 13 (une sortie pour chaque bit) seront défini en état haut quand il y a un 1, et en état bas quand il y a un 0 dans le nombre sous sa forme binaire stocke

Et pour la conversion en ASCII vers de l’entier je ne sais pas faire -(de tout façon l’un ne peut être traité avec et vers l’autre)-
Je te conseille d’utiliser la fonction parseInt().
Traduction du site Arduino => parseInt () retourne le première nombre entier valide (long) de la mémoire tampon série. Les caractères qui ne sont pas des nombres entiers (ou le signe moins) sont ignorés.

Voire https://www.arduino.cc/en/Reference/StreamParseInt

Je l’utilise pour envoyer des données a mes programme.C’est très utile pour ne pas avoir a téléversé à chaque fois qu’il faut corriger une valeur.

Pour tes LEDs je te conseil de déclarer un tableau des broches qui vas te donner énormément de souplesse pour leurs activations. Car tes leds ne prennent que deux état dans ton projet HIGH ou LOW.

Du genre.

const int leds [8] = {5,6,7,8,9,10,11,12} // Tableau des 8 broches utiles.

Ensuite avec deux boucles for et a laide de cette méthode

for (int i = 0; i < 255; i++) {
num++;
    //Affichage pour comparaison avec les leds du montage.
    Serial.print(num);Serial.print(' '); Serial.print(num, HEX); Serial.print(' '); Serial.println(num, BIN);
    delay(500);
    
    //Mise en place d'une boucle pour la lecture des bits contenus dans la variable "num".
    for (int j = 7; j >= 0; j--) {

      /*Affectation d'un état HIGH ou LOW à chaques leds en fonction de la représentation binaire de la variable "num".
         HIGH=Allumage : LOW=Extinction */
      digitalWrite(led[j], bitRead(num, j ) == 1 ?  HIGH : LOW );
    }//fin de la 2nd  boucle.
  }//Fin de la 1er boucle.//---*/

Pour note: num est une variable qui contient le chiffre à afficher sur tes leds. il faut la déclarer dans ton programme.
Essais déjà pour les leds et si tu as besoins d’aide pour la réception de donnée depuis le moniteurs série fait signe !!

A plus !!

Salut Zorro!

Je vois que tu as été plus rapide!!

Que vas donner ma bricole
Ta méthode c’est du costaud technique!!

A plus !

Il te faudra modifier cela dans la seconde boucle.

Car pour mon utilité j’avais du décrémenté et ce n’est peut être pas ton cas.

for (int j = 7; j >= 0; j–);

Faire cela si c’est inversé chez toi !

For (int j= 7; j=< 0; j++);

A plus !

salut manumanu ! ta fonction "bitRead()" doit faire à peu près la même chose que ce que j'ai montré, c'est juste "caché" par une fonction (que je ne connaissais pas), ce qui est peut-être pas plus mal pour les débutants... ;) par contre, mettre tes liens dans une balise [ url ] ca permet de pouvoir cliquer dessus directement :

[url=http://www.zcarcockpit.fr]Z-Car Cockpit[/url]

;)

Merci Zorro!

Savais pas pour les url !

Par contre je viens de me rendre compte que mon programme il n'y a besoins que d'une seul boucle. La seconde suffi . La première servait a incrémenté la variable "num++;"

Alvita tu peut la supprimer ! ou la garder pour faire évoluer tes chiffres c'est marrant !

A plus !!

Bon, puisque tu l’as suggéré en te trompant manumanu, voici un petit code qui compte en binaire de 0 à 255 sur les sorties 5 à 13 :

#define PREMIERE_PIN	5

unsigned char numero = 0;

void setup()
{
	for (int i =0; i < 8 ; i++ )
	{
		pinMode(PREMIERE_PIN + i, OUTPUT);
	}
}

void loop()
{
	for(int i=0; i<8; i++)
	{
		// "affichage" :
		digitalWrite( i + 5,  ((numero >> i) & 1) ? HIGH : LOW);
	}

	// prochain numéro, comme c'est un type char, il va recommencer tout seul à 0 lorsque 255 sera atteint
	numero++;

	// on attend presque 1 séconde entre 2 numéros
	delay(750);
}

Saut Zorro !

Puis je compléter camarade !!

Voici un complément de ce code qui nous épargne “PREMIERE_PIN + i” ou “i + 5” dans la boucle.
Remplacé par un tableau contenant les broches assigné aux leds.

#define PREMIERE_PIN	5 // On peut supprimer ??!

//Déclaration d'un tableau contenant les broches.
const int leds [8] = {5,6,7,8,9,10,11,12}; //Données techniquement invariable => constantes. (const)

unsigned char numero = 0;

void setup()
{
	for (int i =0; i < 8 ; i++ )
	{
 /* Incrémentation des broches systématique en fonction de i
Peut nous éviter des erreurs d'oublie de +X. Et nous donne de la souplesse.*/
		pinMode( leds [i] , OUTPUT);
	}
}

void loop()
{
	for(int i=0; i<8; i++)
	{
		// "affichage" :
		digitalWrite( leds[i] ,  ((numero >> i) & 1) ? HIGH : LOW); // Incrémentation des broches
	}

	// prochain numéro, comme c'est un type char, il va recommencer tout seul à 0 lorsque 255 sera atteint
	numero++;

	// on attend presque 1 séconde entre 2 numéros
	delay(750);
}

J’ai pas trop compris pourquoi le type char je n’aime pas trop les mélange de type (peut etre parceque j’y arrive pas; je suis encore un bricoleur “c” ). On peut faire un raz de la variable numéros une fois sortie de la boucle si cette dernier est déclaré en globale.

A plus !!

Ça y est j'ai compris ! :grin:

Le type char ! c'est vrais ça taille est de 0 à 255.

Ça fait une boucle en moins => Pas mal !!

A plus !!

manumanu: Le type char ! c'est vrais ça taille est de 0 à 255.

pourquoi un byte ne ferais pas l'affaire ?

Bonjour,

Le type char ! c’est vrais ça taille est de 0 à 255.

En C le type char est signé donc de -128 à +127.
Si on veut manipuler des octets on utilise le type byte (qui est équivalent à unsigned char) comme l’indique rjnc38.

comme le dit kamill, un byte c'est un typedef d'un unsigned char, c'est donc la même chose : un entier non signé sur 8 bits. C'est ce que j'ai mis dans mon code d'exemple qui marche très bien sans utiliser un tableau... ;)

après on peut toujours décorer et/ou améliorer, un exemple ca sert de base pour s'en inspirer selon ses propres besoins... ;)

Salut;

Je n'aime pas trop les mélanges de type !

C'est pour ça que je préfère...

digitalWrite(led[i], bitRead(num, i ) == 1 ?  HIGH : LOW );

Puis raz de la variable "numéro" déclaré en "int"

Mais cela dépend de ce que l'on souhaite. J'ai pas essayé mais si le type char nous évite de placer une boucle for supplémentaire pourquoi pas.

A plus!

je ne vois pas où est-ce-que tu trouves "un mélange des types" mais soit, si ta version tu la trouves plus claire, elle fonctionne aussi, donc no soucy... on n'est pas en train de débattre sur quelle est la meilleure solution, j'ai juste proposé une solution... En informatique, c'est comme les artistes, chacun aura une solution différente qui fonctionnera aussi bien. Ce n'est qu'une question de point de vue et appréciation personnelles...

Pour moi utiliser un char pour un nombre c'est un mélange de genre dangereux (attention aux confusions possibles) même si cela fonctionne bien. Le type byte est je crois "un ajout" Wiring.

En C/C++ Il existe ce qu'il faut avec les intx_t qui sont acceptés et utilisés dans les fonctions Wiring/arduino : int8_t : défini un entier sur 1 seul octet uint8_t : défini un entier non signé sur 1 seul octet

int16_t : défini un entier sur 2 octets uint16_t : défini un entier non signé sur 2 octets

int32_t : défini un entier sur 4 octets uint32_t : défini un entier non signé sur 4 octets

Existent dans la norme, mais je ne suis pas sur que l'avr-gcc les acceptent : int64_t : défini un entier sur 8 octets uint64_t : défini un entier non signé sur 8 octets

Comme cela à la mise au point du programme si j'utilise un "char" je sais que c'est un caractère et si j'utilise un intx_t je sais que c'est un nombre. Et si je veux utiliser un entier sur un octet ou sur 2 octets je peux le préciser.

fais une recherche dans tes include et regarde comment est défini "uint8_t"... ;) edit : petit indice, c'est dans le fichier "stdint.h"

Oui et cela veut dire ?
Je ne suis qu’un bidouilleur de la programmation mais cela à toujours fonctionné.

Dans Arduino.h il y a déjà
#include <inttype.h>
Bien sûr si tu veux adjoindre un fichier ***.c au fichier ino il faut ajouter #include <inttype.h> dans le fichier c.

si tu regardes dans inttype.h tout ce que t'as c'est la définition des formats pour les fonctions de type (s)printf() et un include de stdint.h où sont définis les types auxquels tu fais référence...

Il est utile de savoir à tout moment de quelle taille sont les représentations des valeurs que nous sommes en train de manipuler, en cela le fichier stdint.h est très utile, il permet de garantir que quelque soit la plateforme où tu compiles, un int8_t sera toujours codé sur 8 bits et ainsi de suite. Par exemple, traditionnellement le type "int" suit l'architecture du code (Arduino fait exception parce que c'est un processeur 8 bits et les int sont sur 32 bits !), si t'utilises le type int en général c'est que tu te fous de la taille de ta représentation mais que tu souhaites optimiser ton code en fonction de l'architecture où tu compiles...

Pour la clarté du code il est donc utile d'utiliser des "types" distincts, virtuellement associés à des concepts de valeur, pourquoi pas, c'est une façon de s'organiser qui peut aider à mieux s'y retrouver, c'est très bien si l'on en voit l'utilité et raison de plus pour les utiliser.

Comme dit plus haut, le code c'est comme l'art : tu prends 2 personnes et t'auras forcément 2 codes différents pour répondre au même problème. C'est comme ca. Une solution sera peut-être plus performante que l'autre, une sera plus lisible que l'autre, une plus "jolie" que l'autre, etc... ce sont des appréciations qui dépendront soit du besoin initial soit d'appréciations personnelles qui engageront chacun différemment... Il n'y a donc pas à se dire qu'une solution est meilleure qu'une autre, il y a 20'000 solutions possibles, c'est un fait...

Loin de moi l'idée d'insinuer que t'es un bidouilleur 68tjs, c'est toi qui le dis... Mais en programmation il faut aussi apprendre à être tolérant et accepter les solutions des autres qui fonctionnent, comme des solutions au même titre que les tiennes... ;)

Bonjour 68tjs,

Effectivement tu as raison, pour utiliser des variables de taille fixe et assurer la portabilité, il faudrait utiliser uint8_t ... qui sont normalisés. Personnellement je n'arrive pas trop à m'y faire et je préfère utiliser byte qui dit bien ce qu'il veut dire, même si comme tu l'as fait remarqué c'est une extension de wiring (qui existe néanmoins sur d'autres plateformes ou qui peut être défini comme unsigned char).