[Programmation] tableau et envoi rs232
Répondre à la discussion
Affichage des résultats 1 à 13 sur 13

tableau et envoi rs232



  1. #1
    furz

    tableau et envoi rs232


    ------

    Bonjour,
    J'ai un sujet de stage sur lequel je doit programmer une carte avec un µC PIC16F1788. (programmation avec mikroC)

    un de mes objectif est de faire de l'acquisition analogique du traitement et de l'envoie sur le port serie

    j'ai commencé par faire de la lecture analogique et envoie du code binaire sur des LED ==> fonctionnement OK
    Ensuite j'ai fait l'envoie sur la liaison serie ==> OK

    Pour finir j'ai essayé d'ecrire la fonction suivante
    Code:
    unsigned int tab[] = {100, 100, 100, 100};
    
    int maFonction( int tab[], int taille){
       int i;
       int moy;
       int sum = 0;
       for (i = 0; i < taille; ++i) {
          toto=tab[i];  //  ==> PB ne lis pas les valeurs du tableau (il lis " 0")
          sprintf(text, "%d", toto);  /// convertie en texte
          UART1_Write_Text(text); // envoie sur la liaison serie
          sum = sum + tab[i];
         moy = sum / taille;
    
       return moy;  
       }
    
    void main() {
      UART1_Init(9600);               // Initialize UART module at 9600 bps
      Delay_ms(100);                  // Wait for UART module to stabilize
     while (1) {                     // Endless loop
    
      toto=tab[2];  // ====> lis correctement  la case du tableau
      sprintf(text, "%d", toto);
      UART1_Write_Text(text);
      maFonctiont(tab[4],4);
    
      Delay_ms(1000);
    
      }
    }
    à terme je veux rajouter un paramètre "voie à mesuré" , et la fonction renverra un tableau qui servira à alimenté ma fonction .
    Mon tableau contiendra en première case la moyenne des échantillions lu, et en dernière case un indice de pointeur afin que ma fonction puisse réécrire dans l'espace mémoire le plus ancien sans avoir besoin de faire un décalage du tableau.
    malheureusement vu que la première partie de mon code ne fonctionne pas sans que je puisse savoir pourquoi, je suis gêné pour la suite.

    Auriez vous une idée qui me permettrai de savoir pourquoi je n'arrive pas à lire le tableau à l'intérieur de ma fonction et des conseils pour parvenir à réalisé ma fonction ?


    Merci d'avance

    -----

  2. #2
    Seb.26

    Re : tableau et envoi rs232

    ton parametre porte le même nom que ta variable globale ... et le paramètre est prioritaire ... renomme ton parametre et ce sera ok ...

    -> je ne fais pas de commentaires sur la forme


    Code:
    int maFonction( int tab[], int taille){
    ...
    maFonctiont(tab[4],4);
    si ton compilo accepte ça sans broncher, il faut en changer !
    Dernière modification par Seb.26 ; 03/05/2023 à 16h40.
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  3. #3
    Murayama

    Re : tableau et envoi rs232

    Bonjour!

    je ne fais pas de commentaires sur la forme
    Bon, alors je vais m'attacher un peu à la forme.

    un de mes objectif est de faire de l'acquisition analogique du traitement et de l'envoie
    sur le port serie
    Déjà là, on ne comprend rien. Pas à cause de l'orthographe, mais à cause de la formulation.
    Faire de l'acquisition analogique, jusque là, je comprends.
    Acquisition analogique du traitement: traitement de quoi?
    Vous voulez acquérir un signal et l'envoyer sur le port série? C'est possible, mais
    il ne faut pas aller trop vite, à 9600 bps, vous ne pouvez envoyer que (environ)
    1 k byte par seconde. Ceci dit, votre programme a un délai de 1 s dans la boucle,
    ça devrait aller.

    à terme je veux rajouter un paramètre "voie à mesuré",
    Vous parlez d'ajouter, ce qui laisse supposer que le gros du programme fonctionne déjà.
    J'ai bon?

    et la fonction renverra un tableau qui servira à alimenté ma fonction .
    "La fonction": quelle fonction?
    servira à alimenté ma fonction: "Ma fonction", c'est celle que vous avez appelée
    "maFonction"?

    malheureusement vu que la première partie de mon code ne fonctionne pas sans que je
    puisse savoir pourquoi, je suis gêné pour la suite.
    Nous y voilà. Donc avant d'ajouter du code, concentrez-vous sur la première partie.
    Ce qui pourrait commencer par poser le problème avec un peu plus de rigueur.

    Je commence:
    - Vous échantillonnez un signal analogique, et l'ADC remplit un tableau que j'appellerai
    AData[] pour Analog Data.
    - Il est toujours bon, surtout en électronique embarquée, d'utiliser des variables
    dont on connaît la taille. Je ne sais pas ce qu'est un int pour le PIC, alors je vais
    utiliser uint16 qui est un entier 16 bits non signé, suffisant pour stocker les
    données du PIC.

    Ensuite que voulez-vous faire des données?
    Les envoyer par port série sur un terminal et les recevoir sur un PC?

    D'autre part dans votre code, c'est le bordel absolu.
    - Vous définissez une fonction fourre-tout qui calcule une moyenne tout en envoyant
    chaque valeur.
    - Dans votre main, vous lisez la case 2 (allez savoir pourquoi seulement celle-là),
    puis vous l'imprimez (chose qui est déjà faite dans maFonction que vous appelez ensuite).
    - maFonction calcule une moyenne que vous n'utilisez jamais.
    - Comme dit plus haut, appeler maFonctiont(tab[4],4); a des chances d'être jeté par
    le compilateur. La raison est que maFunction prend un tableau et une taille, et vous
    lui donnez à manger un nombre (tab[4]) et une taille. De plus, votre tableau est
    déclaré unsigned, et maFonction prend un tableau de int qui par défaut sont signés.
    - J'ai bien compris que vous n'utilisez pas l'ADC pour le moment et que ceci est un
    test. Alors pour un test, si vous voulez par exemple calculer une moyenne, il serait
    bon d'utiliser des nombres différents, histoire de vérifier. Par exemple
    tab[] = {85, 102, 144, 29}. De cette façon, en avançant pas à pas au débugger,
    vous pouvez voir quel élément est imprimé dans la variable text (qui par ailleurs
    n'est pas déclarée. Le compilateur ne donne pas d'erreur genre text: undeclared
    variable ou unknown in this context?).
    - Encore un conseil de base: utilisez des noms de variables explicites. Tab n'en est
    pas un. AData comme je l'ai suggéré est mieux, mais à la limite analog_data, c'est
    encore mieux. Et si on connaît la nature des données, par exemple temp_data pour
    temperature, ou pressure_data si c'est une pression, ce serait le top. Pareil pour
    les fonction: maFonction ne veut rien dire. Si vous relisez votre code dans 2 mois,
    vous serez perdu.

    Conclusion:
    - Apprenez à expliquer ce que vous voulez faire
    - Avancez pas à pas, et n'allez au pas suivant que si tout fonctionne sans erreur
    ni warning.
    - Accessoirement, consulter de temps à autre un dictionnaire et un Bescherelle ne
    gênerait pas. Pour l'aspect ludique, je vous conseille la grammaire impertinente.
    https://www.fnac.com/a163397/Jean-Lo...t-impertinente

    Pascal

  4. #4
    furz

    Re : tableau et envoi rs232

    @ Seb.26 : Là n'était pas le problème, j'ai fais la modification mais la source de mon problème sur cette partie a été corrigé par le code suivant
    Code:
    int maFonction( int *tab, int taille){
    @Murayama :
    Je ne voulais pas vous perdre dans les détails, je voulais juste expliquer le concept en précisant que la fonction allais réaliser d'autre chose (et elle sera utilisé 7 fois dans le programme principal d'où l'intérêt de la réaliser, voici rapidement ses fonctions.
    - Acquisition voieX et enregistrement dans le tableau (décalage successif de la position en fonction de la valeur dans en tab[0]
    - Pause du traitement tant que N acquisition n'a pas été réalisé (enregistrement en tab[1])
    - (traitement) => calcul de la valeur moyenne des N dernière acquisition
    - Comparaison et enregistrement en eeprom des valeurs min et max
    - Basculement de tab[3] à "1" si la valeur attend certain seuil
    - Comptage du temps pendant lequel il à déplacer seuil sur tab[4]
    - Enregistrement du temps max de dépassement dans Eeprom
    - La fin du tableau contient les N échantillions

    Je n'ai pour le moment pas réalisé ses étape car j'y vais pas à pas,
    l'envois en RS232 ne fais pas partie de ma fonction mais est prévu dans une autre partie. Je me sert de la liaison pour testé mon programme, c'est grâce à elle que j'ai vu qu'a l'intérieur de ma fonction je n'arrivais pas à lire les valeur de tab alors qu''a l'extérieur j'y arrivais. (j'ai fais le test car j'avais des valeurs erroné)

    Le reste du programme n'est pas encore réalisé, j'ai pour le moment juste vérifié que j'arrivais à lire une entrée analogique correct, j'ai également fais un mapping des données que je voulais sauvegardé en Eeprom pour être sur que je ne dépasse pas le nombre de bit du µC

    Vous avez entièrement raison sur la déclaration de text je l'avais bien déclaré mais j'ai oublié de le mettre dans le code fournie (mon but étant de vous épargné les partie poubelle et fonction partie annexe qui ne servent à rien.
    Je retiens également le faite qui faut que je change la déclaration de ma fonction en unsigned.
    Je retiens également le faite qu'il faut que je sois plus explicite sur le nom de mes fonctions et vous remercie pour ce rappel.

    PS merci de laisser se poste ouvert au moins une semaine car je suis pas encore à l'abris d'avoir d'autre soucis sur ce sujet,(j'espère que non)

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

    Re : tableau et envoi rs232

    Bonjour!

    Je ne voulais pas vous perdre dans les détails, je voulais juste expliquer le concept
    en précisant que la fonction allais réaliser d'autre chos
    Pour tout dire, je suis perdu même par le concept lui-même.

    - Acquisition voieX et enregistrement dans le tableau (décalage successif de la position
    en fonction de la valeur dans en tab[0]
    Dès ce point, ce n'est pas clair. C'est quoi la voie x, exactement? Une des entrées
    de l'ADC du pic?

    Bref, si vous voulez faire quelque chose qui fonctionne:
    - Écrivez une fonction qui lit l'ADC. Appelez cette fonction Acquisition ou n'importe
    quoi d'autre du genre, mais pas maFonction.
    - Dans un premier temps, si vous ne savez pas lire l'ADC, vous pouvez faire une fausse
    fonction d'acquisition. Suggestion: (NB: je ne suis pas certain que ce soit le but, mais
    comme expliqué auparavant, je ne comprends pas ce que vous écrivez).

    Code:
    void Acquisition(uint16 * data, uint16 length) {
        uint16 i;
        for(i = 0 ; i < length ; +=i) {
            *(data+i) = 2048 + rand() % 512; // Génère un bruit centré en 2048, d'amplitude 512
        }
    }
    //    Ensuite, faites une fonction pour la moyenne:
    uint16 Average(uint16 * data, uint16 length) {
        uint16 i;
        uint32 accu = 0;    //    Accumulator to calculate the sum
        for(i = 0 ; i < length ; +=i) {
            accu += *(data+i);
        }
        accu /= length;    //    NB: use divide, never use a shift!!!
        lifecount++;
        return (uint16) accu;
    }
    void send_val(uint16 val) {
        char text[0x40];
        sprintf(text, "Average[%05d] = %5d\n", lifecount, val);
        UART1_Write_Text(text);
    }
    //    Et puis si on peut avoir une fonction init qui prend peu de place et s'occupe
    //    de tout...
    void uart_init() {
        UART1_Init(9600);
        Delay_ms(100);        //    Tant qu'à faire, le délai a toute sa place dans l'initialisation
    }
    //    Votre programme principal devient:
    #include "tout_c_qu_y_faut.h"
    #define SIZE 100    //    Ou tout ce que vous voulez d'autre
    uint16 voie_x_data[SIZE];
    uint16 lifecount;    //    Pour être sûr qu'il n'y a pas de ratage de données
    
    void main(void) {
        uint16 avg;
        lifecount = 0;
        uart_init();
        //    Pas de délai ici, il est déjà dans uart_init();
        while(1) {
            Acquisition(voie_x_data, SIZE);        //    Acquisition des données
            avg = Average(voie_x_data, SIZE);    //    Traitement
            send_val(avg);                        //    Envoi du résultat
            delay(1000);
        }
    }
    Règles à observer:
    - Pas plus d'une action par fonction. Cela rend le code réutilisable. Exemple:
    Recueillir des données analogiques dans un tableau pourra toujours resservir
    avec très peu de modifications.
    Recueillir des données et envoyer par UART, probablement jamais. Donc séparez
    ces fonctions.
    - Jamais de fonction longue. Si une fonction est longue, c'est qu'elle est ratée.
    Long, c'est assez subjectif, mais c'est l'idée. Disons que la fonction doit pouvoir
    entrer dans une page sur votre écran, donc être intégralement dans votre champ
    de vision. Si ça dépasse, ce sera moins lisible.
    - Si vous travaillez en C++, jamais plus d'une définition d'objet par fichier.
    - Ah oui, un mot sur lifecount: ça sert à voir si le programme ne s'est pas coincé
    quelque part. Parfois avec 2 valeurs. L'une incrémentée à l'acquisition, l'autre au
    traitement. Si elles diffèrent, c'est qu'il y a une couille dans le piano.

    Au fait, vous êtes germanophone, ou bien votre identificateur est un pur hasard?

    Pascal

  7. #6
    Seb.26

    Re : tableau et envoi rs232

    [HS]
    Code:
    accu /= length;    //    NB: use divide, never use a shift!!!
    what ??!!?
    -> moi justement je dirais de jamais faire de div et toujours des décalages (donc lissage sur 2, 4, 8, 16... valeurs)
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  8. #7
    furz

    Re : tableau et envoi rs232

    voila je commence à avoir quelque chose qui commence à fonctionné comme je le souhaite.
    Le gros de mon problème étant l'usage des pointeurs que je ne maitrise pas.

    je suis plutôt d'accort avec Seb.26 sur les décalages car cela utiliserais moins de ressource (même si je ne l'ai pas appliqué)

    en ce qui concerne mon programme il est encore perfectible (découpe en fonction supplémentaire , modification de nom de certaine variable ....), en revanche je fait le choix de voir cela un peu plus tard car j'ai d'autre fonction à implémenté concernant le traitement

    En ce qui me concerne je réalise une moyenne flottante donc j'enlève la variable la plus vielle et la remplace par une plus récente, de plus je ne fait une moyenne que lorsque j'ai suffisamment d'échantillions (pour le moment je ne l'ai pas mise dans une fonction average )
    Code:
     #define TAILLE_MOYENNAGE 4
     #define VARIABLE_SUPPL_TABLEAU 4          //  Variable pointeur , Variable moyenne, Variable defauft , temps
     #define ENTREE_ANALOGUE_RA0 0
    unsigned int aqui;
    unsigned int uart_rd;
    unsigned int TabM1[TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU]={0};
    unsigned int TabM2[TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU]={0};
    unsigned int moy;
    int *pointeurMesure_1;
    int k;
    unsigned int toto;
    char text[20];
    
    void InitUART(){
      UART1_Init(9600);               // Initialize UART module at 9600 bps
      Delay_ms(100);                  // Wait for UART module to stabilize
      UART1_Write_Text("Start");
      UART1_Write(10);
      UART1_Write(13);
      }
    
    void EnvoiUART(int *donnee,int DebutLectureData , int FinLectureData){ // Envois les données du tableau entre DebutLectureData et DebutLectureData tout deux comprit
        int iNbdata=0;
        for (iNbdata = DebutLectureData; iNbdata <  FinLectureData ; ++iNbdata) {
            sprintf(text, "%d", donnee[iNbdata]);
            UART1_Write_Text(text);
            UART1_Write_Text(" ");
        }
    }
    
    int *MesureDetectionEnregistrement(int InADC, int *tab, int taille){
       int i;
       int moy;
       int sum = 0;
       int pointeur = tab[0];
       aqui = ADC_Read(InADC);
       tab[VARIABLE_SUPPL_TABLEAU+pointeur]=aqui;
       // incrémentation pointeur
       if (pointeur < TAILLE_MOYENNAGE-1){
          tab[0]= pointeur +1; }
       else {
            tab[0]=0;}
    
       tab[1]++; // incrementation Nb acquisition
       if (tab[1]>TAILLE_MOYENNAGE){ // pause traitement temps que Nb acuisition < Nb valeur moyenné
         for (i = VARIABLE_SUPPL_TABLEAU; i < taille ; ++i) {
            sum = sum + tab[i];
         } 
         moy = sum / taille;
         tab[2]=moy;
       }
    
    
       return tab;
    }
    
    
    void main() {
      void ADC_Init();
      osccon = 0X72;
      ANSELA  = 0b11110100;
      trisb = 0X00;
      InitUART();
      
      while (1) {                     // Endless loop
    
      pointeurMesure_1=MesureDetectionEnregistrement(ENTREE_ANALOGUE_RA0,TabM1,TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU);
      EnvoiUART(pointeurMesure_1,0, TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU);
      UART1_Write_Text("\r");
      Delay_ms(5000);
      }
    }
    PS furz= Faire Une Remise à Zero , je sais que dans certain pays sa sens mauvais
    Dernière modification par furz ; 04/05/2023 à 14h40.

  9. #8
    Murayama

    Re : tableau et envoi rs232

    Bonjour!


    À propos du shift / divide.


    moi justement je dirais de jamais faire de div et toujours des décalages (donc lissage sur 2, 4, 8, 16... valeurs)

    Oui, ça marche très bien à condition:
    - que le diviseur soit une puissance de 2.
    - que le diviseur soit une constante. (ce n'est pas le cas ici, length est paramètre d'une fonction).

    En ce qui me concerne et pour paraphraser Cyrano j'au deux raisons dont chaque est suffisante seule.


    1. N'importe quel compilateur récent le fait de lui-même à condition que ce soit une
    constante. J'ai vérifié sur STM32 et MSP430. Pas encore sur PIC ou Atmel, mais je ne
    les utilise quasiment jamais. J'ai retenu d'une discussion que les compilateurs
    PIC et ATMEL le font aussi.


    2. Dans ce contexte, le shift ne peut pas fonctionner. Length n'est pas une
    constante mais une variable, paramètre de la fonction. Mais dans ce cas, il faudrait
    non pas length, mais length_bits = log2(length). Ou alors le calculer avec une
    boucle, ce qui perdrait du temps (while (1<<length_bits) < length) length_bits++.
    Ce qui potentiellement peut causer un bug si un mec non averti reprend le code
    et modifie length sans savoir qu'il doit impérativement être une puissance de 2.
    Autre solution, passer length_bits comme paramètre et itérer de 0 à (1 << length_bits)-1.


    Pascal

  10. #9
    Seb.26

    Re : tableau et envoi rs232

    Citation Envoyé par Murayama Voir le message
    Bonjour!
    À propos du shift / divide.
    [...]
    Pascal
    Alors on est d'accord
    << L'histoire nous apprend que l'on apprend rien de l'histoire. >>

  11. #10
    furz

    Re : tableau et envoi rs232

    Bonjour,
    vraisemblablement j'ai des souci avec les pointeurs ou l'utilisation des type.
    j'ai voulut passer mon tableau en char signed ( au final je mesure que des écart par rapport une référence donc des nombres entre -128 et +127 me suffise)
    mais rien ne va plus et je n'arrive plus à afficher mes valeur
    Code:
    #define TAILLE_MOYENNAGE 4
    #define VARIABLE_SUPPL_TABLEAU 4          //  Variable pointeur , Variable moyenne, Variable defauft , temps
    #define ADC_RA0 0 //11V
    
    // CENTRAGE_ADC correspond a la valeur que l'ADC devrait retourner pour chaque valeur de tension attendu
    #define CENTRAGE_ADC_RA0 3600 //11V   => 4,3957 V  sur l'entrée =>  3600
    
    //COEF permetant de convertir la valeur lu en ecart par rapport à la valeur central
    // écart = Octet signé centré sur la valeur de référence et résolution de 250mV pour les tensions de 60V et 120V 120V (+/-32V de la tension de référence )
    // ecart = Octet signé centré sur la valeur de référence et résolution de 50mV pour les autres tensions (+/-6,4V de la tension de référence )
    // formul d'obtention du Coef =(64*résolution*VrefADC)/( Facteur de divition du pont diviseur * resolutionADC)  ; 64 = mutiplicateur permetant de travailler avec des entiers
    // formul d'utilisation  écart= ( valeur_lu - CENTRAGE_ADC_ )*64 /  COEF_ADC_  ;  enregistrement en  en char singne
    #define COEF_ADC_RA0 1047 //11V   => (64*0,05*5) / (  2,5024455718088 * 4095)
    
    signed char TabRA0[8]={0};
    signed char *TabMesure_RA0=TabRA0 ;
    
    signed char text[20];
    
    void InitUART(){
      UART1_Init(9600);               // Initialize UART module at 9600 bps
      Delay_ms(100);                  // Wait for UART module to stabilize
      UART1_Write_Text("Start");
      UART1_Write(10);
      UART1_Write(13);
      }
    void EnvoiUART( char *donnee,char DebutLectureData , char FinLectureData){ // Envois les données du tableau entre DebutLectureData et DebutLectureData tout deux comprit
        int iNbdata=0;
        for (iNbdata = DebutLectureData; iNbdata <  FinLectureData ; ++iNbdata) {
            sprintf(text, "%d", donnee[iNbdata]);
            UART1_Write_Text(text);
            UART1_Write_Text(" ");
        }
    }
    
    
    
    char *MesurerEtConvertir(char InADC, char *tab,int ref,int coef_ADC){  // tab={ pointeur , Nb aquit , moy , depacement ,  donnee[0] ,donnee[1],donnee[2],donnee[3], ...}
       signed char i;
    
       signed int sum = 0;
       signed char pointeur = tab[0];
       signed int aqui;
       signed char resultat;
       aqui = (ADC_Read(InADC)-ref)<<6; // ecart en bit *64
       tab[VARIABLE_SUPPL_TABLEAU+pointeur]= aqui / coef_ADC; // ecart en tension (0,250V ou 0,05V par unité)
       // incrémentation pointeur
       if (pointeur < TAILLE_MOYENNAGE-1){
          tab[0]= pointeur +1; }
       else {
            tab[0]=0;}
    
       tab[1]++; // incrementation Nb acquisition
       if (tab[1]>TAILLE_MOYENNAGE){ // pause traitement temps que Nb acuisition < Nb valeur moyenne
         for (i = VARIABLE_SUPPL_TABLEAU; i < (TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU) ; ++i) {
            sum += tab[i];
         }
         tab[2]=sum / (TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU);     // enregistrement moyenne
       }
       return tab;
    }
    
    
    void main() {
      void ADC_Init();
      osccon = 0X72;
      ANSELA  = 0b11110100;
      trisb = 0X00;
      InitUART();
    
      while (1) {                     // Endless loop
    
      TabMesure_RA0=MesurerEtConvertir(ADC_RA0,TabMesure_RA0, CENTRAGE_ADC_RA0,COEF_ADC_RA0);
    
      EnvoiUART(TabMesure_RA0,0, TAILLE_MOYENNAGE+ VARIABLE_SUPPL_TABLEAU);
      UART1_Write_Text("\r");
      Delay_ms(5000);
      }
    }
    normalement je devais obtenir ca avec des valeurs comprise entre -128 et +127
    Code:
    1 1 0    0  X  0  0  0
    2 2 0    0  X  Y  0  0
    3 3 0    0  X  Y  Z  0
    0 4 M1  0  X  Y  Z  A
    1 5 M2  0  B  Y   Z  A
    2 6 M3  0  B  C  Z  A
    3 7 M4  0  B  C  D  A
    0 8 M5  0  B  C  D  E
    mais j'ai plutôt le résulta suivant
    Code:
    Start
    
    1025 1025 1024 1024 1252 1024 1024 1024 
    1026 1026 1024 1024 1252 1252 1024 1024 
    1027 1027 1024 1024 1252 1252 1252 1024 
    1024 1028 1024 1024 1252 1252 1252 1252 
    1025 1029 1138 1024 1252 1252 1252 1252 
    1026 1030 1139 1024 1252 1263 1252 1252 
    1027 1031 1114 1024 1252 1263 1054 1252 
    1024 1032 1089 1024 1252 1263 1054 1054 
    1025 1033 1065 1024 1054 1263 1054 1054 
    1026 1034 1039 1024 1054 1054 1054 1054 
    1027 1035 1039 1024 1054 1054 1054 1054 
    1024 1036 1039 1024 1054 1054 1054 1054
    en gros décalage de 1024 sur l'ensemble + décalage de 127 ou 128 la ou je place mes valeurs

  12. #11
    furz

    Re : tableau et envoi rs232

    j'ai aussi fait un test de lecture de mon tableau pour afiché toto si ok mais ca me change les valeurs
    Code:
      TabMesure_RA0=MesurerEtConvertir(ADC_RA0,TabMesure_RA0, CENTRAGE_ADC_RA0,COEF_ADC_RA0);
      if  (TabMesure_RA0[3]==0 ){   UART1_Write_Text("toto");}
    voila le résulta qui m'est entièrement obscure
    Code:
    Start
    
    toto1 257 768 768 798 768 768 768 
    toto770 770 768 768 798 798 768 768 
    toto771 771 768 768 798 798 798 768 
    toto768 772 768 768 798 798 798 798 
    toto769 773 783 768 798 798 798 798 
    toto770 774 783 768 798 798 798 798 
    toto771 775 783 768 798 798 798 798 
    toto768 776 783 768 798 798 798 798 
    toto769 777 783 768 798 798 798 798

  13. #12
    Murayama

    Re : tableau et envoi rs232

    Bonjour!

    vraisemblablement j'ai des souci avec les pointeurs ou l'utilisation des type.


    Vraisemblablement oui, ça doit jouer.

    Bon, je ne vais pas passer de temps à vous réexpliquer, mais il faut faire une chose
    à la fois et ne pas passer à la chose suivante tant que l'étape actuelle n'est pas validée.
    Je ne suis pas certain que vous m'ayez lu / compris.
    Et aussi (bis repetita placent): UNE FONCTIONALITE PAR FONCTION!!!!

    La fonction mesureretconvertir, rien que par le titre, c'est déjà mal parti, elle fait plusieurs choses.
    Donc commencez par écrire une fonction qui mesure et ne fait rien d'autre (elle n'envoie
    rien à l'UART, elle ne calcule pas de moyenne, elle ne convertit pas, elle mesure, point barre).
    Donc cette fonction mesure et produit un tableau de données.
    Testez cette fonction: mettez une entrée analogique (par exemple un potentiomètre), vérifiez
    que quand le potard est à fond, vous avez des valeurs proches de 3.3V ou 5V (ou disons une
    valeur de 1023 puisque je crois que le PIC est à 10 bits), et quand il est proche de 0,
    vous avez des valeurs quasi nulles. N'envoyez rien à l'UART puisque vous savez qu'il fonctionne.
    Vérifiez au debugger les valeurs lues.
    N'entreprenez rien d'autre tant que cela ne fonctionne pas.

    Ensuite, si les données du tableau ne sont pas au format qui vous arrange, faites une
    fonction Convertir qui fera ce qu'il faut, c'est à dire la conversion, mais ne fera que cela
    et rien d'autre. Vérifiez au debugger et modifiez jusqu'à ce que ça marche.
    Mettez un point d'arrêt au début de cette fonction, avancez pas à pas.
    Tant que vous n'avez pas exactement ce que vous souhaitez, ne faites rien d'autre.

    Code:
    #define TAB_SIZE 4 // pour être compatible avec votre tableau qui avait 4 cases.
    
    uint16 tab[TAB_SIZE];
    
    void Measure(void) {
        uint16 i;
        uint16 val;
        for(i = 0 ; i < TAB_SIZE; ++i) {
            val = ReadADC();
            tab[i] = val;
        }
    }
    
    void main(void) {
        ADC_Init();
        while(1) {
            Measure();
            Delay(100);
        }
    }
    NB: si le prochain code est plus long que cela, ou si vous écrivez encore une fonction
    fourre-tout qui fait tout et n'importe quoi, je vous conseille de trouver quelqu'un d'autre
    pour vous guider.

    Sinon, il est impossible que la sortie que vous montrez corresponde au code que vous publiez.
    La raison que dans le code, si je cherche "toto", je trouve un unsigned int et rien ailleurs.
    Donc si vous l'imprimez dans text, vous aurez la valeur contenue dans toto (un entier) mais
    pas "toto". En plus, vu que cette variable n'est pas utilisée ailleurs, toto contient n'importe quoi,
    au mieux 0, au pire une valeur aléatoire.

    Donc si en plus le code ne correspond pas, je ne vois pas comment on pourrait vous aider.

    D'autre part, je ne sais pas pour les autres lecteurs, mais je n'ai pas encore compris ce que
    vous voulez faire. Ce que j'ai compris (ce sera court) :
    - Vous voulez échantillonner un signal analogique
    - Vous voulez faire une moyenne
    - Vous voulez envoyer quelque chose sur l'UART, mais je ne sais pas quoi.
    Ce serait bien de l'écrire d'abord en français. Un problème bien posé est à moitié résolu.

    Pascal


    Dernière modification par Murayama ; 06/05/2023 à 07h07.

  14. #13
    Murayama

    Re : tableau et envoi rs232

    Re!

    J'en remets une petite couche sur les pointeurs avant d'aller manger...

    Un pointeur, c'est une adresse quelque part dans la mémoire du processeur.
    Par exemple si vous déclarez un tableau:
    uint16 tab[0x100];
    Le compilateur va prévoir un espace de 256 nombres de format uint16, donc 512 bytes
    quelque part dans la mémoire. Par exemple si l'espace mémoire RAM du processeur commence
    à 0x2000, le compilateur peut réserver à sa convenance un espace qui commence à une
    certaine adresse, par exemple 0x20C4, et tout l'espace qui suit (donc jusqu'à 0x22C3
    inclus) est réservé pour tab.
    La valeur de tab est donc 0x20C4. Tab est un tableau, c'est statique. Mais vous pouvez
    déclarer un pointeur qui se ballade sur ce tableau.
    Par exemple uint16 * ptr = tab; // ptr est sur le début du tableau et dans notre exemple, il vaut 0x20c4.

    Attention: l'arithmétique des pointeurs est un peu particulière:
    tab = 0x20C4
    MAIS: tab+1 = 0x20C6 et non 0x20c5 comme on pourrait s'y attendre. La raison est que
    tab est un tableau de paquets de 2 bytes. Le paquet suivant est donc 2 bytes plus loin.
    Si c'étaient des uint32, ce serait 4 bytes plus loin.
    Attention: il est déconseillé de faire bouger tab qui est statique. Il vaut mieux non pas
    écrire tab+1 comme ci dessus, mais déclarer un pointeur comme suit:

    Quand vous voulez écrire dans votre tableau, vous pouvez vous servir d'un pointeur.
    Ex pour remplir votre tableau.

    Code:
    // On va supposer que tab, dans la mémoire, commence à 0x20C4 comme ci-dessus
    // On initialise un pointeur sur le tableau.
    uint16 * ptr = tab;              // Là, ptr vaut 0x20c4
    for(i = 0 ; i < TAB_SIZE ; ++i) {
        *ptr++ = ADCRead();          // À i = 0, on va mettre à l'adresse ptr le résultat de la lecture de ADC.
                                     // Puis on va incrémenter le pointeur de 1 cran, il vaut maitenant 0x20c6 comme expliqué plus haut
                                     // Et on va lire une 2ème valeur pointée par ptr qui est maintenant l'adresse de tab[1].
                                     // Et ainsi de suite. Le pointeur va pointer successivement sur tab[2], tab[3] .... tab[TAB_SIZE-1]
                                     // en prenant à chaque fois une valeur de l'ADC. 
    }
    
    Et si vous voulez calculer la moyenne:
    uint16 * ptr = tab;
    uint32 accu = 0;                 // 32 bits pour ne pas que l'accu déborde.
    for(i = 0 ; i < TAB_SIZE ; ++i) {
        accu += *ptr++;              // Ajoute le contenu de la mémoire à l'adresse ptr, puis incrémente cette adresse. (voir plus bas, (1))
    }
    accu /= TAB_SIZE;                // Calcul de la moyenne.
    En bref, un tableau et un pointeur sont de même nature. Si vous avez une fonction func(uint16 * param),
    vous pouvez tout aussi bien appeler func(tab) ou func(ptr), le compilateur ne va pas broncher.
    Un tableau est statique, c'est un espace mémoire. Et un pointeur, c'est juste une position quelque part
    dans la mémoire.
    En fait, on peut faire un parallèle avec en maths un point et un vecteur. Dans le plan, l'un et l'autre
    ont 2 coordonnées. Ce n'est pas la même chose, mais en même temps, le point M et le vecteur OM
    ont les mêmes coordonnées.
    De la même façon, tab et ptr, ce n'est pas la même chose, mais si vous affectez ptr = tab, alors
    ptr et tab représentent la même chose.

    Pascal

Discussions similaires

  1. Réponses: 6
    Dernier message: 07/04/2015, 18h04
  2. Envoi image sur liaison RS232
    Par invite62091fda dans le forum Électronique
    Réponses: 5
    Dernier message: 11/07/2014, 08h33
  3. envoi d'une trame sous rs232
    Par invitec31c0e28 dans le forum Programmation et langages, Algorithmique
    Réponses: 4
    Dernier message: 23/03/2011, 10h21
  4. envoi tram rs232 a pic18f4550
    Par invitea41ba67c dans le forum Électronique
    Réponses: 0
    Dernier message: 01/06/2010, 09h34
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...