Chateau-Thierry (02)
Offline
Full Member
Karma: 0
Posts: 109
Arduino rocks
|
 |
« on: January 16, 2011, 01:25:12 pm » |
Bonsoir Ayant réalisé un petit programme de gestion d'oscillateurs à base de servomoteurs : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293371084J'effectue le changement de paramètres (vitesses, courses, ...) en fonction de l'heure. Pour ce faire, j'ai créé une horloge interne à base de l'instruction millis(). Mais un problème de taille me pose problème. La valeur millis n'évolue pas au rythme souhaité. Normalement, un décalage de 1000 correspond à 1 seconde, et dans mon cas, cela va trop vite. J'ai donc recalé le comptage par une simple règle de trois, mais je me rends compte que le décalage est aléatoire. parfois cela avance, parfois cela retarde. J'ai tout d'abord pensé que cela provenait de la taille du programme et que l'horloge s'apparentait plus à un compteur de cycle où la longueur du programme faisait varier le rythme de la variable interne millis. J'ai donc créé un tout petit programme allumant la LED avec une impulsion toutes les minutes pour vérifier ma théorie. Effectivement la valeur est légèrement différente pour clignoter toutes les minutes, mais toujours pas dans la norme (je devrais en théorie avoir 600 pour incrémenter toutes les minutes). Voici le bout de code : // Déclaration des variables et constantes horloge long compteur_top=0; // Initialisation des tops horloge long ancien_millis=0; // Mémoire de l'horloge millis int minute = 5; // Minutes de l'horloge int heure = 19; // Heures de l'horloge (avec inscription "19h" comme heure initiale) // Sortie LED const int led_int = 13; int etat_led = LOW;
void setup() {
// Adressage des sorties pinMode (led_int, OUTPUT); // Initialise la liaison série Serial.begin(19200); delay(50); }
void loop() { // Création d'une impulsion temporisée (top) pour déplacements oscillateurs sur la base de l'horloge interne millis() int top; if (millis() >= ancien_millis) { // Vérifie que le temps millis() est bien supérieur à l'ancienne valeur mémorisée // >> risque à l'init et au retour à zéro de l'horloge interne. if (millis() - ancien_millis >= 100){ top = 1; // création d'un top toutes les 100ms ancien_millis = millis(); // réinitialisation ancien_millis compteur_top = compteur_top + 1; } // Incrémente le compteur de tops else {delay(100-(millis()-ancien_millis));} } // HORLOGE if (compteur_top >= 498) {minute = minute + 1; //Incrémentation des minutes // (498 au lieu de 600 dans ce cas pour avoir une incrémentation toutes les minutes) compteur_top = 0; etat_led = HIGH; } else etat_led = LOW; if (minute >= 60) {heure = heure + 1; //Incrémentation des heures minute = 0;} if (heure >=24) {heure = 0;} // réinitialise l'horloge toutes les 24h // LIAISON SERIE POUR TESTS
if (top = 1){ Serial.print(heure); Serial.print(" "); Serial.print(minute); Serial.println(" "); Serial.println(" "); Serial.println(" "); }
// Remise à zéro impulsion "Top" top = 0; // Serial.print(" "); Serial.println(" "); Serial.println(" "); Serial.println(" ");
digitalWrite(led_int, etat_led); }
Ma carte aurait-elle un problème, ou la valeur millis est naturellement inexploitable ? Merci pour votre aide Franck
|
|
|
|
|
Logged
|
|
|
|
|
Toulouse / France
Offline
Full Member
Karma: 0
Posts: 208
Arduino rocks
|
 |
« Reply #1 on: January 18, 2011, 04:58:40 am » |
Bonjour, ça me semble un gros offset tout de même, Je viens de refaire le montage DS1307 avec le code suivant (trèèèès fortement issu du lien ci dessus) //ChronoDot test [ds1307] // Based on http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1279385586
#include <WProgram.h> #include <Wire.h> #include <DS1307.h> // written by mattt on the Arduino forum and modified by D. Sjunnesson
#define INT_PIN 3 //DS1307 sqw wire
extern volatile unsigned long timer0_millis; volatile unsigned long t, now, prev;
void setup() { //init wire & serial Wire.begin(); Serial.begin(9600); Wire.beginTransmission(104); // transmit to device #104, the ds 1307 Wire.send(0x07); //select control register Wire.send(0x10); //set sqw at specified Hz of 0=1Hz Wire.endTransmission();
//init interrupt pinMode(INT_PIN, INPUT); attachInterrupt(0, OneHzInterrupt, FALLING); //0 = digital pin 3 }
void loop() { Serial.println(t); delay(1000); }
void OneHzInterrupt(void) { now = timer0_millis; t = now - prev; prev = now; } et j'ai ce genre de résultat : 1000 1000 999 1001 1000 1000 1000 1000 1000 999 1001 999 1001 1000 1000 1000 1000 1000 999 1001 1000 1000 1000 1000 1000 999 1001 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1001 999 1000 1000 1000 1000 1000 1001 999 1000 1000 1000 1000 1000 1001 999 1001 999 1000 1000 1000 1001 999 1001 999 1000 1000 1000 1001 999 Donc c'est de l'ordre de moins de 1ms par seconde de dérive, ce n'est pas du même ordre que ce que tu constates, doit y avoir un souci dans le code, n'étant pas vraiment une star du code, je ne sais pas dire ou est l'erreur dans le tien Par contre, il existe la librairie Time pour simplifier l'usage de l'heure dans les sketches, réglable par le terminal série par exemple http://www.arduino.cc/playground/Code/TimeCeci dit, concernant de la gestion horaire, je pense que tu devrais regarder tu coté des horloges RTC (Real Time Clock) Les plus célèbres sont basées sur le DS1307 ou le Chronodot (DS1321 pour plus de précision) Elles sont autonomes (batterie lithium) donc ne craignant aucunement la coupure secteur. Leur utilisation est bien documentée, elles utilisent le bus I2c (entrées Analogiques 4 & 5) et c'est quand même bien plus simple de jouer avec le temps dans ce cas. Bon courage, Lionel
 - Distributeur officiel Arduino - Conception de shields pour les bricoleurs
|
|
|
|
|
Logged
|
 - Distributeur officiel Arduino - Conception de shields qui défrisent
|
|
|
|
Geneva
Offline
Faraday Member
Karma: 22
Posts: 2878
Yoplait... le pt'it suisse
|
 |
« Reply #2 on: January 18, 2011, 06:12:43 am » |
Ce que je ne comprend pas c'est la raison pour laquelle tu utilises millis() avec un delay si millis() n'est pas à la valeur que tu attends : else {delay(100-(millis()-ancien_millis));}
Essaye simplement de supprimer ce delay() : else {;;} // ou sans les ;;
Ton offset viens peut-être de là. Ensuite, incrémente tes top ainsi : compteur_top ++; }
|
|
|
|
« Last Edit: January 18, 2011, 06:13:32 am by jfs »
|
Logged
|
MacBook intel core 2 duo os X snow Leopard 10.6 eMac PPc G4 os X Leopard 10.5 powerbook G4 os X Leopard 10.5 imac PPC G3 os X Panther 10.3.9 Arduino Diecimila Arduino Mega Arduino Standalone Arduino 1307.04 
|
|
|
|
Chateau-Thierry (02)
Offline
Full Member
Karma: 0
Posts: 109
Arduino rocks
|
 |
« Reply #3 on: January 18, 2011, 07:46:56 am » |
Bonjour Merci à tous les deux pour votre aide !  Lionel J'avais vu cette option "librairie time", mais je n'ai pas compris comment la télécharger (si vous pouviez m'aider, je suis preneur  ) Pour l'utilisation d'une horloge externe RTC, je pensais pouvoir m'en passer au regard du besoin de précision relativement faible dont j'ai besoin. Mais là, c'est énorme ! Jean François Tout le développement que j'avais réalisé était sans le else (delay). Et le décalage était présent. Comme j'ai supposé que l'horloge se décalait à cause du temps de scrutation, je m'étais dit qu'une pause ne ferait pas de mal au processeur. Et ai donc rajouté cette instruction qui repose le proc. en attendant le temps nécessaire à l'obtention du top 100ms. Cela n'a rien changé dans le décalage, mais permet de scruter moins souvent  . Là n'est donc pas le problème Oui, pour l'incrémentation, je vais modifier par "compteur_top ++; " Si vous entrez la totalité du code donné en tête de post, je constate ce décalage. Constatez vous le même ? Franck
|
|
|
|
|
Logged
|
|
|
|
|
Geneva
Offline
Faraday Member
Karma: 22
Posts: 2878
Yoplait... le pt'it suisse
|
 |
« Reply #4 on: January 18, 2011, 12:41:42 pm » |
J'ai effectivement un décalage d'une ou deux secondes au bout de quinze minutes.
|
|
|
|
|
Logged
|
MacBook intel core 2 duo os X snow Leopard 10.6 eMac PPc G4 os X Leopard 10.5 powerbook G4 os X Leopard 10.5 imac PPC G3 os X Panther 10.3.9 Arduino Diecimila Arduino Mega Arduino Standalone Arduino 1307.04 
|
|
|
|
Toulouse / France
Offline
Full Member
Karma: 0
Posts: 208
Arduino rocks
|
 |
« Reply #5 on: January 18, 2011, 03:17:43 pm » |
J'avais vu cette option "librairie time", mais je n'ai pas compris comment la télécharger (si vous pouviez m'aider, je suis preneur )
La librairie se trouve en suivant ce lien http://www.arduino.cc/playground/uploads/Code/Time.zipEn fonction de ton OS il faut l'installer a l'endroit qui convient Lionel
|
|
|
|
|
Logged
|
 - Distributeur officiel Arduino - Conception de shields qui défrisent
|
|
|
|
Geneva
Offline
Faraday Member
Karma: 22
Posts: 2878
Yoplait... le pt'it suisse
|
 |
« Reply #6 on: January 18, 2011, 05:03:07 pm » |
J'ai une hypothèse. la précision est de 1 milliseconde, la résolution est de 4 millisecondes.
Comme on test un chiffre plus grand ou égal à l'écart de temps que l'on veut mesurer, au meilleur des cas on tombe sur le plus petit écart possible, au pire des cas on tombe sur un chiffre plus grand, donc une dérive est obligatoire.
Lors de chaque test if t tu tombes dans la fourchettes de résolution, dans le pire des cas tu as une seconde d'offset au bout de 4 minutes.
|
|
|
|
|
Logged
|
MacBook intel core 2 duo os X snow Leopard 10.6 eMac PPc G4 os X Leopard 10.5 powerbook G4 os X Leopard 10.5 imac PPC G3 os X Panther 10.3.9 Arduino Diecimila Arduino Mega Arduino Standalone Arduino 1307.04 
|
|
|
|
Geneva
Offline
Faraday Member
Karma: 22
Posts: 2878
Yoplait... le pt'it suisse
|
 |
« Reply #7 on: January 18, 2011, 06:06:01 pm » |
J'ai sué un petit moment sur ton problème.... Je t'ai fait un petit bout de code avec commentaires, essaye le. Après 30 minute de test, je n'ai pas de dérive flagrante. // Déclaration des variables et constantes horloge
unsigned long refTemps=0; // reference prise dans le flux du temps // on lance une ancre dans le flux du temps et on compte les noeuds qui défilent sur la corde unsigned long diff=0; // difference entre le temps voulu et le temps reel
int jour=18; // Jour de l'horloge int heure = 23; // Heures de l'horloge int minute = 32; // Minutes de l'horloge int seconde = 0; // Secondes de l'horloge
void setup() {
// Initialise la liaison série Serial.begin(19200);
}
void loop() {
diff=millis()-refTemps-1000; // on calcule les millisecondes qui seront perdues dans la comparaison de la boucle "if" if(millis()-refTemps>=1000){ // on compare a 1000 (1 seconde) le temps actuel moins la longueur de l'ancre jetee dans le flux du temps
refTemps=millis(); // on jette a nouveau une ancre dans le flux du temps seconde++; // on additionne 1 seconde refTemps -= diff; // on enleve les millisecondes de retard a la position de l'ancre, ainsi l'echeance de la seconde arrive plus tot if(seconde>=60){ // lorsque les secondes arrivent a 60 minute++; // on additionne 1 minute seconde=0; // et on remet les seconde a zero if(minute>=60){ // lorsque les minutes arrivent a 60 heure++; // on additionne 1 heure minute=0; // et on remet .... etc, etc if(heure>=24){ jour++; heure=0;
} } } }
// on envoie dans le moniteur serie le jour, l'heure, les minutes et les secondes.... Serial.print(jour); Serial.print(" "); Serial.print(heure); Serial.print(" "); Serial.print(minute); Serial.print(" "); Serial.println(seconde);
delay(100);
}
Tiens moi au courant 
|
|
|
|
« Last Edit: January 19, 2011, 02:35:30 am by jfs »
|
Logged
|
MacBook intel core 2 duo os X snow Leopard 10.6 eMac PPc G4 os X Leopard 10.5 powerbook G4 os X Leopard 10.5 imac PPC G3 os X Panther 10.3.9 Arduino Diecimila Arduino Mega Arduino Standalone Arduino 1307.04 
|
|
|
|
Chateau-Thierry (02)
Offline
Full Member
Karma: 0
Posts: 109
Arduino rocks
|
 |
« Reply #8 on: January 19, 2011, 07:34:01 am » |
Ouhaouuuu ! :o :o :-X
Je vois qu'il y en a qui occupent leurs soirées ;D
Merci Jean François Bien vu la cause très probable du décalage. Je testerais l'intégration de cette astuce ce WE.
Lionel, J'ai un portable dernière (presque) génération sous win7. Le soft Arduino installé est la version Française, sans remise à jour. Je ferais également l'installation ce WE. Mais je n'ai pas tout compris dans la manière de procéder. Où dois-je dézipper ? Suffit-il d'écrire les instructions sans chargement préalable ? y'aurais pas un tuto qui traine des fois ?
Franck
|
|
|
|
|
Logged
|
|
|
|
|
Toulouse / France
Offline
Full Member
Karma: 0
Posts: 208
Arduino rocks
|
 |
« Reply #9 on: January 19, 2011, 08:55:12 am » |
Bonjour, Pour installer une nouvelle librairie, il faut faire comme suggéré sur la page suivante : http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Librairies(...)Pour utiliser les librairies "hors référence" fournies par la communauté, il faut télécharger un fichier zip, le décompresser et copier le répertoire obtenu dans le répertoire /arduino-00xx/libraries/. La nouvelle librairie ainsi installée sera insérée dans un programme à l'aide de l'instruction #include.
Ou alors, il y a aussi la possibilités de place la librairie dans ton répertoire sketchbook, il faut la dézipper dans un dossier /libraries/ que tu auras crée dans ton répertoire sketchbook Ensuite, il faut quitter l'appli et la relancer pour que les nouvelles librairies soient prises en compte lors de la compilation. Souvent, les librairies intègrent des sketches d'exemple qui seront accessibles (une fois la lib installée) par le menu File/examples du GUI arduino. Et je ne savais même pas qu'il y avait une version fr de l'arduino, par curiosité tu l'as trouvée ou ? Par ailleurs, je te conseille plutôt de travailler avec la version à jour du GUI (22 à ce jour) les évolutions du GUI corrigent bien des bugs. Lionel
 - Distributeur officiel Arduino - Conception de shields qui s'empilent
