Création de librairie & fonctions: problème pour trouver delay() [résolu]

Salut SesechXP et merci pour ta réponse, mais ça ne fonctionne pas!

J'ai aussi essayé d'inclure delay.h et delay_basic.h, sans plus de succès...

Une autre idée?

EDIT: Ok, j'ai rien dit, cela fonctionne très bien!

Je n'avais pas mis le #include dans mon .h smiley-kiss

Merci pour ton aide du coup smiley

Par contre, mon programme n'a pas l'air de sortir de la fonction.

En gros, j'utilise un TLC5940 pour multiplier les sorties PWM.
Pour commencer très simple, j'active toutes les sorties du TLC5940 une par une (la led au bout de chaque sortie s'allume), puis j'éteins chaque led les unes après les autres dans le même ordre.

Sans utiliser de fonction, j'arrive très bien à le faire. Mais une fois mes fonctions créées avec 'void' dans mon .h, mes leds s'allument les unes après les autres, mais ne s'éteignent pas.

J'utilise un flag 'i', pour savoir si mon animation a été écrite ou effacée (ça fonctionnait très bien sans utiliser de fonctions). Quand i = 0, l'animation est lue; quand i = 1, l'animation est effacée.

Code Arduino:

#include <animations.h>
#include <Tlc5940.h>

const int zero = 0;
const int plein = 4095;
const int tempo = 500;

int i = 0;
int sortie = 0;
int animation = 0;

void setup()
{
  Tlc.init();
}

void loop()
{
  if (i == 0)
  {
    lireAniSimple(animation,sortie,plein,tempo,i);
  }
  
  if (i == 1)
  {
    effaceAniSimple(animation,sortie,zero,tempo,i);
  }
}

Code animation.h:

#include <Tlc5940.h>
#include <WProgram.h>

