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 sur le langage C !

Modérateur : Jérémy

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#11 Message par albertdela » mer. 17 mai 2023 08:02

Bonjour,
pas eût trop le temps de faire des compte rendus hier soir mais ça fonctionne.
Effectivement, il y avait quelques bricoles à recaler et c'est bon.
Maintenant, il va falloir voir pourquoi les sorties ne basculent pas malgré les LATXXX... C'est une autre histoire, on autre fil. Ce soir, je poste les fichiers qui fonctionnent.
Merci encore et @+

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#12 Message par satinas » mer. 17 mai 2023 08:10

Bonjour,
Regarde les registres ANSEL et surtout leurs valeurs au reset.

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#13 Message par albertdela » mer. 17 mai 2023 21:55

Comme promis, le retour du code qui fonctionne :
le main :

Code : Tout sélectionner

/* 
 * File:   newmain.c
 * Author: Albert
 *
 * Created on 11 mai 2023, 00:18
 */

#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>

/*
 * Ce programme doit permettre de créer un allumage éléctronique type CDI
 * à partir d'un 18F26K22 (configuré à 64MHz)en boitier SOIC ou SSOP pour
 * un moteur mono-cylindre 2 temps.
 * RB0(21) : entrée top vilbrequin supposé à 270° du PMH (ENTREE_TOP)
 * RB2(23) : sortie PWM image de la vitesse (0% : 1000; 100% : 10.000)
 * RC2(13) : sortie led de contrôle de fonctionnement 
 * RC3(14) : sortie de commande de HT (1: géné HT; 0: bloquée) (SORTIE_HT)
 * RC4(15) : sortie Top Allumage (1: commande bobine; 0: bloquée) (SORTIE_ALL)
 * Rupture d'allumage à 10.000tr/min
 * Avance est calée à 0 jusqu'à 1500tr/min.
 * Variation linéaire de 1.500 à 10.000 pour 0 à 30° d'avance.
 */

volatile uint16_t vitesse_rotation = 0; //
volatile bool change_vit = false; // on a pas changé la vitesse de rotation
volatile uint16_t avance = 0; // avance nulle par défaut
volatile uint16_t attente_on = 0; // compteur d'attente pour éviter de chauffer la bobine
volatile bool flag_on_all = false; // au début allumage OFF
volatile bool coupure_all = false; // au début on est pas au rupteur
volatile uint16_t compteur = 0 ; // clignotant de la led de débug

void __interrupt() isr(void) {
    static uint8_t valeur_timer = 0;
    if (INTCONbits.TMR0IF == 1 ) { // Débordement de timer0. On coupe la HT si >5s
        attente_on += 65; // on ajoute 65ms au compteur
        if (attente_on > 5000) { // on dépasse 5.000 ms
            SORTIE_HT = 0;
            attente_on = 5000;
        }        
        TMR0H 
= 0; // Timer0 à 0
        TMR0L = 0; // et on repart pout le comptage
        INTCONbits.TMR0IF = 0; // On efface le flag
        return; // on sort
    }
    
    
/* On utilise le Timer1 pour la gestion de l'étincelle
     * le flag_on_all sert à determiner dans quel état on est.
     *  si ON l'étincelle est en court si OFF on est post-allumage
     * L'étincelle unique est prévue de durer 10us
     * Ensuite on recharge avec la valeur "avance" prévue et le ENTREE_TOP déclenchera
     */
    if (PIR1bits.TMR1IF) { // on est à la fin du Timer1 car débordement
        SORTIE_HT = 1; // on active la HT
        // Réinitialiser Timer2
        T1CONbits.TMR1ON = 0; // Désactiver Timer1
        flag_on_all = !flag_on_all; // si on étincelle on arrête sinon on commence
        if (flag_on_all) {     
            if 
(!coupure_all) {  
            SORTIE_ALL 
= 1; // Allumage si pas au rupteur
            }
            TMR1 = 0x14; // 10 microsecondes d'allumage
            T1CONbits.TMR1ON = 1; // Activer Timer2
        }
        else { // on a fini l'étincelle, on prépare la suivante
            TMR1 = avance; // Précharger Timer1 avec la valeur "avance"
            SORTIE_ALL = 0; // stop allumage
        }
        PIR1bits.TMR1IF = 0; // Effacer le flag d'interruption de Timer2
    }
    /* Quand le TOP arrive sur la broche 21 (RB0), on capture le TIMER0
     * et on fait le calcul l'intègre pour la mesure de vitesse.
     * Le TIMER0 est paramètré pour compter toutes les 1us. La variable
     * vitesse_rotation est mise à jour et le flag change_vit passe à ON.
     * On profite de la mesure pour limiter à 10.000tr/min par coupure d'allumage
     */
    if (INTCONbits.INT0IF) { // calcul de la vitesse de rotation au top HALL
        INTCONbits.INT0IE = 0; // Désactiver l'interruption externe
        unsigned int valeur_timer = (unsigned int)((TMR0H << 8) + TMR0L); // Capturer la valeur de TMR0
        if (valeur_timer > 800) { // Anti-rebond à 800 us
            if (valeur_timer > 6000) { // Limite à 10.000 tr/min
                valeur_timer = 6000;
                coupure_all = true;
            }
            else {
                coupure_all = false;
                T1CONbits.TMR1ON = 1; // on active le TIMER1 pour faire le TOP avance
            }
            vitesse_rotation = valeur_timer; // temps sur un tour en ms
            change_vit = true ; // on a changé la vitesses de rotation
            TMR0H = 0; // Timer0 à 0
            TMR0L = 0; // et on repart pout le comptage
        }
        INTCONbits.INT0IF = 0; // Effacer le flag d'interruption externe
        INTCONbits.INT0IE = 1; // Réactiver l'interruption externe
    }    
}


