Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général en BASIC et PASCAL !

Modérateur : Gérard

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#1 Message par k_lab » sam. 10 déc. 2016 11:06

Bonjour à tous,

Je reviens vers vous car je sèche complètement (2 nuits blanches!).

Voici ce que j'attends de mon code:

produire une onde carrée de fréquence variable.
Pour ce faire j'utilise les interruptions du timer1 (16 bits).
Je règle la fréquence en pré-positionnant le compteur du timer1 (0 = freq min; 2^16 = freq max) via ma variable TMR1preset.

La fréquence produite a un "Duty Cycle" et un comportement complètement erratique. A MOINS d'ajouter la ligne suivante if TMR1preset >= 65535 then qui, apriori, ne sert à rien puisque je ne mets aucune action après le "then". A ce moment là ça fonctionne (trouvé par hazard)!

J'ai ralenti la fréquence de scan des ADC ADCON1 := %00010000;

Autre question plus générale dans la foulée: si je mets RABPU à 0 via OPTION_REG := 0;, les pull-ups sont-ils activés ou non?? (il y a une barre au dessus du paramètre -> inverse la logique?) voir attachement.

RABPU.png


voici les CONFIG WORDS:

CONFIG.png


et le code:

Code : Tout sélectionner

program DVCO_test;

{
Variable square wave frequency generation controlled by analog voltage
Timer1 interrupts used to generate frequency

chip
: PIC16F687   running at 8 Mhz internal oscillator (INTOSC)
all other CONFIG WORDS disabled
}

{
 Declarations section }
var
TMR1preset: word;               // used to set position of Timer1 counter

procedure Interrupt;

  begin
  if  PIR1
.TMR1IF = 1 then        // Interrupt from timer 1?
  begin
    PORTB.6 
:= PORTB.6 xor 1;     // toggle pin
    TMR1H := Hi(TMR1preset);
    TMR1L := Lo(TMR1preset);
    PIR1.TMR1IF := 0;
  end;

end;


begin
  
{ Main program }

  OSCCON.SCS := 1;               // Internal oscillator is used for system clock
  OSCCON.IRCF0 := 1;           // 8 Mhz Internal Clock
  OSCCON.IRCF1 := 1;           // 8 Mhz Internal Clock
  OSCCON.IRCF2 := 1;           // 8 Mhz Internal Clock

  
  CM1CON0 
:= 0;                 // comparator C1 off
  CM2CON0 := 0;                 // comparator C2 off

  TRISA := %00000001;           // PORTA.0 = input
  TRISB := %00000000;
  TRISC := %00000000;
  

  ANSEL 
:= %00000001;          // enable analog channels  0
  ANSELH := %00000000;         // enable analog channel

  
  OPTION_REG 
:= 0;             // reset OPTION register
                               // pull-ups disabled

  INTCON := 0;                 // reset intcon register
  INTCON.GIE := 1;             // enable global interrupts
  INTCON.PEIE := 1;            // enable peripheral interrupts
  T1CON := 0;
  
  T1CON
.TMR1CS := 0;           // reset T1CON register
                               // Timer1 clock source select = internal (FOSC/4)
  T1CON.T1CKPS0 := 0;          // Timer 1 prescale 1:1
  T1CON.T1CKPS1 := 0;          //
  
  
  TMR1H 
:= 0;                  // reset Timer1 counter
  TMR1L := 0;                  // reset Timer1 counter
  PIR1.TMR1IF := 0;            // clear Timer1 interrupt flag
  T1CON.TMR1ON := 1;           // activate Timer1
  PIE1 := 0;                   // reset PEIE register
  PIE1.TMR1IE := 1;            // enable Timer1 interrupts
  PIR1 := 0;                   // reset PIR1 register

  ADC_Init;                    // initialize adc module

  ADCON1 := %00010000;          // ADC acquisition clock = FOSC/8
  
  delay_ms
(500);
  
  PORTA 
:= 0;                   // reset port states
  PORTB := 0;
  PORTC := 0;
  PORTB.6 := 0;                 // to be sure!

  TMR1preset := 0;              // variable reset
  
   while true do
   begin

   TMR1preset 
:= (ADC_Get_Sample(0))*64; 
       
