[resolu] Problème de lecture sur port série

Bonsoir à tous

J'utilise une carte Uno V2, avec le shield SD+ (carte SD + horloge à DS1307+EEPROM) avec laquelle je rencontre le soucis suivant. Bon, pour bien comprendre, je précise le but du projet : je dois faire un data logger sur carte SD pour enregistrer des températures dans un bâtiment. Je vais pour cela utiliser des capteurs OneWire DS1820, cette partie fonctionne correctement pour le moment.

En fait j'ai eu un soucis pour l'utilisation de l'horloge, au moment de la paramétrer pour la mettre à l'heure.

J'ai voulu pour cela utiliser le code suivant :

#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h> // written by  mattt on the Arduino forum and modified by D. Sjunnesson

void setup() {
  Serial.begin(9600); }

int valeur=0;
int commande=0;

void loop() {
  if (Serial.available()) {        
      commande = Serial.read();
      valeur = (byte) ((Serial.read()-48)*10 + (Serial.read()-48)); //-48 car la valeur ascii des chiffres =48 pour zero

      switch (commande) {
	case 'h' :      
	  RTC.set(DS1307_HR,valeur);
	  Serial.print("champ heures regle sur ");
	  Serial.print(valeur,DEC);
	  Serial.println("");
	  break;
	case 'm' :     
	  
(...) etc etc etc

ce programme étant inspiré d'un exemple d'utilisation du DS1307 qui utilisait également un système de lecture de commande sur le port série pour mettre l'horloge à l'heure.

Et bien entendu, ça n'a pas marché. Impossible de lire correctement la commande et la valeur qui la suit, en l'occurence par exemple h21 pour régler l'heure sur 21h, m30 les minutes sur 30, etc etc.

Après plusieurs heures du prise de tête à rajouter des Serial.print() un peu partout pour comprendre où ça bloquait, j'ai fini par me rendre compte que pour que ça fonctionne, je suis obligé d'écrire sur le port série entre chaque lecture, et là, la lecture est correcte et ça marche.

le code est donc devenu le suivant :

#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h> // written by  mattt on the Arduino forum and modified by D. Sjunnesson

void setup() {
  Serial.begin(9600); }

int valeur=0;
int commande=0;
char truc[10];
int i=0;

void loop() {
  if (Serial.available())      // Look for char in serial que and process if found
    {     
      commande = Serial.read();
      Serial.println(commande);
      
      for (i=0;i<2;i++) {
	truc[i]=Serial.read();
	Serial.print("truc[");
	Serial.print(i,DEC);
	Serial.print("] = ");
	Serial.println(truc[i],DEC);
      }
       
      Serial.print(" i = ");
      Serial.println(i,DEC);
      Serial.print(" truc =  ");
      Serial.println(truc);
       
      valeur = (byte) ((truc[0]-48)*10 + (truc[1]-48)); //-48 car la valeur ascii des chiffres =48 pour zero

      switch (commande) {
	case 'h' :      
	  RTC.set(DS1307_HR,valeur);
	  Serial.print("champ heures regle sur ");
	  Serial.print(valeur,DEC);
	  Serial.println("");
	  break;
	case 'm' :     
	  RTC.set(DS1307_MIN,valeur);
	  Serial.print("champ minutes regle sur ");
	  Serial.print(valeur,DEC);

(...) etc

Donc j'avoue ne pas comprendre. D'autant qu'au départ j'ai utilisé un exemple fourni par seedstudio avec leur carte à ds1703 qui utilise le code suivant :

void setDateDs1307()                
{
   hour = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
   minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   second  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   dayOfWeek = (byte) (Serial.rea(...)

Où on voit que les lectures sont parfaitement identiques à ce que j'avais fait en premier... sauf que dans leur cas, ça marche !!

Alors voila, je suis pas vraiment familier des ports série, il y a manifestement une subtilité qui m'échappe... mon bidouillage fonctionne, mais j'aimerai vraiment comprendre pourquoi en faisant la même chose en version simple ça ne marche pas...

Essaie ça :

Bonsoir

Je te remercie pour ta réponse, mais elle ne répond pas à ma question, j'ai du mal m'expliquer dans le premier message.
Toutefois la mise à l'heure via NTP est fort intéressante.

En fait, mon problème n'est pas de mettre le DS1307 à l'heure, ça je l'ai fait, ma question est de savoir pourquoi je dois écrire sur le port série avec l'arduino pour pouvoir lire correctement dessus ce qui vient du PC.

Yop yop,
Ton problème c'est que tu es obligé d'entré des données dans le port série pour avoir une simple lecture de l'heure ?
Si c'est ça c'est sans doute ce que dois faire ce programme exemple ?
Tu pourrais mettre le code exemple et le tien en entier pour voir ce qui pourrait gêné et mieux comprendre ce que tu désires ?
:wink:

A la fin de ton prog tu as une instruction else : tu rajoutes la commande pour afficher les données dedans et au moins quand aucune commande n'est reçue sur le port série il reboucle.

Dans ton cas, il attend une instruction et n'affiche plus rien.

++

Michel_B:
A la fin de ton prog tu as une instruction else : tu rajoutes la commande pour afficher les données dedans et au moins quand aucune commande n'est reçue sur le port série il reboucle.

Dans ton cas, il attend une instruction et n'affiche plus rien.

Oui mais c'est precisément le but recherché, le comportement est le bon, si je boucle sur l'affichage ça rempli le terminal pour rien, ce n'est pas le but.

là ça affiche l'heure si j'envoie un caractère, c'est ce que je veux. La question n'est pas là.

osaka:
Ton problème c'est que tu es obligé d'entré des données dans le port série pour avoir une simple lecture de l'heure ?

Non, je me suis mal expliqué. Mon problème n'a rien à voir avec l'heure ou le DS1307, ni la lecture/écriture de ce dernier.

Mon problème, c'est juste que je ne comprends pas comment lire correctement ce que j'ai envoyé sur le port série. Ou plutot pourquoi la manière dont je le fais ne fonctionne pas.

Par exemple, si dans le terminal j'envoie "h21"

avec les instructions suivantes, en considérant que les variables sont toutes des int :
if(Serial.available()) {
commande=Serial.read();
data1=Serial.read();
data2=Serial.read();
}

je devrais donc avoir commande = 104 data1=50 data2=49 (les valeurs ascii des caractères h 2 1)

or ce n'est pas ce que j'obtiens. Pour arriver à l'obtenir, il faut que entre deux appels à Serial.read() j'envoie des caractères sur le port avec Serial.print(" ")

c'est ÇA que je ne comprends pas.

C'est pas le fait d'envoyer une donnée qui fait fonctionner ta liaison. C'est parce que l'envoi de donnée créé une temporisation et que cela lui laisse le temps de recevoir le caractère suivant.
Il ne faut pas oublier de faire un if (Serial.available()) avant chacune des lecture de caractère.

ok, ça ça me semble logique vu ce qui se passe.

Mais alors pourquoi l'exemple sur lequel je me suis basé fonctionnait, lui ? Il n'y avait pas de temporisation dedans non plus...

il est tombé en marche ?? :smiley:

lol

bon tu avais parfaitement raison, avec une tempo entre chaque lecture ça marche impeccable :slight_smile:
GRAND merci pour ta clairvoyance, je commençais à m'arracher les cheveux car avec la 1.0 le comportement était encore différent !

Je vais donc corriger le code pour vérifier avec serial.available le nombre de bytes dispos avant de faire la lecture.

En tout cas la conclusion de ça, c'est qu'un programme compilé avec la 022 est plus lent qu'un programme compilé avec la 1.0, alors que ce dernier est pourtant légèrement plus lourd.