int main(int argc, char** argv) {
config_ports();
config_timer0();
config_timer1();
config_interrupt_externe ();
config_interrupt();
configure_pwm();
while (1) {    // Boucle principale
    if (change_vit) {   // Un top PMH a eû lieu, 
        avance = calcul_avance(vitesse_rotation);   // on actualise "avance" pour le prochain tour
        change_vit = !change_vit;   // On a bien pris en compte le changement
        CCPR1L = duty(vitesse_rotation);    // On actualise la PWM
    }
    compteur++;
    if (SORTIE_DEBUG == 1) {
        SORTIE_DEBUG = 0 ;
        }
        else {
            SORTIE_DEBUG = 1;
        }
    };
}


le config.h:

Code : Tout sélectionner

/* 
 * File:   config.h
 * Author: Albert
 *
 * Created on 10 mai 2023, 22:02
 */

#ifndef CONFIG_H
#define    CONFIG_H

#include <xc.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

// CONFIG1H
#pragma config FOSC = INTIO67   // Oscillateur interne, broches 6 et 7 sont des entrées/sorties
#pragma config PLLCFG = ON      // Active l'oscillateur PLL (x4)
#pragma config PRICLKEN = ON    // Active le verrouillage de la clock périphérique
#pragma config FCMEN = OFF      // Désactive le moniteur de la clock
#pragma config PWRTEN = OFF     // Désactive le Power-up Timer
#pragma config BOREN = OFF      // Désactive le Brown-out Reset
#pragma config BORV = 0         // Niveau de tension de Brown-out Reset à 4.0V
#pragma config WDTEN = OFF      // Désactive le Watchdog Timer
#pragma config MCLRE = EXTMCLR  // Active le reset MCLR externe
#pragma config DEBUG = OFF      // Désactive le mode de débogage
#pragma config STVREN = ON      // Active le stack overflow reset

#define _XTAL_FREQ 64000000     // Définit la fréquence de l'oscillateur interne

// Configuration des ports
void config_ports(void) {
    TRISB = 1;
    TRISBbits.TRISB0 = 1; // RB0 est en entrée pour la détection du top
#define ENTREE_TOP PORTBbits.RB0
    TRISC = 0xFF;
    TRISCbits.TRISC2 = 0; // RC2 est en sortie pour une LED de debug
#define SORTIE_DEBUG LATCbits.LATC2
    // Sortie pour la HT en RC3
    TRISCbits.TRISC3 = 0; // RC3 est en sortie pour commande de HT
#define SORTIE_HT LATCbits.LATC3
    TRISCbits.TRISC4 = 0; // RC4 est en sortie pour commande d'allumage
#define SORTIE_ALL LATCbits.LATC4
}
// Configuration du Timer0
void config_timer0(void) {
    T0CONbits.T08BIT = 0; // 16-bit mode
    T0CONbits.T0CS = 0; // Utiliser l'oscillateur interne pour TIMER0
    T0CONbits.PSA = 0; // Activer le prédiviseur pour TIMER0
    T0CONbits.T0PS = 0b011; // Prédiviseur de 1:64 pour TIMER0
    INTCONbits.T0IE = 1; // Activation interruption de débordement
    TMR0H = 0; // Timer0 à 0
    TMR0L = 0;
}
   

    
// Configuration du Timer1
void config_timer1(void) {
    T1CONbits.TMR1CS = 0; // Clock interne (Fosc/4): 16MHz
    T1CONbits.T1CKPS = 0b11; // Division de fréquence par 8 : 2Mhz
    T1CONbits.TMR1ON = 0; // Désactivation en attente du PMH
    PIE1bits.TMR1IE = 1; // Activation de l'interruption de débordement
}
        
    
// Configuration de l'interruption externe INT0
void config_interrupt_externe(void) {
    INTCON2bits.INTEDG0 = 1; // Détection sur front montant
    INTCONbits.INT0IF = 0; // Effacer le flag d'interruption externe
    INTCONbits.INT0IE = 1; // Activation de l'interruption externe
}

    // Configuration des interruptions
