Club robotique de Sophia-Antipolis

Accueil > POBOTpedia > Actionneurs > Les afficheurs > Piloter des afficheurs 7 segments

Piloter des afficheurs 7 segments

samedi 18 octobre 2008, par Julien H.

Les afficheurs 7-segments sont des chiffres lumineux que l’on peut piloter pour choisir les valeurs successives qui vont s’allumer. Les 10 chiffres (de 0 à 9) sont décomposés en segments : chacun de ces segments peut s’allumer indépendamment des autres.

Afficheurs 7-segment

On peut représenter l’afficheur comme autant de leds que de segments, mais pour limiter le nombre de pattes, ces leds sont reliées par une même patte. Une diode, même électro-luminescente, étant un bipole polarisé, on distingue deux types d’afficheur : ceux dont la cathode est commune (abbréviation CC) et ceux à anode commune (AC). D’autres informations ici

Anecdote rigolote, il n’y a pas toujours 7 segments mais plutôt 8 car un . est présent sur la plupart d’entre eux, pour servir de virgule par exemple. Bien sûr il n’est pas nécessaire de le câbler, comme il n’est pas nécessaire de câbler tous les segments si vous ne comptez utiliser qu’une partie d’entre eux (pour un 1 par exemple) puisque chaque led est indépendante.

Exemples et cahier des charges

On trouve des afficheurs 7-segments sur un radio-réveil, un chronomètre géant, etc. Une utilisation courante en robotique est d’afficher en permanence la tension disponible dans le robot grâce à un voltmètre simplifié.

Nous présentons dans cet article la réalisation d’un chronomètre pour nos courses de robots Ma-vin. [A CONTINUER]

Quelques solutions possibles

La problématique

Deux aspects :
 le nombre de pattes à contrôler : jusqu’à 9 par afficheur, sachant qu’on peut multiplexer les afficheurs pour avoir 8 pattes communes pour chacun des segments et 1 patte par afficheur. Cela peut s’avérer trop important si on a un microcontrôleur limité ou qui doit gérer d’autres fonctions que l’affichage
 la puissance disponible : le microcontrôleur délivre un courant limité sur chacune des pattes, alors que l’afficheur va demander plus que disponible, surtout s’il est de grande taille

Une solution simple

Utiliser des transistors [A CONTINUER]

Une solution à circuits intégrés

Utiliser un transcodeur dédié aux afficheurs 7 segments. Il s’agit d’un circuit intégré qui va réduire le nombre de sorties nécessaires sur le microcontrôleur et/ou qui va intégrer les transistors pour limiter le nombre de composants.

Une nouvelle solution

Pour notre problème de display 7 segments, et histoire de nous simplifier la vie, Eric nous suggère de jeter un oeil sur ceci : http://www.maxim-ic.com/quick_view2....

Datasheet MAX7219

Une autre approche

Il existe bien sûr une solution "tout-en-un" où même les afficheurs sont intégrés. C’est le plus simple question mise en oeuvre :
board SDP8.

Il y a 8 afficheurs 7 segments, ça se commande avec 4 sorties du microcontrôleur, et la bufferisation est assurée par le chip Maxim présenté ci-dessus.

Cette solution est très intéressante et économique (en argent et en temps) mais elle ne nous convient pas car nous voulons utiliser de grands afficheurs.

Réalisation du chronomètre

Nous utiliserons des transistors, à la fois pour sélectionner successivement chaque afficheur, et pour positionner les segments à éclairer pour afficher la valeur souhaitée.

Schéma de cablage des afficheurs

Il y a donc besoin de :
 6 afficheurs 7 segments à anode commune
 6 transistors PNP pour la sélection successive des afficheurs
 7 transistors NPN pour la sélection du chiffre à afficher
 7 résistances 33 Ohms (voir calculs pour la luminosité)
 19 résistances 2,2 kOhms

Code source


/*
Cible : ATMega8
Quartz : 8MHz
Compilateur : avr-gcc (WInAVR)
*/

#include
#include

// compteur du nombre d’interruptions timer
volatile int tmr_cnt = 0 ;

// vu le prescaling et l’étendue du compteur, un intervalle de 100ms correspond à 3 interruptions
#define _100_MS (3 * 64)
#define _1_S (30 * 4)

