Go Down

Topic: Faire de 5 booleans une variable type 00010 (Read 3633 times) previous topic - next topic

kammo

Je lis ça demain!

En attendant, ceci semble fonctionner:

Code: [Select]
  VarLL = digitalRead(PinLL) * 1;
  VarLC = digitalRead(PinLC) * 10;
  VarCC = digitalRead(PinCC) * 100;
  VarCR = digitalRead(PinCR) * 1000;
  VarRR = digitalRead(PinRR) * 10000;






  long int Traj = 100000 + VarLL + VarLC + VarCC + VarCR + VarRR; //on obtient une variable à 6 chiffres, le premier ne sert à rien^^

  Serial.println(Traj);



Ca renvoie

1   0   100   1000   10000
111101
 
0   10   100   1000   10000
111110
 
0   10   100   1000   10000
111110
 
1   0   100   1000   10000
111101
 
1   0   100   1000   10000
111101
 
1   0   0   1000   10000
111001
 
1   0   0   1000   10000
111001
 
1   10   0   1000   10000
111011
Make it, or make it burn.
carte des membres:
https://drive.google.com/open?id=1QmXJT44QyZHM3SIgDaMo7MGUbBSKAaVD&usp=sharing

RIN67630

Je lis ça demain!

En attendant, ceci semble fonctionner:

Code: [Select]
  VarLL = digitalRead(PinLL) * 1;
  VarLC = digitalRead(PinLC) * 10;
  VarCC = digitalRead(PinCC) * 100;
  VarCR = digitalRead(PinCR) * 1000;
  VarRR = digitalRead(PinRR) * 10000;
  long int Traj = 100000 + VarLL + VarLC + VarCC + VarCR + VarRR; //on obtient une variable à 6 chiffres, le premier ne sert à rien^^

  Serial.println(Traj);




Faire ensuite un switch() avec un long int...
Moi, j'aurais pas osé!

Tiens nous au courant.

lesept

Non!

On ne doit pas faire d'arithmetique avec des booleans!
Si "False" est toujours 0, "True" peut être tout sauf zero.
Et ça :
Code: [Select]
Traj= byte(digitalRead(PinLL))+ byte(digitalRead(PinLC)) <<1  +byte(digitalRead(PinCC)) <<2 +
byte(digitalRead(PinCR)) <<3 + byte(digitalRead(PinRR)) <<4 + 1 <<5;
ça se tente, non ?
Pour le même prix j'ajoute le 1 au début :)
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

kamill

#18
Apr 22, 2018, 07:47 pm Last Edit: Apr 22, 2018, 07:51 pm by kamill
Non!

On ne doit pas faire d'arithmetique avec des booleans!
Si "False" est toujours 0, "True" peut être tout sauf zero.
Suivant le compilateur et le processeur ca peut être 1 ou 255 ou 65535 ou...
Bonjour,

digitalRead() n'est pas un booléen, mais un int. La valeur retournée est soit HIGH soit LOW.

Quand lesept fait
Code: [Select]
Traj= digitalRead(PinLL)+ digitalRead(PinLC) <<1  +digitalRead(PinCC)<<2 + digitalRead(PinCR) <<3 + digitalRead(PinRR) <<4;
Il assume que HIGH vaut 1.
Ce n'est pas très portable, mais guère moins que lorsqu'on fait
Code: [Select]
if (digitalRead(PinLL)) Traj++;
ce qui assume que HIGH est différent de 0.

Pour ma part, si j'avais à le faire j'utiliserai la solution de lesept, car c'est la solution la plus élégante et il y a quand même de grandes chances que HIGH reste à 1 dans les futures révisions du framework.

RIN67630

Et ça :
Code: [Select]
Traj= byte(digitalRead(PinLL))+ byte(digitalRead(PinLC)) <<1  +byte(digitalRead(PinCC)) <<2 +
byte(digitalRead(PinCR)) <<3 + byte(digitalRead(PinRR)) <<4 + 1 <<5;
ça se tente, non ?
Pour le même prix j'ajoute le 1 au début :)
Pourquoi ajouter 1 au début? Juste pour tromper l'ennemi?

Dans le code, on met les zeros non significatifs qu'on veut.

case B00100:

Jambe

C'est tordu la façon de faire, il faut lire le port en entier, comme le suggère RIN67630.