// read ADC channel 0 and multiply by 64 to obtai
       // (almost) full 16 bit span from 10 bit span.
       // 1023 * 64 = 65472 (almost 65535)
  
   if TMR1preset 
>= 65535 then   // without this line output behaviour is strange.

   end;

end.


Je vous ai sorti les pages avec les registres concernés:

PIC16F687 689 CONFIG.pdf



MERCI POUR VOTRE AIDE!!
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#2 Message par Guest » sam. 10 déc. 2016 19:11

bonjour

Effacé le post précédant me suis planté. :sifflotte:

Dans ton code 2 choses me gêne

1/ Ta multiplication par 64,alors que tu peux faire, cela avec des rotations a droite

2/ Tu es sans pitié pour ton CAN. Tu devais, une piste pour faire de échantillonnage utiliser une position de ta sortie. Par exemple, faire un test si front bas -> échantillonne(lance mon CAN). Sinon, le net plus ultra passer par un autre timer X

A+

Faire aussi un test avec une tempo dans la boucle while qui reviens au même que le timer X mais c'est bloquant

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#3 Message par k_lab » sam. 10 déc. 2016 22:20

Salut maï,

merci pour ta réponse. OK pour le SHL, je vais essayer. Comme le pic ne fait pas grand chose pour l'instant, je me suis permis la multiplication...

j'ai essayé avec une tempo dans le boucle infinie, aucun changement...

Lorsque que je module ma variable TMR1preset avec une boucle qui incrémente, ça marche bien aussi. On dirait que c'est le CAN qui coince. Mais je voudrais garder le plus de réactivité possible.

Un avis sur le bit RABPU du registre INTCON, sa "barre" me trouble, je ne sais pas quoi mettre pour désactiver les pull-ups.

Je vais essayer tes propositions, mais là je dois récupérer de ma nuit blanche sur ce foutu timer1 !

Merci, bon dimanche!

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 2595
Enregistré en : juillet 2016
Localisation : Terre

#4 Message par Temps-x » dim. 11 déc. 2016 13:15

Bonjour k_lab, et bonjour à tous,

si je mets RABPU à 0 via OPTION_REG := 0;, les pull-ups sont-ils activés ou non?? (il y a une barre au dessus du paramètre -> inverse la logique?) voir attachement.


Si tu mets à zéro RABPU, tu actives ton pull-ups, sur le PORTA et sur le PORTB, mets tu peux paramétrer individuellement le PORTA,
à l'exception de RA3.

Pour paramétrer le PORTA on se sert du registre WPUA voir page 62 de ton datasheet.

RABPU = 0 activation (pull-ups)
RABPU = 1 désactivation (pull-ups)

D'autre par, si tu actives ton pull-ups , tu risques de te retrouvé avec un convertisseur analogique positif, pense à retirer ton pull-ups,
pour l'entrée de ton convertisseur analogique sur les pattes concernés.

A+
Modifié en dernier par Temps-x le dim. 11 déc. 2016 16:11, modifié 6 fois.
:roll: Les requins, c'est comme le langage ASM, c'est le sommet de la chaîne alimentaire. :wink:

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
Gérard
Avatar de l’utilisateur
Expert
Expert
Messages : 1640
Âge : 65
Enregistré en : septembre 2015
Localisation : Alsace - Haut-Rhin

#5 Message par Gérard » dim. 11 déc. 2016 13:35

maï a écrit :bonjour
...
1/ Ta multiplication par 64,alors que tu peux faire, cela avec des rotations a droite
...


Bonjour,
Il me semble que pour multiplier, il faut faire des rotation à gauche. Voir Décalage et rotation.
Le 18/04/19 je suis devenu papy de jumeaux, le 01/09/23 une petite cousine des jumeaux est née.

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
Temps-x
Avatar de l’utilisateur
Expert
Expert
Messages : 2595
Enregistré en : juillet 2016
Localisation : Terre

#6 Message par Temps-x » dim. 11 déc. 2016 15:45

Bonjour Gérard, et bonjour à tous,

Il me semble que pour multiplier, il faut faire des rotation à gauche.


+1 Pour Gérard.

A+
Modifié en dernier par Temps-x le dim. 11 déc. 2016 15:47, modifié 1 fois.
:roll: Les requins, c'est comme le langage ASM, c'est le sommet de la chaîne alimentaire. :wink:

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#7 Message par Guest » dim. 11 déc. 2016 15:47

