Lecture d'un fichier 16.000 lignes (Module SD)

Bonjour,

J'ai acheté récemment un module SD, j'ai un peu galéré à le faire fonctionner complètement, mais maintenant c'est chose faite grâce à l'aide du forum et de certains membres.

J'ai un fichier qui fait 16.000 lignes, différentes les unes des autres (les lignes).

La vitesse de lecture de l'Arduino est assez lente, après un bref calcul j'en ai sorti qu'il est capable de lire environ 30 lignes à la seconde. Hors mon système devrait pouvoir se mettre à jour toutes les 2 ou 3 secondes, donc c'est impossible.

Alors j'ai pensé à partager le fichier de 16.000 lignes en 500 fichiers de 30 lignes, et le programme en fonction de ce qu'il doit aller chercher, ira directement s'adresser au bon fichier. Seulement voilà, j'ai peur que 500 fichiers sur une carte SD, l'Arduino en perde ses moyens :D

Donc je vais tester mon idée et je vous tiens au courant, en attendant, si vous avez des idées pour faire une recherche dans un gros fichier rapidemment, merci de m'aider :)

Bonsoir,

Et si tu architecturé tes fichiers comme on le ferai pour un base de donnée ?

Un dossier par "tranche" et n fichiers dans chaque dossier, le tout formant une sorte de mini base de donnée ?

500 fichiers dans un seul dossier je suis pas sur que le format FAT32 puisse le supporter (ou c'est le FAT16 ... je sais plus)

Oué le hic c'est que je crois que la librairie SD officielle ne gère pas les dossiers, à tester donc.

Sinon je fais des paquets de 60 lignes et ça fait 250 fichiers, mais du coup la lecture complète du fichier prend plus de temps, et surtout est-ce que la RAM de l'Arduino peut stocker 60 lignes de 30 octets chacunes dans un tableau...

arduimat: Oué le hic c'est que je crois que la librairie SD officielle ne gère pas les dossiers, à tester donc.

Sinon je fais des paquets de 60 lignes et ça fait 250 fichiers, mais du coup la lecture complète du fichier prend plus de temps, et surtout est-ce que la RAM de l'Arduino peut stocker 60 lignes de 30 octets chacunes dans un tableau...

La librairie officiel gère les dossiers, âpres c'est vrai que niveau rapidité tu y gagnerai largement à utiliser sdfatlib directement sans la surcouche arduino "SD".

Chacune des lignes fait 30 octets, mais qu'est ce que tu stock dedans, du texte, un valeur numérique, ... ? Car tu peut accéléré grandement ton programme en utilisant des fichiers binaire au lieu de fichier texte (codage d'un int sur deux octets par exemple, ...).

Ps: il faut aussi se rapeller que l'utilisation de sdfatlib même camoufler par la surcouche SD implique une grosse consommation de ram, il ne reste généralement plus que 500 octets de ram dispo.

Je testerai avec les dossiers, il me semblait avoir lu ça sur un blog...

Les données stockées sont des coordonnées GPS, exemple : 1.1654688, 49.1654651

Et donc il y en a environ 15.000, il faut je j'invente un tri qui me permettra de les stocker dans des dossiers/fichiers et surtout me permettre de les retrouver.

Bonjour,

Ayant déjà du faire ce genre de trick, que ce soit sur de l'Atmega ou autre, la meilleure façon que j'ai trouvé pour prendre le moins de temps possible c'est : - Charger un bloc de données de la SD dans la Ram. Un chunck de 512o généralement. - En même temps que le buffer se remplit, commencer à parser la donnée entrante à l'aide de flags consécutifs sur les caractères recherchés (pattern). - Quand le buffer est rempli, continuer à parser (note : ne pas parser dans les 'cases' du buffer qui n'ont pas été encore remplies, cela implique d'avoir un "flag de niveau" pour savoir où l'on se situe dans le remplissage du buffer) - Une fois arrivé à la fin du buffer, garder les derniers caractères en mémoire si ils correspondent au pattern, et repartir à l'étape 1, en incrémentant le compteur de bloc de la SD de 512o plus loin.

Cette manière d'opérer permet de gagner du temps, car l'opération qui prend le plus de temps sera de lire la SDcard, non de parser les données reçues. En mutualisant tout ceci, avec un buffer tournant, on optimise l'espace en mémoire, tout en gagnant du temps par rapport à des taches trop séquencées.

En espérant vous avoir aidé,

Bonne journée :)