J'essaie d'expliquer. Les broches de ton microcontroleurs sont regroupés en « port ». Un port regroupe 8 broche et l'état du port entier est stocké dans un registre du micro, soit une variable que tu peux lire mais pas modifier. Si toute les broches sont à 0, le registre du port sera égal à 0b00000000, si une sur deux sont à 1 alors ob0101010 etc...

Quand tu fais un appel à digitalRead(), tu demande à aller lire un bit bien particulier du port pour en extraire sont état.

Faire ce que tu fais, c'est en gros aller lire les bits un par un pour aller ensuite reconstituer un octet.

Regroupe tes capteurs sur le même port, lis ton port et agis en conséquence.
C'est un plus le seul moyen que tu as pour lire tes entrées exactement en même temps.
Avec un digitalRead(), le temps de les enchaîner, la première lecture est peut être déjà plus la même


RIN67630

En effet, ici, transcrire cinq variables booléennes en une unique variable entière ne s'avère utile qu'à la compréhension du programme par le développeur.
C'est bien le but: ecrire le code dans un switch(Traj)
et de définir les actions à réaliser par des case: correspondants.
Ca fait du code simple et clair.

Par contre il FAUT coder en binaire dans un octet.
Faire un switch(Traj) sur une variable longue est une heresie.

RIN67630

...
Si par exemple les pins appartiennent à plusieurs ports ou ne sont pas présentées de façon consécutives sur un même port, et si leur lecture doit être réalisée (quasiment) simultanément...
D'après la description de l' OP, c'est des capteurs de proximité. Rien à craindre si on les capture a la queue-le-leu. Pas la peine de compliquer la sauce.

RIN67630