void config_interrupt(void) {
    PIE1bits.TMR2IE = 0; // Désactiver l'interruption de Timer2
    INTCONbits.PEIE = 1; // Activation des interruptions périphériques
    INTCONbits.GIE = 1; // Activation générale des interruptions
}

// Configuration des registres CCP1CON1 et CCP1CON2 pour générer une PWM 5KHz
// Sortie sur RB2
void configure_pwm() {
    // Configurer le mode PWM sur le CCP1
    TRISCbits.TRISC2 = 1; // désactiver la sortie CCP1
    CCP1CONbits.CCP1M = 0b1100; // Configurer CCP1 pour mode PWM
    CCP1CONbits.P1M = 0b00; // Configurer CCP1 pour mode PWM
    CCPTMRS0bits.C1TSEL = 0b00; // Sélectionner Timer2 pour CCP1
    
    
// Configurer le timer 2 pour générer une interruption toutes les 200µs (5kHz)
    T2CONbits.T2CKPS = 0b11;    // Prédivision par 16
    T2CONbits.T2OUTPS = 0;      // Pas de postdivision
    PR2 = 199;                  // Période de 200µs (64MHz / 4 / 199)
    
    
// Configurer le rapport cyclique initial à 0%
    CCPR1L = 0;
    CCP1CONbits.DC1B = 0;
    
    
// Finalisation
    PIR1bits.TMR2IF = 0;    // On s'assure d'un flag a 0
    T2CONbits.TMR2ON = 1;   // Activer le timer 2
    while (PIR1bits.TMR2IF == 0); // Attendre le débordement
    TRISCbits.TRISC2 = 0;   // Activer la sortie
}

unsigned int calcul_avance(unsigned int x) {
    return (unsigned int)(0.2624 * x - 744);
}

uint8_t duty(uint16_t x) {
    return (uint8_t) ((0.004722 * x) - 28.332);
}

#endif /* CONFIG_H */


ATTENTION: ce code résout le problème du TIMER2 qui ne fonctionne pas MAIS NE REALISE PAS LA FONCTION DEMANDEE

Pour que le code soit totalement opérationnel, il faut encore :
- traiter le problème des sorties qui ne basculent pas (certainement le ANSEL comme évoqué précédemment) ;
- trier les patates avec le sorties qui servent à plusieurs fonction (donc forcément ça fonctionne pas !) ;
- revoir le traitement de l'anti-rebond qui pour l'instant fait ... je ne sais pas trop quoi ;
- extraire le code du fichier config.h pour faire plus propre ;
- nettoyer le code pour mettre certaines valeurs numériques en variables pour plus de lisibilité ;
- et d'autres trucs dont je n'ai pas encore conscience ... :lol:

Merci pour le coup de main. Je reviendrais peut-être pour la suite et qui sait, peut-être un jour, je filerais moi aussi à quelqu'un.
@+

[HS ON]
si je souhaite partager le code lorsqu'il sera totalement opérationnel, comment fait-on sur le site ? On ouvre un fil spécifique pour ça ?
[HS OFF]

TIMER2 qui ne démarre pas ...
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2598
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#14 Message par paulfjujo » jeu. 18 mai 2023 09:02

bonjour,


où sont definis SORTIE_HT , SORTIE_ALL ?
as-tu utilisé MCC ?

à rajouter, en premier, dans l'init :
ANSELB=0;
ANSELC=0;
car par defaut ,les entrees sont en analogique ...

tu peux aussi poster le Pack de ton projet MPLABX ?

si je souhaite partager le code lorsqu'il sera totalement opérationnel, comment fait-on sur le site ?
On ouvre un fil spécifique pour ça ?


ouvrir un post , dans la section C ou Projet

bonne suite ...
Aide toi, le ciel ou FantasPic t'aidera

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#15 Message par satinas » jeu. 18 mai 2023 17:17