#define DIGIT_0 0b00111111
#define DIGIT_1 0b00000110
#define DIGIT_2 0b01011011
#define DIGIT_3 0b01001111
#define DIGIT_4 0b01100110
#define DIGIT_5 0b01101101
#define DIGIT_6 0b01111101
#define DIGIT_7 0b00000111
#define DIGIT_8 0b01111111
#define DIGIT_9 0b01101111
#define DIGIT_A 0b01110111
#define DIGIT_B 0b01111100
#define DIGIT_b 0b01111100
#define DIGIT_C 0b00111001
#define DIGIT_d 0b01011110
#define DIGIT_D 0b01011110
#define DIGIT_E 0b01111001
#define DIGIT_F 0b01110001
#define DIGIT_g 0b01111101
#define DIGIT_H 0b01110110
#define DIGIT_h 0b01110100
#define DIGIT_L 0b00111000
#define DIGIT_l DIGIT_1
#define DIGIT_O DIGIT_0
#define DIGIT_o 0b01011100
#define DIGIT_r 0b01010000
#define DIGIT_W 0b00111110
#define DIGIT_w 0b00011100
#define DIGIT_sp 0b00000000
#define DIGIT_dp 0b10000000

unsigned char digits[] =
DIGIT_0,
DIGIT_1,
DIGIT_2,
DIGIT_3,
DIGIT_4,
DIGIT_5,
DIGIT_6,
DIGIT_7,
DIGIT_8,
DIGIT_9,
DIGIT_A,
DIGIT_B,
DIGIT_C,
DIGIT_D,
DIGIT_E,
DIGIT_F
 ;

unsigned char msg[] =
DIGIT_H,
DIGIT_E,
DIGIT_L,
DIGIT_L,
DIGIT_O,
DIGIT_sp,
DIGIT_W,
DIGIT_o,
DIGIT_r,
DIGIT_l,
DIGIT_d,
DIGIT_dp,
DIGIT_dp,
DIGIT_dp,
DIGIT_sp,
DIGIT_sp,
DIGIT_sp,
DIGIT_sp
 ;

unsigned char *p = msg ;

unsigned char digit_num = 0 ;
unsigned char digit_sel ;
unsigned char digit_value[4] = DIGIT_sp, DIGIT_sp, DIGIT_sp, DIGIT_sp ;

/*
Interrupt handler pour l’overflow du timer 0 (T=33ms)
*/
SIGNAL (SIG_OVERFLOW0)
// A chaque interruption, on allume un des digits en activant les segments correspondants
// au motif qu’il doit reproduire via le port A et en activant sa cathode via le port B.
// Vue la fréquence de balayage, l’oeil a l’illusion que les 4 digits sont allumés en permanence
PORTA = digit_value[digit_num] ;
PORTB = digit_sel ;

digit_num = (digit_num + 1) & 0x03 ;
digit_sel = 1 << digit_num ;

// si on est arrivé au nombre nécessaire à l’obtention du délai de défilement souhaité,
// on modifie le contenu du buffer représentant le message à afficher
if (tmr_cnt == 0)
digit_value[3] = digit_value[2] ;
digit_value[2] = digit_value[1] ;
digit_value[1] = digit_value[0] ;
digit_value[0] = *p++ ;

if (p - msg == sizeof(msg)) p = msg ;

// mise à jour du compteur d’interruptions pour la gestion du défilement
tmr_cnt = (tmr_cnt + 1) % (2 * _1_S) ;

/*
Initialisation des ports
*/
void port_init(void)
DDRA = 0xFF ;
DDRB = 0xFF ;

/*
Initialisation des périphériques
*/
void init_devices(void)
cli() ; // inhibition des interruptions (pour avoir la paix)
port_init() ; // initialisation de prts

// MCU Control Register
// - interruptions externes sur niveau bas de la ligne
// - sleep mode désactivé
MCUCR = 0x00 ;

// INT0 et INT1 inactives
GICR = 0x00 ;

// activation de l’interrupt d’overflow du timer 0
TIMSK = 0x01 ;

// réglage du pre-scaler du timer 0
TCCR0 = 0x03 ;

sei() ; // autorisation des interruptions

//- --------------------------------------------------------------------------------
int main(void)
init_devices() ;

// rien à ajouter : tout est fait dans l’interrupt handler
return 0 ;

(supprimez les lignes parasites ci-dessous, bug site web)

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.