Go Down

Topic: Ma loop() ralenti, voir bloque mon monitor... (Read 1 time) previous topic - next topic

pierrot10

Sep 16, 2014, 09:22 pm Last Edit: Sep 16, 2014, 09:28 pm by pierrot10 Reason: 1
Bonjour à tous

Je suis un peu étonné d'un truc...

Afin de résoudre un probleme, j'ai supprimé toutes les fonctions qui ne sont pas utile à lire les positions GPS.

Donc quand j'y suis, il va continuelle (loop()) écouter ce qu'il se passe dans mon Serial1 et m'afficher ce qu'il lit.
Ca fonction partiellement, car plus il avance plus il est lent à la réaction, mais l'affichage est ce que j'attend.

Par exemple quand je décoche la checkbox "Autoscroll", il met plusieurs secondess pour etre decoché.
Aussi quand je veux fermer le monitor, il freeze légérement pour se fermer 1-2 minutes plus tard, voir plus.
Des fois je dois forcer la fermeture d'Arduino pour reprendre mon travail.

J'ai donc relu my fonction et voici mes commentaires que je mets en majuscule.
PS Baute rate est à 9600.
Code: [Select]
#define COORDSSIZE 400
char coords[COORDSSIZE];
int x =0;
void loop()
{
   // S IL Y A QUELQUE CHOSE DANS SERIAL1, CONTINUE
    if(Serial1.available() > 0){
         // TANT QUE X EST PLUS PETIT QUE LA TAILLE DU BUUFER coords, CONTINUE
          if(x < COORDSSIZE-1) // Do not fill the buffer more the it size
          {
            // REMPLIE LE BUFFER
            coords[x] = Serial1.read();
            x++; // INCREMENTE POUR METTRE LA PROCHIANE LETTRE DANS LA POS SUIVANTE
            // check if the desired answer is in the response of the module
           
            //Serial.print(F("Res:")); Serial.println(response);
            //Serial.print(F("Expt:")); Serial.println(expected_answer1);
            //Serial.println(response);
          }
     }
     // APRES SERIAL1, AFFICHE LE RESULTAT
     Serial.println(coords);
}


En fait, je pense qu'il y a des fautes dans ce code. je suis aussi confu.
x est incrémenté a chaque passage dans loop(), mais a quel moment il est remis à 0, puisqu'il est déclaré en dehor de loop()
Ou alors, 'coords', "explose" quans il dépasse 400, car a aucun moment il est vider. Il devrait être vider quand je passe loop(). Car a chaque passe de loop c'est une nouvelle lecture des positions GPS. Donc il y a un truc qui tourne pas rond.

Aussi j'ai penseé vider le buffer coords comme ceci
Code: [Select]

[..code..]
     // APRES SERIAL1, AFFICHE LE RESULTAT
     Serial.println(coords);
coords[0]='\0';
}

En fait, je suis confus avec cette Serial1.available() qui un peu une base  :smiley-roll-sweat: :smiley-mr-green: :smiley-eek-blue: :.

Ou es-ce qu'il y a un defaut?
Milles mercis
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

B@tto

Salut,

x n'est jamais remis à zéro vu que tu l'as déclaré en global. Déclare le en début de loop() et ça sera le cas par contre, ou encore mieux juste après