Bonjour,
C'est quoi exactement ces 5s, la durée de fonctionnement du moteur ?
Pourquoi ce return en plein milieu de l'ISR, on teste toutes les sources d'interruption dans l'ISR.
Le timer 1 déborde quand il passe de 0xFFFF à 0x0000, donc pour 10us c'est 0xFFFF-0x14, à plus ou moins 1 près voir à l'oscillo. Tu le démarres la première fois sans régler sa consigne.
INT0IE = 0 dans l'ISR ne sert à rien, elle ne sera jamais interrompue, car GIE est mis à 0 par le pic durant l'exécution de l'ISR.
TRISB = 1, plutôt TRISB = 0xFF
Il faut toujours lire TMR0L avant TMR0H car TMR0H n'est pas accessible directement, il est mis à jour en lisant TMR0L. donc je te conseille de faire :
unisgned int valeur_timer = TMR0L; valeur_timer += TMR0H << 8;

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#16 Message par albertdela » ven. 19 mai 2023 17:53

Bonjour à tous.
Merci de continuer à vous occuper de cette affaire Merci !
@paulfjujo:
Il me semblait que je les avais définies dans le confit.h... Je vérifierai mais si ça manque ça ne semble pas poser de problème...
Les ANSLEX, le temps de comprendre ce que c'est et c'est ajouter. Pour le cou, ça ça devait manquer au fonctionnement :lol:
MCC?!? Je ne sais pas ce que c'est. Je fouille et te dis. A priori, non je n'ai pas utilisé (ou alors, à l'insu de mon plein gré).

@Satinas
Je vieilli... J'ai une capacité d' abstraction bien inférieure à avant...
J'ai fait tout ce dont tu parles mais il m'a fallu tester pour me rendre compte que ça manque (en plus d'être une pipe à roulette en programmation Pic...)
Pour les 10us c'est exact, le tirmer0 j'ai vu dans la doc corrigé et j'étais arrivé seul à ta proposition 8-). En revanche INT0IE, il faut que je creuse :!:
Pour les 5s, c'est que l'on charge un condensateur en générant une haute tension sur une bobine (entre 800 et 1000V). Ça a tendance à chauffer si le C ne se décharge pas et si le moteur ne tourne pas car pas de ventil. Donc si on dépasse 5s (c'est arbitraire pour l'instant) on coupe cette partie du montage et on la redémarre dès que ça tourne.

Dans les problèmes il y avait aussi l'avance non chargée pour le premier tour, du coup, ça faisait un peu n'importe quoi...

Merci encore et @+.

Ps: je ne manquerai pas de poster l'ensemble du projet quand ce sera abouti.

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#17 Message par satinas » ven. 19 mai 2023 18:25

Pour la lecture de TMR0 en 2 temps, c'est important.

Ne t'embête pas avec INT0IE, c'est un détail, cela ne gêne pas le fonctionnement. Tu fais dans l'ISR.
INT0IE = 0
...
INTOIF = 0
INT0IE = 1

Si une autre impulsion arrive pendant l'ISR, INT0IF est déjà à 1, donc rien ne change, quelle que soit la valeur de INT0IE. Tu remets à 0 INT0IF à la fin, tout est ok. Et si tu imaginais que l'ISR pouvait être interrompue par un autre flag qui monte et qui la redéclenche, ce n'est pas possible car le pic a tout prévu. Avant de démarrer l'ISR, il met GIE à 0 pour éviter tout redémarrage, et à la fin l'instruction RETFIE remet GIE à 1 automatiquement. GIE est le flag général, à 0 il bloque toutes les sources d'interruptions, mais il n'a aucun effet sur les flags IF qui sont autonomes.

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#18 Message par albertdela » dim. 21 mai 2023 10:43

Bonjour,
c'est pris en compte et je vais passer ça en projet.
Pour ceux que ça intéresse...
Il y aura une autre subtilité mais c'est pour plus tard...
Merci pour l'aide. @+

Edit : ah bha non... pour faire un projet, il faut déjà qu'il fonctionne. A priori, ce n'est pas prévu que l'on post un truc en court de construction... Ca va demander un peut de délais mais ça va se faire. Merci tout de même pour l'entraide. @+

TIMER2 qui ne démarre pas ...
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 2598
Âge : 73
Enregistré en : juillet 2015
Localisation : 01800
Contact :

#19 Message par paulfjujo » dim. 21 mai 2023 11:29

bonjour,


[quote="albertdela"
Edit : ah bha non... pour faire un projet, il faut déjà qu'il fonctionne. A priori, ce n'est pas prévu que l'on post un truc en court de construction... Ca va demander un peut de délais mais ça va se faire. Merci tout de même pour l'entraide. @+[/quote]

:sifflotte: Eh ben SI !
le plus interessant dans un projet est de decrire l'évolution de celui-ci, de lister les déboires rencontrés et les solutions trouvées.
Les eventuelles modifications en cours d' évolution de celui-ci ( et le pourquoi !)

sinon, on prend un arduino , un blog sur le sujet
et c'est bouclé !
Aide toi, le ciel ou FantasPic t'aidera


Retourner vers « Langage C »

Qui est en ligne

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