Salut à tous !
Je suis sur un projet d'horloge avec tube nixie (pas très original).
Pour l'affichage j'utilise 3 registres à décalage 74HC595 branchés les un derrière les autres pour obtenir un registre à décalage de 24 bits. Sur chacun des 74HC595 je branche 2 décodeurs BCD pour afficher respectivement les heures, minutes et secondes soit 6 tubes.
Pour la base de temps, j'utilise un DS3231 (Chronodot) qui communique avec l'arduino (UNO) en I2C.
Je n'ai aucun problème pour communiquer avec le DS3231 en I2C, régler l'heure, relever l'heure, les alarmes...Pas de problème.
De même, aucun problème pour faire fonctionner les registres à décalage avec la fonction shiftOut();
Le problème, est lorsque je veux communiquer en I2C et envoyer dans les registres à décalage dans le même programme. Il semble qu'il y ai un conflit entre la librairie wire.h et la fonction shiftOut();. Le programme communique bien en I2C mais les registres ne marche pas.
J'ai également essayé avec la librairie SPI, les registres fonctionne si je n'utilise pas I2C, mais dans un programme avec I2C, les registres ne fonctionne pas non plus.
Je dois dire que je suis un peu à cour d'idées, quelqu'un aurai une solution pour utiliser I2C et des registres à décalage ?
faudrait que tu post un schéma. quelles pins utilises-tu sur l'arduino ?
Voila le code et le schéma.
Note sur le schéma : Les pin OE et MR des registres sont respectivement reliés à la masse et à Vcc sur le montage réel.
L'horloge RTC est une DS3232 sur le schémas et une DS3231 en réalité (aucune différence pour le branchement) et elle a déjà été mise à l'heure.
#include <Wire.h>
#define Horloge_RTC 104 //adresse I2C du DS3231
//Pin connecté à ST_CP
int latchPin = 8;
//Pin connecté à SH_CP
int clockPin = 12;
////Pin connecté à DS
int dataPin = 11;
int secondes;
int minutes;
int heures;
void setup()
{
Wire.begin();
Serial.begin(9600);
// reset du bit /EOSC
Wire.beginTransmission(Horloge_RTC); // adresse DS3231
Wire.send(0x0E); // selection du registre
// Réecriture du registre, bit 7 = /EOSC, activation des alarme sur SQW
Wire.send(0b00000111);
Wire.send(0b10001000);
Wire.endTransmission();
}
void loop()
{
getTime();
afficher(heures);
afficher(minutes);
afficher(secondes);
delay(500);
}
void getTime()
{
Wire.beginTransmission(Horloge_RTC); // Début de transmission avec l'horloge
Wire.send(0); // démarage au registre 0
Wire.endTransmission();
Wire.requestFrom(Horloge_RTC, 3); // requete de 3 octets (secondes, minutes, heures)
while(Wire.available())
{
secondes = Wire.receive();
minutes = Wire.receive();
heures = Wire.receive();
}
}
void afficher(int val)
{
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, val);
digitalWrite(latchPin, HIGH);
Serial.println(bcdToDec(val));
}
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
test.bmp (790 KB)
En fouillant dans le repertoire de Arduino, je suis tombé sur çà :
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)));
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}
Peut-être qu'en redefinissant tes vairiables en byte ou uint8_t çà fonctionnera mieux, à moins que ce bout de code t'aide à comprendre mieux ce qui se passe au niveau de la transmission des signaux entre LOW et HIGH.
Tiens nous au jus
ps es tu certain de ton BCD2DEC ?
je préfère cette version car elle consomme nettement moins de ligne assembleur que la div entiere et le modulo
byte bcd2dec(Byte i)
{
return (i & 0x0F) + 10 * ((i >> 4) & 0x0F);
}
J'ai peut-être trouvé...
il manque dans ton setup l'attribution des lignes digitales non ?
quelque chose dans le style :
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
Sinon ton bcd2dec est correct, j'ai vérifé mais l'autre version est plus 'élégante'
Grag38:
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
Mettre les pin en OUTPUT ne résoud pas le problème, mais bien vu ! Erreur de débutant 
Sinon moi aussi j'ai fait ma petite fonction perso pour envoyer dans les registres. C'est une version simplifié en LSBFIRST seulement de la version de Grag38.
Elle fonctionne à merveille sur mon circuit.
void transRegistre(byte value){
digitalWrite(latchPin, LOW);
for (int i=7; i >= 0; i--){
digitalWrite(dataPin, bitRead(value, i));
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, LOW);
digitalWrite(clockPin, LOW);
}
digitalWrite(latchPin, HIGH);
}
Pour info, il vaut mieux que le data soit en avance sur le clock.
Je suis un peu septique sur ton code Grag38, avec le clock qui fait un HIGH/LOW à la fin, j'ai essayé sur ma fonction d'inverser les lignes et ça ne fonctionne pas.
Si quelqu'un a une méthode plus élégante...Moi je trouve ma solution un peu "sauvage"
Je veux bien que la version soit sauvage mais c'est celle qui est implantée dans Arduino ...
Fait une recherche sur ton disque dur dans le épertoire arduino avec shiftOut et tu verra ce bout de code...
Il existe aussi des librairies pour ce genre de truc. As tu fais des recherches en ce sens ?
Sinon je ne comprends pas le sens de cette ligne :
digitalWrite(dataPin, !!(val & (1 << i)));
pourquoi est-elle précédée d'un double !!
Des idées ?