Code: [Select]
if(Serial1.available() > 0){
Blog électronique : battomicro.wordpress.com
Photographie : www.interactive-celebration.fr
Fablab de Montpellier : www.labsud.org

pierrot10

#2
Sep 16, 2014, 09:49 pm Last Edit: Sep 16, 2014, 09:50 pm by pierrot10 Reason: 1
D'accord, mais je m'excuse de poser des question bête.

Mais ou est alors la deuxieme boucle?
(J'ai changer x avec g)
Code: [Select]

#define COORDSSIZE 400
char coords[COORDSSIZE];
int g =0;
void loop()
{// PREMIERE LOOP
   // CONDITION, SI SERIAL N EST PAS VIDE CONTINUE
    if(Serial1.available() > 0){
    g=0;
   
          if(g < COORDSSIZE-1) // Do not fill the buffer more the it size
          {

            coords[g] = Serial1.read();
            // INCREMENTE g
            g++;

              //Serial.println(response);
          }
     }
     // APRES SERIAL1, AFFICHE LE RESULTAT
     Serial.println(coords);
    // JE VIDE coords
    coords[0]='\0';
}

Enf ait g, restera toujours à 0 puisqu'il est remis à 0 au debut de loop() ????

Confu!!!, je suis

J'ai essayé ca fait la meme chose..
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

jean-I

il manque des bouts de code.

tu devrait utiliser while plutot que if, car ton Serial.println(coords) est executé a chaque octet recu.
x n'est jamais remis a zero, comme on execute Serial.println(coords) a chaque octet recu, tu a un retour "cohérent".

Serial.println(coords) va afficher plus de 400 octects a chaque fois qu'on recoi un octet, sauf s'il y a "\0x0"

on ne quitte jamais loop() autrement que par interruptions.

"chaque passe de loop c'est une nouvelle lecture des positions GPS"
non, a chaque loop() c'est un nouvel octet -et un seul- lu.

a 9600 bauds ~= 960 octets par secondes, 400 octets ~=1/2 sec.

ton buffer de terminal se rempli a cette vitesse? (et c'est certainement la le pb, meme si ton programe n'est pas "sain")

tu est sur quel os et quel ide?


pierrot10

OK, meci

Ceci semble bien fonctionner
#define COORDSSIZE 400
char coords[COORDSSIZE];
Code: [Select]

void loop()
{

  readgps();
  Serial.println("\n***\n");
  delay(5000);


}
int g =0;
void readgps()
{
    while(Serial1.available() > 0){
          if(g < COORDSSIZE-1) // Do not fill the buffer more the it size
          {
            coords[g] = Serial1.read();
            g++;
          }
     }
     Serial.println(coords);
     coords[0]='\0';
     g=0;   
}

Quand pensez-vous?
Comment feriez-vous mieux?
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

jean-I

presque, c'est beaucoups mieux

Code: [Select]

...
  Serial.println("\n***\n");
// pas obligé d'attendre, mais selon l'equipement qui emet il peut y avoir une "rupture du flux" (Serial1.available() = 0)
// il convient egalement de verifier que le buffer de reception ne soit pas overflow
  delay(400); // les trames sont elles obligatoirement de 400 octets? sinon reduire
...
     coords[g]='\0';
     Serial.println(coords);
     g=0;   
...


pierrot10

@jean-i
Quote
ton buffer de terminal se rempli a cette vitesse? (et c'est certainement la le pb, meme si ton programe n'est pas "sain")

tu est sur quel os et quel ide?


Salut Jean-i.
Ce passage m'interesse beaucoup. Je viens de faire une découverte qui peut etre va sortir de ce post.

J'ai remarqué que mn circuit crash toutes les 3-5 minutes. Juste à l'instant, il vient de rebooter après 10mn.
(Je suis sur OSX et Arduino 1.0.5)

Donc cette remarque m'interpelle.
Quote
ton buffer de terminal se rempli a cette vitesse? (et c'est certainement la le pb, meme si ton programe n'est pas "sain"


Pourrais-tu être plus clair? Que veux-tu dire exactement?


Mon programme tourne à 9600 baud et toutes les 15sec il recolte les GPS et les envoit au serveur.
Selon mon fichier gps.txt qui enregistre les position, il les enregistre bien toutes les 15sec.(Sauf quand ca crashe  :))

Mais, J'ai regardé ma fonction sendHTTP(), il lui faut 5 à 45sec pour terminé l'envoi. 45sec, c'est rare.
Je me suis demander si la commande AT ne retournait pas la réponse dans les 30sec, que se passe-til? Il crash? Je pense que la fonction qui récolte les positions GPS, va "attendre" qu'il finisse, mais vu que mes positions sont enregistrée toutes les 15sec, tout c'est bien passé :o).

Mais j'aimerais bien comprendre ta remarque! Elle surement un lein avec mes petits crashs

Merci beaucoup
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

jean-I

si je comprend bien ce que tu as fait, ton gps renvoi les data en flux continu.
:
available()
Description
Get the number of bytes (characters) available for reading from the serial port. This is data that's already arrived and stored in the serial receive buffer (which holds 64 bytes).
...
#if (RAMEND < 1000)
  #define SERIAL_BUFFER_SIZE 16
#else
  #define SERIAL_BUFFER_SIZE 64
#endif
...

le buffer de reception sur l'arduino est par defaut de 64 octect, ou 16 s'il manque de ram.
mais ca ne devrai pas ralentir s'il y a overfolw, on perd les derniers caracteres reçu.
sauf si tu fais une verif que ta trame est coherente dans le reste du code.

je pencherai vers une saturation du buffer de reception coté OSX.
tu devrai te faire un log de ce qui est envoyé par l'arduino. histoire de savoir ce qui va etre traité sur OSX.

pierrot10

Salut Jena-i,

Merci pour ces explication.

Deux-trois petites questions

Code: [Select]
...
#if (RAMEND < 1000)
  #define SERIAL_BUFFER_SIZE 16
#else
  #define SERIAL_BUFFER_SIZE 64
#endif
...

RAMEND c'est une variable prédéfinie?

Je ne pourrais pas utiliser sizeof()? pour vérifier la taille de available()?
par exemple:
Code: [Select]
while(Serial1.available() < 64 AND Serial.available() > 0) Mais ca semble rien 64!!
Comment puis-je vider si available exede sa capacité.

Dans le cas du GPS, je dois récupérer les valeur qui comment par
Quote
$GPGGA,xxxxx,xxxx,xxxx,xxxx,xxxxx,xxxxx,xxx

Des qu'il a recu la ligne commentcant par $GPGGS, on peut supprimer/ignorer le reste.

PS, mon programme reboot/crash quand je ne suis pas connecté avec mon PC. Je me suis promener hier, soir, dans les rues. Mon serveur recevait bien les données envoyées par le module, mais tous les 3,5 ou 10mn, il crash. Je le sais car quand il enregistre la premiere positions reçues, après son démarrage, je recois un SMS, et le vois dans l'heure de l'enregistrement...

Merci encore pour tes explocations ;)

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