P.S : - Si quelqu'un à une meilleure méthode en termes de temps d'exécution/espace mémoire, je suis preneur :) - A faire avec les librairies SD dites "rapides" (SDfatLib ou autres) - Cette méthode est efficace, peut importe la taille du fichier. Avec un fichier de 16000 lignes, on gagnera du temps en évitant toutes les 30lignes de fermer le flux, changer de répertoire/fichier et reouvrir un flux, par rapport à la deuxième solution évoquée.


Stéphane.

http://lwh.free.fr/pages/algo/tri/tri.htm

Ça sent la récursivité qui pointe le bout de son nez :grin: .

Trier et rechercher un pattern ne sont pas les mêmes algos. Je répondais à la recommandation suivante :

Donc je vais tester mon idée et je vous tiens au courant, en attendant, si vous avez des idées pour faire une recherche dans un gros fichier rapidemment, merci de m'aider

Merci pour cette super réponse, mais pour le moment ça dépasse mes connaissances je pense :D J'ai pas tout pigé, en gros c'est un parse partiel au fur et à mesure qu'on lit le fichier. Mais pourtant lors de mes tests, à brut, la lecture caractère par caractère est très lente (25 lignes/seconde).

Ton algorithme permettrait de trouver une valeur en moins de 2 secondes dans un fichier de 16000 lignes ??

[u]Je vais détailler un peu plus ce que je veux faire.[/u]

J'ai une fonction, qui permet de donner la distance (a vol d'oiseau) entre deux coordonnées GPS.

Mon GPS (EM406A) me donne donc un signal de ma position (X.XXXXXXX, Y.YYYYYY) toutes les 3 secondes, et à ce moment là, grâce à ma fonction et mon fichier, je veux savoir quelle est le couple de coordonnées GPS présent dans le fichier le plus proche de ma position actuelle.

En gros faut que je teste avec ma fonction chaque ligne du fichier et ma position actuelle, et je conserve toujours la plus petite (distance en km) dans une variable (si inférieure à la précédent), et à la fin je me retrouve avec le couple le plus proche logiquement.

Et cette opération devrait pouvoir s'effectuer toutes les 3 secondes.

Merci pour votre aide XD

Snootlab: Trier et rechercher un pattern ne sont pas les mêmes algos. Je répondais à la recommandation suivante :

Donc je vais tester mon idée et je vous tiens au courant, en attendant, si vous avez des idées pour faire une recherche dans un gros fichier rapidemment, merci de m'aider

Désolé pour la méprise :p, ce n'étais pas en réponse à ton post, ils ce sont juste croisé. ;) Trier et chercher ne sont pas incompatible et plutôt complémentaire, c'est ça que je voulais montré. :grin:

il faut je j'invente un tri qui me permettra de les stocker dans des dossiers/fichiers et surtout me permettre de les retrouver

