IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Traitement du signal Discussion :

Application OSCILLOSCOPE avec WIN32 API


Sujet :

Traitement du signal

  1. #1
    Membre averti
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Par défaut Application OSCILLOSCOPE avec WIN32 API
    Bonjour,
    Supposant un tableau de données receuilli d'un convertisseur A/N (CAN) d'une résolution de 12bits et avec Vref = 3.3V.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define sample_count  1024
    uint16_t data[sample_count];
    J'arrive à tracer le graphe du signal en utilisant WIN32 API.
    Je voudrais savoir, SVP, comment ajouter les options suivantes:
    1- time/Div
    2- Trigger avec choix de front mont/desc.
    3- Volt/div
    4- calcul de la fréquence et la valeur pic à pic.
    Merci

  2. #2
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 646
    Par défaut
    Bonjour,

    Où est le code ? Deux déclarations, c'est un peu court.

    1. Time/div
    C'est quoi le problème ? Tracer le graticule ? Il y a un CAN de 12 bits pour 3.3V. Ce CAN a également une fréquence d'échantillonnage, fech par exemple, et donc un temps entre 2 échantillons Tech = 1 / fech. Une division correspond à n échantillons donc à n*Tech. En général, on fixe n pour avoir un temps/division plus lisible par exemple de 0.5 ms/div, 1 ms/div etc.
    2. Trigger
    Comment est tracé le graphe ? Le premier élément est déterminé comment ? Si c'est un seul tracé, il n'y a pas de problème, mais si le signal est rafraichi régulièrement, il faut un point de déclanchement (au minimum seuil et sens de passage du seuil) pour que les divers tracés visuellement se superposent approximativement et restent ainsi lisibles. L'utilisation de sensiblement plus d'échantillons que ceux visualisés (par exemple le double) et/ou le bon usage d'un tampon circulaire, permettent de voir également les échantillons précédent le déclenchement.
    3. Volt/div
    Mêmes questions que pour Time/div. Chaque division représente un nombre v de niveaux et chaque niveau vaut 3.3V/212.
    4. Calcul de la fréquence et la valeur pic à pic.
    La fréquence fondamentale vaut 0 Hz (nous sommes avec des entiers non signés). La fondamentale superposée se trouve en retirant la valeur moyenne (ce qui implique de passer de non signé à signé) et en regardant les passages par 0 (simple pour les formes d'onde régulières. Le valeur pic à pic est simplement la différence entre le max et le min du signal.

    Salutations

  3. #3
    Membre averti
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Par défaut
    Merci Guesset pour tes éclaircissements.
    Je simule les données de l'ADC par code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (int i= 0; i < data_length; i++) {
            data[i] = uint16_t((sin(2.0 * PI * i * (frequency  / sample_rate)) + 1.0) * 2048); 
    }
    les échantillons sont centrés autour 2048.
    Trcer le graticule c'est pas un problème. Pour tracer le graphe je commence par le 1er élement du tableau:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (int i = 1; i < sample_count; i++) {
            MoveToEx(hdc, i-1, HEIGHT/2 + (MAX_AMPLITUDE/30 - (data[i-1]/15)), NULL);
            LineTo(hdc, i, HEIGHT/2 + (MAX_AMPLITUDE/30 - data[i]/15));
    }
    Où MAX_AMPLITUDE = 4095 et HEIGHT = 500 (hauteur de l'écran en pixels).
    Oui le graphe doit être rafraichi régulierement en utilisant un timer.

  4. #4
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 646
    Par défaut
    Bonjour,

    Pour que la simulation soit plus proche de la réalité (sans trig, la phase de tracé n'est pas a priori constante), il faudrait que chaque point (et non seulement la courbe) soit généré à l'intérieur d'une fonction appelée par un timer (esquisse) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #define sample_count         1024                // Utiliser 2^n pour un tampon circulaire
    uint16_t data[sample_count];
     
    uint16_t i_smp     = 0;                          // indice de l'échantillon courant
    uint16_t i_smp_max = sample_count - 1;           // indice maximal déchantillon
    double  A          = 0.0;                        // Angle courant (évite une multiplication)
    double dA          = 0.0;                        // Variation d'angle par période d'echantillonage
    ...
    void InitSignal(uint f, uint smppsec) {
       if(smppsec <= 0) dA = 0;
       else dA = 2.0 * PI * (f / smppsec);
    }
     
    void OnTimerSignal(...) {
       A += dA;
       i_smp  = (i_smp + 1) & i_smp_max;             // Ne fonctionne que si sample_count == 2^n
       data[i] = uint16_t((sin(dA) + 1.0) * 2048); 
    }
    Remarque : les échantillons i après l'échantillon courant i_smp (i.e. i > i_smp) sont en fait dans le passé en i-1024. En tenir compte pour l'affichage.

    Dans le cas d'une simulation, on pourra se contenter de simplement désactiver le timer durant l'affichage mais en cas réel il faudra quelque chose de plus sophistiqué (par exemple un tampon > 2 fois la largeur d'affichage).

    Salutations

  5. #5
    Membre averti
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Par défaut
    le graticule est de 10x8 divisions sur un rectangle de 500x400 pixels soit 50 pixels par division.
    Comment tracer le graphe en fonction de la valeur time/div choisie?

  6. #6
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 646
    Par défaut
    Bonjour,

    50 pixels / division.

    Horizontal : 1 pixel = 1 échantillon. Mais sample_rate = nb_échantillon /sec => T_échantillon = 1 / sample_rate, donc 50 pixels / division <=> (50/sample_rate) sec/division.

    Vertical : raisonnement similaire. 1 pixel <=> 3.3V*15 / 4096 (ou 4095) donc 50 pixels/division <=> 3.3V*15*50/4096 = 0.6 V/division.

    Salutations

  7. #7
    Membre averti
    Inscrit en
    Août 2010
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 14
    Par défaut
    Merci Guesset, je vais essayer d'implémenter ça en code.
    Salutations

  8. #8
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 418
    Par défaut
    Dans le cas d'une simulation, on pourra se contenter de simplement désactiver le timer durant l'affichage mais en cas réel il faudra quelque chose de plus sophistiqué (par exemple un tampon > 2 fois la largeur d'affichage).
    Ou bien utiliser un buffer circulaire qui introduira une désynchronisation mais l'affichage sera propre.

  9. #9
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 646
    Par défaut
    Bonjour henderson,

    Citation Envoyé par henderson Voir le message
    Ou bien utiliser un buffer circulaire qui introduira une désynchronisation mais l'affichage sera propre.
    Le tampon circulaire évite élégamment d'avoir deux tampons. J'y faisais implicitement référence en écrivant que "les échantillons i après l'échantillon courant i_smp (i.e. i > i_smp) sont en fait dans le passé en i-1024. En tenir compte pour l'affichage.". Une caractéristique des tampons circulaires est de préférer avoir une dimension en 2n pour faciliter le bouclage sans calcul (un simple masquage i = (i +1) & msk avec msk = (1 << n) -1;).

    Ceci étant, la recherche de synchronisation, nécessaire pour avoir un signal lisible, fait perdre des positions, parfois beaucoup. Aussi que le tampon soit circulaire ou qu'il y ait deux tampons, il est nécessaire d'avoir plus d'espace que la largeur de l'écran surtout si on souhaite voir le signal juste avant le déclenchement. Les séquences de trig peuvent certes être très simples (sur 1 ou 2 échantillons) comme relativement longues et complexe (start d'un protocole par exemple).

    Enfin panorama et zoom accroissent encore le besoin en mémoire.

    Salut

  10. #10
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 418
    Par défaut
    Par ailleurs il faut simplifier la formule pour générer l'onde sinus.
    - 2 * PI est un constante
    - (frequency / sample_rate) est à calculer avant la boucle for.

    Pour le dessin de point en point par segments, il faut un seul MoveToEx sur le premier point et un LineTo de points en points pour les points suivants.

  11. #11
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 418
    Par défaut
    Quelque part j'ose espérer que le hdc est celui d'un bitmap, que l'on recopie dans la zone client de la fenêtre lorsque les opérations graphiques sont terminées.
    C'est une histoire de double buffering ... et j'avoue que ça peut paraître idiot à première vue ... !
    Note qu'avec l'usage du timer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SendMessage(hwnd, WM_PAINT,0,0);
    est plus approprié qu'un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PostMessage(hwnd, WM_PAINT, 0, 0);

  12. #12
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 646
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 646
    Par défaut
    Bonjour,

    Pour le tracé d'un signal, il y a plusieurs techniques dont quelques unes ci-après (en espérant n'avoir pas fait trop d'erreurs ) :
    Nom : Tracé de signal.png
Affichages : 63
Taille : 57,0 Ko
    Je n'ai pas mis les initialisations qui sont assez simples.

    Les différences entre types de tracés se manifestent essentiellement dans les hautes fréquences (au sens visualisation).

    Le premier est le plus simple mais présente le défaut que la valeur courante est souvent moins visible que les valeurs de transitions.
    Le second, simple également, présente les valeurs courantes à des extremums mais propose un signale un peu empâté.
    Une variante l'allège en évitant de repartir de la dernière valeur mais au-dessus ou en dessous.
    Le dernier est aussi un tracé vertical comme les deux précédents, mais on ne trace que les parties de segment qui ne sont pas en recouvrement avec le précédent.

    Je préfère le dernier car je le trouve plus lisible, mais les goûts et les couleurs...

    Salutations

Discussions similaires

  1. Application SNMP avec C API
    Par Alaa-linux dans le forum Développement
    Réponses: 4
    Dernier message: 10/06/2013, 10h20
  2. Problème de compilation avec dev-c++ pour WIN32 API
    Par ValyGator dans le forum Dev-C++
    Réponses: 2
    Dernier message: 08/01/2007, 14h53
  3. Petit probleme avec l'API win32
    Par spiky31 dans le forum Windows
    Réponses: 3
    Dernier message: 24/01/2006, 16h01
  4. faire dérouler une image avec l'api win32
    Par gdkenny dans le forum Windows
    Réponses: 6
    Dernier message: 26/11/2005, 21h46
  5. Redimensionner un composant avec l'API Win32
    Par le merou dans le forum Composants VCL
    Réponses: 5
    Dernier message: 29/05/2005, 13h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo