Go Down

Topic: Petite matrice charlieplexée (Read 1 time) previous topic - next topic

Mossieur_Propre

Apr 26, 2017, 01:11 pm Last Edit: Apr 26, 2017, 01:24 pm by Mossieur_Propre Reason: Ajout des images
Bonjour à tous,

En premier post, je partage mon dernier montage, l'objet d'un petit projet du week-end : une matrice LEDs 3x4 charlieplexée.

Le charlieplexage, qu'est-ce que c'est ? C'est une méthode de multiplexage permettant d'économiser des broches sur nos microcontrôleurs. Alors qu'une matrice 3x4 nécessiterait 7 broches sur mon microcontrôleur, je n'en aurait besoin que de 4 sur cet exemple.

Le fonctionnement est simple : le charlieplexage propose d'utiliser les 3 états possibles proposés par les ports I/O de nos microcontrôleurs : output low, output high, et input. Je vous laisse le soin de demander à Google le fonctionnement exact, le web regorge d'article dessus.

Tout d'abord, le schéma de ma matrice :



On le voit, c'est tout simple. Un microcontrôleur, 4 résistances, 12 LEDs, et un port USB d'alimentation.

Réalisation sur perfboard :





(Je n'avais pas assez de rouge sous la main :smiley-mr-green: )
Le code :

Code: [Select]

/*
 * This is how LEDs are numbered in my physical LED matrix :
 *
 *    1   2   3
 *    4   5   6
 *    7   8   9
 *    10  11  12
 */

// Unused, for reference.
// This is the LED matrix. Rows are anodes, cols are cathodes.
// Rows and cols describes pins. Numbers describes LEDs.
int matrix[4][4] = {
  { -1, 12, 5, 6 },
  { 9, -1, 11, 4 },
  { 2, 8, -1, 10},
  { 3, 1, 7, -1}
};

// LED mapping : For LEDs from 1 to 12, {anode, cathode}.
// We use this to avoid browsing through the previous matrix;
// which should be time consuming.
// Each array line correspond a LED, from 1 to 12. This is why
// I set dummy values for first line (index 0)
// Each number is a pin.
int leds[13][2] = {
  { -1, -1},
  {3, 1},
  {2, 0},
  {3, 0},
  {1, 3},
  {0, 2},
  {0, 3},
  {3, 2},
  {2, 1},
  {1, 0},
  {2, 3},
  {1, 2},
  {0, 1}
};

// Animations
bool anim1[2][4][3] = {
  {
    {true, true, true},
    {false, false, false},
    {true, true, true},
    {false, false, false}
  },
  {
    {false, false, false},
    {true, true, true},
    {false, false, false},
    {true, true, true}
  }
};

bool anim2[6][4][3] = {
  {
    {true, true, true},
    {false, false, false},
    {false, false, false},
    {false, false, false}
  },
  {
    {false, false, false},
    {true, true, true},
    {false, false, false},
    {false, false, false}
  },
  {
    {false, false, false},
    {false, false, false},
    {true, true, true},
    {false, false, false}
  },
  {
    {false, false, false},
    {false, false, false},
    {false, false, false},
    {true, true, true}
  },
  {
    {false, false, false},
    {false, false, false},
    {true, true, true},
    {false, false, false}
  },
  {
    {false, false, false},
    {true, true, true},
    {false, false, false},
    {false, false, false}
  }
};

bool anim3[4][4][3] = {
  {
    {true, false, false},
    {true, false, false},
    {true, false, false},
    {true, false, false}
  },
  {
    {false, true, false},
    {false, true, false},
    {false, true, false},
    {false, true, false}
  },
  {
    {false, false, true},
    {false, false, true},
    {false, false, true},
    {false, false, true}
  },
  {
    {false, true, false},
    {false, true, false},
    {false, true, false},
    {false, true, false}
  }
};

bool anim4[2][4][3] = {
  {
    {false, true, false},
    {true, false, true},
    {false, true, false},
    {true, false, true}
  },
  {
    {true, false, true},
    {false, true, false},
    {true, false, true},
    {false, true, false}
  }
};

void setup() {
  // Light all LEDs for 2 seconds
  unsigned long start = millis();

  while (millis() < start + 2000) {
    for (int i = 1 ; i <= 12 ; i++) {
      lightOn(i);
      delayMicroseconds(500);
    }
  }
}

// Switch all LEDs off
void allOff() {
  pinMode(0, INPUT);
  pinMode(1, INPUT);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
}

// Switch a single LED on
void lightOn(int led) {
  allOff();

  int *ledPins = leds[led];
  pinMode(ledPins[0], OUTPUT);
  pinMode(ledPins[1], OUTPUT);

  digitalWrite(ledPins[0], HIGH);
  digitalWrite(ledPins[1], LOW);
}

// Draw a frame
void draw(boolean frame[4][3]) {
  for (int i = 0 ; i < 4 ; i++) {
    for (int j = 0 ; j < 4 ; j++) {
      if (frame[j][i] == true) {
        lightOn((j * 3) + i + 1);
      }
      delayMicroseconds(500);
    }
  }
}

// Run an animation
void animate (boolean animation[][4][3], int nbFrames, unsigned long frameDuration, unsigned long animationDuration) {
  unsigned long lastFrame = millis();
  unsigned long animationStart = millis();

  while (1) {
    for (int i = 0 ; i < nbFrames ; i++) {
      while (millis() < lastFrame + frameDuration) {
        draw(animation[i]);
      }

      lastFrame = millis();

      if (millis() > animationStart + animationDuration) return;
    }
  }
}

void loop() {
  animate(anim1, 2, 500, 5000);
  animate(anim2, 6, 100, 3000);
  animate(anim3, 4, 150, 3000);
  animate(anim4, 2, 500, 5000);
}


Et ça marche !

https://www.youtube.com/watch?v=ThF2GD7TQ7c

Amusez-vous, et que la lumière soit !

elektrax

bonjour,

étant intéressé par ce schéma, j'ai quelques questions :

- la pin rset doit etre tirée a +vc avec r 10k ou laisser flottante ?

- quelle carte choisir dans l'ide pour compiler ?

testé avec tinycores : attiny85 8 mhz internal : erreur compilation
choix uno : pas d'erreurs

j'aimerais des explications : choix carte, compiler et choix usbasp pour flasher le tiny85 sans bootloader : usbasp ou usbasp tiny classic

Merci beaucoup

Mossieur_Propre

#2
May 03, 2017, 10:05 am Last Edit: May 03, 2017, 10:11 am by Mossieur_Propre
Salut,

Concernant la pin RESET, je la laisse flottante, mais tu peux effectivement la connecter à une résistance de pull-up.

Concernant la compilation, j'utilise une puce Attiny85 que je programme avec un Arduino (http://highlowtech.org/?p=1695). Je choisis donc la carte "Arduino as ISP".

Je me suis fait un petit circuit pour faciliter la programmation du Tiny par un Arduino :



Du coup, j'utilise un bootloader. Je pense bientôt me commander un USBasp pour pouvoir m'en passer.

EDIT : et je laisse le Tiny tourner à 1 MHz, pas besoin de plus pour allumer quelques LEDs

elektrax

bonjour,

merci pour votre réponse, lorsque vous teléversez le croquis :

le uno est chargé avec l'exemple "aduinoisp" ?
puis dans "outils programmateur" : Arduino as ISP ?

et dans "outils type de carte" : vous choisissez laquelle ?

et pour finir "televerser avec un programmateur" ou "televersez" tout court ?

merci


Mossieur_Propre

C'est ça, l'Arduino chargé avec le sketch ArduinoISP, "Arduino as ISP" est sélectionné comme programmateur.

Pour le type de carte, je choisis "ATtiny25/45/85", dans "processeur" je choisis "ATtiny85" et comme fréquence (clock) je choisis "Internal 1 MHz". Il faut avoir bien évidemment installé dans le gestionnaire de cartes le support des ATTiny x5/x4 (ici : https://github.com/damellis/attiny).

Enfin, une fois les connexions effectuées, je clique sur la flèche de téléversement dans la barre d'outils (ça doit correspondre à "téléverser" tout court).

(et avant le tout premier téléversement, je fais "Outils > Graver la séquence d'initialisation" pour téléverser le bootloader sur le Tiny)

elektrax

 je comprends mieux les erreurs sur ma version IDE :
les boards attiny installés sont différents : github.com/SpenceKonde/ATTinyCore
je n'avais pas pensé au bootloader

Merci

Go Up