oui mon gege +1 il avait déjà fait la rectif :sifflotte: je vois que tu ne fais pas la gueule cela fait plaisir :-D

Je rajouterais que pour OPTION_REG au RAZ il est a 0XFF et RABPU n'est pas activé mais comme tu mets la pin en entrée on peut laisser cela de coté :wink:

Tient pour etre tranquille passe le bit 7 OPTION_REG a 1

Pour le CAN je ne vois pas tout a l'air d'être correct de plus quand tu rajoutes la condition cela fonctionne donc le CAN est OK la tempo que tu as rajouté dans ta boucle elle fait combien ??

apres voir aussi de charger le timer 1 dans la boucle et interrompre l'int du timer 1 le temps du chargement ou arret du timer 1

a suivre....

A+

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#8 Message par k_lab » dim. 11 déc. 2016 17:33

Bonjour à tous,

j'ai mieux dormi et je pense avoir trouvé la solution.

Merci pour vos précisions pour RABPU et les pull-ups!

@maï: pour info: ma tempo était de 10 ms, j'ai aussi essayé avec un timer0... aucun changement.

voilà ce que j'ai fait:

la variable TMR1preset (16 bits) (provenant du CAN SHL 6) était jusqu'alors décomposée en deux bytes et assignée au timer1 dans la procédure d'interruption.
Maintenant: je la décompose d'abord dans la boucle infinie:

Code : Tout sélectionner

   while true do
   begin
   TMR1preset 
:= (ADC_Get_Sample(0)) SHL 6; // read ADC channel 0 and multiply by 64 to obtain
   presetH := Hi(TMR1preset);               // (almost) full 16 bit span from 10 bit span.
   presetL := Lo(TMR1preset);               // 1023 * 64 = 65472 (almost 65535)
   end


puis dans la procédure d'interruption elles sont prêtes a être assignées aux deux régistres du timer1:

Code : Tout sélectionner

procedure Interrupt;

  begin
  if  PIR1
.TMR1IF = 1 then        // Interrupt from timer 1?
  begin
    PORTB.6 
:= PORTB.6 xor 1;     // toggle pin
    TMR1H := presetH;
    TMR1L := presetL;
    PIR1.TMR1IF := 0;
  end;

end


Je n'avais pas essayé cette solution car je me disait que si une interruption intervenait juste entre les deux lignes

Code : Tout sélectionner

   presetH := Hi(TMR1preset); 
   presetL 
:= Lo(TMR1preset); 

j'allais avoir un problème, apparement ça n'en pose pas, même avec des interruptions très rapprochées quand le pré-positionnement est maximum.

Tout ce que j'entend encore comme défaut (oui, j'écoute la sortie!) semble provenir de l'hésitation du CAN entre deux valeurs -> quelqu'un a-t-il une solution élégante ou une référence à proposer?

Merci !

Merci à tous pour vos éclairages! J'ai repris en main ce foutu TIMER1! Etape suivante: DDS / 32 bits phase accumulation etc pour avoir une résolution plus fine de la fréquence.

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
Guest
Confirmé
Confirmé
Messages : 800
Enregistré en : mars 2017

#9 Message par Guest » dim. 11 déc. 2016 18:31

bonsoir

Trop court tes 10ms a 65535 cela te fait a 8Mhz 32ms entre chaque int.
Passe par le timer0 une int toute les 100ms qui incrémente une variable sur 8 bits
tu tests cette variable si bit 0 =1 tu fais lecture CAN sinon boucle

A+

Pour le DDS un AD 9851 par exemple :wink:

[PASCAL] comportement inattendu Timer1 et ADC_Get_Sample
k_lab
Membre
Membre
Messages : 10
Enregistré en : septembre 2016

#10 Message par k_lab » dim. 11 déc. 2016 22:09

Merci pour les calculs maï, je testerai pour en avoir le coeur net.

Le dds, je compte le programmer dans le pic! voir ici:

https://circuitsalad.com/2014/06/10/dds ... ontroller/

j'espère pouvoir ré écrire le code qui est en C, en pascal afin d'ajouter d'autres fonctions.

A+ :-D


Retourner vers « Langage BASIC & PASCAL »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 31 invités