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

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#71 Message par satinas » mar. 12 janv. 2021 09:33

Bonjour,
100 essais c'est pas assez, dans le test tu attends 10ms, ensuite sortie du test, on passe au 2ème test poussoir, aux tests flags, et retour au premier test, le tout a consommé au pif une vingtaine d'instructions machine, soit 20us. Donc un risque sur 500 que le bouton passe à 1 en dehors du test. C'est bien sûr pas bien grave, mais les bases de la programmation PIC ou autre, c'est d'abord faire une appli qui marche à tous les coups :)
Pour cette raison, j'ai pas mal cogité pour traiter le cas Ton = 0 ou/et Toff = 0, c'est souvent ce qui prend du temps, les cas limite car source de bug.

Au reset cela se passe comment, tu démarres relais off ou on ?

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#72 Message par djviper16 » mar. 12 janv. 2021 09:53

Oui tu as raison et j'ai bien compris pourquoi.
Après c'est sûr que ça ne va pas gêner au fonctionnement puisque le bidule va être programmé peut-être 3 fois seulement le temps de trouver le bon réglage qui convient à mon père.
Que penses-tu de remplacer if (BP_Ton_RA2==0) par while (BP_Ton_RA2==0) ? Ça éviterait de sortir de la boucle non ?
Oui au reset le relais est inactif, et je me suis même permis le luxe de définir Toff et BaseToff très grand pour pas qu'il s'active après reprogrammation quand l'EEPROM est vierge.

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#73 Message par satinas » mar. 12 janv. 2021 10:14

Code : Tout sélectionner

  if (BP_Ton_RA2==0) {                 //BP de gauche
    nbFlagTimer0 = 0; TMR0 = 0; T0IF=0;
    while (BP_Ton_RA2==0) {
      if (T0IF==1) {
        nbFlagTimer0++; T0IF=0;
      }
    }
    if (nbFlagTimer0<20) { //Si quand on relâche le BP, le flag a été déclenché moins de 20 fois, programmation Toff
      ...
    }   
    else { //Si quand on relâche le BP, le flag a été déclenché plus de 20 fois, programmation BaseToff
      ...
    }   
  }

N'oublie pas les else dans les if.
Il y a quoi comme anti-rebond ?
S'il n y en a pas il faut remettre le delay_ms(); juste après l'appui.

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#74 Message par djviper16 » mar. 12 janv. 2021 10:36

Ça a une vraie utilité les "else" ? Ou c'est juste pour la lisibilité ?
J'ai bien un "delay_ms(10)" après l'appui, tu l'as supprimé quand tu as copié le code :sifflotte:

Code : Tout sélectionner

////////////////////Si appui sur BP gauche (Ton)///////////////////////
        
while (BP_Ton_RA2==0)                //BP de gauche
            
{
            
delay_ms(10);

            if (
T0IF==1)
                {
                
nbFlagTimer0++;
                
T0IF=0;
                }

            if (
BP_Ton_RA2==& (nbFlagTimer0<20))                //Si quand on relâche le BP, le flag a été déclenché moins de 20 fois, programmation Ton
                
{
                
nbFlagTimer0=0;
                
Ton = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                
clignotements_led_courts();
                
EEADR=0x00;                        //adresse Ton EEPROM
                
EEDAT=Ton;
                
sequence_write_EEPROM();
                }    

            if (
BP_Ton_RA2==& (nbFlagTimer0>20))                 //Si quand on relâche le BP, le flag a été déclenché plus de 20 fois, programmation BaseTon
                
{
                
nbFlagTimer0=0;
                
BaseTon = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                
clignotements_led_longs();
                
EEADR=0x02;                        //adresse Ton EEPROM
                
EEDAT=BaseTon;
                
sequence_write_EEPROM();
                }

            
sec=0;
            
min=0;
            
hr=0;
            }    
 

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#75 Message par satinas » mar. 12 janv. 2021 10:47

Oui je pensais que tu avais peut être un anti-rebond hardware. Au fait j'ai gardé ton timer0, mais autant le remplacer par des delay, c'est plus simple.

Le else ou else if permet d'afficher clairement que 2 conditions de test ne peuvent être vérifiées en même temps, et c'est bien le cas dans cet exemple. Cel aide à la compréhension du programme, à mon avis. Et bien sûr on gagne en vitesse.
En plus tu ne traitais pas le cas nbFlagTimer0 = 20, joli bug :) On en conclut donc que cela sert vraiment.