unsigned int ani_simple[][15] = {
	{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
	{14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
	{4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 14, 13, 12, 11, 10},
	{10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}
};

void lireAniSimple(int animation, int sortie, int plein, int tempo, int i)
{
	for (sortie = 0; sortie < 15; sortie++)
	{
		Tlc.set(ani_simple[animation][sortie],plein);
		Tlc.update();
		delay(tempo);
	}
	i = 1;
	sortie = 0;
}

void effaceAniSimple(int animation, int sortie, int zero, int tempo, int i)
{
	for (sortie = 0; sortie < 15; sortie++)
	{
		Tlc.set(ani_simple[animation][sortie],zero);
		Tlc.update();
		delay(tempo);
	}
	i = 0;
	sortie = 0;
}

Désolé pour le code non commenté, c'est vraiment à titre d'essai.
Si vous galérez à le comprendre, je le commenterai.

Merci d'avance pour toute aide.

essaie plutôt ?

#include "WProgram.h"

Salut, et merci pour ta réponse.

Je ne pourrais pas tester ce soir, seulement demain.

Mais, comme WProgram.h ne me sert que pour delay() dans animation.h, et que delay() fonctionne correctement jusqu'à ce que toutes les leds soient allumées, je ne suis pas sûr que ça vienne de là.
L'expérimention, demain, nous le dira :slight_smile:

En attendant, je suis toujours ouvert à toute suggestion.

Bonjour à tous,

J'ai testé de mettre des guillemets sur tous les #include du sketch et dans mon .h: cela n'a rien changé.

Du coup, j'ai décidé de changer les fonctions: avant elles ne renvoyaient rien, maintenant elles renvoient la valeur de i avec return. Et ça fonctionne!

Code du sketch:

#include "animations.h"
#include "Tlc5940.h"

const int zero = 0;
const int plein = 4095;
const int tempo = 500;

int sortie = 0;
int i = 0;
int animation = 0;

void setup()
{
  Tlc.init();
}

void loop()
{
  if (i == 0)
  {
    i = lireAniSimple(animation, sortie, plein, tempo, i);
  }
  
  if (i == 1)
  {
    i = effaceAniSimple(animation, sortie, zero, tempo, i);
  }
  
}

Code animations.h:

#include "Tlc5940.h"
#include "WProgram.h"

unsigned int ani_simple[][15] = {
	{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
	{14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
	{4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 14, 13, 12, 11, 10},
	{10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}
};

int lireAniSimple(int animation, int sortie, int plein, int tempo, int i)
//void lireAniSimple(int animation, int sortie, int plein, int tempo, int i)
{
	for (sortie = 0; sortie < 15; sortie++)
	{
		Tlc.set(ani_simple[animation][sortie],plein);
		Tlc.update();
		delay(tempo);
	}
	i = 1;
	sortie = 0;
	return i;
}

int effaceAniSimple(int animation, int sortie, int zero, int tempo, int i)
//void effaceAniSimple(int animation, int sortie, int zero, int tempo, int i)
{
	for (sortie = 0; sortie < 15; sortie++)
	{
		Tlc.set(ani_simple[animation][sortie],zero);
		Tlc.update();
		delay(tempo);
	}
	i = 0;
	sortie = 0;
	return i;
}

Par contre, mon UNO réinitialise aléatoirement en lisant ce programme. L'intensité de la led de mise sous tension varie légèrement quand ça se produit. J'alimente, pour mes tests, la platine avec l'USB.
Est-ce une cause?

Je testerai demain avec un bloc secteur.

PS: encore désolé pour le code non commenté, flemme quand tu nous tiens :*

Bonjour,

Pour les #include, ce qu'il faut savoir, c'est que lorsque l'on fait un #include "foo.bar", il va chercher dans l'annuaire du fichier source, puis dans les chemins normalisés, atteignables par ton compilateur (Winavr\avr\include ... et d'autres).
Lorsque tu fais par contre un #include <foo.bar>, il ne va chercher que dans les chemins normalisés, et pas dans le répertoire de ton fichier source.
Donc, dans le cas du Wprogram.h, cela ne change rien, étant donné qu'il est dans les répertoires normalisés.

Par contre, ce qui peut poser problème, c'est d'avoir trois variables différentes appellées "i", "animation" ou "sortie", une dans ton main, et une dans la définition de lireAni et effaceAni. C'est quelque chose à ne jamais faire. En effet, dans certains cas, cela passera, dans d'autres (le plus souvent), cela sera source de conflits.

Ensuite, je ne comprends pas l'intérêt de passer "animation" en paramètre, car il semble ne pas changer et égaler toujours 0.

En espérant t'avoir aidé,

Bonne journée.


Stéphane

Bonjour Snootlab, et merci pour ta réponse.

Je comprend maintenant la différence entre "..." et <...> pour les include, merci.

Pour la double définition des variables, j'en conclue que cela peut-être une cause de reset intempestif de la platine?
Je remédirai à cela ce soir :slight_smile:

Quant à 'animation' passée en paramètre, effectivement la variable ne change pas - pour l'instant, car à terme elle changera automatiquement ou manuellement, selon un mode de fonctionnement défini par l'utilisateur (moi :* ).

Voilà tout, merci encore.

Bonjour,

Pour le reset intempestif, je n'ai pas assez d'informations pour savoir à quoi il est dû. Peut-être que renommer correctement tes variables ne réglera pas le problème, mais ce qui est sûr, c'est qu'il ne faut jamais avoir deux variables du même nom, cela fait partie des règles communes de codage "propre", et souvent, cela peut générer des problèmes ou des dysfonctionnements.

Bonne journée.


Stéphane

Salut,

Je suis d'accord avec Snootlab concernant le nom des variables. Par contre on n'a parfois pas le choix et deux variables ont le même nom. Dans ce cas il faut réduire leur portée à l'aide du mot clé static à défaut de pouvoir les mettre en private dans le sketch. Par exemple :

static int i = 0;

Dans ton exemple, il est même possible de pousser plus loin puisque la variable i n'est utilisée que dans la fonction loop :

void loop(){
    static int i = 0;
    // ...
}

++

Bonjour, et merci une fois de plus pour vos réponses.

Ok pour la double déclaration de variable, j'ai résolu en mettant un 'H' devant chaque déclaration dans animations.h:

#include "Tlc5940.h"
#include "WProgram.h"

unsigned int ani_simple[][15] = {
	{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
	{14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
	{4, 3, 2, 1, 0, 9, 8, 7, 6, 5, 14, 13, 12, 11, 10},
	{10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}
};

int lireAniSimple(int Hanimation, int Hsortie, int Hplein, int Htempo, int Hi)
{
	for (Hsortie = 0; Hsortie < 15; Hsortie++)
	{
		Tlc.set(ani_simple[Hanimation][Hsortie],Hplein);
		Tlc.update();
		delay(Htempo);
	}
	Hi = 1;
	Hsortie = 0;
	return Hi;
}

int effaceAniSimple(int Hanimation, int Hsortie, int Hzero, int Htempo, int Hi)
{
	for (Hsortie = 0; Hsortie < 15; Hsortie++)
	{
		Tlc.set(ani_simple[Hanimation][Hsortie],Hzero);
		Tlc.update();
		delay(Htempo);
	}
	Hi = 0;
	Hsortie = 0;
	return Hi;
}

J'ai essayé de les mettre en static, mais j'obtenais ce message:

C:\Program Files (x86)\Arduino 22\libraries\TLC5940/animations.h:11: error: storage class specifiers invalid in parameter declarations
C:\Program Files (x86)\Arduino 22\libraries\TLC5940/animations.h:11: error: storage class specified for parameter 'Hanimation'

Par contre, dans mon .h, je déclare quand même 2 fois chaque variable, une fois pour chaque fonction: les variables de fonctions sont-elles détruites à la fin de la fonction?

PS: le problème de reset intempestif venait d'un port USB défectueux... :*

Quelles variables as-tu essayé de mettre en static ? Les arguments de ta fonction ? Je pensais à celles déclarées dans ton sketch...

Par contre je crois comprendre que tu as des implémentations de fonctions dans animations.h !? Si oui c'est à proscrire : le fichier d'entête (.h) constitue l'API de ta bibliothèque (prototypes de fonctions, etc) alors que le fichier source (.c ou *.cpp) en contient l'implémentation.

++

Hello,

J'ai essayé de mettre les variables des fonctions en static, celles du sketch seront en volatile (utilisation d'une interruption).

Que veux-tu dire par implémentation de fonction?

Bonjour,

Ce qu'il veut dire c'est que dans ton .h tu mettras ça :

int lireAniSimple(int , int , int , int , int );

et dans ton .c tu mettras ceci :

int lireAniSimple(int Hanimation, int Hsortie, int Hplein, int Htempo, int Hi)
{
//ta fonction
}

Bonne journée,


Stéphane

Ouais ok, mais je ne vois toujours pas ce que sont les implémentations de fonction?
Il me semble, quand on compile le sketch, que chaque appel de fonction est remplacé par les instructions la composant, je me trompe? Donc que mon .h ne regroupe que les définitions de fonctions et les instructions les composant. Comme pour toutes les autres librairies utilisées!

Stéphane (Snootlab) te l'a expliqué :roll_eyes:

Dans ton fichier d'entête (*.h), tu mets le prototype de la fonction :

int lireAniSimple(int , int , int , int , int );

Et dans le fichier source, l'implémentation, en gros le corps, les instructions exécutées par ta fonction :

int lireAniSimple(int Hanimation, int Hsortie, int Hplein, int Htempo, int Hi)
{
      //ta fonction
}

schizophrene:
J'ai essayé de mettre les variables des fonctions en static, celles du sketch seront en volatile (utilisation d'une interruption).

En effet c'est normal que ça ne compile pas, le mot clé static s'utilise lors de la déclaration d'une variable, pas sur un argument de fonction...

++

Merci pour toutes c'est explications, même si l'envie de persister dans ma façon de voir me tente encore (une résurgence de mes cours d'assembleur sur PIC 16F84 en BTS, où l'on mettait toutes nos fonctions personnalisées dans une librairie).

Mais je ferai selon vos conseils.

De rien :wink:

De manière générale en programmation il y a de nombreuses manières de faire, mais toutes n'ont pas la même qualité... Au cas où tu ne connaitrais pas, tu peux regarder les tutoriaux du Site du Zero, je les trouve particulièrement bien faits et accessibles pour débuter. Par exemple : http://www.siteduzero.com/tutoriel-3-13993-la-programmation-modulaire.html

++

Je connais très bien le SdZ, pour y avoir appris la programmation PHP et MySQL :slight_smile:
Je lirai le tutoriel dont tu donnes l'adresse quand j'aurais le temps de ne me consacrer qu'à ça, bien que je pense que ce ne soit pas difficile à assimiler :slight_smile:

Merci encore pour vos aides :slight_smile:

Super, j'ai pu lire tout le tutoriel sur la prgrammation modulaire.
J'ai maintenant 4 fichiers de plus dans mon sketch, 2 .h et 2 .cpp, et ça fonctionne nickel :slight_smile:

Je mets en résolu