|
|
|
|
« Last Edit: January 19, 2011, 10:07:39 am by snootlab »
|
Logged
|
 - Distributeur officiel Arduino - Conception de shields qui défrisent
|
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 44
Arduino rocks
|
 |
« Reply #11 on: January 19, 2011, 10:39:25 am » |
Bonjour, En ce qui concerne les libraries ajoutées, j'avais fait comme conseillé sur le site Arduino mais à la 1ere mise à jour du logiciel Arduino comme j'ai créée un nouveau répertoire pour la nouvelle version et que je n'avais pas copié le dossier "libraries", je ne pouvais plus compiler mes projets. J'ai cherché un moment avant de comprendre pourquoi ça ne marchait plus. >  Maintenant j'ai un dossier "librairies" dans le dossier sketchbook et j'y installe les librairies et plus de problème pour les mises à jour Arduino. Serge
|
|
|
|
|
Logged
|
|
|
|
|
Geneva
Offline
Faraday Member
Karma: 22
Posts: 2878
Yoplait... le pt'it suisse
|
 |
« Reply #12 on: January 19, 2011, 11:56:32 am » |
Sur dix heures d'essais, j'ai une dérive de 2 secondes. J'ai une autre solution un peu plus simple, qui devrait fonctionner sans dérive : // Déclaration des variables et constantes horloge
unsigned long refTemps; // echeance placee dans le futur
int jour=19; // Jour de l'horloge int heure = 18; // Heures de l'horloge int minute = 6; // Minutes de l'horloge int seconde = 30; // Secondes de l'horloge
void setup() {
// Initialise la liaison série Serial.begin(19200);
}
void loop() {
if (millis()>= refTemps){ // si millis est egal ou plus grand que l'echeance
refTemps+=1000; //la derniere echeance + 1 seconde seconde++; // on additionne 1 seconde
if(seconde>=60){ // lorsque les secondes arrivent a 60 minute++; // on additionne 1 minute seconde=0; // et on remet les seconde a zero if(minute>=60){ // lorsque les minutes arrivent a 60 heure++; // on additionne 1 heure minute=0; // et on remet .... etc, etc if(heure>=24){ jour++; heure=0;
} } } }
// on envoie dans le moniteur serie le jour, l'heure, les minutes et les secondes.... Serial.print(jour); Serial.print(" "); Serial.print(heure); Serial.print(" "); Serial.print(minute); Serial.print(" "); Serial.println(seconde); delay(100); }
La précision de l'affichage de la seconde doit être dans le 1/100 de seconde, mais dans la globalité on est précis, car l'erreur ne se cumule pas et on réajuste environ toutes les secondes sur une référence qui est exacte.
|
|
|
|
« Last Edit: January 19, 2011, 02:36:16 pm by jfs »
|
Logged
|
MacBook intel core 2 duo os X snow Leopard 10.6 eMac PPc G4 os X Leopard 10.5 powerbook G4 os X Leopard 10.5 imac PPC G3 os X Panther 10.3.9 Arduino Diecimila Arduino Mega Arduino Standalone Arduino 1307.04 
|
|
|
|
Geneva
Offline
Faraday Member
Karma: 22
Posts: 2878
Yoplait... le pt'it suisse
|
 |
« Reply #13 on: January 19, 2011, 04:21:27 pm » |
Après quatre heures d'essai(pour le dernier code), ça marche.... dans une moyenne. Pendant une minute on retarde et la minute suivante on avance (de l'ordre de la 1/2 seconde) et ainsi de suite, donc en moyenne c'est "précis".  Edit: Après 13 heures de test j'ai une avance de 3 secondes due à la précision du quartz et du Mcu.
|
|
|
|
« Last Edit: January 20, 2011, 01:05:29 am by jfs »
|
Logged
|
MacBook intel core 2 duo os X snow Leopard 10.6 eMac PPc G4 os X Leopard 10.5 powerbook G4 os X Leopard 10.5 imac PPC G3 os X Panther 10.3.9 Arduino Diecimila Arduino Mega Arduino Standalone Arduino 1307.04 
|
|
|
|
Chateau-Thierry (02)
Offline
Full Member
Karma: 0
Posts: 109
Arduino rocks
|
 |
« Reply #14 on: January 20, 2011, 04:17:11 am » |
Bonjour 3" sur 13 heures... Et moi qui pensais que la précision Suisse était indiscutable ;D ;D Cela devrait me suffire. Car j'ai commandé un capteur photo-résistif. Je recalerais l'horloge au moment de la détection de l'allumage des HQI (éclairage du bac). Cependant, je me demande comment cela se passera au débordement des variables "refTemps" et millis() puisqu'à aucun moment refTemps n'est réinitialisée. Edit : Si débordement de RefTemps avant millis : RefTemps < millis() = Pas de soucis Si débordement de millis avant refTemps : RefTemps > millis = reste à traiter le cas car l'incrémentation ne se fait plus.if millis() < 1000 {refTemps = 0} ; En tous cas merci à tous. Je vous tiendrais au courant de l'évolution Franck
|
|
|
|
« Last Edit: January 20, 2011, 07:54:27 am by Bubule »
|
Logged
|
|
|
|
|
|