J'ai lu trop vite :blush:, maintenant je vois qu'il n'y a pas de nouvelle écriture dans le fichier, l'algorithme de tri ne servirais pas à en grand chose en effet :* (mais utiles hors arduino je suppose pour la création du fichier?) En ce qui concerne la recherche je vois quelque chose comme plusieurs dossiers correspondant à une marge de "longitude" (° ' " ?) contenant lui même plusieurs dossiers correspondant à une marge de "latitude" pour déjà mieux ciblé le fichiers correspondant et évité les lectures inutile de données que l'on sais déjà incorrecte ? Les données sont introduite de quels façons dans le fichier? Par curiosité, quels sont les critères de ses coordonnées ?

osaka: Désolé pour la méprise :p, ce n'étais pas en réponse à ton post, ils ce sont juste croisé. ;) Trier et chercher ne sont pas incompatible et plutôt complémentaire, c'est ça que je voulais montré. :grin:

il faut je j'invente un tri qui me permettra de les stocker dans des dossiers/fichiers et surtout me permettre de les retrouver

J'ai lu trop vite :blush:, maintenant je vois qu'il n'y a pas de nouvelle écriture dans le fichier, l'algorithme de tri ne servirais pas à en grand chose en effet :* (mais utiles hors arduino je suppose pour la création du fichier?) En ce qui concerne la recherche je vois quelque chose comme plusieurs dossiers correspondant à une marge de "longitude" (° ' " ?) contenant lui même plusieurs dossiers correspondant à une marge de "latitude" pour déjà mieux ciblé le fichiers correspondant et évité les lectures inutile de données que l'on sais déjà incorrecte ? Les données sont introduite de quels façons dans le fichier? Par curiosité, quels sont les critères de ses coordonnées ?

Tout à fait, l'algorithme de tri je l'appliquerai hors Arduino pour établir un certain ordre des données (Je stockerai en base sous wamp par exemple et en PHP je lancerai la génération des dossiers et fichiers, il ne me restera plus qu'a les copier sur la SD).

Donc oui, par exemple plusieurs dossiers longitude, et à l'intérieur, d'autres dossiers latitudes. Pour ainsi savoir dans quel fichier je dois aller chercher la bonne donnée et ainsi, oui, éviter de parser des données qu'on sait déjà incorrectes. C'est semblable à mon idée du premier post donc.

Mon fichier contient toutes les coordonnées GPS des radars en France (Fixe, Emplacements Mobiles les plus fréquents et les radars de feux rouges), tout ça actualisé au 15 Novembre 2011.

Très bien, alors deux solutions.

Soit ton fichier est ordonné avec les L/l classées de manière croissantes/décroissantes, et dans ce cas c'est facile : méthode de dichotomie

Soit c'est inscrit de manière chaotique, alors dans ce cas, il faut tester valeur par valeur (à l'aide de flags pour déterminer les patterns approchants).

Classer les lignes par valeur sur ton PC avant peut du coup, valoir largement le coup.


Stéphane.

Snootlab:
Très bien, alors deux solutions.

Soit ton fichier est ordonné avec les L/l classées de manière croissantes/décroissantes, et dans ce cas c’est facile :
méthode de dichotomie

Soit c’est inscrit de manière chaotique, alors dans ce cas, il faut tester valeur par valeur (à l’aide de flags pour déterminer les patterns approchants).

Classer les lignes par valeur sur ton PC avant peut du coup, valoir largement le coup.


Stéphane.

Oui je vais les classer avec un traitement MySQL/PHP.

Et puis je testerai tout ce dont on vient de discuter, merci à vous, je reviens vers vous après :wink:

Bonjour à tous.

Comme je vais me lancer sur ce type de sujet, je profite de ce post pour savoir pourquoi les I/O sont si lents? A cause du lecteur SD, l'architecture Arduino, la fréquence du processeur, le processeur, les primitives...? Et est ce que cela veut dire qu'il vaut mieux travailler en EEPROM (au volume de données pret)? En espérant ne pas avoir dit trop de bêtises... Serge

Bonjour,

La vitesse d’écriture/lecture de la librairie SD (et par extension sdfatlib) dépend de la vitesse du bus SPI et de la classe/vitesse de la carte SD.

Les opération d’I/O avec le “core arduino” sont relativement lente car le cœur arduino a était crée pour être simple d’utilisation, au dépend de l’optimisation, un digitalWrite demande 6 appels de sous fonction, un nombre important de test et 400 octets de mémoire flash pour stocker la table de correspondance broche<>numéro.
Pour avoir des I/O beaucoup plus rapide il existe digitalWriteFast.h qui est une version optimisé de digitalWrite.

Utiliser de l’eeprom en lieu et place d’une carte SD est une très mauvaise idée, les mémoires EEPROM ont une durée de vie trés courte (~10000 cycles lecture/écriture) et un vitesse relativement lente (3.3ms par opération).

Bon la méthode de faire un tri avec des dossiers dans des dossiers... ça va pas le faire. Parcequ'il reste toujours des fichiers de 500 ou 600 lignes (à cause des villes ou des zones où il y a beaucoup de radars) et c'est beaucoup trop l'Arduino étant capable de lire maximum 30 lignes à la seconde environ.

J'ai donc maintenant un fichier de 14.745 lignes classées par ordre croissant des longitudes.

J'ai donc fait autant de dossiers que de longitudes différentes (les deux premiers chiffres), ça me donne 11 dossiers, et pour chaque dossier j'ai refait des dossiers qui porte le nom de chaque latitude (les deux premiers chiffres), donc 13 différentes.

Ce qui me fait un total de 143 dossiers, malheureusement certains dossiers contiennent des fichiers encore trop gros et à contrario d'autres sont vides :(

Snootlab:
Très bien, alors deux solutions.

Soit ton fichier est ordonné avec les L/l classées de manière croissantes/décroissantes, et dans ce cas c’est facile :
méthode de dichotomie

Soit c’est inscrit de manière chaotique, alors dans ce cas, il faut tester valeur par valeur (à l’aide de flags pour déterminer les patterns approchants).

Classer les lignes par valeur sur ton PC avant peut du coup, valoir largement le coup.


Stéphane.

La dichotomie ne peut s’appliquer dans mon cas, car ça implique de charger les données dans un tableau, hors l’Arduino n’a pas la mémoire nécessaire pour un tableau de 15.000 lignes.

A moins qu’il existe une méthode pour commencer la lecture de mon fichier directement à une ligne précise ?

A moins qu'il existe une méthode pour commencer la lecture de mon fichier directement à une ligne précise ?

C'est exactement de ceci que je parlais. Au fur et à mesure de tes périgrinations dans les différentes librairies pour manipuler des SD card, tu trouveras des fonctions qui te retournent le nombre d'octets d'un fichier. Certaines te retourneront le nombre d'occurences d'un caractère précis (caractère de fin de ligne, ou bien le $ qui est l'en-tête d'une trame NMEA, ...) Et lorsque tu ouvres un fichier, tu peux spécifier à partir de quel offset de caractères tu commences à lire. Par défaut, l'offset est de 0.

En espérant t'avoir donné un petit coup de pouce sur tes pistes de réflexions,

Bonne journée ! :)


Stéphane

Snootlab:

A moins qu'il existe une méthode pour commencer la lecture de mon fichier directement à une ligne précise ?

C'est exactement de ceci que je parlais. Au fur et à mesure de tes périgrinations dans les différentes librairies pour manipuler des SD card, tu trouveras des fonctions qui te retournent le nombre d'octets d'un fichier. Certaines te retourneront le nombre d'occurences d'un caractère précis (caractère de fin de ligne, ou bien le $ qui est l'en-tête d'une trame NMEA, ...) Et lorsque tu ouvres un fichier, tu peux spécifier à partir de quel offset de caractères tu commences à lire. Par défaut, l'offset est de 0.

En espérant t'avoir donné un petit coup de pouce sur tes pistes de réflexions,

Bonne journée ! :)


Stéphane

Merci, je vais me pencher sur tout ça dès que j'aurais un peu plus de temps. Pour être sur d'y arriver avant de commander le module GPS :) Je vous tiens au courant.

Hello Skywodd

Merci pour ta réponse que je viens de voir (je ne suis pas très assidu en ce moment..) Du coup d'autres questions me viennent ]:D

Dans le cas ou on a un gros fichier à constituer (pour une campagne de prises de mesures par exemple) est -il envisageable, toujours en terme de performance de passer via le port USB sur un disque dur ou dans ce cas, on passera toujours par le bus SPI (On oublie la vitesse du DD ou de la carte SD)? Je n'ai pas trouver grand chose sur ce sujet sur le net. Est ce que tu connais le "debit theorique" du bus SPI? N'y a til pas de projet sur des ecritures en paralleles? Et enfin est il plus rapide de passer par une liaison internet pour stocker/lire ses données? Si j'en ai encore une :grin: Tu as parlé dans d'autres posts de la pinguino... Est ce que l'architecture/composants de cette carte ne serait pas plus performant sur ce sujet (mon fils etudie les PIC au lycee et je lui pique en douce ses polyps...) Merci pour toutes ces reponses. Serge