Si le switch() correspond bien au traitement à réaliser (ce dont je ne suis pas certain, compte tenu de l'usage probable des boutons), alors il faut l'utiliser.

Mais si sa seule utilité est de faire du code simple et clair, alors on est certainement dans l'erreur. Quand il s'agit de petits micro-contrôleurs, le programme ne doit pas imposer à la machine de ré-exécuter chaque fois le travail que le développeur ne s'est pas donné la peine de faire au moment du codage.
Non. Une instruction switch() est très efficace et genère un code très compact.

RIN67630

#24
Apr 22, 2018, 10:33 pm Last Edit: Apr 22, 2018, 10:37 pm by RIN67630
Une instruction switch() qui ne justifie pas coûtera toujours plus cher en ressources que le code optimum sans switch(). Par ailleurs, on constate que avr-gcc remplace presque toujours les switch() courts en une succession de if()/else.
Dans le cas présent le code avec switch est optimum.
Même un UNO poussif fera le boulot avec 95% de idle...

Quote
Dans le cas d'un suiveur de ligne, je doute de l'utilité de traiter des valeurs comme 10101, 11011, 00101, etc. . On aurait certainement gros à gagner à ne traiter que les quelques cas de figure auxquels on s'attend vraiment (au lieu de 32), directement à partir de l'état des cinq capteurs.
C'est bien l'avantage de switch().
On ne met que les case: dont on a besoin.
Clair, net et concis.

RIN67630

Désolé, mais faire du travail inutile n'est jamais optimum.

Et l'on ne peut juger des ressources restantes que sur le système complet. Si le reste du code consomme 96%, alors les 95% non utilisés par le bout de code qu'on considère s'avèreront insuffisants.
Quel "travail inutile", quel "reste du code"?

RIN67630

Le travail inutile que j'évoquais au post #27.
Tu te mords la queue. Ce "travail inutile" n'existe que dans ta tête.
Les problèmes ca se résoud quand ils se posent, inventer des hypothèses n'avance à rien.

Reviens quand tu auras programmé quelques robots en fuzzy-logic sous freeRTOS...

RIN67630

#27
Apr 23, 2018, 08:36 am Last Edit: Apr 23, 2018, 08:36 am by RIN67630
[exemples idiots...]
On peut laisser tomber la discussion.

J-M-L

#28
Apr 23, 2018, 10:25 am Last Edit: Apr 23, 2018, 11:47 am by J-M-L
Pour revenir à la base (même si pas adapté) voici un petit exemple qui devrait être simple à lire et comprendre sur comment bâtir un octet avec 5 flags et l'imprimer

Code: [Select]
void print5bits(byte aByte)
{
  Serial.print(F("B"));
  for (int8_t aBit = 4; aBit >= 0; aBit--)
    Serial.print(bitRead(aByte, aBit) == 0 ? F("0") : F("1")); // cf https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/bitread/
  Serial.println();
}

void setup() {
  Serial.begin(115200);       // console Série à 115200 bauds
  randomSeed(analogRead(A0)); // on initialise le générateur de nombre aléatoire avec un peu de variabilité
}

void loop() {
  boolean b4, b3, b2, b1, b0;
  byte b = 0;

  b0 = (random(2) == 0); // une valeur 0 ou 1 transformée en booléen
  b1 = (random(2) == 0);
  b2 = (random(2) == 0);
  b3 = (random(2) == 0);
  b4 = (random(2) == 0);

  // on construit un octet avec des 1 pour chaque booléen qui est à vrai
  b = (b4 ? B10000 : B0) | (b3 ? B1000 : B0) | (b2 ? B100 : B0) | (b1 ? B10 : B0) | (b0 ? B1 : B0) ;
  print5bits(b);

  delay(500); // on attend un peu
}



La console Série (réglée à 115200 bauds) m'affiche alors
B11110
B00100
B11111
B01111
B10111
B10110
B01110
B01111
B11000
B11001
B10101
B01010
B10001
B00101
B11000
B11100
B10000
B00010
B11001
B00001
B01000
B10101
B00100
B01001
B01010
B00011
B10010
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

kammo

Bien...

Bon mon but c'est pas de déchaîner les gens les uns contre les autres.
J'ai l'impression que personne n'a tort mais je ne comprends pas tout quand on se retrouve avec des codes à base de B0100010 ox1201100 honnêtement j'y pige rien.

Quand je dis que ça fait joli, ça veut dire lisible et propre. Pour moi, pour l'arduino.

Je dis ça parce que je cherchais un code exemple, et le type empilait des if et des elseif avec des & partout, j'ai eu la nausée.

Pour avoir déjà utilisé un switch/case, je trouve ça d'une clarté exemplaire, et surtout JE COMPRENDS.

Je rappelle que j'ai un niveau vraiment naze, j'ai commencé ya un mois, sans rien connaître ni à l'électronique, ni à la programmation. RIEN.

Quand on me dit de mettre mes capteurs sur le même port, bah super parce que mon arduino est bourré de fils. Mais, concrètement, ça veut dire quoi? Je mets E1 sur D8? Ouais, j'en suis là...

J'ai très envie de voir ce petit robot courir sur la ligne de scotch que je viens de tracer au pif sur le sol. C'est pas comme ça qu'on fait? bah j'ai fait comme ça parce que je sais pas comment faire, et que les autres sont pas toujours de bon conseil, surtout quand on fouille ailleurs que sur notre forum, c'est ânerie sur connerie.

OUI, il y a forcément une multitude de façons de programmer ça, et c'est ce qui doit nous motiver, pas nous opposer. Je veux pas faire la morale, mais je fais pas des robots pour qu'on s'engueule, sinon je sors le parasol et on règle ça à coups de bière, compris? :D

Avec ma petite tête, j'ai trouvé une solution qui fonctionne, mais qui n'est pas optimale? Bah ouais, j'ai vaguement compris les types de variables la semaines dernière, et je fais tout à tâtons!!! Les copains, c'est mon premier robot ...

Hier je me suis dit que je vais lui claquer un nano pour lire les capteurs et un autre pour traiter le signal. Actuellement, je me sens davantage capable de faire comme ça que d'écrire un code en binaire complexe, parce que j'ignore tout de cette manière de coder, c'est aussi simple que ça.

La proposition de lesept me paraît simple (une ligne) mais je comprends pas les <<, jamais vu avant. je vais chercher.
L'histoire de pins sur le même port, pas j'ai pas compris. (pour moi chaque porc a sa propre pine, non? ok c'est grossier mais elle m'a échappé)
Du binaire pour avoir des valeurs à traiter sous la forme B00100 ?? merveilleux! Comment on fait?

Je suis tout fier d'avoir trouvé mon astuce hier, bien conscient que c'est un bricolage foireux qui va se traîner à mort. J'essaie de faire au mieux avec ce que je comprends, et je comprends pas autant que j'aimerais.
Make it, or make it burn.
carte des membres:
https://drive.google.com/open?id=1QmXJT44QyZHM3SIgDaMo7MGUbBSKAaVD&usp=sharing

Go Up