J'ai l'impression que ton premier code et ton second ne correspondent pas. Il faudrait plus d'explication sur ce que cherches à faire. J'ai l'impression que tu veux par exemple (les données sont en binaire): si led=0 et numberOfRegister=2 : 11111111 puis 11111110 si led=1 et numberOfRegister=2 : 11111111 puis 11111101 si led=13 et numberOfRegister=3 : 11111111 puis 11011111 puis 11111111
Dans tous les cas tu t'en es douté, on ne peut pas indéfiniment décaler à gauche. Le résultat doit tenir dans un int et ça a ses limites (ça semble être 0xFFFFFFFF pour ton processeur.)
Si mon exemple est juste tu veux pour le registre i=registerNumber: - 11111111 si la led n'est pas dans l'intervalle [i*8,i*8+7] - 1111x111 si la led est dans l'intervalle [i*8,i*8+7] avec la position d'un x nul qui serait: led-i*8. la valeur a écrire pour le second cas est donc:
~( 1 << (led - registerNumber*8) ) & 0xFF
Ça fait des décalages et des masques moins compliqués.
Que faut-il envoyer comme valeur pour 5 ou 9 registres ? Et aussi, quel est le type du 4ème paramètre de shiftOut() ?
Au passage, faire des décalages binaires sur des entiers signés est une très mauvaise idée, le résultat ne sera pas celui attendu. Il faut utiliser le même type que celui attendu par shiftOut().
Contrairement à ce que j'ai écrit (je l'ai laissé), les décalages ne sont pas circulaires. Si je considère que le SN74HC595 est un registtre à 8 bits, on peut simuler un décalage circulaire comme suit: unsigned int registre[nombre_registres]; unsigned int carry = 0; for(int i = 0; i < nombre_registres; i++) { registre[i] = (registre[i] << decalage) | carry; // le décalage devrait être inférieur à 8. carry = registre[i] >> 8; registre[i] &= 0xff; } Il suffit de transtyper pour envoyer les registres à la fonction.
>> D'abord, le décalage vers la gauche (ou droite) est circulaire. Si tu décales plus que le type choisi, tu auras des problèmes de calcul ... décaler de 40 bits sur un unsigned int par exemple. Pour faire un masque de N bits tant qu'on est dans les marges (<32 pour uint): mask = (1<<N) - 1; // 2^N -1 donne N bits.; Si tu veux les décaler vers le haut: mask <<= (32-N); // pour un uint Pour le masque complémentaire: mask = ~mask; Pour faire un décalage, on fait un peu comme pour les additions, on a une sorte de "carry". Ce carry est la partie haute du précédent registre carry = 0; for(int i=0; i < nombre_registres; i++) { registre[i] <<= decalage; newcarry = registre[i] & mask; registre[i] ^= newcarry; registre[i] |= carry; carry = newcarry; }
Si ton dernier carry n'est pas nul, tu auras peut-être besoin d'un registre supplémentaire.
Si le décalage global est circulaire, on ramène le dernier carry sur le premier registre. Reste à savoir dans qquel ordre sont placés les registres. J'ai supposé que le registre 0 était celui le moins significatif.
- Edité par PierrotLeFou 19 novembre 2021 à 4:59:32
Le Tout est souvent plus grand que la somme de ses parties.
Effectivement c'est exactement ce que tu décris. Vu que je tourne sur des LEDs montées en anode commune je dois envoyer un état logique à zéro pour les allumer.
Pour le moment en écrivant en dur dans ma méthode les "0x00FF", "0xFF00", etc... je suis allé jusqu'à six registres et donc "0xFF0000000000". C'est plus par manque de place que je ne suis pour le moment pas allé plus loin.
A la fin il me faudra au total 64 registres car je dois piloter 512 LEDs par paquets de 16 LEDs (donc 32 ensembles de 16 LEDs) et je souhaite utiliser un minimum de GPIO. Je ne vais surement pas les mettre tous en cascade car comme tu le dis un int ça a ses limites, mais j'aimerai voir jusqu'où je peux aller avec le micro-contrôleur que j'utilise (SAMD21 de la Carte Arduino Zero).
En plus de ça, chainer les registres génère de fortes variations d'intensité lumineuse sur les LEDs en fonction du nombre qui sont allumées. Je vais essayer de voir si je ne peux pas trouver un moyen de stabiliser ça...
Je vais tester le décalage de masque que tu proposes et je te dirai ce que ça donne.
@jo_link_noir :
Pour 5 ou 9 registres il faudrait théoriquement appeler la méthode avec 5 ou 9 au paramètre "numberOfRegister". Cependant, comme expliqué dans ma réponse à @Dalfab, je travaille sur 32 ensembles de 16 LEDs et donc mes registres seront toujours en nombres pairs.
Pour ce qui est de la méthode shiftOut(), il s'agit d'une méthode de la librairie Arduino :
Si je comprends bien ce que tu me dis, mes différents masques devraient être des "unsigned int" ?
@PierrotLeFou :
Je suis désolé mais je maitrise encore peu les manipulations de bits et j'ai beaucoup de mal à comprendre ce que tu me suggères.
Si je saisis bien, le principe de décalage circulaire est de récupérer les bits qui "perdus" lors du décalage et de les réinjecter de l'autre côté afin de ne pas avoir que des 0. C'est bien ça ? Au quel cas je ne comprends pas bien comment l'appliquer dans mon cas ?
Tu connais l'électronique? Le & correspond au AND et le | correspond au OR. Le ^ correspond au XOR et le ~ est un bête inverseur. Je ne comprend pas que tu sois limité dans le nombre de registres. Si ton arduino supporte les long long, on peut mettre 8 registres dans un tel nombre. Pour le décalage global circulaire, oui le dernier carry se retrouve dans le premier registre dont le bas est à 0.
Tu ferais registre[0] = registre[0] | carry; // carry final. Moi, je ne suis pas un expert en électronique, mais tes variations de luminosité ne sont-elles pas dues à un voltage trop bas sur ton alimentation? Ou c'est ton bloc d'alimentation qui est trop faible.
- Edité par PierrotLeFou 19 novembre 2021 à 15:43:28
Le Tout est souvent plus grand que la somme de ses parties.
Effectivement je connais les opérateurs logiques pour les opérations sur les bits mais c'est surtout que je n'ai pas encore vraiment l'habitude de les utiliser donc c'est un exercice que je maitrise encore mal.
Je ne parviens pas encore à visualiser le résultat d'une suite d'opérations complexes de ce genre.
Pour ce qui est des variations de luminosité je ne pense pas que cela provienne d'un problème d'alimentation. Mon Arduino est alimenté en 5V lors de mes essais.
Une façon de visualiser est peut-être de penser aux registres comme des rectangles ayant 8 cases. Quand tu décales, tu fais passer des bits d'une case dans l'autre et ça peut déborder d'un rectangle dans le suivant.
Le Tout est souvent plus grand que la somme de ses parties.
Du coup, en me basant sur la solution proposée par @Dalfab j'ai pu coder une classe de registre à décalage fonctionnelle mais relativement lente du fait de la quantité importante de "digitalWrite" utilisée par la méthode "shiftOut".
j'ai donc créé une nouvelle classe de registre à décalage plus bas niveau en utilisant les méthodes de manipulation de port de l'Arduino Zero.
Je vous partage mon code au cas où cela vous intéresse.
#include "LowBitRegister.h"
//**************************************************************
LowBitRegister::LowBitRegister(byte dataPin,
byte clockPin,
byte latchPin,
uint8_t registerSize)
: m_dataPin(dataPin),
m_clockPin(clockPin),
m_latchPin(latchPin),
m_registerSize(registerSize) //Number of register (if cascade)
{
REG_PORT_DIR0 |= (1 << m_dataPin) | (1 << m_clockPin) | (1 << m_latchPin); //Set dataPin, clockPin and latchPin to OUTPUT
}
//**************************************************************
void LowBitRegister::sendData(uint8_t led)
{
REG_PORT_OUT0 &= ~(1 << m_latchPin); //Set latchPin to LOW
for(int i = 1; i < m_registerSize + 1; i++){
int registerNumber = m_registerSize - i; //The number of the register we're working on in the loop
lowShiftOut(MSBFIRST, ~( 1 << (led - registerNumber*8) ) & 0xFF);
}
REG_PORT_OUT0 |= (1 << m_latchPin); //Set latchPin to HIGH
}
void LowBitRegister::lowShiftOut(uint8_t bitOrder, uint8_t val)
{
for (int i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST){
if(val & (1 << i))
REG_PORT_OUT0 |= (1 << m_dataPin);
else
REG_PORT_OUT0 &= ~(1 << m_dataPin);
}
else {
if (val & (1 << (7 - i)))
REG_PORT_OUT0 |= (1 << m_dataPin);
else
REG_PORT_OUT0 &= ~(1 << m_dataPin);
}
REG_PORT_OUT0 |= (1 << m_clockPin); //Set clockPin to HIGH
REG_PORT_OUT0 &= ~(1 << m_clockPin); //Set clockPin to LOW
}
}
- Edité par Fanch JMR 24 novembre 2021 à 10:32:00
Hexadécimal et décalage de bits
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
En recherche d'emploi.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.