[Programmation] Emission d'une trame DMX 512 - PIC16
Répondre à la discussion
Affichage des résultats 1 à 8 sur 8

Emission d'une trame DMX 512 - PIC16



  1. #1
    Shepard20

    Emission d'une trame DMX 512 - PIC16


    ------

    Bonjour à tous,
    Je suis actuellement confronté à un problème de programmation avec les timers du PIC de Microship lors de la conception d'une trame DMX 512, et j'espère que vous pourrez m'aider à le résoudre.
    J'ai pour objectif de mettre en œuvre un système de contrôle d'éclairage basé sur le protocole DMX 512. J'ai choisi le microcontrôleur PIC16 pour cette application. Cependant, j'ai rencontré des difficultés lors de la gestion des timers pour générer les délais précis requis par le protocole DMX 512.

    Nom : slide_25.jpg
Affichages : 337
Taille : 104,1 Ko

    Ma difficulté réside dans la programmation des timers pour générer ces délais précis avec une inversion . J'ai essayé d'utiliser le Timer0 du PIC16 avec une interruption d'overflow, mais je n'arrive pas à obtenir des délais (voir pas du tout) aussi précis que nécessaires.
    Voici un extrait du code :

    Code:
    #define DMX_TX_TIMER_100US  TMR0H = 0xC7; TMR0L = 0x00 //Set timer  to trigger in 100uS
    #define DMX_TX_TIMER_8US    TMR0H = 0xF; TMR0L = 0x00 //Set timer to trigger in 8uS
    #define	DMX_TX_UART_IRQ_ENABLE_BIT(state)	PIE3bits.TX2IE = state
    #define	DMX_TX_UART_IRQ_FLAG_BIT(state)		PIR3bits.TX2IF = state
    
    void TMR0_ISR(void)
    {
        PIR0bits.TMR0IF = 0;
        
        PORTCbits.RC3 = ~PORTCbits.RC3;
        if(TMR0_InterruptHandler)
        {
            TMR0_InterruptHandler();
        }
    
    }
    
    void __interrupt() INTERRUPT_DMX (void)
    {
        // interrupt handler
        if(PIE0bits.TMR0IE == 1 && PIR0bits.TMR0IF == 1)
        {
            TMR0_ISR();
         }
    }
    
    
    switch (DMX_TX_STATE) {
    
                    case DMX_TX_BREAK:
                       DMX_TX_TIMER_100US;
                       while ( PIR0bits.TMR0IF == 0);
                       DMX_TX_STATE = DMX_TX_MAB;
                       break;
    
                    case DMX_TX_MAB:
                        DMX_TX_TIMER_8US;
                        while ( PIR0bits.TMR0IF == 0);
                        DMX_TX_STATE = DMX_TX_BREAK;
                        break;
    					
    				/*
    					other code
    				*/
    					
                    default:
                        break;
                }
    }
    Avez-vous des suggestions sur la façon de configurer les timers du PIC16 de manière à obtenir des délais plus précis pour la trame DMX 512 ? Ou existe-t-il une autre approche que je pourrais envisager pour résoudre ce problème ?

    Merci de votre aide

    -----
    Dernière modification par Shepard20 ; 14/06/2023 à 23h18.

  2. #2
    Seb.26

    Re : Emission d'une trame DMX 512 - PIC16

    Tu dois avoir 1 timer : celui qui déclenche l'envoi de la trame, le reste c'est l'uart qui gère

    https://ww1.microchip.com/downloads/...-90003204A.pdf
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  3. #3
    umfred

    Re : Emission d'une trame DMX 512 - PIC16

    ça dépend du PIC retenu. la doc indique que c'est dans les dernier PIC 8 bits

    PIC16 c'est une gamme très varié de PIC donc sans sa référence, on navigue un peu à vue (la fréquence d'horloge du PIC joue aussi sur les timers).

    Précise la précision dont tu as besoin, celle que tu obtiens, .....

  4. #4
    Shepard20

    Re : Emission d'une trame DMX 512 - PIC16

    Pour mon projet, j'utilise le microcontrôleur PIC16F15325 qui ne dispose pas d'un registre spécifique pour faciliter l'envoi d'une trame DMX, comme suggéré par @Seb.26.
    Pour contourner cette limitation, j'utilise la broche GPIO pour simuler l'envoi de la trame. Cela est nécessaire car le module EUSART du microcontrôleur maintient le niveau haut même lorsque le module est désactivé, ce qui empêche l'établissement d'un niveau bas pour générer le DMX Break.
    En utilisant la broche GPIO, je peux contrôler manuellement le niveau de la broche pour générer la trame DMX512 selon les spécifications requises.

    Ah oui, mon horloge est fixé à 16Mhz.

    Et mon Timer0 : 4us avec un prescaler à 1:16, Timer de 8bits

    .h
    Code:
    // Configuration des broches GPIO
    #define DMX_PIN_OUTPUT TRISCbits.TRISC3
    #define DMX_PIN PORTCbits.RC3
    #define DMX_DATA_SIZE 512         // Nombre de canaux DMX512 à envoyer (exemple : 10 canaux)
    uint8_t dmxState = 0;   // État de l'envoi DMX (0 = Break, 1 = Mark After Break, 2 = Start Code et Data)
    // Déclaration des variables globales
    uint8_t dmxData[DMX_DATA_SIZE];  // Mémoire tampon pour les données DMX512
    uint16_t currentIndex = 0;  // Index actuel dans la mémoire tampon
    // TIMER
    #define DMX_TX_TIMER_100US  TMR0H = 0xC7; TMR0L = 0x00 //Set timer BREAL to trigger in 100uS
    #define DMX_TX_TIMER_8US    TMR0H = 0xF; TMR0L =  0x00//Set timer BREAL to trigger in 8uS
    #define DMX_TX_TIMER_36US    TMR0H = 0x47; TMR0L =  0x00//Set timer BREAL to trigger in 8uS

    .c
    Code:
    
    void __interrupt() INTERRUPT_InterruptManager (void)
    {
        // interrupt handler
        if(PIE0bits.TMR0IE == 1 && PIR0bits.TMR0IF == 1)
        {
    
            switch (dmxState)
            {
                case 0:  // Break
                    DMX_PIN = 0;  // Envoyer un signal bas pour générer le DMX Break
                    DMX_TX_TIMER_100US;  // Configurer la valeur de rechargement du Timer1 pour la durée du Break de 100us
                    dmxState++;
                    break;
    
                case 1:  // Mark After Break
                    DMX_PIN = 1;  // Envoyer un signal haut pour générer le Mark After Break
                    DMX_TX_TIMER_8US;  // Configurer la valeur de rechargement du Timer1 pour la durée du Mark After Break de 8us
                    dmxState++;
                    break;
    
                case 2:  // Start Code
                     DMX_PIN = 0;  // Envoyer un signal haut pour générer le Mark After Break
                    DMX_TX_TIMER_36US;  // Configurer la valeur de rechargement du Timer1 pour la durée du Mark After Break de 8us
                    dmxState++;
                    break;
                    
    
                    break;
                case 3:  // Data
                    if (currentIndex < DMX_DATA_SIZE)
                    {
                        LATCbits.LATC4 = dmxData[currentIndex];  // Envoyer les données DMX512 à la broche GPIO
                        currentIndex++;
                    }
                    else
                    {
                        currentIndex = 0;  // Réinitialiser l'index pour la prochaine trame
                    }
    
                    DMX_TX_TIMER_8US;  // Configurer la valeur de rechargement du Timer1 pour la période du signal DMX
                    
                    break;
    
               default:
                    break;
            }
                    PIR0bits.TMR0IF = 0;  // Réinitialiser le drapeau d'interruption du Timer1
        }
    }
    
    void main(void)
    {
        // initialize the device
        SYSTEM_Initialize();
        INTERRUPT_GlobalInterruptEnable();
        INTERRUPT_PeripheralInterruptEnable();
        TMR0_StartTimer();
    
        // Initialisation des données DMX512 dans la mémoire tampon
        for (uint16_t i = 0; i < DMX_DATA_SIZE; i++)
        {
            dmxData[i] = i + 1;  // exemple : Remplir les données avec une séquence de 1 à DMX_DATA_SIZE
        }
    Malheureusement, les délais générés par le timer ne sont pas respectés, ce qui compromet la fonctionnalité de l'envoi de la trame.

    Nom : DMX1.JPG
Affichages : 116
Taille : 18,2 Ko

    Merci pour de votre aide
    Dernière modification par Shepard20 ; 15/06/2023 à 11h20.

  5. A voir en vidéo sur Futura
  6. #5
    umfred

    Re : Emission d'une trame DMX 512 - PIC16

    sans échelle de temps sur ton chrono, difficile de se faire une idée

    moi je réfléchirais en terme de bit: 250kbits/s => 1 bit = 4us, donc mon timer devrait me donner une précision plus grande, je dirais 1us.
    Ainsi 1 bit = 4 unités de temps; le BREAK >= 22 bits (>=88µs, donc 100µs ou 25 bits c'est OK); le MAB = 8µs (dans les faits, il semble qu'il peut être un peu plus long mais bref) = 2 bits

    Dans les timings, il faut aussi penser au temps d'exécution du code qui se base sur Fosc/4, si je ne me trompe pas (1 opération prend x*1/(Fosc/4), x variant selon l'oparation)
    Dernière modification par umfred ; 15/06/2023 à 13h02.

  7. #6
    umfred

    Re : Emission d'une trame DMX 512 - PIC16

    N'oublie pas aussi que chaque donnée c'est 8 bits. Or tu remplis ton tableau de valeur uint_16 (16 bits) (le type de i); à voir ce qu'il se passe après la valeur 255 (mais bon comme le remplissage, c'est pour vérifier que ça fonctionne)

  8. #7
    Seb.26

    Re : Emission d'une trame DMX 512 - PIC16

    Que le break ne soit pas géré par le CPU, OK, mais envoyer les bits un par un en soft, c'est "RoadToFail" AMA ...

    Donc pour le break, tu ajoutes une porte ET, ce qui te permet de forcer à 0 la sortie de l'UART (ou tu prends la main sur la GPIO, comme tu veux).

    Ensuite, tu utilises l'UART en interruption pour envoyer les données ( 1 bit de START, 8bits de data et 2bits de STOP ).

    En tout cas, c'est comme ça que j'irais ...
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  9. #8
    umfred

    Re : Emission d'une trame DMX 512 - PIC16

    ça se fait du soft UART (en assembleur, on maitrise mieux les timings )

    Dans le code que je lis ici http://ww1.microchip.com/downloads/e...tes/01076A.pdf (cf AppendixA en page 9, même si c'est pour un 18F, et il passe effectivement par l'USART en communication 9-bits avec le dernier bit toujours à 1), on y voit que pour l'utilisation du Timer0 (Fosc 16Mhz, avec prescaler 1:4 pour générer des tick à 1µs), on charge uniquement TMR0L avec la valeur 256-Temps_voulu (256-100 pour 100µs par exemple), on ne touche pas à TMR0H

Discussions similaires

  1. [Programmation] PIC16 manque de memoire programme
    Par invite39f545b8 dans le forum Électronique
    Réponses: 16
    Dernier message: 23/03/2016, 12h20
  2. Trame RS485 vers trame Modbus
    Par inviteeac1b2f9 dans le forum Internet - Réseau - Sécurité générale
    Réponses: 11
    Dernier message: 06/11/2013, 16h48
  3. choix PIC18 ou PIC16?
    Par inviteb8b3982e dans le forum Électronique
    Réponses: 3
    Dernier message: 22/05/2012, 16h52
  4. migration de PIC16 vers PIC18
    Par invite51e48a05 dans le forum Électronique
    Réponses: 13
    Dernier message: 10/02/2012, 12h03
  5. VHDL - coeur PIC16
    Par Toufinet dans le forum Électronique
    Réponses: 0
    Dernier message: 17/09/2007, 19h03
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...