fdufnews

RAMEND c'est un define qui indique la taille RAM disponible dans le processeur. Elle est définie en fonction du processeur pour lequel on compile.

sizeof fourni la taille d'une variable pas son contenu. On l'utilise pour savoir combien un type de variable occupe de place en mémoire.

Je ne comprends pas pourquoi tu t'évertues à stocker tout ce qui arrive par la liaison série alors que tu n'es intéressé que par certaines valeurs.
A 9600 bauds un caractère arrive toutes les 1ms environ donc tu as largement le temps de faire le tri.
Ignorer l'écho des commandes envoyées au GPS, attendre le début de la chaîne qui t'intéresse. Stocker les valeurs jusqu'à la fin de ligne. Tu devrais même pouvoir les extraire au vol sans les placer dans un buffer intermédiaire ce qui te laisserait de la place pour avoir un petit tampon avec les N dernières coordonnées reçues et ainsi pouvoir gérer la perte de connexion.

A ce sujet, si la liaison est perdue avec le serveur pourquoi continuer à stocker les coordonnées alors que le processeur n'a plus de mémoire?
Quand on a pas de mémoire il faut faire des choix. Soit tu ignores les nouvelles coordonnées, soit tu rejettes les anciennes pour ne garder que les coordonnées les plus à jour.

pierrot10

Ok, je vous remercie. Je prends note de vos remarques!!! Mercis
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

Go Up