Go Down

Topic: Comment faire une fonction avec un tableau en paramètre pour horloge POV (Read 4964 times) previous topic - next topic

kri13400

Bonjour à tous,
Je débute dans le monde de l'arduino, et je bloque sur la façon de coder mon premier projet, une horloge POV sur 8 leds...
Jusqu'ici ça marche, je n'ai pas encore reçu mon capteur à effet Hall mais j'arrive à me servir de l'horloge en l'attachant à un fil que je fais tourner...
Voilà en gros ce que j'ai pour afficher les chiffres, je déclare ces tableaux:

Code: [Select]

boolean ZERO [8][4] = {
  {0,1,1,0},
  {1,0,0,1},
  {1,0,0,1},
  {1,0,0,1},           
  {1,0,0,1},
  {1,0,0,1},
  {1,0,0,1},
  {0,1,1,0},
};


Puis j'appelle ce type de tableau dans 10 switch case.

Code: [Select]

case 0 :
      digitalWrite(LED[0] ,ZERO [0][0]);
      digitalWrite(LED[1] ,ZERO [1][0]);
      digitalWrite(LED[2] ,ZERO [2][0]);
      digitalWrite(LED[3] ,ZERO [3][0]);
      digitalWrite(LED[4] ,ZERO [4][0]);
      digitalWrite(LED[5] ,ZERO [5][0]);
      digitalWrite(LED[6] ,ZERO [6][0]);
      digitalWrite(LED[7] ,ZERO [7][0]);
      delay (delai);
pareil pour les colonnes 1,2,et 3... et pour les autres chiffres...


Je simplifierais plus tard avec des boucles mais avant tout j'aimerais faire une fonction avec pour parametre mes tableaux (ou argument?) que j'appellerais dans chaque case et qui en gros ressemblerais à ça:

Code: [Select]

void AffColonnes (boolean tab)
  {
      digitalWrite(LED[0] ,tab [0][0]);
      digitalWrite(LED[1] ,tab [1][0]);
      digitalWrite(LED[2] ,tab [2][0]);
      digitalWrite(LED[3] ,tab [3][0]);
...etc...


Et que j'appellerais comme ça:

Code: [Select]

case 0 :
            AffColonnes (ZERO[][]);
            break;


Ce n'est malheureusement pas si simple... Dois-je utiliser les pointeurs?

Code: [Select]

void AffColonnes (boolean* tab)
{
      digitalWrite(LED[0], tab [0][0]);
      digitalWrite(LED[1], tab [1][0]);
      digitalWrite(LED[2] ,tab [2][0]);
      digitalWrite(LED[3] ,tab [3][0]);
...etc...


Ca ne marche pas non plus mais je ne suis pas sûr de la syntaxe.
Pourriez-vous m'aider svp?

skywodd

Bonjour,

1) tu devrais t'intéresser au "bitwise", j'ai fait un tuto sur le sujet ;)
Cela t'éviterai de faire des tableaux de booléen pour stocker tes valeurs 0/1.
http://skyduino.wordpress.com/2013/04/05/tuto-le-bitwise-pour-les-nuls/

2) Pour ton switch ... pourquoi un switch !?
Code: [Select]
for (byte i = 0; i < 8; ++i)
digitalWrite(LED[i], ZERO[i][n]);

Je suppose que tu "switch" sur un entier ? Ici "n" est le fameux entier en question.
+100 lignes de code -> 2 lignes.

3)
Quote
Ce n'est malheureusement pas si simple... Dois-je utiliser les pointeurs?

Ho que oui ! Et tu n'as même pas d'autre choix ;)

Code: [Select]
void AffColonnes (boolean[][4] tab) {
      digitalWrite(LED[0], tab [0][0]);
// ...

Remarque: Tu doit obligatoirement donner la taille de la 2ème dimension de ton tableau dans le prototype de la fonction.
Sinon le compilateur ne pourras pas savoir comment se déplacer dans ton tableau si il ne connait pas la taille d'une "ligne" ;)
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

kri13400

Merci beaucoup de ta réponse, dès que ma fonction tourne je me pencherais sur le bitwise pour alléger tout ça (j'ai peur que ce soit moins lisible pour moi, là c'est plus "graphique"). Je compte rajouter des animations et du texte par la suite...
Par contre la fonction ne marche toujours pas... La syntaxe?
Voici mon code allégé (seuls les chiffres 0, 1 et 2 et le: sont décris) et commenté pour que ce soit plus clair:

Code: [Select]

int LED[]= {5, 6, 7, 8, 9, 10, 11, 12};
int space=2;      //Espace entre deux chiffres
int delai= 1;     //Temps d'affichage d'une colonne
int secondes;
int secondesU;    //U pour unités D pour Dizaines
int secondesD;
int minutes;
int minutesU;
int minutesD;
int heures;
int heuresU;
int heuresD;
long interval = 1000;    //Le temps que dure la seconde
long previousMillis= 0;
int i;
int j;
int n;

boolean ZERO [8][4] = {
 {0,1,1,0},
 {1,0,0,1},
 {1,0,0,1},
 {1,0,0,1},          
 {1,0,0,1},
 {1,0,0,1},
 {1,0,0,1},
 {0,1,1,0},
};

boolean UN [8][4] = {
 {0,0,1,0},
 {0,1,1,0},
 {1,0,1,0},
 {0,0,1,0},
 {0,0,1,0},
 {0,0,1,0},
 {0,0,1,0},
 {1,1,1,1},
};

boolean DEUX [8][4] = {
 {0,1,1,0},
 {1,0,0,1},
 {0,0,0,1},
 {0,0,1,0},
 {0,1,0,0},
 {1,0,0,0},
 {1,0,0,0},
 {1,1,1,1},
};

boolean DIX [8][2] = {       // les deux points separant Heures Min et Sec
 {0,0},
 {1,1},                    
 {1,1},
 {0,0},
 {0,0},
 {1,1},
 {1,1},
 {0,0},
};

boolean initialisation [8]= {0, 0, 0, 0, 0, 0, 0, 0};    //Pour remettre à l'état bas les sorties avant l'affichage d'un autre chiffre

void AffColonnes (boolean tab [][4])
 {

     for (i=0; i<8; i++)
     {
       digitalWrite(LED[i] ,tab [i][0]);     // Ma fameuse fonction qui remplacera les switch case
     }                                       // que je réduirais encore puisque je fais 4x la même chose
     delay (delai);
     for (i=0; i<8; i++)
     {
       digitalWrite(LED[i] ,tab [i][1]);    
     }
     delay (delai);
     for (i=0; i<8; i++)
     {
       digitalWrite(LED[i] ,tab [i][2]);    
     }
     delay (delai);
     for (i=0; i<8; i++)
     {
       digitalWrite(LED[i] ,tab [i][3]);    
     }
     delay (delai);
     for (i=0; i<8; i++)
     {
       digitalWrite(LED[i] ,initialisation [i]);    
     }
     delay (delai * space);
 }


void afficher (int chiffre)
{
 switch(chiffre)
   {
        case 0 :
           AffColonnes (ZERO [8][4]);      //et que je suis censé rappeler comme ça
           break;
     
     
     
//    case 0 :
//    
//      for (i=0; i<8; i++)
//      {
//        digitalWrite(LED[i] ,ZERO [i][0]);    
//      }
//      delay (delai);
//      for (i=0; i<8; i++)
//      {
//        digitalWrite(LED[i] ,ZERO [i][1]);    
//      }
//      delay (delai);
//      for (i=0; i<8; i++)
//      {
//        digitalWrite(LED[i] ,ZERO [i][2]);    
//      }
//      delay (delai);
//      for (i=0; i<8; i++)
//      {
//        digitalWrite(LED[i] ,ZERO [i][3]);    
//      }
//      delay (delai);
//      for (i=0; i<8; i++)
//      {
//        digitalWrite(LED[i] ,initialisation [i]);    
//      }
//      delay (delai * space);
//      break;
     
     
     case 1 :
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,UN [i][0]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,UN [i][1]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,UN [i][2]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,UN [i][3]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,initialisation [i]);    
       }
       delay (delai * space);
       break;
     
     case 2 :
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,DEUX [i][0]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,DEUX [i][1]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,DEUX [i][2]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,DEUX [i][3]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,initialisation [i]);    
       }
       delay (delai * space);
       break;
     
     case 10 :
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,DIX [i][0]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,DIX [i][1]);    
       }
       delay (delai);
       for (i=0; i<8; i++)
       {
         digitalWrite(LED[i] ,initialisation [i]);    
       }
       delay (delai * space);
       break;
    }
}

void setup()
{
 heures =15;        //Je règle l'heure ici
 minutes=35;
 secondes=32;
 Serial.begin (9600);
 int i;
 for (i=0; i<8; i++)
 {
  pinMode (LED[i], OUTPUT);
 }
}

void loop()
{

// Serial.println (ZERO [0][0]);
unsigned long currentMillis = millis();


 if (currentMillis - previousMillis > interval) // Un module real time clock remplacera tout ça
 {                                              // et sera certainement l'objet de futurs posts d'aide ^^
   previousMillis = currentMillis;
   secondes++;
 }
 

secondesD= secondes/10;
secondesU= secondes- (secondesD*10);

minutesD= minutes/10;
minutesU= minutes- (minutesD*10);

heuresD= heures/10;
heuresU= heures- (heuresD*10);

if(secondes == 60)
{
secondes = 0;
minutes++;
}
if(minutes == 60)
{
minutes = 0;
heures++;
}
if(heures == 24)
{
heures = 0;
}

 afficher (heuresD);
 afficher (heuresU);
 afficher (10);
 afficher (minutesD);
 afficher (minutesU);
 afficher (10);
 afficher (secondesD);
 afficher (secondesU);
 
 delay (delai *12);

//      afficher (0);        
//      afficher (1);
//      afficher (2);
//      afficher (3);
//      afficher (4);
//      afficher (5);
//      afficher (6);
//      afficher (7);
//      afficher (8);
//      afficher (9);
}


J'ai essayé avec boolean* tab [][4], et plusieurs manières d'écrire mais rien n'y fait, je ne peux pas compiler.
Encore merci pour votre aide!

skywodd

Tu ne passes pas la taille du tableau lors de l'appel de la fonction, juste le nom de la variable ;)
Code: [Select]
AffColonnes (ZERO);

PS: tu auras des problèmes si tu veut afficher DIX par exemple ([][2] et non [][4]) ;)
C'est la que tu devrais voir l'intérêt du bitwise, certes c'est moins clair (quoi que) mais chaque colonne faisant 8 lignes -> 8 bits = 1 octet.

En bitwise ceci :
Code: [Select]
boolean ZERO [8][4] = {
  {0,1,1,0},
  {1,0,0,1},
  {1,0,0,1},
  {1,0,0,1},           
  {1,0,0,1},
  {1,0,0,1},
  {1,0,0,1},
  {0,1,1,0},
};


Deviendrait cela (rotation de 90°) :
Code: [Select]
byte ZERO [4] = {
  0b01111110,
  0b10000001,
  0b10000001,
  0b01111110
};


-> économie de place mais surtout :
Code: [Select]
void AffColonnes (byte tab[], int taille) { // La fonction est maintenant totalement générique
  // ...
}
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

kri13400

Ca fonctionne à merveille je suis passé de 8Ko à 3,5Ko.
Merci !

kri13400

Bonjour,
Mon projet avance, j'ai ajouté le module RTC et tout fonctionne à merveille, l' affichage tourne un peu sur lui-même, je joue donc sur le rafraîchissement pour qu' il reste plus ou moins stable puisque je ne contrôle pas la vitesse de rotation...
Jusque là ça allait. J'ai reçu aujourd'hui mon capteur à effet hall et après quelques essais l' image ne tourne plus mais se dilate et se contracte aléatoirement.
2 problèmes se posent:

1 - Il faut à présent que je fasse un compteur, pour le moment lorsque je passe devant un aimant une variable capteur passe à 1, et lorsque je fais i++ sur une variable compteur (si capteur passe à 1) comme je me doutais i s'incrémente tant qu'il est devant et pas une seule fois comme je le désire. Comment s'y prendre? Comparer l' état je suppose mais je ne vois pas comment le poser...?

2 - J' ai vu que souvent l'interruption était utilisé, j'ai préféré utiliser une entrée digitale car je ne connais pas encore le fonctionnement de l'interruption. Est-ce possible de cette manière?
Comment s'y prendre? Ajuster mon rafraîchissement pour que mon texte rentre dans un tour complet? Ou faire une moyenne de la variable compteur et ajuster avec ça mes délais?

Je ne sais pas si c'est bien clair présenté comme ça...
Merci de venir à mon aide! Je posterai des photos de l' avançée bientôt.
Encore merci pour votre aide  ;)

Go Up