[Programmation] Réception d'une trame maison
Répondre à la discussion
Affichage des résultats 1 à 7 sur 7

Réception d'une trame maison



  1. #1
    galou32

    Réception d'une trame maison


    ------

    PRÉSENTATION

    Le programme permet de recevoir une trame et de commander un moteur et un servo.

    Le programme fonctionne ainsi*:

    on attend un front montant sur D2 qui génère une interruption*: ISR(INT0_vect)

    si front montant on appelle fct_StartTimer2(); qui démarre le comptage (CmptPulse) à l'aide des interruptions du timer2
    puis on attend maintenant un front descendant.

    lorsque front descendant*: interruption : ISR(INT0_vect) qui appelle la fonction fct_ReadBit().
    Cette dernière va* déterminer si le premier bit fait bien environ 900us ( WildStartPulse) à partir de là autoriser la lecture des 2 octects suivants.
    Pour cette lecture, je teste si à la position des bit successifs (grâce au timer 2)le signal sur D2 est haut ou bas. En fait je teste le bit s'il est à 1 ou 0
    Je rempli un tableau avec les valeurs.

    le programme navigue donc entre
    fct_ReadBit(),
    ISR(TIMER2_OVF_vect) qui incremente (CmptPulse)
    LOOP

    une fois la lecture des 2 octets terminer (CmptPulse>1000) on créer l'octect ByteX et ByteY
    dont on se sert pour commander le moteur et le servo.


    PROBLEME

    le Byte X fonctionne très bien (essai à l'oscilo ou avec le moniteur série) chaque bit de x7 à x0 est correct. On va bien de 0 à 255.

    le ByteY est faux

    SAUF si je rajoute dans le programme* un Serial.println (quelque chose)*;

    pourquoi la fonction Serial.println inserée dans le programme (même sans serialbegin). Me permet d'avoir des valeurs correctes du ByteY*????

    Merci

    TRAME

    Nom : trame.jpg
Affichages : 190
Taille : 84,9 Ko

    PROGRAMME

    Code:
    // ce programme récupère une trame entrante sur D2 (INT0) 
    // il faut que le premier bit ait une largeur de 1000us pour prendre en compte le reste de la trame (fct ReadBit)
    // une fois les 16 bits récuperés (y7 Y6... x1 x0) on reforme un octet byteX et un octet byteY
    // byteX pour commander le moteur et byteY le servo
    // programme effectué avec l'aide de la datasheet de l'atmenga 328P
    // Le Timer2 est utilisé pour determiner la largeur d'implusion entre front montant&descendant d'INT0 (entrée D2)
    // ainsi que pour determiner le moment ou on teste l'etat de chaque bit (on se repère dans la trame avec le timer2)
    // le Timer1 est utilisé pour le PWM du servo
    // le Timer0 est utilisé pour le PWM du moteur 
    // les variables utilisées par les ISR doivent être déclarées en volatile
    // les volatiles sont normalement codée sur 1 octets???
    // il serait necessaire de sauvegarder le SREG aprés une interruption??? (j'ai fait, mais pas tout compris)
    // ne pas utiliser le port serie ou des fonctions comme digitalWrite etc ... trop chronophage.
    
    // je suis obligé de mettre un Serial.println(); pour que le byteY soit correct et fasse fonctionner le servo correctement. 
    
    unsigned int CmptPulse = 0;
    unsigned int WildStartPulse = 0;
    
    volatile int TypeFront=0;
    
    bool xy = 0;// permet de retourner du loop dans fct_ReadBit() tant qu'on n'a pas fini la trame
    bool x7 = 0;// bit 7 de la trame à recevoir
    bool x6 = 0;// bit 6 de la trame à recevoir
    bool x5 = 0;// bit 5 de la trame à recevoir
    bool x4 = 0;// bit 4 de la trame à recevoir
    bool x3 = 0;// bit 3 de la trame à recevoir
    bool x2 = 0;// bit 2 de la trame à recevoir
    bool x1 = 0;// bit 1 de la trame à recevoir
    bool x0 = 0;// bit 0 de la trame à recevoir
    bool y7 = 0;// bit 7 de la trame à recevoir
    bool y6 = 0;// bit 6 de la trame à recevoir
    bool y5 = 0;// bit 5 de la trame à recevoir
    bool y4 = 0;// bit 4 de la trame à recevoir
    bool y3 = 0;// bit 3 de la trame à recevoir
    bool y2 = 0;// bit 2 de la trame à recevoir
    bool y1 = 0;// bit 1 de la trame à recevoir
    bool y0 = 0;// bit 0 de la trame à recevoir
    
    int i=88; // pointeur de pulse (tombe au milieu de la largeur d'implusion du premier bit x7)
    int j=0; // variable pointeur de chaque bit de la trame 16 bit (0 à 15) pour le tableau A[16]
    
    unsigned char  byteX = 0;// Octet du moteur
    unsigned char  byteY = 0;// Octet du servo
    
    int   PWMmoteur=0;
    int   PWMservo=0;
    
    //static unsigned int previousTime = 0; // static : prend la valeur 0 qu'une fois
    //unsigned int currentMillis;
    
    void setup() {
    //Serial.begin(9600); // Ouverture du port série et debit de communication fixé à 9600 bauds
    cli(); // Désactive l'interruption globale
    
    TypeFront = 1; // front montant (TypeFront==0:front descendant)
    
    
    // D2 est defini comme la PIN recevant le signal d'entrée (la trame)
    EICRA = 0b00000011; // decl INT0 sur front montant (pin D2)
    EIMSK = 0b00000001; // autorise interruption broche INT0 (pin D2)
    
    // Timer2 permet de se localisée dans la trame (2 octects)
    TCCR2A = 0b00000000; // comptage normale
    TCCR2B = 0b00000001; // fclock/1 soit 62.5ns/div soit 16 us / 256 div timer2
    
    DDRB |= 0b00000010; // D9 OUTPUT
                        // pour mettre une pin HIGH ou LOW 
                        // on joue sur DDRB et PROTB
    
    // Timer0 PWM du Moteur brushed
    TCCR0A = (1<<COM0A1) | (1<<WGM01)|(1<<WGM00); // fast PWM signal non inversé
    TCCR0B = (1<<CS02) | (1<<CS00); // fclock/1024 soit 64us/div soit 16384 us / 256 div timer0
    DDRD |=0b11010010; // D6 (OC0A signal pont en H); D7 et D4 (sens pont en H) en output TX toujour en output
    
    
    // Timer1 PWM du Servo
    TCCR1A = (1<<COM1A1) | (1<<WGM11); 
    TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11); // prescaler = fcl/8 soit 500ns/div timer 1
    ICR1 = 40000; //Période 20ms (40000x500ns)
    
    sei(); // Active l'interruption globale
    }
    
    void loop() {
    
    // currentMillis = millis();
    
    if (xy==1) { //permet de retourner du loop dans fct_ReadBit() tant qu'on n'a pas fini la trame
      
    fct_ReadBit();
    }
    /*else if ((xy==0)&&(currentMillis - previousTime >100)){ // on teste si pas de signal entrant (D2) pendant 200 ms alors on coupe les sorties
                      PORTD &= ~0b10010000; // D4 D7   mis à LOW 
                      PORTB |= 0b00100000; //D13 allumée
                      previousTime = currentMillis;
       
       }*/
    
    else{
         //rien
        }
    }
    
    int fct_StartTimer2() {
    
    //  previousTime = currentMillis;
      
      EICRA = 0b00000010; // on programme INT0 sur front descendant: interruption sur front descendant (D2)
      EIMSK = 0b00000001; // interruption autorisée
      
      TypeFront = 0; // TypeFront sur front descendant (on attend maintenant un front descendant)
    
      
      TCNT2=0; // on clear le compteur du timer2 permet de compter plus proprement (D2)  
      TIMSK2 |= 0b00000001; // autorise interruption du Timer2 
    
    }
    
    int fct_ReadBit() {
                  
           if ((WildStartPulse>800) && (WildStartPulse<1000)) { //CmptPulse fait environ 55 donc le premier pulse fait environ 55*16us 900us
               
          //      previousTime = currentMillis;
               xy=1;// permet de retourner du loop dans fct_Total tant qu'on n'a pas fini la trame
                                          
                               if (CmptPulse>1000) { // fin de la trame environ 9500us
                                                               
                                          TIMSK2 &= 0b00000000; // interdit interruption du Timer2 
                                          CmptPulse = 0;
                                          WildStartPulse = 0;
                                          i=88;
                                          j=0;
                                          TypeFront = 1; // on attend maintenant un front montant
                                          xy=0;
                                                                                                        
                                          Create_ByteX();
                                     }
    
                                 else if (CmptPulse==i){
                               //else if ((CmptPulse>i-4) && (CmptPulse<i+4)){ //
                                                                                    
                                            byte A[16];  // création du tableau pour octet XYvalue ( x7,x6...y7,y6...)
                                                             // Attention à toujours déclarer le tableau en fonction du type
                                                             // de variable qu'il contient (ici byte) si on met int A[16] 
                                                             // avec y4,y3... en byte, ça déconne
                                             A[j] = PIND & 0b00000100;
                                             A[j]=A[j]>>2; 
                                             i=i+50;
                                             j=j+1;
                                                     
                                             x7 = A[0];// bit 15 de la trame à recevoir
                                             x6 = A[1];// bit 14 de la trame à recevoir
                                             x5 = A[2];//
                                             x4 = A[3];// 
                                             x3 = A[4];// 
                                             x2 = A[5];//
                                             x1 = A[6];// 
                                             x0 = A[7];// 
                                             y7 = A[8];// 
                                             y6 = A[9];//
                                             y5 = A[10];// 
                                             y4 = A[11];//
                                             y3 = A[12];// 
                                             y2 = A[13];// 
                                             y1 = A[14];// 
                                             y0 = A[15];// bit 0 de la trame à recevoir
    
                                             
                                                   
                                     }
                                
                                else {    
                                          // retourne dans loop
                                     }
            }
            else {
                Redem_Trame();
                  }
    }
    
    int Redem_Trame() {
    
              
              TIMSK2 &= 0b00000000; // interdit interruption du Timer2 
              CmptPulse = 0;
              WildStartPulse = 0;
              i=88;
              j=0;
              TypeFront = 1; // on attend maintenant un front montant
              xy=0;
              //delay(1);
              //PORTD &= ~0b00010000; // test
             // Serial.println(byteX); 
                                       
              
    
    EICRA |= 0b00000011; // decl INT0 sur front montant (pin D2)
    EIMSK |= 0b00000001;// autorise interruption broche INT0 (pin D2)
    sei(); // Active l'interruption globale
                   
    }
    
    int Create_ByteX(){
     byteX |= (x7<<7)| (x6<<6)| (x5<<5)| (x4<<4)| (x3<<3)| (x2<<2)| (x1<<1)| (x0<<0);
     
     Create_ByteY();
     }
    
    int Create_ByteY(){
    byteY |= (y7<<7)| (y6<<6)| (y5<<5)| (y4<<4)| (y3<<3)| (y2<<2)| (y1<<1)| (y0<<0);
    //Serial.println(byteY);
    
    /*if (y6==1){ // test
      DDRD |=0b11010010; // D6 (OC0A signal pont en H); D7 et D4 (sens pont en H) en output TX toujour en output
      PORTD |= 0b00010000; // D4 HIGH (il faut DDRD a 1 et PORTD a 1)
    }
    else{
     DDRD |=0b11010010; // D6 (OC0A signal pont en H); D7 et D4 (sens pont en H) en output TX toujour en output
     PORTD &= ~0b00010000; // test 
    }*/
                                            /* y7 = 0;// 
                                             y6 = 0;//
                                             y5 = 0;// 
                                             y4 = 0;//
                                             y3 = 0;// 
                                             y2 = 0;// 
                                             y1 = 0;// 
                                             y0 = 0;// bit 0 de la trame à recevoir*/
    
    
    
    
    //Serial.println(byteX); 
    mappingXY();  
    }
     
    int mappingXY(){                                    
                                                 
                                                     
    if ((byteX<=126) && (byteX>=0)){ // marche arriere
       PWMmoteur=map(byteX,126,0,5,255); 
    }
    else if ((byteX>=128) && (byteX<=255)){ // marche avant
       PWMmoteur=map(byteX,128,255,5,255); 
    }
    else {
    PWMmoteur=3; 
    }
    
    PWMservo=map(byteY,0,255,2000,4000); // 2000 pour 1000us; 3000 pour 1500us et 4000 pour 2000us
    //Serial.println(byteY);
    
    //commande_servo();
    commande_moteur();
    
    }
    
    int commande_moteur(){
    if (byteX <= 126){     // Marche avant
      PORTD |= 0b00010000; // D4 HIGH (il faut DDRD a 1 et PORTD a 1) 
      PORTD &= ~0b10000000; // D7 LOW (il faut DDRD a 1 et PORTD a 1)
      OCR0A = PWMmoteur;
      
    }
    else if (byteX >=128 ){ // Marche arriere
       PORTD |= 0b10000000; // D7 HIGH (il faut DDRD a 1 et PORTD a 1)
       PORTD &= ~0b00010000; // D4 LOW (il faut DDRD a 1 et PORTD a 1)
       OCR0A = PWMmoteur;   
    }
    else {
      OCR0A = 3;// PWM au minimum
      PORTD &= ~0b10000000; // D7 LOW (il faut DDRD a 1 et PORTD a 1)
      PORTD &= ~0b00010000; // D4 LOW (il faut DDRD a 1 et PORTD a 1)
    }
    
    //Serial.println(byteX);
    //Serial.println(PWMmoteur);
    PWMmoteur=0;
    byteX=0;
    
    commande_servo();
    }
    
    int commande_servo(){
      
    OCR1A = PWMservo;
    PWMservo=0;
    byteY=0;
    
    
    Redem_Trame();
     
    }
    
    int Incr_Compteur(){
    CmptPulse++;  
    }
    
    int StartPulse(){
    WildStartPulse = CmptPulse * 16;  //largeur impulsion en us 
    }
    
    ISR(INT0_vect)  {  // lance routine d'interruption externe arrivé signal sur D2
    
    uint8_t reg1_sauv;
    
      sei(); // Active l'interruption globale
    
      if (TypeFront ==1) {
         fct_StartTimer2();
       }
    
      else if (TypeFront ==0){ // Front Descendant
          
        EIMSK = 0b00000000;// interdit interruption broche INT0 (pin D2)
        StartPulse();
        fct_ReadBit();
      }
     SREG=reg1_sauv ; // sauvegarde du registre
    }
    
    ISR(TIMER2_OVF_vect) { // lance routine d'interruption Timer2
      uint8_t reg1_sauv; 
      Incr_Compteur();
      SREG=reg1_sauv ; 
    }

    -----
    Dernière modification par gienas ; 13/05/2022 à 10h16. Motif: Ajout des balises code obligatoires pour les programmes. Le bonjour est AUSSI obligatoire

  2. #2
    penthode

    Re : Réception d'une trame maison

    .
    [b]le bon sens est un fardeau, car il faut s'entendre avec ceux qui ne l'ont pas [/b]

  3. #3
    galou32

    Re : Réception d'une trame maison

    Oups désolé j'ai pas dis bonjour

    Bonjour à tous

  4. #4
    jiherve

    Re : Réception d'une trame maison

    bonjour,
    rien compris et c'est illisible, l'indentation n'est pas faite pour faire joli.
    Ceci dit il faut sauvegarder SREG à l'entrée du programme d'interruption en fin c'est trop tard

    JR
    l'électronique c'est pas du vaudou!

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

    Re : Réception d'une trame maison

    Bonjour!

    En gros commentaires similaires, dans l'ordre:

    - Le programme: Quel programme?
    - On attend un front montant sur D2: C'est quoi D2?

    // On attend que le premier bit...
    Même les commentaires du code sont... comment dire .... imbitables.

    Bref, ce serait bien de situer un peu l'action. Est-ce que c'est un escalier roulant, une
    cocote minute, un sèche-cheveux à intrication quantique?

    Pascal
    Dernière modification par gienas ; 13/05/2022 à 15h38. Motif: Fermeture de la citation

  7. #6
    galou32

    Re : Réception d'une trame maison

    Bonjour,

    je fabrique un émeteur récepteur (ici le récepteur) ( sur arduino nano) capable de communiquer avec la trame ci dessus soit :

    1 bit long d environ 800us et 2 octects (1 pour le moteur nommé byteX et 1 pour le servomoteur nommé byteY). Le bit long servant à dire au récepteur: coucou vla les 2 octects.

    dans ce programme lorsque je met un "serialprintln" dans une des fonctions "int Create_ByteX() ou int Create_ByteY()" tout fonctionne si je l'enlève mon octet byteY donne n'importe quoi.

    je ne comprend pas sur quoi agit le serialprintln dans l'atmenga328P.

  8. #7
    galou32

    Re : Réception d'une trame maison

    Bonjour à tous,

    problème résolu : j'ai déplacer la déclaration de mon tableau byte A[16]; au début du programme!!! erreur de débutant mais comme je suis débutant !!

    par contre je comprend toujours pas pourquoi serialprintln me réglait ce problème!!!
    A+

Discussions similaires

  1. [Programmation] RS-485 - Mauvaise réception trame
    Par Snypp dans le forum Électronique
    Réponses: 14
    Dernier message: 02/09/2021, 18h02
  2. Envoi réception trame bus can
    Par invite92798cb8 dans le forum Électronique
    Réponses: 22
    Dernier message: 17/02/2014, 15h33
  3. Réception de trame via un microcontroleur
    Par invitecd6742e1 dans le forum Programmation et langages, Algorithmique
    Réponses: 4
    Dernier message: 08/12/2013, 12h38
  4. PIC18F et reception de trame d'un DCF77
    Par Thienou dans le forum Électronique
    Réponses: 18
    Dernier message: 24/11/2012, 18h47
  5. Reception trame avec un PIC
    Par flyingrock dans le forum Électronique
    Réponses: 9
    Dernier message: 28/09/2010, 03h19
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...