Dans les conditions de test, utiliser le et logique &&, pas le et binaire &.

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#76 Message par djviper16 » mar. 12 janv. 2021 13:48

Oh oui bien vu pour le "&" et le "20" qui n'est jamais testé !

C'est modifié, super j'ai plus qu'à récupérer le PIC pour le reprogrammer :lol:

Code : Tout sélectionner

        while (BP_Ton_RA2==0)                //BP de gauche
            {
            delay_ms(10);

            if (T0IF==1)
                {
                nbFlagTimer0++;
                T0IF=0;
                }

            if (BP_Ton_RA2==&& (nbFlagTimer0<=20))                //Si quand on relâche le BP, le flag a été déclenché moins de 20 fois, programmation Ton
                {
                nbFlagTimer0=0;
                Ton = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                clignotements_led_courts();
                EEADR=0x00;                        //adresse Ton EEPROM
                EEDAT=Ton;
                sequence_write_EEPROM();
                }    

            else 
(BP_Ton_RA2==&& (nbFlagTimer0>20))                 //Si quand on relâche le BP, le flag a été déclenché plus de 20 fois, programmation BaseTon
                {
                nbFlagTimer0=0;
                BaseTon = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                clignotements_led_longs();
                EEADR=0x02;                        //adresse Ton EEPROM
                EEDAT=BaseTon;
                sequence_write_EEPROM();
                }

            sec=0;
            min=0;
            hr=0;
            


Tu fais comment pour remplacer le Timer0 par des délais ?

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#77 Message par satinas » mar. 12 janv. 2021 14:22

Code : Tout sélectionner

   
  while (BP_Ton_RA2==0)
    {
    delay_ms(10);
    nbDelay++;
    if (BP_Ton_RA2==1 && nbDelay<=20)
      {
        ...
      }
    else if (BP_Ton_RA2==1 && nbDelay>20)
      {
        ...
      }
    sec = min = hr=0;
    }


Mais il y a encore la possibilité que RA2 passe à 1 durant le sec = min = hr=0; et on sort du while sans traitement. Avec un while simple il y a toujours ce risque. Prends mon exemple plus haut, et tu remplaces le timer0 par des délais.

Comprendre les bases de la programmation PIC
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#78 Message par satinas » mar. 12 janv. 2021 15:01

Code : Tout sélectionner

  if (!BP_Ton_RA2)
    {     
    int16 nbDelay = 0;
    do { delay_ms(10); nbDelay++; } while (!BP_Ton_RA2);
    // là on est sur que RA2 est à 1, et il y a eu au moins 1 délai, pour l'anti-rebond
    ...
    }
 

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#79 Message par djviper16 » mar. 12 janv. 2021 21:51

Super, c'est tout de suite moins compliqué que d'utiliser le Timer c'est clair ! :bravo:

Je n'avais pas du tout pensé à cette solution pourtant je m'étais creusé la cervelle...

Je viens de faire une petite recherche par curiosité, et je suis tombé sur ce module qui fait tout comme le mien pour moins de 4€, avec en prime un écran LCD. C'est même pas la moitié du prix des composants de mon montage !
https://fr.aliexpress.com/item/4001078060305.html

Mais bon il n'y a pas le plaisir de faire sois même, et je n'en aurais pas appris autant alors sans regrets.

Comprendre les bases de la programmation PIC
djviper16
Débutant
Débutant
Messages : 60
Enregistré en : décembre 2020

#80 Message par djviper16 » dim. 17 janv. 2021 18:48

Bonsoir,

J'ai pris le temps de corriger mon code, je le joins si jamais quelqu'un voulait un jour reproduire ce montage :

Code : Tout sélectionner

//////////////////////////////////////////////////////////
////                   JEROME D.                      ////
////    CARTE TEMPORISATEUR CYCLIQUE PROGRAMMABLE     ////
////                COMPILATEUR CCS                   ////
////          DEVELOPPEMENT MPLAB IDE v8.10           ////
////                   17/01/2021                     ////
//////////////////////////////////////////////////////////


/*
FONCTIONNEMENT
Le montage permet de basculer cycliquement un relais, en réglant les tempos Ton et Toff, de 1 seconde à 240 heures.
La carte électronique dispose de 2 boutons poussoirs (BP) Ton et Toff, 8 DIP switch, une led d'état, et un relais.
Les DIP switch permettent de régler la base de temps en secondes, minutes ou heures, ainsi que le nombre de secondes, minutes ou heures selon ce qui a été défini préalablement.
Les 8 DIP switch se programment en binaire. 
exemples : 
00000001 = base de temps en seconde
00000010 = base de temps en minutes
00000100 = base de temps en heures
00001010 = 10 (secondes, minutes ou heures selon la base de temps programmée)
Un appui long sur le BP_Ton = réglage de la base de temps Ton + led clignote 3 fois longuement.
Un appui long sur le BP_Toff = réglage de la base de temps Toff + led clignote 3 fois longuement.
Un appui court sur le BP_Ton = réglage du temps Ton + led clignote 6 fois rapidement.
Un appui court sur le BP_Toff = réglage du temps Toff + led clignote 6 fois rapidement.
La led permet aussi de visualiser l'état du relais. (relais fermé = led allumée)
*/


#include <16F684.h> 

#use delay(clock=4000000)    //fréquence de l'oscillateur interne : 4MHz
#fuses INTRC_IO,NOWDT,NOPUT,NOBROWNOUT,NOMCLR,NOPROTECT,NOCPD,NOPUT,NOIESO,NOFCMEN,BROWNOUT_NOSL    //il faut tous les mettre sinon ça marche pas
#use fast_io(A)                // permet d'utiliser set_tris_X(), sinon CCS affecte automatiquement les ports.
#use fast_io(C)                // permet d'utiliser set_tris_X(), sinon CCS affecte automatiquement les ports.

    
#bit RAPU = 0x81.7
#byte ANSEL = 0x91
#byte CMCON0 = 0x19


//////TIMER1 REGISTRES//////
#byte INTCON = 0x0B            //INTCON REGISTER adresse 10h
#byte T1CON = 0x10            //T1CON REGISTER adresse 10h 
#byte TMR1L = 0x0E            //TMR1L REGISTER adresse 0Eh
#byte TMR1H = 0x0F            //TMR1H REGISTER adresse 0Fh
#byte PIR1 = 0x0C            //PIR1 REGISTER adresse 0Ch
#byte PIE1 = 0x8C            //PIE1 REGISTER adresse 8Ch
#bit TMR1IF = 0x0C.0        //adresse du bit Flag quand le timer déborde
#bit TMR1IE = 0x8C.0        //adresse du bit d'activation des interruptions
#bit GIE = 0x0B.7
#bit PEIE = 0x0B.6


//////EEPROM//////
#byte EEDAT = 0x9A
#byte EEADR = 0x9B
#byte EECON1 = 0x9C
#byte EECON2 = 0x9D
#bit EEIF = 0x0C.7
#bit WREN = 0x9C.2
#bit WR = 0x9C.1
#bit RD = 0x9C.0

//////ADRESSES PORTS ET BITS E/S//////
#byte portA=5                //adresse du port A
#byte WPUA=95                //adresse WPUA
#byte IOCA=96                //adresse IOCA
#byte portC=7                //adresse du port C
#bit Relais_RA0=portA.0        //affectation du Relais_RA0
#bit Led_RA1=portA.1        //affectation du Led_RA1
#bit BP_Ton_RA2=portA.2        //affectation du BP_Ton_RA2
#bit RA3=portA.3            //affectation du RA3
#bit RA4=portA.4            //affectation du RA4
#bit RA5=portA.5            //affectation du RA5
#bit BP_Toff_RC0=portC.0    //affectation du BP_Toff_RC0
#bit RC1=portC.1            //affectation du RC1
#bit RC2=portC.2            //affectation du RC2
#bit RC3=portC.3            //affectation du RC3
#bit RC4=portC.4            //affectation du RC4
#bit RC5=portC.5            //affectation du RC5


//////DECLARATION VARIABLES//////
int8 demisec;                //variable 0 à 2 -> pour compter le nombre de flag levés (un flag toutes les 0.5 sec)
int8 sec;                    //variable 0 à 59 -> pour faire une minute
int8 min;                    //variable 0 à 59 -> pour faire une heure
int8 hr;                     //variable 0 à 24
int8 Ton;                    //variable Tempo ON
int8 Toff;                    //variable Tempo OFF
int8 BaseTon;
int8 BaseToff;
int16 nbDelay;                //variable 16 bits -> pour compter combien de temps les boutons Ton et Toff restent appuyés



void clignotements_led_courts()        //routine clignotements courts après appui court
{
Led_RA1=1;
delay_ms(100);
Led_RA1=0;
delay_ms(100);
Led_RA1=1;
delay_ms(100);
Led_RA1=0;
delay_ms(100);
Led_RA1=1;
delay_ms(100);
Led_RA1=0;
delay_ms(100);
Led_RA1=1;
delay_ms(100);
Led_RA1=0;
delay_ms(100);
Led_RA1=1;
delay_ms(100);
Led_RA1=0;
delay_ms(100);
Led_RA1=1;
delay_ms(100);
Led_RA1=0;
}



void clignotements_led_longs()        //routine clignotements longs après appui long
{
Led_RA1=1;
delay_ms(500);
Led_RA1=0;
delay_ms(500);
Led_RA1=1;
delay_ms(500);
Led_RA1=0;
delay_ms(500);
Led_RA1=1;
delay_ms(500);
Led_RA1=0;
}



void sequence_write_EEPROM()        //séquence écriture EEPROM
{
WREN=1;                                //autorise écriture
GIE=0;                                //désactive interruptions générales
EECON2=0x55;
EECON2=0xAA;
WR=1;                                //start écriture
EEIF=0;                                //Write Complete Interrupt Flag bit
GIE=1;                                //ré-activer les interruptions
}



#int_timer1
void interrupt_timer1()                //routine d'interruption Timer1 (if TMR1IF==1)
{
demisec++;
TMR1IF=0;                            //flag du Timer1 à 0
T1CON=0x34;                            //0b00110100 Timer1 arrêté
TMR1L=0xDC;                            //config compteur 16 bits
TMR1H=0x0B;                            //0x0B
T1CON=0x35;                            //0b00110100 Timer1 démarré
if (demisec==2)
    {sec++;
    demisec=0;
    }
if ((sec==60) | (sec==120) | (sec==180) | (sec==240))
    {min++;
    if(sec==240)
    {    sec=0;}
    }
if ((min==60) | (min==120) | (min==180) | (min==240))
    {hr++;
    if(min==240)
    {min=0;}
    }
if (hr==24)
    {hr=0;}            
}


void main()
{
//////PORTS ET BITS E/S//////    
ANSEL=0x00;                        //désactive les entrées analogiques
CMCON0=0xFF;                    //désactive les comparateurs
SET_TRIS_A(0xFC);                  //Relais_RA0 et Led_RA1 en sorties, BP_Ton_RA2, RA3, RA4, RA5 en entrées
SET_TRIS_C(0xFF);                //tout le portC en entrée
RAPU=0;                            //0 = PORTA pull-ups are enabled by individual port latch values
WPUA=0xFF;                         //1 = Pull-up enabled


//////VALEURS VARIABLES//////
demisec=0;
sec=0;
min=0;
hr=0;



//////TIMERS//////
INTCON=0xC0;                    //GIE et PEIE à 1 pour activer interruptions (bits 7 et 6)du Timer1
                                //T0IE : 0 = Disables the TMR0 interrupt
                                //INTE : 0 = Disables the BP_Ton_RA2/INT external interrupt
                                //RAIE : 0 = Disables the PORTA change interrupt
                                //T0IF : 0 = TMR0 register did not overflow
                                //INTF : 0 = The BP_Ton_RA2/INT external interrupt did not occur
                                //RAIF : 0 = None of the PORTA <5:0> pins have changed state


//////TIMER0 REGISTRES//////
//OPTION_REG=0b00000111;
//TMR0=0x3C;                        //0x3C=60    60 à 255 pour 0.05 secondes


//////TIMER1 REGISTRES//////
T1CON=0x34;                        //0b00110100 Timer1 arrêté
TMR1L=0xDC;                        //config compteur 16 bits
TMR1H=0x0B;                        //0x0B
T1CON=0x35;                        //0b00110100 Timer1 démarré
PIR1=0x00;
PIE1=0x00;
TMR1IF=0;                        //flag du Timer1
TMR1IE=1;                        //1 = Enables the Timer1 overflow interrupt

Relais_RA0=0;                            //relais inactif
Led_RA1=0;                        //led éteinte


//////EEPROM//////
EEADR=0x00;                        //adresse Ton EEPROM
RD=1;                            //autorise lecture
Ton=EEDAT;
EEADR=0x01;                        //adresse Toff EEPROM
EECON1=0b00000001;                //autorise écriture, initialise lecture EEPROM
Toff=EEDAT;
EEADR=0x02;                        //adresse BaseTon EEPROM
EECON1=0b00000001;                //autorise écriture, initialise lecture EEPROM
BaseTon=EEDAT;
EEADR=0x03;                        //adresse BaseToff EEPROM
EECON1=0b00000001;                //autorise écriture, initialise lecture EEPROM
BaseToff=EEDAT;

if(
Toff==0x00)                    //
    {Toff=0xFF;                    //Permet de ne pas passer à Ton au premier démarrage
    BaseToff=0b00000100;        //quand l'EEPROM n'est pas encore programmée
    }                            //


//////////////////Boucle principale/////////////////////
    while(1)                
    
{

////////////////////Si appui sur BP gauche (Ton)///////////////////////
        if (BP_TON_RA2==0)                //BP de gauche
            {
            nbDelay=0;
            do { delay_ms(10); nbDelay++; } while (BP_TON_RA2==0);
            

            if 
(BP_Ton_RA2==&& (nbDelay<=100))                //Si quand on relâche le BP, le flag a été déclenché moins de 20 fois, programmation Ton
                {
                Ton = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                clignotements_led_courts();
                EEADR=0x00;                        //adresse Ton EEPROM
                EEDAT=Ton;
                sequence_write_EEPROM();
                }    

            else if 
(BP_Ton_RA2==&& (nbDelay>100))                 //Si quand on relâche le BP, le flag a été déclenché plus de 20 fois, programmation BaseTon
                {
                BaseTon = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                clignotements_led_longs();
                EEADR=0x02;                        //adresse Ton EEPROM
                EEDAT=BaseTon;
                sequence_write_EEPROM();
                }

            sec=0;
            min=0;
            hr=0;
            }    



////////////////////Si appui sur BP droite (Toff)///////////////////////
        if (BP_Toff_RC0==0)                //BP de droite
            {
            nbDelay=0;
            do { delay_ms(10); nbDelay++; } while (BP_Toff_RC0==0);

            if (BP_Toff_RC0==&& (nbDelay<=100))                //Si quand on relâche le BP, le flag a été déclenché moins de 20 fois, programmation Ton
                {
                Toff = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                clignotements_led_courts();
                EEADR=0x01;                        //adresse Ton EEPROM
                EEDAT=Toff;
                sequence_write_EEPROM();
                }    

            else if
(BP_Toff_RC0==&& (nbDelay>100))                 //Si quand on relâche le BP, le flag a été déclenché plus de 20 fois, programmation BaseTon
                {
                BaseToff = (RC3<<0) | (RC4<<1) | (RC5<<2) | (RA3<<3) | (RA4<<4) | (RA5<<5) | (RC1<<6) | (RC2<<7);        //on écrit l'état des 8 interrupteurs
                clignotements_led_longs();
                EEADR=0x03;                        //adresse Ton EEPROM
                EEDAT=BaseToff;
                sequence_write_EEPROM();
                }

            sec=0;
            min=0;
            hr=0;
            }    

////////////////////Si les conditions sont réunies pour basculement état sortie///////////////////////
        if ((sec>=Ton) && (Relais_RA0==1) && (BaseTon==0b00000001))
            {
            Relais_RA0=0;
            Led_RA1=0;
            sec=0;
            min=0;
            hr=0;
            }
        if ((sec>=Toff) && (Relais_RA0==0) && (BaseToff==0b00000001))
            {
            Relais_RA0=1;
            Led_RA1=1;
            sec=0;
            min=0;
            hr=0;
            }
        if ((min>=Ton) && (Relais_RA0==1) && (BaseTon==0b00000010))
            {
            Relais_RA0=0;
            Led_RA1=0;
            sec=0;
            min=0;
            hr=0;
            }
        if ((min>=Toff) && (Relais_RA0==0) && (BaseToff==0b00000010))
            {
            Relais_RA0=1;
            Led_RA1=1;
            sec=0;
            min=0;
            hr=0;
            }
        if ((hr>=Ton) && (Relais_RA0==1) && (BaseTon==0b00000100))
            {
            Relais_RA0=0;
            Led_RA1=0;
            sec=0;
            min=0;
            hr=0;
            }
        if ((hr>=Toff) && (Relais_RA0==0) && (BaseToff==0b00000100))
            {
            Relais_RA0=1;
            Led_RA1=1;
            sec=0;
            min=0;
            hr=0;
            }
    }
}
 


Voilà je pense qu'il y a toujours possibilité d'améliorer mais le programme fonctionne parfaitement bien, je passe à autre chose.

A+


Retourner vers « Langage C »

Qui est en ligne

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