Décodage code hoaraire 162kh
Bonjour à vous... Je suis sagement à la maison lol,
J'essaie en me servant de ton programme, de le réécrire sans interruption, avec des millis() , delay et digitalRead (c'est pour apprendre).
Il me semble que cela devrait être aussi fiable qu'avec des interruptions...? on mesure des temps de plusieurs dizaines de millisecondes (on est au ralenti).
Pour l'instant je bute sur les drapeaux et les millis() qui ne se laissent pas facilement manipuler dans des "conditions IF".
Une aide sera sans doute la bienvenue , sinon, Leclerc vend des horloges pilotées par dcf77 :D.
Bonne soirée
pat42
1 pièce(s) jointe(s)
Décodage code horaire 162kh
Bonjour à vous,
C' est uniquement pour apprendre et bien comprendre que je veux un petit programme sans interruption.
Il est certain que les interrupts seront nécessaires, car il y aura à gérer, l'afficheur I2c, le décodage des bits ect...
Je suis allé faire un tour sur le lien, Effectivement, ce sont des modules pour la réception de DCF 77.
Il y a quelques temps de cela , je m'étais fabriqué un récepteur sur la fréquence de 77.5 khz et la logique qui va bien pour l'heure (avec une tartine de CI).
La réception n'étant pas terrible, je me retourne sur Allouis qui m'arrive clair et net, et la carte arduino nano qui me donnera souplesse et simplicité pour des modifs
éventuelles.
Super le code et les explications, je vais me les garder pour se soir lol.
Je vous mets en pièce jointe un souvenir..
Une carte de développement (intégrant le célèbre 68 HC11) utilisée dans le bureau d'étude dans lequel je bossais en 1991. Cette carte se connecte sur un pc ou un Minitel .
Cela permettait aux collègues programmeurs d'emmener du boulot chez eux lol ...A l'époque les PC n'étaient pas courant chez les particuliers, le minitel SI !
Je vais prendre un peu de temps pour la remettre en fonctionnement, pour le fun.
Merci et bonne soirée à vous.
PAT42
Décodage code hoaraire 162kh
Bonsoir, j'ai testé le code sans interrupt. et cela fonctionne sans avoir eu besoin de débugger...
Avec ce que j' ai appris , je vais essayer de greffer le top des secondes sur le programme.
Bonne soirée à vous et à JP.
Pat 42
Décodage code horaire 162kh
Bonjour a vous,
j'ai bossé sur mon horloge pilotée , mais comme n'ayant pas encore beaucoup d'expérience, je bute sur deux pbs...
J'ai intégré dans le programme qui gère la synchro un timer (timer 2) qui est synchronisé par le top synchro et me génère une interruption toutes les secondes.
Je me suis aperçu que la seconde est trop longue et qu' à la fin d'une minute , je ne suis plus synchro de 5ms. j'ai diminué le compteur "nbrInterrup" à 248, mais là, c'est l"inverse et il me manque du temps. Puis je rajouter du temps précisément avec "delay" sans que cela crée un soucis dans le fonctionnement des interruptions ou y a t 'il une autre solution ?
Et ma question principale est la suivante,
je n'arrive pas à intégrer une fonction tempo de 50ms avec millis(); dans une quelconque routine pour avoir un niveau haut de 50 ms à chaque seconde.
Comment puis je m'y prendre en sachant que je m'en sors avec delay ( mais que je veux éviter d'utiliser car j'aurais besoin après chaque interruption d' un niveau haut de 50ms indiquant par une led les secondes et "au même instant" le démarrage d'une tempo de 200ms pour lire les bits de données suivant le top.) ?
je vous mets les deux programmes.
Je vous remercie.
Pat
Programme avec delay.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| #define interruptPin 2
int16_t nbrInterrupt;
volatile boolean compteur = 0; //volatile boolean mesureEnCours = false;
volatile boolean mesureNouvelle = false;
volatile unsigned long tempoDepart = millis();
volatile unsigned long topSyncMilliSec = millis();
int ledSeconde = 12;
int ledMinute = 13;
const unsigned int topSyncMinimum = 1000;
void setup()
{
Serial.begin(115200);
pinMode (ledSeconde, OUTPUT);
digitalWrite(ledSeconde, LOW);
pinMode (ledMinute, OUTPUT);
digitalWrite(ledMinute, LOW);
// Initialise le Timer 2 pour déclencher les interruptions à intervalle régulier,
TCCR2A = 0; //on peut aussi écrire bitClear (TCCR2A, WGM21); // WGM21 = 0 -----//bitClear (TCCR2A, WGM20); // WGM20 = 0
TCCR2B = 0b00000110; // clk/256 est incrémenté toutes les 16uS
TIMSK2 = 0b00000001; // TOIE2 Autorise l'interruption quand le compteur déborde
pinMode(interruptPin, INPUT_PULLUP);
pinMode(ledMinute, OUTPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), impulsionInterruption, CHANGE);
}
void loop()
{
if (mesureNouvelle == true)
{
topSyncAction();
mesureNouvelle = false;
}
if (compteur == 1)
{
routineSeconde();
compteur = 0;
}
}
void impulsionInterruption()
{
if (digitalRead(interruptPin) == LOW)// && !mesureEnCours)
{
tempoDepart = millis();
//mesureEnCours = true;
}
if (digitalRead(interruptPin) == HIGH)// && mesureEnCours)
{
topSyncMilliSec = millis() - tempoDepart;
// mesureEnCours = false;
mesureNouvelle = true;
}
}
void topSyncAction()
{
if (topSyncMilliSec >= topSyncMinimum)
{
nbrInterrupt = 0;
digitalWrite (ledMinute,HIGH);
delay(50);
digitalWrite (ledMinute, LOW);
//digitalWrite (ledSeconde,HIGH);
//routineSeconde();
//digitalWrite (ledSeconde,HIGH);
}
else
{
digitalWrite(ledMinute, LOW);
}
}
ISR(TIMER2_OVF_vect)
{
TCNT2 = 6; //on met TCNT2 a 7 pour avoir un comptage de 249 incrementations 256 -7= 249
if (nbrInterrupt++ >= 249) //interruption toutes les secondes
{
nbrInterrupt = 0; //on remet nbrIterrupt à 0
compteur = 1;
}
}
void routineSeconde()
{
digitalWrite ( ledSeconde, HIGH);
delay(50);
digitalWrite (ledSeconde, LOW);
} |
programme non fonctionnel avec millis();
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| #define interruptPin 2
int16_t nbrInterrupt;
volatile boolean compteur = 0;
volatile boolean mesureEnCours = false;
volatile boolean mesureNouvelle = false;
volatile unsigned long tempoDepart = millis();
volatile unsigned long topSyncMilliSec = millis();
volatile unsigned long departSeconde = millis();
int ledSeconde = 12;
int ledMinute = 13;
const unsigned int topSyncMinimum = 1000;
void setup()
{
Serial.begin(115200);
pinMode (ledSeconde, OUTPUT);
digitalWrite(ledSeconde, LOW);
pinMode (ledMinute, OUTPUT);
digitalWrite(ledMinute, LOW);
// Initialise le Timer 2 pour déclencher les interruptions à intervalle régulier,
TCCR2A = 0; //on peut aussi écrire bitClear (TCCR2A, WGM21); // WGM21 = 0 -----//bitClear (TCCR2A, WGM20); // WGM20 = 0
TCCR2B = 0b00000110; // clk/256 est incrémenté toutes les 16uS
TIMSK2 = 0b00000001; // TOIE2 Autorise l'interruption quand le compteur déborde
pinMode(interruptPin, INPUT_PULLUP);
pinMode(ledMinute, OUTPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), impulsionInterruption, CHANGE);
}
void loop()
{
if (mesureNouvelle == true)
{
topSyncAction();
mesureNouvelle = false;
}
if (digitalRead (ledSeconde) == HIGH)
{
departSeconde = millis();
routineSeconde();
}
}
void impulsionInterruption()
{
if (digitalRead(interruptPin) == LOW && !mesureEnCours)
{
tempoDepart = millis();
mesureEnCours = true;
}
if (digitalRead(interruptPin) == HIGH && mesureEnCours)
{
topSyncMilliSec = millis() - tempoDepart;
mesureEnCours = false;
mesureNouvelle = true;
}
}
void topSyncAction()
{
if (topSyncMilliSec >= topSyncMinimum)
{
nbrInterrupt = 0;
digitalWrite (ledMinute, HIGH);
delay(50);
digitalWrite (ledMinute, LOW);
//digitalWrite (ledSeconde,HIGH);
//routineSeconde();
//digitalWrite (ledSeconde,HIGH);
}
else
{
digitalWrite(ledMinute, LOW);
}
}
ISR(TIMER2_OVF_vect)
{
TCNT2 = 6; //on met TCNT2 a 7 pour avoir un comptage de 249 incrementations 256 -7= 249
if (nbrInterrupt++ >= 249) //interruption toutes les secondes
{
nbrInterrupt = 0; //on remet nbrIterrupt à 0
compteur = 1;
digitalWrite(ledSeconde , HIGH);
}
}
void routineSeconde()
{
if (millis() >= departSeconde == 50)
{
digitalWrite (ledSeconde, LOW);
}
} |
Décodage code horaire 162kh
Bonjour, Jay M
Je vais modifier "nbrInterrupt"
Je n'aurais pas de pb de dérive étant donné que je réinitialise le compteur une fois par minute avec la synchro. donc pas de soucis . Le pb est que la seconde ne fait pas une seconde et qu'a la fin de la minute, les micros secondes sont devenues des ms.
Mon souci avec millis(), est que cela ne fonctionne pas dans la fonction interruption et même dans une routine appelée par la fonction interruption.
Il faut que j'utilise la loop et là je bug.
j'ai pensé à ne pas utiliser le timer, car oui! cela ne va pas vite...
Merci pour les conseils
Cordialement
Pat
1 pièce(s) jointe(s)
Décodage code horaire 162kh
Petite avancée sur mon projet, " mon horloge à moi" mais maintenant je suis bloqué.
J'ai greffé sur le programme de Jp, une routine qui me permet d'avoir un top de 125ms tout les débuts de seconde et qui sont visualisés... par une led.
Le programme se synchronise impeccablement avec l'interruption générée par le top syncro. du début de la première seconde ( émetteur Allouis sur 162 khz), et pour plus de précision, j'ai utilisé microseconds(); ce qui m'a permis d'ajuster parfaitement mes secondes (qui font 1 seconde).
Une deuxième routine me permet de ne lire que "l'intérieur" des secondes intéressantes, c'est à dire de la seconde 20 à la seconde 58.
Ceci n'était pas obligatoire, c'est pour mon... apprentissage.
Une troisième me permet de mettre les bits en forme pour une lecture et une mémorisation.
Eh là, je suis bloqué...
Comme vous pouvez le voir sur la photo, il y a, encadré par des créneaux de 125ms, des données sur deux bits et sur un bit.
En réalité seul le bit de droite est une donnée , celui de gauche est le top de la seconde en cours, ce qui veut dire qu' un bit = 1 pas de bit = 0.
1) Pourriez vous me donner un coup de main pour ne faire apparaître ou ne lire que le bit de droite ( Etant donné que se sont les données reçues qui génèrent les interruptions qui elles même génèrent les bits de données , j'ai du mal à trouver la solution).
2) Comment associer le numéro de la seconde avec la donnée qu'elle contient. Dans le programme , je lis les secondes de 20 à 58 , mais je ne sais pas trop
écrire par ex: " les secondes 21....27 contiennent chacune un bit à 1 ou à 0, et je vais les mémoriser dans une mémoire nommée "
Il me faudra bien sur plusieurs emplacements mémoires , heure, mois, année etc... que je lirai à la 59° seconde .
N'ayant pas encore les connaissances nécessaires et la maîtrise des subtilités "arduiniennes" pour écrire un joli prg, j'écris le mien en avançant chronologiquement et ainsi, éviter de me perdre...
Merci de m'éclairer.
Pat42
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#define interruptPin 2 // Pin de l'interrupt
volatile boolean mesureEnCours = false; // Volatile pour les variables traitées en interrupt
volatile boolean mesureNouvelle = false;
volatile unsigned long tempoDepart = millis();
volatile unsigned long topSyncMilliSec = millis();
volatile unsigned long departMesure = millis();
volatile unsigned long departbit_Importante = millis();
const unsigned int topSyncMinimum = 800;
#define led_bit 12
#define ledSeconde 13
int compteurSeconde = 0;
int infoMinute = 0;
int infoheure = 0;
int infoJourDuMois = 0;
int infoJourDeLaSemaine = 0;
int infoAnnee = 0;
void setup()
{
Serial.begin (115200);
pinMode(interruptPin, INPUT_PULLUP);
pinMode(ledSeconde, OUTPUT);
digitalWrite(ledSeconde, LOW);
pinMode(led_bit, OUTPUT);
digitalWrite(led_bit, LOW);
attachInterrupt(digitalPinToInterrupt(interruptPin), impulsion_Interruption, CHANGE); //interruption pour rechercher le top syncrho du debut de la pemière seconde
}
void loop()
{
if (mesureNouvelle == true)
{
mesureNouvelle = false;
topSyncAction();
}
calibrage_Seconde();
lecture_Seconde_Importante();
lecture_Bit_Importante();
}
void impulsion_Interruption()
{
if (digitalRead(interruptPin) == LOW && !mesureEnCours)
{
tempoDepart = millis();
mesureEnCours = true;
}
if (digitalRead(interruptPin) == HIGH && mesureEnCours)
{
topSyncMilliSec = millis() - tempoDepart;
mesureEnCours = false;
mesureNouvelle = true;
}
}
void topSyncAction()
{
if (topSyncMilliSec >= topSyncMinimum)
{
departMesure = micros();
digitalWrite (ledSeconde, HIGH);
compteurSeconde = 0;
}
}
void calibrage_Seconde()
{
if (micros() - departMesure >= 140000 )
{
digitalWrite(ledSeconde, LOW);
if (micros() - departMesure >= 999550)
{
digitalWrite(ledSeconde, HIGH);
departMesure = micros();
departbit_Importante = millis();
compteurSeconde++;
}
}
}
void lecture_Seconde_Importante()
{
//Serial.println (compteur);
if ( digitalRead (ledSeconde) == HIGH && digitalRead (interruptPin) == HIGH &&(compteurSeconde >= 20 && compteurSeconde <= 58))
{
digitalWrite (led_bit , HIGH);
departbit_Importante = millis();
//Serial.println (compteurSeconde);
}
}
void lecture_Bit_Importante()
{
if( millis()- departbit_Importante >= 25)
{
digitalWrite (led_bit, LOW);
}
} |
Décodage code horaire 162kh
Bonsoir Jp,
Je crée mon temps de 125 ms dans la routine "calibrage_Seconde". A chaque début de seconde, il faut lire les données et la donnée à lire se termine à 125ms du début de chaque seconde. J'ai donc calibré mon créneau seconde à cette valeur, pour encadrer le top seconde et le bit des données, ce qui me permet en passant de faire clignoter ma led .
Concernant ta réponse à ma première question, du coup il serait peut être plus facile de lire dans ce créneau, et le top seconde qui est présent à chaque seconde et le bit des données. Ce qui ferait 2 bits à 1 = 1 et 1 bit ( le top seconde ) à 1 = 0. On éviterait ainsi de bidouiller :lol:
j'ai essayé en vain de lire ces bits, mais cela ne marche pas ou ce qui est le plus probable , je ne sais pas faire...
je vais me pencher sur le tableau array que je ne connais pas...
Merci et bonne soirée
Pat42
2 pièce(s) jointe(s)
Décodage code horaire 162kh
Bonjour Jp,
C'est cela, toutes les données déclenchent une interruption sur leur front montant ou descendant.
Mais il n'y a que celle du front montant de la première seconde qui synchronise la routine " calibrage_Seconde" par l'intermédiaire de la machine à état et de la routine "topSyncAction" que tu m'avais écrite. Ensuite, la routine tourne seule en attendant le nouveau top synchro qui la recadrera s'il y a besoin (une sorte de PLL:lol:)
Puis il faut lire les données qui arrivent à chaque début de seconde ( durée de 140ms) de la seconde 20 à la seconde 58)
Je dois sans doute me répéter dans ce fil, mais pas toujours facile d'expliquer ou de comprendre par clavier interposé.
DCF 77 est modulé en amplitude, France inter en modulation de phase, mais leur codage horaire est quasi identique. Je pourrais avec quelques composants supplémentaires avoir des données de sortie identiques . A savoir, une amplitude moindre sur 100 ms pour un bit à 0 et 200 ms pour un bit à 1, et du coup utiliser
des bibliothèques DCF77 toutes faites dont je pourrais me servir...
Mais il me faut" me casser la tête" :arf: et avec de l'aide, écrire le prg qui va bien. C'est le meilleur moyen , il me semble pour apprendre et comprendre...Et puis c'est une bonne gymnastique intellectuelle quand on prend de l'âge ...
Merci pour l'exemple et les explications, je vais inclure un tableau dans le prg, et puis je crierais Help si je ne m'en sors pas.
Petite photo de l'émetteur d'Allouis et de la carte de réception, dire que les Chinois mettent ça sur une puce... (l'antenne cadre n'est pas sur la photo)
Bon weekend
Pat42
1 pièce(s) jointe(s)
Décodage code horaire 162kh
Bonjour,
J'ai bien avancé sur mon projet "mon horloge à moi" et j'ai pu résoudre deux problèmes (avec votre aide).
le premier était, comment faire la différence entre deux tops dans un même créneau de 140ms.
L'un est le top seconde et l'autre le bit de donnée... et ne lire que le bit de donnée.
Le deuxième, comment associer le bit de donnée à la seconde concernée et intégrer cette association
dans un tableau array (merci à Jp).
j'ai pu ainsi mettre en mémoire dans un tableau au fur et à mesures des secondes les bits de données. Le tableau est lu
à la 59° seconde et s'affichent sur mon pc par la liaison série (voir photo).
j'ai aussi mis en oeuvre un afficheur ou j'ai pu après quelques incompréhensions, faire défiler les secondes.
Il me reste à lire les données par paquet de 7 bits, les convertir en décimal et les envoyer
sur l'afficheur au prochain top synchro ( début de la première seconde).
Une petite explication pour la bonne compréhension de ce que je dois encore mettre en oeuvre.
Par exemple, sur les secondes 20 à 27 qui concernent la minute qui sera affichée au prochain top.
exp: pour 27 minutes
le bit de la seconde 21 à 1 = 1 -- 1
le bit de la seconde 22 à 1 = 2 -- 1
le bit de la seconde 23 à 1 = 4 -- 1
le bit de la seconde 24 à 1 = 8 -- 0 écriture pour 27 minutes
le bit de la seconde 25 à 1 = 10 -- 0
le bit de la seconde 26 à 1 = 20 -- 1
le bit de la seconde 27 à 1 = 40 -- 0
le bit des secondes 21, 22 ,23 sont à 1 ainsi que le bit de la seconde 26 qui vaux 20 .
il y a comme cela, le paquet des minutes, heures, jour, année...
Comment dois-je mis prendre pour lire un un paquet de 7 bits dans un tableau (contenant 59 cases), les additionner
et les convertir en décimales, en sachant que les secondes 25 à 27 dans cette exemple ne sont pas en binaire, mais multiples de 10 ?
Merci pour votre aide
Pat
Le petit bout de pgr qui récupère les données et les affiches...
------------------------------------------------------------------------------
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| void lecture_Tableau_Info_Donnees()
{
if(compteurSeconde == 59 && top2 == true)
{
for( byte s = 0; s <= nombreDeSeconde ; s++ )
{
Serial.print ("Seconde"); Serial.print(s);Serial.print(" "); Serial.print ("info_donnée--->"); Serial.println(infoDonnees[s]); //pour test
}
top2 = false;
}
}
//---------------------------------------------------------------------------------
void affichage_I2c()
{
if( top3 == true)
{
lcd.backlight();
// Envoi du message
lcd.setCursor(0, 0);
lcd.print("TEST");
lcd.setCursor(10,1);
lcd.print( compteurSeconde);
lcd.setCursor(13,1);
lcd.print("sec");
top3 = false;
}
} |
Décodage code horaire 162kh
Bonjour Jp,
Réponse ultra rapide! Je vais étudier le code attentivement, puis écrire le bout de code qui va bien :pc:
Comme d'habitude, si j'ai un souci j'appelle à l'aide...
Cordialement.
Pat42
Décodage code horaire 162kh
Bonsoir Jp,
je suis devant mon pc à me casser la tête pour comprendre le code que tu m'as écrit.
je bute pour commencer, sur ce morceau de code...
Code:
1 2
| int min= extraireMinute();
Serial.println(min); |
j'ai recherché et je ne trouve que l' instruction" min()" qui détermine le plus petit de deux nombres.
Pourrais je avoir quelques explications.
Merci
Pat