je cherche l'équivalant d'explode(PHP) pour découper un string dans Arduino.
la chaîne ressemble à ceci :
PARAM1|PARAM2|PARAM3(.....)
l'idée serais donc de découper aux '|' pour extraire les PARAM(X), j'ai fait quelques tentative du coté de strtok(), sauf que j'ai encore du mal à piger comment cette function s'argumente, et du mal avec l'initialisation des variables (Merci PHP de ne pas m'avoir appris le typage des variables ), enfin bref, du coup, mon code brailles et comme je débute, je m’emmêle les pinceaux grave !
exemple qui marche avec strtok :
char str[] = "now # is the time for all # good men to come to the # aid of their country";
char delims[] = "#";
char *result = NULL;
result = strtok( str, delims );
while( result != NULL )
{
printf( "result is \"%s\"\n", result );
result = strtok( NULL, delims );
}
et dés que je veut remplacer le string d'exemple par :
char str[] = myFile.read();
L'IDE vire à l'orange :
error: initializer fails to determine size of 'str' !
Pourtant, myFile.read() contient bien ma chaîne, si je l'envoi sur le Serial, mon string s'affiche...
Ce que fait strtok, c'est insérer des \0 aux bons endroit (pour découper la chaine) et retourner des pointeurs aux différents endroits découpés.
Une autre chose à savoir, c'est qu'il n'existe pas (ou qu'il n'est pas vraiment conseillé) de faire de l'allocation dynamique sur de petits processeurs.
Impossible donc de faire un tableau variable mais on peut en faire un de taille fixe
Toujours un petit exemple (avec plus ou moins la solution) :
donc en fait, cela signifie qu'il faut déterminer à l'avance (et de manière définitive), la longueur des chaines qui seront exploiter par le script, en revanche, dans cette longueur de chaîne, je peut jouer avec le nombre et la position des séparateurs...c'est bien ça ?
pour read(), j'avais pas capter de c'étais caractères par caractères, vu que l'exemple sur lequel je me base lit plusieurs lignes, j'étais partie sur l'idée que le while() utilisé servais à passer sur la ligne du dessous, pas au caractère suivant....I'me quiche parfois
donc, il faut (si j'ai bien suivi l'idée) :
récupérer caractère par caractère la ligne (en identifiant la fin de la ligne) issu du fichier de la carte SD
recoller tout les caractères pour reconstruire la chaîne d'origine
séparer la chaine grâce strtok
sinon, question bête, une fois la chaine reconstitué, y aurais pas un moyen de compter les caractères, pour avoir des longueurs dynamiques ?
J'ai dis qu'il était déconseillé de faire de l'allocation dynamique, je n'ai pas dit que ça n'existait pas.
Sur les petits processeurs, la quantité de RAM est extrêmement limitée donc il faut faire très attention à ce que tu utilises.
En faisant de l’allocation dynamique, impossible de savoir combien tu utilises ni si tu te retrouveras en manque de RAM en plein milieu du programme.
Par contre, en utilisant des variables globales pour tous tes buffers de grosses tailles en spécifiant les tailles, le compilateur est capable de vérifier que l'ensemble va tenir dans la RAM du proc.
Par exemple, si tu écris char buffer[65536];, il est certain que le compilateur refusera de compiler et te sortira une erreur du genre data RAM space too short.
A l'inverse, si tu fais char* buffer = malloc(65536);, il est certain que le programme va compiler mais que le malloc retournera un pointeur NULL car l'allocation a échouée. Si par derrière tu fais des accès à ce pointeur sans le tester, ça plante ... ou ça fait n'importe quoi ...
Si tu veux te simplifier la vie, tu peux utiliser la classe String qui fait de l'allocation dynamique de façon à gérer la taille dynamiquement.
Tu pourrais donc avoir :
/*
Fonction bloquante qui ne rend la main qu'après avoir lue une ligne entière sur le Serial
*/
String SerialReadLine() {
String str;
for (;;) {
if (Serial.available()) {
char c = Serial.read();
if (c == '\n') {
break;
}
str += c;
}
}
return str;
}
Par contre, si jamais tu t'amuses à envoyer des données sur le Serial non stop, sans saut de ligne, l'arduino va forcément atteindre sa limite de RAM et je ne sais pas du tout ce qu'il pourrait se passer.
Dans le milieux professionnel ou je travail, l'allocation dynamique est donc tout simplement interdite.
Tout ce fait avec des tailles constantes et vérifications des tailles maxi à l'exécution.
Par exemple, si l'on doit lire les lignes d'un fichier une par une sachant qu'en théorie, elles ne dépassent pas 100 caractère, on prend un buffer de 128 histoire d'avoir un peu de marge.
Et lors de la lecture, si jamais la taille maxi du buffer est atteinte (ce qui en théorie, n'arrive jamais), on continue de lire sans écriture dans le buffer (en clair, on ignore la fin de la ligne mais on continue de lire pour atteindre le \n).
c'est vrai que de mon coté, j'ai une grosse tendance à ne pas prendre attention à ce genre de chose (j'arrive juste dans l'électro, jusqu'à présent, j’étais plus orienté web, donc des échelles de mémoire BEAUCOUP plus larges....)
donc, effectivement, il vaut mieux que je m'impose une bride sur la taille de mes lignes !
en revanche, je suis étonné qu'on ne puisse pas charger une ligne d'un seul coup, qu'on soit obliger de faire du caractère à caractère...
bon, je vais recommencer depuis le départ, en espérant avoir bien saisie tout les principes !
Bienvenue dans le monde de l'électronique embarquée
La puissance de calculs des processeurs embarqué est très réduite donc l'ensemble des fonctions de base se résume à des choses simples.
Et encore, je dirais que tu as de la chance d'être sur arduino et toute la surcouche qu'il y a avec.
Si tu descend sur des processeur PIC low cost, tu verras qu'il y a encore moins de choses.
Par exemple, il n'y a pas de Serial.print. Si tu veux écrire une chaine, c'est caractère par caractère en prenant soin de ne pas surcharger le module UART qui se charge de la com série (soit par boucle while bloquante, soit par interruptions).
Pareil pour Serial.read, c'est à toi d'utiliser une interruption pour lire rapidement le caractère dès qu'il est disponible (car sinon, il sera écrasé par le prochain caractère reçu), le stocker dans un buffer temporaire et le traiter plus tard.
en gros, je passe de la mémoire d'élePHPant, à celle du moineau....je me console en me disant qu'en utilisant une carte SD, j'économise un peu, c'est déjà ça !
ATTENTION SPOIL!!!
si tu tiens à tout savoir, non seulement tu passe de l'elePHPant au poisson rouge maintenant, mais tu vas constater d'ici quelques mois au fait que tu passe aussi du lièvre à la tortue (qui part à l'heure seulement si tu code bien en plus - j'aime pas dire "à point" en parlant d'un animal, ça fait cuisine comme truc).
tout ça sans vouloir sauter du coq à l'âne bien sur.
FIN DU SPOIL!!!
blague à part, la carte SD c'est beau, y'a de la place, mais ça a un temps d'accès beaucoup plus long que la RAM, et surtout, ça augmente pas la taille maxi du string. et comme lorrio a pu te le faire remarquer, le string parachute (pour la surface de voilure, si tu suis l'image ) ça existe pas en électronique
ça fait quand même un paquet de concept à assimilé en même temps, je crois que j'ai eu les yeux plus gros que les ventres de toute ma famille réunis !
bon, ça me démoralise pas, ni ne me fait songer à réduire mes objectifs, en revanche, il est clair que ça va me prendre beaucoup plus de temps que prévu initialement (d'un autre coté, partir d'ou je part et concevoir ce projet avec cette quantité de contraintes lié au matériel, ça fait un p.tain de challenge )!
aujourd'hui, pas de code (enfin, pas avec les doigts, tout reste dans le buffer que j'ai entre les oreilles !), je fini les plans de la future cage de mon calopsitte...
Moi j'ai une question/remarque...
Puisque maintenant on a clarifie le fait qu'on faisait une lecture car. par car. , ca devient presque trivial de stocker les caracteres, detecter le pipe ( | ), faire une action puis continuer a lire, non ?
en fait, j'essaie de mettre en place le stockage de mes menu sur carte SD.
voila l'idée de base :
un fichier s'appelle ACCUEIL.txt, il contient la liste des boutons (et les params de ces boutons) que contient le menu Accueil, genre :
//title-logo-size-background-target
Circulaire|A|MIN|RED|SUBA
Defonceuse|B|MIN|BLUE|SUBB
à l'aide d'une boucle, j'envoi chaque ligne dans une function qui découpe à chaque pipe et retourne les éléments dans la function qui construit le menu.
enfin, ça, c'est la théorie !
dans la pratique, j'avoue, là tout de suite, je nage la pierre comme un poisson hors de l'eau....
Si c'etait moi, j'aurais fait une sorte de specifications pour mes chaines... Du genre "Le titre fait 20 caractere max", "le logo est represente par une lettre capitale", "la taille est represente par trois lettres"... etc.
Comme ca, tu peux tres simplement faire tes buffers (tu connais deja la taille) et faire assez facilement le découpage aussi. Bref, tu fais plus d'effort avant (preparation) pour en faire moins apres (codage)
c'est un peu ce que je m'éfforce de faire, sauf que pour le moment, le buffer, je maitrise pas du tout ni la notion, ni son application, j'ai du mal à clarifier tout ça dans ma tête, et imaginer la structure de mon code, donc, pour le moment, je suis + en phase d'expérimentation sur l'IDE.
j'écris un truc, l'IDE braille, j'essaie de comprendre, je modifie un truc, il braille encore, j'insiste, il braille toujours, mais pas le même charabia...bref, c'est un peu comme avec une femme quoi !
pas tout à fait comme une femme: ton programme finira par entendre raison et finira par faire ce que tu veux, sans aller jusqu'au point godwin ni déclencer une guerre nucléaire pis l'IDE quand il braille, il te dit plus ou moins ce qui va pas. c'est pas toujours le cas côté féminin.
la parenthese "blagues misogynes" étant passée, ce que tu peux faire c' est un peu une espece de fichier xml (ptetre un peu lourd à lire) ou csv (enfin un tableur dans un fichier texte), avec par bouton: le logo, le nom/titre, la position sur l'écran, des couleurs d'affichage (texte, logo, arriere plan)... ça se lit bien, et ça fait pas un trop gros tableau à édcortiquer (vive strtok)
Je répond peut être à côté de la question, mais personnellement je ne m’embêterais même pas à lire un fichier, le parser, gérer les erreurs, etc.. En C, les possibilité de méta-programmation sont extrêmement limité, mais on est dans un des rares cas ou le préprocesseur peut générer du code pour nous alors autant ne pas s’en priver.
N.B. ce que je dis est valable pour du C, je ne sais pas à quel point le langage arduino lui est différent, à prendre avec des pincettes donc.
J'avoue, tu m'a perdu ! (je démarre juste, alors la méta-prog...c'est pas pour tout de suite, si tenté que cette solution soit compatible Arduino )
remace=>
Partir sur une base CSV, j'trouve qu'on se rapproche pas mal de mon idée, ça me plait (mais pourquoi diable n'y ais-je pas pensé ? )
si tu peut m'en dire un peu plus sur la manière dont tu aurais procédé ?(pas du code tout cuit hein, je veut juste savoir comment tu aurais organiser le déroulement des choses )
simbilou: le probleme du code généré par le préprocesseur c'est qu'il vient quand même prendre de la place en RAM a final. le but d'aller stocker des choses dans des fichiers, c'est de pouvoir les effacer de la RAM et de les ouvrir que quand il y en a besoin)
babas: bah moi j'aurais fait un truc du style d'écrire un objet par ligne avec un peu tout ce qui te semble utile dans ses caractéristiques pour créer ton interface (même sur un fichier texte bateau quoi). en utilisant bien des séparateurs pratiques(\t, \n, qui sont les plus lisibles), et après, bah tu lis caractere par caractere au moment de décoder. tu fais un fichier par menu.
plus en détail je sais pas faire, parce que comme je te l'ai surement déjà dit, je n'ai pas d'arduino, je n'ai pas de shield SD. même si je vois comment faire, je l'ai jamais fait proprement.
simbilou: le probleme du code généré par le préprocesseur c'est qu'il vient quand même prendre de la place en RAM a final. le but d'aller stocker des choses dans des fichiers, c'est de pouvoir les effacer de la RAM et de les ouvrir que quand il y en a besoin)
Ah oui c’est sur, c’est moins flexible. Enfin on parle d’un microcontrôleur là, la flexibilité de l’application est rarement ce qu’on en attend. Cela dit je comprend tout à fait l’aspect pédagogique et amusant du truc.
Nan c'est ca Après l'idéal serait de connaitre a l'avance la taille maximal que devra prendre data pour pouvoir déclarer ton tableau au plus juste +1 et ce sera nickel
je pense qu'il s'agit + d'un soucie de capacité mémoire que de flexibilité
Ah oui tiens, j’avais mal compris l’argument. Alors là pour le coup je n’y crois pas. La mémoire devra un moment ou un autre tenir les données pour afficher le menu, et je doute que l’executable soit plus petit avec le code pour aller chercher les données qu’avec les données en dur.
Mais dans tous les cas continue sur ta méthode, c’est un excellent exercice et tu au moins tu sais où tu met les pieds.
ben en fait, j'essaie d'économiser au max en construisant puis affichant au fur et à mesure que je lit le .csv, donc en théorie, je tire le moins possible sur les ressources (enfin, je pense, mais les plus expérimentés verrons sûrement un moyen d'économiser encore plus ), par contre, je suis d'accord avec toi, avec les données en dur, j'aurais peut être consommer moins, mais avec une possibilité de mise à jour de mes menus plus contraignante (j'ai compris ce que tu voulais dire par flexibilité )
Un buffer (aussi appele zone tampon) c'est une zone memoire qu'on se garde pour faire une transition entre deux trucs. Par exemple, tu dois surement connaitre et utiliser de maniere transparente les buffers d'emission et de reception de la voie serie.
Tu vas envoyer a vitesse grand V des donnees a emettre, mais la voie serie ne peut qu'envoyer qu'une quantite limites d'octets par secondes. Il faut donc un endroit ou stocker ces octets a envoyer. Ensuite, ton programme peut tourner dans son coin pendant que le module de la voie serie tournera dans le sien pour prendre les donnees dans le buffer d'emission et les envoyer...
Il se passe la meme chose pour la reception. Tu vas recevoir de maniere asynchrone des donnees. Tu ne peux pas savoir quand elles vont arriver. Ton programme est peut etre parti faire des calculs super complique et s'en cogne de la voie serie pour le moment. Du coup les donnees arriveront dans cette zone temporaire et tu iras les chercher quand tu seras pret (c'est ce que retourne Serial.available ! si oui ou non des donnees sont dans le buffer)
Bien sur il faut faire gaffe a vider de temps en temps sinon les nouvelles donnees risquent d'ecraser les anciennes ou ne seront pas ajoutee et donc perdu.
dans la pratique appliqué à mon idée de code, vu que je construit au fur et à mesure de la réception, en théorie, du coté du buffer, je ne risque pas grand chose, non ?
ou faut-il que je prévois un RAZ du buffer après exploitation de chaque ligne ?
La en effet j'ai un peu fait de l'abus de langage car tu vas etre sur un truc synchrone, donc ce sera pas vraiment un buffer, plutot un "tableau de stockage temporaire" ou une "zone de swap", sorte de zone d'echange entre ta SD et ton ecran.
redeclare le pas, contente toi de pointer sur sa premiere case et ca suffira (suffira juste de bien definir le delimiteur de fin de chaine pour savoir ou s'arreter quand on lit le tableau)
Apres je suis peut etre completement a cote de la plaque, peut etre que je suis parti dans un truc alors que c'est pas ca, il faudrait que je relise le debut du sujet XD
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
oui. non. enfin je regarde et je te dis.
Retrouvez moi sur mon blog et ma chaine Youtube !
Retrouvez moi sur mon blog et ma chaine Youtube !
oui. non. enfin je regarde et je te dis.
oui. non. enfin je regarde et je te dis.
Retrouvez moi sur mon blog et ma chaine Youtube !
Retrouvez moi sur mon blog et ma chaine Youtube !
Retrouvez moi sur mon blog et ma chaine Youtube !
Retrouvez moi sur mon blog et ma chaine Youtube !